diff --git a/BUILD.gn b/BUILD.gn
index ebe8900..8bf24cc 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -16,6 +16,7 @@
 import("//media/media_options.gni")
 import("//third_party/openh264/openh264_args.gni")
 import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
+import("//v8/gni/v8.gni")
 import("//v8/snapshot_toolchain.gni")
 
 if (is_android) {
diff --git a/DEPS b/DEPS
index e787c80..072975df1 100644
--- a/DEPS
+++ b/DEPS
@@ -36,11 +36,11 @@
   # 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': '901257a3ba1d094280b4e1e0868bc0bcd137145a',
+  'skia_revision': '0e72e9ee3b0201f05e5d74917b17c8a427b14d9f',
   # 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': '482fb9decea34b5d3bb2a502ce2b5ae32e681116',
+  'v8_revision': '49d339a2c526907b6613252b008c934c8ea3ecec',
   # 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.
@@ -48,7 +48,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '7da9850643f55335a13a4663d226c73d0ac4d3b1',
+  'angle_revision': 'f178d0bdd19377f8fabd856b118e165803af2fc6',
   # 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.
@@ -88,7 +88,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '20358d6bf8c99ec34037b78e0f8b9022622d362a',
+  'catapult_revision': 'ee0654d7c641b8a38613ac70062853133da6d192',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -178,13 +178,13 @@
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
   'src/third_party/webgl/src':
-   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6e08f374039cda35ba27c771b02cd10a50571f64',
+   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '937acaae1251a1e338bafe1995c0d54cb7142c60',
 
   'src/third_party/webdriver/pylib':
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx/source/libvpx':
-   Var('chromium_git') + '/webm/libvpx.git' + '@' +  '18c7f46c125c107fc08d31f617b2178482fed011',
+   Var('chromium_git') + '/webm/libvpx.git' + '@' +  '4b073bc39a39283577c485ed1e56c92cf0eaaa89',
 
   'src/third_party/ffmpeg':
    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '24ea727552a0eaa95c8de72f99cba8d70ae658cb',
@@ -268,7 +268,7 @@
     Var('chromium_git') + '/external/py_trace_event.git' + '@' + 'dd463ea9e2c430de2b9e53dea57a77b4c3ac9b30',
 
   'src/third_party/dom_distiller_js/dist':
-    Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + 'e87b378779c5641f50fc7ef885a2f88f26e47b7f',
+    Var('chromium_git') + '/external/github.com/chromium/dom-distiller-dist.git' + '@' + 'f092aa790a0eb66135fa26d98a5f118997ed446d',
 
   'src/third_party/catapult':
     Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
@@ -415,7 +415,7 @@
      Var('chromium_git') + '/external/android_protobuf.git' + '@' + '999188d0dc72e97f7fe08bb756958a2cf090f4e7',
 
     'src/third_party/android_tools':
-     Var('chromium_git') + '/android_tools.git' + '@' + '20a4bd598cf3ba8434311156ce94c110a0024fe7',
+     Var('chromium_git') + '/android_tools.git' + '@' + 'e4d61eb8f463e6cb8d1e1269a15c22f7c9bbd122',
 
     'src/third_party/apache-mime4j':
      Var('chromium_git') + '/chromium/deps/apache-mime4j.git' + '@' + '28cb1108bff4b6cf0a2e86ff58b3d025934ebe3a',
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 25a21cf..91ab5d2 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -20,7 +20,10 @@
 #include "base/i18n/rtl.h"
 #include "base/path_service.h"
 #include "components/crash/content/browser/crash_micro_dump_manager_android.h"
+#include "content/public/browser/access_token_store.h"
 #include "content/public/browser/android/synchronous_compositor.h"
+#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/geolocation_provider.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_client.h"
@@ -36,6 +39,42 @@
 #include "ui/gl/gl_surface.h"
 
 namespace android_webview {
+namespace {
+
+class AwAccessTokenStore : public content::AccessTokenStore {
+ public:
+  AwAccessTokenStore() { }
+
+  // content::AccessTokenStore implementation
+  void LoadAccessTokens(const LoadAccessTokensCallback& request) override {
+    AccessTokenStore::AccessTokenMap access_token_map;
+    // AccessTokenMap and net::URLRequestContextGetter not used on Android,
+    // but Run needs to be called to finish the geolocation setup.
+    request.Run(access_token_map, NULL);
+  }
+  void SaveAccessToken(const GURL& server_url,
+                       const base::string16& access_token) override {}
+
+ private:
+  ~AwAccessTokenStore() override {}
+
+  DISALLOW_COPY_AND_ASSIGN(AwAccessTokenStore);
+};
+
+// A provider of Geolocation services to override AccessTokenStore.
+class AwGeolocationDelegate : public content::GeolocationDelegate {
+ public:
+  AwGeolocationDelegate() = default;
+
+  scoped_refptr<content::AccessTokenStore> CreateAccessTokenStore() final {
+    return new AwAccessTokenStore();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AwGeolocationDelegate);
+};
+
+}  // anonymous namespace
 
 AwBrowserMainParts::AwBrowserMainParts(AwBrowserContext* browser_context)
     : browser_context_(browser_context) {
@@ -88,6 +127,9 @@
 void AwBrowserMainParts::PreMainMessageLoopRun() {
   browser_context_->PreMainMessageLoopRun();
 
+  content::GeolocationProvider::SetGeolocationDelegate(
+      new AwGeolocationDelegate());
+
   AwDevToolsDiscoveryProvider::Install();
 
   content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView();
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 2a1e14a..abf4fb9 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -33,12 +33,10 @@
 #include "components/cdm/browser/cdm_message_filter_android.h"
 #include "components/crash/content/browser/crash_micro_dump_manager_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/browser_thread.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/client_certificate_delegate.h"
-#include "content/public/browser/geolocation_delegate.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -142,39 +140,6 @@
       process_id_, parent_render_frame_id, child_render_frame_id);
 }
 
-class AwAccessTokenStore : public content::AccessTokenStore {
- public:
-  AwAccessTokenStore() { }
-
-  // content::AccessTokenStore implementation
-  void LoadAccessTokens(const LoadAccessTokensCallback& request) override {
-    AccessTokenStore::AccessTokenMap access_token_map;
-    // AccessTokenMap and net::URLRequestContextGetter not used on Android,
-    // but Run needs to be called to finish the geolocation setup.
-    request.Run(access_token_map, NULL);
-  }
-  void SaveAccessToken(const GURL& server_url,
-                       const base::string16& access_token) override {}
-
- private:
-  ~AwAccessTokenStore() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(AwAccessTokenStore);
-};
-
-// A provider of Geolocation services to override AccessTokenStore.
-class AwGeolocationDelegate : public content::GeolocationDelegate {
- public:
-  AwGeolocationDelegate() = default;
-
-  scoped_refptr<content::AccessTokenStore> CreateAccessTokenStore() final {
-    return new AwAccessTokenStore();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AwGeolocationDelegate);
-};
-
 AwLocaleManager* g_locale_manager = NULL;
 
 }  // anonymous namespace
@@ -443,11 +408,6 @@
   return browser_context_->GetAwURLRequestContext()->GetNetLog();
 }
 
-content::GeolocationDelegate*
-AwContentBrowserClient::CreateGeolocationDelegate() {
-  return new AwGeolocationDelegate();
-}
-
 bool AwContentBrowserClient::IsFastShutdownPossible() {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kSingleProcess)) {
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 354843a..03bd4cac2 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -108,7 +108,6 @@
                        bool* no_javascript_access) override;
   void ResourceDispatcherHostCreated() override;
   net::NetLog* GetNetLog() override;
-  content::GeolocationDelegate* CreateGeolocationDelegate() override;
   bool IsFastShutdownPossible() override;
   void ClearCache(content::RenderFrameHost* rfh) override;
   void ClearCookies(content::RenderFrameHost* rfh) override;
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index b1405bef..4a1f37c 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -27,10 +27,13 @@
     : render_thread_manager_(state),
       last_egl_context_(eglGetCurrentContext()),
       surfaces_(SurfacesInstance::GetOrCreateInstance()),
-      surface_id_allocator_(surfaces_->CreateSurfaceIdAllocator()),
+      surface_id_allocator_(
+          new cc::SurfaceIdAllocator(surfaces_->AllocateSurfaceClientId())),
       last_committed_output_surface_id_(0u),
       last_submitted_output_surface_id_(0u) {
   DCHECK(last_egl_context_);
+  surfaces_->GetSurfaceManager()->RegisterSurfaceClientId(
+      surface_id_allocator_->client_id());
   surfaces_->GetSurfaceManager()->RegisterSurfaceFactoryClient(
       surface_id_allocator_->client_id(), this);
 }
@@ -43,6 +46,8 @@
   surface_factory_.reset();
   surfaces_->GetSurfaceManager()->UnregisterSurfaceFactoryClient(
       surface_id_allocator_->client_id());
+  surfaces_->GetSurfaceManager()->InvalidateSurfaceClientId(
+      surface_id_allocator_->client_id());
 
   // Reset draw constraints.
   render_thread_manager_->PostExternalDrawConstraintsToChildCompositorOnRT(
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc
index d7b2647..a2e30f3 100644
--- a/android_webview/browser/surfaces_instance.cc
+++ b/android_webview/browser/surfaces_instance.cc
@@ -52,7 +52,7 @@
   surface_manager_.reset(new cc::SurfaceManager);
   surface_id_allocator_.reset(
       new cc::SurfaceIdAllocator(next_surface_client_id_++));
-  surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get());
+  surface_manager_->RegisterSurfaceClientId(surface_id_allocator_->client_id());
 
   std::unique_ptr<cc::BeginFrameSource> begin_frame_source(
       new cc::StubBeginFrameSource);
@@ -87,14 +87,13 @@
   DCHECK(child_ids_.empty());
   if (!root_id_.is_null())
     surface_factory_->Destroy(root_id_);
+
+  surface_manager_->InvalidateSurfaceClientId(
+      surface_id_allocator_->client_id());
 }
 
-std::unique_ptr<cc::SurfaceIdAllocator>
-SurfacesInstance::CreateSurfaceIdAllocator() {
-  std::unique_ptr<cc::SurfaceIdAllocator> allocator =
-      base::WrapUnique(new cc::SurfaceIdAllocator(next_surface_client_id_++));
-  allocator->RegisterSurfaceClientId(surface_manager_.get());
-  return allocator;
+uint32_t SurfacesInstance::AllocateSurfaceClientId() {
+  return next_surface_client_id_++;
 }
 
 cc::SurfaceManager* SurfacesInstance::GetSurfaceManager() {
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h
index e92f15b..eb01f71 100644
--- a/android_webview/browser/surfaces_instance.h
+++ b/android_webview/browser/surfaces_instance.h
@@ -38,7 +38,7 @@
  public:
   static scoped_refptr<SurfacesInstance> GetOrCreateInstance();
 
-  std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator();
+  uint32_t AllocateSurfaceClientId();
   cc::SurfaceManager* GetSurfaceManager();
   void SetBackingFrameBufferObject(int framebuffer_binding_ext);
 
diff --git a/ash/accelerators/accelerator_delegate.cc b/ash/accelerators/accelerator_delegate.cc
index db8024f..92456ea 100644
--- a/ash/accelerators/accelerator_delegate.cc
+++ b/ash/accelerators/accelerator_delegate.cc
@@ -4,114 +4,23 @@
 
 #include "ash/accelerators/accelerator_delegate.h"
 
-#include "ash/common/accelerators/accelerator_controller.h"
-#include "ash/common/wm/window_state.h"
-#include "ash/common/wm_shell.h"
-#include "ash/shell.h"
-#include "ash/wm/window_state_aura.h"
-#include "ui/base/accelerators/accelerator.h"
+#include "ash/aura/wm_window_aura.h"
+#include "ash/common/accelerators/accelerator_router.h"
+#include "ui/aura/window.h"
 #include "ui/events/event.h"
-#include "ui/wm/core/window_util.h"
 
 namespace ash {
 
-namespace {
+AcceleratorDelegate::AcceleratorDelegate() : router_(new AcceleratorRouter) {}
 
-// Returns true if |key_code| is a key usually handled directly by the shell.
-bool IsSystemKey(ui::KeyboardCode key_code) {
-#if defined(OS_CHROMEOS)
-  switch (key_code) {
-    case ui::VKEY_MEDIA_LAUNCH_APP2:  // Fullscreen button.
-    case ui::VKEY_MEDIA_LAUNCH_APP1:  // Overview button.
-    case ui::VKEY_BRIGHTNESS_DOWN:
-    case ui::VKEY_BRIGHTNESS_UP:
-    case ui::VKEY_KBD_BRIGHTNESS_DOWN:
-    case ui::VKEY_KBD_BRIGHTNESS_UP:
-    case ui::VKEY_VOLUME_MUTE:
-    case ui::VKEY_VOLUME_DOWN:
-    case ui::VKEY_VOLUME_UP:
-    case ui::VKEY_POWER:
-      return true;
-    default:
-      return false;
-  }
-#endif  // defined(OS_CHROMEOS)
-  return false;
-}
-
-}  // namespace
-
-AcceleratorDelegate::AcceleratorDelegate() {}
 AcceleratorDelegate::~AcceleratorDelegate() {}
 
 bool AcceleratorDelegate::ProcessAccelerator(
     const ui::KeyEvent& key_event,
     const ui::Accelerator& accelerator) {
-  // Special hardware keys like brightness and volume are handled in
-  // special way. However, some windows can override this behavior
-  // (e.g. Chrome v1 apps by default and Chrome v2 apps with
-  // permission) by setting a window property.
-  if (IsSystemKey(key_event.key_code()) && !CanConsumeSystemKeys(key_event)) {
-    // System keys are always consumed regardless of whether they trigger an
-    // accelerator to prevent windows from seeing unexpected key up events.
-    WmShell::Get()->accelerator_controller()->Process(accelerator);
-    return true;
-  }
-  if (!ShouldProcessAcceleratorNow(key_event, accelerator))
-    return false;
-  return WmShell::Get()->accelerator_controller()->Process(accelerator);
-}
-
-// Uses the top level window so if the target is a web contents window the
-// containing parent window will be checked for the property.
-bool AcceleratorDelegate::CanConsumeSystemKeys(const ui::KeyEvent& event) {
-  aura::Window* target = static_cast<aura::Window*>(event.target());
-  DCHECK(target);
-  aura::Window* top_level = ::wm::GetToplevelWindow(target);
-  return top_level && wm::GetWindowState(top_level)->can_consume_system_keys();
-}
-
-// Returns true if the |accelerator| should be processed now, inside Ash's env
-// event filter.
-bool AcceleratorDelegate::ShouldProcessAcceleratorNow(
-    const ui::KeyEvent& event,
-    const ui::Accelerator& accelerator) {
-  // On ChromeOS, If the accelerator is Search+<key(s)> then it must never be
-  // intercepted by apps or windows.
-  if (accelerator.IsCmdDown())
-    return true;
-
-  aura::Window* target = static_cast<aura::Window*>(event.target());
-  DCHECK(target);
-
-  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
-  if (std::find(root_windows.begin(), root_windows.end(), target) !=
-      root_windows.end())
-    return true;
-
-  aura::Window* top_level = ::wm::GetToplevelWindow(target);
-  AcceleratorController* accelerator_controller =
-      WmShell::Get()->accelerator_controller();
-
-  // Reserved accelerators (such as Power button) always have a prority.
-  if (accelerator_controller->IsReserved(accelerator))
-    return true;
-
-  // A full screen window has a right to handle all key events including the
-  // reserved ones.
-  if (top_level && wm::GetWindowState(top_level)->IsFullscreen()) {
-    // On ChromeOS, fullscreen windows are either browser or apps, which
-    // send key events to a web content first, then will process keys
-    // if the web content didn't consume them.
-    return false;
-  }
-
-  // Handle preferred accelerators (such as ALT-TAB) before sending
-  // to the target.
-  if (accelerator_controller->IsPreferred(accelerator))
-    return true;
-
-  return WmShell::Get()->GetAppListTargetVisibility();
+  return router_->ProcessAccelerator(
+      WmWindowAura::Get(static_cast<aura::Window*>(key_event.target())),
+      key_event, accelerator);
 }
 
 }  // namespace ash
diff --git a/ash/accelerators/accelerator_delegate.h b/ash/accelerators/accelerator_delegate.h
index 0614f87..18775a4 100644
--- a/ash/accelerators/accelerator_delegate.h
+++ b/ash/accelerators/accelerator_delegate.h
@@ -5,6 +5,8 @@
 #ifndef ASH_ACCELERATORS_ACCELERATOR_DELEGATE_H_
 #define ASH_ACCELERATORS_ACCELERATOR_DELEGATE_H_
 
+#include <memory>
+
 #include "ash/ash_export.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
@@ -12,6 +14,8 @@
 
 namespace ash {
 
+class AcceleratorRouter;
+
 class ASH_EXPORT AcceleratorDelegate
     : NON_EXPORTED_BASE(public ::wm::AcceleratorDelegate) {
  public:
@@ -23,12 +27,7 @@
                           const ui::Accelerator& accelerator) override;
 
  private:
-  // Returns true if the window should be allowed a chance to handle
-  // system keys.
-  bool CanConsumeSystemKeys(const ui::KeyEvent& event);
-
-  bool ShouldProcessAcceleratorNow(const ui::KeyEvent& event,
-                                   const ui::Accelerator& accelerator);
+  std::unique_ptr<AcceleratorRouter> router_;
 
   DISALLOW_COPY_AND_ASSIGN(AcceleratorDelegate);
 };
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 8834013..ce88229 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -49,6 +49,8 @@
       'common/accelerators/accelerator_controller.cc',
       'common/accelerators/accelerator_controller.h',
       'common/accelerators/accelerator_controller_delegate.h',
+      'common/accelerators/accelerator_router.cc',
+      'common/accelerators/accelerator_router.h',
       'common/accelerators/accelerator_table.cc',
       'common/accelerators/accelerator_table.h',
       'common/accelerators/debug_commands.cc',
@@ -83,7 +85,7 @@
       'common/metrics/user_metrics_action.h',
       'common/multi_profile_uma.cc',
       'common/multi_profile_uma.h',
-      'common/pointer_down_watcher_delegate.h',
+      'common/pointer_watcher_delegate.h',
       'common/popup_message.cc',
       'common/popup_message.h',
       'common/root_window_controller_common.cc',
@@ -109,8 +111,6 @@
       'common/shelf/shelf_constants.cc',
       'common/shelf/shelf_constants.h',
       'common/shelf/shelf_item_delegate.h',
-      'common/shelf/shelf_item_delegate_manager.cc',
-      'common/shelf/shelf_item_delegate_manager.h',
       'common/shelf/shelf_item_types.cc',
       'common/shelf/shelf_item_types.h',
       'common/shelf/shelf_locking_manager.cc',
@@ -592,8 +592,8 @@
       'metrics/task_switch_time_tracker.h',
       'metrics/user_metrics_recorder.cc',
       'metrics/user_metrics_recorder.h',
-      'pointer_down_watcher_delegate_aura.cc',
-      'pointer_down_watcher_delegate_aura.h',
+      'pointer_watcher_delegate_aura.cc',
+      'pointer_watcher_delegate_aura.h',
       'root_window_controller.cc',
       'root_window_controller.h',
       'root_window_settings.cc',
@@ -809,8 +809,6 @@
       'test/overflow_bubble_view_test_api.h',
       'test/shelf_button_pressed_metric_tracker_test_api.cc',
       'test/shelf_button_pressed_metric_tracker_test_api.h',
-      'test/shelf_item_delegate_manager_test_api.cc',
-      'test/shelf_item_delegate_manager_test_api.h',
       'test/shelf_test_api.h',
       'test/shelf_view_test_api.cc',
       'test/shelf_view_test_api.h',
diff --git a/ash/aura/wm_shell_aura.cc b/ash/aura/wm_shell_aura.cc
index 6ea068cf..3908dad 100644
--- a/ash/aura/wm_shell_aura.cc
+++ b/ash/aura/wm_shell_aura.cc
@@ -205,12 +205,12 @@
   display_observers_.RemoveObserver(observer);
 }
 
-void WmShellAura::AddPointerDownWatcher(views::PointerDownWatcher* watcher) {
-  Shell::GetInstance()->AddPointerDownWatcher(watcher);
+void WmShellAura::AddPointerWatcher(views::PointerWatcher* watcher) {
+  Shell::GetInstance()->AddPointerWatcher(watcher);
 }
 
-void WmShellAura::RemovePointerDownWatcher(views::PointerDownWatcher* watcher) {
-  Shell::GetInstance()->RemovePointerDownWatcher(watcher);
+void WmShellAura::RemovePointerWatcher(views::PointerWatcher* watcher) {
+  Shell::GetInstance()->RemovePointerWatcher(watcher);
 }
 
 #if defined(OS_CHROMEOS)
diff --git a/ash/aura/wm_shell_aura.h b/ash/aura/wm_shell_aura.h
index f5deab9..882afa5 100644
--- a/ash/aura/wm_shell_aura.h
+++ b/ash/aura/wm_shell_aura.h
@@ -61,8 +61,8 @@
   void RemoveActivationObserver(WmActivationObserver* observer) override;
   void AddDisplayObserver(WmDisplayObserver* observer) override;
   void RemoveDisplayObserver(WmDisplayObserver* observer) override;
-  void AddPointerDownWatcher(views::PointerDownWatcher* watcher) override;
-  void RemovePointerDownWatcher(views::PointerDownWatcher* watcher) override;
+  void AddPointerWatcher(views::PointerWatcher* watcher) override;
+  void RemovePointerWatcher(views::PointerWatcher* watcher) override;
 #if defined(OS_CHROMEOS)
   void ToggleIgnoreExternalKeyboard() override;
 #endif
diff --git a/ash/aura/wm_window_aura.cc b/ash/aura/wm_window_aura.cc
index 3717e00..f3345f9 100644
--- a/ash/aura/wm_window_aura.cc
+++ b/ash/aura/wm_window_aura.cc
@@ -286,6 +286,10 @@
   return Get(window_->GetToplevelWindow());
 }
 
+WmWindow* WmWindowAura::GetToplevelWindowForFocus() {
+  return Get(::wm::GetToplevelWindow(window_));
+}
+
 void WmWindowAura::SetParentUsingContext(WmWindow* context,
                                          const gfx::Rect& screen_bounds) {
   aura::client::ParentWindowWithContext(window_, GetAuraWindow(context),
diff --git a/ash/aura/wm_window_aura.h b/ash/aura/wm_window_aura.h
index 07e7239..b084b80f 100644
--- a/ash/aura/wm_window_aura.h
+++ b/ash/aura/wm_window_aura.h
@@ -76,6 +76,7 @@
   int GetIntProperty(WmWindowProperty key) override;
   const wm::WindowState* GetWindowState() const override;
   WmWindow* GetToplevelWindow() override;
+  WmWindow* GetToplevelWindowForFocus() override;
   void SetParentUsingContext(WmWindow* context,
                              const gfx::Rect& screen_bounds) override;
   void AddChild(WmWindow* window) override;
diff --git a/ash/common/accelerators/accelerator_router.cc b/ash/common/accelerators/accelerator_router.cc
new file mode 100644
index 0000000..51e08cbd
--- /dev/null
+++ b/ash/common/accelerators/accelerator_router.cc
@@ -0,0 +1,115 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/common/accelerators/accelerator_router.h"
+
+#include "ash/common/accelerators/accelerator_controller.h"
+#include "ash/common/wm/window_state.h"
+#include "ash/common/wm_shell.h"
+#include "ash/common/wm_window.h"
+#include "base/stl_util.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/events/event.h"
+
+namespace ash {
+
+namespace {
+
+// Returns true if |key_code| is a key usually handled directly by the shell.
+bool IsSystemKey(ui::KeyboardCode key_code) {
+#if defined(OS_CHROMEOS)
+  switch (key_code) {
+    case ui::VKEY_MEDIA_LAUNCH_APP2:  // Fullscreen button.
+    case ui::VKEY_MEDIA_LAUNCH_APP1:  // Overview button.
+    case ui::VKEY_BRIGHTNESS_DOWN:
+    case ui::VKEY_BRIGHTNESS_UP:
+    case ui::VKEY_KBD_BRIGHTNESS_DOWN:
+    case ui::VKEY_KBD_BRIGHTNESS_UP:
+    case ui::VKEY_VOLUME_MUTE:
+    case ui::VKEY_VOLUME_DOWN:
+    case ui::VKEY_VOLUME_UP:
+    case ui::VKEY_POWER:
+      return true;
+    default:
+      return false;
+  }
+#endif  // defined(OS_CHROMEOS)
+  return false;
+}
+
+}  // namespace
+
+AcceleratorRouter::AcceleratorRouter() {}
+
+AcceleratorRouter::~AcceleratorRouter() {}
+
+bool AcceleratorRouter::ProcessAccelerator(WmWindow* target,
+                                           const ui::KeyEvent& key_event,
+                                           const ui::Accelerator& accelerator) {
+  // Callers should never supply null.
+  DCHECK(target);
+  // Special hardware keys like brightness and volume are handled in
+  // special way. However, some windows can override this behavior
+  // (e.g. Chrome v1 apps by default and Chrome v2 apps with
+  // permission) by setting a window property.
+  if (IsSystemKey(key_event.key_code()) &&
+      !CanConsumeSystemKeys(target, key_event)) {
+    // System keys are always consumed regardless of whether they trigger an
+    // accelerator to prevent windows from seeing unexpected key up events.
+    WmShell::Get()->accelerator_controller()->Process(accelerator);
+    return true;
+  }
+  if (!ShouldProcessAcceleratorNow(target, key_event, accelerator))
+    return false;
+  return WmShell::Get()->accelerator_controller()->Process(accelerator);
+}
+
+bool AcceleratorRouter::CanConsumeSystemKeys(WmWindow* target,
+                                             const ui::KeyEvent& event) {
+  // Uses the top level window so if the target is a web contents window the
+  // containing parent window will be checked for the property.
+  WmWindow* top_level = target->GetToplevelWindowForFocus();
+  return top_level && top_level->GetWindowState()->can_consume_system_keys();
+}
+
+bool AcceleratorRouter::ShouldProcessAcceleratorNow(
+    WmWindow* target,
+    const ui::KeyEvent& event,
+    const ui::Accelerator& accelerator) {
+  // Callers should never supply null.
+  DCHECK(target);
+  // On ChromeOS, If the accelerator is Search+<key(s)> then it must never be
+  // intercepted by apps or windows.
+  if (accelerator.IsCmdDown())
+    return true;
+
+  if (ContainsValue(WmShell::Get()->GetAllRootWindows(), target))
+    return true;
+
+  AcceleratorController* accelerator_controller =
+      WmShell::Get()->accelerator_controller();
+
+  // Reserved accelerators (such as Power button) always have a prority.
+  if (accelerator_controller->IsReserved(accelerator))
+    return true;
+
+  // A full screen window has a right to handle all key events including the
+  // reserved ones.
+  WmWindow* top_level = target->GetToplevelWindowForFocus();
+  if (top_level && top_level->GetWindowState()->IsFullscreen()) {
+    // On ChromeOS, fullscreen windows are either browser or apps, which
+    // send key events to a web content first, then will process keys
+    // if the web content didn't consume them.
+    return false;
+  }
+
+  // Handle preferred accelerators (such as ALT-TAB) before sending
+  // to the target.
+  if (accelerator_controller->IsPreferred(accelerator))
+    return true;
+
+  return WmShell::Get()->GetAppListTargetVisibility();
+}
+
+}  // namespace ash
diff --git a/ash/common/accelerators/accelerator_router.h b/ash/common/accelerators/accelerator_router.h
new file mode 100644
index 0000000..048145f
--- /dev/null
+++ b/ash/common/accelerators/accelerator_router.h
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_ACCELERATORS_ACCELERATOR_ROUTER_H_
+#define ASH_ACCELERATORS_ACCELERATOR_ROUTER_H_
+
+#include "ash/ash_export.h"
+#include "base/macros.h"
+
+namespace ui {
+class Accelerator;
+class KeyEvent;
+}
+
+namespace ash {
+
+class WmWindow;
+
+// AcceleratorRouter does a minimal amount of processing before routing the
+// accelerator to the AcceleratorController. AcceleratorRouter may also decide
+// not to process certain accelerators.
+class ASH_EXPORT AcceleratorRouter {
+ public:
+  AcceleratorRouter();
+  ~AcceleratorRouter();
+
+  // Returns true if event should be consumed. |target| is the target of the
+  // event.
+  bool ProcessAccelerator(WmWindow* target,
+                          const ui::KeyEvent& event,
+                          const ui::Accelerator& accelerator);
+
+ private:
+  // Returns true if the window should be allowed a chance to handle
+  // system keys.
+  bool CanConsumeSystemKeys(WmWindow* target, const ui::KeyEvent& event);
+
+  // Returns true if the |accelerator| should be processed now.
+  bool ShouldProcessAcceleratorNow(WmWindow* target,
+                                   const ui::KeyEvent& event,
+                                   const ui::Accelerator& accelerator);
+
+  DISALLOW_COPY_AND_ASSIGN(AcceleratorRouter);
+};
+
+}  // namespace ash
+
+#endif  // ASH_ACCELERATORS_ACCELERATOR_ROUTER_H_
diff --git a/ash/common/pointer_down_watcher_delegate.h b/ash/common/pointer_down_watcher_delegate.h
deleted file mode 100644
index 87a63edc..0000000
--- a/ash/common/pointer_down_watcher_delegate.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_COMMON_POINTER_DOWN_WATCHER_DELEGATE_H_
-#define ASH_COMMON_POINTER_DOWN_WATCHER_DELEGATE_H_
-
-#include "ash/ash_export.h"
-
-namespace views {
-class PointerDownWatcher;
-}
-
-namespace ash {
-
-// Allows different implementations of PointerDownWatcher in mus and
-// non-mus ash.
-class ASH_EXPORT PointerDownWatcherDelegate {
- public:
-  virtual ~PointerDownWatcherDelegate() {}
-
-  virtual void AddPointerDownWatcher(views::PointerDownWatcher* watcher) = 0;
-  virtual void RemovePointerDownWatcher(views::PointerDownWatcher* watcher) = 0;
-};
-
-}  // namespace ash
-
-#endif  // ASH_COMMON_POINTER_DOWN_WATCHER_DELEGATE_H_
diff --git a/ash/common/pointer_watcher_delegate.h b/ash/common/pointer_watcher_delegate.h
new file mode 100644
index 0000000..75f8738
--- /dev/null
+++ b/ash/common/pointer_watcher_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_COMMON_POINTER_WATCHER_DELEGATE_H_
+#define ASH_COMMON_POINTER_WATCHER_DELEGATE_H_
+
+#include "ash/ash_export.h"
+
+namespace views {
+class PointerWatcher;
+}
+
+namespace ash {
+
+// Allows different implementations of PointerWatcher in mus and non-mus ash.
+class ASH_EXPORT PointerWatcherDelegate {
+ public:
+  virtual ~PointerWatcherDelegate() {}
+
+  virtual void AddPointerWatcher(views::PointerWatcher* watcher) = 0;
+  virtual void RemovePointerWatcher(views::PointerWatcher* watcher) = 0;
+};
+
+}  // namespace ash
+
+#endif  // ASH_COMMON_POINTER_WATCHER_DELEGATE_H_
diff --git a/ash/common/shelf/app_list_shelf_item_delegate.cc b/ash/common/shelf/app_list_shelf_item_delegate.cc
index ce1b5e3..128a7e7 100644
--- a/ash/common/shelf/app_list_shelf_item_delegate.cc
+++ b/ash/common/shelf/app_list_shelf_item_delegate.cc
@@ -6,21 +6,32 @@
 
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/wm_shell.h"
+#include "base/memory/ptr_util.h"
 #include "grit/ash_strings.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
 
-AppListShelfItemDelegate::AppListShelfItemDelegate() {
+// static
+void AppListShelfItemDelegate::CreateAppListItemAndDelegate(
+    ShelfModel* shelf_model) {
+  // Add the app list item to the shelf model.
   ShelfItem app_list;
   app_list.type = TYPE_APP_LIST;
-  WmShell::Get()->shelf_model()->Add(app_list);
+  int app_list_index = shelf_model->Add(app_list);
+  DCHECK_GE(app_list_index, 0);
+
+  // Create an AppListShelfItemDelegate for that item.
+  ShelfID app_list_id = shelf_model->items()[app_list_index].id;
+  DCHECK_GE(app_list_id, 0);
+  shelf_model->SetShelfItemDelegate(
+      app_list_id, base::MakeUnique<AppListShelfItemDelegate>());
 }
 
-AppListShelfItemDelegate::~AppListShelfItemDelegate() {
-  // ShelfItemDelegateManager owns and destroys this class.
-}
+AppListShelfItemDelegate::AppListShelfItemDelegate() {}
+
+AppListShelfItemDelegate::~AppListShelfItemDelegate() {}
 
 ShelfItemDelegate::PerformedAction AppListShelfItemDelegate::ItemSelected(
     const ui::Event& event) {
diff --git a/ash/common/shelf/app_list_shelf_item_delegate.h b/ash/common/shelf/app_list_shelf_item_delegate.h
index 07a51fd..bb8e1f0 100644
--- a/ash/common/shelf/app_list_shelf_item_delegate.h
+++ b/ash/common/shelf/app_list_shelf_item_delegate.h
@@ -9,12 +9,16 @@
 #include "base/macros.h"
 
 namespace ash {
+class ShelfModel;
 
 // ShelfItemDelegate for TYPE_APP_LIST.
 class AppListShelfItemDelegate : public ShelfItemDelegate {
  public:
-  AppListShelfItemDelegate();
+  // Initializes the app list item in the shelf data model and creates an
+  // AppListShelfItemDelegate which will be owned by |shelf_model|.
+  static void CreateAppListItemAndDelegate(ShelfModel* shelf_model);
 
+  AppListShelfItemDelegate();
   ~AppListShelfItemDelegate() override;
 
   // ShelfItemDelegate:
diff --git a/ash/common/shelf/overflow_bubble.cc b/ash/common/shelf/overflow_bubble.cc
index eadd54e..0a5428ab3 100644
--- a/ash/common/shelf/overflow_bubble.cc
+++ b/ash/common/shelf/overflow_bubble.cc
@@ -19,12 +19,12 @@
       bubble_(nullptr),
       anchor_(nullptr),
       shelf_view_(nullptr) {
-  WmShell::Get()->AddPointerDownWatcher(this);
+  WmShell::Get()->AddPointerWatcher(this);
 }
 
 OverflowBubble::~OverflowBubble() {
   Hide();
-  WmShell::Get()->RemovePointerDownWatcher(this);
+  WmShell::Get()->RemovePointerWatcher(this);
 }
 
 void OverflowBubble::Show(views::View* anchor, ShelfView* shelf_view) {
diff --git a/ash/common/shelf/overflow_bubble.h b/ash/common/shelf/overflow_bubble.h
index 194c25dd..7e35260 100644
--- a/ash/common/shelf/overflow_bubble.h
+++ b/ash/common/shelf/overflow_bubble.h
@@ -6,7 +6,7 @@
 #define ASH_COMMON_SHELF_OVERFLOW_BUBBLE_H_
 
 #include "base/macros.h"
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 #include "ui/views/widget/widget_observer.h"
 
 namespace ui {
@@ -24,7 +24,7 @@
 
 // OverflowBubble shows shelf items that won't fit on the main shelf in a
 // separate bubble.
-class OverflowBubble : public views::PointerDownWatcher,
+class OverflowBubble : public views::PointerWatcher,
                        public views::WidgetObserver {
  public:
   // |wm_shelf| is the shelf that spawns the bubble.
@@ -48,7 +48,7 @@
  private:
   void ProcessPressedEvent(const gfx::Point& event_location_in_screen);
 
-  // views::PointerDownWatcher:
+  // views::PointerWatcher:
   void OnMousePressed(const ui::MouseEvent& event,
                       const gfx::Point& location_in_screen,
                       views::Widget* target) override;
diff --git a/ash/common/shelf/shelf_item_delegate_manager.cc b/ash/common/shelf/shelf_item_delegate_manager.cc
deleted file mode 100644
index 29670018..0000000
--- a/ash/common/shelf/shelf_item_delegate_manager.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
-
-#include "ash/common/shelf/shelf_item_delegate.h"
-#include "ash/common/shelf/shelf_model.h"
-#include "base/logging.h"
-#include "base/stl_util.h"
-
-namespace ash {
-
-ShelfItemDelegateManager::ShelfItemDelegateManager(ShelfModel* model)
-    : model_(model) {
-  DCHECK(model_);
-  model_->AddObserver(this);
-}
-
-ShelfItemDelegateManager::~ShelfItemDelegateManager() {
-  model_->RemoveObserver(this);
-  STLDeleteContainerPairSecondPointers(id_to_item_delegate_map_.begin(),
-                                       id_to_item_delegate_map_.end());
-}
-
-void ShelfItemDelegateManager::AddObserver(
-    ShelfItemDelegateManagerObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void ShelfItemDelegateManager::RemoveObserver(
-    ShelfItemDelegateManagerObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-void ShelfItemDelegateManager::SetShelfItemDelegate(
-    ShelfID id,
-    std::unique_ptr<ShelfItemDelegate> item_delegate) {
-  // If another ShelfItemDelegate is already registered for |id|, we assume
-  // that this request is replacing ShelfItemDelegate for |id| with
-  // |item_delegate|.
-  RemoveShelfItemDelegate(id);
-
-  FOR_EACH_OBSERVER(ShelfItemDelegateManagerObserver, observers_,
-                    OnSetShelfItemDelegate(id, item_delegate.get()));
-
-  id_to_item_delegate_map_[id] = item_delegate.release();
-}
-
-ShelfItemDelegate* ShelfItemDelegateManager::GetShelfItemDelegate(ShelfID id) {
-  if (model_->ItemIndexByID(id) != -1) {
-    // Each ShelfItem has to have a ShelfItemDelegate.
-    DCHECK(id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end());
-    return id_to_item_delegate_map_[id];
-  }
-  return NULL;
-}
-
-void ShelfItemDelegateManager::ShelfItemAdded(int index) {}
-
-void ShelfItemDelegateManager::ShelfItemRemoved(int index, ShelfID id) {
-  RemoveShelfItemDelegate(id);
-  FOR_EACH_OBSERVER(ShelfItemDelegateManagerObserver, observers_,
-                    OnSetShelfItemDelegate(id, nullptr));
-}
-
-void ShelfItemDelegateManager::ShelfItemMoved(int start_index,
-                                              int target_index) {}
-
-void ShelfItemDelegateManager::ShelfItemChanged(int index,
-                                                const ShelfItem& old_item) {}
-
-void ShelfItemDelegateManager::RemoveShelfItemDelegate(ShelfID id) {
-  if (id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end()) {
-    delete id_to_item_delegate_map_[id];
-    id_to_item_delegate_map_.erase(id);
-  }
-}
-
-}  // namespace ash
diff --git a/ash/common/shelf/shelf_item_delegate_manager.h b/ash/common/shelf/shelf_item_delegate_manager.h
deleted file mode 100644
index 5a863f5..0000000
--- a/ash/common/shelf/shelf_item_delegate_manager.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_COMMON_SHELF_SHELF_ITEM_DELEGATE_MANAGER_H_
-#define ASH_COMMON_SHELF_SHELF_ITEM_DELEGATE_MANAGER_H_
-
-#include <map>
-#include <memory>
-
-#include "ash/ash_export.h"
-#include "ash/common/shelf/shelf_item_types.h"
-#include "ash/common/shelf/shelf_model_observer.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-
-namespace ash {
-class ShelfItemDelegate;
-class ShelfModel;
-
-namespace test {
-class ShelfItemDelegateManagerTestAPI;
-}
-
-// This class is added as a temporary fix for M39 to fix crbug.com/329597.
-// TODO(skuhne): Find the real reason for this problem and remove this fix.
-class ASH_EXPORT ShelfItemDelegateManagerObserver {
- public:
-  ShelfItemDelegateManagerObserver() {}
-  virtual ~ShelfItemDelegateManagerObserver() {}
-
-  // Gets called when a ShelfItemDelegate gets changed. Note that
-  // |item_delegate| can be NULL.
-  virtual void OnSetShelfItemDelegate(ShelfID id,
-                                      ShelfItemDelegate* item_delegate) = 0;
-};
-
-// ShelfItemDelegateManager manages the set of ShelfItemDelegates for the
-// launcher. ShelfItemDelegateManager does not create ShelfItemDelegates,
-// rather it is expected that someone else invokes SetShelfItemDelegate
-// appropriately. On the other hand, ShelfItemDelegateManager destroys
-// ShelfItemDelegates when the corresponding item from the model is removed.
-class ASH_EXPORT ShelfItemDelegateManager : public ShelfModelObserver {
- public:
-  explicit ShelfItemDelegateManager(ShelfModel* model);
-  ~ShelfItemDelegateManager() override;
-
-  void AddObserver(ShelfItemDelegateManagerObserver* observer);
-  void RemoveObserver(ShelfItemDelegateManagerObserver* observer);
-
-  // Set |item_delegate| for |id| and take an ownership.
-  void SetShelfItemDelegate(ShelfID id,
-                            std::unique_ptr<ShelfItemDelegate> item_delegate);
-
-  // Returns ShelfItemDelegate for |item_type|. Always returns non-NULL.
-  ShelfItemDelegate* GetShelfItemDelegate(ShelfID id);
-
-  // ShelfModelObserver overrides:
-  void ShelfItemAdded(int model_index) override;
-  void ShelfItemRemoved(int index, ShelfID id) override;
-  void ShelfItemMoved(int start_index, int targetindex) override;
-  void ShelfItemChanged(int index, const ShelfItem& old_item) override;
-
- private:
-  friend class test::ShelfItemDelegateManagerTestAPI;
-
-  typedef std::map<ShelfID, ShelfItemDelegate*> ShelfIDToItemDelegateMap;
-
-  // Remove and destroy ShelfItemDelegate for |id|.
-  void RemoveShelfItemDelegate(ShelfID id);
-
-  // Owned by Shell.
-  ShelfModel* model_;
-
-  ShelfIDToItemDelegateMap id_to_item_delegate_map_;
-
-  base::ObserverList<ShelfItemDelegateManagerObserver> observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfItemDelegateManager);
-};
-
-}  // namespace ash
-
-#endif  // ASH_COMMON_SHELF_SHELF_ITEM_DELEGATE_MANAGER_H_
diff --git a/ash/common/shelf/shelf_model.cc b/ash/common/shelf/shelf_model.cc
index 7577aec..15b4d09c 100644
--- a/ash/common/shelf/shelf_model.cc
+++ b/ash/common/shelf/shelf_model.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "ash/common/shelf/shelf_item_delegate.h"
 #include "ash/common/shelf/shelf_model_observer.h"
 
 namespace ash {
@@ -49,6 +50,12 @@
 
 ShelfModel::~ShelfModel() {}
 
+void ShelfModel::DestroyItemDelegates() {
+  // Some ShelfItemDelegates access this model in their destructors and hence
+  // need early cleanup.
+  id_to_item_delegate_map_.clear();
+}
+
 int ShelfModel::Add(const ShelfItem& item) {
   return AddAt(items_.size(), item);
 }
@@ -68,6 +75,10 @@
          items_[index].type != TYPE_BROWSER_SHORTCUT);
   ShelfID id = items_[index].id;
   items_.erase(items_.begin() + index);
+  RemoveShelfItemDelegate(id);
+  // TODO(jamescook): Fold this into ShelfItemRemoved in existing observers.
+  FOR_EACH_OBSERVER(ShelfModelObserver, observers_,
+                    OnSetShelfItemDelegate(id, nullptr));
   FOR_EACH_OBSERVER(ShelfModelObserver, observers_,
                     ShelfItemRemoved(index, id));
 }
@@ -151,6 +162,26 @@
          items_.begin();
 }
 
+void ShelfModel::SetShelfItemDelegate(
+    ShelfID id,
+    std::unique_ptr<ShelfItemDelegate> item_delegate) {
+  // If another ShelfItemDelegate is already registered for |id|, we assume
+  // that this request is replacing ShelfItemDelegate for |id| with
+  // |item_delegate|.
+  RemoveShelfItemDelegate(id);
+
+  FOR_EACH_OBSERVER(ShelfModelObserver, observers_,
+                    OnSetShelfItemDelegate(id, item_delegate.get()));
+
+  id_to_item_delegate_map_[id] = std::move(item_delegate);
+}
+
+ShelfItemDelegate* ShelfModel::GetShelfItemDelegate(ShelfID id) {
+  if (id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end())
+    return id_to_item_delegate_map_[id].get();
+  return nullptr;
+}
+
 void ShelfModel::AddObserver(ShelfModelObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -177,4 +208,9 @@
   return index;
 }
 
+void ShelfModel::RemoveShelfItemDelegate(ShelfID id) {
+  if (id_to_item_delegate_map_.find(id) != id_to_item_delegate_map_.end())
+    id_to_item_delegate_map_.erase(id);
+}
+
 }  // namespace ash
diff --git a/ash/common/shelf/shelf_model.h b/ash/common/shelf/shelf_model.h
index deeffac9..112f0b42 100644
--- a/ash/common/shelf/shelf_model.h
+++ b/ash/common/shelf/shelf_model.h
@@ -5,6 +5,9 @@
 #ifndef ASH_COMMON_SHELF_SHELF_MODEL_H_
 #define ASH_COMMON_SHELF_SHELF_MODEL_H_
 
+#include <map>
+#include <memory>
+
 #include "ash/ash_export.h"
 #include "ash/common/shelf/shelf_item_types.h"
 #include "base/macros.h"
@@ -12,9 +15,11 @@
 
 namespace ash {
 
+class ShelfItemDelegate;
 class ShelfModelObserver;
 
-// Model used by ShelfView.
+// Model used for shelf items. Owns ShelfItemDelegates, but does not create
+// them.
 class ASH_EXPORT ShelfModel {
  public:
   enum Status {
@@ -26,6 +31,9 @@
   ShelfModel();
   ~ShelfModel();
 
+  // Cleans up the ShelfItemDelegates.
+  void DestroyItemDelegates();
+
   // Adds a new item to the model. Returns the resulting index.
   int Add(const ShelfItem& item);
 
@@ -77,6 +85,13 @@
   void set_status(Status status) { status_ = status; }
   Status status() const { return status_; }
 
+  // Set |item_delegate| for |id| and takes ownership.
+  void SetShelfItemDelegate(ShelfID id,
+                            std::unique_ptr<ShelfItemDelegate> item_delegate);
+
+  // Returns ShelfItemDelegate for |id|, or null if none exists.
+  ShelfItemDelegate* GetShelfItemDelegate(ShelfID id);
+
   void AddObserver(ShelfModelObserver* observer);
   void RemoveObserver(ShelfModelObserver* observer);
 
@@ -86,6 +101,9 @@
   // returns the new value.
   int ValidateInsertionIndex(ShelfItemType type, int index) const;
 
+  // Remove and destroy ShelfItemDelegate for |id|.
+  void RemoveShelfItemDelegate(ShelfID id);
+
   // ID assigned to the next item.
   ShelfID next_id_;
 
@@ -93,6 +111,9 @@
   Status status_;
   base::ObserverList<ShelfModelObserver> observers_;
 
+  std::map<ShelfID, std::unique_ptr<ShelfItemDelegate>>
+      id_to_item_delegate_map_;
+
   DISALLOW_COPY_AND_ASSIGN(ShelfModel);
 };
 
diff --git a/ash/common/shelf/shelf_model_observer.h b/ash/common/shelf/shelf_model_observer.h
index 7ef6764..794300d 100644
--- a/ash/common/shelf/shelf_model_observer.h
+++ b/ash/common/shelf/shelf_model_observer.h
@@ -11,6 +11,7 @@
 namespace ash {
 
 struct ShelfItem;
+class ShelfItemDelegate;
 
 class ASH_EXPORT ShelfModelObserver {
  public:
@@ -29,6 +30,13 @@
   // before the change.
   virtual void ShelfItemChanged(int index, const ShelfItem& old_item) = 0;
 
+  // Gets called when a ShelfItemDelegate gets changed. Note that
+  // |item_delegate| can be null.
+  // NOTE: This is added a temporary fix for M39 to fix crbug.com/429870.
+  // TODO(skuhne): Find the real reason for this problem and remove this fix.
+  virtual void OnSetShelfItemDelegate(ShelfID id,
+                                      ShelfItemDelegate* item_delegate) = 0;
+
  protected:
   virtual ~ShelfModelObserver() {}
 };
diff --git a/ash/common/shelf/shelf_model_unittest.cc b/ash/common/shelf/shelf_model_unittest.cc
index 209070d..e0b8bcc 100644
--- a/ash/common/shelf/shelf_model_unittest.cc
+++ b/ash/common/shelf/shelf_model_unittest.cc
@@ -45,6 +45,8 @@
   void ShelfItemMoved(int start_index, int target_index) override {
     moved_count_++;
   }
+  void OnSetShelfItemDelegate(ShelfID id,
+                              ShelfItemDelegate* item_delegate) override {}
 
  private:
   void AddToResult(const std::string& format, int count, std::string* result) {
diff --git a/ash/common/shell_delegate.h b/ash/common/shell_delegate.h
index b603675..11ffaf3 100644
--- a/ash/common/shell_delegate.h
+++ b/ash/common/shell_delegate.h
@@ -41,7 +41,7 @@
 class GPUSupport;
 class MediaDelegate;
 class NewWindowDelegate;
-class PointerDownWatcherDelegate;
+class PointerWatcherDelegate;
 class SessionStateDelegate;
 class ShelfDelegate;
 class ShelfModel;
@@ -123,8 +123,8 @@
   // Creates a media delegate. Shell takes ownership of the delegate.
   virtual MediaDelegate* CreateMediaDelegate() = 0;
 
-  virtual std::unique_ptr<PointerDownWatcherDelegate>
-  CreatePointerDownWatcherDelegate() = 0;
+  virtual std::unique_ptr<PointerWatcherDelegate>
+  CreatePointerWatcherDelegate() = 0;
 
   // Creates a menu model for the |wm_shelf| and optional shelf |item|.
   // If |item| is null, this creates a context menu for the desktop or shelf.
diff --git a/ash/common/strings/ash_strings_ca.xtb b/ash/common/strings/ash_strings_ca.xtb
index 316aef30..b186404 100644
--- a/ash/common/strings/ash_strings_ca.xtb
+++ b/ash/common/strings/ash_strings_ca.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">Ara se us tancarà la sessió.</translation>
 <translation id="2825619548187458965">Prestatge</translation>
 <translation id="2844169650293029770">Dispositiu USB-C (port frontal esquerre)</translation>
-<translation id="2857608528410806398">El cos de la notificació per a la funció QU va aquí. El cos de la notificació per a la funció QU va aquí. El cos de la notificació per a la funció QU va aquí. El cos de la notificació per a la funció QU va aquí. El cos de la notificació per a la funció QU va aquí.</translation>
+<translation id="2857608528410806398">El cos de la notificació per a la funció Desbloqueig ràpid va aquí. El cos de la notificació per a la funció Desbloqueig ràpid va aquí. El cos de la notificació per a la funció Desbloqueig ràpid va aquí. El cos de la notificació per a la funció Desbloqueig ràpid va aquí. El cos de la notificació per a la funció Desbloqueig ràpid va aquí.</translation>
 <translation id="2872961005593481000">Apaga</translation>
 <translation id="2942516765047364088">Posició del prestatge</translation>
 <translation id="2946640296642327832">Activa Bluetooth</translation>
@@ -222,7 +222,7 @@
 <translation id="7957227661277029961">És possible que el dispositiu <ph name="DEVICE_TYPE" /> no es carregui mentre està encès. Us recomanem que utilitzeu el carregador oficial.</translation>
 <translation id="7982789257301363584">Xarxa</translation>
 <translation id="8054466585765276473">S'està calculant el temps de la bateria.</translation>
-<translation id="8077816382010018681">El títol de la notificació per a la funció QU va aquí</translation>
+<translation id="8077816382010018681">El títol de la notificació per a la funció Desbloqueig ràpid va aquí</translation>
 <translation id="8103386449138765447">Missatges SMS: <ph name="MESSAGE_COUNT" /></translation>
 <translation id="8190698733819146287">Personalitza els idiomes i l'entrada...</translation>
 <translation id="8206859287963243715">Cel·lular</translation>
diff --git a/ash/common/strings/ash_strings_da.xtb b/ash/common/strings/ash_strings_da.xtb
index 881b2ca..40b071d 100644
--- a/ash/common/strings/ash_strings_da.xtb
+++ b/ash/common/strings/ash_strings_da.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">Du bliver logget ud nu.</translation>
 <translation id="2825619548187458965">Hylde</translation>
 <translation id="2844169650293029770">USB-C-enhed (porten foran i venstre side)</translation>
-<translation id="2857608528410806398">Underretningsteksten for QU-funktionen angives her.</translation>
+<translation id="2857608528410806398">QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here.</translation>
 <translation id="2872961005593481000">Sluk</translation>
 <translation id="2942516765047364088">Hyldeplacering</translation>
 <translation id="2946640296642327832">Aktivér Bluetooth</translation>
diff --git a/ash/common/strings/ash_strings_fr.xtb b/ash/common/strings/ash_strings_fr.xtb
index 88893e9..bd6ba52 100644
--- a/ash/common/strings/ash_strings_fr.xtb
+++ b/ash/common/strings/ash_strings_fr.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">Vous allez être déconnecté maintenant.</translation>
 <translation id="2825619548187458965">Étagère</translation>
 <translation id="2844169650293029770">Appareil USB de type C (port situé sur la gauche de l'appareil, à l'avant)</translation>
-<translation id="2857608528410806398">Le texte de la notification relative à la fonctionnalité de déverrouillage rapide s'affiche ici. Le texte de la notification relative à la fonctionnalité de déverrouillage rapide s'affiche ici. Le texte de la notification relative à la fonctionnalité de déverrouillage rapide s'affiche ici. Le texte de la notification relative à la fonctionnalité de déverrouillage rapide s'affiche ici. Le texte de la notification relative à la fonctionnalité de déverrouillage rapide s'affiche ici.</translation>
+<translation id="2857608528410806398">QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here.</translation>
 <translation id="2872961005593481000">Éteindre</translation>
 <translation id="2942516765047364088">Position de l'étagère</translation>
 <translation id="2946640296642327832">Activer le Bluetooth</translation>
@@ -222,7 +222,7 @@
 <translation id="7957227661277029961">Il est possible que votre appareil <ph name="DEVICE_TYPE" /> ne se recharge pas lorsqu'il est allumé. Essayez d'utiliser le chargeur officiel.</translation>
 <translation id="7982789257301363584">Réseau</translation>
 <translation id="8054466585765276473">Calcul de l'autonomie de la batterie en cours…</translation>
-<translation id="8077816382010018681">Saisir le titre de la notification relative à la fonctionnalité de déverrouillage rapide ici</translation>
+<translation id="8077816382010018681">QU Feature notification title here</translation>
 <translation id="8103386449138765447">Messages SMS : <ph name="MESSAGE_COUNT" /></translation>
 <translation id="8190698733819146287">Personnaliser les langues et la saisie...</translation>
 <translation id="8206859287963243715">Mobile</translation>
diff --git a/ash/common/strings/ash_strings_id.xtb b/ash/common/strings/ash_strings_id.xtb
index 9b7da90..cb0983c 100644
--- a/ash/common/strings/ash_strings_id.xtb
+++ b/ash/common/strings/ash_strings_id.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">Anda akan dikeluarkan sekarang.</translation>
 <translation id="2825619548187458965">Rak</translation>
 <translation id="2844169650293029770">Perangkat USB-C (port depan sebelah kiri)</translation>
-<translation id="2857608528410806398">Isi notifikasi Fitur QU ada di sini. Isi notifikasi Fitur QU ada di sini. Isi notifikasi Fitur QU ada di sini. Isi notifikasi Fitur QU ada di sini. Isi notifikasi Fitur QU ada di sini.</translation>
+<translation id="2857608528410806398">QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here.</translation>
 <translation id="2872961005593481000">Matikan</translation>
 <translation id="2942516765047364088">Posisi rak</translation>
 <translation id="2946640296642327832">Aktifkan Bluetooth</translation>
@@ -222,7 +222,7 @@
 <translation id="7957227661277029961"><ph name="DEVICE_TYPE" /> mungkin tidak diisi daya saat dinyalakan. Pertimbangkan untuk menggunakan pengisi daya resmi.</translation>
 <translation id="7982789257301363584">Jaringan</translation>
 <translation id="8054466585765276473">Menghitung masa pakai baterai.</translation>
-<translation id="8077816382010018681">Judul notifikasi Fitur QU ada di sini.</translation>
+<translation id="8077816382010018681">QU Feature notification title here</translation>
 <translation id="8103386449138765447">Pesan SMS: <ph name="MESSAGE_COUNT" /></translation>
 <translation id="8190698733819146287">Sesuaikan bahasa dan masukan...</translation>
 <translation id="8206859287963243715">Seluler</translation>
diff --git a/ash/common/strings/ash_strings_it.xtb b/ash/common/strings/ash_strings_it.xtb
index 1b385b0b..31d6919 100644
--- a/ash/common/strings/ash_strings_it.xtb
+++ b/ash/common/strings/ash_strings_it.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">Verrai disconnesso ora.</translation>
 <translation id="2825619548187458965">Shelf</translation>
 <translation id="2844169650293029770">Dispositivo USB-C (porta anteriore sinistra)</translation>
-<translation id="2857608528410806398">Inserisci qui il corpo della notifica della funzione Sblocco rapido. Inserisci qui il corpo della notifica della funzione Sblocco rapido. Inserisci qui il corpo della notifica della funzione Sblocco rapido. Inserisci qui il corpo della notifica della funzione Sblocco rapido. Inserisci qui il corpo della notifica della funzione Sblocco rapido.</translation>
+<translation id="2857608528410806398">Inserisci qui il corpo della notifica della funzione di sblocco rapido. Inserisci qui il corpo della notifica della funzione di sblocco rapido. Inserisci qui il corpo della notifica della funzione di sblocco rapido. Inserisci qui il corpo della notifica della funzione di sblocco rapido. Inserisci qui il corpo della notifica della funzione di sblocco rapido.</translation>
 <translation id="2872961005593481000">Spegni</translation>
 <translation id="2942516765047364088">Posizione shelf</translation>
 <translation id="2946640296642327832">Attiva Bluetooth</translation>
@@ -222,7 +222,7 @@
 <translation id="7957227661277029961">Il tuo dispositivo <ph name="DEVICE_TYPE" /> potrebbe non caricarsi mentre è acceso. Utilizza un caricabatterie originale.</translation>
 <translation id="7982789257301363584">Rete</translation>
 <translation id="8054466585765276473">Calcolo della durata della batteria.</translation>
-<translation id="8077816382010018681">Inserisci qui il titolo della notifica della funzione Sblocco rapido</translation>
+<translation id="8077816382010018681">Inserisci qui il titolo della notifica della funzione di sblocco rapido</translation>
 <translation id="8103386449138765447">Messaggi SMS: <ph name="MESSAGE_COUNT" /></translation>
 <translation id="8190698733819146287">Personalizza lingue e immissione...</translation>
 <translation id="8206859287963243715">Cellulare</translation>
diff --git a/ash/common/strings/ash_strings_ja.xtb b/ash/common/strings/ash_strings_ja.xtb
index 0273deb..fec1485 100644
--- a/ash/common/strings/ash_strings_ja.xtb
+++ b/ash/common/strings/ash_strings_ja.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">ログアウトします。</translation>
 <translation id="2825619548187458965">シェルフ</translation>
 <translation id="2844169650293029770">USB-C デバイス(左手前のポート)</translation>
-<translation id="2857608528410806398">ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。</translation>
+<translation id="2857608528410806398">ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。ロックのクイック解除機能の通知本文がここに表示されます。</translation>
 <translation id="2872961005593481000">終了</translation>
 <translation id="2942516765047364088">シェルフの位置</translation>
 <translation id="2946640296642327832">Bluetooth を有効にする</translation>
diff --git a/ash/common/strings/ash_strings_mr.xtb b/ash/common/strings/ash_strings_mr.xtb
index 6cd9b52..51a60da11b 100644
--- a/ash/common/strings/ash_strings_mr.xtb
+++ b/ash/common/strings/ash_strings_mr.xtb
@@ -65,7 +65,7 @@
 <translation id="2819276065543622893">आता आपल्याला साइन आउट केले जाईल.</translation>
 <translation id="2825619548187458965">शेल्फ</translation>
 <translation id="2844169650293029770">USB-C डिव्‍हाइस (डाव्‍या बाजूचे पुढील पोर्ट)</translation>
-<translation id="2857608528410806398">QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे आहे. QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे आहे. QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे आहे. QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे आहे.</translation>
+<translation id="2857608528410806398">QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे असेल. QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे असेल. QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे असेल. QU वैशिष्‍ट्य सूचनेेचा मुख्य भाग येथे असेल.</translation>
 <translation id="2872961005593481000">बंद करा</translation>
 <translation id="2942516765047364088">शेल्फ स्थिती</translation>
 <translation id="2946640296642327832">Bluetooth सक्षम करा</translation>
@@ -221,7 +221,7 @@
 <translation id="7957227661277029961">आपले <ph name="DEVICE_TYPE" /> चालू केलेले असते तेव्‍हा ते कदाचित चार्ज होणार नाही. अधिकृत चार्जर वापरून पहा.</translation>
 <translation id="7982789257301363584">नेटवर्क</translation>
 <translation id="8054466585765276473">बॅटरी वेळ गणना करत आहे.</translation>
-<translation id="8077816382010018681">QU वैशिष्‍ट्य सूचना शीर्षक येथे आहे</translation>
+<translation id="8077816382010018681">QU वैशिष्‍ट्य सूचना शीर्षक येथे असेल</translation>
 <translation id="8103386449138765447">SMS संदेश: <ph name="MESSAGE_COUNT" /></translation>
 <translation id="8190698733819146287">भाषा आणि इनपुट सानुकूलित करा...</translation>
 <translation id="8206859287963243715">सेल्यूलर</translation>
diff --git a/ash/common/system/tray/hover_highlight_view.cc b/ash/common/system/tray/hover_highlight_view.cc
index dfcc8a72..01173d9 100644
--- a/ash/common/system/tray/hover_highlight_view.cc
+++ b/ash/common/system/tray/hover_highlight_view.cc
@@ -52,7 +52,9 @@
   DCHECK(box_layout_);
   DCHECK(!right_icon_);
 
-  right_icon_ = new FixedSizedImageView(kTrayPopupDetailsIconWidth, 0);
+  right_icon_ = new views::ImageView();
+  right_icon_->SetImageSize(
+      gfx::Size(kTrayPopupDetailsIconWidth, kTrayPopupDetailsIconWidth));
   right_icon_->SetImage(image);
   right_icon_->SetEnabled(enabled());
   AddChildView(right_icon_);
diff --git a/ash/common/system/tray/tray_event_filter.cc b/ash/common/system/tray/tray_event_filter.cc
index 6d98214..3b277ccf 100644
--- a/ash/common/system/tray/tray_event_filter.cc
+++ b/ash/common/system/tray/tray_event_filter.cc
@@ -25,13 +25,13 @@
   bool was_empty = wrappers_.empty();
   wrappers_.insert(wrapper);
   if (was_empty && !wrappers_.empty())
-    WmShell::Get()->AddPointerDownWatcher(this);
+    WmShell::Get()->AddPointerWatcher(this);
 }
 
 void TrayEventFilter::RemoveWrapper(TrayBubbleWrapper* wrapper) {
   wrappers_.erase(wrapper);
   if (wrappers_.empty())
-    WmShell::Get()->RemovePointerDownWatcher(this);
+    WmShell::Get()->RemovePointerWatcher(this);
 }
 
 void TrayEventFilter::OnMousePressed(const ui::MouseEvent& event,
diff --git a/ash/common/system/tray/tray_event_filter.h b/ash/common/system/tray/tray_event_filter.h
index ac544a3..88a5ba80 100644
--- a/ash/common/system/tray/tray_event_filter.h
+++ b/ash/common/system/tray/tray_event_filter.h
@@ -8,7 +8,7 @@
 #include <set>
 
 #include "base/macros.h"
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 
 namespace gfx {
 class Point;
@@ -23,7 +23,7 @@
 
 // Handles events for a tray bubble, e.g. to close the system tray bubble when
 // the user clicks outside it.
-class TrayEventFilter : public views::PointerDownWatcher {
+class TrayEventFilter : public views::PointerWatcher {
  public:
   TrayEventFilter();
   ~TrayEventFilter() override;
@@ -31,7 +31,7 @@
   void AddWrapper(TrayBubbleWrapper* wrapper);
   void RemoveWrapper(TrayBubbleWrapper* wrapper);
 
-  // views::PointerDownWatcher:
+  // views::PointerWatcher:
   void OnMousePressed(const ui::MouseEvent& event,
                       const gfx::Point& location_in_screen,
                       views::Widget* target) override;
diff --git a/ash/common/wm_shell.cc b/ash/common/wm_shell.cc
index 35b8dfa..f0ed84e 100644
--- a/ash/common/wm_shell.cc
+++ b/ash/common/wm_shell.cc
@@ -10,6 +10,7 @@
 #include "ash/common/accessibility_delegate.h"
 #include "ash/common/focus_cycler.h"
 #include "ash/common/keyboard/keyboard_ui.h"
+#include "ash/common/shelf/app_list_shelf_item_delegate.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shell_delegate.h"
 #include "ash/common/shell_window_ids.h"
@@ -55,11 +56,17 @@
   accessibility_delegate_.reset(delegate_->CreateAccessibilityDelegate());
   media_delegate_.reset(delegate_->CreateMediaDelegate());
   toast_manager_.reset(new ToastManager);
+
+  // Create the app list item in the shelf data model.
+  AppListShelfItemDelegate::CreateAppListItemAndDelegate(shelf_model_.get());
 }
 
 void WmShell::Shutdown() {
   // Accesses WmShell in its destructor.
   accessibility_delegate_.reset();
+  // ShelfItemDelegate subclasses it owns have complex cleanup to run (e.g. ARC
+  // shelf items in Chrome) so explicitly shutdown early.
+  shelf_model_->DestroyItemDelegates();
 }
 
 void WmShell::OnMaximizeModeStarted() {
@@ -104,14 +111,14 @@
 WmShell::WmShell(std::unique_ptr<ShellDelegate> shell_delegate)
     : delegate_(std::move(shell_delegate)),
       focus_cycler_(new FocusCycler),
-      shelf_model_(new ShelfModel),
+      shelf_model_(new ShelfModel),  // Must create before ShelfDelegate.
       system_tray_notifier_(new SystemTrayNotifier),
+      window_cycle_controller_(new WindowCycleController),
       window_selector_controller_(new WindowSelectorController) {
 #if defined(OS_CHROMEOS)
   brightness_control_delegate_.reset(new system::BrightnessControllerChromeos);
   keyboard_brightness_control_delegate_.reset(new KeyboardBrightnessController);
 #endif
-  window_cycle_controller_.reset(new WindowCycleController());
 }
 
 WmShell::~WmShell() {}
diff --git a/ash/common/wm_shell.h b/ash/common/wm_shell.h
index 2801611..ec0b094 100644
--- a/ash/common/wm_shell.h
+++ b/ash/common/wm_shell.h
@@ -17,7 +17,7 @@
 #include "base/observer_list.h"
 
 namespace views {
-class PointerDownWatcher;
+class PointerWatcher;
 }
 
 namespace ash {
@@ -250,8 +250,8 @@
   void AddShellObserver(ShellObserver* observer);
   void RemoveShellObserver(ShellObserver* observer);
 
-  virtual void AddPointerDownWatcher(views::PointerDownWatcher* watcher) = 0;
-  virtual void RemovePointerDownWatcher(views::PointerDownWatcher* watcher) = 0;
+  virtual void AddPointerWatcher(views::PointerWatcher* watcher) = 0;
+  virtual void RemovePointerWatcher(views::PointerWatcher* watcher) = 0;
 
   // TODO: Move these back to LockStateController when that has been moved.
   void OnLockStateEvent(LockStateObserver::EventType event);
diff --git a/ash/common/wm_window.h b/ash/common/wm_window.h
index 3bfb302a..d371cae 100644
--- a/ash/common/wm_window.h
+++ b/ash/common/wm_window.h
@@ -126,7 +126,11 @@
   }
   virtual const wm::WindowState* GetWindowState() const = 0;
 
+  // The implementation of this matches aura::Window::GetToplevelWindow().
   virtual WmWindow* GetToplevelWindow() = 0;
+  // The implementation of this matches
+  // aura::client::ActivationClient::GetToplevelWindow().
+  virtual WmWindow* GetToplevelWindowForFocus() = 0;
 
   // See aura::client::ParentWindowWithContext() for details of what this does.
   virtual void SetParentUsingContext(WmWindow* context,
diff --git a/ash/mus/BUILD.gn b/ash/mus/BUILD.gn
index 43a73388..f49dd22 100644
--- a/ash/mus/BUILD.gn
+++ b/ash/mus/BUILD.gn
@@ -10,10 +10,12 @@
 
 source_set("lib") {
   sources = [
-    "accelerator_registrar_impl.cc",
-    "accelerator_registrar_impl.h",
     "accelerators/accelerator_controller_delegate_mus.cc",
     "accelerators/accelerator_controller_delegate_mus.h",
+    "accelerators/accelerator_handler.h",
+    "accelerators/accelerator_ids.h",
+    "accelerators/accelerator_registrar_impl.cc",
+    "accelerators/accelerator_registrar_impl.h",
     "accessibility_delegate_mus.cc",
     "accessibility_delegate_mus.h",
     "bridge/mus_layout_manager_adapter.cc",
@@ -177,7 +179,7 @@
   testonly = true
 
   sources = [
-    "accelerator_registrar_unittest.cc",
+    "accelerators/accelerator_registrar_unittest.cc",
     "app_launch_unittest.cc",
     "layout_manager_unittest.cc",
     "root_window_controller_unittest.cc",
diff --git a/ash/mus/accelerators/accelerator_handler.h b/ash/mus/accelerators/accelerator_handler.h
new file mode 100644
index 0000000..87e50a0
--- /dev/null
+++ b/ash/mus/accelerators/accelerator_handler.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_MUS_ACCELERATORS_ACCELERATOR_HANDLER_H_
+#define ASH_MUS_ACCELERATORS_ACCELERATOR_HANDLER_H_
+
+#include "services/ui/public/interfaces/window_manager.mojom.h"
+
+namespace ash {
+namespace mus {
+
+// Used by WindowManager for handling accelerators.
+class AcceleratorHandler {
+ public:
+  virtual ui::mojom::EventResult OnAccelerator(uint32_t id,
+                                               const ui::Event& event) = 0;
+
+ protected:
+  virtual ~AcceleratorHandler() {}
+};
+
+}  // namespace mus
+}  // namespace ash
+
+#endif  // ASH_MUS_ACCELERATORS_ACCELERATOR_HANDLER_H_
diff --git a/ash/mus/accelerators/accelerator_ids.h b/ash/mus/accelerators/accelerator_ids.h
new file mode 100644
index 0000000..7d9465a5
--- /dev/null
+++ b/ash/mus/accelerators/accelerator_ids.h
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_MUS_ACCELERATORS_ACCELERATOR_IDS_H_
+#define ASH_MUS_ACCELERATORS_ACCELERATOR_IDS_H_
+
+namespace ash {
+namespace mus {
+
+// Accelerator ids consist of two parts:
+// . Upper 16 bits identifies source (namespace part).
+// . Lower 16 supplied from client (local part).
+constexpr uint16_t kLocalIdMask = 0xFFFF;
+
+inline uint32_t ComputeAcceleratorId(uint16_t accelerator_namespace,
+                                     uint16_t local_id) {
+  return (accelerator_namespace << 16) | local_id;
+}
+
+inline uint16_t GetAcceleratorLocalId(uint32_t accelerator_id) {
+  return static_cast<uint16_t>(accelerator_id & kLocalIdMask);
+}
+
+inline uint16_t GetAcceleratorNamespaceId(uint32_t accelerator_id) {
+  return static_cast<uint16_t>((accelerator_id >> 16) & kLocalIdMask);
+}
+
+}  // namespace mus
+}  // namespace ash
+
+#endif  // ASH_MUS_ACCELERATORS_ACCELERATOR_IDS_H_
diff --git a/ash/mus/accelerator_registrar_impl.cc b/ash/mus/accelerators/accelerator_registrar_impl.cc
similarity index 80%
rename from ash/mus/accelerator_registrar_impl.cc
rename to ash/mus/accelerators/accelerator_registrar_impl.cc
index 1def720..f43d1c65 100644
--- a/ash/mus/accelerator_registrar_impl.cc
+++ b/ash/mus/accelerators/accelerator_registrar_impl.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/mus/accelerator_registrar_impl.h"
+#include "ash/mus/accelerators/accelerator_registrar_impl.h"
 
 #include <stdint.h>
 #include <utility>
 
+#include "ash/mus/accelerators/accelerator_ids.h"
 #include "ash/mus/root_window_controller.h"
 #include "ash/mus/window_manager.h"
 #include "base/bind.h"
@@ -16,7 +17,6 @@
 namespace mus {
 
 namespace {
-const int kAcceleratorIdMask = 0xffff;
 
 void CallAddAcceleratorCallback(
     const ::ui::mojom::AcceleratorRegistrar::AddAcceleratorCallback& callback,
@@ -28,14 +28,15 @@
 
 AcceleratorRegistrarImpl::AcceleratorRegistrarImpl(
     WindowManager* window_manager,
-    uint32_t accelerator_namespace,
+    uint16_t accelerator_namespace,
     mojo::InterfaceRequest<AcceleratorRegistrar> request,
     const DestroyCallback& destroy_callback)
     : window_manager_(window_manager),
       binding_(this, std::move(request)),
-      accelerator_namespace_(accelerator_namespace & 0xffff),
+      accelerator_namespace_(accelerator_namespace),
       destroy_callback_(destroy_callback) {
   window_manager_->AddObserver(this);
+  window_manager_->AddAcceleratorHandler(accelerator_namespace_, this);
   binding_.set_connection_error_handler(base::Bind(
       &AcceleratorRegistrarImpl::OnBindingGone, base::Unretained(this)));
 }
@@ -53,21 +54,17 @@
   DCHECK(OwnsAccelerator(accelerator_id));
   // TODO(moshayedi): crbug.com/617167. Don't clone even once we map
   // mojom::Event directly to ui::Event.
-  accelerator_handler_->OnAccelerator(accelerator_id & kAcceleratorIdMask,
+  accelerator_handler_->OnAccelerator(accelerator_id & kLocalIdMask,
                                       ui::Event::Clone(event));
 }
 
 AcceleratorRegistrarImpl::~AcceleratorRegistrarImpl() {
+  window_manager_->RemoveAcceleratorHandler(accelerator_namespace_);
   window_manager_->RemoveObserver(this);
   RemoveAllAccelerators();
   destroy_callback_.Run(this);
 }
 
-uint32_t AcceleratorRegistrarImpl::ComputeAcceleratorId(
-    uint32_t accelerator_id) const {
-  return (accelerator_namespace_ << 16) | (accelerator_id & kAcceleratorIdMask);
-}
-
 void AcceleratorRegistrarImpl::OnBindingGone() {
   binding_.Unbind();
   // If there's no outstanding accelerators for this connection, then destroy
@@ -107,13 +104,14 @@
     uint32_t accelerator_id,
     ::ui::mojom::EventMatcherPtr matcher,
     const AddAcceleratorCallback& callback) {
-  if (!accelerator_handler_ ||
-      (accelerator_id & kAcceleratorIdMask) != accelerator_id) {
+  if (!accelerator_handler_ || accelerator_id > 0xFFFF) {
     // The |accelerator_id| is too large, and it can't be handled correctly.
     callback.Run(false);
+    DVLOG(1) << "AddAccelerator failed because of bogus id";
     return;
   }
-  uint32_t namespaced_accelerator_id = ComputeAcceleratorId(accelerator_id);
+  uint32_t namespaced_accelerator_id = ComputeAcceleratorId(
+      accelerator_namespace_, static_cast<uint16_t>(accelerator_id));
   accelerators_.insert(namespaced_accelerator_id);
   window_manager_->window_manager_client()->AddAccelerator(
       namespaced_accelerator_id, std::move(matcher),
@@ -121,7 +119,11 @@
 }
 
 void AcceleratorRegistrarImpl::RemoveAccelerator(uint32_t accelerator_id) {
-  uint32_t namespaced_accelerator_id = ComputeAcceleratorId(accelerator_id);
+  if (accelerator_id > 0xFFFF)
+    return;
+
+  uint32_t namespaced_accelerator_id = ComputeAcceleratorId(
+      accelerator_namespace_, static_cast<uint16_t>(accelerator_id));
   if (accelerators_.erase(namespaced_accelerator_id) == 0)
     return;
   window_manager_->window_manager_client()->RemoveAccelerator(
@@ -134,10 +136,12 @@
     delete this;
 }
 
-void AcceleratorRegistrarImpl::OnAccelerator(uint32_t id,
-                                             const ui::Event& event) {
+ui::mojom::EventResult AcceleratorRegistrarImpl::OnAccelerator(
+    uint32_t id,
+    const ui::Event& event) {
   if (OwnsAccelerator(id))
     ProcessAccelerator(id, event);
+  return ui::mojom::EventResult::HANDLED;
 }
 
 void AcceleratorRegistrarImpl::OnWindowTreeClientDestroyed() {
diff --git a/ash/mus/accelerator_registrar_impl.h b/ash/mus/accelerators/accelerator_registrar_impl.h
similarity index 78%
rename from ash/mus/accelerator_registrar_impl.h
rename to ash/mus/accelerators/accelerator_registrar_impl.h
index bc8f5a7..39940ee 100644
--- a/ash/mus/accelerator_registrar_impl.h
+++ b/ash/mus/accelerators/accelerator_registrar_impl.h
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_MUS_ACCELERATOR_REGISTRAR_IMPL_H_
-#define ASH_MUS_ACCELERATOR_REGISTRAR_IMPL_H_
+#ifndef ASH_MUS_ACCELERATORS_ACCELERATOR_REGISTRAR_IMPL_H_
+#define ASH_MUS_ACCELERATORS_ACCELERATOR_REGISTRAR_IMPL_H_
 
 #include <stdint.h>
 
 #include <map>
 
+#include "ash/mus/accelerators/accelerator_handler.h"
 #include "ash/mus/window_manager_observer.h"
 #include "base/callback.h"
 #include "base/macros.h"
@@ -26,11 +27,12 @@
 // AcceleratorRegistrar and all its AcceleratorHandlers are disconnected. Upon
 // destruction, it calls the DestroyCallback.
 class AcceleratorRegistrarImpl : public ::ui::mojom::AcceleratorRegistrar,
-                                 public WindowManagerObserver {
+                                 public WindowManagerObserver,
+                                 public AcceleratorHandler {
  public:
   using DestroyCallback = base::Callback<void(AcceleratorRegistrarImpl*)>;
   AcceleratorRegistrarImpl(WindowManager* window_manager,
-                           uint32_t accelerator_namespace,
+                           uint16_t accelerator_namespace,
                            mojo::InterfaceRequest<AcceleratorRegistrar> request,
                            const DestroyCallback& destroy_callback);
 
@@ -45,7 +47,6 @@
  private:
   ~AcceleratorRegistrarImpl() override;
 
-  uint32_t ComputeAcceleratorId(uint32_t accelerator_id) const;
   void OnBindingGone();
   void OnHandlerGone();
 
@@ -58,14 +59,17 @@
                       const AddAcceleratorCallback& callback) override;
   void RemoveAccelerator(uint32_t accelerator_id) override;
 
+  // AcceleratorHandler:
+  ui::mojom::EventResult OnAccelerator(uint32_t id,
+                                       const ui::Event& event) override;
+
   // WindowManagerObserver:
-  void OnAccelerator(uint32_t id, const ui::Event& event) override;
   void OnWindowTreeClientDestroyed() override;
 
   WindowManager* window_manager_;
   ::ui::mojom::AcceleratorHandlerPtr accelerator_handler_;
   mojo::Binding<AcceleratorRegistrar> binding_;
-  uint32_t accelerator_namespace_;
+  uint16_t accelerator_namespace_;
   std::set<uint32_t> accelerators_;
   DestroyCallback destroy_callback_;
 
@@ -75,4 +79,4 @@
 }  // namespace mus
 }  // namespace ash
 
-#endif  // ASH_MUS_ACCELERATOR_REGISTRAR_IMPL_H_
+#endif  // ASH_MUS_ACCELERATORS_ACCELERATOR_REGISTRAR_IMPL_H_
diff --git a/ash/mus/accelerator_registrar_unittest.cc b/ash/mus/accelerators/accelerator_registrar_unittest.cc
similarity index 100%
rename from ash/mus/accelerator_registrar_unittest.cc
rename to ash/mus/accelerators/accelerator_registrar_unittest.cc
diff --git a/ash/mus/bridge/wm_shell_mus.cc b/ash/mus/bridge/wm_shell_mus.cc
index 195250df..f6aacd9 100644
--- a/ash/mus/bridge/wm_shell_mus.cc
+++ b/ash/mus/bridge/wm_shell_mus.cc
@@ -313,13 +313,12 @@
   NOTIMPLEMENTED();
 }
 
-void WmShellMus::AddPointerDownWatcher(views::PointerDownWatcher* watcher) {
-  // TODO(jamescook): Move PointerDownWatcherDelegateMus to //ash/mus
-  // and use here.
+void WmShellMus::AddPointerWatcher(views::PointerWatcher* watcher) {
+  // TODO(jamescook): Move PointerWatcherDelegateMus to //ash/mus and use here.
   NOTIMPLEMENTED();
 }
 
-void WmShellMus::RemovePointerDownWatcher(views::PointerDownWatcher* watcher) {
+void WmShellMus::RemovePointerWatcher(views::PointerWatcher* watcher) {
   NOTIMPLEMENTED();
 }
 
diff --git a/ash/mus/bridge/wm_shell_mus.h b/ash/mus/bridge/wm_shell_mus.h
index 938a1d5c..6a9f1b5 100644
--- a/ash/mus/bridge/wm_shell_mus.h
+++ b/ash/mus/bridge/wm_shell_mus.h
@@ -82,8 +82,8 @@
   void RemoveActivationObserver(WmActivationObserver* observer) override;
   void AddDisplayObserver(WmDisplayObserver* observer) override;
   void RemoveDisplayObserver(WmDisplayObserver* observer) override;
-  void AddPointerDownWatcher(views::PointerDownWatcher* watcher) override;
-  void RemovePointerDownWatcher(views::PointerDownWatcher* watcher) override;
+  void AddPointerWatcher(views::PointerWatcher* watcher) override;
+  void RemovePointerWatcher(views::PointerWatcher* watcher) override;
 #if defined(OS_CHROMEOS)
   void ToggleIgnoreExternalKeyboard() override;
 #endif
diff --git a/ash/mus/bridge/wm_window_mus.cc b/ash/mus/bridge/wm_window_mus.cc
index f52b9d9..c635a13f 100644
--- a/ash/mus/bridge/wm_window_mus.cc
+++ b/ash/mus/bridge/wm_window_mus.cc
@@ -352,6 +352,12 @@
   return WmShellMus::GetToplevelAncestor(window_);
 }
 
+WmWindow* WmWindowMus::GetToplevelWindowForFocus() {
+  // TODO(sky): resolve if we really need two notions of top-level. In the mus
+  // world they are the same.
+  return WmShellMus::GetToplevelAncestor(window_);
+}
+
 void WmWindowMus::SetParentUsingContext(WmWindow* context,
                                         const gfx::Rect& screen_bounds) {
   wm::GetDefaultParent(context, this, screen_bounds)->AddChild(this);
diff --git a/ash/mus/bridge/wm_window_mus.h b/ash/mus/bridge/wm_window_mus.h
index ec246c6..bbd26cb 100644
--- a/ash/mus/bridge/wm_window_mus.h
+++ b/ash/mus/bridge/wm_window_mus.h
@@ -134,6 +134,7 @@
   int GetIntProperty(WmWindowProperty key) override;
   const wm::WindowState* GetWindowState() const override;
   WmWindow* GetToplevelWindow() override;
+  WmWindow* GetToplevelWindowForFocus() override;
   void SetParentUsingContext(WmWindow* context,
                              const gfx::Rect& screen_bounds) override;
   void AddChild(WmWindow* window) override;
diff --git a/ash/mus/shell_delegate_mus.cc b/ash/mus/shell_delegate_mus.cc
index a6a4b36..301f6157 100644
--- a/ash/mus/shell_delegate_mus.cc
+++ b/ash/mus/shell_delegate_mus.cc
@@ -8,7 +8,7 @@
 
 #include "ash/common/gpu_support_stub.h"
 #include "ash/common/media_delegate.h"
-#include "ash/common/pointer_down_watcher_delegate.h"
+#include "ash/common/pointer_watcher_delegate.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/system/tray/default_system_tray_delegate.h"
 #include "ash/mus/accessibility_delegate_mus.h"
@@ -196,8 +196,8 @@
   return new MediaDelegateStub;
 }
 
-std::unique_ptr<PointerDownWatcherDelegate>
-ShellDelegateMus::CreatePointerDownWatcherDelegate() {
+std::unique_ptr<PointerWatcherDelegate>
+ShellDelegateMus::CreatePointerWatcherDelegate() {
   NOTIMPLEMENTED();
   return nullptr;
 }
diff --git a/ash/mus/shell_delegate_mus.h b/ash/mus/shell_delegate_mus.h
index df46db9..aa1c8d0f 100644
--- a/ash/mus/shell_delegate_mus.h
+++ b/ash/mus/shell_delegate_mus.h
@@ -46,7 +46,7 @@
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
   NewWindowDelegate* CreateNewWindowDelegate() override;
   MediaDelegate* CreateMediaDelegate() override;
-  std::unique_ptr<PointerDownWatcherDelegate> CreatePointerDownWatcherDelegate()
+  std::unique_ptr<PointerWatcherDelegate> CreatePointerWatcherDelegate()
       override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc
index 3ab6ea5..b9640f6 100644
--- a/ash/mus/window_manager.cc
+++ b/ash/mus/window_manager.cc
@@ -9,6 +9,8 @@
 #include <utility>
 
 #include "ash/common/shell_window_ids.h"
+#include "ash/mus/accelerators/accelerator_handler.h"
+#include "ash/mus/accelerators/accelerator_ids.h"
 #include "ash/mus/bridge/wm_lookup_mus.h"
 #include "ash/mus/bridge/wm_shell_mus.h"
 #include "ash/mus/bridge/wm_window_mus.h"
@@ -36,8 +38,6 @@
 namespace ash {
 namespace mus {
 
-const uint32_t kWindowSwitchAccelerator = 1;
-
 void AssertTrue(bool success) {
   DCHECK(success);
 }
@@ -79,8 +79,6 @@
 
   shadow_controller_.reset(new ShadowController(window_tree_client));
 
-  AddAccelerators();
-
   // The insets are roughly what is needed by CustomFrameView. The expectation
   // is at some point we'll write our own NonClientFrameView and get the insets
   // from it.
@@ -127,6 +125,26 @@
   return result;
 }
 
+bool WindowManager::GetNextAcceleratorNamespaceId(uint16_t* id) {
+  if (accelerator_handlers_.size() == std::numeric_limits<uint16_t>::max())
+    return false;
+  while (accelerator_handlers_.count(next_accelerator_namespace_id_) > 0)
+    ++next_accelerator_namespace_id_;
+  *id = next_accelerator_namespace_id_;
+  ++next_accelerator_namespace_id_;
+  return true;
+}
+
+void WindowManager::AddAcceleratorHandler(uint16_t id_namespace,
+                                          AcceleratorHandler* handler) {
+  DCHECK_EQ(0u, accelerator_handlers_.count(id_namespace));
+  accelerator_handlers_[id_namespace] = handler;
+}
+
+void WindowManager::RemoveAcceleratorHandler(uint16_t id_namespace) {
+  accelerator_handlers_.erase(id_namespace);
+}
+
 void WindowManager::AddObserver(WindowManagerObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -135,16 +153,6 @@
   observers_.RemoveObserver(observer);
 }
 
-void WindowManager::AddAccelerators() {
-  // TODO(sky): this is broke for multi-display case. Need to fix mus to
-  // deal correctly.
-  window_manager_client_->AddAccelerator(
-      kWindowSwitchAccelerator,
-      ::ui::CreateKeyMatcher(ui::mojom::KeyboardCode::TAB,
-                             ui::mojom::kEventFlagControlDown),
-      base::Bind(&AssertTrue));
-}
-
 RootWindowController* WindowManager::CreateRootWindowController(
     ::ui::Window* window,
     const display::Display& display) {
@@ -288,17 +296,11 @@
 
 ui::mojom::EventResult WindowManager::OnAccelerator(uint32_t id,
                                                     const ui::Event& event) {
-  switch (id) {
-    case kWindowSwitchAccelerator:
-      window_manager_client()->ActivateNextWindow();
-      break;
-    default:
-      FOR_EACH_OBSERVER(WindowManagerObserver, observers_,
-                        OnAccelerator(id, event));
-      break;
-  }
+  auto iter = accelerator_handlers_.find(GetAcceleratorNamespaceId(id));
+  if (iter == accelerator_handlers_.end())
+    return ui::mojom::EventResult::HANDLED;
 
-  return ui::mojom::EventResult::HANDLED;
+  return iter->second->OnAccelerator(id, event);
 }
 
 }  // namespace mus
diff --git a/ash/mus/window_manager.h b/ash/mus/window_manager.h
index 515f4f9..98730e1 100644
--- a/ash/mus/window_manager.h
+++ b/ash/mus/window_manager.h
@@ -30,6 +30,7 @@
 namespace ash {
 namespace mus {
 
+class AcceleratorHandler;
 class RootWindowController;
 class ShadowController;
 class WindowManagerObserver;
@@ -68,14 +69,19 @@
 
   std::set<RootWindowController*> GetRootWindowControllers();
 
+  // Returns the next accelerator namespace id by value in |id|. Returns true
+  // if there is another slot available, false if all slots are taken up.
+  bool GetNextAcceleratorNamespaceId(uint16_t* id);
+  void AddAcceleratorHandler(uint16_t id_namespace,
+                             AcceleratorHandler* handler);
+  void RemoveAcceleratorHandler(uint16_t id_namespace);
+
   void AddObserver(WindowManagerObserver* observer);
   void RemoveObserver(WindowManagerObserver* observer);
 
  private:
   friend class WmTestHelper;
 
-  void AddAccelerators();
-
   RootWindowController* CreateRootWindowController(
       ::ui::Window* window,
       const display::Display& display);
@@ -128,6 +134,9 @@
 
   std::unique_ptr<WmLookupMus> lookup_;
 
+  std::map<uint16_t, AcceleratorHandler*> accelerator_handlers_;
+  uint16_t next_accelerator_namespace_id_ = 0u;
+
   DISALLOW_COPY_AND_ASSIGN(WindowManager);
 };
 
diff --git a/ash/mus/window_manager_application.cc b/ash/mus/window_manager_application.cc
index 00ddb0f..d1e83166 100644
--- a/ash/mus/window_manager_application.cc
+++ b/ash/mus/window_manager_application.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "ash/common/material_design/material_design_controller.h"
-#include "ash/mus/accelerator_registrar_impl.h"
+#include "ash/mus/accelerators/accelerator_registrar_impl.h"
 #include "ash/mus/root_window_controller.h"
 #include "ash/mus/shelf_layout_impl.h"
 #include "ash/mus/user_window_controller_impl.h"
@@ -154,17 +154,15 @@
   if (!window_manager_->window_manager_client())
     return;  // Can happen during shutdown.
 
-  static int accelerator_registrar_count = 0;
-  if (accelerator_registrar_count == std::numeric_limits<int>::max()) {
-    // Restart from zero if we have reached the limit. It is technically
-    // possible to end up with multiple active registrars with the same
-    // namespace, but it is highly unlikely. In the event that multiple
-    // registrars have the same namespace, this new registrar will be unable to
-    // install accelerators.
-    accelerator_registrar_count = 0;
+  uint16_t accelerator_namespace_id;
+  if (!window_manager_->GetNextAcceleratorNamespaceId(
+          &accelerator_namespace_id)) {
+    DVLOG(1) << "Max number of accelerators registered, ignoring request.";
+    // All ids are used. Normally shouldn't happen, so we close the connection.
+    return;
   }
   accelerator_registrars_.insert(new AcceleratorRegistrarImpl(
-      window_manager_.get(), ++accelerator_registrar_count, std::move(request),
+      window_manager_.get(), accelerator_namespace_id, std::move(request),
       base::Bind(&WindowManagerApplication::OnAcceleratorRegistrarDestroyed,
                  base::Unretained(this))));
 }
diff --git a/ash/mus/window_manager_observer.h b/ash/mus/window_manager_observer.h
index 0fa0982aa..e5c5070 100644
--- a/ash/mus/window_manager_observer.h
+++ b/ash/mus/window_manager_observer.h
@@ -5,12 +5,6 @@
 #ifndef ASH_MUS_WINDOW_OBSERVER_H_
 #define ASH_MUS_WINDOW_OBSERVER_H_
 
-#include <stdint.h>
-
-namespace ui {
-class Event;
-}
-
 namespace ash {
 namespace mus {
 
@@ -22,8 +16,6 @@
   // about to be destroyed.
   virtual void OnWindowTreeClientDestroyed() {}
 
-  virtual void OnAccelerator(uint32_t id, const ui::Event& event) {}
-
   virtual void OnRootWindowControllerAdded(RootWindowController* controller) {}
   virtual void OnWillDestroyRootWindowController(
       RootWindowController* controller) {}
diff --git a/ash/pointer_down_watcher_delegate_aura.h b/ash/pointer_down_watcher_delegate_aura.h
deleted file mode 100644
index 4b21a9b7..0000000
--- a/ash/pointer_down_watcher_delegate_aura.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/ash_export.h"
-#include "ash/common/pointer_down_watcher_delegate.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "ui/events/event_handler.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace ui {
-class LocatedEvent;
-}
-
-namespace views {
-class Widget;
-}
-
-namespace ash {
-
-// Support for PointerDownWatchers in non-mus ash, implemented with a pre-target
-// EventHandler on the Shell.
-class ASH_EXPORT PointerDownWatcherDelegateAura
-    : public PointerDownWatcherDelegate,
-      public ui::EventHandler {
- public:
-  PointerDownWatcherDelegateAura();
-  ~PointerDownWatcherDelegateAura() override;
-
-  // PointerDownWatcherDelegate:
-  void AddPointerDownWatcher(views::PointerDownWatcher* watcher) override;
-  void RemovePointerDownWatcher(views::PointerDownWatcher* watcher) override;
-
-  // ui::EventHandler:
-  void OnMouseEvent(ui::MouseEvent* event) override;
-  void OnTouchEvent(ui::TouchEvent* event) override;
-
- private:
-  gfx::Point GetLocationInScreen(const ui::LocatedEvent& event) const;
-  views::Widget* GetTargetWidget(const ui::LocatedEvent& event) const;
-
-  // Must be empty on destruction.
-  base::ObserverList<views::PointerDownWatcher, true> pointer_down_watchers_;
-
-  DISALLOW_COPY_AND_ASSIGN(PointerDownWatcherDelegateAura);
-};
-
-}  // namespace ash
diff --git a/ash/pointer_down_watcher_delegate_aura.cc b/ash/pointer_watcher_delegate_aura.cc
similarity index 60%
rename from ash/pointer_down_watcher_delegate_aura.cc
rename to ash/pointer_watcher_delegate_aura.cc
index 58c23d8..d70720d5 100644
--- a/ash/pointer_down_watcher_delegate_aura.cc
+++ b/ash/pointer_watcher_delegate_aura.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 "ash/pointer_down_watcher_delegate_aura.h"
+#include "ash/pointer_watcher_delegate_aura.h"
 
 #include "ash/shell.h"
 #include "ui/aura/client/screen_position_client.h"
@@ -10,44 +10,44 @@
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 #include "ui/views/widget/widget.h"
 
 namespace ash {
 
-PointerDownWatcherDelegateAura::PointerDownWatcherDelegateAura() {
+PointerWatcherDelegateAura::PointerWatcherDelegateAura() {
   Shell::GetInstance()->AddPreTargetHandler(this);
 }
 
-PointerDownWatcherDelegateAura::~PointerDownWatcherDelegateAura() {
+PointerWatcherDelegateAura::~PointerWatcherDelegateAura() {
   Shell::GetInstance()->RemovePreTargetHandler(this);
 }
 
-void PointerDownWatcherDelegateAura::AddPointerDownWatcher(
-    views::PointerDownWatcher* watcher) {
-  pointer_down_watchers_.AddObserver(watcher);
+void PointerWatcherDelegateAura::AddPointerWatcher(
+    views::PointerWatcher* watcher) {
+  pointer_watchers_.AddObserver(watcher);
 }
 
-void PointerDownWatcherDelegateAura::RemovePointerDownWatcher(
-    views::PointerDownWatcher* watcher) {
-  pointer_down_watchers_.RemoveObserver(watcher);
+void PointerWatcherDelegateAura::RemovePointerWatcher(
+    views::PointerWatcher* watcher) {
+  pointer_watchers_.RemoveObserver(watcher);
 }
 
-void PointerDownWatcherDelegateAura::OnMouseEvent(ui::MouseEvent* event) {
+void PointerWatcherDelegateAura::OnMouseEvent(ui::MouseEvent* event) {
   if (event->type() == ui::ET_MOUSE_PRESSED)
-    FOR_EACH_OBSERVER(views::PointerDownWatcher, pointer_down_watchers_,
+    FOR_EACH_OBSERVER(views::PointerWatcher, pointer_watchers_,
                       OnMousePressed(*event, GetLocationInScreen(*event),
                                      GetTargetWidget(*event)));
 }
 
-void PointerDownWatcherDelegateAura::OnTouchEvent(ui::TouchEvent* event) {
+void PointerWatcherDelegateAura::OnTouchEvent(ui::TouchEvent* event) {
   if (event->type() == ui::ET_TOUCH_PRESSED)
-    FOR_EACH_OBSERVER(views::PointerDownWatcher, pointer_down_watchers_,
+    FOR_EACH_OBSERVER(views::PointerWatcher, pointer_watchers_,
                       OnTouchPressed(*event, GetLocationInScreen(*event),
                                      GetTargetWidget(*event)));
 }
 
-gfx::Point PointerDownWatcherDelegateAura::GetLocationInScreen(
+gfx::Point PointerWatcherDelegateAura::GetLocationInScreen(
     const ui::LocatedEvent& event) const {
   aura::Window* target = static_cast<aura::Window*>(event.target());
   gfx::Point location_in_screen = event.location();
@@ -56,7 +56,7 @@
   return location_in_screen;
 }
 
-views::Widget* PointerDownWatcherDelegateAura::GetTargetWidget(
+views::Widget* PointerWatcherDelegateAura::GetTargetWidget(
     const ui::LocatedEvent& event) const {
   aura::Window* window = static_cast<aura::Window*>(event.target());
   return views::Widget::GetTopLevelWidgetForNativeView(window);
diff --git a/ash/pointer_watcher_delegate_aura.h b/ash/pointer_watcher_delegate_aura.h
new file mode 100644
index 0000000..1bea01d
--- /dev/null
+++ b/ash/pointer_watcher_delegate_aura.h
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/ash_export.h"
+#include "ash/common/pointer_watcher_delegate.h"
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "ui/events/event_handler.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace ui {
+class LocatedEvent;
+}
+
+namespace views {
+class Widget;
+}
+
+namespace ash {
+
+// Support for PointerWatchers in non-mus ash, implemented with a pre-target
+// EventHandler on the Shell.
+class ASH_EXPORT PointerWatcherDelegateAura : public PointerWatcherDelegate,
+                                              public ui::EventHandler {
+ public:
+  PointerWatcherDelegateAura();
+  ~PointerWatcherDelegateAura() override;
+
+  // PointerWatcherDelegate:
+  void AddPointerWatcher(views::PointerWatcher* watcher) override;
+  void RemovePointerWatcher(views::PointerWatcher* watcher) override;
+
+  // ui::EventHandler:
+  void OnMouseEvent(ui::MouseEvent* event) override;
+  void OnTouchEvent(ui::TouchEvent* event) override;
+
+ private:
+  gfx::Point GetLocationInScreen(const ui::LocatedEvent& event) const;
+  views::Widget* GetTargetWidget(const ui::LocatedEvent& event) const;
+
+  // Must be empty on destruction.
+  base::ObserverList<views::PointerWatcher, true> pointer_watchers_;
+
+  DISALLOW_COPY_AND_ASSIGN(PointerWatcherDelegateAura);
+};
+
+}  // namespace ash
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index 2821059..2030432 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -9,7 +9,6 @@
 
 #include "ash/aura/wm_window_aura.h"
 #include "ash/common/shelf/shelf_item_delegate.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shelf/shelf_navigator.h"
 #include "ash/common/shelf/wm_shelf_util.h"
@@ -139,8 +138,7 @@
 
   const ShelfItem& item = shelf_view_->model()->items()[index];
   ShelfItemDelegate* item_delegate =
-      Shell::GetInstance()->shelf_item_delegate_manager()->GetShelfItemDelegate(
-          item.id);
+      shelf_view_->model()->GetShelfItemDelegate(item.id);
   item_delegate->ItemSelected(event);
 }
 
diff --git a/ash/shelf/shelf_tooltip_manager.cc b/ash/shelf/shelf_tooltip_manager.cc
index b977475..35a83a2 100644
--- a/ash/shelf/shelf_tooltip_manager.cc
+++ b/ash/shelf/shelf_tooltip_manager.cc
@@ -103,7 +103,7 @@
 ShelfTooltipManager::~ShelfTooltipManager() {
   WillDeleteShelfLayoutManager();
 
-  Shell::GetInstance()->RemovePointerDownWatcher(this);
+  Shell::GetInstance()->RemovePointerWatcher(this);
 
   if (root_window_) {
     root_window_->RemoveObserver(this);
@@ -120,7 +120,7 @@
   root_window_->AddPreTargetHandler(this);
   root_window_->AddObserver(this);
 
-  Shell::GetInstance()->AddPointerDownWatcher(this);
+  Shell::GetInstance()->AddPointerWatcher(this);
 }
 
 void ShelfTooltipManager::Close() {
@@ -188,7 +188,7 @@
 }
 
 void ShelfTooltipManager::OnEvent(ui::Event* event) {
-  // Mouse and touch press events are handled via views::PointerDownWatcher.
+  // Mouse and touch press events are handled via views::PointerWatcher.
   if (event->type() == ui::ET_MOUSE_PRESSED ||
       event->type() == ui::ET_TOUCH_PRESSED) {
     return;
diff --git a/ash/shelf/shelf_tooltip_manager.h b/ash/shelf/shelf_tooltip_manager.h
index 390988e..cccd7d3 100644
--- a/ash/shelf/shelf_tooltip_manager.h
+++ b/ash/shelf/shelf_tooltip_manager.h
@@ -12,7 +12,7 @@
 #include "base/timer/timer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 
 namespace views {
 class BubbleDialogDelegateView;
@@ -31,7 +31,7 @@
 // ShelfTooltipManager manages the tooltip bubble that appears for shelf items.
 class ASH_EXPORT ShelfTooltipManager : public ui::EventHandler,
                                        public aura::WindowObserver,
-                                       public views::PointerDownWatcher,
+                                       public views::PointerWatcher,
                                        public ShelfLayoutManagerObserver {
  public:
   explicit ShelfTooltipManager(ShelfView* shelf_view);
@@ -63,7 +63,7 @@
   // aura::WindowObserver overrides:
   void OnWindowDestroying(aura::Window* window) override;
 
-  // views::PointerDownWatcher overrides:
+  // views::PointerWatcher overrides:
   void OnMousePressed(const ui::MouseEvent& event,
                       const gfx::Point& location_in_screen,
                       views::Widget* target) override;
diff --git a/ash/shelf/shelf_tooltip_manager_unittest.cc b/ash/shelf/shelf_tooltip_manager_unittest.cc
index b284191..bdb90510b 100644
--- a/ash/shelf/shelf_tooltip_manager_unittest.cc
+++ b/ash/shelf/shelf_tooltip_manager_unittest.cc
@@ -5,7 +5,6 @@
 #include "ash/shelf/shelf_tooltip_manager.h"
 
 #include "ash/common/shelf/app_list_button.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_view.h"
@@ -83,7 +82,7 @@
   item.type = TYPE_APP_SHORTCUT;
   const int index = model->Add(item);
   const ShelfID id = model->items()[index].id;
-  Shell::GetInstance()->shelf_item_delegate_manager()->SetShelfItemDelegate(
+  model->SetShelfItemDelegate(
       id, base::WrapUnique(new TestShelfItemDelegate(nullptr)));
   // Note: There's no easy way to correlate shelf a model index/id to its view.
   tooltip_manager_->ShowTooltipWithDelay(
diff --git a/ash/shelf/shelf_unittest.cc b/ash/shelf/shelf_unittest.cc
index 91f3417..084ae1c 100644
--- a/ash/shelf/shelf_unittest.cc
+++ b/ash/shelf/shelf_unittest.cc
@@ -6,12 +6,10 @@
 
 #include <utility>
 
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/shelf/shelf_button.h"
 #include "ash/shelf/shelf_view.h"
 #include "ash/shelf/shelf_widget.h"
-#include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/shelf_test_api.h"
 #include "ash/test/shelf_view_test_api.h"
@@ -25,18 +23,11 @@
 #include "base/win/windows_version.h"
 #endif
 
-using ash::ShelfView;
-using ash::ShelfButton;
-
 namespace ash {
 
-class ShelfTest : public ash::test::AshTestBase {
+class ShelfTest : public test::AshTestBase {
  public:
-  ShelfTest()
-      : shelf_(NULL),
-        shelf_view_(NULL),
-        shelf_model_(NULL),
-        item_delegate_manager_(NULL) {}
+  ShelfTest() : shelf_(nullptr), shelf_view_(nullptr), shelf_model_(nullptr) {}
 
   ~ShelfTest() override {}
 
@@ -49,29 +40,22 @@
     test::ShelfTestAPI test(shelf_);
     shelf_view_ = test.shelf_view();
     shelf_model_ = shelf_view_->model();
-    item_delegate_manager_ =
-        Shell::GetInstance()->shelf_item_delegate_manager();
 
-    test_.reset(new ash::test::ShelfViewTestAPI(shelf_view_));
+    test_.reset(new test::ShelfViewTestAPI(shelf_view_));
   }
 
-  void TearDown() override { test::AshTestBase::TearDown(); }
-
   Shelf* shelf() { return shelf_; }
 
   ShelfView* shelf_view() { return shelf_view_; }
 
   ShelfModel* shelf_model() { return shelf_model_; }
 
-  ShelfItemDelegateManager* item_manager() { return item_delegate_manager_; }
-
-  ash::test::ShelfViewTestAPI* test_api() { return test_.get(); }
+  test::ShelfViewTestAPI* test_api() { return test_.get(); }
 
  private:
   Shelf* shelf_;
   ShelfView* shelf_view_;
   ShelfModel* shelf_model_;
-  ShelfItemDelegateManager* item_delegate_manager_;
   std::unique_ptr<test::ShelfViewTestAPI> test_;
 
   DISALLOW_COPY_AND_ASSIGN(ShelfTest);
@@ -98,7 +82,7 @@
 
 // Confirm that using the menu will clear the hover attribute. To avoid another
 // browser test we check this here.
-TEST_F(ShelfTest, checkHoverAfterMenu) {
+TEST_F(ShelfTest, CheckHoverAfterMenu) {
   // Initially we have the app list.
   int button_count = test_api()->GetButtonCount();
 
@@ -110,8 +94,8 @@
 
   std::unique_ptr<ShelfItemDelegate> delegate(
       new test::TestShelfItemDelegate(NULL));
-  item_manager()->SetShelfItemDelegate(shelf_model()->items()[index].id,
-                                       std::move(delegate));
+  shelf_model()->SetShelfItemDelegate(shelf_model()->items()[index].id,
+                                      std::move(delegate));
 
   ASSERT_EQ(++button_count, test_api()->GetButtonCount());
   ShelfButton* button = test_api()->GetButton(index);
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index c6d6808..19fecf8 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -15,7 +15,6 @@
 #include "ash/common/shelf/overflow_bubble_view.h"
 #include "ash/common/shelf/overflow_button.h"
 #include "ash/common/shelf/shelf_constants.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_menu_model.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shell_delegate.h"
@@ -385,7 +384,6 @@
       drag_replaced_view_(nullptr),
       dragged_off_shelf_(false),
       snap_back_from_rip_off_view_(nullptr),
-      item_manager_(Shell::GetInstance()->shelf_item_delegate_manager()),
       overflow_mode_(false),
       main_shelf_(nullptr),
       dragged_off_from_overflow_to_shelf_(false),
@@ -538,14 +536,14 @@
   const ShelfItem* item = ShelfItemForView(view);
   if (!item)
     return false;
-  return item_manager_->GetShelfItemDelegate(item->id)->ShouldShowTooltip();
+  return model_->GetShelfItemDelegate(item->id)->ShouldShowTooltip();
 }
 
 base::string16 ShelfView::GetTitleForView(const views::View* view) const {
   const ShelfItem* item = ShelfItemForView(view);
-  if (!item || !item_manager_->GetShelfItemDelegate(item->id))
+  if (!item || !model_->GetShelfItemDelegate(item->id))
     return base::string16();
-  return item_manager_->GetShelfItemDelegate(item->id)->GetTitle();
+  return model_->GetShelfItemDelegate(item->id)->GetTitle();
 }
 
 gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
@@ -742,7 +740,7 @@
     return;  // View is being deleted, ignore request.
 
   ShelfItemDelegate* item_delegate =
-      item_manager_->GetShelfItemDelegate(model_->items()[index].id);
+      model_->GetShelfItemDelegate(model_->items()[index].id);
   if (!item_delegate->IsDraggable())
     return;  // View is not draggable, ignore request.
 
@@ -1049,8 +1047,8 @@
   }
 
   // If the item is no longer draggable, bail out.
-  ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
-      model_->items()[start_drag_index_].id);
+  ShelfItemDelegate* item_delegate =
+      model_->GetShelfItemDelegate(model_->items()[start_drag_index_].id);
   if (!item_delegate->IsDraggable()) {
     CancelDrag(-1);
     return;
@@ -1070,7 +1068,7 @@
   DCHECK_NE(-1, current_index);
 
   ShelfItemDelegate* item_delegate =
-      item_manager_->GetShelfItemDelegate(model_->items()[current_index].id);
+      model_->GetShelfItemDelegate(model_->items()[current_index].id);
   if (!item_delegate->IsDraggable()) {
     CancelDrag(-1);
     return;
@@ -1130,8 +1128,7 @@
 
   int first_draggable_item = 0;
   while (first_draggable_item < static_cast<int>(model_->items().size()) &&
-         !item_manager_
-              ->GetShelfItemDelegate(model_->items()[first_draggable_item].id)
+         !model_->GetShelfItemDelegate(model_->items()[first_draggable_item].id)
               ->IsDraggable()) {
     first_draggable_item++;
   }
@@ -1314,7 +1311,7 @@
 
   std::string app_id = delegate_->GetAppIDForShelfID(model_->items()[index].id);
   ShelfItemDelegate* item_delegate =
-      item_manager_->GetShelfItemDelegate(model_->items()[index].id);
+      model_->GetShelfItemDelegate(model_->items()[index].id);
   if (!item_delegate->CanPin())
     return NOT_REMOVABLE;
   // Note: Only pinned app shortcuts can be removed!
@@ -1681,6 +1678,9 @@
     AnimateToIdealBounds();
 }
 
+void ShelfView::OnSetShelfItemDelegate(ShelfID id,
+                                       ShelfItemDelegate* item_delegate) {}
+
 void ShelfView::ButtonPressed(views::Button* sender,
                               const ui::Event& event,
                               views::InkDrop* ink_drop) {
@@ -1734,8 +1734,7 @@
   }
 
   ShelfItemDelegate::PerformedAction performed_action =
-      item_manager_
-          ->GetShelfItemDelegate(model_->items()[last_pressed_index_].id)
+      model_->GetShelfItemDelegate(model_->items()[last_pressed_index_].id)
           ->ItemSelected(event);
 
   shelf_button_pressed_metric_tracker_.ButtonPressed(event, sender,
@@ -1758,8 +1757,7 @@
                                     views::View* source,
                                     const ui::Event& event,
                                     views::InkDrop* ink_drop) {
-  ShelfItemDelegate* item_delegate =
-      item_manager_->GetShelfItemDelegate(item.id);
+  ShelfItemDelegate* item_delegate = model_->GetShelfItemDelegate(item.id);
   std::unique_ptr<ui::MenuModel> list_menu_model(
       item_delegate->CreateApplicationMenu(event.flags()));
 
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index c57dc15..0bbc334 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -47,7 +47,6 @@
 class ShelfButton;
 class ShelfDelegate;
 class ShelfIconObserver;
-class ShelfItemDelegateManager;
 class ShelfModel;
 struct ShelfItem;
 class WmShelf;
@@ -288,6 +287,8 @@
   void ShelfItemRemoved(int model_index, ShelfID id) override;
   void ShelfItemChanged(int model_index, const ShelfItem& old_item) override;
   void ShelfItemMoved(int start_index, int target_index) override;
+  void OnSetShelfItemDelegate(ShelfID id,
+                              ShelfItemDelegate* item_delegate) override;
 
   // Overridden from InkDropButtonListener:
   void ButtonPressed(views::Button* sender,
@@ -445,9 +446,6 @@
   // The rip off view when a snap back operation is underway.
   views::View* snap_back_from_rip_off_view_;
 
-  // Holds ShelfItemDelegateManager.
-  ShelfItemDelegateManager* item_manager_;
-
   // True when this ShelfView is used for Overflow Bubble.
   bool overflow_mode_;
 
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 6bb9a23..ec1be9f 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -13,7 +13,6 @@
 #include "ash/common/shelf/overflow_bubble.h"
 #include "ash/common/shelf/overflow_bubble_view.h"
 #include "ash/common/shelf/shelf_constants.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_menu_model.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shell_window_ids.h"
@@ -309,11 +308,7 @@
   static const char*
       kTimeBetweenWindowMinimizedAndActivatedActionsHistogramName;
 
-  ShelfViewTest()
-      : model_(NULL),
-        shelf_view_(NULL),
-        browser_index_(1),
-        item_manager_(NULL) {}
+  ShelfViewTest() : model_(nullptr), shelf_view_(nullptr), browser_index_(1) {}
   ~ShelfViewTest() override {}
 
   void SetUp() override {
@@ -331,9 +326,6 @@
 
     ReplaceShelfDelegate();
 
-    item_manager_ = Shell::GetInstance()->shelf_item_delegate_manager();
-    DCHECK(item_manager_);
-
     // Add browser shortcut shelf item at index 0 for test.
     AddBrowserShortcut();
   }
@@ -348,7 +340,7 @@
   void CreateAndSetShelfItemDelegateForID(ShelfID id) {
     std::unique_ptr<ShelfItemDelegate> delegate(
         new TestShelfItemDelegate(NULL));
-    item_manager_->SetShelfItemDelegate(id, std::move(delegate));
+    model_->SetShelfItemDelegate(id, std::move(delegate));
   }
 
   ShelfID AddBrowserShortcut() {
@@ -705,7 +697,6 @@
   ShelfModel* model_;
   ShelfView* shelf_view_;
   int browser_index_;
-  ShelfItemDelegateManager* item_manager_;
 
   // Owned by ash::Shell.
   TestShelfDelegateForShelfView* shelf_delegate_;
@@ -1210,10 +1201,10 @@
   SetupForDragTest(&id_map);
 
   (static_cast<TestShelfItemDelegate*>(
-       item_manager_->GetShelfItemDelegate(id_map[1].first)))
+       model_->GetShelfItemDelegate(id_map[1].first)))
       ->set_is_draggable(false);
   (static_cast<TestShelfItemDelegate*>(
-       item_manager_->GetShelfItemDelegate(id_map[2].first)))
+       model_->GetShelfItemDelegate(id_map[2].first)))
       ->set_is_draggable(false);
 
   ASSERT_NO_FATAL_FAILURE(DragAndVerify(3, 1, shelf_view_, id_map));
@@ -1248,7 +1239,7 @@
   // Watch for selection of the browser shortcut.
   ShelfID browser_shelf_id = model_->items()[browser_index_].id;
   ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
-  item_manager_->SetShelfItemDelegate(
+  model_->SetShelfItemDelegate(
       browser_shelf_id, std::unique_ptr<ShelfItemDelegate>(selection_tracker));
 
   // A single click selects the item.
@@ -1273,7 +1264,7 @@
   // Replace the ShelfItemDelegate for |shelf_id| with one which tracks whether
   // the shelf item gets selected.
   ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
-  item_manager_->SetShelfItemDelegate(
+  model_->SetShelfItemDelegate(
       shelf_id, std::unique_ptr<ShelfItemDelegate>(selection_tracker));
 
   gfx::Vector2d press_offset(5, 30);
@@ -1881,7 +1872,7 @@
 
   ShelfID browser_shelf_id = model_->items()[browser_index_].id;
   ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
-  item_manager_->SetShelfItemDelegate(
+  model_->SetShelfItemDelegate(
       browser_shelf_id, std::unique_ptr<ShelfItemDelegate>(selection_tracker));
 
   SimulateClick(browser_index_);
@@ -1898,7 +1889,7 @@
   ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
   selection_tracker->set_item_selected_action(
       ShelfItemDelegate::kNewWindowCreated);
-  item_manager_->SetShelfItemDelegate(
+  model_->SetShelfItemDelegate(
       browser_shelf_id, std::unique_ptr<ShelfItemDelegate>(selection_tracker));
 
   SimulateClick(browser_index_);
@@ -1913,7 +1904,7 @@
 
   ShelfID browser_shelf_id = model_->items()[browser_index_].id;
   ShelfItemSelectionTracker* selection_tracker = new ShelfItemSelectionTracker;
-  item_manager_->SetShelfItemDelegate(
+  model_->SetShelfItemDelegate(
       browser_shelf_id, std::unique_ptr<ShelfItemDelegate>(selection_tracker));
 
   selection_tracker->set_item_selected_action(
@@ -2569,8 +2560,8 @@
   // Set a delegate for the shelf item that returns an app list menu.
   ShelfID browser_shelf_id = model_->items()[browser_index_].id;
   ListMenuShelfItemDelegate* list_menu_delegate = new ListMenuShelfItemDelegate;
-  item_manager_->SetShelfItemDelegate(browser_shelf_id,
-                                      base::WrapUnique(list_menu_delegate));
+  model_->SetShelfItemDelegate(browser_shelf_id,
+                               base::WrapUnique(list_menu_delegate));
 
   views::CustomButton* button = browser_button_;
   gfx::Point mouse_location = button->GetLocalBounds().CenterPoint();
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc
index 25661b3..6ca0240 100644
--- a/ash/shelf/shelf_window_watcher.cc
+++ b/ash/shelf/shelf_window_watcher.cc
@@ -9,7 +9,6 @@
 
 #include "ash/aura/wm_window_aura.h"
 #include "ash/common/shelf/shelf_constants.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shell_window_ids.h"
 #include "ash/common/wm/window_state.h"
@@ -100,11 +99,8 @@
   window_watcher_->FinishObservingRemovedWindow(window);
 }
 
-ShelfWindowWatcher::ShelfWindowWatcher(
-    ShelfModel* model,
-    ShelfItemDelegateManager* item_delegate_manager)
+ShelfWindowWatcher::ShelfWindowWatcher(ShelfModel* model)
     : model_(model),
-      item_delegate_manager_(item_delegate_manager),
       root_window_observer_(this),
       removed_window_observer_(this),
       observed_windows_(this),
@@ -132,8 +128,7 @@
   SetShelfIDForWindow(id, window);
   std::unique_ptr<ShelfItemDelegate> item_delegate(
       new ShelfWindowWatcherItemDelegate(window));
-  // |item_delegate| is owned by |item_delegate_manager_|.
-  item_delegate_manager_->SetShelfItemDelegate(id, std::move(item_delegate));
+  model_->SetShelfItemDelegate(id, std::move(item_delegate));
   model_->Add(item);
 }
 
diff --git a/ash/shelf/shelf_window_watcher.h b/ash/shelf/shelf_window_watcher.h
index 7cfe2dca..e61cacb5 100644
--- a/ash/shelf/shelf_window_watcher.h
+++ b/ash/shelf/shelf_window_watcher.h
@@ -28,7 +28,6 @@
 namespace ash {
 
 class ShelfModel;
-class ShelfItemDelegateManager;
 class WmWindow;
 
 // ShelfWindowWatcher creates and handles a ShelfItem for windows that have
@@ -37,8 +36,7 @@
                            public aura::WindowObserver,
                            public display::DisplayObserver {
  public:
-  ShelfWindowWatcher(ShelfModel* model,
-                     ShelfItemDelegateManager* item_delegate_manager);
+  explicit ShelfWindowWatcher(ShelfModel* model);
   ~ShelfWindowWatcher() override;
 
  private:
@@ -127,7 +125,6 @@
 
   // Owned by Shell.
   ShelfModel* model_;
-  ShelfItemDelegateManager* item_delegate_manager_;
 
   RootWindowObserver root_window_observer_;
 
diff --git a/ash/shell.cc b/ash/shell.cc
index ffd8e46..a237945 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -19,11 +19,10 @@
 #include "ash/common/gpu_support.h"
 #include "ash/common/keyboard/keyboard_ui.h"
 #include "ash/common/login_status.h"
-#include "ash/common/pointer_down_watcher_delegate.h"
+#include "ash/common/pointer_watcher_delegate.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/shelf/app_list_shelf_item_delegate.h"
 #include "ash/common/shelf/shelf_item_delegate.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shell_delegate.h"
 #include "ash/common/shell_window_ids.h"
@@ -425,12 +424,12 @@
   }
 }
 
-void Shell::AddPointerDownWatcher(views::PointerDownWatcher* watcher) {
-  pointer_down_watcher_delegate_->AddPointerDownWatcher(watcher);
+void Shell::AddPointerWatcher(views::PointerWatcher* watcher) {
+  pointer_watcher_delegate_->AddPointerWatcher(watcher);
 }
 
-void Shell::RemovePointerDownWatcher(views::PointerDownWatcher* watcher) {
-  pointer_down_watcher_delegate_->RemovePointerDownWatcher(watcher);
+void Shell::RemovePointerWatcher(views::PointerWatcher* watcher) {
+  pointer_watcher_delegate_->RemovePointerWatcher(watcher);
 }
 
 #if defined(OS_CHROMEOS)
@@ -507,25 +506,9 @@
 ShelfDelegate* Shell::GetShelfDelegate() {
   if (!shelf_delegate_) {
     ShelfModel* shelf_model = wm_shell_->shelf_model();
-    // Creates ShelfItemDelegateManager before ShelfDelegate.
-    // TODO(jamescook): Move this into WmShell.
-    shelf_item_delegate_manager_.reset(
-        new ShelfItemDelegateManager(shelf_model));
-
     shelf_delegate_.reset(
         wm_shell_->delegate()->CreateShelfDelegate(shelf_model));
-    std::unique_ptr<ShelfItemDelegate> controller(new AppListShelfItemDelegate);
-
-    // Finding the shelf model's location of the app list and setting its
-    // ShelfItemDelegate.
-    int app_list_index = shelf_model->GetItemIndexForType(TYPE_APP_LIST);
-    DCHECK_GE(app_list_index, 0);
-    ShelfID app_list_id = shelf_model->items()[app_list_index].id;
-    DCHECK(app_list_id);
-    shelf_item_delegate_manager_->SetShelfItemDelegate(app_list_id,
-                                                       std::move(controller));
-    shelf_window_watcher_.reset(new ShelfWindowWatcher(
-        shelf_model, shelf_item_delegate_manager_.get()));
+    shelf_window_watcher_.reset(new ShelfWindowWatcher(shelf_model));
   }
   return shelf_delegate_.get();
 }
@@ -698,8 +681,6 @@
   event_client_.reset();
   toplevel_window_event_handler_.reset();
   visibility_controller_.reset();
-  // |shelf_item_delegate_manager_| observes the shelf model.
-  shelf_item_delegate_manager_.reset();
 
   power_button_controller_.reset();
   lock_state_controller_.reset();
@@ -736,7 +717,7 @@
   focus_client_.reset();
   screen_position_controller_.reset();
   new_window_delegate_.reset();
-  pointer_down_watcher_delegate_.reset();
+  pointer_watcher_delegate_.reset();
 
   keyboard::KeyboardController::ResetInstance(nullptr);
 
@@ -981,8 +962,8 @@
   session_state_delegate_.reset(
       wm_shell_->delegate()->CreateSessionStateDelegate());
   new_window_delegate_.reset(wm_shell_->delegate()->CreateNewWindowDelegate());
-  pointer_down_watcher_delegate_ =
-      wm_shell_->delegate()->CreatePointerDownWatcherDelegate();
+  pointer_watcher_delegate_ =
+      wm_shell_->delegate()->CreatePointerWatcherDelegate();
 
   resize_shadow_controller_.reset(new ResizeShadowController());
   shadow_controller_.reset(new ::wm::ShadowController(activation_client_));
diff --git a/ash/shell.h b/ash/shell.h
index 25e6ddc..85f9901 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -59,7 +59,7 @@
 }
 namespace views {
 class NonClientFrameView;
-class PointerDownWatcher;
+class PointerWatcher;
 class Widget;
 namespace corewm {
 class TooltipController;
@@ -105,7 +105,7 @@
 class NewWindowDelegate;
 class OverlayEventFilter;
 class PartialMagnificationController;
-class PointerDownWatcherDelegate;
+class PointerWatcherDelegate;
 class PowerButtonController;
 class PowerEventObserver;
 class ProjectingObserver;
@@ -122,7 +122,6 @@
 class SessionStateDelegate;
 class Shelf;
 class ShelfDelegate;
-class ShelfItemDelegateManager;
 class ShelfWindowWatcher;
 class ShellDelegate;
 struct ShellInitParams;
@@ -274,8 +273,8 @@
   // Show shelf view if it was created hidden (before session has started).
   void ShowShelf();
 
-  void AddPointerDownWatcher(views::PointerDownWatcher* watcher);
-  void RemovePointerDownWatcher(views::PointerDownWatcher* watcher);
+  void AddPointerWatcher(views::PointerWatcher* watcher);
+  void RemovePointerWatcher(views::PointerWatcher* watcher);
 
 #if defined(OS_CHROMEOS)
   // Test if MaximizeModeWindowManager is not enabled, and if
@@ -369,10 +368,6 @@
     return activation_client_;
   }
 
-  ShelfItemDelegateManager* shelf_item_delegate_manager() {
-    return shelf_item_delegate_manager_.get();
-  }
-
   base::SequencedWorkerPool* blocking_pool() { return blocking_pool_; }
 
   // Force the shelf to query for it's current visibility state.
@@ -559,9 +554,8 @@
   std::unique_ptr<UserWallpaperDelegate> user_wallpaper_delegate_;
   std::unique_ptr<SessionStateDelegate> session_state_delegate_;
   std::unique_ptr<NewWindowDelegate> new_window_delegate_;
-  std::unique_ptr<PointerDownWatcherDelegate> pointer_down_watcher_delegate_;
+  std::unique_ptr<PointerWatcherDelegate> pointer_watcher_delegate_;
   std::unique_ptr<ShelfDelegate> shelf_delegate_;
-  std::unique_ptr<ShelfItemDelegateManager> shelf_item_delegate_manager_;
   std::unique_ptr<ShelfWindowWatcher> shelf_window_watcher_;
   std::unique_ptr<WindowPositioner> window_positioner_;
 
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index b5e9d9c..e3fee20c 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -15,7 +15,7 @@
 #include "ash/common/wm/window_state.h"
 #include "ash/default_user_wallpaper_delegate.h"
 #include "ash/new_window_delegate.h"
-#include "ash/pointer_down_watcher_delegate_aura.h"
+#include "ash/pointer_watcher_delegate_aura.h"
 #include "ash/shell.h"
 #include "ash/shell/context_menu.h"
 #include "ash/shell/example_factory.h"
@@ -243,9 +243,9 @@
   return new MediaDelegateImpl;
 }
 
-std::unique_ptr<ash::PointerDownWatcherDelegate>
-ShellDelegateImpl::CreatePointerDownWatcherDelegate() {
-  return base::WrapUnique(new PointerDownWatcherDelegateAura);
+std::unique_ptr<ash::PointerWatcherDelegate>
+ShellDelegateImpl::CreatePointerWatcherDelegate() {
+  return base::WrapUnique(new PointerWatcherDelegateAura);
 }
 
 ui::MenuModel* ShellDelegateImpl::CreateContextMenu(WmShelf* wm_shelf,
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h
index 85962370..4043567 100644
--- a/ash/shell/shell_delegate_impl.h
+++ b/ash/shell/shell_delegate_impl.h
@@ -49,7 +49,7 @@
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
   NewWindowDelegate* CreateNewWindowDelegate() override;
   MediaDelegate* CreateMediaDelegate() override;
-  std::unique_ptr<PointerDownWatcherDelegate> CreatePointerDownWatcherDelegate()
+  std::unique_ptr<PointerWatcherDelegate> CreatePointerWatcherDelegate()
       override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc
index 64f1bc93..da8bddc4 100644
--- a/ash/shell/window_watcher.cc
+++ b/ash/shell/window_watcher.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shell_window_ids.h"
 #include "ash/common/wm_shell.h"
@@ -114,11 +113,9 @@
 
   model->Add(item);
 
-  ShelfItemDelegateManager* manager =
-      Shell::GetInstance()->shelf_item_delegate_manager();
   std::unique_ptr<ShelfItemDelegate> delegate(
       new WindowWatcherShelfItemDelegate(id, this));
-  manager->SetShelfItemDelegate(id, std::move(delegate));
+  model->SetShelfItemDelegate(id, std::move(delegate));
   SetShelfIDForWindow(id, new_window);
 }
 
diff --git a/ash/sysui/BUILD.gn b/ash/sysui/BUILD.gn
index 4ab5f8e..adf4ac8 100644
--- a/ash/sysui/BUILD.gn
+++ b/ash/sysui/BUILD.gn
@@ -15,8 +15,8 @@
     "context_menu_mus.h",
     "keyboard_ui_mus.cc",
     "keyboard_ui_mus.h",
-    "pointer_down_watcher_delegate_mus.cc",
-    "pointer_down_watcher_delegate_mus.h",
+    "pointer_watcher_delegate_mus.cc",
+    "pointer_watcher_delegate_mus.h",
     "shelf_delegate_mus.cc",
     "shelf_delegate_mus.h",
     "shell_delegate_mus.cc",
diff --git a/ash/sysui/pointer_down_watcher_delegate_mus.cc b/ash/sysui/pointer_down_watcher_delegate_mus.cc
deleted file mode 100644
index 9dc01d8a..0000000
--- a/ash/sysui/pointer_down_watcher_delegate_mus.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/sysui/pointer_down_watcher_delegate_mus.h"
-
-#include "ui/views/mus/window_manager_connection.h"
-
-namespace ash {
-
-PointerDownWatcherDelegateMus::PointerDownWatcherDelegateMus() {}
-
-PointerDownWatcherDelegateMus::~PointerDownWatcherDelegateMus() {}
-
-void PointerDownWatcherDelegateMus::AddPointerDownWatcher(
-    views::PointerDownWatcher* watcher) {
-  views::WindowManagerConnection::Get()->AddPointerDownWatcher(watcher);
-}
-
-void PointerDownWatcherDelegateMus::RemovePointerDownWatcher(
-    views::PointerDownWatcher* watcher) {
-  views::WindowManagerConnection::Get()->RemovePointerDownWatcher(watcher);
-}
-
-}  // namespace ash
diff --git a/ash/sysui/pointer_down_watcher_delegate_mus.h b/ash/sysui/pointer_down_watcher_delegate_mus.h
deleted file mode 100644
index b0b12ec..0000000
--- a/ash/sysui/pointer_down_watcher_delegate_mus.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_SYSUI_POINTER_DOWN_WATCHER_DELEGATE_MUS_H_
-#define ASH_SYSUI_POINTER_DOWN_WATCHER_DELEGATE_MUS_H_
-
-#include "ash/common/pointer_down_watcher_delegate.h"
-#include "base/macros.h"
-
-namespace ash {
-
-// PointerDownWatcher support on mus via the WindowManagerConnection.
-class PointerDownWatcherDelegateMus : public PointerDownWatcherDelegate {
- public:
-  PointerDownWatcherDelegateMus();
-  ~PointerDownWatcherDelegateMus() override;
-
-  // PointerDownWatcherDelegate:
-  void AddPointerDownWatcher(views::PointerDownWatcher* watcher) override;
-  void RemovePointerDownWatcher(views::PointerDownWatcher* watcher) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PointerDownWatcherDelegateMus);
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSUI_POINTER_DOWN_WATCHER_DELEGATE_MUS_H_
diff --git a/ash/sysui/pointer_watcher_delegate_mus.cc b/ash/sysui/pointer_watcher_delegate_mus.cc
new file mode 100644
index 0000000..8118237
--- /dev/null
+++ b/ash/sysui/pointer_watcher_delegate_mus.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/sysui/pointer_watcher_delegate_mus.h"
+
+#include "ui/views/mus/window_manager_connection.h"
+
+namespace ash {
+
+PointerWatcherDelegateMus::PointerWatcherDelegateMus() {}
+
+PointerWatcherDelegateMus::~PointerWatcherDelegateMus() {}
+
+void PointerWatcherDelegateMus::AddPointerWatcher(
+    views::PointerWatcher* watcher) {
+  views::WindowManagerConnection::Get()->AddPointerWatcher(watcher);
+}
+
+void PointerWatcherDelegateMus::RemovePointerWatcher(
+    views::PointerWatcher* watcher) {
+  views::WindowManagerConnection::Get()->RemovePointerWatcher(watcher);
+}
+
+}  // namespace ash
diff --git a/ash/sysui/pointer_watcher_delegate_mus.h b/ash/sysui/pointer_watcher_delegate_mus.h
new file mode 100644
index 0000000..360b8a98
--- /dev/null
+++ b/ash/sysui/pointer_watcher_delegate_mus.h
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSUI_POINTER_WATCHER_DELEGATE_MUS_H_
+#define ASH_SYSUI_POINTER_WATCHER_DELEGATE_MUS_H_
+
+#include "ash/common/pointer_watcher_delegate.h"
+#include "base/macros.h"
+
+namespace ash {
+
+// PointerWatcher support on mus via the WindowManagerConnection.
+class PointerWatcherDelegateMus : public PointerWatcherDelegate {
+ public:
+  PointerWatcherDelegateMus();
+  ~PointerWatcherDelegateMus() override;
+
+  // PointerWatcherDelegate:
+  void AddPointerWatcher(views::PointerWatcher* watcher) override;
+  void RemovePointerWatcher(views::PointerWatcher* watcher) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PointerWatcherDelegateMus);
+};
+
+}  // namespace ash
+
+#endif  // ASH_SYSUI_POINTER_WATCHER_DELEGATE_MUS_H_
diff --git a/ash/sysui/shelf_delegate_mus.cc b/ash/sysui/shelf_delegate_mus.cc
index a1c229d..d679f56 100644
--- a/ash/sysui/shelf_delegate_mus.cc
+++ b/ash/sysui/shelf_delegate_mus.cc
@@ -7,14 +7,13 @@
 #include <memory>
 
 #include "ash/common/shelf/shelf_item_delegate.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_menu_model.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shelf/shelf_types.h"
+#include "ash/common/wm_shell.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_widget.h"
-#include "ash/shell.h"
 #include "base/strings/string_util.h"
 #include "mojo/common/common_type_converters.h"
 #include "services/shell/public/cpp/connector.h"
@@ -153,8 +152,7 @@
 
 ShelfItemDelegateMus* GetShelfItemDelegate(ShelfID shelf_id) {
   return static_cast<ShelfItemDelegateMus*>(
-      Shell::GetInstance()->shelf_item_delegate_manager()->GetShelfItemDelegate(
-          shelf_id));
+      WmShell::Get()->shelf_model()->GetShelfItemDelegate(shelf_id));
 }
 
 // Returns an icon image from an SkBitmap, or the default shelf icon
@@ -322,8 +320,7 @@
   item_delegate->SetDelegate(std::move(delegate));
   item_delegate->set_pinned(true);
   item_delegate->set_title(item->app_title.To<base::string16>());
-  Shell::GetInstance()->shelf_item_delegate_manager()->SetShelfItemDelegate(
-      shelf_id, std::move(item_delegate));
+  model_->SetShelfItemDelegate(shelf_id, std::move(item_delegate));
 }
 
 void ShelfDelegateMus::UnpinItem(const mojo::String& app_id) {
@@ -393,8 +390,7 @@
       new ShelfItemDelegateMus(user_window_controller_.get()));
   item_delegate->AddWindow(user_window->window_id,
                            user_window->window_title.To<base::string16>());
-  Shell::GetInstance()->shelf_item_delegate_manager()->SetShelfItemDelegate(
-      shelf_id, std::move(item_delegate));
+  model_->SetShelfItemDelegate(shelf_id, std::move(item_delegate));
 }
 
 void ShelfDelegateMus::OnUserWindowRemoved(uint32_t window_id) {
diff --git a/ash/sysui/shell_delegate_mus.cc b/ash/sysui/shell_delegate_mus.cc
index ea3e518d..0734d17 100644
--- a/ash/sysui/shell_delegate_mus.cc
+++ b/ash/sysui/shell_delegate_mus.cc
@@ -11,7 +11,7 @@
 #include "ash/common/system/tray/default_system_tray_delegate.h"
 #include "ash/sysui/app_list_presenter_mus.h"
 #include "ash/sysui/context_menu_mus.h"
-#include "ash/sysui/pointer_down_watcher_delegate_mus.h"
+#include "ash/sysui/pointer_watcher_delegate_mus.h"
 #include "ash/sysui/shelf_delegate_mus.h"
 #include "ash/sysui/user_wallpaper_delegate_mus.h"
 #include "base/memory/ptr_util.h"
@@ -195,9 +195,9 @@
   return new MediaDelegateStub;
 }
 
-std::unique_ptr<PointerDownWatcherDelegate>
-ShellDelegateMus::CreatePointerDownWatcherDelegate() {
-  return base::WrapUnique(new PointerDownWatcherDelegateMus);
+std::unique_ptr<PointerWatcherDelegate>
+ShellDelegateMus::CreatePointerWatcherDelegate() {
+  return base::WrapUnique(new PointerWatcherDelegateMus);
 }
 
 ui::MenuModel* ShellDelegateMus::CreateContextMenu(WmShelf* wm_shelf,
diff --git a/ash/sysui/shell_delegate_mus.h b/ash/sysui/shell_delegate_mus.h
index d5ce8bc..c5323bc 100644
--- a/ash/sysui/shell_delegate_mus.h
+++ b/ash/sysui/shell_delegate_mus.h
@@ -44,7 +44,7 @@
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
   NewWindowDelegate* CreateNewWindowDelegate() override;
   MediaDelegate* CreateMediaDelegate() override;
-  std::unique_ptr<PointerDownWatcherDelegate> CreatePointerDownWatcherDelegate()
+  std::unique_ptr<PointerWatcherDelegate> CreatePointerWatcherDelegate()
       override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
diff --git a/ash/sysui/stub_context_factory.cc b/ash/sysui/stub_context_factory.cc
index ce7af105..44f7512c 100644
--- a/ash/sysui/stub_context_factory.cc
+++ b/ash/sysui/stub_context_factory.cc
@@ -71,10 +71,8 @@
   return task_graph_runner_.get();
 }
 
-std::unique_ptr<cc::SurfaceIdAllocator>
-StubContextFactory::CreateSurfaceIdAllocator() {
-  return base::WrapUnique(
-      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
+uint32_t StubContextFactory::AllocateSurfaceClientId() {
+  return next_surface_id_namespace_++;
 }
 
 cc::SurfaceManager* StubContextFactory::GetSurfaceManager() {
diff --git a/ash/sysui/stub_context_factory.h b/ash/sysui/stub_context_factory.h
index ec3aa9f1..f1f5d65 100644
--- a/ash/sysui/stub_context_factory.h
+++ b/ash/sysui/stub_context_factory.h
@@ -37,7 +37,7 @@
   cc::SharedBitmapManager* GetSharedBitmapManager() override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
-  std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
+  uint32_t AllocateSurfaceClientId() override;
   cc::SurfaceManager* GetSurfaceManager() override;
   void ResizeDisplay(ui::Compositor* compositor,
                      const gfx::Size& size) override;
diff --git a/ash/test/shelf_item_delegate_manager_test_api.cc b/ash/test/shelf_item_delegate_manager_test_api.cc
deleted file mode 100644
index 002336e..0000000
--- a/ash/test/shelf_item_delegate_manager_test_api.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/test/shelf_item_delegate_manager_test_api.h"
-
-#include "ash/common/shelf/shelf_item_delegate.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
-#include "base/stl_util.h"
-
-namespace ash {
-namespace test {
-
-ShelfItemDelegateManagerTestAPI::ShelfItemDelegateManagerTestAPI(
-    ShelfItemDelegateManager* manager)
-    : manager_(manager) {
-  DCHECK(manager_);
-}
-
-void ShelfItemDelegateManagerTestAPI::RemoveAllShelfItemDelegateForTest() {
-  STLDeleteContainerPairSecondPointers(
-      manager_->id_to_item_delegate_map_.begin(),
-      manager_->id_to_item_delegate_map_.end());
-  manager_->id_to_item_delegate_map_.clear();
-}
-
-}  // namespace test
-}  // namespace ash
diff --git a/ash/test/shelf_item_delegate_manager_test_api.h b/ash/test/shelf_item_delegate_manager_test_api.h
deleted file mode 100644
index e68c5d9..0000000
--- a/ash/test/shelf_item_delegate_manager_test_api.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_TEST_SHELF_ITEM_DELEGATE_MANAGER_TEST_API_H_
-#define ASH_TEST_SHELF_ITEM_DELEGATE_MANAGER_TEST_API_H_
-
-#include "base/macros.h"
-
-namespace ash {
-
-class ShelfItemDelegateManager;
-
-namespace test {
-
-// Accesses private methods from a ShelfItemDelegateManager for testing.
-class ShelfItemDelegateManagerTestAPI {
- public:
-  explicit ShelfItemDelegateManagerTestAPI(ShelfItemDelegateManager* manager);
-
-  // Clear all exsiting ShelfItemDelegate for test.
-  void RemoveAllShelfItemDelegateForTest();
-
- private:
-  ShelfItemDelegateManager* manager_;  // Not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(ShelfItemDelegateManagerTestAPI);
-};
-
-}  // namespace test
-}  // namespace ash
-
-#endif  // ASH_TEST_SHELF_ITEM_DELEGATE_MANAGER_TEST_API_H_
diff --git a/ash/test/test_shelf_delegate.cc b/ash/test/test_shelf_delegate.cc
index 2605eb1..8f836d99 100644
--- a/ash/test/test_shelf_delegate.cc
+++ b/ash/test/test_shelf_delegate.cc
@@ -6,10 +6,8 @@
 
 #include <utility>
 
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/shelf/shelf_util.h"
-#include "ash/shell.h"
 #include "ash/test/test_shelf_item_delegate.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -51,12 +49,9 @@
   model_->Add(item);
   window->AddObserver(this);
 
-  ShelfItemDelegateManager* manager =
-      Shell::GetInstance()->shelf_item_delegate_manager();
-  // |manager| owns TestShelfItemDelegate.
   std::unique_ptr<ShelfItemDelegate> delegate(
       new TestShelfItemDelegate(window));
-  manager->SetShelfItemDelegate(id, std::move(delegate));
+  model_->SetShelfItemDelegate(id, std::move(delegate));
   SetShelfIDForWindow(id, window);
 }
 
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index 882bf01..07e7c18 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -16,7 +16,7 @@
 #include "ash/common/wm/window_state.h"
 #include "ash/common/wm_shell.h"
 #include "ash/new_window_delegate.h"
-#include "ash/pointer_down_watcher_delegate_aura.h"
+#include "ash/pointer_watcher_delegate_aura.h"
 #include "ash/test/test_keyboard_ui.h"
 #include "ash/test/test_session_state_delegate.h"
 #include "ash/test/test_shelf_delegate.h"
@@ -186,9 +186,9 @@
   return new MediaDelegateImpl;
 }
 
-std::unique_ptr<PointerDownWatcherDelegate>
-TestShellDelegate::CreatePointerDownWatcherDelegate() {
-  return base::WrapUnique(new PointerDownWatcherDelegateAura);
+std::unique_ptr<PointerWatcherDelegate>
+TestShellDelegate::CreatePointerWatcherDelegate() {
+  return base::WrapUnique(new PointerWatcherDelegateAura);
 }
 
 ui::MenuModel* TestShellDelegate::CreateContextMenu(WmShelf* wm_shelf,
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index 666a3ab..bc9b92d49 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -54,7 +54,7 @@
   AccessibilityDelegate* CreateAccessibilityDelegate() override;
   NewWindowDelegate* CreateNewWindowDelegate() override;
   MediaDelegate* CreateMediaDelegate() override;
-  std::unique_ptr<PointerDownWatcherDelegate> CreatePointerDownWatcherDelegate()
+  std::unique_ptr<PointerWatcherDelegate> CreatePointerWatcherDelegate()
       override;
   ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
                                    const ShelfItem* item) override;
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java
index ef2887ac..5fc1d21 100644
--- a/base/android/java/src/org/chromium/base/ThreadUtils.java
+++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -189,7 +189,9 @@
      * Asserts that the current thread is running on the main thread.
      */
     public static void assertOnUiThread() {
-        assert runningOnUiThread();
+        if (BuildConfig.IS_DEBUG && !runningOnUiThread()) {
+            throw new IllegalStateException("Must be called on the Ui thread.");
+        }
     }
 
     /**
diff --git a/base/files/file.cc b/base/files/file.cc
index ab05630..1b2224e3 100644
--- a/base/files/file.cc
+++ b/base/files/file.cc
@@ -138,12 +138,4 @@
   return "";
 }
 
-bool File::Flush() {
-  ElapsedTimer timer;
-  SCOPED_FILE_TRACE("Flush");
-  bool return_value = DoFlush();
-  UMA_HISTOGRAM_TIMES("PlatformFile.FlushTime", timer.Elapsed());
-  return return_value;
-}
-
 }  // namespace base
diff --git a/base/files/file.h b/base/files/file.h
index 43ef354..885e00b9 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -252,6 +252,16 @@
 
   // Instructs the filesystem to flush the file to disk. (POSIX: fsync, Windows:
   // FlushFileBuffers).
+  // Calling Flush() does not guarantee file integrity and thus is not a valid
+  // substitute for file integrity checks and recovery codepaths for malformed
+  // files. It can also be *really* slow, so avoid blocking on Flush(),
+  // especially please don't block shutdown on Flush().
+  // Latency percentiles of Flush() across all platforms as of July 2016:
+  // 50 %     > 5 ms
+  // 10 %     > 58 ms
+  //  1 %     > 357 ms
+  //  0.1 %   > 1.8 seconds
+  //  0.01 %  > 7.6 seconds
   bool Flush();
 
   // Updates the file times.
@@ -310,10 +320,6 @@
   // traversal ('..') components.
   void DoInitialize(const FilePath& path, uint32_t flags);
 
-  // TODO(tnagel): Reintegrate into Flush() once histogram isn't needed anymore,
-  // cf. issue 473337.
-  bool DoFlush();
-
   void SetPlatformFile(PlatformFile file);
 
 #if defined(OS_WIN)
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 532ae3f0..3d2d54a 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -511,9 +511,10 @@
 }
 #endif  // !defined(OS_NACL)
 
-bool File::DoFlush() {
+bool File::Flush() {
   ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
+  SCOPED_FILE_TRACE("Flush");
 
 #if defined(OS_NACL)
   NOTIMPLEMENTED();  // NaCl doesn't implement fsync.
diff --git a/base/files/file_win.cc b/base/files/file_win.cc
index 83ce88a..b5bb232 100644
--- a/base/files/file_win.cc
+++ b/base/files/file_win.cc
@@ -396,9 +396,10 @@
   }
 }
 
-bool File::DoFlush() {
+bool File::Flush() {
   ThreadRestrictions::AssertIOAllowed();
   DCHECK(IsValid());
+  SCOPED_FILE_TRACE("Flush");
   return ::FlushFileBuffers(file_.Get()) != FALSE;
 }
 
diff --git a/base/metrics/histogram_macros.h b/base/metrics/histogram_macros.h
index ce1811a5..dcde725 100644
--- a/base/metrics/histogram_macros.h
+++ b/base/metrics/histogram_macros.h
@@ -145,6 +145,9 @@
                                     base::HistogramBase::kNoFlags))
 
 // This is a helper macro used by other macros and shouldn't be used directly.
+// One additional bucket is created in the LinearHistogram for the illegal
+// values >= boundary_value so that mistakes in calling the UMA enumeration
+// macros can be detected.
 #define HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary, flag) \
     STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
         base::LinearHistogram::FactoryGet(name, 1, boundary, boundary + 1, \
@@ -162,7 +165,9 @@
 // problems down the line if you add additional buckets to the histogram.  Note
 // also that, despite explicitly setting the minimum bucket value to |1| below,
 // it is fine for enumerated histograms to be 0-indexed -- this is because
-// enumerated histograms should never have underflow.
+// enumerated histograms should never have underflow. One additional bucket is
+// created in the LinearHistogram for the illegal values >= boundary_value so
+// that mistakes in calling this macro can be detected.
 #define LOCAL_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
     STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \
         base::LinearHistogram::FactoryGet(name, 1, boundary_value, \
diff --git a/base/process/memory.cc b/base/process/memory.cc
index 75d45303..6349c08 100644
--- a/base/process/memory.cc
+++ b/base/process/memory.cc
@@ -9,6 +9,9 @@
 
 namespace base {
 
+// Defined in memory_win.cc for Windows.
+#if !defined(OS_WIN)
+
 namespace {
 
 // Breakpad server classifies base::`anonymous namespace'::OnNoMemory as
@@ -25,6 +28,8 @@
   OnNoMemory(size);
 }
 
+#endif
+
 // Defined in memory_mac.mm for Mac.
 #if !defined(OS_MACOSX)
 
diff --git a/base/process/memory.h b/base/process/memory.h
index fc0a2f04..77911cfc 100644
--- a/base/process/memory.h
+++ b/base/process/memory.h
@@ -51,7 +51,7 @@
 #if defined(OS_WIN)
 namespace win {
 
-// Custom exception code chosen to indicate an out of memory error.
+// Custom Windows exception code chosen to indicate an out of memory error.
 // See https://msdn.microsoft.com/en-us/library/het71c37.aspx.
 // "To make sure that you do not define a code that conflicts with an existing
 // exception code" ... "The resulting error code should therefore have the
diff --git a/base/process/memory_stubs.cc b/base/process/memory_stubs.cc
index 7ed012d..787d9aef 100644
--- a/base/process/memory_stubs.cc
+++ b/base/process/memory_stubs.cc
@@ -19,6 +19,10 @@
   return false;
 }
 
+void TerminateBecauseOutOfMemory(size_t size) {
+  abort();
+}
+
 // UncheckedMalloc and Calloc exist so that platforms making use of
 // EnableTerminationOnOutOfMemory have a way to allocate memory without
 // crashing. This _stubs.cc file is for platforms that do not support
diff --git a/base/process/memory_win.cc b/base/process/memory_win.cc
index 9d75efe..d433020d 100644
--- a/base/process/memory_win.cc
+++ b/base/process/memory_win.cc
@@ -29,9 +29,9 @@
 namespace {
 
 #pragma warning(push)
-#pragma warning(disable: 4702)
+#pragma warning(disable: 4702)  // Unreachable code after the _exit.
 
-int OnNoMemory(size_t size) {
+NOINLINE int OnNoMemory(size_t size) {
   // Kill the process. This is important for security since most of code
   // does not check the result of memory allocation.
   // https://msdn.microsoft.com/en-us/library/het71c37.aspx
@@ -44,11 +44,12 @@
 
 #pragma warning(pop)
 
-// HeapSetInformation function pointer.
-typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
-
 }  // namespace
 
+void TerminateBecauseOutOfMemory(size_t size) {
+  OnNoMemory(size);
+}
+
 void EnableTerminationOnHeapCorruption() {
   // Ignore the result code. Supported on XP SP3 and Vista.
   HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
index 447c249..8b5a9da 100644
--- a/base/sys_info_android.cc
+++ b/base/sys_info_android.cc
@@ -62,7 +62,7 @@
 // cannot be acquired. Use the latest Android release with a higher bug fix
 // version to avoid unnecessarily comparison errors with the latest release.
 // This should be manually kept up to date on each Android release.
-const int kDefaultAndroidMajorVersion = 6;
+const int kDefaultAndroidMajorVersion = 7;
 const int kDefaultAndroidMinorVersion = 0;
 const int kDefaultAndroidBugfixVersion = 99;
 
diff --git a/base/task_scheduler/scheduler_service_thread_unittest.cc b/base/task_scheduler/scheduler_service_thread_unittest.cc
index b0750b8..65690b00 100644
--- a/base/task_scheduler/scheduler_service_thread_unittest.cc
+++ b/base/task_scheduler/scheduler_service_thread_unittest.cc
@@ -59,7 +59,8 @@
                                   ThreadPriority::BACKGROUND,
                                   SchedulerWorkerPoolParams::IORestriction::
                                       DISALLOWED,
-                                  1u),
+                                  1u,
+                                  TimeDelta::Max()),
         Bind(&ReEnqueueSequenceCallback), &task_tracker_,
         &delayed_task_manager_);
     ASSERT_TRUE(scheduler_worker_pool_);
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc
index 5a2a7d6a..6f5be94 100644
--- a/base/task_scheduler/scheduler_worker.cc
+++ b/base/task_scheduler/scheduler_worker.cc
@@ -10,6 +10,11 @@
 
 #include "base/logging.h"
 #include "base/task_scheduler/task_tracker.h"
+#include "build/build_config.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
 
 namespace base {
 namespace internal {
@@ -39,6 +44,15 @@
     while (!outer_->task_tracker_->IsShutdownComplete() &&
            !outer_->ShouldExitForTesting()) {
       DCHECK(outer_);
+
+#if defined(OS_MACOSX)
+      mac::ScopedNSAutoreleasePool autorelease_pool;
+#endif
+
+#if !defined(OS_LINUX)
+      UpdateThreadPriority(GetDesiredThreadPriority());
+#endif
+
       // Get the sequence containing the next task to execute.
       scoped_refptr<Sequence> sequence = outer_->delegate_->GetWork(outer_);
       if (!sequence) {
@@ -91,17 +105,17 @@
 
  private:
   Thread(SchedulerWorker* outer)
-    : outer_(outer),
-      wake_up_event_(WaitableEvent::ResetPolicy::MANUAL,
-                     WaitableEvent::InitialState::NOT_SIGNALED) {
+      : outer_(outer),
+        wake_up_event_(WaitableEvent::ResetPolicy::MANUAL,
+                       WaitableEvent::InitialState::NOT_SIGNALED),
+        current_thread_priority_(GetDesiredThreadPriority()) {
     DCHECK(outer_);
   }
 
   void Initialize() {
     constexpr size_t kDefaultStackSize = 0;
-    PlatformThread::CreateWithPriority(kDefaultStackSize, this,
-                                       &thread_handle_,
-                                       outer_->thread_priority_);
+    PlatformThread::CreateWithPriority(kDefaultStackSize, this, &thread_handle_,
+                                       current_thread_priority_);
   }
 
   void WaitForWork() {
@@ -117,6 +131,31 @@
     wake_up_event_.Reset();
   }
 
+  // Returns the desired thread priority based on the worker priority and the
+  // current shutdown state.
+  ThreadPriority GetDesiredThreadPriority() {
+    DCHECK(outer_);
+
+    if (outer_->task_tracker_->HasShutdownStarted() &&
+        static_cast<int>(outer_->thread_priority_) <
+            static_cast<int>(ThreadPriority::NORMAL)) {
+      return ThreadPriority::NORMAL;
+    }
+    return outer_->thread_priority_;
+  }
+
+  // Increasing the thread priority requires the CAP_SYS_NICE capability on
+  // Linux.
+#if !defined(OS_LINUX)
+  void UpdateThreadPriority(ThreadPriority desired_thread_priority) {
+    if (desired_thread_priority == current_thread_priority_)
+      return;
+
+    PlatformThread::SetCurrentThreadPriority(desired_thread_priority);
+    current_thread_priority_ = desired_thread_priority;
+  }
+#endif  // !defined(OS_LINUX)
+
   PlatformThreadHandle thread_handle_;
 
   SchedulerWorker* outer_;
@@ -124,6 +163,10 @@
   // Event signaled to wake up this thread.
   WaitableEvent wake_up_event_;
 
+  // Current priority of this thread. May be different from
+  // |outer_->thread_priority_| during shutdown.
+  ThreadPriority current_thread_priority_;
+
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc
index 9f521e2..cd50c95c 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "base/atomicops.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
@@ -21,6 +22,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_local.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
 
 namespace base {
 namespace internal {
@@ -43,7 +45,9 @@
   // TODO(robliao): Find a concrete way to manage |worker_pool|'s memory.
   SchedulerParallelTaskRunner(const TaskTraits& traits,
                               SchedulerWorkerPool* worker_pool)
-      : traits_(traits), worker_pool_(worker_pool) {}
+      : traits_(traits), worker_pool_(worker_pool) {
+    DCHECK(worker_pool_);
+  }
 
   // TaskRunner:
   bool PostDelayedTask(const tracked_objects::Location& from_here,
@@ -76,7 +80,9 @@
   // TODO(robliao): Find a concrete way to manage |worker_pool|'s memory.
   SchedulerSequencedTaskRunner(const TaskTraits& traits,
                                SchedulerWorkerPool* worker_pool)
-      : traits_(traits), worker_pool_(worker_pool) {}
+      : traits_(traits), worker_pool_(worker_pool) {
+    DCHECK(worker_pool_);
+  }
 
   // SequencedTaskRunner:
   bool PostDelayedTask(const tracked_objects::Location& from_here,
@@ -113,8 +119,22 @@
   DISALLOW_COPY_AND_ASSIGN(SchedulerSequencedTaskRunner);
 };
 
+// Only used in DCHECKs.
+bool ContainsWorker(
+    const std::vector<std::unique_ptr<SchedulerWorker>>& workers,
+    const SchedulerWorker* worker) {
+  auto it = std::find_if(workers.begin(), workers.end(),
+      [worker](const std::unique_ptr<SchedulerWorker>& i) {
+        return i.get() == worker;
+      });
+  return it != workers.end();
+}
+
+}  // namespace
+
 // A task runner that runs tasks with the SINGLE_THREADED ExecutionMode.
-class SchedulerSingleThreadTaskRunner : public SingleThreadTaskRunner {
+class SchedulerWorkerPoolImpl::SchedulerSingleThreadTaskRunner :
+    public SingleThreadTaskRunner {
  public:
   // Constructs a SchedulerSingleThreadTaskRunner which can be used to post
   // tasks so long as |worker_pool| and |worker| are alive.
@@ -122,10 +142,7 @@
   // and |worker|.
   SchedulerSingleThreadTaskRunner(const TaskTraits& traits,
                                   SchedulerWorkerPool* worker_pool,
-                                  SchedulerWorker* worker)
-      : traits_(traits),
-        worker_pool_(worker_pool),
-        worker_(worker) {}
+                                  SchedulerWorker* worker);
 
   // SingleThreadTaskRunner:
   bool PostDelayedTask(const tracked_objects::Location& from_here,
@@ -151,7 +168,7 @@
   }
 
  private:
-  ~SchedulerSingleThreadTaskRunner() override = default;
+  ~SchedulerSingleThreadTaskRunner() override;
 
   // Sequence for all Tasks posted through this TaskRunner.
   const scoped_refptr<Sequence> sequence_ = new Sequence;
@@ -163,19 +180,6 @@
   DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner);
 };
 
-// Only used in DCHECKs.
-bool ContainsWorker(
-    const std::vector<std::unique_ptr<SchedulerWorker>>& workers,
-    const SchedulerWorker* worker) {
-  auto it = std::find_if(workers.begin(), workers.end(),
-      [worker](const std::unique_ptr<SchedulerWorker>& i) {
-        return i.get() == worker;
-      });
-  return it != workers.end();
-}
-
-}  // namespace
-
 class SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl
     : public SchedulerWorker::Delegate {
  public:
@@ -203,6 +207,14 @@
   TimeDelta GetSleepTimeout() override;
   bool CanDetach(SchedulerWorker* worker) override;
 
+  void RegisterSingleThreadTaskRunner() {
+    subtle::Barrier_AtomicIncrement(&num_single_threaded_runners_, 1);
+  }
+
+  void UnregisterSingleThreadTaskRunner() {
+    subtle::Barrier_AtomicIncrement(&num_single_threaded_runners_, -1);
+  }
+
  private:
   SchedulerWorkerPoolImpl* outer_;
   const ReEnqueueSequenceCallback re_enqueue_sequence_callback_;
@@ -214,6 +226,11 @@
   // |single_threaded_priority_queue_|.
   bool last_sequence_is_single_threaded_ = false;
 
+  // Time when GetWork() first returned nullptr.
+  TimeTicks idle_start_time_;
+
+  subtle::Atomic32 num_single_threaded_runners_ = 0;
+
   const int index_;
 
   DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegateImpl);
@@ -234,6 +251,7 @@
   std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool(
       new SchedulerWorkerPoolImpl(params.name(),
                                   params.io_restriction(),
+                                  params.suggested_reclaim_time(),
                                   task_tracker, delayed_task_manager));
   if (worker_pool->Initialize(params.thread_priority(),
                               params.max_threads(),
@@ -250,6 +268,8 @@
 }
 
 void SchedulerWorkerPoolImpl::JoinForTesting() {
+  DCHECK(!CanWorkerDetachForTesting() || suggested_reclaim_time_.is_max()) <<
+      "Workers can detach during join.";
   for (const auto& worker : workers_)
     worker->JoinForTesting();
 
@@ -257,6 +277,11 @@
   join_for_testing_returned_.Signal();
 }
 
+void SchedulerWorkerPoolImpl::DisallowWorkerDetachmentForTesting() {
+  AutoSchedulerLock auto_lock(worker_detachment_allowed_lock_);
+  worker_detachment_allowed_ = false;
+}
+
 scoped_refptr<TaskRunner> SchedulerWorkerPoolImpl::CreateTaskRunnerWithTraits(
     const TaskTraits& traits,
     ExecutionMode execution_mode) {
@@ -367,6 +392,25 @@
   }
 }
 
+SchedulerWorkerPoolImpl::SchedulerSingleThreadTaskRunner::
+    SchedulerSingleThreadTaskRunner(const TaskTraits& traits,
+                                    SchedulerWorkerPool* worker_pool,
+                                    SchedulerWorker* worker)
+    : traits_(traits),
+      worker_pool_(worker_pool),
+      worker_(worker) {
+  DCHECK(worker_pool_);
+  DCHECK(worker_);
+  static_cast<SchedulerWorkerDelegateImpl*>(worker_->delegate())->
+      RegisterSingleThreadTaskRunner();
+}
+
+SchedulerWorkerPoolImpl::SchedulerSingleThreadTaskRunner::
+    ~SchedulerSingleThreadTaskRunner() {
+  static_cast<SchedulerWorkerDelegateImpl*>(worker_->delegate())->
+      UnregisterSingleThreadTaskRunner();
+}
+
 SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
     SchedulerWorkerDelegateImpl(
         SchedulerWorkerPoolImpl* outer,
@@ -398,6 +442,9 @@
   tls_current_worker.Get().Set(worker);
   tls_current_worker_pool.Get().Set(outer_);
 
+  // New threads haven't run GetWork() yet, so reset the idle_start_time_.
+  idle_start_time_ = TimeTicks();
+
   ThreadRestrictions::SetIOAllowed(
       outer_->io_restriction_ ==
           SchedulerWorkerPoolParams::IORestriction::ALLOWED);
@@ -432,6 +479,8 @@
       // 4. This thread adds itself to |idle_workers_stack_| and goes to sleep.
       //    No thread runs the Sequence inserted in step 2.
       outer_->AddToIdleWorkersStack(worker);
+      if (idle_start_time_.is_null())
+        idle_start_time_ = TimeTicks::Now();
       return nullptr;
     }
 
@@ -455,6 +504,8 @@
   }
   DCHECK(sequence);
 
+  idle_start_time_ = TimeTicks();
+
   outer_->RemoveFromIdleWorkersStack(worker);
   return sequence;
 }
@@ -476,21 +527,33 @@
 
 TimeDelta SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
     GetSleepTimeout() {
-  return TimeDelta::Max();
+  return outer_->suggested_reclaim_time_;
 }
 
 bool SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::CanDetach(
     SchedulerWorker* worker) {
-  return false;
+  // It's not an issue if |num_single_threaded_runners_| is incremented after
+  // this because the newly created TaskRunner (from which no task has run yet)
+  // will simply run all its tasks on the next physical thread created by the
+  // worker.
+  const bool can_detach =
+      !idle_start_time_.is_null() &&
+      (TimeTicks::Now() - idle_start_time_) > outer_->suggested_reclaim_time_ &&
+      worker != outer_->PeekAtIdleWorkersStack() &&
+      !subtle::Acquire_Load(&num_single_threaded_runners_) &&
+      outer_->CanWorkerDetachForTesting();
+  return can_detach;
 }
 
 SchedulerWorkerPoolImpl::SchedulerWorkerPoolImpl(
     StringPiece name,
     SchedulerWorkerPoolParams::IORestriction io_restriction,
+    const TimeDelta& suggested_reclaim_time,
     TaskTracker* task_tracker,
     DelayedTaskManager* delayed_task_manager)
     : name_(name.as_string()),
       io_restriction_(io_restriction),
+      suggested_reclaim_time_(suggested_reclaim_time),
       idle_workers_stack_lock_(shared_priority_queue_.container_lock()),
       idle_workers_stack_cv_for_testing_(
           idle_workers_stack_lock_.CreateConditionVariable()),
@@ -521,7 +584,9 @@
                                  this, re_enqueue_sequence_callback,
                                  &shared_priority_queue_, static_cast<int>(i))),
             task_tracker_,
-            SchedulerWorker::InitialState::ALIVE);
+            i == 0
+                ? SchedulerWorker::InitialState::ALIVE
+                : SchedulerWorker::InitialState::DETACHED);
     if (!worker)
       break;
     idle_workers_stack_.Push(worker.get());
@@ -548,18 +613,34 @@
 void SchedulerWorkerPoolImpl::AddToIdleWorkersStack(
     SchedulerWorker* worker) {
   AutoSchedulerLock auto_lock(idle_workers_stack_lock_);
-  idle_workers_stack_.Push(worker);
+  // Detachment may cause multiple attempts to add because the delegate cannot
+  // determine who woke it up. As a result, when it wakes up, it may conclude
+  // there's no work to be done and attempt to add itself to the idle stack
+  // again.
+  if (!idle_workers_stack_.Contains(worker))
+    idle_workers_stack_.Push(worker);
+
   DCHECK_LE(idle_workers_stack_.Size(), workers_.size());
 
   if (idle_workers_stack_.Size() == workers_.size())
     idle_workers_stack_cv_for_testing_->Broadcast();
 }
 
+const SchedulerWorker* SchedulerWorkerPoolImpl::PeekAtIdleWorkersStack() const {
+  AutoSchedulerLock auto_lock(idle_workers_stack_lock_);
+  return idle_workers_stack_.Peek();
+}
+
 void SchedulerWorkerPoolImpl::RemoveFromIdleWorkersStack(
     SchedulerWorker* worker) {
   AutoSchedulerLock auto_lock(idle_workers_stack_lock_);
   idle_workers_stack_.Remove(worker);
 }
 
+bool SchedulerWorkerPoolImpl::CanWorkerDetachForTesting() {
+  AutoSchedulerLock auto_lock(worker_detachment_allowed_lock_);
+  return worker_detachment_allowed_;
+}
+
 }  // namespace internal
 }  // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h
index 85b852f1..8c4f96ce 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl.h
+++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -31,6 +31,9 @@
 #include "base/threading/platform_thread.h"
 
 namespace base {
+
+class TimeDelta;
+
 namespace internal {
 
 class DelayedTaskManager;
@@ -67,6 +70,14 @@
   // allowed to complete their execution. This can only be called once.
   void JoinForTesting();
 
+  // Disallows worker thread detachment. If the suggested reclaim time is not
+  // TimeDelta::Max(), then the test should call this before the detach code can
+  // run. The safest place to do this is before the a set of work is dispatched
+  // (the worker pool is idle and steady state) or before the last
+  // synchronization point for all workers (all threads are busy and can't be
+  // reclaimed).
+  void DisallowWorkerDetachmentForTesting();
+
   // SchedulerWorkerPool:
   scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
       const TaskTraits& traits,
@@ -81,11 +92,13 @@
                                SchedulerWorker* worker) override;
 
  private:
+  class SchedulerSingleThreadTaskRunner;
   class SchedulerWorkerDelegateImpl;
 
   SchedulerWorkerPoolImpl(StringPiece name,
                           SchedulerWorkerPoolParams::IORestriction
                               io_restriction,
+                          const TimeDelta& suggested_reclaim_time,
                           TaskTracker* task_tracker,
                           DelayedTaskManager* delayed_task_manager);
 
@@ -100,9 +113,15 @@
   // Adds |worker| to |idle_workers_stack_|.
   void AddToIdleWorkersStack(SchedulerWorker* worker);
 
+  // Peeks from |idle_workers_stack_|.
+  const SchedulerWorker* PeekAtIdleWorkersStack() const;
+
   // Removes |worker| from |idle_workers_stack_|.
   void RemoveFromIdleWorkersStack(SchedulerWorker* worker);
 
+  // Returns true if worker thread detachment is permitted.
+  bool CanWorkerDetachForTesting();
+
   // The name of this worker pool, used to label its worker threads.
   const std::string name_;
 
@@ -123,12 +142,15 @@
   // Indicates whether Tasks on this worker pool are allowed to make I/O calls.
   const SchedulerWorkerPoolParams::IORestriction io_restriction_;
 
+  // Suggested reclaim time for workers.
+  const TimeDelta suggested_reclaim_time_;
+
   // Synchronizes access to |idle_workers_stack_| and
   // |idle_workers_stack_cv_for_testing_|. Has |shared_priority_queue_|'s
   // lock as its predecessor so that a worker can be pushed to
   // |idle_workers_stack_| within the scope of a Transaction (more
   // details in GetWork()).
-  SchedulerLock idle_workers_stack_lock_;
+  mutable SchedulerLock idle_workers_stack_lock_;
 
   // Stack of idle workers.
   SchedulerWorkerStack idle_workers_stack_;
@@ -139,6 +161,13 @@
   // Signaled once JoinForTesting() has returned.
   WaitableEvent join_for_testing_returned_;
 
+  // Synchronizes access to |worker_detachment_allowed_|.
+  SchedulerLock worker_detachment_allowed_lock_;
+
+  // Indicates to the delegates that workers are permitted to detach their
+  // threads.
+  bool worker_detachment_allowed_ = true;
+
 #if DCHECK_IS_ON()
   // Signaled when all workers have been created.
   WaitableEvent workers_created_;
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
index 9c968830..6bf04a4 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include <unordered_set>
 #include <vector>
 
+#include "base/atomicops.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
@@ -29,7 +30,10 @@
 #include "base/task_scheduler/test_utils.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/simple_thread.h"
+#include "base/threading/thread_checker_impl.h"
+#include "base/threading/thread_local_storage.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -39,6 +43,8 @@
 const size_t kNumWorkersInWorkerPool = 4;
 const size_t kNumThreadsPostingTasks = 4;
 const size_t kNumTasksPostedPerThread = 150;
+constexpr TimeDelta kReclaimTimeForDetachTests =
+    TimeDelta::FromMilliseconds(10);
 
 using IORestriction = SchedulerWorkerPoolParams::IORestriction;
 
@@ -63,15 +69,7 @@
   TaskSchedulerWorkerPoolImplTest() = default;
 
   void SetUp() override {
-    worker_pool_ = SchedulerWorkerPoolImpl::Create(
-        SchedulerWorkerPoolParams("TestWorkerPoolWithFileIO",
-                                  ThreadPriority::NORMAL,
-                                  IORestriction::ALLOWED,
-                                  kNumWorkersInWorkerPool),
-        Bind(&TaskSchedulerWorkerPoolImplTest::ReEnqueueSequenceCallback,
-             Unretained(this)),
-        &task_tracker_, &delayed_task_manager_);
-    ASSERT_TRUE(worker_pool_);
+    InitializeWorkerPool(TimeDelta::Max());
   }
 
   void TearDown() override {
@@ -79,6 +77,19 @@
     worker_pool_->JoinForTesting();
   }
 
+  void InitializeWorkerPool(const TimeDelta& suggested_reclaim_time) {
+    worker_pool_ = SchedulerWorkerPoolImpl::Create(
+        SchedulerWorkerPoolParams("TestWorkerPoolWithFileIO",
+                                  ThreadPriority::NORMAL,
+                                  IORestriction::ALLOWED,
+                                  kNumWorkersInWorkerPool,
+                                  suggested_reclaim_time),
+        Bind(&TaskSchedulerWorkerPoolImplTest::ReEnqueueSequenceCallback,
+             Unretained(this)),
+        &task_tracker_, &delayed_task_manager_);
+    ASSERT_TRUE(worker_pool_);
+  }
+
   std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool_;
 
   TaskTracker task_tracker_;
@@ -367,7 +378,8 @@
 
   auto worker_pool = SchedulerWorkerPoolImpl::Create(
       SchedulerWorkerPoolParams("TestWorkerPoolWithParam",
-                                ThreadPriority::NORMAL, GetParam(), 1U),
+                                ThreadPriority::NORMAL, GetParam(), 1U,
+                                TimeDelta::Max()),
       Bind(&NotReachedReEnqueueSequenceCallback), &task_tracker,
       &delayed_task_manager);
   ASSERT_TRUE(worker_pool);
@@ -388,5 +400,161 @@
                         TaskSchedulerWorkerPoolImplIORestrictionTest,
                         ::testing::Values(IORestriction::DISALLOWED));
 
+namespace {
+
+class TaskSchedulerWorkerPoolSingleThreadedTest
+    : public TaskSchedulerWorkerPoolImplTest {
+ public:
+  void InitializeThreadChecker() {
+    thread_checker_.reset(new ThreadCheckerImpl());
+  }
+
+  void CheckValidThread() {
+    EXPECT_TRUE(thread_checker_->CalledOnValidThread());
+  }
+
+ protected:
+  void SetUp() override {
+    InitializeWorkerPool(kReclaimTimeForDetachTests);
+  }
+
+  TaskSchedulerWorkerPoolSingleThreadedTest() = default;
+
+ private:
+  std::unique_ptr<ThreadCheckerImpl> thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolSingleThreadedTest);
+};
+
+}  // namespace
+
+// Verify that thread resources for a single thread remain.
+TEST_F(TaskSchedulerWorkerPoolSingleThreadedTest, SingleThreadTask) {
+  auto single_thread_task_runner =
+      worker_pool_->CreateTaskRunnerWithTraits(
+          TaskTraits().
+              WithShutdownBehavior(TaskShutdownBehavior::BLOCK_SHUTDOWN),
+          ExecutionMode::SINGLE_THREADED);
+  single_thread_task_runner->PostTask(
+      FROM_HERE,
+      Bind(&TaskSchedulerWorkerPoolSingleThreadedTest::InitializeThreadChecker,
+           Unretained(this)));
+  WaitableEvent task_waiter(WaitableEvent::ResetPolicy::AUTOMATIC,
+                            WaitableEvent::InitialState::NOT_SIGNALED);
+  single_thread_task_runner->PostTask(
+      FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_waiter)));
+  task_waiter.Wait();
+  worker_pool_->WaitForAllWorkersIdleForTesting();
+
+  // Give the worker pool a chance to reclaim its threads.
+  PlatformThread::Sleep(
+      kReclaimTimeForDetachTests + TimeDelta::FromMilliseconds(200));
+
+  worker_pool_->DisallowWorkerDetachmentForTesting();
+
+  single_thread_task_runner->PostTask(
+      FROM_HERE,
+      Bind(&TaskSchedulerWorkerPoolSingleThreadedTest::CheckValidThread,
+           Unretained(this)));
+  single_thread_task_runner->PostTask(
+      FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_waiter)));
+  task_waiter.Wait();
+}
+
+namespace {
+
+constexpr size_t kMagicTlsValue = 42;
+
+class TaskSchedulerWorkerPoolCheckTlsReuse
+    : public TaskSchedulerWorkerPoolImplTest {
+ public:
+  void SetTlsValueAndWait() {
+    slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
+    waiter_.Wait();
+  }
+
+  void CountZeroTlsValuesAndWait(WaitableEvent* count_waiter) {
+    if (!slot_.Get())
+      subtle::NoBarrier_AtomicIncrement(&zero_tls_values_, 1);
+
+    count_waiter->Signal();
+    waiter_.Wait();
+  }
+
+ protected:
+  TaskSchedulerWorkerPoolCheckTlsReuse() :
+      waiter_(WaitableEvent::ResetPolicy::MANUAL,
+              WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+  void SetUp() override {
+    InitializeWorkerPool(kReclaimTimeForDetachTests);
+  }
+
+  subtle::Atomic32 zero_tls_values_ = 0;
+
+  WaitableEvent waiter_;
+
+ private:
+  ThreadLocalStorage::Slot slot_;
+
+  DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolCheckTlsReuse);
+};
+
+}  // namespace
+
+// Checks that at least one thread has detached by checking the TLS.
+TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) {
+  // Saturate the threads and mark each thread with a magic TLS value.
+  std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
+  for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) {
+    factories.push_back(WrapUnique(new test::TestTaskFactory(
+        worker_pool_->CreateTaskRunnerWithTraits(
+            TaskTraits(), ExecutionMode::PARALLEL),
+        ExecutionMode::PARALLEL)));
+    ASSERT_TRUE(factories.back()->PostTask(
+        PostNestedTask::NO,
+        Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait,
+             Unretained(this))));
+    factories.back()->WaitForAllTasksToRun();
+  }
+
+  // Release tasks waiting on |waiter_|.
+  waiter_.Signal();
+  worker_pool_->WaitForAllWorkersIdleForTesting();
+
+  // All threads should be done running by now, so reset for the next phase.
+  waiter_.Reset();
+
+  // Give the worker pool a chance to detach its threads.
+  PlatformThread::Sleep(
+      kReclaimTimeForDetachTests + TimeDelta::FromMilliseconds(200));
+
+  worker_pool_->DisallowWorkerDetachmentForTesting();
+
+  // Saturate and count the threads that do not have the magic TLS value. If the
+  // value is not there, that means we're at a new thread.
+  std::vector<std::unique_ptr<WaitableEvent>> count_waiters;
+  for (auto& factory : factories) {
+    count_waiters.push_back(WrapUnique(new WaitableEvent(
+        WaitableEvent::ResetPolicy::MANUAL,
+        WaitableEvent::InitialState::NOT_SIGNALED)));
+    ASSERT_TRUE(factory->PostTask(
+          PostNestedTask::NO,
+          Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::CountZeroTlsValuesAndWait,
+               Unretained(this),
+               count_waiters.back().get())));
+    factory->WaitForAllTasksToRun();
+  }
+
+  // Wait for all counters to complete.
+  for (auto& count_waiter : count_waiters)
+    count_waiter->Wait();
+
+  EXPECT_GT(subtle::NoBarrier_Load(&zero_tls_values_), 0);
+
+  // Release tasks waiting on |waiter_|.
+  waiter_.Signal();
+}
+
 }  // namespace internal
 }  // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_params.cc b/base/task_scheduler/scheduler_worker_pool_params.cc
index beefc38..6164498 100644
--- a/base/task_scheduler/scheduler_worker_pool_params.cc
+++ b/base/task_scheduler/scheduler_worker_pool_params.cc
@@ -4,6 +4,8 @@
 
 #include "base/task_scheduler/scheduler_worker_pool_params.h"
 
+#include "base/time/time.h"
+
 namespace base {
 namespace internal {
 
@@ -11,11 +13,13 @@
     const std::string& name,
     ThreadPriority thread_priority,
     IORestriction io_restriction,
-    int max_threads)
+    int max_threads,
+    const TimeDelta& suggested_reclaim_time)
     : name_(name),
       thread_priority_(thread_priority),
       io_restriction_(io_restriction),
-      max_threads_(max_threads) {}
+      max_threads_(max_threads),
+      suggested_reclaim_time_(suggested_reclaim_time) {}
 
 SchedulerWorkerPoolParams::SchedulerWorkerPoolParams(
     SchedulerWorkerPoolParams&& other) = default;
diff --git a/base/task_scheduler/scheduler_worker_pool_params.h b/base/task_scheduler/scheduler_worker_pool_params.h
index 955e0e89..6d2fd89 100644
--- a/base/task_scheduler/scheduler_worker_pool_params.h
+++ b/base/task_scheduler/scheduler_worker_pool_params.h
@@ -11,6 +11,9 @@
 #include "base/threading/platform_thread.h"
 
 namespace base {
+
+class TimeDelta;
+
 namespace internal {
 
 class BASE_EXPORT SchedulerWorkerPoolParams final {
@@ -24,12 +27,15 @@
   // scheduler worker pool to use the label |name| and create up to
   // |max_threads| threads of priority |thread_priority|. |io_restriction|
   // indicates whether Tasks on the scheduler worker pool are allowed to make
-  // I/O calls.
+  // I/O calls. |suggested_reclaim_time| sets a suggestion on when to reclaim
+  // idle threads. The worker pool is free to ignore this value for performance
+  // or correctness reasons.
   SchedulerWorkerPoolParams(
       const std::string& name,
       ThreadPriority thread_priority,
       IORestriction io_restriction,
-      int max_threads);
+      int max_threads,
+      const TimeDelta& suggested_reclaim_time);
   SchedulerWorkerPoolParams(SchedulerWorkerPoolParams&& other);
   SchedulerWorkerPoolParams& operator=(SchedulerWorkerPoolParams&& other);
 
@@ -45,11 +51,17 @@
   // Maximum number of threads in the pool.
   size_t max_threads() const { return max_threads_; }
 
+  // Suggested reclaim time for threads in the worker pool.
+  const TimeDelta& suggested_reclaim_time() const {
+    return suggested_reclaim_time_;
+  }
+
  private:
   std::string name_;
   ThreadPriority thread_priority_;
   IORestriction io_restriction_;
   size_t max_threads_;
+  TimeDelta suggested_reclaim_time_;
 
   DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPoolParams);
 };
diff --git a/base/task_scheduler/scheduler_worker_stack.cc b/base/task_scheduler/scheduler_worker_stack.cc
index 7746373..7996efe 100644
--- a/base/task_scheduler/scheduler_worker_stack.cc
+++ b/base/task_scheduler/scheduler_worker_stack.cc
@@ -16,8 +16,7 @@
 SchedulerWorkerStack::~SchedulerWorkerStack() = default;
 
 void SchedulerWorkerStack::Push(SchedulerWorker* worker) {
-  DCHECK(std::find(stack_.begin(), stack_.end(), worker) == stack_.end())
-      << "SchedulerWorker already on stack";
+  DCHECK(!Contains(worker)) << "SchedulerWorker already on stack";
   stack_.push_back(worker);
 }
 
@@ -29,6 +28,16 @@
   return worker;
 }
 
+SchedulerWorker* SchedulerWorkerStack::Peek() const {
+  if (IsEmpty())
+    return nullptr;
+  return stack_.back();
+}
+
+bool SchedulerWorkerStack::Contains(const SchedulerWorker* worker) const {
+  return std::find(stack_.begin(), stack_.end(), worker) != stack_.end();
+}
+
 void SchedulerWorkerStack::Remove(const SchedulerWorker* worker) {
   auto it = std::find(stack_.begin(), stack_.end(), worker);
   if (it != stack_.end())
diff --git a/base/task_scheduler/scheduler_worker_stack.h b/base/task_scheduler/scheduler_worker_stack.h
index 1d1748c..b96fc5ac 100644
--- a/base/task_scheduler/scheduler_worker_stack.h
+++ b/base/task_scheduler/scheduler_worker_stack.h
@@ -17,11 +17,11 @@
 
 class SchedulerWorker;
 
-// A stack of SchedulerWorkers. Supports removal of arbitrary
-// SchedulerWorkers. DCHECKs when a SchedulerWorker is inserted
-// multiple times. SchedulerWorkers are not owned by the stack. Push() is
-// amortized O(1). Pop(), Size() and Empty() are O(1). Remove is O(n). This
-// class is NOT thread-safe.
+// A stack of SchedulerWorkers. Supports removal of arbitrary SchedulerWorkers.
+// DCHECKs when a SchedulerWorker is inserted multiple times. SchedulerWorkers
+// are not owned by the stack. Push() is amortized O(1). Pop(), Peek(), Size()
+// and Empty() are O(1). Contains() and Remove() are O(n).
+// This class is NOT thread-safe.
 class BASE_EXPORT SchedulerWorkerStack {
  public:
   SchedulerWorkerStack();
@@ -35,6 +35,12 @@
   // Returns nullptr if the stack is empty.
   SchedulerWorker* Pop();
 
+  // Returns the top SchedulerWorker from the stack, nullptr if empty.
+  SchedulerWorker* Peek() const;
+
+  // Returns true if |worker| is already on the stack.
+  bool Contains(const SchedulerWorker* worker) const;
+
   // Removes |worker| from the stack.
   void Remove(const SchedulerWorker* worker);
 
diff --git a/base/task_scheduler/scheduler_worker_stack_unittest.cc b/base/task_scheduler/scheduler_worker_stack_unittest.cc
index 2a77008..847d37d 100644
--- a/base/task_scheduler/scheduler_worker_stack_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_stack_unittest.cc
@@ -76,6 +76,8 @@
 // Verify that Push() and Pop() add/remove values in FIFO order.
 TEST_F(TaskSchedulerWorkerStackTest, PushPop) {
   SchedulerWorkerStack stack;
+  EXPECT_EQ(nullptr, stack.Pop());
+
   EXPECT_TRUE(stack.IsEmpty());
   EXPECT_EQ(0U, stack.Size());
 
@@ -110,6 +112,86 @@
   EXPECT_EQ(worker_a_.get(), stack.Pop());
   EXPECT_TRUE(stack.IsEmpty());
   EXPECT_EQ(0U, stack.Size());
+
+  EXPECT_EQ(nullptr, stack.Pop());
+}
+
+// Verify that Peek() returns the correct values in FIFO order.
+TEST_F(TaskSchedulerWorkerStackTest, PeekPop) {
+  SchedulerWorkerStack stack;
+  EXPECT_EQ(nullptr, stack.Peek());
+
+  EXPECT_TRUE(stack.IsEmpty());
+  EXPECT_EQ(0U, stack.Size());
+
+  stack.Push(worker_a_.get());
+  EXPECT_EQ(worker_a_.get(), stack.Peek());
+  EXPECT_FALSE(stack.IsEmpty());
+  EXPECT_EQ(1U, stack.Size());
+
+  stack.Push(worker_b_.get());
+  EXPECT_EQ(worker_b_.get(), stack.Peek());
+  EXPECT_FALSE(stack.IsEmpty());
+  EXPECT_EQ(2U, stack.Size());
+
+  stack.Push(worker_c_.get());
+  EXPECT_EQ(worker_c_.get(), stack.Peek());
+  EXPECT_FALSE(stack.IsEmpty());
+  EXPECT_EQ(3U, stack.Size());
+
+  EXPECT_EQ(worker_c_.get(), stack.Pop());
+  EXPECT_EQ(worker_b_.get(), stack.Peek());
+  EXPECT_FALSE(stack.IsEmpty());
+  EXPECT_EQ(2U, stack.Size());
+
+  EXPECT_EQ(worker_b_.get(), stack.Pop());
+  EXPECT_EQ(worker_a_.get(), stack.Peek());
+  EXPECT_FALSE(stack.IsEmpty());
+  EXPECT_EQ(1U, stack.Size());
+
+  EXPECT_EQ(worker_a_.get(), stack.Pop());
+  EXPECT_TRUE(stack.IsEmpty());
+  EXPECT_EQ(0U, stack.Size());
+
+  EXPECT_EQ(nullptr, stack.Peek());
+}
+
+// Verify that Contains() returns true for workers on the stack.
+TEST_F(TaskSchedulerWorkerStackTest, Contains) {
+  SchedulerWorkerStack stack;
+  EXPECT_FALSE(stack.Contains(worker_a_.get()));
+  EXPECT_FALSE(stack.Contains(worker_b_.get()));
+  EXPECT_FALSE(stack.Contains(worker_c_.get()));
+
+  stack.Push(worker_a_.get());
+  EXPECT_TRUE(stack.Contains(worker_a_.get()));
+  EXPECT_FALSE(stack.Contains(worker_b_.get()));
+  EXPECT_FALSE(stack.Contains(worker_c_.get()));
+
+  stack.Push(worker_b_.get());
+  EXPECT_TRUE(stack.Contains(worker_a_.get()));
+  EXPECT_TRUE(stack.Contains(worker_b_.get()));
+  EXPECT_FALSE(stack.Contains(worker_c_.get()));
+
+  stack.Push(worker_c_.get());
+  EXPECT_TRUE(stack.Contains(worker_a_.get()));
+  EXPECT_TRUE(stack.Contains(worker_b_.get()));
+  EXPECT_TRUE(stack.Contains(worker_c_.get()));
+
+  stack.Pop();
+  EXPECT_TRUE(stack.Contains(worker_a_.get()));
+  EXPECT_TRUE(stack.Contains(worker_b_.get()));
+  EXPECT_FALSE(stack.Contains(worker_c_.get()));
+
+  stack.Pop();
+  EXPECT_TRUE(stack.Contains(worker_a_.get()));
+  EXPECT_FALSE(stack.Contains(worker_b_.get()));
+  EXPECT_FALSE(stack.Contains(worker_c_.get()));
+
+  stack.Pop();
+  EXPECT_FALSE(stack.Contains(worker_a_.get()));
+  EXPECT_FALSE(stack.Contains(worker_b_.get()));
+  EXPECT_FALSE(stack.Contains(worker_c_.get()));
 }
 
 // Verify that a value can be removed by Remove().
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc
index 437bbedfd..fb94edc 100644
--- a/base/task_scheduler/scheduler_worker_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_unittest.cc
@@ -14,11 +14,14 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/synchronization/condition_variable.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/task_scheduler/scheduler_lock.h"
 #include "base/task_scheduler/sequence.h"
 #include "base/task_scheduler/task.h"
 #include "base/task_scheduler/task_tracker.h"
+#include "base/threading/platform_thread.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -421,6 +424,108 @@
   worker->JoinForTesting();
 }
 
+namespace {
+
+class ExpectThreadPriorityDelegate : public SchedulerWorker::Delegate {
+ public:
+  ExpectThreadPriorityDelegate()
+      : priority_verified_in_get_work_event_(
+            WaitableEvent::ResetPolicy::AUTOMATIC,
+            WaitableEvent::InitialState::NOT_SIGNALED),
+        expected_thread_priority_(ThreadPriority::BACKGROUND) {}
+
+  void SetExpectedThreadPriority(ThreadPriority expected_thread_priority) {
+    expected_thread_priority_ = expected_thread_priority;
+  }
+
+  void WaitForPriorityVerifiedInGetWork() {
+    priority_verified_in_get_work_event_.Wait();
+  }
+
+  // SchedulerWorker::Delegate:
+  void OnMainEntry(SchedulerWorker* worker) override { VerifyThreadPriority(); }
+  scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
+    VerifyThreadPriority();
+    priority_verified_in_get_work_event_.Signal();
+    return nullptr;
+  }
+  void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override {}
+  TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); }
+  bool CanDetach(SchedulerWorker* worker) override { return false; }
+
+ private:
+  void VerifyThreadPriority() {
+    AutoSchedulerLock auto_lock(expected_thread_priority_lock_);
+    EXPECT_EQ(expected_thread_priority_,
+              PlatformThread::GetCurrentThreadPriority());
+  }
+
+  // Signaled after GetWork() has verified the priority of the worker thread.
+  WaitableEvent priority_verified_in_get_work_event_;
+
+  // Synchronizes access to |expected_thread_priority_|.
+  SchedulerLock expected_thread_priority_lock_;
+
+  // Expected thread priority for the next call to OnMainEntry() or GetWork().
+  ThreadPriority expected_thread_priority_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExpectThreadPriorityDelegate);
+};
+
+}  // namespace
+
+// Increasing the thread priority requires the CAP_SYS_NICE capability on Linux.
+#if !defined(OS_LINUX)
+TEST(TaskSchedulerWorkerTest, BumpPriorityOfAliveThreadDuringShutdown) {
+  TaskTracker task_tracker;
+
+  std::unique_ptr<ExpectThreadPriorityDelegate> delegate(
+      new ExpectThreadPriorityDelegate);
+  ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
+  delegate_raw->SetExpectedThreadPriority(ThreadPriority::BACKGROUND);
+
+  std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create(
+      ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
+      SchedulerWorker::InitialState::ALIVE);
+
+  // Verify that the initial thread priority is BACKGROUND.
+  worker->WakeUp();
+  delegate_raw->WaitForPriorityVerifiedInGetWork();
+
+  // Verify that the thread priority is bumped to NORMAL during shutdown.
+  delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL);
+  task_tracker.SetHasShutdownStartedForTesting();
+  worker->WakeUp();
+  delegate_raw->WaitForPriorityVerifiedInGetWork();
+
+  worker->JoinForTesting();
+}
+#endif  // defined(OS_LINUX)
+
+TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) {
+  TaskTracker task_tracker;
+
+  std::unique_ptr<ExpectThreadPriorityDelegate> delegate(
+      new ExpectThreadPriorityDelegate);
+  ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
+  delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL);
+
+  // Create a DETACHED thread.
+  std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create(
+      ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker,
+      SchedulerWorker::InitialState::DETACHED);
+
+  // Pretend that shutdown has started.
+  task_tracker.SetHasShutdownStartedForTesting();
+
+  // Wake up the thread and verify that its priority is NORMAL when
+  // OnMainEntry() and GetWork() are called.
+  worker->WakeUp();
+  delegate_raw->WaitForPriorityVerifiedInGetWork();
+
+  worker->JoinForTesting();
+}
+
 }  // namespace
 }  // namespace internal
 }  // namespace base
diff --git a/base/task_scheduler/task_scheduler_impl_unittest.cc b/base/task_scheduler/task_scheduler_impl_unittest.cc
index 91f6986..d275fbf 100644
--- a/base/task_scheduler/task_scheduler_impl_unittest.cc
+++ b/base/task_scheduler/task_scheduler_impl_unittest.cc
@@ -23,6 +23,7 @@
 #include "base/threading/simple_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -166,22 +167,22 @@
     ASSERT_EQ(BACKGROUND_WORKER_POOL, params_vector.size());
     params_vector.emplace_back("TaskSchedulerBackground",
                                ThreadPriority::BACKGROUND,
-                               IORestriction::DISALLOWED, 1U);
+                               IORestriction::DISALLOWED, 1U, TimeDelta::Max());
 
     ASSERT_EQ(BACKGROUND_FILE_IO_WORKER_POOL, params_vector.size());
     params_vector.emplace_back("TaskSchedulerBackgroundFileIO",
                                ThreadPriority::BACKGROUND,
-                               IORestriction::ALLOWED, 3U);
+                               IORestriction::ALLOWED, 3U, TimeDelta::Max());
 
     ASSERT_EQ(FOREGROUND_WORKER_POOL, params_vector.size());
     params_vector.emplace_back("TaskSchedulerForeground",
                                ThreadPriority::NORMAL,
-                               IORestriction::DISALLOWED, 4U);
+                               IORestriction::DISALLOWED, 4U, TimeDelta::Max());
 
     ASSERT_EQ(FOREGROUND_FILE_IO_WORKER_POOL, params_vector.size());
     params_vector.emplace_back("TaskSchedulerForegroundFileIO",
                                ThreadPriority::NORMAL, IORestriction::ALLOWED,
-                               12U);
+                               12U, TimeDelta::Max());
 
     scheduler_ = TaskSchedulerImpl::Create(params_vector,
                                            Bind(&GetThreadPoolIndexForTraits));
diff --git a/base/task_scheduler/task_tracker.cc b/base/task_scheduler/task_tracker.cc
index 8817baa..1ebc81b 100644
--- a/base/task_scheduler/task_tracker.cc
+++ b/base/task_scheduler/task_tracker.cc
@@ -124,6 +124,7 @@
     // This method can only be called once.
     DCHECK(!shutdown_event_);
     DCHECK(!num_block_shutdown_tasks_posted_during_shutdown_);
+    DCHECK(!state_->HasShutdownStarted());
 
     shutdown_event_.reset(
         new WaitableEvent(WaitableEvent::ResetPolicy::MANUAL,
@@ -214,14 +215,17 @@
   AfterRunTask(shutdown_behavior);
 }
 
+bool TaskTracker::HasShutdownStarted() const {
+  return state_->HasShutdownStarted();
+}
+
 bool TaskTracker::IsShutdownComplete() const {
   AutoSchedulerLock auto_lock(shutdown_lock_);
   return shutdown_event_ && shutdown_event_->IsSignaled();
 }
 
-bool TaskTracker::IsShuttingDownForTesting() const {
-  AutoSchedulerLock auto_lock(shutdown_lock_);
-  return shutdown_event_ && !shutdown_event_->IsSignaled();
+void TaskTracker::SetHasShutdownStartedForTesting() {
+  state_->StartShutdown();
 }
 
 bool TaskTracker::BeforePostTask(TaskShutdownBehavior shutdown_behavior) {
diff --git a/base/task_scheduler/task_tracker.h b/base/task_scheduler/task_tracker.h
index fc0901f..609edbc 100644
--- a/base/task_scheduler/task_tracker.h
+++ b/base/task_scheduler/task_tracker.h
@@ -44,12 +44,17 @@
   // must have allowed |task| to be posted.
   void RunTask(const Task* task);
 
-  // Returns true if shutdown has completed.
+  // Returns true once shutdown has started (Shutdown() has been called but
+  // might not have returned).
+  bool HasShutdownStarted() const;
+
+  // Returns true if shutdown has completed (Shutdown() has returned).
   bool IsShutdownComplete() const;
 
-  // Returns true while shutdown is in progress (i.e. Shutdown() has been called
-  // but hasn't returned).
-  bool IsShuttingDownForTesting() const;
+  // Causes HasShutdownStarted() to return true. Unlike when Shutdown() returns,
+  // IsShutdownComplete() won't return true after this returns. Shutdown()
+  // cannot be called after this.
+  void SetHasShutdownStartedForTesting();
 
  private:
   class State;
diff --git a/base/task_scheduler/task_tracker_unittest.cc b/base/task_scheduler/task_tracker_unittest.cc
index 58f47b81..326f7aa0 100644
--- a/base/task_scheduler/task_tracker_unittest.cc
+++ b/base/task_scheduler/task_tracker_unittest.cc
@@ -132,10 +132,8 @@
     ASSERT_FALSE(thread_calling_shutdown_);
     thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_));
     thread_calling_shutdown_->Start();
-    while (!tracker_.IsShuttingDownForTesting() &&
-           !tracker_.IsShutdownComplete()) {
+    while (!tracker_.HasShutdownStarted())
       PlatformThread::YieldCurrentThread();
-    }
   }
 
   void WaitForAsyncIsShutdownComplete() {
@@ -148,8 +146,8 @@
   void VerifyAsyncShutdownInProgress() {
     ASSERT_TRUE(thread_calling_shutdown_);
     EXPECT_FALSE(thread_calling_shutdown_->has_returned());
+    EXPECT_TRUE(tracker_.HasShutdownStarted());
     EXPECT_FALSE(tracker_.IsShutdownComplete());
-    EXPECT_TRUE(tracker_.IsShuttingDownForTesting());
   }
 
   size_t NumTasksExecuted() {
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index a8833aeb..98610a6 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -33,42 +33,26 @@
 
 }  // namespace
 
-Thread::Options::Options()
-    : message_loop_type(MessageLoop::TYPE_DEFAULT),
-      timer_slack(TIMER_SLACK_NONE),
-      stack_size(0),
-      priority(ThreadPriority::NORMAL) {
-}
+Thread::Options::Options() = default;
 
-Thread::Options::Options(MessageLoop::Type type,
-                         size_t size)
-    : message_loop_type(type),
-      timer_slack(TIMER_SLACK_NONE),
-      stack_size(size),
-      priority(ThreadPriority::NORMAL) {
-}
+Thread::Options::Options(MessageLoop::Type type, size_t size)
+    : message_loop_type(type), stack_size(size) {}
 
 Thread::Options::Options(const Options& other) = default;
 
-Thread::Options::~Options() {
-}
+Thread::Options::~Options() = default;
 
 Thread::Thread(const std::string& name)
-    :
-#if defined(OS_WIN)
-      com_status_(NONE),
-#endif
-      stopping_(false),
-      running_(false),
-      thread_(0),
-      id_(kInvalidThreadId),
-      id_event_(WaitableEvent::ResetPolicy::MANUAL,
+    : id_event_(WaitableEvent::ResetPolicy::MANUAL,
                 WaitableEvent::InitialState::NOT_SIGNALED),
-      message_loop_(nullptr),
-      message_loop_timer_slack_(TIMER_SLACK_NONE),
       name_(name),
       start_event_(WaitableEvent::ResetPolicy::MANUAL,
                    WaitableEvent::InitialState::NOT_SIGNALED) {
+  // Only bind the sequence on Start(): the state is constant between
+  // construction and Start() and it's thus valid for Start() to be called on
+  // another sequence as long as every other operation is then performed on that
+  // sequence.
+  owning_sequence_checker_.DetachFromSequence();
 }
 
 Thread::~Thread() {
@@ -76,6 +60,8 @@
 }
 
 bool Thread::Start() {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
+
   Options options;
 #if defined(OS_WIN)
   if (com_status_ == STA)
@@ -85,7 +71,9 @@
 }
 
 bool Thread::StartWithOptions(const Options& options) {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
   DCHECK(!message_loop_);
+  DCHECK(!IsRunning());
 #if defined(OS_WIN)
   DCHECK((com_status_ != STA) ||
       (options.message_loop_type == MessageLoop::TYPE_UI));
@@ -102,13 +90,14 @@
     type = MessageLoop::TYPE_CUSTOM;
 
   message_loop_timer_slack_ = options.timer_slack;
-  std::unique_ptr<MessageLoop> message_loop =
+  std::unique_ptr<MessageLoop> message_loop_owned =
       MessageLoop::CreateUnbound(type, options.message_pump_factory);
-  message_loop_ = message_loop.get();
+  message_loop_ = message_loop_owned.get();
   start_event_.Reset();
 
-  // Hold the thread_lock_ while starting a new thread, so that we can make sure
-  // that thread_ is populated before the newly created thread accesses it.
+  // Hold |thread_lock_| while starting the new thread to synchronize with
+  // Stop() while it's not guaranteed to be sequenced (until crbug/629139 is
+  // fixed).
   {
     AutoLock lock(thread_lock_);
     if (!PlatformThread::CreateWithPriority(options.stack_size, this, &thread_,
@@ -119,15 +108,16 @@
     }
   }
 
-  // The ownership of message_loop is managemed by the newly created thread
+  // The ownership of |message_loop_| is managed by the newly created thread
   // within the ThreadMain.
-  ignore_result(message_loop.release());
+  ignore_result(message_loop_owned.release());
 
   DCHECK(message_loop_);
   return true;
 }
 
 bool Thread::StartAndWaitForTesting() {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
   bool result = Start();
   if (!result)
     return false;
@@ -136,6 +126,7 @@
 }
 
 bool Thread::WaitUntilThreadStarted() const {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
   if (!message_loop_)
     return false;
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
@@ -144,7 +135,12 @@
 }
 
 void Thread::Stop() {
+  // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+  // enable this check, until then synchronization with Start() via
+  // |thread_lock_| is required...
+  // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
   AutoLock lock(thread_lock_);
+
   if (thread_.is_null())
     return;
 
@@ -152,22 +148,23 @@
 
   // Wait for the thread to exit.
   //
-  // TODO(darin): Unfortunately, we need to keep message_loop_ around until
+  // TODO(darin): Unfortunately, we need to keep |message_loop_| around until
   // the thread exits.  Some consumers are abusing the API.  Make them stop.
   //
   PlatformThread::Join(thread_);
   thread_ = base::PlatformThreadHandle();
 
-  // The thread should nullify message_loop_ on exit.
+  // The thread should nullify |message_loop_| on exit (note: Join() adds an
+  // implicit memory barrier and no lock is thus required for this check).
   DCHECK(!message_loop_);
 
   stopping_ = false;
 }
 
 void Thread::StopSoon() {
-  // We should only be called on the same thread that started us.
-
-  DCHECK_NE(GetThreadId(), PlatformThread::CurrentId());
+  // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+  // enable this check.
+  // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
 
   if (stopping_ || !message_loop_)
     return;
@@ -185,26 +182,35 @@
 }
 
 bool Thread::IsRunning() const {
-  // If the thread's already started (i.e. message_loop_ is non-null) and
-  // not yet requested to stop (i.e. stopping_ is false) we can just return
-  // true. (Note that stopping_ is touched only on the same thread that
-  // starts / started the new thread so we need no locking here.)
+  // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+  // enable this check.
+  // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
+
+  // If the thread's already started (i.e. |message_loop_| is non-null) and not
+  // yet requested to stop (i.e. |stopping_| is false) we can just return true.
+  // (Note that |stopping_| is touched only on the same sequence that starts /
+  // started the new thread so we need no locking here.)
   if (message_loop_ && !stopping_)
     return true;
-  // Otherwise check the running_ flag, which is set to true by the new thread
+  // Otherwise check the |running_| flag, which is set to true by the new thread
   // only while it is inside Run().
   AutoLock lock(running_lock_);
   return running_;
 }
 
 void Thread::Run(RunLoop* run_loop) {
+  // Overridable protected method to be called from our |thread_| only.
+  DCHECK_EQ(id_, PlatformThread::CurrentId());
+
   run_loop->Run();
 }
 
+// static
 void Thread::SetThreadWasQuitProperly(bool flag) {
   lazy_tls_bool.Pointer()->Set(flag);
 }
 
+// static
 bool Thread::GetThreadWasQuitProperly() {
   bool quit_properly = true;
 #ifndef NDEBUG
@@ -224,7 +230,7 @@
   PlatformThread::SetName(name_.c_str());
   ANNOTATE_THREAD_NAME(name_.c_str());  // Tell the name to race detector.
 
-  // Lazily initialize the message_loop so that it can run on this thread.
+  // Lazily initialize the |message_loop| so that it can run on this thread.
   DCHECK(message_loop_);
   std::unique_ptr<MessageLoop> message_loop(message_loop_);
   message_loop_->BindToCurrentThread();
diff --git a/base/threading/thread.h b/base/threading/thread.h
index f68154e..4506424 100644
--- a/base/threading/thread.h
+++ b/base/threading/thread.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/timer_slack.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
@@ -39,6 +40,10 @@
 //  (1) Thread::CleanUp()
 //  (2) MessageLoop::~MessageLoop
 //  (3.b)    MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop
+//
+// This API is not thread-safe: unless indicated otherwise its methods are only
+// valid from the owning sequence (which is the one from which Start() is
+// invoked, should it differ from the one on which it was constructed).
 class BASE_EXPORT Thread : PlatformThread::Delegate {
  public:
   struct BASE_EXPORT Options {
@@ -51,10 +56,10 @@
 
     // Specifies the type of message loop that will be allocated on the thread.
     // This is ignored if message_pump_factory.is_null() is false.
-    MessageLoop::Type message_loop_type;
+    MessageLoop::Type message_loop_type = MessageLoop::TYPE_DEFAULT;
 
     // Specifies timer slack for thread message loop.
-    TimerSlack timer_slack;
+    TimerSlack timer_slack = TIMER_SLACK_NONE;
 
     // Used to create the MessagePump for the MessageLoop. The callback is Run()
     // on the thread. If message_pump_factory.is_null(), then a MessagePump
@@ -65,10 +70,10 @@
     // Specifies the maximum stack size that the thread is allowed to use.
     // This does not necessarily correspond to the thread's initial stack size.
     // A value of 0 indicates that the default maximum should be used.
-    size_t stack_size;
+    size_t stack_size = 0;
 
     // Specifies the initial thread priority.
-    ThreadPriority priority;
+    ThreadPriority priority = ThreadPriority::NORMAL;
   };
 
   // Constructor.
@@ -159,14 +164,39 @@
   // NOTE: You must not call this MessageLoop's Quit method directly.  Use
   // the Thread's Stop method instead.
   //
-  MessageLoop* message_loop() const { return message_loop_; }
+  // In addition to this Thread's owning sequence, this can also safely be
+  // called from the underlying thread itself.
+  MessageLoop* message_loop() const {
+    // This class doesn't provide synchronization around |message_loop_| and as
+    // such only the owner should access it (and the underlying thread which
+    // never sees it before it's set). In practice, many callers are coming from
+    // unrelated threads but provide their own implicit (e.g. memory barriers
+    // from task posting) or explicit (e.g. locks) synchronization making the
+    // access of |message_loop_| safe... Changing all of those callers is
+    // unfeasible; instead verify that they can reliably see
+    // |message_loop_ != nullptr| without synchronization as a proof that their
+    // external synchronization catches the unsynchronized effects of Start().
+    // TODO(gab): Despite all of the above this test has to be disabled for now
+    // per crbug.com/629139#c6.
+    // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread() ||
+    //        id_ == PlatformThread::CurrentId() || message_loop_)
+    //     << id_ << " vs " << PlatformThread::CurrentId();
+    return message_loop_;
+  }
 
   // Returns a TaskRunner for this thread. Use the TaskRunner's PostTask
   // methods to execute code on the thread. Returns nullptr if the thread is not
   // running (e.g. before Start or after Stop have been called). Callers can
   // hold on to this even after the thread is gone; in this situation, attempts
   // to PostTask() will fail.
+  //
+  // In addition to this Thread's owning sequence, this can also safely be
+  // called from the underlying thread itself.
   scoped_refptr<SingleThreadTaskRunner> task_runner() const {
+    // Refer to the DCHECK and comment inside |message_loop()|.
+    DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread() ||
+           id_ == PlatformThread::CurrentId() || message_loop_)
+        << id_ << " vs " << PlatformThread::CurrentId();
     return message_loop_ ? message_loop_->task_runner() : nullptr;
   }
 
@@ -179,6 +209,7 @@
   //
   // WARNING: This function will block if the thread hasn't started yet.
   //
+  // This method is thread-safe.
   PlatformThreadId GetThreadId() const;
 
   // Returns true if the thread has been started, and not yet stopped.
@@ -198,6 +229,7 @@
   static bool GetThreadWasQuitProperly();
 
   void set_message_loop(MessageLoop* message_loop) {
+    DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
     message_loop_ = message_loop;
   }
 
@@ -217,17 +249,17 @@
 
 #if defined(OS_WIN)
   // Whether this thread needs to initialize COM, and if so, in what mode.
-  ComStatus com_status_;
+  ComStatus com_status_ = NONE;
 #endif
 
   // If true, we're in the middle of stopping, and shouldn't access
   // |message_loop_|. It may non-nullptr and invalid.
   // Should be written on the thread that created this thread. Also read data
   // could be wrong on other threads.
-  bool stopping_;
+  bool stopping_ = false;
 
   // True while inside of Run().
-  bool running_;
+  bool running_ = false;
   mutable base::Lock running_lock_;  // Protects |running_|.
 
   // The thread's handle.
@@ -235,24 +267,28 @@
   mutable base::Lock thread_lock_;  // Protects |thread_|.
 
   // The thread's id once it has started.
-  PlatformThreadId id_;
+  PlatformThreadId id_ = kInvalidThreadId;
   mutable WaitableEvent id_event_;  // Protects |id_|.
 
   // The thread's MessageLoop and RunLoop. Valid only while the thread is alive.
   // Set by the created thread.
-  MessageLoop* message_loop_;
-  RunLoop* run_loop_;
+  MessageLoop* message_loop_ = nullptr;
+  RunLoop* run_loop_ = nullptr;
 
   // Stores Options::timer_slack_ until the message loop has been bound to
   // a thread.
-  TimerSlack message_loop_timer_slack_;
+  TimerSlack message_loop_timer_slack_ = TIMER_SLACK_NONE;
 
   // The name of the thread.  Used for debugging purposes.
-  std::string name_;
+  const std::string name_;
 
   // Signaled when the created thread gets ready to use the message loop.
   mutable WaitableEvent start_event_;
 
+  // This class is not thread-safe, use this to verify access from the owning
+  // sequence of the Thread.
+  SequenceChecker owning_sequence_checker_;
+
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
diff --git a/base/threading/thread_unittest.cc b/base/threading/thread_unittest.cc
index b01f52f..dfa04c6 100644
--- a/base/threading/thread_unittest.cc
+++ b/base/threading/thread_unittest.cc
@@ -157,16 +157,11 @@
   EXPECT_TRUE(a.message_loop());
   EXPECT_TRUE(a.IsRunning());
 
-  bool was_invoked = false;
-  a.task_runner()->PostTask(FROM_HERE, base::Bind(&ToggleValue, &was_invoked));
-
-  // wait for the task to run (we could use a kernel event here
-  // instead to avoid busy waiting, but this is sufficient for
-  // testing purposes).
-  for (int i = 100; i >= 0 && !was_invoked; --i) {
-    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
-  }
-  EXPECT_TRUE(was_invoked);
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  a.task_runner()->PostTask(FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
+                                                  base::Unretained(&event)));
+  event.Wait();
 }
 
 TEST_F(ThreadTest, TwoTasks) {
@@ -195,7 +190,42 @@
   EXPECT_TRUE(a.message_loop());
   EXPECT_TRUE(a.IsRunning());
   a.StopSoon();
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+}
+
+TEST_F(ThreadTest, StopTwiceNop) {
+  Thread a("StopTwiceNop");
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
   a.StopSoon();
+  // Calling StopSoon() a second time should be a nop.
+  a.StopSoon();
+  a.Stop();
+  // Same with Stop().
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+  // Calling them when not running should also nop.
+  a.StopSoon();
+  a.Stop();
+}
+
+TEST_F(ThreadTest, StartTwice) {
+  Thread a("StartTwice");
+
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
   a.Stop();
   EXPECT_FALSE(a.message_loop());
   EXPECT_FALSE(a.IsRunning());
diff --git a/base/time/time.h b/base/time/time.h
index efece96..be0eb20 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -713,6 +713,13 @@
   // clock will be used instead.
   static bool IsHighResolution();
 
+  // Returns true if TimeTicks is consistent across processes, meaning that
+  // timestamps taken on different processes can be safely compared with one
+  // another. (Note that, even on platforms where this returns true, time values
+  // from different threads that are within one tick of each other must be
+  // considered to have an ambiguous ordering.)
+  static bool IsConsistentAcrossProcesses();
+
 #if defined(OS_WIN)
   // Translates an absolute QPC timestamp into a TimeTicks value. The returned
   // value has the same origin as Now(). Do NOT attempt to use this if
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc
index 373ec3a..8f589166 100644
--- a/base/time/time_mac.cc
+++ b/base/time/time_mac.cc
@@ -259,6 +259,11 @@
 }
 
 // static
+bool TimeTicks::IsConsistentAcrossProcesses() {
+  return true;
+}
+
+// static
 TimeTicks::Clock TimeTicks::GetClock() {
 #if defined(OS_IOS)
   return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME;
diff --git a/base/time/time_posix.cc b/base/time/time_posix.cc
index 495e249..0897f9c 100644
--- a/base/time/time_posix.cc
+++ b/base/time/time_posix.cc
@@ -340,6 +340,11 @@
 }
 
 // static
+bool TimeTicks::IsConsistentAcrossProcesses() {
+  return true;
+}
+
+// static
 ThreadTicks ThreadTicks::Now() {
 #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
     defined(OS_ANDROID)
diff --git a/base/time/time_win.cc b/base/time/time_win.cc
index 8708eb2..ba6fc1d 100644
--- a/base/time/time_win.cc
+++ b/base/time/time_win.cc
@@ -504,6 +504,26 @@
 }
 
 // static
+bool TimeTicks::IsConsistentAcrossProcesses() {
+  // According to Windows documentation [1] QPC is consistent post-Windows
+  // Vista. So if we are using QPC then we are consistent which is the same as
+  // being high resolution.
+  //
+  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+  //
+  // "In general, the performance counter results are consistent across all
+  // processors in multi-core and multi-processor systems, even when measured on
+  // different threads or processes. Here are some exceptions to this rule:
+  // - Pre-Windows Vista operating systems that run on certain processors might
+  // violate this consistency because of one of these reasons:
+  //     1. The hardware processors have a non-invariant TSC and the BIOS
+  //     doesn't indicate this condition correctly.
+  //     2. The TSC synchronization algorithm that was used wasn't suitable for
+  //     systems with large numbers of processors."
+  return IsHighResolution();
+}
+
+// static
 TimeTicks::Clock TimeTicks::GetClock() {
   return IsHighResolution() ?
       Clock::WIN_QPC : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME;
diff --git a/blimp/BUILD.gn b/blimp/BUILD.gn
index 131ec09..bcfbd81a 100644
--- a/blimp/BUILD.gn
+++ b/blimp/BUILD.gn
@@ -175,6 +175,8 @@
       _rebased_blimp_engine_env_tests_manifest,
       "--output",
       rebase_path(_bundle),
+      "--tar-contents-rooted-in",
+      rebase_path("//")
     ]
   }
 }
diff --git a/blimp/engine/Dockerfile b/blimp/engine/Dockerfile
index 12b4b61..36699a7 100644
--- a/blimp/engine/Dockerfile
+++ b/blimp/engine/Dockerfile
@@ -4,8 +4,6 @@
 
 RUN useradd -ms /bin/bash blimp_user
 
-# The glob below expands to all files, but does not add directories
-# recursively.
 ADD * /engine/
 ADD gen/third_party/blimp_fonts /engine/fonts
 RUN mv /engine/chrome_sandbox /engine/chrome-sandbox
diff --git a/blimp/engine/app/blimp_browser_main_parts.cc b/blimp/engine/app/blimp_browser_main_parts.cc
index d1a95ec..d5390e9 100644
--- a/blimp/engine/app/blimp_browser_main_parts.cc
+++ b/blimp/engine/app/blimp_browser_main_parts.cc
@@ -5,14 +5,18 @@
 #include "blimp/engine/app/blimp_browser_main_parts.h"
 
 #include "base/command_line.h"
+#include "base/memory/ptr_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "blimp/common/proto/blimp_message.pb.h"
 #include "blimp/engine/app/blimp_engine_config.h"
 #include "blimp/engine/app/settings_manager.h"
 #include "blimp/engine/common/blimp_browser_context.h"
+#include "blimp/engine/feature/geolocation/blimp_location_provider.h"
 #include "blimp/engine/session/blimp_engine_session.h"
 #include "blimp/net/blimp_connection.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/geolocation_provider.h"
 #include "content/public/common/main_function_params.h"
 #include "net/base/net_module.h"
 #include "net/log/net_log.h"
@@ -20,6 +24,25 @@
 namespace blimp {
 namespace engine {
 
+namespace {
+// A provider of services needed by Geolocation.
+class BlimpGeolocationDelegate : public content::GeolocationDelegate {
+ public:
+  BlimpGeolocationDelegate() = default;
+
+  bool UseNetworkLocationProviders() final { return false; }
+
+  std::unique_ptr<content::LocationProvider> OverrideSystemLocationProvider()
+      final {
+    return base::WrapUnique(new BlimpLocationProvider());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BlimpGeolocationDelegate);
+};
+
+}  // anonymous namespace
+
 BlimpBrowserMainParts::BlimpBrowserMainParts(
     const content::MainFunctionParams& parameters) {}
 
@@ -42,6 +65,8 @@
   settings_manager_.reset(new SettingsManager);
   std::unique_ptr<BlimpBrowserContext> browser_context(
       new BlimpBrowserContext(false, net_log_.get()));
+  content::GeolocationProvider::SetGeolocationDelegate(
+      new BlimpGeolocationDelegate());
   engine_session_.reset(
       new BlimpEngineSession(std::move(browser_context), net_log_.get(),
                              engine_config_.get(), settings_manager_.get()));
diff --git a/blimp/engine/app/blimp_content_browser_client.cc b/blimp/engine/app/blimp_content_browser_client.cc
index 90ea2f52..2afbe417 100644
--- a/blimp/engine/app/blimp_content_browser_client.cc
+++ b/blimp/engine/app/blimp_content_browser_client.cc
@@ -5,33 +5,12 @@
 #include "blimp/engine/app/blimp_content_browser_client.h"
 #include "blimp/engine/app/blimp_browser_main_parts.h"
 #include "blimp/engine/app/settings_manager.h"
-#include "blimp/engine/feature/geolocation/blimp_location_provider.h"
 #include "blimp/engine/mojo/blob_channel_service.h"
-#include "content/public/browser/geolocation_delegate.h"
 #include "services/shell/public/cpp/interface_registry.h"
 
 namespace blimp {
 namespace engine {
 
-namespace {
-// A provider of services needed by Geolocation.
-class BlimpGeolocationDelegate : public content::GeolocationDelegate {
- public:
-  BlimpGeolocationDelegate() = default;
-
-  bool UseNetworkLocationProviders() final { return false; }
-
-  std::unique_ptr<content::LocationProvider> OverrideSystemLocationProvider()
-      final {
-    return base::WrapUnique(new BlimpLocationProvider());
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BlimpGeolocationDelegate);
-};
-
-}  // anonymous namespace
-
 BlimpContentBrowserClient::BlimpContentBrowserClient() {}
 
 BlimpContentBrowserClient::~BlimpContentBrowserClient() {}
@@ -60,11 +39,6 @@
   return blimp_browser_main_parts_->GetBrowserContext();
 }
 
-content::GeolocationDelegate*
-BlimpContentBrowserClient::CreateGeolocationDelegate() {
-  return new BlimpGeolocationDelegate();
-}
-
 void BlimpContentBrowserClient::ExposeInterfacesToRenderer(
     shell::InterfaceRegistry* registry,
     content::RenderProcessHost* render_process_host) {
diff --git a/blimp/engine/app/blimp_content_browser_client.h b/blimp/engine/app/blimp_content_browser_client.h
index 7263056..24ae734 100644
--- a/blimp/engine/app/blimp_content_browser_client.h
+++ b/blimp/engine/app/blimp_content_browser_client.h
@@ -36,8 +36,6 @@
       shell::InterfaceRegistry* registry,
       content::RenderProcessHost* render_process_host) override;
 
-  content::GeolocationDelegate* CreateGeolocationDelegate() override;
-
   BlimpBrowserContext* GetBrowserContext();
 
  private:
diff --git a/blimp/engine/app/blimp_engine_crash_keys.cc b/blimp/engine/app/blimp_engine_crash_keys.cc
index dade52bc..db8460bb 100644
--- a/blimp/engine/app/blimp_engine_crash_keys.cc
+++ b/blimp/engine/app/blimp_engine_crash_keys.cc
@@ -75,10 +75,6 @@
 
       // Temporary for https://crbug.com/616149.
       { "existing_extension_pref_value_type", crash_keys::kSmallSize },
-
-      // Temporary for https://crbug.com/625040
-      { "swdh_not_handled_message_type", crash_keys::kMediumSize },
-      { "swdh_not_handled_worker_status", crash_keys::kMediumSize },
     };
 
   return base::debug::InitCrashKeys(engine_keys, arraysize(engine_keys),
diff --git a/blimp/engine/testing/Dockerfile b/blimp/engine/testing/Dockerfile
index 71c87fc..cdce8fcd 100644
--- a/blimp/engine/testing/Dockerfile
+++ b/blimp/engine/testing/Dockerfile
@@ -4,15 +4,15 @@
 # Engine itself.
 FROM base:latest
 
-RUN mkdir -p /out/test/
+RUN mkdir -p /blimp/
 
-# The glob below expands to all files, but does not add directories
-# recursively.
-# Test binaries assume src directory is 2 levels down. While this behavior can
-# be changed with flags, the directory structure is set up to minimize
-# potential problems with initial integration.
-ADD * /out/test/
+RUN useradd -ms /bin/bash blimp_user
 
-RUN chown -R blimp_user /out/test/
+# Put all the Blimp related files in /blimp so they are kept separate from
+# the OS files. Using '.' instead of '*' ensures directory structure is
+# maintained since ADD only copies the contents of directories.
+ADD . /blimp/
+
+RUN chown -R blimp_user /blimp
 
 USER blimp_user
\ No newline at end of file
diff --git a/blimp/tools/create-bundle.py b/blimp/tools/create-bundle.py
index 5aab7fcb..e7d77888 100755
--- a/blimp/tools/create-bundle.py
+++ b/blimp/tools/create-bundle.py
@@ -15,19 +15,22 @@
 import subprocess
 import sys
 
-def ReadDependencies(manifest):
-  """Read the manifest and return the list of dependencies.
+def ReadDependencies(manifest, relative_path):
+  """Returns a list of dependencies based on the specified manifest file.
+  The returned dependencies will be made relative to |relative_path| and
+  normalized.
   :raises IOError: if the manifest could not be read.
   """
-  deps = []
+  dependency_list = []
   with open(manifest) as f:
     for line in f.readlines():
       # Strip comments.
-      dep = line.partition('#')[0].strip()
+      dependency = line.partition('#')[0].strip()
       # Ignore empty strings.
-      if dep:
-        deps.append(dep)
-  return deps
+      if dependency:
+        dependency = os.path.normpath(os.path.join(relative_path, dependency))
+        dependency_list.append(dependency)
+  return dependency_list
 
 def main():
   parser = argparse.ArgumentParser(description=__doc__)
@@ -50,9 +53,19 @@
                       help=('name and path of bundle to create'),
                       required=True,
                       metavar='FILE')
+  parser.add_argument('--tar-contents-rooted-in',
+                      help=('optional path prefix to use inside the resulting '
+                            'tar file'),
+                      required=False,
+                      metavar='DIR')
   args = parser.parse_args()
 
-  deps = ReadDependencies(args.manifest)
+  dependencies_path = args.build_dir
+  if args.tar_contents_rooted_in:
+    dependencies_path = args.tar_contents_rooted_in
+  relative_path = os.path.relpath(args.build_dir, dependencies_path)
+
+  dependency_list = ReadDependencies(args.manifest, relative_path)
 
   try:
     env = os.environ.copy()
@@ -65,7 +78,7 @@
         # use as part of a "docker build". That is group readable with
         # executable files also being group executable.
         "--mode=g+rX",
-        "-C", args.build_dir] + deps
+        "-C", dependencies_path] + dependency_list
     for f in args.filelist:
       dirname, basename = os.path.split(f)
       subprocess_args.extend(["-C", dirname, basename])
diff --git a/build/android/pylib/base/base_test_result.py b/build/android/pylib/base/base_test_result.py
index b8812656..dabe132b 100644
--- a/build/android/pylib/base/base_test_result.py
+++ b/build/android/pylib/base/base_test_result.py
@@ -180,7 +180,8 @@
     Args:
       results: An instance of TestRunResults.
     """
-    assert isinstance(results, TestRunResults)
+    assert isinstance(results, TestRunResults), (
+           'Expected TestRunResult object: %s' % type(results))
     with self._results_lock:
       # pylint: disable=W0212
       self._results.update(results._results)
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 91f40810..79c79a42d 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1487,7 +1487,10 @@
   if (is_win) {
     import("//build/toolchain/goma.gni")
     if (use_goma) {
-      cflags = [ "/Z7" ]  # No PDB file
+      # Disable symbols during goma compilation because otherwise the redundant
+      # debug information (repeated in every .obj file) makes linker memory
+      # consumption and link times unsustainable (crbug.com/630074).
+      cflags = []
     } else {
       cflags = [ "/Zi" ]  # Produce PDB file, no edit and continue.
     }
diff --git a/build/config/ios/BUILD.gn b/build/config/ios/BUILD.gn
index 3ccffab..6b8896c 100644
--- a/build/config/ios/BUILD.gn
+++ b/build/config/ios/BUILD.gn
@@ -41,3 +41,18 @@
 config("ios_dynamic_flags") {
   ldflags = [ "-Wl,-ObjC" ]  # Always load Objective-C categories and class.
 }
+
+config("xctest_config") {
+  common_flags = [
+    "-F",
+    "$ios_sdk_platform_path/Developer/Library/Frameworks",
+  ]
+
+  cflags = common_flags
+  ldflags = common_flags
+
+  libs = [
+    "Foundation.framework",
+    "XCTest.framework",
+  ]
+}
diff --git a/build/config/ios/Host-Info.plist b/build/config/ios/Host-Info.plist
new file mode 100644
index 0000000..c306faa
--- /dev/null
+++ b/build/config/ios/Host-Info.plist
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.chromium.test.ios_web_shell_test_host</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSAppTransportSecurity</key>
+	<dict>
+		<key>NSAllowsArbitraryLoads</key>
+		<true/>
+	</dict>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UILaunchImages</key>
+	<array>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>7.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Portrait</string>
+			<key>UILaunchImageSize</key>
+			<string>{320, 480}</string>
+		</dict>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>7.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Portrait</string>
+			<key>UILaunchImageSize</key>
+			<string>{320, 568}</string>
+		</dict>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>8.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Portrait</string>
+			<key>UILaunchImageSize</key>
+			<string>{375, 667}</string>
+		</dict>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>8.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Portrait</string>
+			<key>UILaunchImageSize</key>
+			<string>{414, 736}</string>
+		</dict>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>8.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Landscape</string>
+			<key>UILaunchImageSize</key>
+			<string>{414, 736}</string>
+		</dict>
+	</array>
+	<key>UILaunchImages~ipad</key>
+	<array>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>7.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Portrait</string>
+			<key>UILaunchImageSize</key>
+			<string>{768, 1024}</string>
+		</dict>
+		<dict>
+			<key>UILaunchImageMinimumOSVersion</key>
+			<string>7.0</string>
+			<key>UILaunchImageName</key>
+			<string>Default</string>
+			<key>UILaunchImageOrientation</key>
+			<string>Landscape</string>
+			<key>UILaunchImageSize</key>
+			<string>{768, 1024}</string>
+		</dict>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>
diff --git a/build/config/ios/Module-Info.plist b/build/config/ios/Module-Info.plist
new file mode 100644
index 0000000..6131774
--- /dev/null
+++ b/build/config/ios/Module-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIdentifier</key>
+  <string>org.chromium.test.ios_web_shell_test_host.ios_web_shell_test</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>1.0</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+</dict>
+</plist>
diff --git a/build/config/ios/codesign.py b/build/config/ios/codesign.py
index dee1cc2..fb3817a 100644
--- a/build/config/ios/codesign.py
+++ b/build/config/ios/codesign.py
@@ -206,7 +206,21 @@
       key=lambda p: len(p.application_identifier_pattern))
 
 
-def CodeSignBundle(binary, bundle, args):
+def InstallFramework(framework_path, bundle, args):
+  """Install framework from |framework_path| to |bundle| and code-re-sign it."""
+  installed_framework_path = os.path.join(
+      bundle.path, 'Frameworks', os.path.basename(framework_path))
+
+  if os.path.exists(installed_framework_path):
+    shutil.rmtree(installed_framework_path)
+
+  shutil.copytree(framework_path, installed_framework_path)
+
+  framework_bundle = Bundle(installed_framework_path)
+  CodeSignBundle(framework_bundle.binary_path, framework_bundle, args, True)
+
+
+def CodeSignBundle(binary, bundle, args, preserve=False):
   """Cryptographically signs bundle.
 
   Args:
@@ -219,18 +233,29 @@
       bundle, args.provisioning_profile_short_name)
   provisioning_profile.Install(bundle)
 
-  signature_file = os.path.join(bundle.path, '_CodeSignature', 'CodeResources')
-  if os.path.isfile(signature_file):
-    os.unlink(signature_file)
-
-  shutil.copy(binary, bundle.binary_path)
-
-  if args.preserve:
-    subprocess.check_call([
+  if preserve:
+    process = subprocess.Popen([
         'xcrun', 'codesign', '--force', '--sign', args.identity,
         '--deep', '--preserve-metadata=identifier,entitlements',
-        '--timestamp=none', bundle.path])
+        '--timestamp=none', bundle.path], stderr=subprocess.PIPE)
+    _, stderr = process.communicate()
+    if process.returncode:
+      sys.stderr.write(stderr)
+      sys.exit(process.returncode)
+    for line in stderr.splitlines():
+      # Ignore expected warning as we are replacing the signature on purpose.
+      if not line.endswith(': replacing existing signature'):
+        sys.stderr.write(line + '\n')
   else:
+    signature_file = os.path.join(
+        bundle.path, '_CodeSignature', 'CodeResources')
+    if os.path.isfile(signature_file):
+      os.unlink(signature_file)
+
+    if os.path.isfile(bundle.binary_path):
+      os.unlink(bundle.binary_path)
+    shutil.copy(binary, bundle.binary_path)
+
     entitlements = Entitlements(args.entitlements_path)
     entitlements.LoadDefaults(provisioning_profile.entitlements)
     entitlements.ExpandVariables({
@@ -261,16 +286,19 @@
   parser.add_argument(
       '--identity', '-i', required=True,
       help='identity to use to codesign')
-  group = parser.add_mutually_exclusive_group(required=True)
-  group.add_argument(
+  parser.add_argument(
       '--entitlements', '-e', dest='entitlements_path',
       help='path to the entitlements file to use')
-  group.add_argument(
-      '--deep', '-d', action='store_true', default=False, dest='preserve',
-      help='deep signature (default: %(default)s)')
+  parser.add_argument(
+      '--framework', '-F', action='append', default=[], dest="frameworks",
+      help='install and resign system framework')
   args = parser.parse_args()
 
-  CodeSignBundle(args.binary, Bundle(args.path), args)
+  bundle = Bundle(args.path)
+  for framework in args.frameworks:
+    InstallFramework(framework, bundle, args)
+
+  CodeSignBundle(args.binary, bundle, args)
 
 
 if __name__ == '__main__':
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index 843d4017..5fdd640 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -158,7 +158,9 @@
       forward_variables_from(invoker,
                              "*",
                              [
+                               "bundle_deps",
                                "bundle_extension",
+                               "extra_system_frameworks",
                                "entitlements_path",
                                "extra_substitutions",
                                "info_plist",
@@ -236,7 +238,9 @@
       forward_variables_from(invoker,
                              "*",
                              [
+                               "bundle_deps",
                                "bundle_extension",
+                               "extra_system_frameworks",
                                "data_deps",
                                "entitlements_path",
                                "extra_substitutions",
@@ -356,6 +360,16 @@
       }
     }
 
+    if (!ios_enable_code_signing && defined(invoker.extra_system_frameworks)) {
+      bundle_data(_target_name + "_extra_system_frameworks") {
+        visibility = [ ":$_target_name" ]
+        sources = invoker.extra_system_frameworks
+        outputs = [
+          "{{bundle_resources_dir}}/Frameworks/{{source_file_part}}",
+        ]
+      }
+    }
+
     create_bundle(target_name) {
       forward_variables_from(invoker,
                              [
@@ -378,6 +392,12 @@
         }
       } else {
         deps += [ ":$_bundle_data_executable" ]
+        if (defined(invoker.extra_system_frameworks)) {
+          deps += [ ":${_target_name}_extra_system_frameworks" ]
+        }
+      }
+      if (defined(invoker.bundle_deps)) {
+        deps += invoker.bundle_deps
       }
 
       if (use_ios_simulator) {
@@ -420,12 +440,26 @@
           "$bundle_root_dir/_CodeSignature/CodeResources",
           "$bundle_root_dir/embedded.mobileprovision",
         ]
+        if (defined(invoker.extra_system_frameworks)) {
+          foreach(_framework, invoker.extra_system_frameworks) {
+            code_signing_outputs += [ "$bundle_root_dir/Frameworks/" +
+                                      get_path_info(_framework, "name") ]
+          }
+        }
         code_signing_args = [
           "-i=" + ios_code_signing_identity,
           "-b=" + rebase_path("$target_out_dir/$_output_name", root_build_dir),
           "-e=" + rebase_path(_entitlements_path, root_build_dir),
           rebase_path(bundle_root_dir, root_build_dir),
         ]
+        if (defined(invoker.extra_system_frameworks)) {
+          # All framework in extra_system_frameworks are expected to be
+          # system framework and the path to be already system absolute
+          # so do not use rebase_path here.
+          foreach(_framework, invoker.extra_system_frameworks) {
+            code_signing_args += [ "-F=" + _framework ]
+          }
+        }
       }
     }
   }
@@ -462,6 +496,9 @@
   if (defined(invoker.product_type)) {
     assert(invoker.product_type != "", "mark product_type as used")
   }
+  if (defined(invoker.bundle_deps)) {
+    assert(invoker.bundle_deps != [], "mark bundle_deps as used")
+  }
 }
 
 set_defaults("ios_app_bundle") {
@@ -768,16 +805,42 @@
       }
 
       config(_framework_public_config) {
-        visibility = [ ":$_framework_public_config" ]
-        common_flags = [ "-F" + rebase_path("$root_out_dir/.", root_build_dir) ]
-        cflags_objc = common_flags
-        cflags_objcc = common_flags
-
         # The link settings are inherited from the framework_bundle config.
+        cflags = [
+          "-F",
+          rebase_path("$root_out_dir/.", root_build_dir),
+        ]
       }
     }
   }
 
+  if (!_is_fat_build || _is_fat_build_main_target) {
+    _info_plist_target = _target_name + "_info_plist"
+    _info_plist_bundle = _target_name + "_info_plist_bundle"
+    ios_info_plist(_info_plist_target) {
+      visibility = [ ":$_info_plist_bundle" ]
+      executable_name = _output_name
+      forward_variables_from(invoker,
+                             [
+                               "extra_substitutions",
+                               "info_plist",
+                               "info_plist_target",
+                             ])
+    }
+
+    bundle_data(_info_plist_bundle) {
+      visibility = [ ":$_framework_target" ]
+      forward_variables_from(invoker, [ "testonly" ])
+      sources = get_target_outputs(":$_info_plist_target")
+      outputs = [
+        "{{bundle_root_dir}}/Info.plist",
+      ]
+      public_deps = [
+        ":$_info_plist_target",
+      ]
+    }
+  }
+
   framework_bundle(_framework_target) {
     forward_variables_from(invoker,
                            "*",
@@ -788,6 +851,13 @@
                            ])
     output_name = _output_name
 
+    if (!_is_fat_build || _is_fat_build_main_target) {
+      if (!defined(bundle_deps)) {
+        bundle_deps = []
+      }
+      bundle_deps += [ ":$_info_plist_bundle" ]
+    }
+
     if (_has_public_headers) {
       if (!defined(public_configs)) {
         public_configs = []
@@ -799,6 +869,7 @@
       visibility = [
         ":$_target_name$_toolchain_suffix",
         ":$_target_name+link$_toolchain_suffix",
+        ":$_target_name+bundle$_toolchain_suffix",
       ]
       configs += [ ":$_headers_map_config$_toolchain_suffix" ]
 
@@ -843,8 +914,305 @@
       ]
     }
   }
+
+  if (!_is_fat_build || _is_fat_build_main_target) {
+    bundle_data(_target_name + "+bundle") {
+      forward_variables_from(invoker,
+                             [
+                               "testonly",
+                               "visibility",
+                             ])
+      public_deps = [
+        ":$_framework_target",
+      ]
+      sources = [
+        "$root_out_dir/$_output_name.framework",
+      ]
+      outputs = [
+        "{{bundle_resources_dir}}/Frameworks/$_output_name.framework",
+      ]
+    }
+  }
 }
 
 set_defaults("ios_framework_bundle") {
   configs = default_shared_library_configs
 }
+
+# For Chrome on iOS we want to run XCTests for all our build configurations
+# (Debug, Release, ...). In addition, the symbols visibility is configured to
+# private by default. To simplify testing with those constraints, our tests are
+# compiled in the TEST_HOST target instead of the .xctest bundle.
+template("ios_xctest_test") {
+  _target_name = target_name
+  _output_name = target_name
+  if (defined(invoker.output_name)) {
+    _output_name = invoker.output_name
+  }
+
+  _is_fat_build = additional_toolchains != []
+  if (_is_fat_build) {
+    _is_fat_build_main_target = current_toolchain == default_toolchain
+  }
+
+  _xctest_target = _target_name
+  _xctest_output = _output_name
+
+  _host_target = _target_name + "_host"
+  _host_output = _output_name + "_host"
+
+  if (_is_fat_build && !_is_fat_build_main_target) {
+    loadable_module(_xctest_target) {
+      visibility = [ ":${_xctest_target}_loadable_module($default_toolchain)" ]
+      sources = [
+        "//build/config/ios/xctest_shell.mm",
+      ]
+      configs += [ "//build/config/ios:xctest_config" ]
+
+      output_name = _xctest_output
+      output_extension = ""
+    }
+  } else {
+    _xctest_info_plist_target = _xctest_target + "_info_plist"
+    _xctest_info_plist_bundle = _xctest_target + "_info_plist_bundle"
+    ios_info_plist(_xctest_info_plist_target) {
+      visibility = [ ":$_xctest_info_plist_bundle" ]
+      info_plist = "//build/config/ios/Module-Info.plist"
+      executable_name = _output_name
+    }
+
+    bundle_data(_xctest_info_plist_bundle) {
+      visibility = [ ":$_xctest_target" ]
+      public_deps = [
+        ":$_xctest_info_plist_target",
+      ]
+      sources = get_target_outputs(":$_xctest_info_plist_target")
+      outputs = [
+        "{{bundle_root_dir}}/Info.plist",
+      ]
+    }
+
+    _xctest_loadable_module_target = _xctest_target + "_loadable_module"
+    _xctest_loadable_module_path = "$target_out_dir/$_xctest_output"
+
+    if (!ios_enable_code_signing) {
+      _xctest_loadable_module_bundle =
+          _xctest_target + "_loadable_module_bundle"
+      _xctest_loadable_module_visibility =
+          [ ":$_xctest_loadable_module_bundle" ]
+    } else {
+      _xctest_loadable_module_visibility = [ ":$_xctest_target" ]
+    }
+
+    if (_is_fat_build) {
+      _xctest_lipo_loadable_module_target = _xctest_loadable_module_target
+      _xctest_lipo_loadable_module_visibility =
+          _xctest_loadable_module_visibility
+      _arch_xctest_loadable_module_path =
+          "$target_out_dir/$current_cpu/$_xctest_output"
+
+      _xctest_loadable_module_visibility = []
+      _xctest_loadable_module_visibility =
+          [ ":$_xctest_lipo_loadable_module_target" ]
+      _xctest_loadable_module_target = _xctest_target + "_arch_loadable_module"
+    }
+
+    loadable_module(_xctest_loadable_module_target) {
+      visibility = _xctest_loadable_module_visibility
+      sources = [
+        "//build/config/ios/xctest_shell.mm",
+      ]
+      configs += [ "//build/config/ios:xctest_config" ]
+
+      if (_is_fat_build) {
+        output_name =
+            rebase_path(_arch_xctest_loadable_module_path, root_out_dir)
+      } else {
+        output_name = rebase_path(_xctest_loadable_module_path, root_out_dir)
+      }
+
+      output_prefix_override = true
+      output_extension = ""
+    }
+
+    if (_is_fat_build) {
+      action(_xctest_lipo_loadable_module_target) {
+        visibility = _xctest_lipo_loadable_module_visibility
+        script = "//build/toolchain/mac/linker_driver.py"
+        outputs = [
+          _xctest_loadable_module_path,
+        ]
+        inputs = [
+          _arch_xctest_loadable_module_path,
+        ]
+        deps = [
+          ":$_xctest_loadable_module_target",
+        ]
+        foreach(_additional_toolchain, additional_toolchains) {
+          _additional_toolchain_target = "$_target_name($_additional_toolchain)"
+          deps += [ ":$_additional_toolchain_target" ]
+          inputs += [ get_label_info(_additional_toolchain_target,
+                                     "root_out_dir") + "/$_xctest_output" ]
+        }
+        args = [
+                 "xcrun",
+                 "lipo",
+                 "-create",
+                 "-output",
+                 rebase_path(outputs[0], root_build_dir),
+               ] + rebase_path(inputs, root_build_dir)
+
+        if (enable_dsyms) {
+          outputs += [ "$root_out_dir/$_xctest_output.dSYM/" ]
+          args +=
+              [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
+        }
+
+        if (enable_stripping) {
+          # Check whether //build/config/mac:strip_all has been removed from
+          # the configs variable (as this is how stripping is disabled for a
+          # single target).
+          _strip_all_in_config = false
+          if (defined(invoker.configs)) {
+            foreach(_config, invoker.configs) {
+              if (_config == "//build/config/mac:strip_all") {
+                _strip_all_in_config = true
+              }
+            }
+          }
+
+          if (_strip_all_in_config) {
+            args += [ "-Wcrl,strip,-x,-S" ]
+
+            if (save_unstripped_output) {
+              outputs += [ outputs[0] + ".unstripped" ]
+              args += [ "-Wcrl,unstripped," +
+                        rebase_path(get_path_info(outputs[0], "dir"),
+                                    root_build_dir) ]
+            }
+          }
+        }
+      }
+    }
+
+    if (!ios_enable_code_signing) {
+      bundle_data(_xctest_loadable_module_bundle) {
+        visibility = [ ":$_xctest_target" ]
+        if (_is_fat_build) {
+          public_deps = [
+            ":$_xctest_lipo_loadable_module_target",
+          ]
+        } else {
+          public_deps = [
+            ":$_xctest_loadable_module_target",
+          ]
+        }
+        sources = [
+          "$target_out_dir/$_xctest_output",
+        ]
+        outputs = [
+          "{{bundle_root_dir}}/$_xctest_output",
+        ]
+      }
+    }
+
+    _xctest_bundle = _xctest_target + "_bundle"
+
+    create_bundle(_xctest_target) {
+      visibility = [ ":$_xctest_bundle" ]
+      product_type = "com.apple.product-type.bundle.unit-test"
+      deps = [
+        ":$_xctest_info_plist_bundle",
+      ]
+      bundle_root_dir = "$root_out_dir/$_xctest_output.xctest"
+
+      if (!ios_enable_code_signing) {
+        deps += [ ":$_xctest_loadable_module_bundle" ]
+      } else {
+        if (_is_fat_build) {
+          deps += [ ":$_xctest_lipo_loadable_module_target" ]
+        } else {
+          deps += [ ":$_xctest_loadable_module_target" ]
+        }
+
+        _entitlements_path = "$ios_sdk_path/Entitlements.plist"
+        if (defined(invoker.entitlements_path)) {
+          _entitlements_path = invoker.entitlements_path
+        }
+
+        code_signing_script = "//build/config/ios/codesign.py"
+        code_signing_sources = [
+          _entitlements_path,
+          "$target_out_dir/$_xctest_output",
+        ]
+        code_signing_outputs = [
+          "$bundle_root_dir/$_xctest_output",
+          "$bundle_root_dir/_CodeSignature/CodeResources",
+          "$bundle_root_dir/embedded.mobileprovision",
+        ]
+        code_signing_args = [
+          "-i=" + ios_code_signing_identity,
+          "-b=" +
+              rebase_path("$target_out_dir/$_xctest_output", root_build_dir),
+          "-e=" + rebase_path(_entitlements_path, root_build_dir),
+          rebase_path(bundle_root_dir, root_build_dir),
+        ]
+      }
+    }
+
+    bundle_data(_xctest_bundle) {
+      visibility = [ ":$_host_target" ]
+      public_deps = [
+        ":$_xctest_target",
+      ]
+      sources = [
+        "$root_out_dir/$_xctest_output.xctest",
+      ]
+      outputs = [
+        "{{bundle_plugins_dir}}/$_xctest_output.xctest",
+      ]
+    }
+  }
+
+  ios_app_bundle(_host_target) {
+    forward_variables_from(invoker, "*", [ "testonly" ])
+
+    testonly = true
+    output_name = _host_output
+    info_plist = "//build/config/ios/Host-Info.plist"
+    configs += [ "//build/config/ios:xctest_config" ]
+
+    # Xcode needs those two framework installed in the application (and signed)
+    # for the XCTest to run, so install them using extra_system_frameworks.
+    _ios_platform_library = "$ios_sdk_platform_path/Developer/Library"
+    extra_system_frameworks = [
+      "$_ios_platform_library/Frameworks/XCTest.framework",
+      "$_ios_platform_library/PrivateFrameworks/IDEBundleInjection.framework",
+    ]
+
+    if (!_is_fat_build || _is_fat_build_main_target) {
+      if (!defined(bundle_deps)) {
+        bundle_deps = []
+      }
+      bundle_deps += [ ":$_xctest_bundle" ]
+    }
+
+    if (!defined(ldflags)) {
+      ldflags = []
+    }
+    ldflags += [
+      "-Xlinker",
+      "-rpath",
+      "-Xlinker",
+      "@executable_path/Frameworks",
+      "-Xlinker",
+      "-rpath",
+      "-Xlinker",
+      "@loader_path/Frameworks",
+    ]
+  }
+}
+
+set_defaults("ios_xctest_test") {
+  configs = default_executable_configs
+}
diff --git a/build/config/ios/xctest_shell.mm b/build/config/ios/xctest_shell.mm
new file mode 100644
index 0000000..dcf5bad
--- /dev/null
+++ b/build/config/ios/xctest_shell.mm
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium 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 <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+// For Chrome on iOS we want to run EarlGrey tests (that are XCTests) for all
+// our build configurations (Debug, Release, ...). In addition, the symbols
+// visibility is configured to private by default. To simplify testing with
+// those constraints, our tests are compiled in the TEST_HOST target instead
+// of the .xctest bundle that all link against this single test (just there to
+// ensure that the bundle is not empty).
+
+@interface XCTestShellEmptyClass : NSObject
+@end
+
+@implementation XCTestShellEmptyClass
+@end
diff --git a/build/config/mac/base_rules.gni b/build/config/mac/base_rules.gni
index 151c235..3e8f5b3 100644
--- a/build/config/mac/base_rules.gni
+++ b/build/config/mac/base_rules.gni
@@ -244,8 +244,11 @@
                              "*",
                              [
                                "assert_no_deps",
+                               "bundle_deps",
+                               "code_signing_enabled",
                                "data_deps",
                                "info_plist",
+                               "info_plist_target",
                                "output_name",
                              ])
       if (defined(visibility)) {
@@ -267,7 +270,17 @@
         ":$_target_name($default_toolchain)",
       ]
     }
+
+    if (defined(invoker.bundle_deps)) {
+      assert(invoker.bundle_deps != [], "mark bundle_deps as used")
+    }
   } else {
+    _code_signing_enabled = is_ios && ios_enable_code_signing
+    if (defined(invoker.code_signing_enabled)) {
+      _code_signing_enabled =
+          invoker.code_signing_enabled && _code_signing_enabled
+    }
+
     # If the framework is unversioned, the final _target_name will be the
     # create_bundle(_framework_target), otherwise an action with the name
     # _target_name will depends on the the create_bundle() in order to prepare
@@ -282,8 +295,14 @@
     }
 
     _link_shared_library_target = target_name + "_shared_library"
-    _shared_library_bundle_data = target_name + "_shared_library_bundle_data"
-    _link_shared_library_visibility = [ ":$_shared_library_bundle_data" ]
+    _shared_library_dir = "$target_out_dir/$_link_shared_library_target"
+
+    if (_code_signing_enabled) {
+      _link_shared_library_visibility = [ ":$_framework_target" ]
+    } else {
+      _shared_library_bundle_data = target_name + "_shared_library_bundle_data"
+      _link_shared_library_visibility = [ ":$_shared_library_bundle_data" ]
+    }
 
     if (_is_fat_build) {
       _lipo_shared_library_target = _link_shared_library_target
@@ -292,6 +311,9 @@
       _link_shared_library_visibility = []
       _link_shared_library_visibility = [ ":$_lipo_shared_library_target" ]
       _link_shared_library_target = target_name + "_arch_shared_library"
+
+      _arch_shared_library_dir = "$target_out_dir/$_link_shared_library_target"
+      _shared_library_dir = "$target_out_dir/$_lipo_shared_library_target"
     }
 
     shared_library(_link_shared_library_target) {
@@ -299,6 +321,8 @@
                              "*",
                              [
                                "assert_no_deps",
+                               "bundle_deps",
+                               "code_signing_enabled",
                                "data_deps",
                                "info_plist",
                                "output_name",
@@ -308,7 +332,12 @@
       output_name = _output_name
       output_prefix_override = true
       output_extension = ""
-      output_dir = "$target_out_dir/$_link_shared_library_target"
+
+      if (!_is_fat_build) {
+        output_dir = _shared_library_dir
+      } else {
+        output_dir = _arch_shared_library_dir
+      }
     }
 
     if (_is_fat_build) {
@@ -317,10 +346,10 @@
         visibility = _lipo_shared_library_visibility
         script = "//build/toolchain/mac/linker_driver.py"
         outputs = [
-          "$target_out_dir/$_lipo_shared_library_target/$_output_name",
+          "$_shared_library_dir/$_output_name",
         ]
         inputs = [
-          "$target_out_dir/$_link_shared_library_target/$_output_name",
+          "$_arch_shared_library_dir/$_output_name",
         ]
         deps = [
           ":$_link_shared_library_target",
@@ -372,26 +401,25 @@
       }
     }
 
-    bundle_data(_shared_library_bundle_data) {
-      visibility = [ ":$_framework_target" ]
-      forward_variables_from(invoker, [ "testonly" ])
-      outputs = [
-        "{{bundle_executable_dir}}/$_output_name",
-      ]
-      if (_is_fat_build) {
+    if (!_code_signing_enabled) {
+      bundle_data(_shared_library_bundle_data) {
+        visibility = [ ":$_framework_target" ]
+        forward_variables_from(invoker, [ "testonly" ])
         sources = [
-          "$target_out_dir/$_lipo_shared_library_target/$_output_name",
+          "$_shared_library_dir/$_output_name",
         ]
-        public_deps = [
-          ":$_lipo_shared_library_target",
+        outputs = [
+          "{{bundle_executable_dir}}/$_output_name",
         ]
-      } else {
-        sources = [
-          "$target_out_dir/$_link_shared_library_target/$_output_name",
-        ]
-        public_deps = [
-          ":$_link_shared_library_target",
-        ]
+        if (_is_fat_build) {
+          public_deps = [
+            ":$_lipo_shared_library_target",
+          ]
+        } else {
+          public_deps = [
+            ":$_link_shared_library_target",
+          ]
+        }
       }
     }
 
@@ -400,7 +428,10 @@
       # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs
       # and include_dirs to avoid duplicate values on the command-line.
       visibility = [ ":$_framework_target" ]
-      ldflags = [ "-F" + rebase_path("$root_out_dir/.", root_build_dir) ]
+      ldflags = [
+        "-F",
+        rebase_path("$root_out_dir/.", root_build_dir),
+      ]
       lib_dirs = [ root_out_dir ]
       libs = [ _framework_name ]
     }
@@ -423,14 +454,58 @@
         }
       }
 
-      if (!defined(public_deps)) {
-        public_deps = []
+      if (!_code_signing_enabled) {
+        if (!defined(public_deps)) {
+          public_deps = []
+        }
+        public_deps += [ ":$_shared_library_bundle_data" ]
+
+        if (defined(invoker.bundle_deps)) {
+          if (!defined(deps)) {
+            deps = []
+          }
+          deps += invoker.bundle_deps
+        }
       }
-      public_deps += [ ":$_shared_library_bundle_data" ]
 
       bundle_root_dir = _framework_root_dir
       bundle_resources_dir = "$bundle_root_dir/Resources"
       bundle_executable_dir = "$bundle_root_dir"
+
+      if (_code_signing_enabled) {
+        if (!defined(deps)) {
+          deps = []
+        }
+
+        if (_is_fat_build) {
+          deps += [ ":$_lipo_shared_library_target" ]
+        } else {
+          deps += [ ":$_link_shared_library_target" ]
+        }
+
+        _entitlements_path = "$ios_sdk_path/Entitlements.plist"
+        if (defined(invoker.entitlements_path)) {
+          _entitlements_path = invoker.entitlements_path
+        }
+
+        code_signing_script = "//build/config/ios/codesign.py"
+        code_signing_sources = [
+          _entitlements_path,
+          "$_shared_library_dir/$_output_name",
+        ]
+        code_signing_outputs = [
+          "$bundle_root_dir/$_output_name",
+          "$bundle_root_dir/_CodeSignature/CodeResources",
+          "$bundle_root_dir/embedded.mobileprovision",
+        ]
+        code_signing_args = [
+          "-i=" + ios_code_signing_identity,
+          "-b=" +
+              rebase_path("$_shared_library_dir/$_output_name", root_build_dir),
+          "-e=" + rebase_path(_entitlements_path, root_build_dir),
+          rebase_path(bundle_root_dir, root_build_dir),
+        ]
+      }
     }
 
     if (defined(_framework_version)) {
@@ -459,13 +534,17 @@
     group(_target_name + "+link") {
       forward_variables_from(invoker,
                              [
-                               "visibility",
+                               "public_configs",
                                "testonly",
+                               "visibility",
                              ])
       public_deps = [
         ":$_target_name",
       ]
-      public_configs = [ ":$_framework_public_config" ]
+      if (!defined(public_configs)) {
+        public_configs = []
+      }
+      public_configs += [ ":$_framework_public_config" ]
     }
   }
 }
diff --git a/build/secondary/testing/gmock/BUILD.gn b/build/secondary/testing/gmock/BUILD.gn
index 6298241..1a5b76a 100644
--- a/build/secondary/testing/gmock/BUILD.gn
+++ b/build/secondary/testing/gmock/BUILD.gn
@@ -4,7 +4,10 @@
 
 config("gmock_config") {
   # Gmock headers need to be able to find themselves.
-  include_dirs = [ "include" ]
+  include_dirs = [
+    "//testing/gmock_custom",
+    "include",
+  ]
 }
 
 static_library("gmock") {
diff --git a/build/secondary/testing/gtest/BUILD.gn b/build/secondary/testing/gtest/BUILD.gn
index 16423d0..a8cab244 100644
--- a/build/secondary/testing/gtest/BUILD.gn
+++ b/build/secondary/testing/gtest/BUILD.gn
@@ -14,9 +14,6 @@
     # In order to allow regex matches in gtest to be shared between Windows
     # and other systems, we tell gtest to always use it's internal engine.
     "GTEST_HAS_POSIX_RE=0",
-
-    # Chrome doesn't support / require C++11, yet.
-    "GTEST_LANG_CXX11=0",
   ]
 
   # Gtest headers need to be able to find themselves.
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index daf758b..00641376b 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -76,6 +76,11 @@
   aar_path = "$lib_path/$lib_name/$lib_version/$lib_name-$lib_version.aar"
 }
 
+android_aar_prebuilt("android_support_vector_drawable_java") {
+  lib_name = "support-vector-drawable"
+  aar_path = "$lib_path/$lib_name/$lib_version/$lib_name-$lib_version.aar"
+}
+
 android_aar_prebuilt("android_support_v7_appcompat_java_internal") {
   lib_name = "appcompat-v7"
   aar_path = "$lib_path/$lib_name/$lib_version/$lib_name-$lib_version.aar"
@@ -85,6 +90,7 @@
   deps = [
     ":android_support_v4_java",
     ":android_support_v7_appcompat_java_internal",
+    ":android_support_vector_drawable_java",
   ]
 }
 
diff --git a/build/util/version.gni b/build/util/version.gni
index 6542341..dd28d7a 100644
--- a/build/util/version.gni
+++ b/build/util/version.gni
@@ -17,15 +17,11 @@
 # all values we need at once.
 _version_dictionary_template = "full = \"@MAJOR@.@MINOR@.@BUILD@.@PATCH@\" " +
                                "major = \"@MAJOR@\" minor = \"@MINOR@\" " +
-                               "build = \"@BUILD@\" patch = \"@PATCH@\" " +
-                               "remoting = \"@REMOTING_PATCH\" "
+                               "build = \"@BUILD@\" patch = \"@PATCH@\" "
 
 # The file containing the Chrome version number.
 chrome_version_file = "//chrome/VERSION"
 
-# The file containing the Chromoting version number.
-remoting_version_file = "//remoting/VERSION"
-
 _result = exec_script("version.py",
                       [
                         "-f",
@@ -44,7 +40,6 @@
 chrome_version_minor = _result.minor
 chrome_version_build = _result.build
 chrome_version_patch = _result.patch
-remoting_version_patch = _result.remoting
 
 if (is_mac) {
   _result = exec_script("version.py",
diff --git a/build_overrides/v8.gni b/build_overrides/v8.gni
index af9d9cc..668c0c7 100644
--- a/build_overrides/v8.gni
+++ b/build_overrides/v8.gni
@@ -9,11 +9,6 @@
 # TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456.
 enable_correct_v8_arch = false
 
-v8_use_external_startup_data = !is_ios
-
-# Turns on compiler optimizations in V8 in Debug build.
-v8_optimized_debug = true
-
 # V8 extras
 # Adding V8 extras files requires API owners review
 # Be sure to synchronize with build/common.gypi
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index d580155..a7711b8 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -711,6 +711,10 @@
     "test/skia_common.h",
     "test/solid_color_content_layer_client.cc",
     "test/solid_color_content_layer_client.h",
+    "test/stub_layer_tree_host_client.cc",
+    "test/stub_layer_tree_host_client.h",
+    "test/stub_layer_tree_host_single_thread_client.cc",
+    "test/stub_layer_tree_host_single_thread_client.h",
     "test/surface_aggregator_test_helpers.cc",
     "test/surface_aggregator_test_helpers.h",
     "test/surface_hittest_test_helpers.cc",
diff --git a/cc/animation/animation_host_perftest.cc b/cc/animation/animation_host_perftest.cc
index a478a220..8d855e5 100644
--- a/cc/animation/animation_host_perftest.cc
+++ b/cc/animation/animation_host_perftest.cc
@@ -14,6 +14,7 @@
 #include "cc/test/fake_layer_tree_host.h"
 #include "cc/test/fake_layer_tree_host_client.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
@@ -21,16 +22,13 @@
 namespace cc {
 
 class AnimationHostPerfTest : public testing::Test {
- public:
-  AnimationHostPerfTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
  protected:
   void SetUp() override {
     LayerTreeSettings settings;
     layer_tree_host_ =
         FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_, settings);
     layer_tree_host_->InitializeSingleThreaded(
-        &fake_client_, base::ThreadTaskRunnerHandle::Get(), nullptr);
+        &single_thread_client_, base::ThreadTaskRunnerHandle::Get(), nullptr);
 
     root_layer_ = Layer::Create();
     layer_tree_host_->SetRootLayer(root_layer_);
@@ -115,13 +113,14 @@
   }
 
  protected:
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
+  FakeLayerTreeHostClient fake_client_;
   std::unique_ptr<FakeLayerTreeHost> layer_tree_host_;
   scoped_refptr<Layer> root_layer_;
   LayerImpl* root_layer_impl_;
 
   LapTimer timer_;
   TestTaskGraphRunner task_graph_runner_;
-  FakeLayerTreeHostClient fake_client_;
 };
 
 TEST_F(AnimationHostPerfTest, Push1000PlayersPropertiesTo) {
diff --git a/cc/blink/web_layer_impl_fixed_bounds_unittest.cc b/cc/blink/web_layer_impl_fixed_bounds_unittest.cc
index 1fa6b8d..1074c8a6 100644
--- a/cc/blink/web_layer_impl_fixed_bounds_unittest.cc
+++ b/cc/blink/web_layer_impl_fixed_bounds_unittest.cc
@@ -105,7 +105,7 @@
   normal_layer->setPosition(position);
   root_layer->addChild(normal_layer);
 
-  cc::FakeLayerTreeHostClient client(cc::FakeLayerTreeHostClient::DIRECT_3D);
+  cc::FakeLayerTreeHostClient client;
   cc::TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<cc::FakeLayerTreeHost> host =
       cc::FakeLayerTreeHost::Create(&client, &task_graph_runner);
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 14ead61..b8b99c75 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -286,6 +286,10 @@
       'test/skia_common.h',
       'test/solid_color_content_layer_client.cc',
       'test/solid_color_content_layer_client.h',
+      'test/stub_layer_tree_host_client.cc',
+      'test/stub_layer_tree_host_client.h',
+      'test/stub_layer_tree_host_single_thread_client.cc',
+      'test/stub_layer_tree_host_single_thread_client.h',
       'test/surface_aggregator_test_helpers.cc',
       'test/surface_aggregator_test_helpers.h',
       'test/surface_hittest_test_helpers.cc',
diff --git a/cc/debug/micro_benchmark_controller_unittest.cc b/cc/debug/micro_benchmark_controller_unittest.cc
index d8664df..30abcc46 100644
--- a/cc/debug/micro_benchmark_controller_unittest.cc
+++ b/cc/debug/micro_benchmark_controller_unittest.cc
@@ -23,9 +23,6 @@
 
 class MicroBenchmarkControllerTest : public testing::Test {
  public:
-  MicroBenchmarkControllerTest()
-      : layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
   void SetUp() override {
     impl_task_runner_provider_ =
         base::WrapUnique(new FakeImplTaskRunnerProvider);
diff --git a/cc/layers/heads_up_display_layer_impl_unittest.cc b/cc/layers/heads_up_display_layer_impl_unittest.cc
index e5b8cbd9..8d27d7d 100644
--- a/cc/layers/heads_up_display_layer_impl_unittest.cc
+++ b/cc/layers/heads_up_display_layer_impl_unittest.cc
@@ -37,7 +37,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.CreatePendingTree();
diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc
index 95c00b8..1a65acb 100644
--- a/cc/layers/layer_impl_unittest.cc
+++ b/cc/layers/layer_impl_unittest.cc
@@ -112,7 +112,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
@@ -224,7 +225,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
@@ -345,7 +347,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
diff --git a/cc/layers/layer_list_iterator_unittest.cc b/cc/layers/layer_list_iterator_unittest.cc
index cb538e0..457752db 100644
--- a/cc/layers/layer_list_iterator_unittest.cc
+++ b/cc/layers/layer_list_iterator_unittest.cc
@@ -23,7 +23,7 @@
 
 TEST(LayerListIteratorTest, VerifyTraversalOrder) {
   // Unfortunate preamble.
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host_ptr =
       FakeLayerTreeHost::Create(&client, &task_graph_runner);
@@ -75,7 +75,7 @@
 
 TEST(LayerListIteratorTest, VerifySingleLayer) {
   // Unfortunate preamble.
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host_ptr =
       FakeLayerTreeHost::Create(&client, &task_graph_runner);
@@ -108,7 +108,7 @@
 
 TEST(LayerListReverseIteratorTest, VerifyTraversalOrder) {
   // Unfortunate preamble.
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host_ptr =
       FakeLayerTreeHost::Create(&client, &task_graph_runner);
@@ -162,7 +162,7 @@
 
 TEST(LayerListReverseIteratorTest, VerifySingleLayer) {
   // Unfortunate preamble.
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host_ptr =
       FakeLayerTreeHost::Create(&client, &task_graph_runner);
@@ -200,7 +200,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
@@ -254,7 +255,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
@@ -290,7 +292,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
@@ -346,7 +349,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   host_impl.SetVisible(true);
diff --git a/cc/layers/layer_perftest.cc b/cc/layers/layer_perftest.cc
index 9f85a208..13c14b2 100644
--- a/cc/layers/layer_perftest.cc
+++ b/cc/layers/layer_perftest.cc
@@ -10,6 +10,7 @@
 #include "cc/test/fake_layer_tree_host.h"
 #include "cc/test/fake_layer_tree_host_client.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
@@ -27,7 +28,6 @@
       : host_impl_(&task_runner_provider_,
                    &shared_bitmap_manager_,
                    &task_graph_runner_),
-        fake_client_(FakeLayerTreeHostClient::DIRECT_3D),
         timer_(kWarmupRuns,
                base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
                kTimeCheckInterval) {}
@@ -37,7 +37,7 @@
     layer_tree_host_ =
         FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
     layer_tree_host_->InitializeSingleThreaded(
-        &fake_client_, base::ThreadTaskRunnerHandle::Get(), nullptr);
+        &single_thread_client_, base::ThreadTaskRunnerHandle::Get(), nullptr);
   }
 
   void TearDown() override {
@@ -50,6 +50,7 @@
   TestTaskGraphRunner task_graph_runner_;
   FakeLayerTreeHostImpl host_impl_;
 
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
   FakeLayerTreeHostClient fake_client_;
   std::unique_ptr<FakeLayerTreeHost> layer_tree_host_;
   LapTimer timer_;
diff --git a/cc/layers/layer_position_constraint_unittest.cc b/cc/layers/layer_position_constraint_unittest.cc
index 2ce51c9..d9aa0ed5 100644
--- a/cc/layers/layer_position_constraint_unittest.cc
+++ b/cc/layers/layer_position_constraint_unittest.cc
@@ -61,8 +61,7 @@
 class LayerPositionConstraintTest : public testing::Test {
  public:
   LayerPositionConstraintTest()
-      : fake_client_(FakeLayerTreeHostClient::DIRECT_3D),
-        layer_tree_host_(
+      : layer_tree_host_(
             FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_)),
         root_impl_(nullptr),
         inner_viewport_container_layer_impl_(nullptr),
diff --git a/cc/layers/layer_proto_converter_unittest.cc b/cc/layers/layer_proto_converter_unittest.cc
index 49da6c8..5f88dc3 100644
--- a/cc/layers/layer_proto_converter_unittest.cc
+++ b/cc/layers/layer_proto_converter_unittest.cc
@@ -18,10 +18,6 @@
 namespace cc {
 namespace {
 class LayerProtoConverterTest : public testing::Test {
- public:
-  LayerProtoConverterTest()
-      : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
  protected:
   void SetUp() override {
     layer_tree_host_ =
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 179e0a5..adc7894 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -26,6 +26,7 @@
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/layer_internals_for_test.h"
 #include "cc/test/layer_test_common.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.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"
@@ -108,9 +109,6 @@
 // The tests still have helpful names, and a test with the name FooBar would
 // have a wrapper method in this class called RunFooBarTest.
 class LayerSerializationTest : public testing::Test {
- public:
-  LayerSerializationTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
  protected:
   void SetUp() override {
     layer_tree_host_ =
@@ -899,8 +897,7 @@
       : host_impl_(LayerTreeSettings(),
                    &task_runner_provider_,
                    &shared_bitmap_manager_,
-                   &task_graph_runner_),
-        fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {
+                   &task_graph_runner_) {
     timeline_impl_ =
         AnimationTimeline::Create(AnimationIdProvider::NextTimelineId());
     timeline_impl_->set_is_impl_only(true);
@@ -920,7 +917,7 @@
         AnimationHost::CreateForTesting(ThreadInstance::MAIN);
 
     layer_tree_host_.reset(
-        new StrictMock<MockLayerTreeHost>(&fake_client_, &params));
+        new StrictMock<MockLayerTreeHost>(&single_thread_client_, &params));
   }
 
   void TearDown() override {
@@ -989,6 +986,7 @@
   TestTaskGraphRunner task_graph_runner_;
   FakeLayerTreeHostImpl host_impl_;
 
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
   FakeLayerTreeHostClient fake_client_;
   std::unique_ptr<StrictMock<MockLayerTreeHost>> layer_tree_host_;
   scoped_refptr<Layer> parent_;
@@ -1846,8 +1844,6 @@
 
 class LayerTreeHostFactory {
  public:
-  LayerTreeHostFactory() : client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
   std::unique_ptr<LayerTreeHost> Create() {
     return Create(LayerTreeSettings());
   }
@@ -1862,11 +1858,12 @@
     params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
     params.animation_host =
         AnimationHost::CreateForTesting(ThreadInstance::MAIN);
-    return LayerTreeHost::CreateSingleThreaded(&client_, &params);
+    return LayerTreeHost::CreateSingleThreaded(&single_thread_client_, &params);
   }
 
  private:
   FakeLayerTreeHostClient client_;
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
   TestSharedBitmapManager shared_bitmap_manager_;
   TestTaskGraphRunner task_graph_runner_;
   TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
diff --git a/cc/layers/nine_patch_layer_impl_unittest.cc b/cc/layers/nine_patch_layer_impl_unittest.cc
index f5ecfbe1..5919299a 100644
--- a/cc/layers/nine_patch_layer_impl_unittest.cc
+++ b/cc/layers/nine_patch_layer_impl_unittest.cc
@@ -47,7 +47,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeUIResourceLayerTreeHostImpl host_impl(
       &task_runner_provider, &shared_bitmap_manager, &task_graph_runner);
   host_impl.SetVisible(true);
diff --git a/cc/layers/nine_patch_layer_unittest.cc b/cc/layers/nine_patch_layer_unittest.cc
index 5cc14e2..abc431b7 100644
--- a/cc/layers/nine_patch_layer_unittest.cc
+++ b/cc/layers/nine_patch_layer_unittest.cc
@@ -27,9 +27,6 @@
 namespace {
 
 class NinePatchLayerTest : public testing::Test {
- public:
-  NinePatchLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
  protected:
   void SetUp() override {
     layer_tree_host_ =
diff --git a/cc/layers/painted_scrollbar_layer_unittest.cc b/cc/layers/painted_scrollbar_layer_unittest.cc
index cb969e5..3a447b8 100644
--- a/cc/layers/painted_scrollbar_layer_unittest.cc
+++ b/cc/layers/painted_scrollbar_layer_unittest.cc
@@ -27,7 +27,7 @@
 };
 
 TEST(PaintedScrollbarLayerTest, NeedsPaint) {
-  FakeLayerTreeHostClient fake_client_(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient fake_client_;
   TestTaskGraphRunner task_graph_runner_;
   std::unique_ptr<FakeLayerTreeHost> layer_tree_host_;
 
diff --git a/cc/layers/picture_image_layer_unittest.cc b/cc/layers/picture_image_layer_unittest.cc
index a741e74..572ee7a 100644
--- a/cc/layers/picture_image_layer_unittest.cc
+++ b/cc/layers/picture_image_layer_unittest.cc
@@ -19,7 +19,7 @@
 
 TEST(PictureImageLayerTest, PaintContentsToDisplayList) {
   scoped_refptr<PictureImageLayer> layer = PictureImageLayer::Create();
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&client, &task_graph_runner);
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc
index ce3f413..87a883454 100644
--- a/cc/layers/picture_layer_impl_perftest.cc
+++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -42,7 +42,7 @@
  public:
   PictureLayerImplPerfTest()
       : task_runner_provider_(base::ThreadTaskRunnerHandle::Get()),
-        output_surface_(FakeOutputSurface::Create3d()),
+        output_surface_(FakeOutputSurface::CreateDelegating3d()),
         host_impl_(LayerTreeSettings(),
                    &task_runner_provider_,
                    &shared_bitmap_manager_,
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index f3f389a..70face0 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -22,6 +22,8 @@
 #include "cc/test/begin_frame_args_test.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/fake_picture_layer_impl.h"
@@ -1450,7 +1452,7 @@
   std::unique_ptr<TestWebGraphicsContext3D> context =
       TestWebGraphicsContext3D::Create();
   context->set_max_texture_size(140);
-  ResetOutputSurface(FakeOutputSurface::Create3d(std::move(context)));
+  ResetOutputSurface(FakeOutputSurface::CreateDelegating3d(std::move(context)));
 
   SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
                                     false);
@@ -1485,7 +1487,7 @@
   std::unique_ptr<TestWebGraphicsContext3D> context =
       TestWebGraphicsContext3D::Create();
   context->set_max_texture_size(140);
-  ResetOutputSurface(FakeOutputSurface::Create3d(std::move(context)));
+  ResetOutputSurface(FakeOutputSurface::CreateDelegating3d(std::move(context)));
 
   SetupDrawPropertiesAndUpdateTiles(active_layer(), 1.f, 1.f, 1.f, 1.f, 0.f,
                                     false);
@@ -4317,7 +4319,7 @@
   FakeContentLayerClient client;
   client.set_bounds(layer_bounds);
   scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
@@ -4380,7 +4382,7 @@
   FakeContentLayerClient client;
   client.set_bounds(layer_bounds);
   scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 0b14eb4..1a80b597 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -26,6 +26,7 @@
 #include "cc/test/fake_recording_source.h"
 #include "cc/test/layer_tree_settings_for_testing.h"
 #include "cc/test/skia_common.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/single_thread_proxy.h"
@@ -129,7 +130,7 @@
 namespace {
 
 TEST(PictureLayerTest, TestSetAllPropsSerializationDeserialization) {
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   LayerTreeSettings settings;
   std::unique_ptr<FakeImageSerializationProcessor>
@@ -163,7 +164,7 @@
 }
 
 TEST(PictureLayerTest, TestSerializationDeserialization) {
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeImageSerializationProcessor>
       fake_image_serialization_processor =
@@ -194,7 +195,7 @@
   std::unique_ptr<FakeImageSerializationProcessor>
       fake_image_serialization_processor =
           base::WrapUnique(new FakeImageSerializationProcessor);
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(
       &host_client, &task_graph_runner, LayerTreeSettings(),
@@ -215,7 +216,7 @@
   scoped_refptr<PictureLayer> layer = PictureLayer::Create(client);
   layer->SetBounds(gfx::Size(10, 10));
 
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
@@ -261,7 +262,7 @@
   scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
   layer->SetBounds(gfx::Size(50, 50));
 
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
@@ -278,7 +279,8 @@
   host->CommitComplete();
   FakeImplTaskRunnerProvider impl_task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
-  std::unique_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
+  std::unique_ptr<OutputSurface> output_surface(
+      FakeOutputSurface::CreateDelegating3d());
   LayerTreeSettings layer_tree_settings = LayerTreeSettings();
   layer_tree_settings.image_decode_tasks_enabled = true;
   FakeLayerTreeHostImpl host_impl(layer_tree_settings,
@@ -305,7 +307,7 @@
   scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
   layer->SetBounds(gfx::Size(50, 50));
 
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
@@ -321,7 +323,8 @@
   host->CommitComplete();
   FakeImplTaskRunnerProvider impl_task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
-  std::unique_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
+  std::unique_ptr<OutputSurface> output_surface(
+      FakeOutputSurface::CreateDelegating3d());
   LayerTreeSettings layer_tree_settings = LayerTreeSettings();
   layer_tree_settings.image_decode_tasks_enabled = true;
   FakeLayerTreeHostImpl host_impl(layer_tree_settings,
@@ -349,7 +352,7 @@
   scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client);
   layer->SetBounds(gfx::Size(10, 10));
 
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
@@ -368,7 +371,8 @@
   FakeImplTaskRunnerProvider impl_task_runner_provider;
 
   TestSharedBitmapManager shared_bitmap_manager;
-  std::unique_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
+  std::unique_ptr<OutputSurface> output_surface(
+      FakeOutputSurface::CreateDelegating3d());
   LayerTreeSettings layer_tree_settings = LayerTreeSettingsForTesting();
   layer_tree_settings.image_decode_tasks_enabled = true;
   FakeLayerTreeHostImpl host_impl(layer_tree_settings,
@@ -430,7 +434,7 @@
       FakePictureLayer::CreateWithRecordingSource(
           client, std::move(recording_source_owned));
 
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&host_client, &task_graph_runner);
@@ -464,8 +468,9 @@
   settings.verify_clip_tree_calculations = true;
   settings.verify_transform_tree_calculations = true;
 
-  FakeLayerTreeHostClient host_client1(FakeLayerTreeHostClient::DIRECT_3D);
-  FakeLayerTreeHostClient host_client2(FakeLayerTreeHostClient::DIRECT_3D);
+  StubLayerTreeHostSingleThreadClient single_thread_client;
+  FakeLayerTreeHostClient host_client1;
+  FakeLayerTreeHostClient host_client2;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
 
@@ -480,7 +485,7 @@
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
   std::unique_ptr<LayerTreeHost> host1 =
-      LayerTreeHost::CreateSingleThreaded(&host_client1, &params);
+      LayerTreeHost::CreateSingleThreaded(&single_thread_client, &params);
   host1->SetVisible(true);
   host_client1.SetLayerTreeHost(host1.get());
 
@@ -495,7 +500,7 @@
   params2.animation_host =
       AnimationHost::CreateForTesting(ThreadInstance::MAIN);
   std::unique_ptr<LayerTreeHost> host2 =
-      LayerTreeHost::CreateSingleThreaded(&host_client2, &params2);
+      LayerTreeHost::CreateSingleThreaded(&single_thread_client, &params2);
   host2->SetVisible(true);
   host_client2.SetLayerTreeHost(host2.get());
 
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index 49d87b1..de89059b 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -89,7 +89,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
   std::unique_ptr<LayerImpl> root_layer =
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 6852fee..a4752241 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -25,6 +25,7 @@
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/test/mock_occlusion_tracker.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/effect_node.h"
@@ -48,8 +49,8 @@
         next_id_(1),
         total_ui_resource_created_(0),
         total_ui_resource_deleted_(0) {
-    InitializeSingleThreaded(client, base::ThreadTaskRunnerHandle::Get(),
-                             nullptr);
+    InitializeSingleThreaded(&single_thread_client_,
+                             base::ThreadTaskRunnerHandle::Get(), nullptr);
   }
 
   UIResourceId CreateUIResource(UIResourceClient* content) override {
@@ -92,6 +93,7 @@
       std::unordered_map<UIResourceId, UIResourceBitmap>;
   UIResourceBitmapMap ui_resource_bitmap_map_;
 
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
   int next_id_;
   int total_ui_resource_created_;
   int total_ui_resource_deleted_;
@@ -99,7 +101,7 @@
 
 class ScrollbarLayerTest : public testing::Test {
  public:
-  ScrollbarLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {
+  ScrollbarLayerTest() {
     layer_tree_settings_.single_thread_proxy_scheduler = false;
     layer_tree_settings_.use_zero_copy = true;
     layer_tree_settings_.scrollbar_animator = LayerTreeSettings::LINEAR_FADE;
diff --git a/cc/layers/solid_color_layer_impl_unittest.cc b/cc/layers/solid_color_layer_impl_unittest.cc
index 90e8be5..f02e0d29 100644
--- a/cc/layers/solid_color_layer_impl_unittest.cc
+++ b/cc/layers/solid_color_layer_impl_unittest.cc
@@ -137,7 +137,7 @@
   scoped_refptr<Layer> root = Layer::Create();
   root->AddChild(layer);
 
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient client;
   TestTaskGraphRunner task_graph_runner;
   std::unique_ptr<FakeLayerTreeHost> host =
       FakeLayerTreeHost::Create(&client, &task_graph_runner);
diff --git a/cc/layers/surface_layer_unittest.cc b/cc/layers/surface_layer_unittest.cc
index 4471fa5..5f40deb 100644
--- a/cc/layers/surface_layer_unittest.cc
+++ b/cc/layers/surface_layer_unittest.cc
@@ -29,11 +29,6 @@
 static constexpr uint32_t kArbitraryClientId = 0;
 
 class SurfaceLayerTest : public testing::Test {
- public:
-  SurfaceLayerTest()
-      : fake_client_(
-            FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
-
  protected:
   void SetUp() override {
     layer_tree_host_ =
@@ -182,8 +177,7 @@
   SurfaceLayerSwapPromiseWithDraw() : SurfaceLayerSwapPromise() {}
 
   std::unique_ptr<OutputSurface> CreateOutputSurface() override {
-    auto ret = delegating_renderer() ? FakeOutputSurface::CreateDelegating3d()
-                                     : FakeOutputSurface::Create3d();
+    auto ret = FakeOutputSurface::CreateDelegating3d();
     output_surface_ = ret.get();
     return std::move(ret);
   }
@@ -229,9 +223,7 @@
   FakeOutputSurface* output_surface_;
 };
 
-// TODO(jbauman): Reenable on single thread once http://crbug.com/421923 is
-// fixed.
-MULTI_THREAD_TEST_F(SurfaceLayerSwapPromiseWithDraw);
+SINGLE_AND_MULTI_THREAD_TEST_F(SurfaceLayerSwapPromiseWithDraw);
 
 // Check that SurfaceSequence is sent through swap promise and resolved when
 // swap fails.
diff --git a/cc/layers/texture_layer_impl_unittest.cc b/cc/layers/texture_layer_impl_unittest.cc
index ee87c31..32c74e9 100644
--- a/cc/layers/texture_layer_impl_unittest.cc
+++ b/cc/layers/texture_layer_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/test/layer_test_common.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 9c9fe93b..17a06a2 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -33,6 +33,7 @@
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/layer_test_common.h"
 #include "cc/test/layer_tree_test.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/blocking_task_runner.h"
@@ -75,7 +76,7 @@
         AnimationHost::CreateForTesting(ThreadInstance::MAIN);
     LayerTreeSettings settings;
     params.settings = &settings;
-    return base::WrapUnique(new MockLayerTreeHost(client, &params));
+    return base::WrapUnique(new MockLayerTreeHost(&params));
   }
 
   MOCK_METHOD0(SetNeedsCommit, void());
@@ -84,12 +85,13 @@
   MOCK_METHOD0(StopRateLimiter, void());
 
  private:
-  MockLayerTreeHost(FakeLayerTreeHostClient* client,
-                    LayerTreeHost::InitParams* params)
+  explicit MockLayerTreeHost(LayerTreeHost::InitParams* params)
       : LayerTreeHost(params, CompositorMode::SINGLE_THREADED) {
-    InitializeSingleThreaded(client, base::ThreadTaskRunnerHandle::Get(),
-                             nullptr);
+    InitializeSingleThreaded(&single_thread_client_,
+                             base::ThreadTaskRunnerHandle::Get(), nullptr);
   }
+
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
 };
 
 class FakeTextureLayerClient : public TextureLayerClient {
@@ -205,9 +207,7 @@
 class TextureLayerTest : public testing::Test {
  public:
   TextureLayerTest()
-      : fake_client_(
-            FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
-        output_surface_(FakeOutputSurface::Create3d()),
+      : output_surface_(FakeOutputSurface::CreateDelegating3d()),
         host_impl_(&task_runner_provider_,
                    &shared_bitmap_manager_,
                    &task_graph_runner_),
@@ -841,10 +841,6 @@
 
 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
  protected:
-  TextureLayerImplWithMailboxTest()
-      : fake_client_(
-          FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
-
   void SetUp() override {
     TextureLayerTest::SetUp();
     layer_tree_host_ =
diff --git a/cc/layers/ui_resource_layer_impl_unittest.cc b/cc/layers/ui_resource_layer_impl_unittest.cc
index b86fada..67a986d 100644
--- a/cc/layers/ui_resource_layer_impl_unittest.cc
+++ b/cc/layers/ui_resource_layer_impl_unittest.cc
@@ -61,7 +61,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeUIResourceLayerTreeHostImpl host_impl(
       &task_runner_provider, &shared_bitmap_manager, &task_graph_runner);
   host_impl.SetVisible(true);
@@ -106,7 +107,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeUIResourceLayerTreeHostImpl host_impl(
       &task_runner_provider, &shared_bitmap_manager, &task_graph_runner);
   host_impl.SetVisible(true);
@@ -135,7 +137,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeUIResourceLayerTreeHostImpl host_impl(
       &task_runner_provider, &shared_bitmap_manager, &task_graph_runner);
   host_impl.SetVisible(true);
diff --git a/cc/layers/ui_resource_layer_unittest.cc b/cc/layers/ui_resource_layer_unittest.cc
index 7163828..62906af 100644
--- a/cc/layers/ui_resource_layer_unittest.cc
+++ b/cc/layers/ui_resource_layer_unittest.cc
@@ -12,6 +12,7 @@
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/fake_output_surface_client.h"
 #include "cc/test/geometry_test_utils.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/single_thread_proxy.h"
@@ -45,15 +46,12 @@
 };
 
 class UIResourceLayerTest : public testing::Test {
- public:
-  UIResourceLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
  protected:
   void SetUp() override {
     layer_tree_host_ =
         FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
     layer_tree_host_->InitializeSingleThreaded(
-        &fake_client_, base::ThreadTaskRunnerHandle::Get(), nullptr);
+        &single_thread_client_, base::ThreadTaskRunnerHandle::Get(), nullptr);
   }
 
   void TearDown() override {
@@ -61,6 +59,7 @@
   }
 
   FakeLayerTreeHostClient fake_client_;
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
   TestTaskGraphRunner task_graph_runner_;
   std::unique_ptr<FakeLayerTreeHost> layer_tree_host_;
 };
diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc
index af14a60..976afae 100644
--- a/cc/resources/resource_pool_unittest.cc
+++ b/cc/resources/resource_pool_unittest.cc
@@ -22,7 +22,7 @@
 class ResourcePoolTest : public testing::Test {
  public:
   void SetUp() override {
-    output_surface_ = FakeOutputSurface::Create3d();
+    output_surface_ = FakeOutputSurface::CreateDelegating3d();
     ASSERT_TRUE(output_surface_->BindToClient(&output_surface_client_));
     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
     resource_provider_ = FakeResourceProvider::Create(
diff --git a/cc/resources/scoped_resource_unittest.cc b/cc/resources/scoped_resource_unittest.cc
index a7811d0..dbb2625 100644
--- a/cc/resources/scoped_resource_unittest.cc
+++ b/cc/resources/scoped_resource_unittest.cc
@@ -18,7 +18,8 @@
 
 TEST(ScopedResourceTest, NewScopedResource) {
   FakeOutputSurfaceClient output_surface_client;
-  std::unique_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
+  std::unique_ptr<OutputSurface> output_surface(
+      FakeOutputSurface::CreateDelegating3d());
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
@@ -40,7 +41,8 @@
 
 TEST(ScopedResourceTest, CreateScopedResource) {
   FakeOutputSurfaceClient output_surface_client;
-  std::unique_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
+  std::unique_ptr<OutputSurface> output_surface(
+      FakeOutputSurface::CreateDelegating3d());
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
@@ -65,7 +67,8 @@
 
 TEST(ScopedResourceTest, ScopedResourceIsDeleted) {
   FakeOutputSurfaceClient output_surface_client;
-  std::unique_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d());
+  std::unique_ptr<OutputSurface> output_surface(
+      FakeOutputSurface::CreateDelegating3d());
   CHECK(output_surface->BindToClient(&output_surface_client));
 
   std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
diff --git a/cc/surfaces/display_unittest.cc b/cc/surfaces/display_unittest.cc
index b17a63a0..74c6508 100644
--- a/cc/surfaces/display_unittest.cc
+++ b/cc/surfaces/display_unittest.cc
@@ -99,7 +99,11 @@
       : factory_(&manager_, &surface_factory_client_),
         id_allocator_(kArbitraryClientId),
         task_runner_(new base::NullTaskRunner) {
-    id_allocator_.RegisterSurfaceClientId(&manager_);
+    manager_.RegisterSurfaceClientId(id_allocator_.client_id());
+  }
+
+  ~DisplayTest() override {
+    manager_.InvalidateSurfaceClientId(id_allocator_.client_id());
   }
 
   void SetUpDisplay(const RendererSettings& settings,
diff --git a/cc/surfaces/surface_id_allocator.cc b/cc/surfaces/surface_id_allocator.cc
index 9151400f..7ed7f521 100644
--- a/cc/surfaces/surface_id_allocator.cc
+++ b/cc/surfaces/surface_id_allocator.cc
@@ -12,17 +12,9 @@
 namespace cc {
 
 SurfaceIdAllocator::SurfaceIdAllocator(uint32_t client_id)
-    : client_id_(client_id), next_id_(1u), manager_(nullptr) {}
-
-void SurfaceIdAllocator::RegisterSurfaceClientId(SurfaceManager* manager) {
-  DCHECK(!manager_);
-  manager_ = manager;
-  manager_->RegisterSurfaceClientId(client_id_);
-}
+    : client_id_(client_id), next_id_(1u) {}
 
 SurfaceIdAllocator::~SurfaceIdAllocator() {
-  if (manager_)
-    manager_->InvalidateSurfaceClientId(client_id_);
 }
 
 SurfaceId SurfaceIdAllocator::GenerateId() {
diff --git a/cc/surfaces/surface_id_allocator.h b/cc/surfaces/surface_id_allocator.h
index c77f359..5ed3b117 100644
--- a/cc/surfaces/surface_id_allocator.h
+++ b/cc/surfaces/surface_id_allocator.h
@@ -25,24 +25,11 @@
 
   SurfaceId GenerateId();
 
-  // This needs to be called before any sequences with this allocator's
-  // namespace will be used to enforce destruction dependencies.
-  // When this SurfaceIdAllocator is destroyed, its namespace is
-  // automatically invalidated and any remaining sequences with that
-  // namespace will be ignored. This method does not need to be called in
-  // contexts where there is no SurfaceManager (e.g. a renderer process).
-  void RegisterSurfaceClientId(SurfaceManager* manager);
-
   uint32_t client_id() const { return client_id_; }
 
-  // SurfaceIdAllocator's owner can call this when it find out that
-  // SurfaceManager is no longer alive during destruction.
-  void DidDestroySurfaceManager() { manager_ = nullptr; }
-
  private:
   const uint32_t client_id_;
   uint32_t next_id_;
-  SurfaceManager* manager_;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceIdAllocator);
 };
diff --git a/cc/test/fake_layer_tree_host_client.cc b/cc/test/fake_layer_tree_host_client.cc
index 6de02bf6..b886b18 100644
--- a/cc/test/fake_layer_tree_host_client.cc
+++ b/cc/test/fake_layer_tree_host_client.cc
@@ -4,41 +4,17 @@
 
 #include "cc/test/fake_layer_tree_host_client.h"
 
-#include "base/memory/ptr_util.h"
-#include "cc/output/context_provider.h"
 #include "cc/test/fake_output_surface.h"
-#include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/layer_tree_host.h"
 
 namespace cc {
 
-FakeLayerTreeHostClient::FakeLayerTreeHostClient(RendererOptions options)
-    : use_software_rendering_(options == DIRECT_SOFTWARE ||
-                              options == DELEGATED_SOFTWARE),
-      use_delegating_renderer_(options == DELEGATED_3D ||
-                               options == DELEGATED_SOFTWARE),
-      host_(NULL) {
-}
-
-FakeLayerTreeHostClient::~FakeLayerTreeHostClient() {}
+FakeLayerTreeHostClient::FakeLayerTreeHostClient() = default;
+FakeLayerTreeHostClient::~FakeLayerTreeHostClient() = default;
 
 void FakeLayerTreeHostClient::RequestNewOutputSurface() {
   DCHECK(host_);
-  std::unique_ptr<OutputSurface> surface;
-  if (use_software_rendering_) {
-    if (use_delegating_renderer_) {
-      surface = FakeOutputSurface::CreateDelegatingSoftware(
-          base::WrapUnique(new SoftwareOutputDevice));
-    } else {
-      surface = FakeOutputSurface::CreateSoftware(
-          base::WrapUnique(new SoftwareOutputDevice));
-    }
-  } else if (use_delegating_renderer_) {
-    surface = FakeOutputSurface::CreateDelegating3d();
-  } else {
-    surface = FakeOutputSurface::Create3d();
-  }
-  host_->SetOutputSurface(std::move(surface));
+  host_->SetOutputSurface(FakeOutputSurface::CreateDelegating3d());
 }
 
 void FakeLayerTreeHostClient::DidFailToInitializeOutputSurface() {
diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h
index 1684e3e..ad24d4a 100644
--- a/cc/test/fake_layer_tree_host_client.h
+++ b/cc/test/fake_layer_tree_host_client.h
@@ -5,60 +5,25 @@
 #ifndef CC_TEST_FAKE_LAYER_TREE_HOST_CLIENT_H_
 #define CC_TEST_FAKE_LAYER_TREE_HOST_CLIENT_H_
 
-#include <memory>
-
-#include "cc/input/input_handler.h"
-#include "cc/test/test_context_provider.h"
-#include "cc/trees/layer_tree_host_client.h"
-#include "cc/trees/layer_tree_host_single_thread_client.h"
+#include "cc/test/stub_layer_tree_host_client.h"
 
 namespace cc {
-class OutputSurface;
+class LayerTreeHost;
 
-class FakeLayerTreeHostClient : public LayerTreeHostClient,
-                                public LayerTreeHostSingleThreadClient {
+class FakeLayerTreeHostClient : public StubLayerTreeHostClient {
  public:
-  enum RendererOptions {
-    DIRECT_3D,
-    DIRECT_SOFTWARE,
-    DELEGATED_3D,
-    DELEGATED_SOFTWARE
-  };
-  explicit FakeLayerTreeHostClient(RendererOptions options);
+  FakeLayerTreeHostClient();
   ~FakeLayerTreeHostClient() override;
 
   // Caller responsible for unsetting this and maintaining the host's lifetime.
   void SetLayerTreeHost(LayerTreeHost* host) { host_ = host; }
 
-  // LayerTreeHostClient implementation.
-  void WillBeginMainFrame() override {}
-  void DidBeginMainFrame() override {}
-  void BeginMainFrame(const BeginFrameArgs& args) override {}
-  void BeginMainFrameNotExpectedSoon() override {}
-  void UpdateLayerTreeHost() override {}
-  void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
-                           const gfx::Vector2dF& outer_delta,
-                           const gfx::Vector2dF& elastic_overscroll_delta,
-                           float page_scale,
-                           float top_controls_delta) override {}
+  // StubLayerTreeHostClient overrides.
   void RequestNewOutputSurface() override;
-  void DidInitializeOutputSurface() override {}
   void DidFailToInitializeOutputSurface() override;
-  void WillCommit() override {}
-  void DidCommit() override {}
-  void DidCommitAndDrawFrame() override {}
-  void DidCompleteSwapBuffers() override {}
-  void DidCompletePageScaleAnimation() override {}
-
-  // LayerTreeHostSingleThreadClient implementation.
-  void DidPostSwapBuffers() override {}
-  void DidAbortSwapBuffers() override {}
 
  private:
-  bool use_software_rendering_;
-  bool use_delegating_renderer_;
-
-  LayerTreeHost* host_;
+  LayerTreeHost* host_ = nullptr;
 };
 
 }  // namespace cc
diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc
index c867d6b..1fb7f23 100644
--- a/cc/test/fake_output_surface.cc
+++ b/cc/test/fake_output_surface.cc
@@ -23,14 +23,6 @@
                         delegated_rendering) {}
 
 FakeOutputSurface::FakeOutputSurface(
-    std::unique_ptr<SoftwareOutputDevice> software_device,
-    bool delegated_rendering)
-    : FakeOutputSurface(nullptr,
-                        nullptr,
-                        std::move(software_device),
-                        delegated_rendering) {}
-
-FakeOutputSurface::FakeOutputSurface(
     scoped_refptr<ContextProvider> context_provider,
     scoped_refptr<ContextProvider> worker_context_provider,
     std::unique_ptr<SoftwareOutputDevice> software_device,
@@ -108,12 +100,6 @@
   OutputSurface::DetachFromClient();
 }
 
-void FakeOutputSurface::SetTreeActivationCallback(
-    const base::Closure& callback) {
-  DCHECK(client_);
-  client_->SetTreeActivationCallback(callback);
-}
-
 bool FakeOutputSurface::HasExternalStencilTest() const {
   return has_external_stencil_test_;
 }
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index ad91f08..e985bcf5 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -28,14 +28,13 @@
 
   static std::unique_ptr<FakeOutputSurface> Create3d() {
     return base::WrapUnique(
-        new FakeOutputSurface(TestContextProvider::Create(),
-                              TestContextProvider::CreateWorker(), false));
+        new FakeOutputSurface(TestContextProvider::Create(), nullptr, false));
   }
 
   static std::unique_ptr<FakeOutputSurface> Create3d(
       scoped_refptr<ContextProvider> context_provider) {
-    return base::WrapUnique(new FakeOutputSurface(
-        context_provider, TestContextProvider::CreateWorker(), false));
+    return base::WrapUnique(
+        new FakeOutputSurface(context_provider, nullptr, false));
   }
 
   static std::unique_ptr<FakeOutputSurface> Create3d(
@@ -54,15 +53,14 @@
 
   static std::unique_ptr<FakeOutputSurface> Create3d(
       std::unique_ptr<TestWebGraphicsContext3D> context) {
-    return base::WrapUnique(
-        new FakeOutputSurface(TestContextProvider::Create(std::move(context)),
-                              TestContextProvider::CreateWorker(), false));
+    return base::WrapUnique(new FakeOutputSurface(
+        TestContextProvider::Create(std::move(context)), nullptr, false));
   }
 
   static std::unique_ptr<FakeOutputSurface> CreateSoftware(
       std::unique_ptr<SoftwareOutputDevice> software_device) {
-    return base::WrapUnique(
-        new FakeOutputSurface(std::move(software_device), false));
+    return base::WrapUnique(new FakeOutputSurface(
+        nullptr, nullptr, std::move(software_device), false));
   }
 
   static std::unique_ptr<FakeOutputSurface> CreateDelegating3d() {
@@ -84,10 +82,9 @@
                               TestContextProvider::CreateWorker(), true));
   }
 
-  static std::unique_ptr<FakeOutputSurface> CreateDelegatingSoftware(
-      std::unique_ptr<SoftwareOutputDevice> software_device) {
+  static std::unique_ptr<FakeOutputSurface> CreateDelegatingSoftware() {
     return base::WrapUnique(
-        new FakeOutputSurface(std::move(software_device), true));
+        new FakeOutputSurface(nullptr, nullptr, nullptr, true));
   }
 
   static std::unique_ptr<FakeOutputSurface> CreateNoRequireSyncPoint(
@@ -126,8 +123,6 @@
   void BindFramebuffer() override;
   uint32_t GetFramebufferCopyTextureFormat() override;
 
-  void SetTreeActivationCallback(const base::Closure& callback);
-
   const TransferableResourceArray& resources_held_by_parent() {
     return resources_held_by_parent_;
   }
@@ -164,9 +159,6 @@
                     scoped_refptr<ContextProvider> worker_context_provider,
                     bool delegated_rendering);
 
-  FakeOutputSurface(std::unique_ptr<SoftwareOutputDevice> software_device,
-                    bool delegated_rendering);
-
   FakeOutputSurface(scoped_refptr<ContextProvider> context_provider,
                     scoped_refptr<ContextProvider> worker_context_provider,
                     std::unique_ptr<SoftwareOutputDevice> software_device,
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index be054de..b08f7444 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -119,8 +119,7 @@
     : LayerImplTest(LayerTreeSettingsForTesting()) {}
 
 LayerTestCommon::LayerImplTest::LayerImplTest(const LayerTreeSettings& settings)
-    : client_(FakeLayerTreeHostClient::DIRECT_3D),
-      output_surface_(FakeOutputSurface::Create3d()),
+    : output_surface_(FakeOutputSurface::CreateDelegating3d()),
       host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_, settings)),
       render_pass_(RenderPass::Create()),
       layer_impl_id_(2) {
diff --git a/cc/test/layer_test_common.h b/cc/test/layer_test_common.h
index f3c2eed..aaf8024 100644
--- a/cc/test/layer_test_common.h
+++ b/cc/test/layer_test_common.h
@@ -13,6 +13,7 @@
 #include "cc/animation/animation_timeline.h"
 #include "cc/quads/render_pass.h"
 #include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_host_impl.h"
 
diff --git a/cc/test/layer_tree_host_common_test.h b/cc/test/layer_tree_host_common_test.h
index 1d38e71b..8399743 100644
--- a/cc/test/layer_tree_host_common_test.h
+++ b/cc/test/layer_tree_host_common_test.h
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "cc/layers/layer_collections.h"
-#include "cc/test/fake_layer_tree_host_client.h"
 #include "cc/test/layer_test_common.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_settings.h"
@@ -26,7 +25,6 @@
 
 namespace cc {
 
-class FakeLayerTreeHost;
 class Layer;
 class LayerImpl;
 
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index daeb5c3..f2c5265 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -854,8 +854,14 @@
 }
 
 std::unique_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface() {
-  return delegating_renderer_ ? FakeOutputSurface::CreateDelegating3d()
-                              : FakeOutputSurface::Create3d();
+  if (delegating_renderer_)
+    return FakeOutputSurface::CreateDelegating3d();
+
+  // Make a worker context in a non-delegating OutputSurface. This is an
+  // exceptional situation for these tests as they put a non-delegating
+  // OutputSurface into the LayerTreeHost.
+  return FakeOutputSurface::Create3d(TestContextProvider::Create(),
+                                     TestContextProvider::CreateWorker());
 }
 
 void LayerTreeTest::DestroyLayerTreeHost() {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 6d15122..678b5d7 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -230,13 +230,6 @@
   }                                                              \
   class MultiThreadDelegatingImplNeedsSemicolon##TEST_FIXTURE_NAME {}
 
-// The Remote mode tests don't need to run for delegated renderer.
-#define REMOTE_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME) \
-  TEST_F(TEST_FIXTURE_NAME, RunRemote_DirectRenderer) {  \
-    RunTest(CompositorMode::REMOTE, false);              \
-  }                                                      \
-  class RemoteDirectImplNeedsSemicolon##TEST_FIXTURE_NAME {}
-
 #define SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME) \
   SINGLE_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME);                \
   MULTI_THREAD_DIRECT_RENDERER_TEST_F(TEST_FIXTURE_NAME)
diff --git a/cc/test/stub_layer_tree_host_client.cc b/cc/test/stub_layer_tree_host_client.cc
new file mode 100644
index 0000000..650faaf
--- /dev/null
+++ b/cc/test/stub_layer_tree_host_client.cc
@@ -0,0 +1,11 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/stub_layer_tree_host_client.h"
+
+namespace cc {
+
+StubLayerTreeHostClient::~StubLayerTreeHostClient() = default;
+
+}  // namespace cc
diff --git a/cc/test/stub_layer_tree_host_client.h b/cc/test/stub_layer_tree_host_client.h
new file mode 100644
index 0000000..ed6bd4b
--- /dev/null
+++ b/cc/test/stub_layer_tree_host_client.h
@@ -0,0 +1,39 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_STUB_LAYER_TREE_HOST_CLIENT_H_
+#define CC_TEST_STUB_LAYER_TREE_HOST_CLIENT_H_
+
+#include "cc/trees/layer_tree_host_client.h"
+
+namespace cc {
+
+class StubLayerTreeHostClient : public LayerTreeHostClient {
+ public:
+  ~StubLayerTreeHostClient() override;
+
+  // LayerTreeHostClient implementation.
+  void WillBeginMainFrame() override {}
+  void DidBeginMainFrame() override {}
+  void BeginMainFrame(const BeginFrameArgs& args) override {}
+  void BeginMainFrameNotExpectedSoon() override {}
+  void UpdateLayerTreeHost() override {}
+  void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+                           const gfx::Vector2dF& outer_delta,
+                           const gfx::Vector2dF& elastic_overscroll_delta,
+                           float page_scale,
+                           float top_controls_delta) override {}
+  void RequestNewOutputSurface() override {}
+  void DidInitializeOutputSurface() override {}
+  void DidFailToInitializeOutputSurface() override {}
+  void WillCommit() override {}
+  void DidCommit() override {}
+  void DidCommitAndDrawFrame() override {}
+  void DidCompleteSwapBuffers() override {}
+  void DidCompletePageScaleAnimation() override {}
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_STUB_LAYER_TREE_HOST_CLIENT_H_
diff --git a/cc/test/stub_layer_tree_host_single_thread_client.cc b/cc/test/stub_layer_tree_host_single_thread_client.cc
new file mode 100644
index 0000000..028e738f
--- /dev/null
+++ b/cc/test/stub_layer_tree_host_single_thread_client.cc
@@ -0,0 +1,12 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
+
+namespace cc {
+
+StubLayerTreeHostSingleThreadClient::~StubLayerTreeHostSingleThreadClient() =
+    default;
+
+}  // namespace cc
diff --git a/cc/test/stub_layer_tree_host_single_thread_client.h b/cc/test/stub_layer_tree_host_single_thread_client.h
new file mode 100644
index 0000000..c17c11e
--- /dev/null
+++ b/cc/test/stub_layer_tree_host_single_thread_client.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_STUB_LAYER_TREE_HOST_SINGLE_THREAD_CLIENT_H_
+#define CC_TEST_STUB_LAYER_TREE_HOST_SINGLE_THREAD_CLIENT_H_
+
+#include "cc/trees/layer_tree_host_single_thread_client.h"
+
+namespace cc {
+
+class StubLayerTreeHostSingleThreadClient
+    : public LayerTreeHostSingleThreadClient {
+ public:
+  ~StubLayerTreeHostSingleThreadClient() override;
+
+  // LayerTreeHostSingleThreadClient implementation.
+  void RequestScheduleComposite() override {}
+  void RequestScheduleAnimation() override {}
+  void DidPostSwapBuffers() override {}
+  void DidCompleteSwapBuffers() override {}
+  void DidAbortSwapBuffers() override {}
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_STUB_LAYER_TREE_HOST_SINGLE_THREAD_CLIENT_H_
diff --git a/cc/test/test_delegating_output_surface.cc b/cc/test/test_delegating_output_surface.cc
index 15fca6c..64a15fd 100644
--- a/cc/test/test_delegating_output_surface.cc
+++ b/cc/test/test_delegating_output_surface.cc
@@ -55,8 +55,6 @@
   capabilities_.can_force_reclaim_resources = true;
   capabilities_.delegated_sync_points_required =
       !context_shared_with_compositor;
-
-  surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get());
 }
 
 TestDelegatingOutputSurface::~TestDelegatingOutputSurface() {}
@@ -72,6 +70,7 @@
   if (!capabilities_.delegated_sync_points_required && context_provider())
     context_provider()->SetLostContextCallback(base::Closure());
 
+  surface_manager_->RegisterSurfaceClientId(surface_id_allocator_->client_id());
   surface_manager_->RegisterSurfaceFactoryClient(
       surface_id_allocator_->client_id(), this);
   display_->Initialize(this, surface_manager_.get(),
@@ -87,6 +86,8 @@
       surface_factory_->Destroy(delegated_surface_id_);
     surface_manager_->UnregisterSurfaceFactoryClient(
         surface_id_allocator_->client_id());
+    surface_manager_->InvalidateSurfaceClientId(
+        surface_id_allocator_->client_id());
     bound_ = false;
   }
   display_ = nullptr;
diff --git a/cc/test/test_layer_tree_host_base.cc b/cc/test/test_layer_tree_host_base.cc
index 23aff28..9a32fc4 100644
--- a/cc/test/test_layer_tree_host_base.cc
+++ b/cc/test/test_layer_tree_host_base.cc
@@ -35,7 +35,7 @@
 }
 
 std::unique_ptr<OutputSurface> TestLayerTreeHostBase::CreateOutputSurface() {
-  return FakeOutputSurface::Create3d();
+  return FakeOutputSurface::CreateDelegating3d();
 }
 
 std::unique_ptr<FakeLayerTreeHostImpl> TestLayerTreeHostBase::CreateHostImpl(
diff --git a/cc/tiles/picture_layer_tiling_set_unittest.cc b/cc/tiles/picture_layer_tiling_set_unittest.cc
index 985afbef..27cfcb5c 100644
--- a/cc/tiles/picture_layer_tiling_set_unittest.cc
+++ b/cc/tiles/picture_layer_tiling_set_unittest.cc
@@ -236,7 +236,7 @@
                float expected_scale) {
     FakeOutputSurfaceClient output_surface_client;
     std::unique_ptr<FakeOutputSurface> output_surface =
-        FakeOutputSurface::Create3d();
+        FakeOutputSurface::CreateDelegating3d();
     CHECK(output_surface->BindToClient(&output_surface_client));
 
     std::unique_ptr<SharedBitmapManager> shared_bitmap_manager(
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 10d35efc..0ce2358 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -1667,7 +1667,7 @@
   }
 
   std::unique_ptr<OutputSurface> CreateOutputSurface() override {
-    return FakeOutputSurface::Create3d();
+    return FakeOutputSurface::CreateDelegating3d();
   }
 
   LayerTreeSettings CreateSettings() override {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 77f21fd..366fafc 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -82,26 +82,28 @@
 template <typename LayerType>
 bool ComputeClipRectInTargetSpace(const LayerType* layer,
                                   const ClipNode* clip_node,
-                                  const TransformTree& transform_tree,
-                                  const EffectTree& effect_tree,
+                                  const PropertyTrees* property_trees,
                                   int target_node_id,
                                   gfx::RectF* clip_rect_in_target_space) {
   DCHECK(layer->clip_tree_index() == clip_node->id);
   DCHECK(clip_node->target_transform_id != target_node_id);
 
+  const EffectTree& effect_tree = property_trees->effect_tree;
+  const EffectNode* target_effect_node =
+      ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree);
   gfx::Transform clip_to_target;
   if (clip_node->target_transform_id > target_node_id) {
     // In this case, layer has a scroll parent. We need to keep the scale
     // at the layer's target but remove the scale at the scroll parent's
     // target.
-    if (transform_tree.ComputeTransform(clip_node->target_transform_id,
-                                        target_node_id, &clip_to_target)) {
+    if (property_trees->ComputeTransformToTarget(clip_node->target_transform_id,
+                                                 target_effect_node->id,
+                                                 &clip_to_target)) {
       // We don't have to apply surface contents scale when target is root.
       if (target_node_id != 0) {
-        const EffectNode* target_effect_node =
-            ContentsTargetEffectNode(layer->effect_tree_index(), effect_tree);
         PostConcatSurfaceContentsScale(target_effect_node, &clip_to_target);
 #if DCHECK_IS_ON()
+        const TransformTree& transform_tree = property_trees->transform_tree;
         VerifySurfaceContentsScalesMatch(layer->effect_tree_index(),
                                          target_node_id, effect_tree,
                                          transform_tree);
@@ -112,6 +114,7 @@
           effect_tree.Node(clip_node->target_effect_id);
       ConcatInverseSurfaceContentsScale(source_node, &clip_to_target);
 #if DCHECK_IS_ON()
+      const TransformTree& transform_tree = property_trees->transform_tree;
       VerifySurfaceContentsScalesMatch(clip_node->target_effect_id,
                                        clip_node->target_transform_id,
                                        effect_tree, transform_tree);
@@ -122,8 +125,9 @@
       return false;
     }
   } else {
-    if (transform_tree.ComputeTransform(clip_node->target_transform_id,
-                                        target_node_id, &clip_to_target)) {
+    if (property_trees->ComputeTransformToTarget(clip_node->target_transform_id,
+                                                 target_effect_node->id,
+                                                 &clip_to_target)) {
       *clip_rect_in_target_space = MathUtil::ProjectClippedRect(
           clip_to_target, clip_node->clip_in_target_space);
     } else {
@@ -140,11 +144,12 @@
 
 static ConditionalClip ComputeTargetRectInLocalSpace(
     gfx::RectF rect,
-    const TransformTree& transform_tree,
-    const EffectTree& effect_tree,
+    const PropertyTrees* property_trees,
     int current_transform_id,
     int target_transform_id,
     const int current_effect_id) {
+  const TransformTree& transform_tree = property_trees->transform_tree;
+  const EffectTree& effect_tree = property_trees->effect_tree;
   gfx::Transform current_to_target;
   bool success = transform_tree.ComputeTransform(
       current_transform_id, target_transform_id, &current_to_target);
@@ -164,21 +169,22 @@
 
 static ConditionalClip ComputeLocalRectInTargetSpace(
     gfx::RectF rect,
-    const TransformTree& transform_tree,
-    const EffectTree& effect_tree,
+    const PropertyTrees* property_trees,
     int current_transform_id,
     int target_transform_id,
     int target_effect_id) {
   gfx::Transform current_to_target;
-  if (!transform_tree.ComputeTransform(current_transform_id,
-                                       target_transform_id, &current_to_target))
+  if (!property_trees->ComputeTransformToTarget(
+          current_transform_id, target_effect_id, &current_to_target))
     // If transform is not invertible, cannot apply clip.
     return ConditionalClip{false, gfx::RectF()};
   // We don't have to apply surface contents scale when target is root.
   if (target_transform_id != 0) {
+    const EffectTree& effect_tree = property_trees->effect_tree;
     const EffectNode* target_effect_node = effect_tree.Node(target_effect_id);
     PostConcatSurfaceContentsScale(target_effect_node, &current_to_target);
 #if DCHECK_IS_ON()
+    const TransformTree& transform_tree = property_trees->transform_tree;
     VerifySurfaceContentsScalesMatch(target_effect_id, target_transform_id,
                                      effect_tree, transform_tree);
 #endif
@@ -193,15 +199,15 @@
 }
 
 static ConditionalClip ComputeCurrentClip(const ClipNode* clip_node,
-                                          const TransformTree& transform_tree,
-                                          const EffectTree& effect_tree,
+                                          const PropertyTrees* property_trees,
                                           int target_transform_id,
                                           int target_effect_id) {
   if (clip_node->transform_id != target_transform_id)
-    return ComputeLocalRectInTargetSpace(clip_node->clip, transform_tree,
-                                         effect_tree, clip_node->transform_id,
+    return ComputeLocalRectInTargetSpace(clip_node->clip, property_trees,
+                                         clip_node->transform_id,
                                          target_transform_id, target_effect_id);
 
+  const EffectTree& effect_tree = property_trees->effect_tree;
   gfx::RectF current_clip = clip_node->clip;
   gfx::Vector2dF surface_contents_scale =
       effect_tree.Node(target_effect_id)->surface_contents_scale;
@@ -211,11 +217,12 @@
 }
 
 static ConditionalClip ComputeAccumulatedClip(
-    const ClipTree& clip_tree,
+    const PropertyTrees* property_trees,
     int local_clip_id,
-    const EffectTree& effect_tree,
-    int target_id,
-    const TransformTree& transform_tree) {
+    int target_id) {
+  const ClipTree& clip_tree = property_trees->clip_tree;
+  const EffectTree& effect_tree = property_trees->effect_tree;
+
   const ClipNode* clip_node = clip_tree.Node(local_clip_id);
   const EffectNode* target_node = effect_tree.Node(target_id);
   int target_transform_id = target_node->transform_id;
@@ -259,7 +266,7 @@
     return ConditionalClip{false, gfx::RectF()};
 
   ConditionalClip current_clip = ComputeCurrentClip(
-      clip_node, transform_tree, effect_tree, target_transform_id, target_id);
+      clip_node, property_trees, target_transform_id, target_id);
   is_clipped = current_clip.is_clipped;
   gfx::RectF accumulated_clip = current_clip.clip_rect;
 
@@ -270,7 +277,7 @@
       continue;
     }
     ConditionalClip current_clip = ComputeCurrentClip(
-        clip_node, transform_tree, effect_tree, target_transform_id, target_id);
+        clip_node, property_trees, target_transform_id, target_id);
 
     // If transform is not invertible, no clip will be applied.
     if (!current_clip.is_clipped)
@@ -288,10 +295,9 @@
 template <typename LayerType>
 void CalculateClipRects(
     const typename LayerType::LayerListType& visible_layer_list,
-    const ClipTree& clip_tree,
-    const TransformTree& transform_tree,
-    const EffectTree& effect_tree,
+    const PropertyTrees* property_trees,
     bool non_root_surfaces_enabled) {
+  const ClipTree& clip_tree = property_trees->clip_tree;
   for (auto& layer : visible_layer_list) {
     const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
     if (!non_root_surfaces_enabled) {
@@ -306,6 +312,7 @@
         !clip_node->layers_are_clipped && !clip_node->target_is_clipped;
 
     if (!fully_visible) {
+      const TransformTree& transform_tree = property_trees->transform_tree;
       const TransformNode* transform_node =
           transform_tree.Node(layer->transform_tree_index());
       int target_node_id = transform_tree.ContentTargetId(transform_node->id);
@@ -324,8 +331,8 @@
           continue;
 
         // Compute the clip rect in target space and store it.
-        if (!ComputeClipRectInTargetSpace(layer, clip_node, transform_tree,
-                                          effect_tree, target_node_id,
+        if (!ComputeClipRectInTargetSpace(layer, clip_node, property_trees,
+                                          target_node_id,
                                           &clip_rect_in_target_space))
           continue;
       }
@@ -341,33 +348,33 @@
 
 bool GetLayerClipRect(const scoped_refptr<Layer> layer,
                       const ClipNode* clip_node,
-                      const TransformTree& transform_tree,
-                      const EffectTree& effect_tree,
+                      const PropertyTrees* property_trees,
                       int target_node_id,
                       gfx::RectF* clip_rect_in_target_space) {
-  return ComputeClipRectInTargetSpace(layer.get(), clip_node, transform_tree,
-                                      effect_tree, target_node_id,
+  return ComputeClipRectInTargetSpace(layer.get(), clip_node, property_trees,
+                                      target_node_id,
                                       clip_rect_in_target_space);
 }
 
 bool GetLayerClipRect(const LayerImpl* layer,
                       const ClipNode* clip_node,
-                      const TransformTree& transform_tree,
-                      const EffectTree& effect_tree,
+                      const PropertyTrees* property_trees,
                       int target_node_id,
                       gfx::RectF* clip_rect_in_target_space) {
   // This is equivalent of calling ComputeClipRectInTargetSpace.
   *clip_rect_in_target_space = gfx::RectF(layer->clip_rect());
-  return transform_tree.Node(target_node_id)->ancestors_are_invertible;
+  return property_trees->transform_tree.Node(target_node_id)
+      ->ancestors_are_invertible;
 }
 
 template <typename LayerType>
 void CalculateVisibleRects(
     const typename LayerType::LayerListType& visible_layer_list,
-    const ClipTree& clip_tree,
-    const TransformTree& transform_tree,
-    const EffectTree& effect_tree,
+    const PropertyTrees* property_trees,
     bool non_root_surfaces_enabled) {
+  const EffectTree& effect_tree = property_trees->effect_tree;
+  const TransformTree& transform_tree = property_trees->transform_tree;
+  const ClipTree& clip_tree = property_trees->clip_tree;
   for (auto& layer : visible_layer_list) {
     gfx::Size layer_bounds = layer->bounds();
 
@@ -375,9 +382,9 @@
         effect_tree.ClosestAncestorWithCopyRequest(layer->effect_tree_index());
     if (effect_ancestor_with_copy_request > 1) {
       // Non root copy request.
-      ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
-          clip_tree, layer->clip_tree_index(), effect_tree,
-          effect_ancestor_with_copy_request, transform_tree);
+      ConditionalClip accumulated_clip_rect =
+          ComputeAccumulatedClip(property_trees, layer->clip_tree_index(),
+                                 effect_ancestor_with_copy_request);
       if (!accumulated_clip_rect.is_clipped) {
         layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
         continue;
@@ -389,7 +396,7 @@
       const EffectNode* copy_request_effect_node =
           effect_tree.Node(effect_ancestor_with_copy_request);
       ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace(
-          accumulated_clip_in_copy_request_space, transform_tree, effect_tree,
+          accumulated_clip_in_copy_request_space, property_trees,
           copy_request_effect_node->transform_id, layer->transform_tree_index(),
           copy_request_effect_node->id);
 
@@ -463,8 +470,7 @@
       // the combined clip has even the clip parent's target's clip baked into
       // it and as our target is different, we don't want to use it in our
       // visible rect computation.
-      if (!GetLayerClipRect(layer, clip_node, transform_tree, effect_tree,
-                            target_node_id,
+      if (!GetLayerClipRect(layer, clip_node, property_trees, target_node_id,
                             &combined_clip_rect_in_target_space)) {
         layer->set_visible_layer_rect(gfx::Rect(layer_bounds));
         continue;
@@ -740,10 +746,9 @@
                      1.0 / effect_node->surface_contents_scale.y());
 }
 
-void ComputeClips(ClipTree* clip_tree,
-                  const TransformTree& transform_tree,
-                  const EffectTree& effect_tree,
+void ComputeClips(PropertyTrees* property_trees,
                   bool non_root_surfaces_enabled) {
+  ClipTree* clip_tree = &property_trees->clip_tree;
   if (!clip_tree->needs_update())
     return;
   for (int i = 1; i < static_cast<int>(clip_tree->size()); ++i) {
@@ -755,6 +760,8 @@
       clip_node->combined_clip_in_target_space = clip_node->clip;
       continue;
     }
+    const TransformTree& transform_tree = property_trees->transform_tree;
+    const EffectTree& effect_tree = property_trees->effect_tree;
     const TransformNode* transform_node =
         transform_tree.Node(clip_node->transform_id);
     ClipNode* parent_clip_node = clip_tree->parent(clip_node);
@@ -781,8 +788,8 @@
     if (parent_target_transform_node &&
         parent_target_transform_node->id != clip_node->target_transform_id &&
         non_root_surfaces_enabled) {
-      success &= transform_tree.ComputeTransform(
-          parent_target_transform_node->id, clip_node->target_transform_id,
+      success &= property_trees->ComputeTransformToTarget(
+          parent_target_transform_node->id, clip_node->target_effect_id,
           &parent_to_current);
       // We don't have to apply surface contents scale when target is root.
       if (clip_node->target_transform_id != 0) {
@@ -862,9 +869,8 @@
                  clip_node->target_transform_id) {
         source_to_target = transform_tree.ToTarget(clip_node->transform_id);
       } else {
-        success = transform_tree.ComputeTransform(
-            transform_node->id, clip_node->target_transform_id,
-            &source_to_target);
+        success = property_trees->ComputeTransformToTarget(
+            transform_node->id, clip_node->target_effect_id, &source_to_target);
         // We don't have to apply surface contents scale when target is root.
         if (clip_node->target_transform_id != 0) {
           const EffectNode* target_effect_node =
@@ -943,7 +949,6 @@
 static void ComputeClipsWithEffectTree(PropertyTrees* property_trees) {
   EffectTree* effect_tree = &property_trees->effect_tree;
   const ClipTree* clip_tree = &property_trees->clip_tree;
-  const TransformTree* transform_tree = &property_trees->transform_tree;
   EffectNode* root_effect_node = effect_tree->Node(1);
   const RenderSurfaceImpl* root_render_surface =
       root_effect_node->render_surface;
@@ -957,9 +962,8 @@
   for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) {
     EffectNode* effect_node = effect_tree->Node(i);
     const EffectNode* target_node = effect_tree->Node(effect_node->target_id);
-    ConditionalClip accumulated_clip_rect =
-        ComputeAccumulatedClip(*clip_tree, effect_node->clip_id, *effect_tree,
-                               target_node->id, *transform_tree);
+    ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
+        property_trees, effect_node->clip_id, target_node->id);
     gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
     const RenderSurfaceImpl* render_surface = effect_node->render_surface;
     if (render_surface && render_surface->is_clipped()) {
@@ -977,7 +981,6 @@
                                  const LayerImpl* layer) {
   const EffectTree* effect_tree = &property_trees->effect_tree;
   const ClipTree* clip_tree = &property_trees->clip_tree;
-  const TransformTree* transform_tree = &property_trees->transform_tree;
   const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index());
   const EffectNode* target_node =
       effect_node->has_render_surface
@@ -989,9 +992,8 @@
     target_node = effect_tree->Node(1);
   }
 
-  ConditionalClip accumulated_clip_rect =
-      ComputeAccumulatedClip(*clip_tree, layer->clip_tree_index(), *effect_tree,
-                             target_node->id, *transform_tree);
+  ConditionalClip accumulated_clip_rect = ComputeAccumulatedClip(
+      property_trees, layer->clip_tree_index(), target_node->id);
 
   gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect;
 
@@ -1025,13 +1027,13 @@
   const int source_id = layer->transform_tree_index();
   int destination_id = FindTargetTransformTreeIndexFromEffectTree(
       property_trees->effect_tree, layer->effect_tree_index());
+  const EffectNode* target_effect_node = ContentsTargetEffectNode(
+      layer->effect_tree_index(), property_trees->effect_tree);
   gfx::Transform draw_transform;
-  property_trees->transform_tree.ComputeTransform(source_id, destination_id,
-                                                  &draw_transform);
+  property_trees->ComputeTransformToTarget(source_id, target_effect_node->id,
+                                           &draw_transform);
   // We don't have to apply surface contents scale when target is root.
   if (destination_id != 0) {
-    const EffectNode* target_effect_node = ContentsTargetEffectNode(
-        layer->effect_tree_index(), property_trees->effect_tree);
     PostConcatSurfaceContentsScale(target_effect_node, &draw_transform);
 #if DCHECK_IS_ON()
     VerifySurfaceContentsScalesMatch(layer->effect_tree_index(), destination_id,
@@ -1074,20 +1076,15 @@
   // Computation of clips uses surface contents scale which is updated while
   // computing effects. So, ComputeEffects should be before ComputeClips.
   ComputeEffects(&property_trees->effect_tree);
-  ComputeClips(&property_trees->clip_tree, property_trees->transform_tree,
-               property_trees->effect_tree, can_render_to_separate_surface);
+  ComputeClips(property_trees, can_render_to_separate_surface);
 
   FindLayersThatNeedUpdates(root_layer->layer_tree_impl(),
                             property_trees->transform_tree,
                             property_trees->effect_tree, visible_layer_list);
-  CalculateClipRects<LayerImpl>(*visible_layer_list, property_trees->clip_tree,
-                                property_trees->transform_tree,
-                                property_trees->effect_tree,
+  CalculateClipRects<LayerImpl>(*visible_layer_list, property_trees,
                                 can_render_to_separate_surface);
-  CalculateVisibleRects<LayerImpl>(
-      *visible_layer_list, property_trees->clip_tree,
-      property_trees->transform_tree, property_trees->effect_tree,
-      can_render_to_separate_surface);
+  CalculateVisibleRects<LayerImpl>(*visible_layer_list, property_trees,
+                                   can_render_to_separate_surface);
 }
 
 void UpdatePropertyTrees(PropertyTrees* property_trees,
@@ -1105,16 +1102,13 @@
   // Computation of clips uses surface contents scale which is updated while
   // computing effects. So, ComputeEffects should be before ComputeClips.
   ComputeEffects(&property_trees->effect_tree);
-  ComputeClips(&property_trees->clip_tree, property_trees->transform_tree,
-               property_trees->effect_tree, can_render_to_separate_surface);
+  ComputeClips(property_trees, can_render_to_separate_surface);
 }
 
 void ComputeVisibleRectsForTesting(PropertyTrees* property_trees,
                                    bool can_render_to_separate_surface,
                                    LayerList* update_layer_list) {
-  CalculateVisibleRects<Layer>(*update_layer_list, property_trees->clip_tree,
-                               property_trees->transform_tree,
-                               property_trees->effect_tree,
+  CalculateVisibleRects<Layer>(*update_layer_list, property_trees,
                                can_render_to_separate_surface);
 }
 
@@ -1218,9 +1212,10 @@
   return xform;
 }
 
-static void SetSurfaceDrawTransform(const TransformTree& transform_tree,
-                                    const EffectTree& effect_tree,
+static void SetSurfaceDrawTransform(const PropertyTrees* property_trees,
                                     RenderSurfaceImpl* render_surface) {
+  const TransformTree& transform_tree = property_trees->transform_tree;
+  const EffectTree& effect_tree = property_trees->effect_tree;
   const TransformNode* transform_node =
       transform_tree.Node(render_surface->TransformTreeIndex());
   const EffectNode* effect_node =
@@ -1234,12 +1229,12 @@
   gfx::Transform render_surface_transform;
   const TransformNode* target_transform_node =
       transform_tree.Node(transform_tree.TargetId(transform_node->id));
-  transform_tree.ComputeTransform(transform_node->id, target_transform_node->id,
-                                  &render_surface_transform);
+  const EffectNode* target_effect_node =
+      effect_tree.Node(effect_node->target_id);
+  property_trees->ComputeTransformToTarget(
+      transform_node->id, target_effect_node->id, &render_surface_transform);
   // We don't have to apply surface contents scale when target is root.
   if (target_transform_node->id != 0) {
-    const EffectNode* target_effect_node =
-        effect_tree.Node(effect_node->target_id);
     PostConcatSurfaceContentsScale(target_effect_node,
                                    &render_surface_transform);
 #if DCHECK_IS_ON()
@@ -1266,14 +1261,15 @@
 }
 
 static void SetSurfaceClipRect(const ClipNode* parent_clip_node,
-                               const TransformTree& transform_tree,
-                               const EffectTree& effect_tree,
+                               const PropertyTrees* property_trees,
                                RenderSurfaceImpl* render_surface) {
   if (!render_surface->is_clipped()) {
     render_surface->SetClipRect(gfx::Rect());
     return;
   }
 
+  const EffectTree& effect_tree = property_trees->effect_tree;
+  const TransformTree& transform_tree = property_trees->transform_tree;
   const TransformNode* transform_node =
       transform_tree.Node(render_surface->TransformTreeIndex());
   if (transform_tree.TargetId(transform_node->id) ==
@@ -1287,9 +1283,11 @@
   // the parent clip node's clip rect is in clip parent's target space and not
   // our target space. We need to transform it to our target space.
   gfx::Transform clip_parent_target_to_target;
-  const bool success = transform_tree.ComputeTransform(
-      parent_clip_node->target_transform_id,
-      transform_tree.TargetId(transform_node->id),
+  const EffectNode* effect_node =
+      effect_tree.Node(render_surface->EffectTreeIndex());
+  int target_effect_id = effect_node->target_id;
+  const bool success = property_trees->ComputeTransformToTarget(
+      parent_clip_node->target_transform_id, target_effect_id,
       &clip_parent_target_to_target);
 
   if (!success) {
@@ -1381,18 +1379,19 @@
 
 static gfx::Transform ReplicaToSurfaceTransform(
     const RenderSurfaceImpl* render_surface,
-    const TransformTree& transform_tree,
-    const EffectTree& effect_tree) {
+    const PropertyTrees* property_trees) {
   gfx::Transform replica_to_surface;
   if (!render_surface->HasReplica())
     return replica_to_surface;
   const LayerImpl* replica_layer = render_surface->ReplicaLayer();
+  const EffectTree& effect_tree = property_trees->effect_tree;
   const EffectNode* surface_effect_node =
       effect_tree.Node(render_surface->EffectTreeIndex());
   if (render_surface->TransformTreeIndex() != 0) {
     replica_to_surface.Scale(surface_effect_node->surface_contents_scale.x(),
                              surface_effect_node->surface_contents_scale.y());
 #if DCHECK_IS_ON()
+    const TransformTree& transform_tree = property_trees->transform_tree;
     VerifySurfaceContentsScalesMatch(render_surface->EffectTreeIndex(),
                                      render_surface->TransformTreeIndex(),
                                      effect_tree, transform_tree);
@@ -1401,9 +1400,9 @@
   replica_to_surface.Translate(replica_layer->offset_to_transform_parent().x(),
                                replica_layer->offset_to_transform_parent().y());
   gfx::Transform replica_transform_node_to_surface;
-  transform_tree.ComputeTransform(replica_layer->transform_tree_index(),
-                                  render_surface->TransformTreeIndex(),
-                                  &replica_transform_node_to_surface);
+  property_trees->ComputeTransformToTarget(
+      replica_layer->transform_tree_index(), render_surface->EffectTreeIndex(),
+      &replica_transform_node_to_surface);
   replica_to_surface.PreconcatTransform(replica_transform_node_to_surface);
   if (surface_effect_node->surface_contents_scale.x() != 0 &&
       surface_effect_node->surface_contents_scale.y() != 0) {
@@ -1467,17 +1466,15 @@
 
   SetSurfaceIsClipped(clip_node, render_surface);
   SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface);
-  SetSurfaceDrawTransform(property_trees->transform_tree,
-                          property_trees->effect_tree, render_surface);
+  SetSurfaceDrawTransform(property_trees, render_surface);
   render_surface->SetScreenSpaceTransform(
       property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale(
           render_surface->TransformTreeIndex(),
           render_surface->EffectTreeIndex()));
 
   if (render_surface->HasReplica()) {
-    gfx::Transform replica_to_surface = ReplicaToSurfaceTransform(
-        render_surface, property_trees->transform_tree,
-        property_trees->effect_tree);
+    gfx::Transform replica_to_surface =
+        ReplicaToSurfaceTransform(render_surface, property_trees);
     render_surface->SetReplicaDrawTransform(render_surface->draw_transform() *
                                             replica_to_surface);
     render_surface->SetReplicaScreenSpaceTransform(
@@ -1488,8 +1485,7 @@
   }
 
   SetSurfaceClipRect(property_trees->clip_tree.parent(clip_node),
-                     property_trees->transform_tree,
-                     property_trees->effect_tree, render_surface);
+                     property_trees, render_surface);
 }
 
 #if DCHECK_IS_ON()
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index 6e6ecb57..b66c40f 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -3707,7 +3707,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
 
@@ -3795,7 +3796,8 @@
   FakeImplTaskRunnerProvider task_runner_provider;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   FakeLayerTreeHostImpl host_impl(&task_runner_provider, &shared_bitmap_manager,
                                   &task_graph_runner);
 
@@ -8503,6 +8505,34 @@
             descendant_of_animation->visible_layer_rect_for_testing());
 }
 
+// Verify that having animated opacity but current opacity 1 still creates
+// a render surface.
+TEST_F(LayerTreeHostCommonTest, AnimatedOpacityCreatesRenderSurface) {
+  LayerImpl* root = root_layer_for_testing();
+  LayerImpl* child = AddChild<LayerImpl>(root);
+  LayerImpl* grandchild = AddChild<LayerImpl>(child);
+  child->SetDrawsContent(true);
+  grandchild->SetDrawsContent(true);
+
+  gfx::Transform identity_transform;
+  SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false);
+  SetLayerPropertiesForTesting(child, identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false);
+  SetLayerPropertiesForTesting(grandchild, identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false);
+
+  SetElementIdsForTesting();
+  AddOpacityTransitionToElementWithPlayer(child->element_id(), timeline_impl(),
+                                          10.0, 1.f, 0.2f, false);
+  ExecuteCalculateDrawProperties(root);
+
+  EXPECT_EQ(1.f, child->Opacity());
+  EXPECT_TRUE(root->has_render_surface());
+  EXPECT_TRUE(child->has_render_surface());
+  EXPECT_FALSE(grandchild->has_render_surface());
+}
+
 // Verify that having an animated filter (but no current filter, as these
 // are mutually exclusive) correctly creates a render surface.
 TEST_F(LayerTreeHostCommonTest, AnimatedFilterCreatesRenderSurface) {
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 17d1bfba..db3fcbd 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -573,8 +573,7 @@
 
 TEST_F(LayerTreeHostImplTest, ResourcelessDrawWithEmptyViewport) {
   CreateHostImpl(DefaultSettings(),
-                 FakeOutputSurface::CreateDelegatingSoftware(
-                     base::WrapUnique(new SoftwareOutputDevice())));
+                 FakeOutputSurface::CreateDelegatingSoftware());
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
@@ -3800,8 +3799,7 @@
 TEST_F(LayerTreeHostImplTest,
        PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
   CreateHostImpl(DefaultSettings(),
-                 FakeOutputSurface::CreateDelegatingSoftware(
-                     base::WrapUnique(new SoftwareOutputDevice())));
+                 FakeOutputSurface::CreateDelegatingSoftware());
 
   const gfx::Transform external_transform;
   const gfx::Rect external_viewport;
@@ -6759,10 +6757,8 @@
       did_activate_pending_tree_(false) {}
 
   std::unique_ptr<OutputSurface> CreateFakeOutputSurface(bool software) {
-    if (software) {
-      return FakeOutputSurface::CreateDelegatingSoftware(
-          base::WrapUnique(new SoftwareOutputDevice()));
-    }
+    if (software)
+      return FakeOutputSurface::CreateDelegatingSoftware();
     return FakeOutputSurface::CreateDelegating3d();
   }
 
@@ -7643,9 +7639,8 @@
 TEST_F(LayerTreeHostImplTest,
        ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
   set_reduce_memory_result(false);
-  EXPECT_TRUE(CreateHostImpl(
-      DefaultSettings(), FakeOutputSurface::CreateDelegatingSoftware(
-                             base::WrapUnique(new CountingSoftwareDevice))));
+  EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
+                             FakeOutputSurface::CreateDelegatingSoftware()));
 
   const gfx::Transform external_transform;
   const gfx::Rect external_viewport;
@@ -10857,8 +10852,7 @@
   EXPECT_TRUE(host_impl_->use_gpu_rasterization());
 
   // Re-initialize with a software output surface.
-  output_surface_ = FakeOutputSurface::CreateDelegatingSoftware(
-      base::WrapUnique(new SoftwareOutputDevice));
+  output_surface_ = FakeOutputSurface::CreateDelegatingSoftware();
   host_impl_->InitializeRenderer(output_surface_.get());
   EXPECT_FALSE(host_impl_->use_gpu_rasterization());
 }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index d76c9df..baa1618b 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -73,27 +73,7 @@
 namespace cc {
 namespace {
 
-class LayerTreeHostTest : public LayerTreeTest {
- protected:
-  // These tests are not pixel tests, and they use a fake output surface,
-  // while storing pointers to the test-types for tests to poke at.
-  std::unique_ptr<OutputSurface> CreateOutputSurface() override {
-    auto context = TestContextProvider::Create();
-    context_provider_ = context.get();
-    auto ret = delegating_renderer()
-                   ? FakeOutputSurface::CreateDelegating3d(std::move(context))
-                   : FakeOutputSurface::Create3d(std::move(context));
-    output_surface_ = ret.get();
-    return std::move(ret);
-  }
-
-  FakeOutputSurface* fake_output_surface() { return output_surface_; }
-  TestContextProvider* test_context_provider() { return context_provider_; }
-
- private:
-  FakeOutputSurface* output_surface_ = nullptr;
-  TestContextProvider* context_provider_ = nullptr;
-};
+class LayerTreeHostTest : public LayerTreeTest {};
 
 class LayerTreeHostTestHasImplThreadTest : public LayerTreeHostTest {
  public:
@@ -2979,7 +2959,9 @@
   }
 
   void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
-    auto* context = test_context_provider()->TestContext3d();
+    auto* context = static_cast<TestContextProvider*>(
+                        impl->output_surface()->context_provider())
+                        ->TestContext3d();
 
     int frame = impl->active_tree()->source_frame_number();
     switch (frame) {
@@ -4040,13 +4022,13 @@
       case 1:
         EXPECT_EQ(0, callback_count_);
         callback_count_ = 0;
-        SetCallback(true);
+        SetCallback(host_impl, true);
         PostSetNeedsCommitToMainThread();
         break;
       case 2:
         EXPECT_EQ(1, callback_count_);
         callback_count_ = 0;
-        SetCallback(false);
+        SetCallback(host_impl, false);
         PostSetNeedsCommitToMainThread();
         break;
       case 3:
@@ -4065,8 +4047,8 @@
 
   void AfterTest() override { EXPECT_EQ(3, num_commits_); }
 
-  void SetCallback(bool enable) {
-    fake_output_surface()->SetTreeActivationCallback(
+  void SetCallback(LayerTreeHostImpl* host_impl, bool enable) {
+    host_impl->SetTreeActivationCallback(
         enable
             ? base::Bind(
                   &LayerTreeHostTestTreeActivationCallback::ActivationCallback,
@@ -4660,9 +4642,9 @@
         base::AutoLock lock(swap_promise_result_.lock);
         EXPECT_FALSE(swap_promise_result_.did_activate_called);
         EXPECT_FALSE(swap_promise_result_.did_swap_called);
-        SetCallback(true);
+        SetCallback(host_impl, true);
       } else {
-        SetCallback(false);
+        SetCallback(host_impl, false);
       }
     }
   }
@@ -4681,8 +4663,8 @@
     EXPECT_TRUE(swap_promise_result_.did_activate_called);
   }
 
-  void SetCallback(bool enable) {
-    fake_output_surface()->SetTreeActivationCallback(
+  void SetCallback(LayerTreeHostImpl* host_impl, bool enable) {
+    host_impl->SetTreeActivationCallback(
         enable
             ? base::Bind(&LayerTreeHostTestKeepSwapPromise::ActivationCallback,
                          base::Unretained(this))
@@ -6804,6 +6786,14 @@
 // frame's metadata.
 class LayerTreeHostTestPaintedDeviceScaleFactor : public LayerTreeHostTest {
  protected:
+  LayerTreeHostTestPaintedDeviceScaleFactor() = default;
+
+  std::unique_ptr<OutputSurface> CreateOutputSurface() override {
+    auto ret = FakeOutputSurface::CreateDelegating3d();
+    fake_output_surface_ = ret.get();
+    return std::move(ret);
+  }
+
   void BeginTest() override {
     layer_tree_host()->SetPaintedDeviceScaleFactor(2.0f);
     EXPECT_EQ(1.0f, layer_tree_host()->device_scale_factor());
@@ -6818,11 +6808,13 @@
   void SwapBuffersCompleteOnThread() override {
     EXPECT_EQ(
         2.0f,
-        fake_output_surface()->last_sent_frame()->metadata.device_scale_factor);
+        fake_output_surface_->last_sent_frame()->metadata.device_scale_factor);
     EndTest();
   }
 
   void AfterTest() override {}
+
+  FakeOutputSurface* fake_output_surface_ = nullptr;
 };
 
 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPaintedDeviceScaleFactor);
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 7e0a729..c9a0291 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -96,10 +96,8 @@
       context3d_->set_have_extension_egl_image(true);
     }
 
-    if (delegating_renderer())
-      return FakeOutputSurface::CreateDelegating3d(std::move(context3d));
-    else
-      return FakeOutputSurface::Create3d(std::move(context3d));
+    DCHECK(delegating_renderer());
+    return FakeOutputSurface::CreateDelegating3d(std::move(context3d));
   }
 
   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
@@ -780,48 +778,24 @@
 };
 
 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
-       LoseAfterEvict_SingleThread_DirectRenderer) {
-  lose_after_evict_ = true;
-  RunTest(CompositorMode::SINGLE_THREADED, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
        LoseAfterEvict_SingleThread_DelegatingRenderer) {
   lose_after_evict_ = true;
   RunTest(CompositorMode::SINGLE_THREADED, true);
 }
 
 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
-       LoseAfterEvict_MultiThread_DirectRenderer) {
-  lose_after_evict_ = true;
-  RunTest(CompositorMode::THREADED, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
        LoseAfterEvict_MultiThread_DelegatingRenderer) {
   lose_after_evict_ = true;
   RunTest(CompositorMode::THREADED, true);
 }
 
 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
-       LoseBeforeEvict_SingleThread_DirectRenderer) {
-  lose_after_evict_ = false;
-  RunTest(CompositorMode::SINGLE_THREADED, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
        LoseBeforeEvict_SingleThread_DelegatingRenderer) {
   lose_after_evict_ = false;
   RunTest(CompositorMode::SINGLE_THREADED, true);
 }
 
 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
-       LoseBeforeEvict_MultiThread_DirectRenderer) {
-  lose_after_evict_ = false;
-  RunTest(CompositorMode::THREADED, false);
-}
-
-TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
        LoseBeforeEvict_MultiThread_DelegatingRenderer) {
   lose_after_evict_ = false;
   RunTest(CompositorMode::THREADED, true);
@@ -903,7 +877,7 @@
   LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
     context_should_support_io_surface_ = true;
 
-    child_output_surface_ = FakeOutputSurface::Create3d();
+    child_output_surface_ = FakeOutputSurface::CreateDelegating3d();
     child_output_surface_->BindToClient(&output_surface_client_);
     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
     child_resource_provider_ = FakeResourceProvider::Create(
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc
index f64b2fcc..623d403 100644
--- a/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -131,8 +131,10 @@
       return FakeOutputSurface::CreateSoftware(
           base::WrapUnique(new SoftwareOutputDevice));
     }
+
     std::unique_ptr<FakeOutputSurface> output_surface =
-        FakeOutputSurface::Create3d();
+        FakeOutputSurface::Create3d(TestContextProvider::Create(),
+                                    TestContextProvider::CreateWorker());
     TestContextSupport* context_support = static_cast<TestContextSupport*>(
         output_surface->context_provider()->ContextSupport());
     context_support->set_out_of_order_callbacks(out_of_order_callbacks_);
diff --git a/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc b/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc
index f56109b0..a9b1993 100644
--- a/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc
+++ b/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc
@@ -12,7 +12,7 @@
 namespace {
 
 TEST(LayerTreeHostRecordGpuHistogramTest, SingleThreaded) {
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   LayerTreeSettings settings;
   std::unique_ptr<FakeLayerTreeHost> host =
@@ -23,7 +23,7 @@
 }
 
 TEST(LayerTreeHostRecordGpuHistogramTest, Threaded) {
-  FakeLayerTreeHostClient host_client(FakeLayerTreeHostClient::DIRECT_3D);
+  FakeLayerTreeHostClient host_client;
   TestTaskGraphRunner task_graph_runner;
   LayerTreeSettings settings;
   std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 484cbc0..03c34bbc 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1351,20 +1351,17 @@
 TEST(LayerTreeHostFlingTest, DidStopFlingingThread) {
   base::Thread impl_thread("cc");
   ASSERT_TRUE(impl_thread.Start());
+  ASSERT_TRUE(impl_thread.task_runner());
 
   bool received_stop_flinging = false;
   LayerTreeSettings settings;
 
-  ThreadCheckingInputHandlerClient input_handler_client(
-      impl_thread.task_runner().get(), &received_stop_flinging);
-  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
-
-  ASSERT_TRUE(impl_thread.task_runner());
+  StubLayerTreeHostClient layer_tree_host_client;
   TestSharedBitmapManager shared_bitmap_manager;
   TestTaskGraphRunner task_graph_runner;
 
   LayerTreeHost::InitParams params;
-  params.client = &client;
+  params.client = &layer_tree_host_client;
   params.shared_bitmap_manager = &shared_bitmap_manager;
   params.task_graph_runner = &task_graph_runner;
   params.settings = &settings;
@@ -1373,6 +1370,8 @@
   std::unique_ptr<LayerTreeHost> layer_tree_host =
       LayerTreeHost::CreateThreaded(impl_thread.task_runner(), &params);
 
+  ThreadCheckingInputHandlerClient input_handler_client(
+      impl_thread.task_runner().get(), &received_stop_flinging);
   impl_thread.task_runner()->PostTask(
       FROM_HERE, base::Bind(&BindInputHandlerOnCompositorThread,
                             layer_tree_host->GetInputHandler(),
diff --git a/cc/trees/layer_tree_host_unittest_serialization.cc b/cc/trees/layer_tree_host_unittest_serialization.cc
index 1cc36bd..fbae1b82 100644
--- a/cc/trees/layer_tree_host_unittest_serialization.cc
+++ b/cc/trees/layer_tree_host_unittest_serialization.cc
@@ -63,9 +63,7 @@
  public:
   LayerTreeHostSerializationTest()
       : image_serialization_processor_(
-            base::WrapUnique(new FakeImageSerializationProcessor)),
-        client_src_(FakeLayerTreeHostClient::DIRECT_3D),
-        client_dst_(FakeLayerTreeHostClient::DIRECT_3D) {}
+            base::MakeUnique<FakeImageSerializationProcessor>()) {}
 
  protected:
   void SetUp() override {
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index b0b3ae30..2904658 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1001,9 +1001,9 @@
           // We are calculating transform between two render surfaces. So, we
           // need to apply the surface contents scale at target and remove the
           // surface contents scale at source.
-          property_trees()->transform_tree.ComputeTransform(
+          property_trees()->ComputeTransformToTarget(
               it->render_surface()->TransformTreeIndex(),
-              occlusion_surface->TransformTreeIndex(), &draw_transform);
+              occlusion_surface->EffectTreeIndex(), &draw_transform);
           // We don't have to apply surface contents scale when target is root.
           if (occlusion_surface->TransformTreeIndex() != 0) {
             const EffectNode* occlusion_effect_node =
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index 665942f..ee02d66 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -24,7 +24,8 @@
 
 class LayerTreeImplTest : public LayerTreeHostCommonTest {
  public:
-  LayerTreeImplTest() : output_surface_(FakeOutputSurface::Create3d()) {
+  LayerTreeImplTest()
+      : output_surface_(FakeOutputSurface::CreateDelegating3d()) {
     LayerTreeSettings settings;
     settings.layer_transforms_should_scale_layer_contents = true;
     settings.verify_clip_tree_calculations = true;
@@ -116,7 +117,8 @@
   LayerTreeSettings settings;
   settings.verify_clip_tree_calculations = true;
   settings.verify_transform_tree_calculations = true;
-  std::unique_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d();
+  std::unique_ptr<OutputSurface> output_surface =
+      FakeOutputSurface::CreateDelegating3d();
   std::unique_ptr<FakeLayerTreeHostImpl> host_impl;
   host_impl.reset(new FakeLayerTreeHostImpl(settings, &task_runner_provider,
                                             &shared_bitmap_manager,
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index 48eaefc..709b880 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -87,7 +87,6 @@
  protected:
   explicit OcclusionTrackerTest(bool opaque_layers)
       : opaque_layers_(opaque_layers),
-        client_(FakeLayerTreeHostClient::DIRECT_3D),
         host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_)),
         next_layer_impl_id_(1) {}
 
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index ef0a2f3..f1dd7ca 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -773,9 +773,8 @@
             parent_transform_node->sorting_context_id ==
                 transform_node->sorting_context_id) {
           gfx::Transform surface_draw_transform;
-          transform_tree.ComputeTransform(
-              transform_node->id, transform_tree.TargetId(transform_node->id),
-              &surface_draw_transform);
+          property_trees()->ComputeTransformToTarget(
+              transform_node->id, node->target_id, &surface_draw_transform);
           node->hidden_by_backface_visibility =
               surface_draw_transform.IsBackFaceVisible();
         } else {
@@ -1876,4 +1875,33 @@
   return screen_space_transform;
 }
 
+bool PropertyTrees::ComputeTransformToTarget(int transform_id,
+                                             int effect_id,
+                                             gfx::Transform* transform) const {
+  transform->MakeIdentity();
+
+  int destination_transform_id;
+  if (effect_id == -1) {
+    // This can happen when PaintArtifactCompositor builds property trees as
+    // it doesn't set effect ids on clip nodes. We want to compute transform
+    // to the root in this case.
+    destination_transform_id = 0;
+  } else {
+    const EffectNode* effect_node = effect_tree.Node(effect_id);
+    DCHECK(effect_node->has_render_surface || effect_node->id == 0);
+    destination_transform_id = effect_node->transform_id;
+  }
+
+  if (transform_id == destination_transform_id)
+    return true;
+
+  if (transform_id > destination_transform_id) {
+    return transform_tree.CombineTransformsBetween(
+        transform_id, destination_transform_id, transform);
+  }
+
+  return transform_tree.CombineInversesBetween(
+      transform_id, destination_transform_id, transform);
+}
+
 }  // namespace cc
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index dbc9b4d..86d95ab7 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -237,11 +237,6 @@
   void FromProtobuf(const proto::PropertyTree& proto,
                     std::unordered_map<int, int>* node_id_to_index_map);
 
- private:
-  // Returns true iff the node at |desc_id| is a descendant of the node at
-  // |anc_id|.
-  bool IsDescendant(int desc_id, int anc_id) const;
-
   // Computes the combined transform between |source_id| and |dest_id| and
   // returns false if the inverse of a singular transform was used. These two
   // nodes must be on the same ancestor chain.
@@ -256,6 +251,11 @@
                               int dest_id,
                               gfx::Transform* transform) const;
 
+ private:
+  // Returns true iff the node at |desc_id| is a descendant of the node at
+  // |anc_id|.
+  bool IsDescendant(int desc_id, int anc_id) const;
+
   void UpdateLocalTransform(TransformNode* node);
   void UpdateScreenSpaceTransform(TransformNode* node,
                                   TransformNode* parent_node,
@@ -544,6 +544,9 @@
   gfx::Transform ToScreenSpaceTransformWithoutSurfaceContentsScale(
       int transform_id,
       int effect_id) const;
+  bool ComputeTransformToTarget(int transform_id,
+                                int effect_id,
+                                gfx::Transform* transform) const;
 
  private:
   gfx::Vector2dF inner_viewport_container_bounds_delta_;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 591be67..e066b21 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -882,7 +882,9 @@
       num_descendants_that_draw_content > 0 &&
       (layer->DrawsContent() || num_descendants_that_draw_content > 1);
 
-  if (EffectiveOpacity(layer) != 1.f && ShouldFlattenTransform(layer) &&
+  bool may_have_transparency = EffectiveOpacity(layer) != 1.f ||
+                               HasPotentiallyRunningOpacityAnimation(layer);
+  if (may_have_transparency && ShouldFlattenTransform(layer) &&
       at_least_two_layers_in_subtree_draw_content) {
     TRACE_EVENT_INSTANT0(
         "cc", "PropertyTreeBuilder::ShouldCreateRenderSurface opacity",
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index 81bfec18..8090415 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -19,6 +19,7 @@
 #include "cc/test/fake_impl_task_runner_provider.h"
 #include "cc/test/fake_layer_tree_host.h"
 #include "cc/test/fake_rendering_stats_instrumentation.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/effect_node.h"
@@ -142,15 +143,9 @@
 }
 
 class TreeSynchronizerTest : public testing::Test {
- public:
-  TreeSynchronizerTest()
-      : client_(FakeLayerTreeHostClient::DIRECT_3D),
-        host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_)) {}
-
  protected:
-  FakeLayerTreeHostClient client_;
-  TestTaskGraphRunner task_graph_runner_;
-  std::unique_ptr<FakeLayerTreeHost> host_;
+  TreeSynchronizerTest()
+      : host_(FakeLayerTreeHost::Create(&client_, &task_graph_runner_)) {}
 
   bool is_equal(ScrollTree::ScrollOffsetMap map,
                 ScrollTree::ScrollOffsetMap other) {
@@ -169,6 +164,11 @@
     }
     return true;
   }
+
+  FakeLayerTreeHostClient client_;
+  StubLayerTreeHostSingleThreadClient single_thread_client_;
+  TestTaskGraphRunner task_graph_runner_;
+  std::unique_ptr<FakeLayerTreeHost> host_;
 };
 
 // Attempts to synchronizes a null tree. This should not crash, and should
@@ -563,8 +563,8 @@
 }
 
 TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) {
-  host_->InitializeSingleThreaded(&client_, base::ThreadTaskRunnerHandle::Get(),
-                                  nullptr);
+  host_->InitializeSingleThreaded(&single_thread_client_,
+                                  base::ThreadTaskRunnerHandle::Get(), nullptr);
   LayerTreeSettings settings;
   FakeLayerTreeHostImplClient client;
   FakeImplTaskRunnerProvider task_runner_provider;
@@ -659,8 +659,8 @@
 }
 
 TEST_F(TreeSynchronizerTest, RefreshPropertyTreesCachedData) {
-  host_->InitializeSingleThreaded(&client_, base::ThreadTaskRunnerHandle::Get(),
-                                  nullptr);
+  host_->InitializeSingleThreaded(&single_thread_client_,
+                                  base::ThreadTaskRunnerHandle::Get(), nullptr);
   LayerTreeSettings settings;
   FakeLayerTreeHostImplClient client;
   FakeImplTaskRunnerProvider task_runner_provider;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index a3e5041..ee1ff08 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -15,6 +15,7 @@
 import("//chrome/common/features.gni")
 import("//chrome/version.gni")
 import("//ui/base/ui_features.gni")
+import("//v8/gni/v8.gni")
 
 if (is_android) {
   import("//build/config/android/rules.gni")
diff --git a/chrome/VERSION b/chrome/VERSION
index e75b9ad..8c77b09 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=54
 MINOR=0
-BUILD=2805
+BUILD=2806
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/ic_content_copy.png b/chrome/android/java/res/drawable-hdpi/ic_content_copy.png
new file mode 100644
index 0000000..6e5b54ac
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/ic_content_copy.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_visibility.png b/chrome/android/java/res/drawable-hdpi/ic_visibility.png
new file mode 100644
index 0000000..8b85083e
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/ic_visibility.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/settings_usb.png b/chrome/android/java/res/drawable-hdpi/settings_usb.png
new file mode 100644
index 0000000..a7979e3
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/settings_usb.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_content_copy.png b/chrome/android/java/res/drawable-mdpi/ic_content_copy.png
new file mode 100644
index 0000000..7e46e67
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/ic_content_copy.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_visibility.png b/chrome/android/java/res/drawable-mdpi/ic_visibility.png
new file mode 100644
index 0000000..3a0bc8b0
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/ic_visibility.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/settings_usb.png b/chrome/android/java/res/drawable-mdpi/settings_usb.png
new file mode 100644
index 0000000..933df00
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/settings_usb.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_content_copy.png b/chrome/android/java/res/drawable-xhdpi/ic_content_copy.png
new file mode 100644
index 0000000..cca4652
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/ic_content_copy.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_visibility.png b/chrome/android/java/res/drawable-xhdpi/ic_visibility.png
new file mode 100644
index 0000000..d4e8b98
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/ic_visibility.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/settings_usb.png b/chrome/android/java/res/drawable-xhdpi/settings_usb.png
new file mode 100644
index 0000000..f7028c0
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/settings_usb.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_content_copy.png b/chrome/android/java/res/drawable-xxhdpi/ic_content_copy.png
new file mode 100644
index 0000000..fc00002
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/ic_content_copy.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_visibility.png b/chrome/android/java/res/drawable-xxhdpi/ic_visibility.png
new file mode 100644
index 0000000..11616c80
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/ic_visibility.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/settings_usb.png b/chrome/android/java/res/drawable-xxhdpi/settings_usb.png
new file mode 100644
index 0000000..7f301c7
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/settings_usb.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_content_copy.png b/chrome/android/java/res/drawable-xxxhdpi/ic_content_copy.png
new file mode 100644
index 0000000..7b77168
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/ic_content_copy.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_visibility.png b/chrome/android/java/res/drawable-xxxhdpi/ic_visibility.png
new file mode 100644
index 0000000..f10d1887
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/ic_visibility.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/settings_usb.png b/chrome/android/java/res/drawable-xxxhdpi/settings_usb.png
new file mode 100644
index 0000000..0134297
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/settings_usb.png
Binary files differ
diff --git a/chrome/android/java/res/layout/new_tab_page_snippets_card.xml b/chrome/android/java/res/layout/new_tab_page_snippets_card.xml
index 395ff79..b2a9109 100644
--- a/chrome/android/java/res/layout/new_tab_page_snippets_card.xml
+++ b/chrome/android/java/res/layout/new_tab_page_snippets_card.xml
@@ -18,7 +18,6 @@
         android:layout_height="wrap_content"
         android:layout_alignParentStart="true"
         android:layout_toStartOf="@+id/article_thumbnail"
-        android:lines="2"
         android:ellipsize="end"
         android:textSize="16sp"
         android:textColor="@color/snippets_headline_text_color"
@@ -32,7 +31,7 @@
         android:layout_below="@+id/article_headline"
         android:layout_toStartOf="@+id/article_thumbnail"
         android:layout_marginTop="8dp"
-        android:lines="2"
+        android:maxLines="2"
         android:ellipsize="end"
         android:textSize="14sp"
         android:textColor="@color/snippets_text_color"
diff --git a/chrome/android/java/res/layout/new_tab_page_snippets_header.xml b/chrome/android/java/res/layout/new_tab_page_snippets_header.xml
index 019d86c..f13a91d9 100644
--- a/chrome/android/java/res/layout/new_tab_page_snippets_header.xml
+++ b/chrome/android/java/res/layout/new_tab_page_snippets_header.xml
@@ -8,9 +8,9 @@
     android:id="@+id/snippets_list_header"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginStart="@dimen/snippets_padding_and_peeking_card_height"
     android:text="@string/snippets_header"
     android:textColor="@color/snippets_list_header_text_color"
     android:textSize="12sp"
+    android:paddingStart="@dimen/snippets_padding_and_peeking_card_height"
     android:paddingTop="10dp"
     android:gravity="start|center_vertical" />
diff --git a/chrome/android/java/res/layout/password_entry_editor.xml b/chrome/android/java/res/layout/password_entry_editor.xml
index bf79a3b..c335665b 100644
--- a/chrome/android/java/res/layout/password_entry_editor.xml
+++ b/chrome/android/java/res/layout/password_entry_editor.xml
@@ -54,7 +54,8 @@
             android:divider="?android:attr/dividerVertical"
             android:dividerPadding="0dp"
             android:orientation="horizontal"
-            android:showDividers="middle" >
+            android:showDividers="middle" 
+            android:visibility="gone">
 
             <Button
                 android:id="@+id/password_entry_editor_delete"
diff --git a/chrome/android/java/res/layout/password_entry_editor_interactive.xml b/chrome/android/java/res/layout/password_entry_editor_interactive.xml
new file mode 100644
index 0000000..4b5540160
--- /dev/null
+++ b/chrome/android/java/res/layout/password_entry_editor_interactive.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true" >
+
+    <LinearLayout
+        android:id="@+id/password_entry_editor_interactive"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:title="@string/password_entry_editor_title" 
+        android:visibility="gone">
+        
+        <TextView
+            android:text="@string/password_entry_editor_site_title"
+            android:textColor="@color/google_blue_700"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:layout_marginStart="15dp"
+            android:gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+        
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+            
+            <TextView
+                android:id="@+id/password_entry_editor_url"
+                android:textColor="@color/default_text_color"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="15dp"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+            
+            <View
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+        
+            <ImageButton
+                style="?android:attr/buttonStyleSmall"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginTop="10dp"
+                android:layout_marginEnd="15dp"
+                android:src="@drawable/ic_content_copy"
+                android:contentDescription="@string/password_entry_editor_copy_stored_site" />
+        
+        </LinearLayout>
+            
+        <TextView
+            android:text="@string/password_entry_editor_username_title"
+            android:textColor="@color/google_blue_700"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:layout_marginStart="15dp"
+            android:gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+            
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+            
+            <TextView
+                android:id="@+id/password_entry_editor_name"
+                android:textColor="@color/default_text_color"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="15dp"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:contentDescription="@string/password_entry_editor_copy_stored_username" />
+            
+            <View
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+        
+            <ImageButton
+                style="?android:attr/buttonStyleSmall"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginTop="10dp"
+                android:layout_marginEnd="15dp"
+                android:src="@drawable/ic_content_copy" />
+        
+        </LinearLayout>
+        
+        <TextView
+            android:text="@string/password_entry_editor_password"
+            android:textColor="@color/google_blue_700"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:layout_marginStart="15dp"
+            android:gravity="center_vertical"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+            
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+            
+            <TextView
+                android:id="@+id/password_entry_editor_password"
+                android:textColor="@color/default_text_color"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="15dp"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+            
+            <View
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+            
+            <ImageButton
+                style="?android:attr/buttonStyleSmall"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginTop="10dp"
+                android:layout_marginEnd="15dp"
+                android:src="@drawable/ic_visibility"
+                android:contentDescription="@string/password_entry_editor_view_stored_password" />
+        
+            <ImageButton
+                style="?android:attr/buttonStyleSmall"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginTop="10dp"
+                android:layout_marginEnd="15dp"
+                android:src="@drawable/ic_content_copy"
+                android:contentDescription="@string/password_entry_editor_copy_stored_password" />
+        
+        </LinearLayout>
+
+    </LinearLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/usb_permission.xml b/chrome/android/java/res/layout/usb_permission.xml
new file mode 100644
index 0000000..f502c39
--- /dev/null
+++ b/chrome/android/java/res/layout/usb_permission.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:contentDescription="@string/website_settings_revoke_device_permission"
+    android:src="@drawable/btn_close" />
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index c5eec61..6addfe4 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -282,6 +282,7 @@
     <dimen name="ntp_search_box_material_padding_left">2dp</dimen>
     <dimen name="ntp_search_box_material_padding_right">2dp</dimen>
     <dimen name="ntp_search_box_transition_length">16dp</dimen>
+    <dimen name="ntp_wide_card_lateral_margins">48dp</dimen>
     <dimen name="ntp_list_item_padding">16dp</dimen>
     <dimen name="ntp_list_item_min_height">48dp</dimen>
     <dimen name="ntp_list_item_text_size">16sp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
index 8c2602f..0655c4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
@@ -70,6 +70,10 @@
                     activity.onMenuOrKeyboardAction(R.id.show_menu, false);
                 }
                 return true;
+            case KeyEvent.KEYCODE_ESCAPE:
+                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+                    return activity.exitFullscreenIfShowing();
+                }
             case KeyEvent.KEYCODE_TV:
             case KeyEvent.KEYCODE_GUIDE:
             case KeyEvent.KEYCODE_DVR:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
index c396899..886ce1b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandler.java
@@ -12,7 +12,6 @@
 import android.view.ContextThemeWrapper;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.Surface;
 import android.view.View;
 import android.widget.PopupMenu;
 
@@ -87,19 +86,6 @@
             // This fixes the bug where the bottom of the menu starts at the top of
             // the keyboard, instead of overlapping the keyboard as it should.
             int displayHeight = mActivity.getResources().getDisplayMetrics().heightPixels;
-            int widthHeight = mActivity.getResources().getDisplayMetrics().widthPixels;
-
-            // In appcompat 23.2.1, DisplayMetrics are not updated after rotation change. This is a
-            // workaround for it. See crbug.com/599048.
-            // TODO(ianwen): Remove the rotation check after we roll to 23.3.0.
-            if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
-                displayHeight = Math.max(displayHeight, widthHeight);
-            } else if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
-                displayHeight = Math.min(displayHeight, widthHeight);
-            } else {
-                assert false : "Rotation unexpected";
-            }
-
             Rect rect = new Rect();
             mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
             int statusBarHeight = rect.top;
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 aadaeaa..a8df5211 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
@@ -653,8 +653,14 @@
      * Handle any clean up left after a session is destroyed.
      * @param session The session that has been destroyed.
      */
-    void cleanUpSession(CustomTabsSessionToken session) {
-        mClientManager.cleanupSession(session);
+    @VisibleForTesting
+    void cleanUpSession(final CustomTabsSessionToken session) {
+        ThreadUtils.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mClientManager.cleanupSession(session);
+            }
+        });
     }
 
     private boolean mayPrerender(CustomTabsSessionToken session) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
index 2e931bd..d49818c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
@@ -20,12 +20,11 @@
  */
 public class CustomTabsConnectionService extends CustomTabsService {
     private CustomTabsConnection mConnection;
+    private Intent mBindIntent;
 
     @Override
     public IBinder onBind(Intent intent) {
-        boolean firstRunNecessary = FirstRunFlowSequencer
-                .checkIfFirstRunIsNecessary(getApplicationContext(), intent) != null;
-        if (firstRunNecessary) return null;
+        mBindIntent = intent;
         mConnection = CustomTabsConnection.getInstance(getApplication());
         mConnection.logCall("Service#onBind()", true);
         return super.onBind(intent);
@@ -40,6 +39,7 @@
 
     @Override
     protected boolean warmup(long flags) {
+        if (!isFirstRunDone()) return false;
         return mConnection.warmup(flags);
     }
 
@@ -51,6 +51,7 @@
     @Override
     protected boolean mayLaunchUrl(CustomTabsSessionToken sessionToken, Uri url, Bundle extras,
             List<Bundle> otherLikelyBundles) {
+        if (!isFirstRunDone()) return false;
         return mConnection.mayLaunchUrl(sessionToken, url, extras, otherLikelyBundles);
     }
 
@@ -61,6 +62,7 @@
 
     @Override
     protected boolean updateVisuals(CustomTabsSessionToken sessionToken, Bundle bundle) {
+        if (!isFirstRunDone()) return false;
         return mConnection.updateVisuals(sessionToken, bundle);
     }
 
@@ -69,4 +71,15 @@
         mConnection.cleanUpSession(sessionToken);
         return super.cleanUpSession(sessionToken);
     }
+
+    private boolean isFirstRunDone() {
+        if (mBindIntent == null) return true;
+        boolean firstRunNecessary = FirstRunFlowSequencer
+                .checkIfFirstRunIsNecessary(getApplicationContext(), mBindIntent) != null;
+        if (!firstRunNecessary) {
+            mBindIntent = null;
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index 5900fb2..be8f535 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -1549,16 +1549,16 @@
     public void onMaxBandwidthChanged(double maxBandwidthMbps) {}
 
     @Override
-    public void onNetworkConnect(int netId, int connectionType) {}
+    public void onNetworkConnect(long netId, int connectionType) {}
 
     @Override
-    public void onNetworkSoonToDisconnect(int netId) {}
+    public void onNetworkSoonToDisconnect(long netId) {}
 
     @Override
-    public void onNetworkDisconnect(int netId) {}
+    public void onNetworkDisconnect(long netId) {}
 
     @Override
-    public void purgeActiveNetworkList(int[] activeNetIds) {}
+    public void purgeActiveNetworkList(long[] activeNetIds) {}
 
     private native long nativeInit();
     private native void nativeResumeDownload(
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 3fe89ce8..cfacc689 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
@@ -8,7 +8,6 @@
 import android.app.Fragment;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.v4.view.ViewPager;
 import android.support.v7.app.AppCompatActivity;
 import android.text.TextUtils;
 
@@ -84,7 +83,7 @@
     private boolean mNativeSideIsInitialized;
 
     private ProfileDataCache mProfileDataCache;
-    private ViewPager mPager;
+    private FirstRunViewPager mPager;
 
     private Bundle mFreProperties;
 
@@ -147,7 +146,7 @@
             return;
         }
 
-        mPager = new ViewPager(this);
+        mPager = new FirstRunViewPager(this);
         mPager.setId(R.id.fre_pager);
         setContentView(mPager);
 
@@ -234,7 +233,7 @@
         if (mPager.getCurrentItem() == 0) {
             abortFirstRunExperience();
         } else {
-            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
+            mPager.setCurrentItem(mPager.getCurrentItem() - 1, false);
         }
     }
 
@@ -247,7 +246,7 @@
 
     @Override
     public void advanceToNextPage() {
-        jumpToPage(mPager.getCurrentItem() + 1, true);
+        jumpToPage(mPager.getCurrentItem() + 1);
     }
 
     @Override
@@ -356,7 +355,7 @@
         FirstRunStatus.setSkipWelcomePage(FirstRunActivity.this, true);
         flushPersistentData();
         stopProgressionIfNotAcceptedTermsOfService();
-        jumpToPage(mPager.getCurrentItem() + 1, true);
+        jumpToPage(mPager.getCurrentItem() + 1);
     }
 
     @Override
@@ -389,9 +388,8 @@
      * Transitions to a given page.
      * @return Whether the transition to a given page was allowed.
      * @param position A page index to transition to.
-     * @param smooth   Whether the transition should be smooth.
      */
-    private boolean jumpToPage(int position, boolean smooth) {
+    private boolean jumpToPage(int position) {
         if (mShowWelcomePage && !didAcceptTermsOfService()) {
             return position == 0;
         }
@@ -399,7 +397,7 @@
             completeFirstRunExperience();
             return false;
         }
-        mPager.setCurrentItem(position, smooth);
+        mPager.setCurrentItem(position, false);
         return true;
     }
 
@@ -415,7 +413,7 @@
         while (currentPageIndex < mPagerAdapter.getCount()) {
             FirstRunPage currentPage = (FirstRunPage) mPagerAdapter.getItem(currentPageIndex);
             if (!currentPage.shouldSkipPageOnCreate(getApplicationContext())) return;
-            if (!jumpToPage(currentPageIndex + 1, false)) return;
+            if (!jumpToPage(currentPageIndex + 1)) return;
             currentPageIndex = mPager.getCurrentItem();
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
index d424dfd..7221c6ff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
@@ -14,24 +14,6 @@
 public class FirstRunPage extends Fragment {
     private Bundle mProperties = new Bundle();
 
-    // FRE properties:
-    private static final String LAST_PAGE_NUMBER = "LastPageNumber";
-
-    // Per-page properties:
-    private static final String THIS_PAGE_NUMBER = "ThisPageNumber";
-
-    /**
-     * Appends page-specific properties to the page instance bundle.
-     * @param props Instance properties.
-     * @param pageNumber This page number in the First Run sequence.
-     * @param lastPageNumber Last page number in the First Run sequence.
-     * @return Instance properties with the page-specific properties added.
-     */
-    public static Bundle addProperties(Bundle props, int pageNumber, int lastPageNumber) {
-        props.putInt(THIS_PAGE_NUMBER, pageNumber);
-        return props;
-    }
-
     /**
      * @return Whether this page should be skipped on the FRE creation.
      * @param appContext An application context.
@@ -81,13 +63,6 @@
     }
 
     /**
-     * @return Whether this page is the last page of the FRE.
-     */
-    protected boolean isLastPage() {
-        return getProperties().getInt(THIS_PAGE_NUMBER) == getProperties().getInt(LAST_PAGE_NUMBER);
-    }
-
-    /**
      * Advances to the next FRE page.
      */
     protected void advanceToNextPage() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
index a926aa31..79cb9875 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
@@ -55,7 +55,6 @@
 
         Bundle props = new Bundle();
         props.putAll(mFreProperties);
-        FirstRunPage.addProperties(props, position, getCount() - 1);
         result.setArguments(props);
 
         return result;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunViewPager.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunViewPager.java
new file mode 100644
index 0000000..8d79c6089
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunViewPager.java
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium 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.support.v4.view.ViewPager;
+import android.view.MotionEvent;
+
+/**
+* ViewPager without swipe gesture.
+*/
+public class FirstRunViewPager extends ViewPager {
+    FirstRunViewPager(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        return false;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/DisplayStyleObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/DisplayStyleObserver.java
new file mode 100644
index 0000000..8e21a65
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/DisplayStyleObserver.java
@@ -0,0 +1,16 @@
+// Copyright 2016 The Chromium 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.ntp;
+
+/**
+ * Gets notified of changes in the display style.
+ *
+ * @see UiConfig.DisplayStyle
+ * @see UiConfig#getDisplayStyle()
+ * @see org.chromium.chrome.browser.ntp.cards.DisplayStyleObserverAdapter
+ */
+public interface DisplayStyleObserver {
+    void onDisplayStyleChanged(@UiConfig.DisplayStyle int newDisplayStyle);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java
index 9360f975..0bf53e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java
@@ -134,7 +134,7 @@
     /**
      * @return True after we receive an animated logo from the server.
      */
-    public boolean isAnimatedLogoShowing() {
+    private boolean isAnimatedLogoShowing() {
         return mAnimatedLogoDrawable != null;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 7cd9270..917cfb3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -6,6 +6,7 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -95,6 +96,7 @@
     private OnSearchBoxScrollListener mSearchBoxScrollListener;
 
     private NewTabPageManager mManager;
+    private UiConfig mUiConfig;
     private MostVisitedDesign mMostVisitedDesign;
     private MostVisitedItem[] mMostVisitedItems;
     private boolean mFirstShow = true;
@@ -238,6 +240,7 @@
     public void initialize(NewTabPageManager manager, boolean searchProviderHasLogo,
             SnippetsBridge snippetsBridge) {
         mManager = manager;
+        mUiConfig = new UiConfig(this);
         ViewStub stub = (ViewStub) findViewById(R.id.new_tab_page_layout_stub);
 
         mUseCardsUi = snippetsBridge != null;
@@ -288,7 +291,8 @@
 
         // Set up snippets
         if (mUseCardsUi) {
-            mNewTabPageAdapter = new NewTabPageAdapter(mManager, mNewTabPageLayout, snippetsBridge);
+            mNewTabPageAdapter =
+                    new NewTabPageAdapter(mManager, mNewTabPageLayout, snippetsBridge, mUiConfig);
             mRecyclerView.setAdapter(mNewTabPageAdapter);
 
             // Set up swipe-to-dismiss
@@ -621,13 +625,6 @@
     }
 
     /**
-     * @return Whether the GIF animation is playing in the logo.
-     */
-    boolean isAnimatedLogoShowing() {
-        return mSearchProviderLogoView.isAnimatedLogoShowing();
-    }
-
-    /**
      * @return Whether URL focus animations are currently disabled.
      */
     boolean urlFocusAnimationsDisabled() {
@@ -1085,6 +1082,18 @@
         }
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        // When the viewport configuration changes, we want to update the display style so that the
+        // observers are aware of the new available space. Another moment to do this update could
+        // be through a OnLayoutChangeListener, but then we get notified of the change after the
+        // layout pass, which means that the new style will only be visible after layout happens
+        // again. We prefer updating here to avoid having to require that additional layout pass.
+        mUiConfig.updateDisplayStyle();
+    }
+
     private int getVerticalScroll() {
         if (mUseCardsUi) {
             return mRecyclerView.computeVerticalScrollOffset();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/UiConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/UiConfig.java
new file mode 100644
index 0000000..7b12a3b2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/UiConfig.java
@@ -0,0 +1,113 @@
+// Copyright 2016 The Chromium 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.ntp;
+
+import android.content.Context;
+import android.support.annotation.IntDef;
+import android.view.View;
+
+import org.chromium.base.Log;
+import org.chromium.ui.widget.Toast;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Exposes general configuration info about the NTP UI.
+ */
+public class UiConfig {
+    /** The different supported UI setups. Observers can register to be notified of changes.*/
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({DISPLAY_STYLE_UNDEFINED, DISPLAY_STYLE_NARROW, DISPLAY_STYLE_REGULAR,
+            DISPLAY_STYLE_WIDE})
+    public @interface DisplayStyle {}
+    public static final int DISPLAY_STYLE_UNDEFINED = -1;
+    public static final int DISPLAY_STYLE_NARROW = 0;
+    public static final int DISPLAY_STYLE_REGULAR = 1;
+    public static final int DISPLAY_STYLE_WIDE = 2;
+
+    private static final int REGULAR_CARD_MIN_WIDTH_DP = 360;
+    private static final int WIDE_CARD_MIN_WIDTH_DP = 600;
+
+    private static final String TAG = "Ntp";
+    private static final boolean DEBUG = false;
+
+    @DisplayStyle
+    private int mCurrentDisplayStyle;
+
+    private final List<DisplayStyleObserver> mObservers = new ArrayList<>();
+    private final Context mContext;
+
+    /**
+     * @param referenceView the View we observe to deduce the configuration from.
+     */
+    public UiConfig(View referenceView) {
+        mContext = referenceView.getContext();
+        mCurrentDisplayStyle = computeDisplayStyleForCurrentConfig();
+
+        referenceView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+                updateDisplayStyle();
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {}
+        });
+    }
+
+    /**
+     * Registers a {@link DisplayStyleObserver}. It will be notified right away with the current
+     * display style.
+     */
+    public void addObserver(DisplayStyleObserver observer) {
+        mObservers.add(observer);
+        observer.onDisplayStyleChanged(mCurrentDisplayStyle);
+    }
+
+    /**
+     * Refresh the display style, notify observers of changes.
+     */
+    public void updateDisplayStyle() {
+        @DisplayStyle
+        int newDisplayStyle = computeDisplayStyleForCurrentConfig();
+
+        if (newDisplayStyle == mCurrentDisplayStyle) return;
+
+        mCurrentDisplayStyle = newDisplayStyle;
+        for (DisplayStyleObserver observer : mObservers) {
+            observer.onDisplayStyleChanged(newDisplayStyle);
+        }
+    }
+
+    @DisplayStyle
+    private int computeDisplayStyleForCurrentConfig() {
+        int widthDp = mContext.getResources().getConfiguration().screenWidthDp;
+
+        String debugString;
+
+        @DisplayStyle
+        int newDisplayStyle;
+        if (widthDp < REGULAR_CARD_MIN_WIDTH_DP) {
+            newDisplayStyle = DISPLAY_STYLE_NARROW;
+            if (DEBUG) debugString = String.format("DISPLAY_STYLE_NARROW (w=%ddp)", widthDp);
+        } else if (widthDp >= WIDE_CARD_MIN_WIDTH_DP) {
+            newDisplayStyle = DISPLAY_STYLE_WIDE;
+            if (DEBUG) debugString = String.format("DISPLAY_STYLE_WIDE (w=%ddp)", widthDp);
+        } else {
+            newDisplayStyle = DISPLAY_STYLE_REGULAR;
+            if (DEBUG) debugString = String.format("DISPLAY_STYLE_REGULAR (w=%ddp)", widthDp);
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, debugString);
+            Toast.makeText(mContext, debugString, Toast.LENGTH_SHORT).show();
+        }
+
+        return newDisplayStyle;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
index f45eb14d1..a7cb3d7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
@@ -13,6 +13,7 @@
 import android.view.animation.Interpolator;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ntp.UiConfig;
 import org.chromium.chrome.browser.util.MathUtils;
 
 /**
@@ -27,6 +28,9 @@
  *   {@link NewTabPageRecyclerView#showCardsFrom(int)}). Tap events in non-peeking state will be
  *   routed through {@link #onCardTapped()} for subclasses to override.
  *
+ * - Cards will get some lateral margins when the viewport is sufficiently wide.
+ *   (see {@link UiConfig#DISPLAY_STYLE_WIDE})
+ *
  * Note: If a subclass overrides {@link #onBindViewHolder(NewTabPageListItem)}, it should call the
  * parent implementation to reset the private state when a card is recycled.
  */
@@ -45,6 +49,10 @@
 
     private final NewTabPageRecyclerView mRecyclerView;
 
+    private final UiConfig mUiConfig;
+    private final int mWideMarginSizePixels;
+    private final DisplayStyleObserverAdapter mDisplayStyleObserverAdapter;
+
     /**
      * Current padding value. The padding and the margins are manipulated together to create the
      * shrunk/peeking appearance of the cards. When the padding is low, the margins are high and
@@ -57,9 +65,13 @@
     /**
      * @param layoutId resource id of the layout to inflate and to use as card.
      * @param recyclerView ViewGroup that will contain the newly created view.
+     * @param uiConfig The NTP UI configuration object used to adjust the card UI.
      */
-    public CardViewHolder(int layoutId, final NewTabPageRecyclerView recyclerView) {
+    public CardViewHolder(
+            int layoutId, final NewTabPageRecyclerView recyclerView, UiConfig uiConfig) {
         super(inflateView(layoutId, recyclerView));
+        mWideMarginSizePixels = itemView.getResources().getDimensionPixelSize(
+                R.dimen.ntp_wide_card_lateral_margins);
 
         mCards9PatchAdjustment = recyclerView.getResources().getDimensionPixelSize(
                 R.dimen.snippets_card_9_patch_adjustment);
@@ -81,6 +93,9 @@
                 }
             }
         });
+
+        mUiConfig = uiConfig;
+        mDisplayStyleObserverAdapter = MarginResizer.createWithViewAdapter(itemView, mUiConfig);
     }
 
     /**
@@ -164,13 +179,23 @@
 
         // Modify the padding so as the margin increases, the padding decreases, keeping the card's
         // contents in the same position. The top and bottom remain the same.
-        itemView.setPadding(mPeekPadding, mMaxPeekPadding, mPeekPadding, mMaxPeekPadding);
+        int lateralPadding;
+        int lateralMargin;
+        if (mDisplayStyleObserverAdapter.getDisplayStyle() != UiConfig.DISPLAY_STYLE_WIDE) {
+            lateralPadding = mPeekPadding;
+            lateralMargin = mMaxPeekPadding - (mPeekPadding + mCards9PatchAdjustment);
+        } else {
+            lateralPadding = mMaxPeekPadding;
+            lateralMargin = mWideMarginSizePixels;
+        }
+
+        itemView.setPadding(lateralPadding, mMaxPeekPadding, lateralPadding, mMaxPeekPadding);
 
         // This mCards9PatchAdjustment value will be used to adjust the padding so the card width
         // is the actual width not including the elevation shadow so we can have full bleed.
         RecyclerView.LayoutParams params = getParams();
-        params.leftMargin = mMaxPeekPadding - (mPeekPadding + mCards9PatchAdjustment);
-        params.rightMargin = mMaxPeekPadding - (mPeekPadding + mCards9PatchAdjustment);
+        params.leftMargin = lateralMargin;
+        params.rightMargin = lateralMargin;
 
         // Set the opacity of the card content to be 0 when peeking and 1 when full width.
         int itemViewChildCount = ((ViewGroup) itemView).getChildCount();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java
new file mode 100644
index 0000000..90fffb6
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium 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.ntp.cards;
+
+import android.view.View;
+
+import org.chromium.chrome.browser.ntp.DisplayStyleObserver;
+import org.chromium.chrome.browser.ntp.UiConfig;
+
+/**
+ * Implementation of {@link DisplayStyleObserver} designed to play nicely with
+ * {@link android.support.v7.widget.RecyclerView}. It will not notify of changes when the
+ * associated view is not attached to the window.
+ */
+public class DisplayStyleObserverAdapter
+        implements DisplayStyleObserver, View.OnAttachStateChangeListener {
+    private final DisplayStyleObserver mObserver;
+
+    /** Current display style, gets updated as the UiConfig detects changes and notifies us. */
+    @UiConfig.DisplayStyle
+    private int mCurrentDisplayStyle;
+
+    /**
+     * Latest value that we transmitted to the adapted observer. If we didn't transfer any yet,
+     * the value is not a valid {@code DisplayStyle}
+     */
+    @UiConfig.DisplayStyle
+    private Integer mNotifiedDisplayStyle;
+
+    private boolean mIsViewAttached;
+
+    /**
+     * @param view the view whose lifecycle is tracked to determine when to not fire the
+     *             observer.
+     * @param config the {@link UiConfig} object to subscribe to.
+     * @param observer the observer to adapt. It's {#onDisplayStyleChanged} will be called when
+     *                 the configuration changes, provided that {@code view} is attached to the
+     *                 window.
+     */
+    public DisplayStyleObserverAdapter(View view, UiConfig config, DisplayStyleObserver observer) {
+        mObserver = observer;
+
+        // TODO(dgn): getParent() is not a good way to test that, but isAttachedToWindow()
+        // requires API 19.
+        mIsViewAttached = view.getParent() != null;
+
+        view.addOnAttachStateChangeListener(this);
+
+        // This call will also assign the initial value to |mCurrentDisplayStyle|
+        config.addObserver(this);
+    }
+
+    @Override
+    public void onDisplayStyleChanged(@UiConfig.DisplayStyle int newDisplayStyle) {
+        mCurrentDisplayStyle = newDisplayStyle;
+
+        if (!mIsViewAttached) return;
+        if (mNotifiedDisplayStyle != null && mCurrentDisplayStyle == mNotifiedDisplayStyle) return;
+
+        mNotifiedDisplayStyle = mCurrentDisplayStyle;
+
+        mObserver.onDisplayStyleChanged(mCurrentDisplayStyle);
+    }
+
+    @Override
+    public void onViewAttachedToWindow(View v) {
+        mIsViewAttached = true;
+        onDisplayStyleChanged(mCurrentDisplayStyle);
+    }
+
+    @Override
+    public void onViewDetachedFromWindow(View v) {
+        mIsViewAttached = false;
+    }
+
+    @UiConfig.DisplayStyle
+    public int getDisplayStyle() {
+        return mCurrentDisplayStyle;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/MarginResizer.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/MarginResizer.java
new file mode 100644
index 0000000..71591da
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/MarginResizer.java
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium 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.ntp.cards;
+
+import android.view.View;
+import android.view.ViewGroup.MarginLayoutParams;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ntp.DisplayStyleObserver;
+import org.chromium.chrome.browser.ntp.UiConfig;
+
+/**
+ * Adds lateral margins to the view when the display style is {@link UiConfig#DISPLAY_STYLE_WIDE}.
+ */
+public class MarginResizer implements DisplayStyleObserver {
+    private final int mWideMarginSizePixels;
+    private final View mView;
+
+    public static DisplayStyleObserverAdapter createWithViewAdapter(View view, UiConfig config) {
+        return new DisplayStyleObserverAdapter(view, config, new MarginResizer(view));
+    }
+
+    public MarginResizer(View view) {
+        mView = view;
+        mWideMarginSizePixels =
+                view.getResources().getDimensionPixelSize(R.dimen.ntp_wide_card_lateral_margins);
+    }
+
+    @Override
+    public void onDisplayStyleChanged(@UiConfig.DisplayStyle int newDisplayStyle) {
+        MarginLayoutParams layoutParams = (MarginLayoutParams) mView.getLayoutParams();
+        if (newDisplayStyle == UiConfig.DISPLAY_STYLE_WIDE) {
+            layoutParams.setMargins(mWideMarginSizePixels, layoutParams.topMargin,
+                    mWideMarginSizePixels, layoutParams.bottomMargin);
+        } else {
+            layoutParams.setMargins(0, layoutParams.topMargin, 0, layoutParams.bottomMargin);
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index 78e85e4..72e80b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -16,6 +16,7 @@
 import org.chromium.chrome.browser.ntp.NewTabPageLayout;
 import org.chromium.chrome.browser.ntp.NewTabPageUma;
 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
+import org.chromium.chrome.browser.ntp.UiConfig;
 import org.chromium.chrome.browser.ntp.snippets.DisabledReason;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleListItem;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder;
@@ -46,6 +47,7 @@
     private final NewTabPageLayout mNewTabPageLayout;
     private final AboveTheFoldListItem mAboveTheFoldListItem;
     private final SnippetHeaderListItem mHeaderListItem;
+    private final UiConfig mUiConfig;
     private StatusListItem mStatusListItem;
     private final List<NewTabPageListItem> mNewTabPageListItems;
     private final ItemTouchCallbacks mItemTouchCallbacks;
@@ -110,9 +112,10 @@
      * @param newTabPageLayout the layout encapsulating all the above-the-fold elements
      *                         (logo, search box, most visited tiles)
      * @param snippetsBridge the bridge to interact with the snippets service.
+     * @param uiConfig the NTP UI configuration, to be passed to created views.
      */
     public NewTabPageAdapter(NewTabPageManager manager, NewTabPageLayout newTabPageLayout,
-            SnippetsBridge snippetsBridge) {
+            SnippetsBridge snippetsBridge, UiConfig uiConfig) {
         mNewTabPageManager = manager;
         mNewTabPageLayout = newTabPageLayout;
         mAboveTheFoldListItem = new AboveTheFoldListItem();
@@ -121,6 +124,7 @@
         mNewTabPageListItems = new ArrayList<NewTabPageListItem>();
         mServiceStatus = DisabledReason.NONE;
         mSnippetsBridge = snippetsBridge;
+        mUiConfig = uiConfig;
         mStatusListItem = StatusListItem.create(snippetsBridge.getDisabledReason(), this, manager);
 
         loadSnippets(new ArrayList<SnippetArticleListItem>());
@@ -192,12 +196,12 @@
         }
 
         if (viewType == NewTabPageListItem.VIEW_TYPE_HEADER) {
-            return new SnippetHeaderViewHolder(
-                    SnippetHeaderListItem.createView(parent), mRecyclerView);
+            return new SnippetHeaderViewHolder(mRecyclerView, mUiConfig);
         }
 
         if (viewType == NewTabPageListItem.VIEW_TYPE_SNIPPET) {
-            return new SnippetArticleViewHolder(mRecyclerView, mNewTabPageManager, mSnippetsBridge);
+            return new SnippetArticleViewHolder(
+                    mRecyclerView, mNewTabPageManager, mSnippetsBridge, mUiConfig);
         }
 
         if (viewType == NewTabPageListItem.VIEW_TYPE_SPACING) {
@@ -205,7 +209,7 @@
         }
 
         if (viewType == NewTabPageListItem.VIEW_TYPE_STATUS) {
-            return new StatusListItem.ViewHolder(mRecyclerView);
+            return new StatusListItem.ViewHolder(mRecyclerView, mUiConfig);
         }
 
         return null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusListItem.java
index 68a8e945..88f33d0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusListItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusListItem.java
@@ -13,6 +13,7 @@
 import org.chromium.base.Log;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
+import org.chromium.chrome.browser.ntp.UiConfig;
 import org.chromium.chrome.browser.ntp.snippets.DisabledReason;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.signin.AccountSigninActivity;
@@ -33,8 +34,8 @@
         private final TextView mBodyView;
         private final Button mActionView;
 
-        public ViewHolder(NewTabPageRecyclerView parent) {
-            super(R.layout.new_tab_page_status_card, parent);
+        public ViewHolder(NewTabPageRecyclerView parent, UiConfig config) {
+            super(R.layout.new_tab_page_status_card, parent, config);
             mTitleView = (TextView) itemView.findViewById(R.id.status_title);
             mBodyView = (TextView) itemView.findViewById(R.id.status_body);
             mActionView = (Button) itemView.findViewById(R.id.status_action_button);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
index 25d1d95..b53b89a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -24,9 +24,12 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback;
 import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback;
+import org.chromium.chrome.browser.ntp.DisplayStyleObserver;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
+import org.chromium.chrome.browser.ntp.UiConfig;
 import org.chromium.chrome.browser.ntp.cards.CardViewHolder;
+import org.chromium.chrome.browser.ntp.cards.DisplayStyleObserverAdapter;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageListItem;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
 import org.chromium.components.variations.VariationsAssociatedData;
@@ -69,10 +72,11 @@
      * @param parent The ViewGroup that is going to contain the newly created view.
      * @param manager The NTPManager object used to open an article
      * @param snippetsBridge The SnippetsBridge used to retrieve the snippet thumbnails.
+     * @param uiConfig The NTP UI configuration object used to adjust the article UI.
      */
     public SnippetArticleViewHolder(NewTabPageRecyclerView parent, NewTabPageManager manager,
-            SnippetsBridge snippetsBridge) {
-        super(R.layout.new_tab_page_snippets_card, parent);
+            SnippetsBridge snippetsBridge, UiConfig uiConfig) {
+        super(R.layout.new_tab_page_snippets_card, parent, uiConfig);
 
         mNewTabPageManager = manager;
         mSnippetsBridge = snippetsBridge;
@@ -108,6 +112,19 @@
             }
         });
 
+        new DisplayStyleObserverAdapter(itemView, uiConfig, new DisplayStyleObserver() {
+            @Override
+            public void onDisplayStyleChanged(@UiConfig.DisplayStyle int newDisplayStyle) {
+                if (newDisplayStyle == UiConfig.DISPLAY_STYLE_NARROW) {
+                    mHeadlineTextView.setMaxLines(4);
+                    mArticleSnippetTextView.setVisibility(View.GONE);
+                } else {
+                    mHeadlineTextView.setMaxLines(2);
+                    mArticleSnippetTextView.setVisibility(View.VISIBLE);
+                }
+            }
+        });
+
         mUseFaviconService =
                 !PARAMETER_DISABLED_VALUE.equals(VariationsAssociatedData.getVariationParamValue(
                         NewTabPage.FIELD_TRIAL_NAME, PARAMETER_FAVICON_SERVICE_NAME));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetHeaderViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetHeaderViewHolder.java
index d9a0b02..3edfc373 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetHeaderViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetHeaderViewHolder.java
@@ -6,10 +6,10 @@
 
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ntp.UiConfig;
+import org.chromium.chrome.browser.ntp.cards.MarginResizer;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageListItem;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
@@ -27,20 +27,17 @@
 
     private SnippetHeaderListItem mHeader;
 
-    public static View createView(ViewGroup parent) {
-        return LayoutInflater.from(parent.getContext())
-                .inflate(R.layout.new_tab_page_snippets_card, parent, false);
-    }
-
-    public SnippetHeaderViewHolder(final View cardView, final NewTabPageRecyclerView recyclerView) {
-        super(cardView);
-        mMaxSnippetHeaderHeight = cardView.getResources().getDimensionPixelSize(
+    public SnippetHeaderViewHolder(final NewTabPageRecyclerView recyclerView, UiConfig config) {
+        super(LayoutInflater.from(recyclerView.getContext())
+                        .inflate(R.layout.new_tab_page_snippets_header, recyclerView, false));
+        mMaxSnippetHeaderHeight = itemView.getResources().getDimensionPixelSize(
                 R.dimen.snippets_article_header_height);
 
-        mMaxPeekPadding = cardView.getResources().getDimensionPixelSize(
+        mMaxPeekPadding = itemView.getResources().getDimensionPixelSize(
                 R.dimen.snippets_padding_and_peeking_card_height);
 
         mRecyclerView = recyclerView;
+        MarginResizer.createWithViewAdapter(itemView, config);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
index 50f19af..57c5596 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -423,7 +423,7 @@
     private void addBillingAddressDropdown(EditorModel editor, final CreditCard card) {
         final List<DropdownKeyValue> billingAddresses = new ArrayList<>();
         billingAddresses.add(new DropdownKeyValue(BILLING_ADDRESS_NONE,
-                mContext.getString(R.string.autofill_billing_address_select_prompt)));
+                mContext.getString(R.string.select)));
 
         // Re-read profiles every time, in case any of them have changed. This does not cause a disk
         // read, because personal_data_manager.h holds a cache.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index c198b8c..b6a653d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -53,6 +53,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -89,8 +90,14 @@
     }
 
     private static final String TAG = "cr_PaymentRequest";
-
     private static final int SUGGESTIONS_LIMIT = 4;
+    private static final Comparator<Completable> COMPLETENESS_COMPARATOR =
+            new Comparator<Completable>() {
+                @Override
+                public int compare(Completable a, Completable b) {
+                    return (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0);
+                }
+            };
 
     private static PaymentRequestServiceObserverForTest sObserverForTest;
 
@@ -127,12 +134,12 @@
      */
     private SectionInformation mUiShippingOptions;
 
-    private HashMap<String, JSONObject> mMethodData;
+    private Map<String, JSONObject> mMethodData;
     private SectionInformation mShippingAddressesSection;
     private SectionInformation mContactSection;
     private List<PaymentApp> mPendingApps;
-    private int mFirstCompletePendingInstrument;
     private List<PaymentInstrument> mPendingInstruments;
+    private List<PaymentInstrument> mPendingAutofillInstruments;
     private SectionInformation mPaymentMethodsSection;
     private PaymentRequestUI mUI;
     private Callback<PaymentInformation> mPaymentInformationCallback;
@@ -237,20 +244,6 @@
             return;
         }
 
-        // Create a comparator to sort the suggestions by completeness.
-        Comparator<Completable> completenessComparator = new Comparator<Completable>() {
-            @Override
-            public int compare(Completable a, Completable b) {
-                if (a.isComplete() == b.isComplete()) {
-                    return 0;
-                } else if (a.isComplete()) {
-                    return -1;
-                } else {
-                    return 1;
-                }
-            }
-        };
-
         // If the merchant requests shipping and does not provide a selected shipping option, then
         // the merchant needs the shipping address to calculate the shipping price and availability.
         boolean requestShipping = options != null && options.requestShipping;
@@ -277,7 +270,7 @@
             }
 
             // Suggest complete addresses first.
-            Collections.sort(addresses, completenessComparator);
+            Collections.sort(addresses, COMPLETENESS_COMPARATOR);
 
             // Limit the number of suggestions.
             addresses = addresses.subList(0, Math.min(addresses.size(), SUGGESTIONS_LIMIT));
@@ -324,7 +317,7 @@
             }
 
             // Suggest complete contact infos first.
-            Collections.sort(contacts, completenessComparator);
+            Collections.sort(contacts, COMPLETENESS_COMPARATOR);
 
             // Limit the number of suggestions.
             contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS_LIMIT));
@@ -351,11 +344,11 @@
         if (mContactEditor != null) mContactEditor.setEditorView(mUI.getEditorView());
     }
 
-    private static HashMap<String, JSONObject> getValidatedMethodData(
+    private static Map<String, JSONObject> getValidatedMethodData(
             PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) {
         // Payment methodData are required.
         if (methodData == null || methodData.length == 0) return null;
-        HashMap<String, JSONObject> result = new HashMap<>();
+        Map<String, JSONObject> result = new HashMap<>();
         for (int i = 0; i < methodData.length; i++) {
             JSONObject data = null;
             if (!TextUtils.isEmpty(methodData[i].stringifiedData)) {
@@ -395,10 +388,11 @@
      */
     private boolean getMatchingPaymentInstruments() {
         mPendingApps = new ArrayList<>(mApps);
-        mFirstCompletePendingInstrument = SectionInformation.NO_SELECTION;
         mPendingInstruments = new ArrayList<>();
+        mPendingAutofillInstruments = new ArrayList<>();
         boolean arePaymentMethodsSupported = false;
 
+        Map<PaymentApp, JSONObject> queryApps = new HashMap<>();
         for (int i = 0; i < mApps.size(); i++) {
             PaymentApp app = mApps.get(i);
             Set<String> appMethods = app.getSupportedMethodNames();
@@ -407,11 +401,18 @@
                 mPendingApps.remove(app);
             } else {
                 arePaymentMethodsSupported = true;
-                mMerchantSupportsAutofillPaymentInstruments = app instanceof AutofillPaymentApp;
-                app.getInstruments(mMethodData.get(appMethods.iterator().next()), this);
+                mMerchantSupportsAutofillPaymentInstruments |= app instanceof AutofillPaymentApp;
+                queryApps.put(app, mMethodData.get(appMethods.iterator().next()));
             }
         }
 
+        // Query instruments after mMerchantSupportsAutofillPaymentInstruments has been initialized,
+        // so a fast response from a non-autofill payment app at the front of the app list does not
+        // cause NOT_SUPPORTED payment rejection.
+        for (Map.Entry<PaymentApp, JSONObject> q : queryApps.entrySet()) {
+            q.getKey().getInstruments(q.getValue(), this);
+        }
+
         return arePaymentMethodsSupported;
     }
 
@@ -868,12 +869,13 @@
     public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instruments) {
         mPendingApps.remove(app);
 
+        // Place the instruments into either "autofill" or "non-autofill" list to be displayed when
+        // all apps have responded.
         if (instruments != null) {
             for (int i = 0; i < instruments.size(); i++) {
                 PaymentInstrument instrument = instruments.get(i);
                 if (mMethodData.containsKey(instrument.getMethodName())) {
-                    checkForCompletePaymentInstrument(instrument, mPendingInstruments.size());
-                    mPendingInstruments.add(instrument);
+                    addPendingInstrument(instrument);
                 } else {
                     instrument.dismiss();
                 }
@@ -893,25 +895,56 @@
             return;
         }
 
+        // List order:
+        // > Non-autofill instruments.
+        // > Complete autofill instruments.
+        // > Incomplete autofill instruments.
+        Collections.sort(mPendingAutofillInstruments, COMPLETENESS_COMPARATOR);
+        mPendingInstruments.addAll(mPendingAutofillInstruments);
+
+        mPendingAutofillInstruments.clear();
+        mPendingAutofillInstruments = null;
+
+        // Pre-select the first instrument on the list, if it is complete.
+        int selection = SectionInformation.NO_SELECTION;
+        if (!mPendingInstruments.isEmpty()) {
+            PaymentInstrument first = mPendingInstruments.get(0);
+            if (!(first instanceof AutofillPaymentInstrument)
+                    || ((AutofillPaymentInstrument) first).isComplete()) {
+                selection = 0;
+            }
+        }
+
         // The list of payment instruments is ready to display.
         mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PAYMENT_METHODS,
-                mFirstCompletePendingInstrument, mPendingInstruments);
+                selection, mPendingInstruments);
+
         mPendingInstruments.clear();
+        mPendingInstruments = null;
 
         // UI has requested the full list of payment instruments. Provide it now.
         if (mPaymentInformationCallback != null) providePaymentInformation();
     }
 
-    private void checkForCompletePaymentInstrument(PaymentInstrument instrument, int index) {
-        boolean isComplete = true;
+    /**
+     * Saves the given instrument in either "autofill" or "non-autofill" list. The separation
+     * enables placing autofill instruments on the bottom of the list.
+     *
+     * Autofill instruments are also checked for completeness. A complete autofill instrument can be
+     * sent to the merchant as-is, without editing first. Such instruments should be displayed
+     * higher in the list.
+     *
+     * @param instrument The instrument to add to either "autofill" or "non-autofill" list.
+     */
+    private void addPendingInstrument(PaymentInstrument instrument) {
         if (instrument instanceof AutofillPaymentInstrument) {
             AutofillPaymentInstrument autofillInstrument = (AutofillPaymentInstrument) instrument;
-            isComplete = mCardEditor.isCardComplete(autofillInstrument.getCard());
-            if (isComplete) autofillInstrument.setIsComplete();
-        }
-
-        if (isComplete && mFirstCompletePendingInstrument == SectionInformation.NO_SELECTION) {
-            mFirstCompletePendingInstrument = index;
+            if (mCardEditor.isCardComplete(autofillInstrument.getCard())) {
+                autofillInstrument.setIsComplete();
+            }
+            mPendingAutofillInstruments.add(instrument);
+        } else {
+            mPendingInstruments.add(instrument);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
index a8a9f33..d1639520 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -17,6 +17,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.GridLayout;
 import android.widget.ImageButton;
 import android.widget.ImageView;
@@ -27,6 +28,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.DualControlLayout;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 
 import java.util.ArrayList;
@@ -39,11 +41,11 @@
  *
  * The row is broken up into three major, vertically-centered sections:
  * .............................................................................................
- * . TITLE                                                          |                |         .
- * .................................................................|                |         .
- * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT |           LOGO | CHEVRON .
- * .................................................................|                |         .
- * . MAIN SECTION CONTENT                                           |                |         .
+ * . TITLE                                                          |                | CHEVRON .
+ * .................................................................|                |    or   .
+ * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT |           LOGO |   ADD   .
+ * .................................................................|                |    or   .
+ * . MAIN SECTION CONTENT                                           |                |  SELECT .
  * .............................................................................................
  *
  * 1) MAIN CONTENT
@@ -55,19 +57,14 @@
  *    Displays an optional logo (e.g. a credit card image) that floats to the right of the main
  *    content.
  *
- * 3) CHEVRON
+ * 3) CHEVRON or ADD or SELECT
  *    Drawn to indicate that the current section may be expanded.  Displayed only when the view is
- *    in the {@link #DISPLAY_MODE_EXPANDABLE} state.
+ *    in the {@link #DISPLAY_MODE_EXPANDABLE} state and only if an ADD or SELECT button isn't shown.
  *
  * There are three states that the UI may flip between; see {@link #DISPLAY_MODE_NORMAL},
  * {@link #DISPLAY_MODE_EXPANDABLE}, and {@link #DISPLAY_MODE_FOCUSED} for details.
- *
- * TODO(dfalcantara): Figure out what kind of Layout we should really be using here now that mocks
- *                    have stabilized, somewhat.  A RelativeLayout is gross because it doesn't
- *                    automatically account for Views being removed, meaning we'd have to twiddle
- *                    with each View's LayoutParams as their visibility was toggled.
  */
-public abstract class PaymentRequestSection extends LinearLayout {
+public abstract class PaymentRequestSection extends LinearLayout implements View.OnClickListener {
     public static final String TAG = "PaymentRequestUI";
 
     /** Handles clicks on the widgets and providing data to the PaymentsRequestSection. */
@@ -78,38 +75,54 @@
          * @param section Section that was changed.
          * @param option  {@link PaymentOption} that was selected.
          */
-        void onPaymentOptionChanged(OptionSection section, PaymentOption option);
+        void onPaymentOptionChanged(PaymentRequestSection section, PaymentOption option);
 
         /** Called when the user requests adding a new PaymentOption to a given section. */
-        void onAddPaymentOption(OptionSection section);
+        void onAddPaymentOption(PaymentRequestSection section);
 
         /** Checks whether or not the text should be formatted with a bold label. */
-        boolean isBoldLabelNeeded(OptionSection section);
+        boolean isBoldLabelNeeded(PaymentRequestSection section);
 
         /** Checks whether or not the user should be allowed to click on controls. */
         boolean isAcceptingUserInput();
 
         /** Returns any additional text that needs to be displayed. */
-        @Nullable String getAdditionalText(OptionSection section);
+        @Nullable String getAdditionalText(PaymentRequestSection section);
 
         /** Returns true if the additional text should be stylized as a warning instead of info. */
-        boolean isAdditionalTextDisplayingWarning(OptionSection section);
+        boolean isAdditionalTextDisplayingWarning(PaymentRequestSection section);
+
+        /** Called when a section has been clicked. */
+        void onSectionClicked(PaymentRequestSection section);
     }
 
+    /** Edit button mode: Hide the button. */
+    public static final int EDIT_BUTTON_GONE = 0;
+
+    /** Edit button mode: Indicate that the section requires a selection. */
+    public static final int EDIT_BUTTON_SELECT = 1;
+
+    /** Edit button mode: Indicate that the section requires adding an option. */
+    public static final int EDIT_BUTTON_ADD = 2;
+
     /** Normal mode: White background, displays the item assuming the user accepts it as is. */
-    static final int DISPLAY_MODE_NORMAL = 0;
+    static final int DISPLAY_MODE_NORMAL = 3;
 
     /** Editable mode: White background, displays the item with an edit chevron. */
-    static final int DISPLAY_MODE_EXPANDABLE = 1;
+    static final int DISPLAY_MODE_EXPANDABLE = 4;
 
     /** Focused mode: Gray background, more padding, no edit chevron. */
-    static final int DISPLAY_MODE_FOCUSED = 2;
+    static final int DISPLAY_MODE_FOCUSED = 5;
 
     /** Checking mode: Gray background, spinner overlay hides everything except the title. */
-    static final int DISPLAY_MODE_CHECKING = 3;
+    static final int DISPLAY_MODE_CHECKING = 6;
 
     protected final SectionDelegate mDelegate;
     protected final int mLargeSpacing;
+    protected final Button mEditButtonView;
+    protected final boolean mIsLayoutInitialized;
+
+    protected int mDisplayMode = DISPLAY_MODE_NORMAL;
 
     private final int mVerticalSpacing;
     private final int mFocusedBackgroundColor;
@@ -123,7 +136,6 @@
     private TextView mSummaryRightTextView;
 
     private int mLogoResourceId;
-    private int mDisplayMode;
     private boolean mIsSummaryAllowed = true;
 
     /**
@@ -136,7 +148,6 @@
     private PaymentRequestSection(Context context, String sectionName, SectionDelegate delegate) {
         super(context);
         mDelegate = delegate;
-        setId(R.id.payments_section);
         setOnClickListener(delegate);
         setOrientation(HORIZONTAL);
         setGravity(Gravity.CENTER_VERTICAL);
@@ -153,7 +164,9 @@
         // Create the main content.
         mMainSection = prepareMainSection(sectionName);
         mLogoView = isLogoNecessary() ? createAndAddLogoView(this, 0, mLargeSpacing) : null;
+        mEditButtonView = createAndAddEditButton(this);
         mChevronView = createAndAddChevron(this);
+        mIsLayoutInitialized = true;
         setDisplayMode(DISPLAY_MODE_NORMAL);
     }
 
@@ -166,7 +179,40 @@
         assert isLogoNecessary();
         mLogoResourceId = resourceId;
         mLogoView.setImageResource(resourceId);
-        updateLogoVisibility();
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        // Allow touches to propagate to children only if the layout can be interacted with.
+        return !mDelegate.isAcceptingUserInput();
+    }
+
+    @Override
+    public final void onClick(View v) {
+        if (!mDelegate.isAcceptingUserInput()) return;
+
+        // Handle clicking on "ADD" or "SELECT".
+        if (v == mEditButtonView) {
+            if (getEditButtonState() == EDIT_BUTTON_ADD) {
+                mDelegate.onAddPaymentOption(this);
+            } else {
+                mDelegate.onSectionClicked(this);
+            }
+            return;
+        }
+
+        handleClick(v);
+        updateControlLayout();
+    }
+
+    /** Handles clicks on the PaymentRequestSection. */
+    protected void handleClick(View v) { }
+
+    /**
+     * Called when the UI is telling the section that it has either gained or lost focus.
+     */
+    public void focusSection(boolean shouldFocus) {
+        setDisplayMode(shouldFocus ? DISPLAY_MODE_FOCUSED : DISPLAY_MODE_EXPANDABLE);
     }
 
     /**
@@ -176,20 +222,7 @@
      */
     public void setDisplayMode(int displayMode) {
         mDisplayMode = displayMode;
-        boolean isExpanded =
-                displayMode == DISPLAY_MODE_FOCUSED || displayMode == DISPLAY_MODE_CHECKING;
-        setBackgroundColor(isExpanded ? mFocusedBackgroundColor : Color.WHITE);
-        updateLogoVisibility();
-        mChevronView.setVisibility(displayMode == DISPLAY_MODE_EXPANDABLE ? VISIBLE : GONE);
-
-        // The title gains extra spacing when there is another visible view in the main section.
-        int numVisibleMainViews = 0;
-        for (int i = 0; i < mMainSection.getChildCount(); i++) {
-            if (mMainSection.getChildAt(i).getVisibility() == VISIBLE) numVisibleMainViews += 1;
-        }
-        boolean isTitleMarginNecessary = numVisibleMainViews > 1 && isExpanded;
-        ((ViewGroup.MarginLayoutParams) mTitleView.getLayoutParams()).bottomMargin =
-                isTitleMarginNecessary ? mVerticalSpacing : 0;
+        updateControlLayout();
     }
 
     /**
@@ -203,7 +236,7 @@
         mSummaryLeftTextView.setText(leftText);
         mSummaryRightTextView.setText(rightText);
         mSummaryRightTextView.setVisibility(TextUtils.isEmpty(rightText) ? GONE : VISIBLE);
-        updateSummaryVisibility();
+        updateControlLayout();
     }
 
     /**
@@ -229,13 +262,21 @@
     protected abstract void createMainSectionContent(LinearLayout mainSectionLayout);
 
     /**
+     * Sets whether the edit button may be interacted with.
+     *
+     * @param isEnabled Whether the button may be interacted with.
+     */
+    public void setIsEditButtonEnabled(boolean isEnabled) {
+        mEditButtonView.setEnabled(isEnabled);
+    }
+
+    /**
      * Sets whether the summary text can be displayed.
      *
-     * @param isAllowed Whether to display the summary text.
+     * @param isAllowed Whether to display the summary text when needed.
      */
     protected void setIsSummaryAllowed(boolean isAllowed) {
         mIsSummaryAllowed = isAllowed;
-        updateSummaryVisibility();
     }
 
     /** @return Whether or not the logo should be displayed. */
@@ -244,6 +285,15 @@
     }
 
     /**
+     * Returns the state of the edit button, which is hidden by default.
+     *
+     * @return State of the edit button.
+     */
+    public int getEditButtonState() {
+        return EDIT_BUTTON_GONE;
+    }
+
+    /**
      * Creates the main section.  Subclasses must call super#createMainSection() immediately to
      * guarantee that Views are added in the correct order.
      *
@@ -315,6 +365,19 @@
         return view;
     }
 
+    private Button createAndAddEditButton(ViewGroup parent) {
+        Resources resources = parent.getResources();
+        Button view = DualControlLayout.createButtonForLayout(
+                parent.getContext(), true, resources.getString(R.string.select), this);
+        view.setId(R.id.payments_section);
+
+        LayoutParams params =
+                new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+        ApiCompatibilityUtils.setMarginStart(params, mLargeSpacing);
+        parent.addView(view, params);
+        return view;
+    }
+
     private ImageView createAndAddChevron(ViewGroup parent) {
         Resources resources = parent.getResources();
         TintedDrawable chevron = TintedDrawable.constructTintedDrawable(
@@ -331,30 +394,81 @@
         return view;
     }
 
-    private void updateSummaryVisibility() {
-        boolean show = mIsSummaryAllowed && !TextUtils.isEmpty(mSummaryLeftTextView.getText());
-        mSummaryLayout.setVisibility(show ? VISIBLE : GONE);
-    }
+    /**
+     * Called when the section's controls need to be updated after configuration changes.
+     *
+     * Because of the complicated special casing of what controls hide other controls, all calls to
+     * update just one of the controls causes the visibility logic to trigger for all of them.
+     *
+     * Subclasses should call the super method after they update their own controls.
+     */
+    protected void updateControlLayout() {
+        if (!mIsLayoutInitialized) return;
 
-    private void updateLogoVisibility() {
-        if (mLogoView == null) return;
-        boolean show = mLogoResourceId != 0 && mDisplayMode != DISPLAY_MODE_FOCUSED;
-        mLogoView.setVisibility(show ? VISIBLE : GONE);
+        boolean isExpanded =
+                mDisplayMode == DISPLAY_MODE_FOCUSED || mDisplayMode == DISPLAY_MODE_CHECKING;
+        setBackgroundColor(isExpanded ? mFocusedBackgroundColor : Color.WHITE);
+
+        // Update whether the logo is displayed.
+        if (mLogoView != null) {
+            boolean show = mLogoResourceId != 0 && mDisplayMode != DISPLAY_MODE_FOCUSED;
+            mLogoView.setVisibility(show ? VISIBLE : GONE);
+        }
+
+        // The button takes precedence over the summary text and the chevron.
+        int editButtonState = getEditButtonState();
+        if (editButtonState == EDIT_BUTTON_GONE) {
+            mEditButtonView.setVisibility(GONE);
+            mChevronView.setVisibility(
+                    mDisplayMode == DISPLAY_MODE_EXPANDABLE ? VISIBLE : GONE);
+
+            // Update whether the summary is displayed.
+            boolean showSummary =
+                    mIsSummaryAllowed && !TextUtils.isEmpty(mSummaryLeftTextView.getText());
+            mSummaryLayout.setVisibility(showSummary ? VISIBLE : GONE);
+        } else {
+            // Show the edit button and hide the chevron and the summary.
+            boolean isButtonAllowed = mDisplayMode == DISPLAY_MODE_EXPANDABLE
+                    || mDisplayMode == DISPLAY_MODE_NORMAL;
+            mSummaryLayout.setVisibility(GONE);
+            mChevronView.setVisibility(GONE);
+            mEditButtonView.setVisibility(isButtonAllowed ? VISIBLE : GONE);
+            mEditButtonView.setText(
+                    editButtonState == EDIT_BUTTON_SELECT ? R.string.select : R.string.add);
+        }
+
+        // The title gains extra spacing when there is another visible view in the main section.
+        int numVisibleMainViews = 0;
+        for (int i = 0; i < mMainSection.getChildCount(); i++) {
+            if (mMainSection.getChildAt(i).getVisibility() == VISIBLE) numVisibleMainViews += 1;
+        }
+
+        boolean isTitleMarginNecessary = numVisibleMainViews > 1 && isExpanded;
+        int oldMargin =
+                ((ViewGroup.MarginLayoutParams) mTitleView.getLayoutParams()).bottomMargin;
+        int newMargin = isTitleMarginNecessary ? mVerticalSpacing : 0;
+
+        if (oldMargin != newMargin) {
+            ((ViewGroup.MarginLayoutParams) mTitleView.getLayoutParams()).bottomMargin =
+                    newMargin;
+            requestLayout();
+        }
     }
 
     /**
      * Section with a secondary TextView beneath the summary to show additional details.
      *
      * ............................................................................
-     * . TITLE                                                          |         .
-     * .................................................................|         .
-     * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT | CHEVRON .
-     * .................................................................|         .
-     * . EXTRA TEXT                                                     |         .
+     * . TITLE                                                          | CHEVRON .
+     * .................................................................|    or   .
+     * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT |   ADD   .
+     * .................................................................|    or   .
+     * . EXTRA TEXT                                                     |  SELECT .
      * ............................................................................
      */
     public static class ExtraTextSection extends PaymentRequestSection {
         private TextView mExtraTextView;
+        private int mEditButtonState = EDIT_BUTTON_GONE;
 
         public ExtraTextSection(Context context, String sectionName, SectionDelegate delegate) {
             super(context, sectionName, delegate);
@@ -381,6 +495,17 @@
             mExtraTextView.setText(text);
             mExtraTextView.setVisibility(TextUtils.isEmpty(text) ? GONE : VISIBLE);
         }
+
+        /** Sets the state of the edit button. */
+        public void setEditButtonState(int state) {
+            mEditButtonState = state;
+            updateControlLayout();
+        }
+
+        @Override
+        public int getEditButtonState() {
+            return mEditButtonState;
+        }
     }
 
     /**
@@ -393,11 +518,11 @@
      *
      * ............................................................................
      * . TITLE                                                          |         .
-     * .................................................................|         .
-     * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT |         .
-     * .................................................................| CHEVRON .
-     * .                                      | Line item 1 |    $13.99 |         .
-     * .                                      | Line item 2 |      $.99 |         .
+     * .................................................................| CHERVON .
+     * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT |    or   .
+     * .................................................................|   ADD   .
+     * .                                      | Line item 1 |    $13.99 |    or   .
+     * .                                      | Line item 2 |      $.99 |  SELECT .
      * .                                      | Line item 3 |     $2.99 |         .
      * ............................................................................
      */
@@ -495,9 +620,11 @@
         }
 
         @Override
-        public void setDisplayMode(int displayMode) {
-            super.setDisplayMode(displayMode);
-            mBreakdownLayout.setVisibility(displayMode == DISPLAY_MODE_FOCUSED ? VISIBLE : GONE);
+        protected void updateControlLayout() {
+            if (!mIsLayoutInitialized) return;
+
+            mBreakdownLayout.setVisibility(mDisplayMode == DISPLAY_MODE_FOCUSED ? VISIBLE : GONE);
+            super.updateControlLayout();
         }
     }
 
@@ -516,16 +643,16 @@
      * . TITLE                                                          |                |         .
      * .................................................................|                |         .
      * . LEFT SUMMARY TEXT                        |  RIGHT SUMMARY TEXT |                |         .
-     * .................................................................|                |         .
-     * . Descriptive text that spans all three columns because it can.  |                |         .
-     * . ! Warning text that displays a big scary warning and icon.     |           LOGO | CHEVRON .
-     * . O Option 1                                              ICON 1 |                |         .
-     * . O Option 2                                              ICON 2 |                |         .
+     * .................................................................|                | CHEVRON .
+     * . Descriptive text that spans all three columns because it can.  |                |    or   .
+     * . ! Warning text that displays a big scary warning and icon.     |           LOGO |   ADD   .
+     * . O Option 1                                              ICON 1 |                |    or   .
+     * . O Option 2                                              ICON 2 |                |  SELECT .
      * . O Option 3                                              ICON 3 |                |         .
      * . + ADD THING                                                    |                |         .
      * .............................................................................................
      */
-    public static class OptionSection extends PaymentRequestSection implements OnClickListener {
+    public static class OptionSection extends PaymentRequestSection {
 
         private static final int INVALID_OPTION_INDEX = -1;
 
@@ -540,7 +667,7 @@
          * + The "label" is text describing the row.
          * + The "icon" is a logo representing the option, like a credit card.
          */
-        private class OptionRow {
+        public class OptionRow {
             private static final int OPTION_ROW_TYPE_OPTION = 0;
             private static final int OPTION_ROW_TYPE_ADD = 1;
             private static final int OPTION_ROW_TYPE_DESCRIPTION = 2;
@@ -589,6 +716,12 @@
                 mButton.setId(id);
             }
 
+            /** @return the label for the row. */
+            @VisibleForTesting
+            public CharSequence getLabelText() {
+                return mLabel.getText();
+            }
+
             private View createButton(
                     GridLayout parent, int rowIndex, boolean isSelected, boolean isEnabled) {
                 if (mRowType == OPTION_ROW_TYPE_DESCRIPTION) return null;
@@ -716,9 +849,6 @@
             }
         }
 
-        /** Text to display in the summary when there is no selected option. */
-        private final CharSequence mEmptyLabel;
-
         /** Top and bottom margins for each item. */
         private final int mVerticalMargin;
 
@@ -734,29 +864,27 @@
         /** A spinner to show when the user selection is being checked. */
         private View mCheckingProgress;
 
+        /** SectionInformation that is used to populate the views in this section. */
+        private SectionInformation mSectionInformation;
+
         /**
          * Constructs an OptionSection.
          *
          * @param context     Context to pull resources from.
          * @param sectionName Title of the section to display.
-         * @param emptyLabel  An optional string to display when no item is selected.
          * @param delegate    Delegate to alert when something changes in the dialog.
          */
-        public OptionSection(Context context, String sectionName, @Nullable CharSequence emptyLabel,
-                SectionDelegate delegate) {
+        public OptionSection(Context context, String sectionName, SectionDelegate delegate) {
             super(context, sectionName, delegate);
             mVerticalMargin = context.getResources().getDimensionPixelSize(
                     R.dimen.payments_section_small_spacing);
-            mEmptyLabel = emptyLabel;
             mIconMaxWidth = context.getResources().getDimensionPixelSize(
                     R.dimen.payments_section_logo_width);
-            setSummaryText(emptyLabel, null);
+            setSummaryText(null, null);
         }
 
         @Override
-        public void onClick(View v) {
-            if (!mDelegate.isAcceptingUserInput()) return;
-
+        public void handleClick(View v) {
             // Handle click on the "ADD THING" button.
             for (int i = 0; i < mOptionRows.size(); i++) {
                 OptionRow row = mOptionRows.get(i);
@@ -776,9 +904,15 @@
         }
 
         @Override
-        public boolean onInterceptTouchEvent(MotionEvent event) {
-            // Allow touches to propagate to children only if the layout can be interacted with.
-            return !mDelegate.isAcceptingUserInput();
+        public void focusSection(boolean shouldFocus) {
+            // Override expansion of the section if there's no options to show.
+            boolean mayFocus = mSectionInformation != null && mSectionInformation.getSize() > 0;
+            if (!mayFocus && shouldFocus) {
+                setDisplayMode(PaymentRequestSection.DISPLAY_MODE_NORMAL);
+                return;
+            }
+
+            super.focusSection(shouldFocus);
         }
 
         @Override
@@ -804,9 +938,11 @@
 
         /** Updates the View to account for the new {@link SectionInformation} being passed in. */
         public void update(SectionInformation information) {
+            mSectionInformation = information;
             PaymentOption selectedItem = information.getSelectedItem();
             updateSelectedItem(selectedItem);
             updateOptionList(information, selectedItem);
+            updateControlLayout();
         }
 
         private View createLoadingSpinner() {
@@ -843,14 +979,14 @@
         }
 
         @Override
-        public void setDisplayMode(int displayMode) {
-            super.setDisplayMode(displayMode);
+        protected void updateControlLayout() {
+            if (!mIsLayoutInitialized) return;
 
-            if (displayMode == DISPLAY_MODE_FOCUSED) {
+            if (mDisplayMode == DISPLAY_MODE_FOCUSED) {
                 setIsSummaryAllowed(false);
                 mOptionLayout.setVisibility(VISIBLE);
                 setSpinnerVisibility(false);
-            } else if (displayMode == DISPLAY_MODE_CHECKING) {
+            } else if (mDisplayMode == DISPLAY_MODE_CHECKING) {
                 setIsSummaryAllowed(false);
                 mOptionLayout.setVisibility(GONE);
                 setSpinnerVisibility(true);
@@ -859,20 +995,36 @@
                 mOptionLayout.setVisibility(GONE);
                 setSpinnerVisibility(false);
             }
+
+            super.updateControlLayout();
+        }
+
+        @Override
+        public int getEditButtonState() {
+            if (mSectionInformation == null) return EDIT_BUTTON_GONE;
+
+            if (mSectionInformation.getSize() == 0 && mCanAddItems) {
+                // There aren't any PaymentOptions.  Ask the user to add a new one.
+                return EDIT_BUTTON_ADD;
+            } else if (mSectionInformation.getSelectedItem() == null) {
+                // The user hasn't selected any available PaymentOptions.  Ask the user to pick one.
+                return EDIT_BUTTON_SELECT;
+            } else {
+                return EDIT_BUTTON_GONE;
+            }
         }
 
         private void updateSelectedItem(PaymentOption selectedItem) {
             if (selectedItem == null) {
                 setLogoResource(0);
-                if (TextUtils.isEmpty(mEmptyLabel)) {
-                    setIsSummaryAllowed(false);
-                } else {
-                    setSummaryText(mEmptyLabel, null);
-                }
+                setIsSummaryAllowed(false);
+                setSummaryText(null, null);
             } else {
                 setLogoResource(selectedItem.getDrawableIconId());
                 setSummaryText(convertOptionToString(selectedItem, false), null);
             }
+
+            updateControlLayout();
         }
 
         private void updateOptionList(SectionInformation information, PaymentOption selectedItem) {
@@ -881,21 +1033,22 @@
             mLabelsForTest.clear();
 
             // Show any additional text requested by the layout.
-            if (!TextUtils.isEmpty(mDelegate.getAdditionalText(this))) {
+            String additionalText = mDelegate.getAdditionalText(this);
+            if (!TextUtils.isEmpty(additionalText)) {
                 OptionRow descriptionRow = new OptionRow(mOptionLayout,
-                        mOptionLayout.getChildCount(),
+                        mOptionRows.size(),
                         mDelegate.isAdditionalTextDisplayingWarning(this)
                                 ? OptionRow.OPTION_ROW_TYPE_WARNING
                                 : OptionRow.OPTION_ROW_TYPE_DESCRIPTION,
                                 null, false);
                 mOptionRows.add(descriptionRow);
-                descriptionRow.setLabel(mDelegate.getAdditionalText(this));
+                descriptionRow.setLabel(additionalText);
             }
 
             // List out known payment options.
             int firstOptionIndex = INVALID_OPTION_INDEX;
             for (int i = 0; i < information.getSize(); i++) {
-                int currentRow = mOptionLayout.getChildCount();
+                int currentRow = mOptionRows.size();
                 if (firstOptionIndex == INVALID_OPTION_INDEX) firstOptionIndex = currentRow;
 
                 PaymentOption item = information.getItem(i);
@@ -957,6 +1110,12 @@
         public int getNumberOfOptionLabelsForTest() {
             return mLabelsForTest.size();
         }
+
+        /** Returns the OptionRow at the specified |index|. */
+        @VisibleForTesting
+        public OptionRow getOptionRowAtIndex(int index) {
+            return mOptionRows.get(index);
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
index 92318667..b38d06d4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.payments.ui;
 
+import static org.chromium.chrome.browser.payments.ui.PaymentRequestSection.EDIT_BUTTON_GONE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -194,6 +196,11 @@
         void onPaymentRequestReadyToPay(PaymentRequestUI ui);
 
         /**
+         * Called when the UI has been updated to reflect checking a selected option.
+         */
+        void onPaymentRequestSelectionChecked(PaymentRequestUI ui);
+
+        /**
          * Called when edit dialog is showing.
          */
         void onPaymentRequestReadyToEdit();
@@ -257,7 +264,7 @@
     private OptionSection mPaymentMethodSection;
     private List<SectionSeparator> mSectionSeparators;
 
-    private ViewGroup mSelectedSection;
+    private PaymentRequestSection mSelectedSection;
     private boolean mIsShowingEditDialog;
     private boolean mIsProcessingPayClicked;
     private boolean mIsClientClosing;
@@ -323,12 +330,12 @@
                 }
                 updateSection(TYPE_PAYMENT_METHODS, result.getPaymentMethods());
                 if (mShippingAddressSectionInformation.getSelectedItem() == null) {
-                    mShippingAddressSection.setDisplayMode(
-                            PaymentRequestSection.DISPLAY_MODE_FOCUSED);
+                    expand(mShippingAddressSection);
                 } else {
                     expand(null);
                 }
                 updatePayButtonEnabled();
+                notifySelectionChecked();
             }
         };
 
@@ -375,24 +382,26 @@
                     String selectedShippingAddress = result.getSelectedShippingAddressLabel();
                     String selectedShippingName = result.getSelectedShippingAddressSublabel();
                     String selectedShippingOptionLabel = result.getSelectedShippingOptionLabel();
-                    if (selectedShippingAddress == null && selectedShippingOptionLabel == null) {
-                        mShippingSummarySection.setSummaryText(mContext.getString(
-                                R.string.payments_select_shipping_prompt), null);
+
+                    if (selectedShippingAddress == null || selectedShippingOptionLabel == null) {
+                        // Let the summary display a SELECT/ADD button for the first subsection
+                        // that needs it.
+                        mShippingSummarySection.setSummaryText(null, null);
                         mShippingSummarySection.setSummaryProperties(null, false, null, false);
+
+                        PaymentRequestSection section =
+                                mShippingAddressSection.getEditButtonState() == EDIT_BUTTON_GONE
+                                        ? mShippingOptionSection : mShippingAddressSection;
+                        mShippingSummarySection.setEditButtonState(section.getEditButtonState());
                     } else {
                         // Show the shipping address and the name in the summary section.
-                        mShippingSummarySection.setSummaryText(selectedShippingAddress == null
-                                ? mContext.getString(
-                                        R.string.payments_select_shipping_address_prompt)
-                                : selectedShippingAddress, selectedShippingName);
+                        mShippingSummarySection.setSummaryText(
+                                selectedShippingAddress, selectedShippingName);
                         mShippingSummarySection.setSummaryProperties(
                                 TruncateAt.MIDDLE, true, null, true);
 
                         // Indicate the shipping option below the address.
-                        mShippingSummarySection.setExtraText(selectedShippingOptionLabel == null
-                                ? mContext.getString(
-                                        R.string.payments_select_shipping_option_prompt)
-                                : selectedShippingOptionLabel);
+                        mShippingSummarySection.setExtraText(selectedShippingOptionLabel);
                     }
                 }
 
@@ -453,22 +462,21 @@
         mPaymentContainer = (ScrollView) mRequestView.findViewById(R.id.option_container);
         mPaymentContainerLayout =
                 (LinearLayout) mRequestView.findViewById(R.id.payment_container_layout);
-        mOrderSummarySection = new LineItemBreakdownSection(activity,
-                activity.getString(R.string.payments_order_summary_label), this);
-        mShippingSummarySection = new ExtraTextSection(activity,
-                activity.getString(R.string.payments_shipping_summary_label), this);
-        mShippingAddressSection = new OptionSection(activity,
-                activity.getString(R.string.payments_shipping_address_label),
-                activity.getString(R.string.payments_select_shipping_address_prompt), this);
-        mShippingOptionSection = new OptionSection(activity,
-                activity.getString(R.string.payments_shipping_option_label),
-                activity.getString(R.string.payments_select_shipping_option_prompt), this);
-        mContactDetailsSection = new OptionSection(activity,
-                activity.getString(R.string.payments_contact_details_label),
-                activity.getString(R.string.payments_select_contact_details_prompt), this);
-        mPaymentMethodSection = new OptionSection(activity,
-                activity.getString(R.string.payments_method_of_payment_label),
-                activity.getString(R.string.payments_select_method_of_payment_prompt), this);
+        mOrderSummarySection = new LineItemBreakdownSection(
+                activity, activity.getString(R.string.payments_order_summary_label), this);
+        mShippingSummarySection = new ExtraTextSection(
+                activity, activity.getString(R.string.payments_shipping_summary_label), this);
+        mShippingAddressSection = new OptionSection(
+                activity, activity.getString(R.string.payments_shipping_address_label), this);
+        mShippingOptionSection = new OptionSection(
+                activity, activity.getString(R.string.payments_shipping_option_label), this);
+        mContactDetailsSection = new OptionSection(
+                activity, activity.getString(R.string.payments_contact_details_label), this);
+        mPaymentMethodSection = new OptionSection(
+                activity, activity.getString(R.string.payments_method_of_payment_label), this);
+
+        // Some sections conditionally allow adding new options.
+        mShippingOptionSection.setCanAddItems(false);
         mPaymentMethodSection.setCanAddItems(canAddCards);
 
         // Add the necessary sections to the layout.
@@ -588,12 +596,13 @@
             mPaymentMethodSection.update(section);
         }
         mIsEditingPaymentItem = false;
+        updateSectionButtons();
         notifyReadyToClose();
         updatePayButtonEnabled();
     }
 
     @Override
-    public void onPaymentOptionChanged(final OptionSection section, PaymentOption option) {
+    public void onPaymentOptionChanged(final PaymentRequestSection section, PaymentOption option) {
         @SelectionResult int result = SELECTION_RESULT_NONE;
         if (section == mShippingAddressSection
                 && mShippingAddressSectionInformation.getSelectedItem() != option) {
@@ -615,9 +624,17 @@
     }
 
     @Override
-    public void onAddPaymentOption(OptionSection section) {
+    public void onAddPaymentOption(PaymentRequestSection section) {
         assert section != mShippingOptionSection;
 
+        // There's no way to add new shipping options, so users adding an option via the shipping
+        // summary's button have to be adding an address.  Expand the sheet when this happens so
+        // that the shipping address section properly appears afterward.
+        if (section == mShippingSummarySection) {
+            expand(null);
+            section = mShippingAddressSection;
+        }
+
         @SelectionResult int result = SELECTION_RESULT_NONE;
         if (section == mShippingAddressSection) {
             result = mClient.onSectionAddOption(TYPE_SHIPPING_ADDRESSES, mUpdateSectionsCallback);
@@ -630,12 +647,13 @@
         updateStateFromResult(section, result);
     }
 
-    void updateStateFromResult(OptionSection section, @SelectionResult int result) {
+    void updateStateFromResult(PaymentRequestSection section, @SelectionResult int result) {
         mIsClientCheckingSelection = result == SELECTION_RESULT_ASYNCHRONOUS_VALIDATION;
         mIsEditingPaymentItem = result == SELECTION_RESULT_EDITOR_LAUNCH;
 
         if (mIsClientCheckingSelection) {
-            startSectionResizeAnimation();
+            mSelectedSection = section;
+            updateSectionVisibility();
             section.setDisplayMode(PaymentRequestSection.DISPLAY_MODE_CHECKING);
         } else {
             expand(null);
@@ -645,7 +663,7 @@
     }
 
     @Override
-    public boolean isBoldLabelNeeded(OptionSection section) {
+    public boolean isBoldLabelNeeded(PaymentRequestSection section) {
         return section == mShippingAddressSection;
     }
 
@@ -674,6 +692,12 @@
 
         if (!isAcceptingUserInput()) return;
 
+        // Users can only expand incomplete sections by clicking on their edit buttons.
+        if (v instanceof PaymentRequestSection) {
+            PaymentRequestSection section = (PaymentRequestSection) v;
+            if (section.getEditButtonState() != EDIT_BUTTON_GONE) return;
+        }
+
         if (v == mOrderSummarySection) {
             expand(mOrderSummarySection);
         } else if (v == mShippingSummarySection || v == mShippingAddressSection) {
@@ -809,7 +833,7 @@
                 && !mIsClientCheckingSelection;
     }
 
-    private void expand(ViewGroup section) {
+    private void expand(PaymentRequestSection section) {
         if (!mIsShowingEditDialog) {
             // Container now takes the full height of the screen, animating towards it.
             mRequestView.getLayoutParams().height = LayoutParams.MATCH_PARENT;
@@ -844,6 +868,10 @@
             // Make the dialog take the whole screen.
             mDialog.getWindow().setLayout(
                     ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
+            // Disable all but the first button.
+            updateSectionButtons();
+
             mIsShowingEditDialog = true;
         }
 
@@ -885,25 +913,33 @@
         };
     }
 
-    /** Update the display status of each expandable section. */
+    /** Update the display status of each expandable section in the full dialog. */
     private void updateSectionVisibility() {
         startSectionResizeAnimation();
+        mOrderSummarySection.focusSection(mSelectedSection == mOrderSummarySection);
+        mShippingAddressSection.focusSection(mSelectedSection == mShippingAddressSection);
+        mShippingOptionSection.focusSection(mSelectedSection == mShippingOptionSection);
+        mContactDetailsSection.focusSection(mSelectedSection == mContactDetailsSection);
+        mPaymentMethodSection.focusSection(mSelectedSection == mPaymentMethodSection);
+        updateSectionButtons();
+    }
 
-        mOrderSummarySection.setDisplayMode(mSelectedSection == mOrderSummarySection
-                ? PaymentRequestSection.DISPLAY_MODE_FOCUSED
-                : PaymentRequestSection.DISPLAY_MODE_EXPANDABLE);
-        mShippingAddressSection.setDisplayMode(mSelectedSection == mShippingAddressSection
-                ? PaymentRequestSection.DISPLAY_MODE_FOCUSED
-                : PaymentRequestSection.DISPLAY_MODE_EXPANDABLE);
-        mShippingOptionSection.setDisplayMode(mSelectedSection == mShippingOptionSection
-                ? PaymentRequestSection.DISPLAY_MODE_FOCUSED
-                : PaymentRequestSection.DISPLAY_MODE_EXPANDABLE);
-        mContactDetailsSection.setDisplayMode(mSelectedSection == mContactDetailsSection
-                ? PaymentRequestSection.DISPLAY_MODE_FOCUSED
-                : PaymentRequestSection.DISPLAY_MODE_EXPANDABLE);
-        mPaymentMethodSection.setDisplayMode(mSelectedSection == mPaymentMethodSection
-                ? PaymentRequestSection.DISPLAY_MODE_FOCUSED
-                : PaymentRequestSection.DISPLAY_MODE_EXPANDABLE);
+    /**
+     * Updates the enabled/disbled state of each section's edit button.
+     *
+     * Only the top-most button is enabled -- the others are disabled so the user is directed
+     * through the form from top to bottom.
+     */
+    private void updateSectionButtons() {
+        boolean mayEnableButton = true;
+        for (int i = 0; i < mPaymentContainerLayout.getChildCount(); i++) {
+            View child = mPaymentContainerLayout.getChildAt(i);
+            if (!(child instanceof PaymentRequestSection)) continue;
+
+            PaymentRequestSection section = (PaymentRequestSection) child;
+            section.setIsEditButtonEnabled(mayEnableButton);
+            if (section.getEditButtonState() != EDIT_BUTTON_GONE) mayEnableButton = false;
+        }
     }
 
     /**
@@ -926,7 +962,7 @@
     }
 
     @Override
-    public String getAdditionalText(OptionSection section) {
+    public String getAdditionalText(PaymentRequestSection section) {
         if (section == mShippingAddressSection) {
             int selectedItemIndex = mShippingAddressSectionInformation.getSelectedItemIndex();
             boolean isNecessary = mClient.merchantNeedsShippingAddress()
@@ -942,13 +978,23 @@
     }
 
     @Override
-    public boolean isAdditionalTextDisplayingWarning(OptionSection section) {
+    public boolean isAdditionalTextDisplayingWarning(PaymentRequestSection section) {
         return section == mShippingAddressSection
                 && mShippingAddressSectionInformation != null
                 && mShippingAddressSectionInformation.getSelectedItemIndex()
                         == SectionInformation.INVALID_SELECTION;
     }
 
+    @Override
+    public void onSectionClicked(PaymentRequestSection section) {
+        if (section == mShippingSummarySection) {
+            // Clicking the summary section focuses one of its subsections.
+            section = mShippingAddressSection.getEditButtonState() == EDIT_BUTTON_GONE
+                    ? mShippingOptionSection : mShippingAddressSection;
+        }
+        expand(section);
+    }
+
     /**
      * Animates the different sections of the dialog expanding and contracting into their final
      * positions.
@@ -1132,7 +1178,7 @@
     }
 
     @VisibleForTesting
-    public ViewGroup getShippingSummarySectionForTest() {
+    public PaymentRequestSection getShippingSummarySectionForTest() {
         return mShippingSummarySection;
     }
 
@@ -1168,4 +1214,10 @@
             sObserverForTest.onPaymentRequestReadyToClose(this);
         }
     }
+
+    private void notifySelectionChecked() {
+        if (sObserverForTest != null) {
+            sObserverForTest.onPaymentRequestSelectionChecked(this);
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
index 95afcd2..89c119f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
@@ -594,14 +594,6 @@
     }
 
     /**
-     * @return whether there is a user set value for kNetworkPredictionEnabled.  This should only be
-     * used for preference migration. See http://crbug.com/334602
-     */
-    public boolean obsoleteNetworkPredictionEnabledHasUserSetting() {
-        return nativeObsoleteNetworkPredictionEnabledHasUserSetting();
-    }
-
-    /**
      * @return whether there is a user set value for kNetworkPredictionOptions.  This should only be
      * used for preference migration. See http://crbug.com/334602
      */
@@ -610,14 +602,6 @@
     }
 
     /**
-     * @return the user set value for kNetworkPredictionEnabled. This should only be used for
-     * preference migration. See http://crbug.com/334602
-     */
-    public boolean obsoleteGetNetworkPredictionEnabledUserPrefValue() {
-        return nativeObsoleteGetNetworkPredictionEnabledUserPrefValue();
-    }
-
-    /**
      * @return Network predictions preference.
      */
     public boolean getNetworkPredictionEnabled() {
@@ -1187,9 +1171,7 @@
     private native void nativeSetSafeBrowsingEnabled(boolean enabled);
     private native boolean nativeGetSafeBrowsingManaged();
     private native boolean nativeGetNetworkPredictionManaged();
-    private native boolean nativeObsoleteNetworkPredictionEnabledHasUserSetting();
     private native boolean nativeObsoleteNetworkPredictionOptionsHasUserSetting();
-    private native boolean nativeObsoleteGetNetworkPredictionEnabledUserPrefValue();
     private native boolean nativeGetNetworkPredictionEnabled();
     private native void nativeSetNetworkPredictionEnabled(boolean enabled);
     private native void nativeSetResolveNavigationErrorEnabled(boolean enabled);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
index c4181576..1f4f1faf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java
@@ -38,8 +38,7 @@
         profilesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
         AutofillProfile noSelection = new AutofillProfile();
-        noSelection.setLabel(
-                getActivity().getString(R.string.autofill_billing_address_select_prompt));
+        noSelection.setLabel(getActivity().getString(R.string.select));
         profilesAdapter.add(noSelection);
 
         List<AutofillProfile> profiles = PersonalDataManager.getInstance().getProfilesForSettings();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
index 3c32b0888..c8e15c13 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -13,6 +13,7 @@
 import android.widget.TextView;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.PasswordUIView;
 import org.chromium.chrome.browser.PasswordUIView.PasswordListObserver;
 
@@ -28,6 +29,8 @@
     // If false this represents a saved name/password.
     private boolean mException;
 
+    public static final String VIEW_PASSWORDS = "view-passwords";
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -37,7 +40,12 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        View v = inflater.inflate(R.layout.password_entry_editor, container, false);
+        View v;
+        if (ChromeFeatureList.isEnabled(VIEW_PASSWORDS)) {
+            v = inflater.inflate(R.layout.password_entry_editor_interactive, container, false);
+        } else {
+            v = inflater.inflate(R.layout.password_entry_editor, container, false);
+        }
         getActivity().setTitle(R.string.password_entry_editor_title);
 
         // Extras are set on this intent in class SavePasswordsPreferences.
@@ -58,8 +66,9 @@
         String url = extras.getString(SavePasswordsPreferences.PASSWORD_LIST_URL);
         TextView urlView = (TextView) v.findViewById(R.id.password_entry_editor_url);
         urlView.setText(url);
-
-        hookupCancelDeleteButtons(v);
+        if (!ChromeFeatureList.isEnabled(VIEW_PASSWORDS)) {
+            hookupCancelDeleteButtons(v);
+        }
         return v;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
index c4c2d433..cc67d03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
@@ -147,11 +147,6 @@
                     }
                 }
             }
-            // But disable after all if kNetworkPredictionEnabled was disabled by the user.
-            if (prefService.obsoleteNetworkPredictionEnabledHasUserSetting()
-                    && !prefService.obsoleteGetNetworkPredictionEnabledUserPrefValue()) {
-                newValue = false;
-            }
             // Save new value in Chrome PrefService.
             prefService.setNetworkPredictionEnabled(newValue);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
index bca422e..88a2a1ae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
@@ -29,7 +29,10 @@
 import org.chromium.content_public.browser.WebContents;
 
 import java.net.URI;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Shows the permissions and other settings for a particular website.
@@ -49,6 +52,7 @@
     public static final String EXTRA_LOCATION = "org.chromium.chrome.preferences.location";
 
     public static final String EXTRA_WEB_CONTENTS = "org.chromium.chrome.preferences.web_contents";
+    public static final String EXTRA_USB_INFO = "org.chromium.chrome.preferences.usb_info";
 
     // Preference keys, see single_website_preferences.xml
     // Headings:
@@ -103,6 +107,9 @@
     // The address of the site we want to display. Used only if EXTRA_ADDRESS is provided.
     private WebsiteAddress mSiteAddress;
 
+    // The number of USB device permissions displayed.
+    private int mUsbPermissionCount;
+
     private class SingleWebsitePermissionsPopulator
             implements WebsitePermissionsFetcher.WebsitePermissionsCallback {
         private final WebContents mWebContents;
@@ -242,6 +249,9 @@
                     merged.addStorageInfo(storageInfo);
                 }
             }
+            for (UsbInfo usbInfo : other.getUsbInfo()) {
+                if (origin.equals(usbInfo.getOrigin())) merged.addUsbInfo(usbInfo);
+            }
 
             // TODO(mvanouwerkerk): Make the various info types share a common interface that
             // supports reading the origin or host.
@@ -266,6 +276,9 @@
     private void displaySitePermissions() {
         addPreferencesFromResource(R.xml.single_website_preferences);
 
+        Set<String> permissionPreferenceKeys =
+                new HashSet<>(Arrays.asList(PERMISSION_PREFERENCE_KEYS));
+        int maxPermissionOrder = 0;
         ListAdapter preferences = getPreferenceScreen().getRootAdapter();
         for (int i = 0; i < preferences.getCount(); ++i) {
             Preference preference = (Preference) preferences.getItem(i);
@@ -312,6 +325,22 @@
             } else if (PREF_PROTECTED_MEDIA_IDENTIFIER_PERMISSION.equals(preference.getKey())) {
                 setUpListPreference(preference, mSite.getProtectedMediaIdentifierPermission());
             }
+
+            if (permissionPreferenceKeys.contains(preference.getKey())) {
+                maxPermissionOrder = Math.max(maxPermissionOrder, preference.getOrder());
+            }
+        }
+
+        for (UsbInfo info : mSite.getUsbInfo()) {
+            Preference preference = new Preference(getActivity());
+            preference.getExtras().putSerializable(EXTRA_USB_INFO, info);
+            preference.setIcon(R.drawable.settings_usb);
+            preference.setOnPreferenceClickListener(this);
+            preference.setOrder(maxPermissionOrder++);
+            preference.setTitle(info.getName());
+            preference.setWidgetLayoutResource(R.layout.usb_permission);
+            getPreferenceScreen().addPreference(preference);
+            mUsbPermissionCount++;
         }
 
         // Remove the 'permission is off in Android' message if not needed.
@@ -396,6 +425,7 @@
     }
 
     private boolean hasPermissionsPreferences() {
+        if (mUsbPermissionCount > 0) return true;
         PreferenceScreen screen = getPreferenceScreen();
         for (String key : PERMISSION_PREFERENCE_KEYS) {
             if (screen.findPreference(key) != null) return true;
@@ -600,6 +630,23 @@
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
+        Bundle extras = preference.peekExtras();
+        if (extras != null) {
+            UsbInfo usbInfo = (UsbInfo) extras.getSerializable(EXTRA_USB_INFO);
+            if (usbInfo != null) {
+                usbInfo.revoke();
+
+                PreferenceScreen preferenceScreen = getPreferenceScreen();
+                preferenceScreen.removePreference(preference);
+                mUsbPermissionCount--;
+                if (!hasPermissionsPreferences()) {
+                    Preference heading = preferenceScreen.findPreference(PREF_PERMISSIONS);
+                    preferenceScreen.removePreference(heading);
+                }
+                return true;
+            }
+        }
+
         // Handle the Clear & Reset preference click by showing a confirmation.
         new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
                 .setTitle(R.string.website_reset)
@@ -646,6 +693,7 @@
         mSite.setNotificationPermission(ContentSetting.DEFAULT);
         mSite.setPopupPermission(ContentSetting.DEFAULT);
         mSite.setProtectedMediaIdentifierPermission(ContentSetting.DEFAULT);
+        for (UsbInfo info : mSite.getUsbInfo()) info.revoke();
 
         // Clear the storage and finish the activity if necessary.
         if (mSite.getTotalUsage() > 0) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/UsbInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/UsbInfo.java
new file mode 100644
index 0000000..c48aa1e
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/UsbInfo.java
@@ -0,0 +1,52 @@
+// Copyright 2016 The Chromium 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.preferences.website;
+
+import java.io.Serializable;
+
+/**
+ * USB device information for a given origin.
+ */
+public class UsbInfo implements Serializable {
+    private final String mOrigin;
+    private final String mEmbedder;
+    private final String mName;
+    private final String mObject;
+
+    UsbInfo(String origin, String embedder, String name, String object) {
+        mOrigin = origin;
+        mEmbedder = embedder;
+        mName = name;
+        mObject = object;
+    }
+
+    /**
+     * Returns the origin that requested the permission.
+     */
+    public String getOrigin() {
+        return mOrigin;
+    }
+
+    /**
+     * Returns the origin that the requester was embedded in.
+     */
+    public String getEmbedder() {
+        return mEmbedder;
+    }
+
+    /**
+     * Returns the name of the USB device for display in the UI.
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Revokes permission for the origin to access the USB device.
+     */
+    public void revoke() {
+        WebsitePreferenceBridge.nativeRevokeUsbPermission(mOrigin, mEmbedder, mObject);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java
index a3ad7e0e..9cc2118 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java
@@ -42,6 +42,7 @@
     private ProtectedMediaIdentifierInfo mProtectedMediaIdentifierInfo;
     private final List<StorageInfo> mStorageInfo = new ArrayList<StorageInfo>();
     private int mStorageInfoCallbacksLeft;
+    private final List<UsbInfo> mUsbInfo = new ArrayList<UsbInfo>();
 
     public Website(WebsiteAddress origin, WebsiteAddress embedder) {
         mOrigin = origin;
@@ -485,4 +486,18 @@
         }
         return usage;
     }
+
+    /**
+     * Add information about a USB device permission to the set stored in this object.
+     */
+    public void addUsbInfo(UsbInfo info) {
+        mUsbInfo.add(info);
+    }
+
+    /**
+     * Returns the set of USB devices this website has been granted permission to access.
+     */
+    public List<UsbInfo> getUsbInfo() {
+        return new ArrayList<UsbInfo>(mUsbInfo);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
index 414676ef..7fdff01 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
@@ -80,6 +80,8 @@
         queue.add(new BackgroundSyncExceptionInfoFetcher());
         // Autoplay permission is per-origin.
         queue.add(new AutoplayExceptionInfoFetcher());
+        // USB device permission is per-origin and per-embedder.
+        queue.add(new UsbInfoFetcher());
 
         queue.add(new PermissionsAvailableCallbackRunner());
 
@@ -388,6 +390,18 @@
         }
     }
 
+    private class UsbInfoFetcher extends Task {
+        @Override
+        public void run() {
+            for (UsbInfo info : WebsitePreferenceBridge.getUsbInfo()) {
+                WebsiteAddress origin = WebsiteAddress.create(info.getOrigin());
+                if (origin == null) continue;
+                WebsiteAddress embedder = WebsiteAddress.create(info.getEmbedder());
+                findOrCreateSite(origin, embedder).addUsbInfo(info);
+            }
+        }
+    }
+
     private class PermissionsAvailableCallbackRunner extends Task {
         @Override
         public void run() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
index c61cd728..b5968e1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
@@ -231,6 +231,19 @@
     }
 
     /**
+     * Returns the list of all USB device permissions.
+     *
+     * There will be one UsbInfo instance for each granted permission. That
+     * means that if two origin/embedder pairs have permission for the same
+     * device there will be two UsbInfo instances.
+     */
+    public static List<UsbInfo> getUsbInfo() {
+        ArrayList<UsbInfo> list = new ArrayList<UsbInfo>();
+        nativeGetUsbOrigins(list);
+        return list;
+    }
+
+    /**
      * Inserts fullscreen information into a list.
      */
     @CalledByNative
@@ -239,6 +252,15 @@
         list.add(new FullscreenInfo(origin, embedder, false));
     }
 
+    /**
+     * Inserts USB device information into a list.
+     */
+    @CalledByNative
+    private static void insertUsbInfoIntoList(
+            ArrayList<UsbInfo> list, String origin, String embedder, String name, String object) {
+        list.add(new UsbInfo(origin, embedder, name, object));
+    }
+
     private static native void nativeGetGeolocationOrigins(Object list, boolean managedOnly);
     static native int nativeGetGeolocationSettingForOrigin(
             String origin, String embedder, boolean isIncognito);
@@ -287,4 +309,6 @@
             String origin, String embedder, boolean isIncognito);
     static native void nativeSetFullscreenSettingForOrigin(
             String origin, String embedder, int value, boolean isIncognito);
+    static native void nativeGetUsbOrigins(Object list);
+    static native void nativeRevokeUsbPermission(String origin, String embedder, String object);
 }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index f42fce8..9494600 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -195,6 +195,12 @@
       <message name="IDS_YESTERDAY" desc="Generic Label saying the date is yesterday.">
         Yesterday
       </message>
+      <message name="IDS_SELECT" desc="Prompt for user to select something. [CHAR-LIMIT=20]">
+        Select
+      </message>
+      <message name="IDS_ADD" desc="Prompt for the user to add something, like a new address. [CHAR-LIMIT=20]">
+        Add
+      </message>
 
       <!-- Main Preferences -->
       <message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
@@ -290,9 +296,6 @@
       <message name="IDS_AUTOFILL_CREDIT_CARD_EDITOR_BILLING_ADDRESS" desc="Label for a spinner input field containing a list of billing addresses for a credit card. [CHAR-LIMIT=32]">
         Billing address
       </message>
-      <message name="IDS_AUTOFILL_BILLING_ADDRESS_SELECT_PROMPT" desc="Prompt for user to select a billing address in autofill settings for a credit card. [CHAR-LIMIT=24]">
-        Select
-      </message>
       <message name="IDS_AUTOFILL_DESCRIBE_LOCAL_COPY" desc="Text label that describes a Wallet credit card which has been copied to the local Chrome instance.">
          Copied to Chrome
        </message>
@@ -337,7 +340,28 @@
         Saved passwords will appear here.
       </message>
       <message name="IDS_PASSWORD_ENTRY_EDITOR_TITLE" desc='Title of the "edit a name/password" screen.'>
-        Edit saved name/password or exception
+        Edit saved account
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_SITE_TITLE" desc='Title preceding the identification of the site where the stored password comes from.'>
+        Site
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_USERNAME_TITLE" desc='Title preceding username of the account where the stored password comes from.'>
+        Username
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_PASSWORD" desc='Title preceding password on password entry editor.'>
+        Password
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_COPY_STORED_SITE" desc='Content description for the button that copies the stored password.'>
+        Copy site
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_COPY_STORED_USERNAME" desc='Content description for the button that copies the stored password.'>
+        Copy username
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_COPY_STORED_PASSWORD" desc='Content description for the button that copies the stored password.'>
+        Copy password
+      </message>
+      <message name="IDS_PASSWORD_ENTRY_EDITOR_VIEW_STORED_PASSWORD" desc='Content description for the button that allows users to view the stored password upon reauthentication.'>
+        Unmask password
       </message>
 
       <!-- Homepage preferences -->
@@ -818,6 +842,11 @@
         Full screen
       </message>
 
+      <!-- USB preferences -->
+      <message name="IDS_WEBSITE_SETTINGS_REVOKE_DEVICE_PERMISSION" desc="Content description for revoking a website's permission to access a device.">
+        Revoke device permission
+      </message>
+
       <!-- Data Saver -->
       <message name="IDS_DATA_REDUCTION_LO_FI_SNACKBAR_MESSAGE" desc="Message shown when a page is opened in low fidelity mode when there is a slow unreliable connection.">
         Slow connection detected
@@ -1557,9 +1586,6 @@
       </message>
 
       <!-- Add to Home screen strings -->
-      <message name="IDS_ADD" desc="Title for Add button [CHAR-LIMIT=20]">
-        Add
-      </message>
       <message name="IDS_ADD_TO_HOMESCREEN_TITLE" desc="Edit text title for Add to Home screen dialog [CHAR-LIMIT=30]">
         Title
       </message>
@@ -2608,15 +2634,9 @@
       <message name="IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL" desc="The title for the section that lets the user select the method of payment.">
         Payment
       </message>
-      <message name="IDS_PAYMENTS_SELECT_METHOD_OF_PAYMENT_PROMPT" desc="The label for the button that presents the user with the list of possible methods of payments, for example a list of their credit cards..">
-        Select payment method
-      </message>
       <message name="IDS_PAYMENTS_CONTACT_DETAILS_LABEL" desc="The title for the section that lets the user select how they can be contacted.">
         Contact info
       </message>
-      <message name="IDS_PAYMENTS_SELECT_CONTACT_DETAILS_PROMPT" desc="The label for the button that presents the user with the list of possible phone numbers and email addresses where the user can be reached.">
-        Select contact details
-      </message>
       <message name="IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL" desc="The title of the dialog for user to add new contact information, such as email address or phone number.">
         Add contact info
       </message>
@@ -2632,15 +2652,6 @@
       <message name="IDS_PAYMENTS_SHIPPING_OPTION_LABEL" desc="The title for the section that lets the user select how the product should be shipped.">
         Shipping option
       </message>
-      <message name="IDS_PAYMENTS_SELECT_SHIPPING_PROMPT" desc="The label for the button that presents the user with the list of possible shipping addresses and options.">
-        Select shipping
-      </message>
-      <message name="IDS_PAYMENTS_SELECT_SHIPPING_OPTION_PROMPT" desc="The label for the button that presents the user with the list of possible shipping options.">
-        Select shipping option
-      </message>
-      <message name="IDS_PAYMENTS_SELECT_SHIPPING_ADDRESS_PROMPT" desc="The label for the button that presents the user with the list of possible shipping addresses.">
-        Select shipping address
-      </message>
       <message name="IDS_PAYMENTS_ORDER_SUMMARY_LABEL" desc="The title of the section that shows the summary of the order, including names and prices of individual line items, i.e. the bill.">
         Order summary
       </message>
@@ -2681,7 +2692,7 @@
         Add contact info
       </message>
       <message name="IDS_PAYMENTS_SELECT_SHIPPING_ADDRESS_FOR_SHIPPING_METHODS" desc="Text implying that a user needs to pick a shipping address to see the shipping methods.">
-        Select a shipping address to check shipping methods.
+        Select a shipping address to check shipping methods and requirements.
       </message>
       <message name="IDS_PAYMENTS_CHECKING_OPTION" desc="Text explaining that the option the user selected is being checked and verified.">
         Checking
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_am.xtb b/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
index a3d89846..4a4dde29 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">ዕልባቶች እና የድር ታሪክ</translation>
 <translation id="1549000191223877751">ወደ ሌላ መስኮት ውሰድ</translation>
 <translation id="1553358976309200471">Chromeን አዘምን</translation>
-<translation id="1557201757634521564">ምስጠራን በራስ እወቅ</translation>
 <translation id="1612196535745283361">Chrome መሣሪያዎችን መቃኘት እንዲችል የአካባቢ መዳረሻ ያስፈልገዋል። የአካባቢ መዳረሻ <ph name="BEGIN_LINK" />ለዚህ መሣሪያ ጠፍቷል<ph name="END_LINK" />።</translation>
 <translation id="1620510694547887537">ካሜራ</translation>
 <translation id="1623104350909869708">ይህ ገጽ ተጨማሪ መገናኛዎችን እንዳይፈጥር አግድ</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">የይለፍ ሐረጎቹ አይዛመዱም</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />እገዛ ያግኙ<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">ቪዲዮ አስቀምጥ</translation>
-<translation id="307329814453917357">Google ትርጉምን በመጠቀም ገጾችን ለመተርጎም የቀረበ ሃሳብ</translation>
 <translation id="3089395242580810162">ማንነትን በማያሳውቅ ትር ክፈት</translation>
 <translation id="3090193911106258841">የኦዲዮ እና የቪዲዮ ግብዓትን በመድረስ ላይ</translation>
 <translation id="3117051980354074377">ዕልባቶችዎን ከሌሎች መሣሪያዎችዎ ለማግኘት ወደ Chrome ይግቡ።</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">ገፆች</translation>
 <translation id="4996978546172906250">ያጋሩ በ</translation>
 <translation id="5000922062037820727">ታግዷል (የሚመከር)</translation>
+<translation id="5005498671520578047">የይለፍ ቃል ቅዳ</translation>
 <translation id="5016205925109358554">ሰሪፍ</translation>
 <translation id="5039804452771397117">ፍቀድ</translation>
 <translation id="5040262127954254034">ግላዊነት</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">ከሙሉ ማያ ገጽ ለመውጣት ከላይ ይጎትቱ እና የተመለስ አዝራሩን ይንኩ።</translation>
 <translation id="5284584623296338184">በእርስዎ ዕልባቶች፣ ታሪክ፣ የይለፍ ቃላት እና ሌሎች ቅንብሮች ላይ የተደረጉ ለውጦች ከአሁን በኋላ ከእርስዎ የGoogle መለያ ጋር አይሠምሩም። ሆኖም ግን ነባር ውሂብዎ በእርስዎ የGoogle መለያ ላይ እንደተከማቸ ይቆያል።</translation>
 <translation id="5301954838959518834">እሺ፣ ገባኝ</translation>
-<translation id="5302048478445481009">ቋንቋ</translation>
 <translation id="5304593522240415983">ይህ መስክ ባዶ ሊሆን አይችልም</translation>
 <translation id="5308380583665731573">ይገናኙ</translation>
+<translation id="5308603654685598744">ይህ ባህሪ ሲበራ Chrome Google ትርጉምን ተጠቅሞ በሌሎች ቋንቋዎች የተጻፉ ገጾችን ሊተረጉምልዎ ይጠይቀዎታል።</translation>
 <translation id="5313967007315987356">ጣቢያ አክል</translation>
 <translation id="5317780077021120954">አስቀምጥ</translation>
 <translation id="5324858694974489420">የወላጅ መቆጣጠሪያዎች</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">ይህን መተግበሪያ በመጠቀምዎ በChrome <ph name="BEGIN_LINK1" />አገልግሎት ውል<ph name="END_LINK1" /> እና <ph name="BEGIN_LINK2" />የግላዊነት ማስታወቂያ<ph name="END_LINK2" /> ተስማምተዋል።</translation>
 <translation id="5414836363063783498">በማረጋገጥ ላይ…</translation>
 <translation id="5423934151118863508">በጣም በብዛት የተጎበኙ ገጾችዎ እዚህ ይመጣሉ</translation>
-<translation id="5424715742813396254">የተቀመጠ ስም/የይለፍ ቃል ወይም ለየት ያለውን ያርትዑ</translation>
 <translation id="5437003064129843501">የእርስዎ የተሰመረ ውሂብ በብጁ የይለፍ ሐረግ ጥበቃ የሚደረግለት ስለሆነ ግላዊነት የተላበሰ የይዘት ጥቆማዎች በአሁኑ ጊዜ ተሰናክለዋል።</translation>
 <translation id="544291274896356069">ይህ አገናኝ በውጫዊ መተግበሪያ ከተከፈተ ከማንነት የማያሳውቅ ሁነታ ይወጣል። ይቀጥሉ?</translation>
 <translation id="5447201525962359567">ኩኪዎች እና ሌላ በአከባቢያዊ የተከማቸ ውሂብን ጨምሮ ሁሉም የጣቢያ ማከማቻ</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">ሁሉም ጣቢያዎች</translation>
 <translation id="6320088164292336938">ንዘር</translation>
 <translation id="6324034347079777476">የAndroid ሥርዓት ስምረት ተሰናክሏል</translation>
-<translation id="6324360525379265737">የየቁምፊ ምስጠራን በራስ ሰር እወቅ</translation>
 <translation id="6333140779060797560">በ<ph name="APPLICATION" /> በኩል ያጋሩ</translation>
 <translation id="6337234675334993532">ምስጠራ</translation>
 <translation id="6364438453358674297">ጥቆማው ከታሪክ ይወገድ?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">አጽዳ</translation>
 <translation id="6647073004883890710"><ph name="PASSWORD_MANAGER_BRAND" /> የዚህ ጣቢያ የ<ph name="USERNAME" /> ይለፍ ቃልን እንዲያዘምን ይፈልጋሉ?</translation>
 <translation id="6656545060687952787">Chrome መሣሪያዎችን ለመቃኘት የአካባቢ መዳረሻ ያስፈልገዋል። <ph name="BEGIN_LINK" />ፍቃዶችን ያዘምኑ<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
 <translation id="6659594942844771486">ትር</translation>
 <translation id="666268767214822976">በአድራሻ አሞሌው ላይ እየተየቡ ሳለ ተዛማጅ መጠይቆችን ለማሳየት እና ታዋቂ ድር ጣቢያዎችን ለማሳየት የመገመቻ አገልግሎት ይጠቀሙ</translation>
 <translation id="666981079809192359">የChrome ግላዊነት ማስታወቂያ</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">ወደዚህ ጣቢያ ያልዎት ግንኙነት የግልዎ ብቻ ነው፣ ነገር ግን አንድ በአውታረ መረቡ ላይ ያለው ሰው የገጹን መልክ ሊለውጥ ይችላል።</translation>
 <translation id="8493948351860045254">ቦታ አስለቅቅ</translation>
 <translation id="8497726226069778601">እዚህ ምንም የሚታይ ነገር የለም... ገና</translation>
+<translation id="8503813439785031346">የተጣቃሚ ስም</translation>
 <translation id="8514577642972634246">ማንነት ወደ ማያሳውቅ ሁነታ ይግቡ</translation>
 <translation id="8518901949365209398">ይህ ጣቢያ ደካማ የደህንነት ውቅረት (SHA-1 ፊርማዎች) እየተጠቀም ነው፣ ስለዚህ የእርስዎ ግንኙነት የግል ላይሆን ይችላል።</translation>
 <translation id="8525306231823319788">ሙሉ ማያ ገጽ</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
index bb4a505..5c778ae 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">الإشارات المرجعية وسجل بحث الويب</translation>
 <translation id="1549000191223877751">الانتقال إلى نافذة أخرى</translation>
 <translation id="1553358976309200471">‏تحديث Chrome‏</translation>
-<translation id="1557201757634521564">الاكتشاف التلقائي للتشفير</translation>
 <translation id="1612196535745283361">‏يحتاج Chrome للوصول إلى الموقع للبحث عن الأجهزة. الوصول إلى الموقع <ph name="BEGIN_LINK" />معطل لهذا الجهاز<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">الكاميرا</translation>
 <translation id="1623104350909869708">منع هذه الصفحة من إنشاء مربعات حوار إضافية.</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">عبارات المرور غير متطابقة</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />الحصول على مساعدة<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">حفظ الفيديو</translation>
-<translation id="307329814453917357">‏عرض ترجمة الصفحات باستخدام ترجمة Google.</translation>
 <translation id="3089395242580810162">فتح في علامة تبويب تصفح متخفي</translation>
 <translation id="3090193911106258841">جارٍ الوصول إلى إدخال الصوت والفيديو</translation>
 <translation id="3117051980354074377">‏للحصول على الإشارات من أجهزتك الأخرى، سجّل الدخول إلى Chrome.</translation>
@@ -338,6 +336,7 @@
 <translation id="4988526792673242964">صفحات</translation>
 <translation id="4996978546172906250">مشاركة عن طريق</translation>
 <translation id="5000922062037820727">محظور (موصى به)</translation>
+<translation id="5005498671520578047">نسخ كلمة المرور</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">سماح</translation>
 <translation id="5040262127954254034">الخصوصية</translation>
@@ -366,9 +365,9 @@
 <translation id="528192093759286357">اسحب من الجزء العلوي والمس زر الرجوع للخروج من وضع ملء الشاشة.</translation>
 <translation id="5284584623296338184">‏لن تتم مزامنة التغييرات الطارئة على الإشارات المرجعية والسجل وكلمات المرور وغيرها من الإعدادات بحسابك في Google. ومع ذلك، ستظل بياناتك الحالية مخزنة في حسابك في Google.</translation>
 <translation id="5301954838959518834">موافق وأعي ذلك</translation>
-<translation id="5302048478445481009">اللغة</translation>
 <translation id="5304593522240415983">لا يمكن ترك هذا الحقل فارغًا</translation>
 <translation id="5308380583665731573">اتصال</translation>
+<translation id="5308603654685598744">‏عند تشغيل هذه الميزة، سيعرض Chrome ترجمة الصفحات المكتوبة بلغات أخرى باستخدام الترجمة من Google.</translation>
 <translation id="5313967007315987356">إضافة موقع ويب</translation>
 <translation id="5317780077021120954">حفظ</translation>
 <translation id="5324858694974489420">الإعدادات الأبوية</translation>
@@ -381,7 +380,6 @@
 <translation id="5400569084694353794">باستخدام هذا التطبيق، فإنك توافق على <ph name="BEGIN_LINK1" />شروط الخدمة<ph name="END_LINK1" /> و<ph name="BEGIN_LINK2" />إشعار الخصوصية<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">جارٍ التحقق...</translation>
 <translation id="5423934151118863508">ستظهر صفحاتك الأكثر زيارة هنا</translation>
-<translation id="5424715742813396254">تعديل الاسم/كلمة المرور المحفوظة أو الاستثناء</translation>
 <translation id="5437003064129843501">اقتراحات المحتوى المخصص معطلة حاليًا، لأن بياناتك المتزامنة محمية بعبارة مرور مخصصة.</translation>
 <translation id="544291274896356069">ستتم مغادرة وضع التصفح المتخفي إذا تم فتح هذا الرابط في تطبيق خارجي. هل تريد المتابعة؟</translation>
 <translation id="5447201525962359567">سعة التخزين في الموقع كاملة، بما في ذلك ملفات تعريف الارتباط وغيرها من البيانات المُخزَّنَة محليًا</translation>
@@ -461,7 +459,6 @@
 <translation id="6295158916970320988">جميع المواقع</translation>
 <translation id="6320088164292336938">اهتزاز</translation>
 <translation id="6324034347079777476">‏تمّ تعطيل مزامنة نظام Android</translation>
-<translation id="6324360525379265737">يحدد تلقائيا ترميز الأحرف</translation>
 <translation id="6333140779060797560">مشاركة عن طريق <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">تشفير</translation>
 <translation id="6364438453358674297">هل تريد إزالة اقتراح من السجل؟</translation>
@@ -494,6 +491,7 @@
 <translation id="6643016212128521049">محو</translation>
 <translation id="6647073004883890710">هل تريد من <ph name="PASSWORD_MANAGER_BRAND" /> تحديث كلمة المرور لـ <ph name="USERNAME" /> لهذا الموقع؟</translation>
 <translation id="6656545060687952787">‏يحتاج Chrome للوصول إلى المواقع للبحث عن الأجهزة. <ph name="BEGIN_LINK" />تحديث الأذونات<ph name="END_LINK" />.</translation>
+<translation id="6657585470893396449">كلمة المرور</translation>
 <translation id="6659594942844771486">علامة تبويب</translation>
 <translation id="666268767214822976">يمكنك استخدام خدمة التوقعات لعرض طلبات البحث ذات الصلة ومواقع الويب الشائعة أثناء الكتابة في شريط العناوين</translation>
 <translation id="666981079809192359">‏إشعار خصوصية Chrome</translation>
@@ -655,6 +653,7 @@
 <translation id="8481940801237642152">إن اتصالك بهذا الموقع له خصوصية، لكن قد يتمكن أحد الأشخاص على هذه الشبكة من تغيير مظهر الصفحة.</translation>
 <translation id="8493948351860045254">تفريغ بعض المساحة</translation>
 <translation id="8497726226069778601">لا يوجد شيء هنا... حتى الآن</translation>
+<translation id="8503813439785031346">اسم المستخدم</translation>
 <translation id="8514577642972634246">الدخول إلى وضع التصفح المتخفي</translation>
 <translation id="8518901949365209398">‏يستخدم هذا الموقع تهيئة أمان ضعيفة (توقيعات SHA-1)، لذا قد لا يتم اتصالك بشكل خاص.</translation>
 <translation id="8525306231823319788">ملء الشاشة</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb b/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb
index 216d7df..e38bd576 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Отметки и посетени сайтове</translation>
 <translation id="1549000191223877751">Преместв. в другия прозорец</translation>
 <translation id="1553358976309200471">Актуализиране на Chrome</translation>
-<translation id="1557201757634521564">Автоматично откриване на кодирането</translation>
 <translation id="1612196535745283361">Chrome се нуждае от достъп до местоположението, за да сканира за устройства, но съответните услуги са <ph name="BEGIN_LINK" />изключени за това устройство<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Камера</translation>
 <translation id="1623104350909869708">Да не се създават допълнителни диалогови прозорци от тази страница</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Пропуските не са идентични</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Получете помощ<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Запазване на видеоклипа</translation>
-<translation id="307329814453917357">Извеждане на предложения за превод на страниците посредством Google Преводач</translation>
 <translation id="3089395242580810162">Отваряне в раздел „инкогнито“</translation>
 <translation id="3090193911106258841">Осъществява се достъп до аудио- и видеовхода</translation>
 <translation id="3117051980354074377">Влезте в Chrome, за да получите отметките си от другите си устройства.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Страници</translation>
 <translation id="4996978546172906250">Споделяне чрез</translation>
 <translation id="5000922062037820727">Блокирано (препоръчително)</translation>
+<translation id="5005498671520578047">Копиране на паролата</translation>
 <translation id="5016205925109358554">Серифен</translation>
 <translation id="5039804452771397117">Разрешаване</translation>
 <translation id="5040262127954254034">Поверителност</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Плъзнете пръст от горната част на екрана и докоснете бутона за връщане назад, за да излезете от режима на цял екран.</translation>
 <translation id="5284584623296338184">Промените в отметките, историята, паролите и другите ви настройки вече няма да се синхронизират с профила ви в Google. Съществуващите ви данни обаче ще продължат да се съхраняват в него.</translation>
 <translation id="5301954838959518834">Добре, разбрах</translation>
-<translation id="5302048478445481009">Език</translation>
 <translation id="5304593522240415983">Това поле трябва да се попълни</translation>
 <translation id="5308380583665731573">Свързване</translation>
+<translation id="5308603654685598744">Когато тази функция е включена, Chrome ще предложи да преведе посредством Google Преводач страниците, написани на други езици.</translation>
 <translation id="5313967007315987356">Добавяне на сайт</translation>
 <translation id="5317780077021120954">Запазване</translation>
 <translation id="5324858694974489420">Родителски настройки</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">С използването на това приложение приемате <ph name="BEGIN_LINK1" />Общите условия<ph name="END_LINK1" /> и <ph name="BEGIN_LINK2" />Съобщението за поверителност<ph name="END_LINK2" /> на Chrome.</translation>
 <translation id="5414836363063783498">Потвърждава се…</translation>
 <translation id="5423934151118863508">Най-посещаваните от вас страници ще се показват тук</translation>
-<translation id="5424715742813396254">Редактиране на запазено име/парола или изключение</translation>
 <translation id="5437003064129843501">Понастоящем персонализираните предложения за съдържание са деактивирани, защото синхронизираните ви данни са защитени с персонализиран пропуск.</translation>
 <translation id="544291274896356069">Ще напуснете режим „инкогнито“, ако тази връзка се отвори във външно приложение. Искате ли да продължите?</translation>
 <translation id="5447201525962359567">Всички данни от сайтове, включително „бисквитки“ и друга локално съхранявана информация</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Всички сайтове</translation>
 <translation id="6320088164292336938">Вибриране</translation>
 <translation id="6324034347079777476">Системното синхронизиране под Android е деактивирано</translation>
-<translation id="6324360525379265737">Автоматично определяне на кодирането на знаците</translation>
 <translation id="6333140779060797560">Споделяне чрез <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Шифроване</translation>
 <translation id="6364438453358674297">Предложението да се премахне ли от историята?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Изчистване</translation>
 <translation id="6647073004883890710">Искате ли <ph name="PASSWORD_MANAGER_BRAND" /> да актуализира паролата за <ph name="USERNAME" /> за този сайт?</translation>
 <translation id="6656545060687952787">Chrome се нуждае от достъп до местоположението, за да сканира за устройства. <ph name="BEGIN_LINK" />Актуализиране на разрешенията<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Парола</translation>
 <translation id="6659594942844771486">Раздел</translation>
 <translation id="666268767214822976">Използване на услуга за предвиждания за показване на сродни заявки и популярни уебсайтове, докато пишете в адресната лента</translation>
 <translation id="666981079809192359">Съобщение за поверителност на Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Връзката ви с този сайт е частна, но някой в мрежата може да промени облика на страницата.</translation>
 <translation id="8493948351860045254">Освобождаване на място</translation>
 <translation id="8497726226069778601">Тук няма нищо… засега</translation>
+<translation id="8503813439785031346">Потребителско име</translation>
 <translation id="8514577642972634246">Влизане в режим „инкогнито“</translation>
 <translation id="8518901949365209398">Този сайт използва слаба защитна конфигурация (подписи, шифровани чрез SHA-1), поради което връзката ви може да не е частна.</translation>
 <translation id="8525306231823319788">На цял екран</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb
index 71b2913..54d54ea 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Adreces interès i historial web</translation>
 <translation id="1549000191223877751">Mou a l'altra finestra</translation>
 <translation id="1553358976309200471">Actualitza Chrome</translation>
-<translation id="1557201757634521564">Detecta automàticament la codificació</translation>
 <translation id="1612196535745283361">Chrome necessita tenir accés a la ubicació per poder cercar dispositius, però aquesta funció està <ph name="BEGIN_LINK" />desactivada en aquest dispositiu<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Càmera</translation>
 <translation id="1623104350909869708">Impedeix que aquesta pàgina creï diàlegs addicionals.</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Les frases de contrasenya no coincideixen</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Obteniu ajuda<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Desa el vídeo</translation>
-<translation id="307329814453917357">Proposa'm de traduir les pàgines amb el Traductor de Google</translation>
 <translation id="3089395242580810162">Obre en una pestanya d'incògnit</translation>
 <translation id="3090193911106258841">S'està accedint a l'entrada d'àudio i de vídeo</translation>
 <translation id="3117051980354074377">Inicieu la sessió a Chrome per accedir a les adreces d'interès des dels altres dispositius que tingueu.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Pàgines</translation>
 <translation id="4996978546172906250">Compartir mitjançant</translation>
 <translation id="5000922062037820727">Bloquejat (recomanat)</translation>
+<translation id="5005498671520578047">Copia la contrasenya</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Permet</translation>
 <translation id="5040262127954254034">Privadesa</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Arrossegueu la pantalla des de la part superior i toqueu el botó Enrere per sortir de la pantalla completa.</translation>
 <translation id="5284584623296338184">Els canvis fets a les adreces d'interès, l'historial, les contrasenyes i altres opcions de configuració es deixaran de sincronitzar amb el vostre compte de Google. No obstant això, les dades actuals hi continuaran emmagatzemades.</translation>
 <translation id="5301954838959518834">D'acord, entesos</translation>
-<translation id="5302048478445481009">Idioma</translation>
 <translation id="5304593522240415983">Aquest camp no pot estar en blanc</translation>
 <translation id="5308380583665731573">Connecta</translation>
+<translation id="5308603654685598744">Quan aquesta funció està activada, Chrome ofereix la possibilitat de traduir pàgines escrites en altres idiomes mitjançant el Traductor de Google.</translation>
 <translation id="5313967007315987356">Afegeix un lloc</translation>
 <translation id="5317780077021120954">Desa</translation>
 <translation id="5324858694974489420">Configuració parental</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">En fer servir aquesta aplicació, accepteu les <ph name="BEGIN_LINK1" />Condicions del servei<ph name="END_LINK1" /> i l'<ph name="BEGIN_LINK2" />Avís de privadesa<ph name="END_LINK2" /> de Chrome.</translation>
 <translation id="5414836363063783498">S'està verificant...</translation>
 <translation id="5423934151118863508">Les pàgines més visitades es mostraran aquí</translation>
-<translation id="5424715742813396254">Editar el nom, la contrasenya o l'excepció desats</translation>
 <translation id="5437003064129843501">Actualment, els suggeriments de contingut personalitzats estan desactivats perquè les teves dades sincronitzades estan protegides per una frase de contrasenya personalitzada.</translation>
 <translation id="544291274896356069">Si obriu aquest enllaç en una aplicació externa abandonareu el mode d'incògnit. Voleu continuar?</translation>
 <translation id="5447201525962359567">Tot l'emmagatzematge del lloc, com ara les galetes i altres dades emmagatzemades localment</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Tots els llocs</translation>
 <translation id="6320088164292336938">Vibració</translation>
 <translation id="6324034347079777476">La sincronització del sistema Android està desactivada</translation>
-<translation id="6324360525379265737">Detecta automàticament la codificació de caràcters</translation>
 <translation id="6333140779060797560">Comparteix mitjançant <ph name="APPLICATION" />.</translation>
 <translation id="6337234675334993532">Encriptació</translation>
 <translation id="6364438453358674297">Voleu suprimir el suggeriment de l'historial?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Esborra</translation>
 <translation id="6647073004883890710">Voleu que <ph name="PASSWORD_MANAGER_BRAND" /> actualitzi la contrasenya de l'usuari <ph name="USERNAME" /> per a aquest lloc?</translation>
 <translation id="6656545060687952787">Chrome necessita tenir accés a la ubicació per poder cercar dispositius. <ph name="BEGIN_LINK" />Actualitza els permisos<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Contrasenya</translation>
 <translation id="6659594942844771486">Pestanya</translation>
 <translation id="666268767214822976">Utilitza un servei de predicció per mostrar consultes relacionades i llocs web populars mentre escriviu a la barra d'adreces</translation>
 <translation id="666981079809192359">Avís de privadesa de Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">La vostra connexió amb aquest lloc és privada, però és possible que algun usuari de la xarxa pugui canviar l'aspecte de la pàgina.</translation>
 <translation id="8493948351860045254">Allibera espai</translation>
 <translation id="8497726226069778601">Aquí encara no hi ha contingut per mostrar</translation>
+<translation id="8503813439785031346">Nom d'usuari</translation>
 <translation id="8514577642972634246">Entra al mode d'incògnit</translation>
 <translation id="8518901949365209398">Aquest lloc fa servir una configuració de seguretat dèbil (signatures SHA-1), de manera que és possible que la vostra connexió no sigui privada.</translation>
 <translation id="8525306231823319788">Pantalla completa</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb b/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb
index 405704d..9c5e5465 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Záložky a webová historie</translation>
 <translation id="1549000191223877751">Přejít do jiného okna</translation>
 <translation id="1553358976309200471">Aktualizovat Chrome</translation>
-<translation id="1557201757634521564">Automaticky rozpoznávat kódování</translation>
 <translation id="1612196535745283361">K vyhledání zařízení potřebuje Chrome přístup k informacím o poloze. Přístup k poloze je v tomto zařízení <ph name="BEGIN_LINK" />vypnut<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Bránit této stránce ve vytváření dalších dialogových oken</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Heslové fráze se neshodují</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Zobrazit nápovědu<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Uložit video</translation>
-<translation id="307329814453917357">Nabízet překlad stránek pomocí Překladače Google</translation>
 <translation id="3089395242580810162">Otevřít na anonymní kartě</translation>
 <translation id="3090193911106258841">Přístup ke vstupu zvuku a videa</translation>
 <translation id="3117051980354074377">Chcete-li získat přístup k záložkám ze svých ostatních zařízení, přihlaste se do Chromu.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Stránky</translation>
 <translation id="4996978546172906250">Sdílet prostřednictvím</translation>
 <translation id="5000922062037820727">Blokováno (doporučeno)</translation>
+<translation id="5005498671520578047">Kopírování hesla</translation>
 <translation id="5016205925109358554">Patková</translation>
 <translation id="5039804452771397117">Povolit</translation>
 <translation id="5040262127954254034">Ochrana soukromí</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Režim celé obrazovky ukončíte přetažením z horního okraje obrazovky a klepnutím na tlačítko Zpět.</translation>
 <translation id="5284584623296338184">Změny záložek, historie, hesel a dalších nastavení se již nebudou synchronizovat do vašeho účtu Google. Vaše existující data však v účtu Google uložena zůstanou.</translation>
 <translation id="5301954838959518834">Ano, chápu</translation>
-<translation id="5302048478445481009">Jazyk</translation>
 <translation id="5304593522240415983">Toto pole nesmí být prázdné</translation>
 <translation id="5308380583665731573">Připojení</translation>
+<translation id="5308603654685598744">Pokud je tato funkce zapnutá, bude Chrome nabízet překlad stránek v jiných jazycích pomocí Překladače Google.</translation>
 <translation id="5313967007315987356">Přidat web</translation>
 <translation id="5317780077021120954">Uložit</translation>
 <translation id="5324858694974489420">Rodičovská nastavení</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Používáním této aplikace vyjadřujete souhlas se <ph name="BEGIN_LINK1" />smluvními podmínkami<ph name="END_LINK1" /> a <ph name="BEGIN_LINK2" />zásadami ochrany soukromí<ph name="END_LINK2" /> prohlížeče Chrome.</translation>
 <translation id="5414836363063783498">Ověřování…</translation>
 <translation id="5423934151118863508">Zde se zobrazí vaše nejnavštěvovanější stránky.</translation>
-<translation id="5424715742813396254">Úprava uloženého jména a hesla nebo výjimky</translation>
 <translation id="5437003064129843501">Personalizované návrhy obsahu jsou aktuálně vypnuty, protože jsou vaše synchronizovaná data chráněna vlastní heslovou frází.</translation>
 <translation id="544291274896356069">Pokud tento odkaz otevřete v externí aplikaci, opustíte anonymní režim. Chcete pokračovat?</translation>
 <translation id="5447201525962359567">Veškerá data webů, včetně souborů cookie a dalších místně uložených dat</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Všechny weby</translation>
 <translation id="6320088164292336938">Vibrovat</translation>
 <translation id="6324034347079777476">Synchronizace systému Android je vypnuta.</translation>
-<translation id="6324360525379265737">Automaticky určovat kódování znaků</translation>
 <translation id="6333140779060797560">Sdílet prostřednictvím aplikace <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Šifrování</translation>
 <translation id="6364438453358674297">Odstranit návrh z historie?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Vymazat</translation>
 <translation id="6647073004883890710">Chcete, aby aplikace <ph name="PASSWORD_MANAGER_BRAND" /> aktualizovala heslo uživatele <ph name="USERNAME" /> pro tento web?</translation>
 <translation id="6656545060687952787">K vyhledání zařízení Chrome potřebuje přístup k informacím o poloze. <ph name="BEGIN_LINK" />Aktualizovat oprávnění<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Heslo</translation>
 <translation id="6659594942844771486">Karta</translation>
 <translation id="666268767214822976">Používat službu předpovídání k zobrazení souvisejících dotazů a oblíbených webových stránek.</translation>
 <translation id="666981079809192359">Ochrana soukromí v Chromu</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Spojení s tímto webem je soukromé, avšak některý uživatel v síti může být schopen změnit vzhled stránky.</translation>
 <translation id="8493948351860045254">Uvolnit místo</translation>
 <translation id="8497726226069778601">Zatím tu nic není...</translation>
+<translation id="8503813439785031346">Uživatelské jméno</translation>
 <translation id="8514577642972634246">Přejít do anonymního režimu</translation>
 <translation id="8518901949365209398">Tento web používá slabou konfiguraci zabezpečení (podpisy SHA-1). Připojení proto nemusí být soukromé.</translation>
 <translation id="8525306231823319788">Celá obrazovka</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_da.xtb b/chrome/android/java/strings/translations/android_chrome_strings_da.xtb
index e93a3a2..0cbf5aa 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_da.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_da.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bogmærker og webhistorik</translation>
 <translation id="1549000191223877751">Flyt til et andet vindue</translation>
 <translation id="1553358976309200471">Opdater Chrome</translation>
-<translation id="1557201757634521564">Registrer kodning automatisk</translation>
 <translation id="1612196535745283361">Chrome skal have placeringsadgang for at kunne scanne efter enheder. Placeringsadgang er <ph name="BEGIN_LINK" />slået fra på denne enhed<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Undgå, at denne side opretter yderligere dialogbokse</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Adgangssætningerne stemmer ikke overens</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Få hjælp<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Gem video</translation>
-<translation id="307329814453917357">Tilbyd at oversætte sider ved hjælp af Google Oversæt</translation>
 <translation id="3089395242580810162">Åbn i inkognitofane</translation>
 <translation id="3090193911106258841">Åbner lyd- og videoinput</translation>
 <translation id="3117051980354074377">Log ind på Chrome for at se dine bogmærker på dine andre enheder.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Sider</translation>
 <translation id="4996978546172906250">Del via</translation>
 <translation id="5000922062037820727">Blokeret (anbefales)</translation>
+<translation id="5005498671520578047">Kopiér adgangskode</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Tillad</translation>
 <translation id="5040262127954254034">Beskyttelse af personlige oplysninger</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Træk fra toppen, og tryk på tilbageknappen igen for at afslutte fuld skærm.</translation>
 <translation id="5284584623296338184">Ændringer i dine bogmærker, din historik, dine adgangskoder og andre indstillinger synkroniseres ikke længere til din Google-konto, men dine eksisterende data er stadig gemt på din Google-konto.</translation>
 <translation id="5301954838959518834">OK, det er forstået</translation>
-<translation id="5302048478445481009">Sprog</translation>
 <translation id="5304593522240415983">Dette felt må ikke være tomt</translation>
 <translation id="5308380583665731573">Få forbindelse</translation>
+<translation id="5308603654685598744">Når denne funktion er slået til, vil Chrome tilbyde at oversætte sider, som er skrevet på andre sprog, ved hjælp af Google Oversæt.</translation>
 <translation id="5313967007315987356">Tilføj website</translation>
 <translation id="5317780077021120954">Gem</translation>
 <translation id="5324858694974489420">Indstillinger for forældrekontrol</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Ved at bruge denne applikation accepterer du Chromes <ph name="BEGIN_LINK1" />servicevilkår<ph name="END_LINK1" /> og <ph name="BEGIN_LINK2" />erklæring om privatliv<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Bekræfter...</translation>
 <translation id="5423934151118863508">Dine mest besøgte sider vises her</translation>
-<translation id="5424715742813396254">Rediger gemt navn/adgangskode eller undtagelse</translation>
 <translation id="5437003064129843501">Du modtager i øjeblikket ikke forslag til brugertilpasset indhold, da dine synkroniserede data beskyttes med en brugerdefineret adgangssætning.</translation>
 <translation id="544291274896356069">Du forlader inkognitotilstand, hvis dette link åbnes i en ekstern applikation. Vil du fortsætte?</translation>
 <translation id="5447201525962359567">Al websitelagerplads, herunder cookies og andre data, der er gemt lokalt</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Alle websites</translation>
 <translation id="6320088164292336938">Vibrer</translation>
 <translation id="6324034347079777476">Synkronisering af Android-systemet blev deaktiveret</translation>
-<translation id="6324360525379265737">Registrer tegnkodning automatisk</translation>
 <translation id="6333140779060797560">Del via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Kryptering</translation>
 <translation id="6364438453358674297">Vil du fjerne forslaget fra historikken?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Ryd</translation>
 <translation id="6647073004883890710">Skal <ph name="PASSWORD_MANAGER_BRAND" /> opdatere adgangskoden for <ph name="USERNAME" /> for dette website?</translation>
 <translation id="6656545060687952787">Chrome skal bruge placeringsadgang for at kunne scanne efter enheder. <ph name="BEGIN_LINK" />Opdater tilladelser<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Adgangskode</translation>
 <translation id="6659594942844771486">Fane</translation>
 <translation id="666268767214822976">Brug en forslagstjeneste til at få vist relaterede forespørgsler og populære websites, mens du skriver i adresselinjen</translation>
 <translation id="666981079809192359">Erklæring om privatliv for Google Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Din forbindelse til dette website er privat, men andre på netværket vil muligvis kunne ændre sidens udseende.</translation>
 <translation id="8493948351860045254">Frigør plads</translation>
 <translation id="8497726226069778601">Her er ikke noget at se… endnu</translation>
+<translation id="8503813439785031346">Brugernavn</translation>
 <translation id="8514577642972634246">Slå inkognitotilstand til</translation>
 <translation id="8518901949365209398">Dette website benytter en svag sikkerhedskonfiguration (SHA-1-signaturer), så din forbindelse er muligvis ikke privat.</translation>
 <translation id="8525306231823319788">Fuld skærm</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
index ca00931..44fea68 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Lesezeichen und Webprotokoll</translation>
 <translation id="1549000191223877751">Zu anderem Fenster wechseln</translation>
 <translation id="1553358976309200471">Chrome aktualisieren</translation>
-<translation id="1557201757634521564">Codierung automatisch erkennen</translation>
 <translation id="1612196535745283361">Chrome benötigt Zugriff auf den Standort, um nach Geräten suchen zu können. Der Standortzugriff ist <ph name="BEGIN_LINK" />für dieses Gerät deaktiviert<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Keine weiteren Dialogfelder auf dieser Seite zulassen</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Passphrasen stimmen nicht überein.</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Hilfe aufrufen<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Video speichern</translation>
-<translation id="307329814453917357">Übersetzung der Seiten mithilfe von Google Übersetzer anbieten</translation>
 <translation id="3089395242580810162">In Inkognito-Tab öffnen</translation>
 <translation id="3090193911106258841">Zugriff auf Audio- und Video-Eingang</translation>
 <translation id="3117051980354074377">Melden Sie sich in Chrome an, um Lesezeichen von Ihren anderen Geräten abzurufen.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Seiten</translation>
 <translation id="4996978546172906250">Teilen über</translation>
 <translation id="5000922062037820727">Blockiert (empfohlen)</translation>
+<translation id="5005498671520578047">Passwort kopieren</translation>
 <translation id="5016205925109358554">Serifenschrift</translation>
 <translation id="5039804452771397117">Zulassen</translation>
 <translation id="5040262127954254034">Datenschutz</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Ziehen Sie zum Beenden des Vollbildmodus von oben und tippen Sie auf die Zurück-Taste.</translation>
 <translation id="5284584623296338184">Änderungen an Ihren Lesezeichen, Ihrem Verlauf, Ihren Passwörtern und anderen Einstellungen werden nicht mehr mit Ihrem Google-Konto synchronisiert. Ihre vorhandenen Daten bleiben aber in Ihrem Google-Konto gespeichert.</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">Sprache</translation>
 <translation id="5304593522240415983">Dieses Feld darf nicht leer sein.</translation>
 <translation id="5308380583665731573">Verbinden</translation>
+<translation id="5308603654685598744">Wenn diese Funktion aktiviert ist, bietet Chrome eine Übersetzung von Seiten in anderen Sprachen durch Google Übersetzer an.</translation>
 <translation id="5313967007315987356">Website hinzufügen</translation>
 <translation id="5317780077021120954">Speichern</translation>
 <translation id="5324858694974489420">Jugendschutzeinstellungen</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Durch die Verwendung dieser App stimmen Sie den <ph name="BEGIN_LINK1" />Nutzungsbedingungen<ph name="END_LINK1" /> und <ph name="BEGIN_LINK2" />Datenschutzhinweisen<ph name="END_LINK2" /> von Chrome zu.</translation>
 <translation id="5414836363063783498">Überprüfung...</translation>
 <translation id="5423934151118863508">Hier werden Ihre am meisten aufgerufenen Seiten angezeigt.</translation>
-<translation id="5424715742813396254">Gespeicherten Eintrag oder Ausnahme bearbeiten</translation>
 <translation id="5437003064129843501">Die personalisierten Inhaltsvorschläge sind momentan deaktiviert, weil Ihre synchronisierten Daten durch eine benutzerdefinierte Passphrase geschützt werden.</translation>
 <translation id="544291274896356069">Der Inkognitomodus wird beendet, wenn dieser Link in einer externen App geöffnet wird. Vorgang fortsetzen?</translation>
 <translation id="5447201525962359567">Gesamter Websitespeicher einschließlich Cookies und anderer lokal gespeicherter Daten</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Alle Websites</translation>
 <translation id="6320088164292336938">Vibrieren</translation>
 <translation id="6324034347079777476">Android-Systemsynchronisierung deaktiviert</translation>
-<translation id="6324360525379265737">Zeichencodierung automatisch ermitteln</translation>
 <translation id="6333140779060797560">Über <ph name="APPLICATION" /> teilen</translation>
 <translation id="6337234675334993532">Verschlüsselung</translation>
 <translation id="6364438453358674297">Vorschlag aus Verlauf entfernen?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Löschen</translation>
 <translation id="6647073004883890710">Soll <ph name="PASSWORD_MANAGER_BRAND" /> das Passwort für <ph name="USERNAME" /> für diese Website aktualisieren?</translation>
 <translation id="6656545060687952787">Chrome benötigt Zugriff auf den Standort, um nach Geräten suchen zu können. <ph name="BEGIN_LINK" />Berechtigungen aktualisieren<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Passwort</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Während der Eingabe in die Adressleiste mithilfe einer Vervollständigungsfunktion verwandte Suchanfragen und beliebte Websites einblenden</translation>
 <translation id="666981079809192359">Chrome-Datenschutzhinweise</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Ihre Verbindung zu dieser Website ist privat, möglicherweise ist jedoch jemand im Netzwerk in der Lage, das Aussehen der Seite zu ändern.</translation>
 <translation id="8493948351860045254">Speicherplatz freigeben</translation>
 <translation id="8497726226069778601">Noch keine Seiten</translation>
+<translation id="8503813439785031346">Nutzername</translation>
 <translation id="8514577642972634246">Inkognitomodus aktivieren</translation>
 <translation id="8518901949365209398">Diese Website verwendet eine schwache Sicherheitskonfiguration (SHA-1-Signaturen). Daher ist Ihre Verbindung möglicherweise nicht geschützt.</translation>
 <translation id="8525306231823319788">Vollbildmodus</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_el.xtb b/chrome/android/java/strings/translations/android_chrome_strings_el.xtb
index 09c09025..e013cc5 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_el.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_el.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Σελιδοδείκτες και ιστορικό ιστού</translation>
 <translation id="1549000191223877751">Μεταβείτε σε άλλο παράθυρο</translation>
 <translation id="1553358976309200471">Ενημερώστε το Chrome</translation>
-<translation id="1557201757634521564">Αυτόματος εντοπισμός κωδικοποίησης</translation>
 <translation id="1612196535745283361">Το Chrome χρειάζεται πρόσβαση στην τοποθεσία, προκειμένου να κάνει σάρωση για συσκευές. Η πρόσβαση τοποθεσίας είναι <ph name="BEGIN_LINK" />απενεργοποιημένη για αυτήν τη συσκευή<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Κάμερα</translation>
 <translation id="1623104350909869708">Αποτροπή δημιουργίας πρόσθετων παραθύρων διαλόγου από αυτήν τη σελίδα</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Οι φράσεις πρόσβασης δεν συμφωνούν</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Λάβετε βοήθεια<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Αποθήκευση βίντεο</translation>
-<translation id="307329814453917357">Πρόταση μετάφρασης σελίδων χρησιμοποιώντας τη Μετάφραση Google</translation>
 <translation id="3089395242580810162">Άνοιγμα σε καρτέλα ανώνυμης περιήγησης</translation>
 <translation id="3090193911106258841">Πρόσβαση στην είσοδο ήχου και βίντεο</translation>
 <translation id="3117051980354074377">Για να εμφανίζονται οι σελιδοδείκτες από τις άλλες συσκευές σας, συνδεθείτε στο Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Σελίδες</translation>
 <translation id="4996978546172906250">Κοινή χρήση μέσω</translation>
 <translation id="5000922062037820727">Αποκλείεται (συνιστάται)</translation>
+<translation id="5005498671520578047">Αντιγραφή κωδικού πρόσβασης</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Επιτρέπεται</translation>
 <translation id="5040262127954254034">Απόρρητο</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Σύρετε από το επάνω τμήμα και αγγίξτε το κουμπί επιστροφής για έξοδο από την πλήρη οθόνη.</translation>
 <translation id="5284584623296338184">Οι αλλαγές σε σελιδοδείκτες, ιστορικό, κωδικούς πρόσβασης και άλλες ρυθμίσεις δεν θα συγχρονίζονται πλέον με το Λογαριασμό σας Google. Ωστόσο, τα υπάρχοντα δεδομένα σας θα παραμείνουν αποθηκευμένα στο λογαριασμό σας Google.</translation>
 <translation id="5301954838959518834">Εντάξει, το κατάλαβα</translation>
-<translation id="5302048478445481009">Γλώσσα</translation>
 <translation id="5304593522240415983">Αυτό το πεδίο δεν μπορεί να είναι κενό</translation>
 <translation id="5308380583665731573">Σύνδεση</translation>
+<translation id="5308603654685598744">Όταν είναι ενεργοποιημένη αυτή η λειτουργία, το Chrome θα προσφέρεται να μεταφράζει σελίδες σε άλλες γλώσσες χρησιμοποιώντας τη Μετάφραση Google.</translation>
 <translation id="5313967007315987356">Προσθήκη ιστότοπου</translation>
 <translation id="5317780077021120954">Αποθήκευση</translation>
 <translation id="5324858694974489420">Ρυθμίσεις γονικού ελέγχου</translation>
@@ -382,8 +381,6 @@
 <translation id="5400569084694353794">Χρησιμοποιώντας αυτήν την εφαρμογή, αποδέχεστε τους <ph name="BEGIN_LINK1" />Όρους Παροχής Υπηρεσιών<ph name="END_LINK1" /> και τη <ph name="BEGIN_LINK2" />Σημείωση Απορρήτου<ph name="END_LINK2" /> του Chrome.</translation>
 <translation id="5414836363063783498">Γίνεται επαλήθευση…</translation>
 <translation id="5423934151118863508">Οι πιο δημοφιλείς σελίδες σας θα εμφανίζονται εδώ</translation>
-<translation id="5424715742813396254">Επεξεργασία ονόματος/κωδικού πρόσβασης ή εξαίρεσης
-</translation>
 <translation id="5437003064129843501">Οι προτάσεις εξατομικευμένου περιεχομένου είναι επί του παρόντος απενεργοποιημένες, επειδή τα συγχρονισμένα δεδομένα σας προστατεύονται με μια προσαρμοσμένη φράση πρόσβασης.</translation>
 <translation id="544291274896356069">Αποχώρηση από την κατάσταση ανώνυμης περιήγησης εάν αυτός ο σύνδεσμος έχει ανοίξει σε εξωτερική εφαρμογή. Συνέχεια;</translation>
 <translation id="5447201525962359567">Όλος ο αποθηκευτικός χώρος ιστότοπων, συμπεριλαμβανομένων των cookie και άλλων τοπικά αποθηκευμένων δεδομένων</translation>
@@ -463,7 +460,6 @@
 <translation id="6295158916970320988">Όλοι οι ιστότοποι</translation>
 <translation id="6320088164292336938">Δόνηση</translation>
 <translation id="6324034347079777476">Ο συγχρονισμός συστήματος Android απενεργοποιήθηκε</translation>
-<translation id="6324360525379265737">Αυτόματος καθορισμός κωδικοποίησης χαρακτήρων</translation>
 <translation id="6333140779060797560">Κοινή χρήση μέσω <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Κρυπτογράφηση</translation>
 <translation id="6364438453358674297">Κατάργηση πρότασης από το ιστορικό;</translation>
@@ -496,6 +492,7 @@
 <translation id="6643016212128521049">Διαγραφή</translation>
 <translation id="6647073004883890710">Θέλετε το <ph name="PASSWORD_MANAGER_BRAND" /> να ενημερώσει τον κωδικό πρόσβασης για το χρήστη <ph name="USERNAME" /> για αυτόν τον ιστότοπο;</translation>
 <translation id="6656545060687952787">Το Chrome χρειάζεται πρόσβαση στην τοποθεσία, προκειμένου να κάνει σάρωση για συσκευές. <ph name="BEGIN_LINK" />Ενημέρωση δικαιωμάτων<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
 <translation id="6659594942844771486">Καρτέλα</translation>
 <translation id="666268767214822976">Χρήση υπηρεσίας προβλέψεων για την εμφάνιση σχετικών ερωτημάτων και δημοφιλών ιστότοπων, καθώς πληκτρολογείτε στη γραμμή διευθύνσεων</translation>
 <translation id="666981079809192359">Σημείωση Απορρήτου του Chrome</translation>
@@ -657,6 +654,7 @@
 <translation id="8481940801237642152">Η σύνδεσή σας σε αυτόν τον ιστότοπο είναι ιδιωτική, αλλά κάποιος χρήστης του δικτύου ενδέχεται να έχει τη δυνατότητα να αλλάξει την εμφάνιση της σελίδας.</translation>
 <translation id="8493948351860045254">Ελευθερώστε χώρο</translation>
 <translation id="8497726226069778601">Δεν υπάρχει τίποτα να δείτε εδώ…ακόμη</translation>
+<translation id="8503813439785031346">Όνομα χρήστη</translation>
 <translation id="8514577642972634246">Είσοδος στην κατάσταση ανώνυμης περιήγησης</translation>
 <translation id="8518901949365209398">Αυτός ο ιστότοπος δεν χρησιμοποιεί ισχυρή ρύθμιση παραμέτρων ασφαλείας (υπογραφές SHA-1), επομένως η σύνδεσή σας ενδέχεται να μην είναι απόρρητη.</translation>
 <translation id="8525306231823319788">Πλήρης οθόνη</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb b/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb
index 59562e8..91007fe0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bookmarks and web history</translation>
 <translation id="1549000191223877751">Move to other window</translation>
 <translation id="1553358976309200471">Update Chrome</translation>
-<translation id="1557201757634521564">Auto-detect encoding</translation>
 <translation id="1612196535745283361">Chrome needs location access to scan for devices. Location access is <ph name="BEGIN_LINK" />turned off for this device<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Camera</translation>
 <translation id="1623104350909869708">Prevent this page from creating additional dialogues</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Passphrases do not match</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Get help<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Save video</translation>
-<translation id="307329814453917357">Offer to translate pages using Google Translate</translation>
 <translation id="3089395242580810162">Open in incognito tab</translation>
 <translation id="3090193911106258841">Accessing audio and video input</translation>
 <translation id="3117051980354074377">To get your bookmarks your other devices, sign in to Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Pages</translation>
 <translation id="4996978546172906250">Share via</translation>
 <translation id="5000922062037820727">Blocked (recommended)</translation>
+<translation id="5005498671520578047">Copy password</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Allow</translation>
 <translation id="5040262127954254034">Privacy</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Drag from top and touch the back button to exit full screen.</translation>
 <translation id="5284584623296338184">Changes to your bookmarks, history, passwords and other settings will no longer be synced to your Google Account. However, your existing data will remain stored in your Google account.</translation>
 <translation id="5301954838959518834">OK, got it</translation>
-<translation id="5302048478445481009">Language</translation>
 <translation id="5304593522240415983">This field cannot be blank</translation>
 <translation id="5308380583665731573">Connect</translation>
+<translation id="5308603654685598744">When this feature is turned on, Chrome will offer to translate pages written in other languages using Google Translate.</translation>
 <translation id="5313967007315987356">Add site</translation>
 <translation id="5317780077021120954">Save</translation>
 <translation id="5324858694974489420">Parental Settings</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">By using this application, you agree to Chrome’s <ph name="BEGIN_LINK1" />Terms of Service<ph name="END_LINK1" /> and <ph name="BEGIN_LINK2" />Privacy Notice<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Verifying…</translation>
 <translation id="5423934151118863508">Your most visited pages will appear here</translation>
-<translation id="5424715742813396254">Edit saved name/password or exception</translation>
 <translation id="5437003064129843501">Personalised content suggestions are currently disabled, because your synced data is protected with a customised passphrase.</translation>
 <translation id="544291274896356069">Leaving incognito mode if this link is opened in an external application. Continue?</translation>
 <translation id="5447201525962359567">All site storage, including cookies and other locally stored data</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">All sites</translation>
 <translation id="6320088164292336938">Vibrate</translation>
 <translation id="6324034347079777476">Android system sync disabled</translation>
-<translation id="6324360525379265737">Automatically determine character encoding</translation>
 <translation id="6333140779060797560">Share via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Encryption</translation>
 <translation id="6364438453358674297">Remove suggestion from history?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Clear</translation>
 <translation id="6647073004883890710">Do you want <ph name="PASSWORD_MANAGER_BRAND" /> to update the password for <ph name="USERNAME" /> for this site?</translation>
 <translation id="6656545060687952787">Chrome needs location access to scan for devices. <ph name="BEGIN_LINK" />Update permissions<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Password</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Use a prediction service to show related queries and popular websites as you type in the address bar</translation>
 <translation id="666981079809192359">Chrome Privacy Notice</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Your connection to this site is private, but someone on the network might be able to change the look of the page.</translation>
 <translation id="8493948351860045254">Free up space</translation>
 <translation id="8497726226069778601">Nothing to see here… yet</translation>
+<translation id="8503813439785031346">Username</translation>
 <translation id="8514577642972634246">Enter incognito mode</translation>
 <translation id="8518901949365209398">This site uses a weak security configuration (SHA-1 signatures), so your connection may not be private.</translation>
 <translation id="8525306231823319788">Full screen</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb b/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
index 982ba3ae..a726226 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Marcadores e historial web</translation>
 <translation id="1549000191223877751">Mover a otra ventana</translation>
 <translation id="1553358976309200471">Actualizar Chrome</translation>
-<translation id="1557201757634521564">Autodetectar codificación</translation>
 <translation id="1612196535745283361">Chrome debe acceder a la ubicación para buscar dispositivos. El acceso a la ubicación está <ph name="BEGIN_LINK" />desactivado en este dispositivo<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Cámara</translation>
 <translation id="1623104350909869708">Evitar que esta página cree cuadros de diálogo adicionales</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Las frases de contraseña no coinciden.</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Obtener ayuda<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Guardar video</translation>
-<translation id="307329814453917357">Ofrecer la traducción de páginas con Google Traductor</translation>
 <translation id="3089395242580810162">Abrir en pestaña de incógnito</translation>
 <translation id="3090193911106258841">Accediendo a la entrada de video y de audio</translation>
 <translation id="3117051980354074377">Accede a Chrome para obtener los marcadores de tus otros dispositivos.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Páginas</translation>
 <translation id="4996978546172906250">Compartir mediante</translation>
 <translation id="5000922062037820727">Bloqueado (recomendado)</translation>
+<translation id="5005498671520578047">Copiar contraseña</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Permitir</translation>
 <translation id="5040262127954254034">Privacidad</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Arrastra el dedo desde la parte superior y toca el botón Atrás para salir de la pantalla completa.</translation>
 <translation id="5284584623296338184">Los cambios que hagas en tus marcadores, historial, contraseñas y otras opciones de configuración se seguirán sincronizando con tu cuenta de Google. Sin embargo, tus datos existentes seguirán almacenados en tu cuenta de Google.</translation>
 <translation id="5301954838959518834">Entendido</translation>
-<translation id="5302048478445481009">Idioma</translation>
 <translation id="5304593522240415983">Este campo no puede quedar en blanco.</translation>
 <translation id="5308380583665731573">Conectar</translation>
+<translation id="5308603654685598744">Cuando esta función esté activada, Chrome te ofrecerá traducir páginas escritas en otros idiomas con Google Traductor.</translation>
 <translation id="5313967007315987356">Agregar sitio</translation>
 <translation id="5317780077021120954">Guardar</translation>
 <translation id="5324858694974489420">Configuración parental</translation>
@@ -382,8 +381,6 @@
 <translation id="5400569084694353794">Al utilizar esta aplicación, aceptas las <ph name="BEGIN_LINK1" />Condiciones del servicio<ph name="END_LINK1" /> y el <ph name="BEGIN_LINK2" />Aviso de privacidad<ph name="END_LINK2" /> de Chrome.</translation>
 <translation id="5414836363063783498">Verificando…</translation>
 <translation id="5423934151118863508">Aquí aparecerán las páginas que visites con más frecuencia</translation>
-<translation id="5424715742813396254">Editar nombre, contraseña o excepción guardados
-</translation>
 <translation id="5437003064129843501">Las sugerencias de contenido personalizado están inhabilitadas, porque tus datos sincronizados están protegidos con una frase de contraseña personalizada.</translation>
 <translation id="544291274896356069">Saldrás del modo de navegación de incógnito si este vínculo se abre en una aplicación externa. ¿Quieres continuar?</translation>
 <translation id="5447201525962359567">Todo el almacenamiento de sitios, lo que incluye cookies y otros datos almacenados de forma local</translation>
@@ -463,7 +460,6 @@
 <translation id="6295158916970320988">Todos los sitios</translation>
 <translation id="6320088164292336938">Vibrar</translation>
 <translation id="6324034347079777476">Sincronización del sistema Android inhabilitada</translation>
-<translation id="6324360525379265737">Determinar automáticamente la codificación de caracteres</translation>
 <translation id="6333140779060797560">Compartir mediante <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Encriptación</translation>
 <translation id="6364438453358674297">¿Borrar la sugerencia del historial?</translation>
@@ -496,6 +492,7 @@
 <translation id="6643016212128521049">Borrar</translation>
 <translation id="6647073004883890710">¿Deseas que <ph name="PASSWORD_MANAGER_BRAND" /> actualice la contraseña para <ph name="USERNAME" /> en este sitio?</translation>
 <translation id="6656545060687952787">Chrome necesita acceder a la ubicación para buscar dispositivos. <ph name="BEGIN_LINK" />Actualizar permisos<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Contraseña</translation>
 <translation id="6659594942844771486">Pestaña</translation>
 <translation id="666268767214822976">Usar un servicio de predicción para ver consultas relacionadas y sitios web populares a medida que escribes en la barra de direcciones.</translation>
 <translation id="666981079809192359">Aviso de privacidad de Chrome</translation>
@@ -657,6 +654,7 @@
 <translation id="8481940801237642152">Tu conexión con este sitio es privada, pero alguien en la red podría cambiar el aspecto de la página.</translation>
 <translation id="8493948351860045254">Liberar espacio</translation>
 <translation id="8497726226069778601">Aún no hay elementos para ver</translation>
+<translation id="8503813439785031346">Nombre de usuario</translation>
 <translation id="8514577642972634246">Acceder al modo de navegación de incógnito</translation>
 <translation id="8518901949365209398">Este sitio usa una configuración de seguridad vulnerable (firmas SHA-1). Por lo tanto, es posible que la conexión no sea privada.</translation>
 <translation id="8525306231823319788">Pantalla completa</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_es.xtb b/chrome/android/java/strings/translations/android_chrome_strings_es.xtb
index 41395c0..4dd0cef 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_es.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_es.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Historial web y marcadores</translation>
 <translation id="1549000191223877751">Mover a otra ventana</translation>
 <translation id="1553358976309200471">Actualizar Chrome</translation>
-<translation id="1557201757634521564">Autodetectar codificación</translation>
 <translation id="1612196535745283361">Chrome necesita acceder a la ubicación para buscar dispositivos. El acceso a la ubicación está <ph name="BEGIN_LINK" />desactivado en este dispositivo<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Cámara</translation>
 <translation id="1623104350909869708">Evitar que esta página cree cuadros de diálogo adicionales</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Las frases de contraseña no coinciden</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Obtener ayuda<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Guardar vídeo</translation>
-<translation id="307329814453917357">Ofrece la traducción de páginas con el Traductor de Google</translation>
 <translation id="3089395242580810162">Abrir en modo de incógnito</translation>
 <translation id="3090193911106258841">Accediendo a la entrada de vídeo y audio</translation>
 <translation id="3117051980354074377">Inicia sesión en Chrome para ver los marcadores de tus otros dispositivos.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Páginas</translation>
 <translation id="4996978546172906250">Compartir a través de</translation>
 <translation id="5000922062037820727">Bloqueado (recomendado)</translation>
+<translation id="5005498671520578047">Copiar contraseña</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Permitir</translation>
 <translation id="5040262127954254034">Privacidad</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Arrastra el dedo desde la parte superior y toca el botón de retroceso para salir de la pantalla completa.</translation>
 <translation id="5284584623296338184">Los cambios que realices en los marcadores, el historial, las contraseñas y otras opciones no se sincronizarán con tu cuenta de Google. Sin embargo, tus datos actuales seguirán almacenados en tu cuenta.</translation>
 <translation id="5301954838959518834">Entendido</translation>
-<translation id="5302048478445481009">Idioma</translation>
 <translation id="5304593522240415983">Este campo no puede estar vacío</translation>
 <translation id="5308380583665731573">Conectar</translation>
+<translation id="5308603654685598744">Cuando esta función está activada, Chrome ofrece la posibilidad de traducir páginas escritas en otros idiomas con el Traductor de Google.</translation>
 <translation id="5313967007315987356">Añadir sitio</translation>
 <translation id="5317780077021120954">Guardar</translation>
 <translation id="5324858694974489420">Configuración parental</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Al utilizar esta aplicación, aceptas las <ph name="BEGIN_LINK1" />Condiciones de Servicio<ph name="END_LINK1" /> y el <ph name="BEGIN_LINK2" />Aviso de Privacidad<ph name="END_LINK2" /> de Chrome.</translation>
 <translation id="5414836363063783498">Verificando…</translation>
 <translation id="5423934151118863508">Aquí aparecerán las páginas a las que accedes con más frecuencia</translation>
-<translation id="5424715742813396254">Editar nombre/contraseña o excepción guardados</translation>
 <translation id="5437003064129843501">Las sugerencias de contenido personalizado están actualmente inhabilitadas porque tus datos sincronizados están protegidos con una frase de contraseña personalizada.</translation>
 <translation id="544291274896356069">Saldrás del modo incógnito si este enlace se abre en una aplicación externa. ¿Quieres continuar?</translation>
 <translation id="5447201525962359567">Todo el almacenamiento del sitio web, como las cookies y otros datos almacenados de forma local</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Todos los sitios</translation>
 <translation id="6320088164292336938">Vibrar</translation>
 <translation id="6324034347079777476">Sincronización del sistema Android inhabilitada</translation>
-<translation id="6324360525379265737">Determinar codificación de caracteres automáticamente</translation>
 <translation id="6333140779060797560">Compartir a través de <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Cifrado</translation>
 <translation id="6364438453358674297">¿Eliminar sugerencia del historial?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Eliminar</translation>
 <translation id="6647073004883890710">¿Quieres que <ph name="PASSWORD_MANAGER_BRAND" /> actualice la contraseña de <ph name="USERNAME" /> en este sitio web?</translation>
 <translation id="6656545060687952787">Chrome necesita acceder a la ubicación para buscar dispositivos. <ph name="BEGIN_LINK" />Actualizar los permisos<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Contraseña</translation>
 <translation id="6659594942844771486">Pestaña</translation>
 <translation id="666268767214822976">Utiliza un servicio de predicciones para mostrar consultas relacionadas y sitios web populares a medida que escribes en la barra de direcciones</translation>
 <translation id="666981079809192359">Aviso de privacidad de Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Tu conexión a este sitio es privada, pero alguien en la red podría cambiar la apariencia de la página.</translation>
 <translation id="8493948351860045254">Liberar espacio</translation>
 <translation id="8497726226069778601">Aún no tienes contenido</translation>
+<translation id="8503813439785031346">Nombre de usuario</translation>
 <translation id="8514577642972634246">Navegar en modo incógnito</translation>
 <translation id="8518901949365209398">En este sitio se utiliza una configuración de seguridad vulnerable (firmas SHA-1), de modo que es posible que tu conexión no sea privada.</translation>
 <translation id="8525306231823319788">Pantalla completa</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb
index 0cb625c..b78c538 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">نشانک‌ها و سابقه وب</translation>
 <translation id="1549000191223877751">انتقال به پنجره دیگر</translation>
 <translation id="1553358976309200471">‏به‌روزرسانی Chrome</translation>
-<translation id="1557201757634521564">شناسایی خودکار کدبندی</translation>
 <translation id="1612196535745283361">‏Chrome برای جستجوی دستگاه‌ها باید به مکان دسترسی داشته باشد. دسترسی به مکان <ph name="BEGIN_LINK" />برای این دستگاه خاموش است<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">دوربین</translation>
 <translation id="1623104350909869708">جلوگیری از ایجاد پنجره‌های اضافی توسط این صفحه</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">عبارت‌های عبور مطابقت ندارند</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />دریافت راهنمایی<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">ذخیره ویدیو</translation>
-<translation id="307329814453917357">‏پیشنهاد ترجمه صفحه‌ها با استفاده از ‏‫مترجم Google‬</translation>
 <translation id="3089395242580810162">باز کردن در برگه ناشناس</translation>
 <translation id="3090193911106258841">در حال دسترسی به ورودی صوتی و ویدیویی</translation>
 <translation id="3117051980354074377">‏برای دسترسی به نشانک‌هایتان در دستگاه‌های دیگر، به سیستم Chrome وارد شوید.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">صفحات</translation>
 <translation id="4996978546172906250">اشتراک‌گذاری از طریق</translation>
 <translation id="5000922062037820727">مسدود (توصیه می‌شود)</translation>
+<translation id="5005498671520578047">کپی گذرواژه</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">اجازه دادن</translation>
 <translation id="5040262127954254034">حریم خصوصی</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">برای خروج از حالت تمام صفحه، از بالا صفحه را بکشید و دکمه برگشت را لمس کنید.</translation>
 <translation id="5284584623296338184">‏تغییرات در نشانک‌ها، سابقه، گذرواژه و سایر تنظیمات دیگر با حساب Google شما همگام‌سازی نخواهد شد. با این حال، داده‌های موجودتان در حساب Google شما باقی خواهند ماند.</translation>
 <translation id="5301954838959518834">بله، متوجه شدم</translation>
-<translation id="5302048478445481009">زبان</translation>
 <translation id="5304593522240415983">این قسمت باید پر شود</translation>
 <translation id="5308380583665731573">اتصال</translation>
+<translation id="5308603654685598744">‏‫اگر این قابلیت روشن باشد، Chrome ترجمه صفحات نوشته شده به زبان‌های دیگر را با استفاده از ‏‫مترجم Google‬ پیشنهاد می‌دهد.</translation>
 <translation id="5313967007315987356">افزودن سایت</translation>
 <translation id="5317780077021120954">ذخیره</translation>
 <translation id="5324858694974489420">تنظیمات والدین</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">‏استفاده از این برنامه به معنای اعلام موافقت شما با <ph name="BEGIN_LINK1" />شرایط خدمات<ph name="END_LINK1" /> و <ph name="BEGIN_LINK2" />اعلامیه حریم خصوصی<ph name="END_LINK2" /> Chrome است.</translation>
 <translation id="5414836363063783498">در حال تأیید...</translation>
 <translation id="5423934151118863508">صفحاتی که بیشترین بازدید را از آنها داشته‌اید در اینجا نمایان می‌شوند</translation>
-<translation id="5424715742813396254">ویرایش نام/گذرواژه ذخیره شده یا مورد استثنا</translation>
 <translation id="5437003064129843501">پیشنهاد محتوای شخصی‌سازی‌شده درحال حاضر غیرفعال است، چون داده‌های همگام‌سازی‌شده‌تان با عبارت عبور سفارشی محافظت می‌شود.</translation>
 <translation id="544291274896356069">اگر این پیوند در یک برنامه خارجی باز شود از حالت ناشناس خارج می‌شوید. ادامه می‌دهید؟</translation>
 <translation id="5447201525962359567">همه فضای ذخیره سایت‌ها، ازجمله کوکی‌ها و سایر داده‌های ذخیره‌شده در دستگاه</translation>
@@ -461,7 +459,6 @@
 <translation id="6295158916970320988">همه سایت‌ها</translation>
 <translation id="6320088164292336938">لرزش</translation>
 <translation id="6324034347079777476">‏همگام‌سازی سیستم Android غیرفعال شد</translation>
-<translation id="6324360525379265737">تعیین کدبندی نویسه به‌صورت خودکار</translation>
 <translation id="6333140779060797560">اشتراک‌گذاری از طریق <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">رمزگذاری</translation>
 <translation id="6364438453358674297">پیشنهاد از سابقه حذف شود؟</translation>
@@ -494,6 +491,7 @@
 <translation id="6643016212128521049">پاک کردن</translation>
 <translation id="6647073004883890710">می‌خواهید <ph name="PASSWORD_MANAGER_BRAND" /> گذرواژه <ph name="USERNAME" /> را برای این سایت به‌روزرسانی کند؟</translation>
 <translation id="6656545060687952787">‏Chrome برای جستجوی دستگاه‌ها باید به مکان دسترسی داشته باشد. <ph name="BEGIN_LINK" />به‌روزرسانی مجوزها<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">گذرواژه</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">از یک سرویس پیش‌بینی استفاده می‌شود تا هم‌زمان با تایپ کردن شما در نوار آدرس، عبارت‌های جستجوی مرتبط و وب‌سایت‌های محبوب نشان داده شوند</translation>
 <translation id="666981079809192359">‏اخطار حریم خصوصی Chrome</translation>
@@ -655,6 +653,7 @@
 <translation id="8481940801237642152">اتصال شما به این سایت خصوصی است، اما ممکن است شخصی در شبکه بتواند ظاهر این صفحه را تغییر دهد.</translation>
 <translation id="8493948351860045254">آزاد کردن فضا</translation>
 <translation id="8497726226069778601">هنوز… چیزی برای دیدن وجود ندارد</translation>
+<translation id="8503813439785031346">نام کاربری</translation>
 <translation id="8514577642972634246">ورود به حالت ناشناس</translation>
 <translation id="8518901949365209398">‏این سایت از یک پیکربندی امنیتی ضعیف (امضاهای SHA-1) استفاده می‌کند، بنابراین ممکن است اتصال شما خصوصی نباشد.</translation>
 <translation id="8525306231823319788">تمام صفحه</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb
index fe7fe43..3aff217 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Kirjanmerkit ja verkkohistoria</translation>
 <translation id="1549000191223877751">Siirrä toiseen ikkunaan</translation>
 <translation id="1553358976309200471">Päivitä Chrome</translation>
-<translation id="1557201757634521564">Havaitse merkistökoodaus automaattisesti</translation>
 <translation id="1612196535745283361">Chrome tarvitsee sijaintitietoja hakeakseen laitteita. Sijaintitiedot on <ph name="BEGIN_LINK" />poistettu käytöstä tällä laitteella<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">kameraasi</translation>
 <translation id="1623104350909869708">Estä tätä sivua luomasta muita viestejä</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Tunnuslauseet eivät vastaa toisiaan.</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Tutustu ohjeisiin<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Tallenna video</translation>
-<translation id="307329814453917357">Tarjoa sivujen kääntämistä Google Kääntäjällä.</translation>
 <translation id="3089395242580810162">Avaa incognito-välilehdessä</translation>
 <translation id="3090193911106258841">Ääni- ja videotuloa käytetään</translation>
 <translation id="3117051980354074377">Käytä kirjanmerkkejä muilta laitteiltasi kirjautumalla Chromeen.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Sivut</translation>
 <translation id="4996978546172906250">Jaa tällä palvelulla:</translation>
 <translation id="5000922062037820727">Estetty (suositus)</translation>
+<translation id="5005498671520578047">Kopioi salasana</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Salli</translation>
 <translation id="5040262127954254034">Tietosuoja</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Poistu koko näytön tilasta vetämällä näytön yläreunasta ja koskettamalla Takaisin-painiketta.</translation>
 <translation id="5284584623296338184">Kirjanmerkkeihin, historiaan, salasanoihin ja muihin asetuksiin tehtäviä muutoksia ei enää synkronoida Google-tilillesi. Olemassa olevia tietojasi säilytetään kuitenkin Google-tililläsi.</translation>
 <translation id="5301954838959518834">Selvä</translation>
-<translation id="5302048478445481009">Kieli</translation>
 <translation id="5304593522240415983">Kenttä ei voi olla tyhjä.</translation>
 <translation id="5308380583665731573">Muodosta yhteys</translation>
+<translation id="5308603654685598744">Kun tämä ominaisuus on käytössä, Chrome tarjoaa vieraskielisten sivujen käännöksiä Google Kääntäjän avulla.</translation>
 <translation id="5313967007315987356">Lisää sivusto</translation>
 <translation id="5317780077021120954">Tallenna</translation>
 <translation id="5324858694974489420">Vanhempien asetukset</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Käyttämällä sovellusta hyväksyt Chromen <ph name="BEGIN_LINK1" />käyttöehdot<ph name="END_LINK1" /> ja <ph name="BEGIN_LINK2" />tietosuojailmoituksen<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Vahvistetaan…</translation>
 <translation id="5423934151118863508">Käydyimmät sivusi näkyvät täällä</translation>
-<translation id="5424715742813396254">Muokkaa tallennettua nimeä/salasanaa tai poikkeusta</translation>
 <translation id="5437003064129843501">Yksilölliset sisältöehdotukset eivät ole tällä hetkellä käytössä, koska synkronoidut tietosi on suojattu omalla tunnuslauseella.</translation>
 <translation id="544291274896356069">Incognito-tilasta poistutaan, jos avaat tämän linkin ulkoisessa sovelluksessa. Haluatko jatkaa?</translation>
 <translation id="5447201525962359567">Kaikki tallennetut sivustotiedot, mukaan lukien evästeet ja muut paikallisesti tallennetut tiedot</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Kaikki sivustot</translation>
 <translation id="6320088164292336938">Värinä</translation>
 <translation id="6324034347079777476">Android-järjestelmän synkronointi poistettu käytöstä</translation>
-<translation id="6324360525379265737">Tunnista merkistökoodaus automaattisesti.</translation>
 <translation id="6333140779060797560">Jaa sovelluksella <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Salaus</translation>
 <translation id="6364438453358674297">Poistetaanko ehdotus historiasta?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Tyhjennä</translation>
 <translation id="6647073004883890710">Haluatko, että <ph name="PASSWORD_MANAGER_BRAND" /> päivittää tilin <ph name="USERNAME" /> salasanan tällä sivustolla?</translation>
 <translation id="6656545060687952787">Chrome tarvitsee sijaintitietojen käyttöoikeuden hakeakseen laitteita. <ph name="BEGIN_LINK" />Päivitä käyttöoikeudet<ph name="END_LINK" />.</translation>
+<translation id="6657585470893396449">Salasana</translation>
 <translation id="6659594942844771486">Välilehti</translation>
 <translation id="666268767214822976">Käytä ennakointipalvelua, joka näyttää sinulle aiheeseen liittyviä kyselyitä sekä suosittuja verkkosivustoja kirjoittaessasi osoitepalkkiin.</translation>
 <translation id="666981079809192359">Chromen tietosuojailmoitus</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Sivustoon on muodostettu salattu yhteys, mutta verkon käyttäjät voivat päästä muokkaamaan sivun ulkoasua.</translation>
 <translation id="8493948351860045254">Vapauta tilaa</translation>
 <translation id="8497726226069778601">Täällä ei ole mitään nähtävää… vielä</translation>
+<translation id="8503813439785031346">Käyttäjätunnus</translation>
 <translation id="8514577642972634246">Siirry incognito-tilaan</translation>
 <translation id="8518901949365209398">Sivusto käyttää heikkoa suojausta (SHA-1-allekirjoitukset), joten yhteytesi ei välttämättä ole täysin turvallinen.</translation>
 <translation id="8525306231823319788">Koko näyttö</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb
index 5c579c89..d0ca5d0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bookmark at history ng web</translation>
 <translation id="1549000191223877751">Lumipat sa ibang window</translation>
 <translation id="1553358976309200471">I-update ang Chrome</translation>
-<translation id="1557201757634521564">Awtomatikong i-detect ang pag-e-encode</translation>
 <translation id="1612196535745283361">Kailangan ng Chrome ng access sa lokasyon upang magkapag-scan ng mga device. Ang access sa lokasyon ay <ph name="BEGIN_LINK" />naka-off para sa device na ito<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Camera</translation>
 <translation id="1623104350909869708">Pigilan ang pahinang ito sa paggawa ng mga karagdagang dialog</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Hindi nagtutugma ang mga passphrase</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Humingi ng tulong<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">I-save ang video</translation>
-<translation id="307329814453917357">Mag-alok na magsalin ng mga page sa pamamagitan ng Google Translate</translation>
 <translation id="3089395242580810162">Buksan sa tab na incognito</translation>
 <translation id="3090193911106258841">Ina-access ang input ng audio at video</translation>
 <translation id="3117051980354074377">Upang mailagay ang iyong mga bookmark sa iba mo pang mga device, mag-sign in sa Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Mga Page</translation>
 <translation id="4996978546172906250">Ibahagi gamit ang</translation>
 <translation id="5000922062037820727">Naka-block (inirerekomenda)</translation>
+<translation id="5005498671520578047">Kopyahin password</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Payagan</translation>
 <translation id="5040262127954254034">Privacy</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">I-drag mula sa itaas at pindutin ang button na bumalik upang lumabas sa full screen.</translation>
 <translation id="5284584623296338184">Hindi na masi-sync sa iyong Google Account ang mga pagbabago sa iyong mga bookmark, history, password at iba pang mga setting. Gayunpaman, mananatiling nakaimbak sa iyong Google account ang iyong kasalukuyang data.</translation>
 <translation id="5301954838959518834">OK, nakuha ko na</translation>
-<translation id="5302048478445481009">Wika</translation>
 <translation id="5304593522240415983">Hindi maaaring maging blangko ang field na ito</translation>
 <translation id="5308380583665731573">Kumonekta</translation>
+<translation id="5308603654685598744">Kapag naka-on ang feature na ito, mag-aalok ang Chrome na magsalin ng mga page na nakasulat sa iba pang mga wika gamit ang Google Translate.</translation>
 <translation id="5313967007315987356">Magdagdag ng site</translation>
 <translation id="5317780077021120954">I-save</translation>
 <translation id="5324858694974489420">Mga Setting para sa Magulang</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Kapag ginamit mo ang application na ito, ang ibig sabihin, sumasang-ayon ka sa <ph name="BEGIN_LINK1" />Mga Tuntunin ng Serbisyo<ph name="END_LINK1" /> at <ph name="BEGIN_LINK2" />Patakaran sa Privacy<ph name="END_LINK2" /> ng Chrome.</translation>
 <translation id="5414836363063783498">Vine-verify…</translation>
 <translation id="5423934151118863508">Lalabas dito ang mga page na madalas mong bisitahin</translation>
-<translation id="5424715742813396254">I-edit ang naka-save na pangalan/password o pagbubukod</translation>
 <translation id="5437003064129843501">Kasalukuyang naka-disable ang mga naka-personalize na suhestyon sa content, dahil pinoprotektahan ng custom na passphrase ang iyong naka-sync na data.</translation>
 <translation id="544291274896356069">Aalis ka sa incognito mode kung bubuksan mo ang link na ito sa isang panlabas na application. Gusto mo bang magpatuloy?</translation>
 <translation id="5447201525962359567">Lahat ng storage ng site, kabilang ang cookies at iba pang lokal na nakaimbak na data</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Lahat ng site</translation>
 <translation id="6320088164292336938">Mag-vibrate</translation>
 <translation id="6324034347079777476">Naka-disable ang pag-sync ng Android system</translation>
-<translation id="6324360525379265737">Awtomatikong tukuyin ang pag-e-encode ng character</translation>
 <translation id="6333140779060797560">Ibahagi sa pamamagitan ng <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Pag-encrypt</translation>
 <translation id="6364438453358674297">Alisin ang suhestyon mula sa history?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">I-clear</translation>
 <translation id="6647073004883890710">Gusto mo bang i-update ng <ph name="PASSWORD_MANAGER_BRAND" /> ang password para kay <ph name="USERNAME" /> para sa site na ito?</translation>
 <translation id="6656545060687952787">Kailangan ng Chrome ng access sa lokasyon upang makapag-scan at makakita ng mga device. <ph name="BEGIN_LINK" />I-update ang mga pahintulot<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Password</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Gumamit ng serbisyo sa paghula upang magpakita ng mga nauugnay na query at sikat na website habang nagta-type ka sa address bar</translation>
 <translation id="666981079809192359">Notification ng Privacy ng Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Pribado ang iyong koneksyon sa site na ito, ngunit maaaring mabago ng isang tao sa network ang hitsura ng page.</translation>
 <translation id="8493948351860045254">Magbakante ng espasyo</translation>
 <translation id="8497726226069778601">Walang makikita dito... sa ngayon</translation>
+<translation id="8503813439785031346">Username</translation>
 <translation id="8514577642972634246">Pumasok sa mode na incognito</translation>
 <translation id="8518901949365209398">Gumagamit ng mahinang configuration sa seguridad (mga SHA-1 signature) ang site na ito, kaya maaaring hindi pribado ang iyong koneksyon.</translation>
 <translation id="8525306231823319788">Buong screen</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb
index 0b13c29..9969a21 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Favoris et historique Web</translation>
 <translation id="1549000191223877751">Déplacer vers autre fenêtre</translation>
 <translation id="1553358976309200471">Mettre à jour Chrome</translation>
-<translation id="1557201757634521564">Détecter automatiquement l'encodage</translation>
 <translation id="1612196535745283361">Chrome doit avoir accès aux données de localisation pour rechercher des appareils. Cette fonctionnalité est <ph name="BEGIN_LINK" />désactivée pour cet appareil<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Appareil photo</translation>
 <translation id="1623104350909869708">Empêcher cette page de générer des boîtes de dialogue supplémentaires</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Les phrases secrètes ne correspondent pas.</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Obtenir de l'aide<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Enregistrer la vidéo</translation>
-<translation id="307329814453917357">Proposer de traduire des pages avec Google Traduction</translation>
 <translation id="3089395242580810162">Ouvrir dans un onglet de nav. privée</translation>
 <translation id="3090193911106258841">Accès à l'entrée audio et vidéo en cours…</translation>
 <translation id="3117051980354074377">Connectez-vous à Chrome pour accéder à vos favoris sur vos autres appareils.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Pages</translation>
 <translation id="4996978546172906250">Partager via</translation>
 <translation id="5000922062037820727">Bloquée (recommandé)</translation>
+<translation id="5005498671520578047">Copier mot de passe</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Autoriser</translation>
 <translation id="5040262127954254034">Confidentialité</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Pour quitter le mode plein écran, faites glisser un doigt du haut vers le bas, puis appuyez sur le bouton Retour.</translation>
 <translation id="5284584623296338184">Les modifications apportées à vos favoris, votre historique, vos mots de passe et d'autres paramètres ne seront plus synchronisées avec votre compte Google. Vos données resteront cependant conservées dans votre compte Google.</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">Langue</translation>
 <translation id="5304593522240415983">Champ obligatoire.</translation>
 <translation id="5308380583665731573">Connexion</translation>
+<translation id="5308603654685598744">Si cette fonctionnalité est activée, une proposition de traduction des pages rédigées dans d'autres langues à l'aide de Google Traduction vous est envoyée dans Chrome.</translation>
 <translation id="5313967007315987356">Ajouter un site</translation>
 <translation id="5317780077021120954">Enregistrer</translation>
 <translation id="5324858694974489420">Paramètres parentaux</translation>
@@ -382,8 +381,6 @@
 <translation id="5400569084694353794">En utilisant cette application, vous acceptez les <ph name="BEGIN_LINK1" />Conditions d'utilisation<ph name="END_LINK1" /> et l'<ph name="BEGIN_LINK2" />Avis de confidentialité<ph name="END_LINK2" /> de Chrome.</translation>
 <translation id="5414836363063783498">Validation en cours…</translation>
 <translation id="5423934151118863508">Les pages les plus consultées s'affichent ici.</translation>
-<translation id="5424715742813396254">Modifier nom et mot passe ou exception enregistrés
-</translation>
 <translation id="5437003064129843501">Les recommandations de contenu personnalisé sont actuellement désactivées, car vos informations synchronisées sont protégées par une phrase secrète personnalisée.</translation>
 <translation id="544291274896356069">En ouvrant ce lien dans une application externe, vous allez quitter le mode navigation privée. Voulez-vous continuer ?</translation>
 <translation id="5447201525962359567">Toutes les données de site stockées, y compris les cookies et d'autres données stockées en local</translation>
@@ -463,7 +460,6 @@
 <translation id="6295158916970320988">Tous les sites</translation>
 <translation id="6320088164292336938">Vibreur</translation>
 <translation id="6324034347079777476">La synchronisation du système Android est désactivée.</translation>
-<translation id="6324360525379265737">Déterminer automatiquement l'encodage des caractères</translation>
 <translation id="6333140779060797560">Partager via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Chiffrement</translation>
 <translation id="6364438453358674297">Supprimer la suggestion de l'historique ?</translation>
@@ -496,6 +492,7 @@
 <translation id="6643016212128521049">Effacer</translation>
 <translation id="6647073004883890710">Voulez-vous que <ph name="PASSWORD_MANAGER_BRAND" /> mette à jour le mot de passe de "<ph name="USERNAME" />" pour ce site ?</translation>
 <translation id="6656545060687952787">Chrome doit accéder aux données de localisation pour rechercher des appareils. <ph name="BEGIN_LINK" />Mettre à jour les autorisations<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Mot de passe</translation>
 <translation id="6659594942844771486">Onglet</translation>
 <translation id="666268767214822976">Utiliser un service de prédiction pour suggérer des requêtes associées et des sites populaires lorsque vous saisissez des termes dans la barre d'adresse</translation>
 <translation id="666981079809192359">Avis de confidentialité de Chrome</translation>
@@ -657,6 +654,7 @@
 <translation id="8481940801237642152">Votre connexion à ce site est privée, mais d'autres personnes connectées au réseau peuvent réussir à modifier l'apparence de la page.</translation>
 <translation id="8493948351860045254">Libérer de l'espace</translation>
 <translation id="8497726226069778601">Aucune page à afficher pour le moment</translation>
+<translation id="8503813439785031346">Nom d'utilisateur</translation>
 <translation id="8514577642972634246">Activer le mode navigation privée</translation>
 <translation id="8518901949365209398">Ce site utilise une configuration de sécurité faible (signatures SHA-1). Il est donc possible que votre connexion ne soit pas privée.</translation>
 <translation id="8525306231823319788">Plein écran</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb b/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb
index 9631d6f..56866e5 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">बुकमार्क और वेब इतिहास</translation>
 <translation id="1549000191223877751">अन्य विंडो में ले जाएं</translation>
 <translation id="1553358976309200471">Chrome अपडेट करें</translation>
-<translation id="1557201757634521564">एन्कोडिंग का स्वत: पता लगाना</translation>
 <translation id="1612196535745283361">डिवाइस स्कैन करने के लिए Chrome को स्थान एक्सेस की आवश्यकता होती है. स्थान एक्सेस <ph name="BEGIN_LINK" />इस डिवाइस के लिए बंद<ph name="END_LINK" /> है.</translation>
 <translation id="1620510694547887537">कैमरा</translation>
 <translation id="1623104350909869708">इस पृष्ठ को अतिरिक्त डॉयलॉग बनाने से रोकें</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">पासफ़्रेज़ मिलान नहीं करते</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />सहायता प्राप्त करें<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">वीडियो सहेजें</translation>
-<translation id="307329814453917357">Google अनुवाद का उपयोग करके पृष्ठों का अनुवाद ऑफ़र करें</translation>
 <translation id="3089395242580810162">गुप्त टैब में खोलें</translation>
 <translation id="3090193911106258841">ऑडियो और वीडियो इनपुट ऐक्सेस हो रहा है</translation>
 <translation id="3117051980354074377">अपने अन्य डिवाइस पर अपने बुकमार्क प्राप्‍त करने के लिए, Chrome में प्रवेश करें.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">पृष्ठ</translation>
 <translation id="4996978546172906250">इसके द्वारा साझा करें</translation>
 <translation id="5000922062037820727">अवरोधित (सुझाया गया)</translation>
+<translation id="5005498671520578047">पासवर्ड कॉपी करें</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">अनुमति दें</translation>
 <translation id="5040262127954254034">गोपनीयता</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">पूर्ण स्क्रीन से बाहर निकलने के लिए ऊपर से खींचें और वापस जाएं स्पर्श करें.</translation>
 <translation id="5284584623296338184">आपके बुकमार्क, इतिहास, पासवर्ड और अन्य सेटिंग में किए गए बदलाव अब आपके Google खाते में समन्वयित नहीं किए जाएंगे. हालांकि, आपका मौजूदा डेटा आपके Google खाते में संग्रहीत रहेगा.</translation>
 <translation id="5301954838959518834">ठीक है, समझ गया/गई</translation>
-<translation id="5302048478445481009">भाषा</translation>
 <translation id="5304593522240415983">यह फ़ील्‍ड खाली नहीं छोड़ी जा सकती</translation>
 <translation id="5308380583665731573">कनेक्ट करें</translation>
+<translation id="5308603654685598744">जब यह सुविधा चालू होती है तो Chrome, Google अनुवाद का उपयोग करके अन्य भाषाओं में लिखे गए पृष्ठों का अनुवाद करना ऑफ़र करेगा.</translation>
 <translation id="5313967007315987356">साइट जोड़ें</translation>
 <translation id="5317780077021120954">सहेजें</translation>
 <translation id="5324858694974489420">अभिभावकीय सेटिंग</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">इस ऐप्‍लिकेशन का उपयाेग करके, आप Chrome की <ph name="BEGIN_LINK1" />सेवा की शर्तों<ph name="END_LINK1" /> और <ph name="BEGIN_LINK2" />गोपनीयता नोटिस<ph name="END_LINK2" /> से सहमत होते हैं.</translation>
 <translation id="5414836363063783498">सत्यापन हो रहा है...</translation>
 <translation id="5423934151118863508">आपके द्वारा सबसे अधिक देखे गए पृष्ठ यहां दिखाई देंगे</translation>
-<translation id="5424715742813396254">सहेजे गए नाम/पासवर्ड या अपवाद को संपादित करना</translation>
 <translation id="5437003064129843501">वैयक्तिकृत सामग्री सुझाव वर्तमान में अक्षम हैं, क्योंकि आपका समन्वयित डेटा किसी कस्टम पासफ़्रेज़ से रक्षित है.</translation>
 <translation id="544291274896356069">इस लिंक के किसी बाहरी ऐप्स में खुले होने पर गुप्त मोड छोड़ा जा रहा है. जारी रखें?</translation>
 <translation id="5447201525962359567">सभी साइट मेमोरी, जिसमें कुकी और स्थानीय रूप से संग्रहीत अन्य डेटा शामिल है</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">सभी साइटें</translation>
 <translation id="6320088164292336938">कंपन</translation>
 <translation id="6324034347079777476">Android सिस्टम समन्वयन अक्षम है</translation>
-<translation id="6324360525379265737">वर्ण एन्कोडिंग अपने आप निर्धारित करें</translation>
 <translation id="6333140779060797560"><ph name="APPLICATION" /> के द्वारा साझा करें</translation>
 <translation id="6337234675334993532">सुरक्षित तरीका</translation>
 <translation id="6364438453358674297">सुझाव को इतिहास से निकालें?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">साफ़ करें</translation>
 <translation id="6647073004883890710">क्या आप चाहते हैं कि <ph name="PASSWORD_MANAGER_BRAND" /> इस साइट के लिए <ph name="USERNAME" /> के पासवर्ड को अपडेट करे?</translation>
 <translation id="6656545060687952787">डिवाइस स्‍कैन करने के लिए Chrome को स्‍थान एक्‍सेस की आवश्‍यकता है. <ph name="BEGIN_LINK" />अनुमतियां अपडेट करें<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">पासवर्ड</translation>
 <translation id="6659594942844771486">टैब</translation>
 <translation id="666268767214822976">आपके द्वारा पता बार में लिखते ही संबंधित क्‍वेरी और लोकप्रिय वेबसाइटें दिखाने के लिए पूर्वानुमान सेवा का उपयोग करें</translation>
 <translation id="666981079809192359">Chrome गोपनीयता सूचना</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">इस साइट से आपका कनेक्‍शन निजी है, लेकिन नेटवर्क पर मौजूद कोई व्‍यक्‍ति पृष्‍ठ का रूप बदल सकता है.</translation>
 <translation id="8493948351860045254">स्‍थान खाली करें</translation>
 <translation id="8497726226069778601">यहां देखने के लिए…अभी तक कुछ भी नहीं है</translation>
+<translation id="8503813439785031346">उपयोगकर्ता नाम</translation>
 <translation id="8514577642972634246">गुप्त मोड में प्रवेश करें</translation>
 <translation id="8518901949365209398">यह साइट कमज़ोर सुरक्षा कॉन्‍फ़िगरेशन (SHA-1 हस्‍ताक्षर) का उपयोग करती है, इसलिए हो सकता है कि आपका कनेक्‍शन निजी ना रहे.</translation>
 <translation id="8525306231823319788">पूर्ण स्‍क्रीन</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb
index f3d6684..ff78816c2 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Oznake i Google povijest</translation>
 <translation id="1549000191223877751">Premjesti u drugi prozor</translation>
 <translation id="1553358976309200471">Ažuriraj Chrome</translation>
-<translation id="1557201757634521564">Automatski otkrij kodiranje</translation>
 <translation id="1612196535745283361">Chrome treba pristup lokaciji kako bi skenirao uređaje. Pristup lokaciji <ph name="BEGIN_LINK" />isključen je za ovaj uređaj<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Fotoaparat</translation>
 <translation id="1623104350909869708">Spriječi da ova stranica stvori dodatne dijaloške okvire</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Zaporke se ne podudaraju</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Potražite pomoć<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Spremi videozapis</translation>
-<translation id="307329814453917357">Ponudi prijevod stranica pomoću Google prevoditelja</translation>
 <translation id="3089395242580810162">Otvori na kartici Anonimno</translation>
 <translation id="3090193911106258841">Pristupanje audio i videoulazu</translation>
 <translation id="3117051980354074377">Da bi se prikazale oznake s vaših ostalih uređaja, prijavite se na Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Stranice</translation>
 <translation id="4996978546172906250">Dijeli putem</translation>
 <translation id="5000922062037820727">Blokirano (preporučeno)</translation>
+<translation id="5005498671520578047">Kopiranje zaporke</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Dopusti</translation>
 <translation id="5040262127954254034">Privatnost</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Povucite od vrha zaslona i dodirnite gumb Natrag da biste zatvorili prikaz na cijelom zaslonu.</translation>
 <translation id="5284584623296338184">Promjene oznaka, povijesti, zaporki i drugih postavki više se neće sinkronizirati s vašim Google računom. No vaši postojeći podaci ostat će pohranjeni na vašem Google računu.</translation>
 <translation id="5301954838959518834">U redu, shvaćam</translation>
-<translation id="5302048478445481009">Jezik</translation>
 <translation id="5304593522240415983">To polje ne može biti prazno</translation>
 <translation id="5308380583665731573">Povežite se</translation>
+<translation id="5308603654685598744">Kada je ta značajka uključena, Chrome će nuditi prevođenje stranica napisanih na drugim jezicima Google prevoditeljem.</translation>
 <translation id="5313967007315987356">Dodaj web-lokaciju</translation>
 <translation id="5317780077021120954">Spremi</translation>
 <translation id="5324858694974489420">Postavke nadređenog računa</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Upotrebom te aplikacije prihvaćate Chromeove <ph name="BEGIN_LINK1" />Uvjete pružanja usluge<ph name="END_LINK1" /> i <ph name="BEGIN_LINK2" />Obavijest o privatnosti<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Potvrđivanje…</translation>
 <translation id="5423934151118863508">Najposjećenije stranice prikazivat će se ovdje</translation>
-<translation id="5424715742813396254">Uređivanje spremljenog imena/zaporke ili iznimke</translation>
 <translation id="5437003064129843501">Prijedlozi prilagođenog sadržaja trenutačno su onemogućeni jer su sinkronizirani podaci zaštićeni prilagođenom zaporkom.</translation>
 <translation id="544291274896356069">Izaći ćete iz anonimnog načina ako se ta veza otvori u vanjskoj aplikaciji. Želite li nastaviti?</translation>
 <translation id="5447201525962359567">Cijela pohrana web-lokacije, uključujući kolačiće i druge lokalno pohranjene podatke</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Sve web-lokacije</translation>
 <translation id="6320088164292336938">Omogući vibraciju</translation>
 <translation id="6324034347079777476">Sinkronizacija sustava Android onemogućena</translation>
-<translation id="6324360525379265737">Automatsko određivanje kodiranja znakova</translation>
 <translation id="6333140779060797560">Dijeljenje putem aplikacije <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Enkripcija</translation>
 <translation id="6364438453358674297">Želite li ukloniti prijedlog iz povijesti?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Izbriši</translation>
 <translation id="6647073004883890710">Želite li da <ph name="PASSWORD_MANAGER_BRAND" /> ažurira zaporku korisnika <ph name="USERNAME" /> za tu web-lokaciju?</translation>
 <translation id="6656545060687952787">Chrome treba pristup lokaciji kako bi skenirao uređaje. <ph name="BEGIN_LINK" />Ažuriraj dopuštenja<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Zaporka</translation>
 <translation id="6659594942844771486">Kartica</translation>
 <translation id="666268767214822976">Upotrijebi uslugu predviđanja za prikaz srodnih upita i popularnih web-lokacija prilikom upisivanja u adresnu traku</translation>
 <translation id="666981079809192359">Obavijest o privatnosti za Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Veza s tom web-lokacijom privatna je, ali bi netko na mreži mogao izmijeniti izgled stranice.</translation>
 <translation id="8493948351860045254">Oslobodi prostor</translation>
 <translation id="8497726226069778601">Ovdje nema ničega... zasad</translation>
+<translation id="8503813439785031346">Korisničko ime</translation>
 <translation id="8514577642972634246">Ulaz u anonimni način</translation>
 <translation id="8518901949365209398">Ova web-lokacija upotrebljava slabu sigurnosnu konfiguraciju (SHA-1 potpise), pa vaša veza možda nije privatna.</translation>
 <translation id="8525306231823319788">Cijeli zaslon</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb b/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb
index 5c06be8..97fa166a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Könyvjelzők és webes előzmények</translation>
 <translation id="1549000191223877751">Áthelyezés másik ablakba</translation>
 <translation id="1553358976309200471">A Chrome böngésző frissítése</translation>
-<translation id="1557201757634521564">Kódolás automatikus felismerése</translation>
 <translation id="1612196535745283361">A Chrome-nak hozzá kell férnie a tartózkodási helyhez, hogy eszközöket kereshessen. A tartózkodási helyhez való hozzáférés <ph name="BEGIN_LINK" />ki van kapcsolva ezen az eszközön<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Akadályozza meg, hogy ez az oldal további párbeszédablakokat hozzon létre.</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Az összetett jelszavak nem egyeznek</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Kérjen segítséget<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Videó mentése</translation>
-<translation id="307329814453917357">Az oldalak Google Fordítóval történő lefordításának felajánlása</translation>
 <translation id="3089395242580810162">Megnyitás inkognitólapon</translation>
 <translation id="3090193911106258841">Hozzáférés a hang- és videobementhez</translation>
 <translation id="3117051980354074377">Ha a többi eszközén is szeretné elérni könyvjelzőit, jelentkezzen be a Chrome-ba.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Oldal</translation>
 <translation id="4996978546172906250">Megosztás itt:</translation>
 <translation id="5000922062037820727">Letiltva (ajánlott)</translation>
+<translation id="5005498671520578047">Jelszó másolása</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Engedélyezés</translation>
 <translation id="5040262127954254034">Adatvédelem</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">A teljes képernyős megjelenítésből való kilépéshez húzza le felülről, majd koppintson a vissza gombra.</translation>
 <translation id="5284584623296338184">Könyvjelzői, előzményei, jelszavai és más beállításai a továbbiakban már nem lesznek szinkronizálva Google-fiókjával. Meglévő adatainak tárolása azonban továbbra is megmarad Google-fiókjában.</translation>
 <translation id="5301954838959518834">Rendben, értem</translation>
-<translation id="5302048478445481009">Nyelv</translation>
 <translation id="5304593522240415983">Ez a mező nem lehet üres</translation>
 <translation id="5308380583665731573">Csatlakozás</translation>
+<translation id="5308603654685598744">Ha a funkció be van kapcsolva, a Chrome felajánlja az idegen nyelven írt oldalak fordítását a Google Fordítóval.</translation>
 <translation id="5313967007315987356">Webhely hozzáadása</translation>
 <translation id="5317780077021120954">Mentés</translation>
 <translation id="5324858694974489420">Szülői beállítások</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Az alkalmazás használatával Ön elfogadja a Chrome <ph name="BEGIN_LINK1" />Általános Szerződési Feltételeit<ph name="END_LINK1" /> és az <ph name="BEGIN_LINK2" />Adatvédelmi közleményt<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Ellenőrzés...</translation>
 <translation id="5423934151118863508">A leggyakrabban látogatott oldalak fognak itt megjelenni</translation>
-<translation id="5424715742813396254">Mentett név/jelszó vagy kivétel szerkesztése</translation>
 <translation id="5437003064129843501">A személyre szabott tartalomjavaslatok jelenleg ki vannak kapcsolva, mert szinkronizált adatait egyedi összetett jelszó védi.</translation>
 <translation id="544291274896356069">Ha ezt a linket külső alkalmazásban nyitja meg, elhagyja az inkognitómódot. Folytatja?</translation>
 <translation id="5447201525962359567">Összes webhelytárhely, beleértve a cookie-kat és más helyben tárolt adatokat</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Az összes webhely</translation>
 <translation id="6320088164292336938">Rezgés</translation>
 <translation id="6324034347079777476">Az Android rendszer szinkronizálása letiltva</translation>
-<translation id="6324360525379265737">Karakterkódolás automatikus meghatározása</translation>
 <translation id="6333140779060797560">Megosztás a következőn keresztül: <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Titkosítás</translation>
 <translation id="6364438453358674297">Eltávolítja a javaslatot az előzményekből?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Törlés</translation>
 <translation id="6647073004883890710">Szeretné, hogy a <ph name="PASSWORD_MANAGER_BRAND" /> frissítse a(z) <ph name="USERNAME" /> fiók jelszavát ennél a webhelynél?</translation>
 <translation id="6656545060687952787">A Chrome-nak hozzá kell férnie a tartózkodási helyhez, hogy eszközöket kereshessen. <ph name="BEGIN_LINK" />Frissítse az engedélyeket<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Jelszó</translation>
 <translation id="6659594942844771486">Lap</translation>
 <translation id="666268767214822976">„Várható kifejezések” szolgáltatás használata a kapcsolódó lekérdezések és népszerű webhelyek megjelenítéséhez a címsávba történő gépelés során.</translation>
 <translation id="666981079809192359">Chrome – Adatvédelmi közlemény</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">A webhellyel való kapcsolata privát, ám valaki a hálózaton módosíthatja az oldal megjelenését.</translation>
 <translation id="8493948351860045254">Terület felszabadítása</translation>
 <translation id="8497726226069778601">Nincs itt semmi látnivaló… még</translation>
+<translation id="8503813439785031346">Felhasználónév</translation>
 <translation id="8514577642972634246">Belépés inkognitómódba</translation>
 <translation id="8518901949365209398">Ez a webhely gyenge biztonsági beállításokat (SHA-1 aláírásokat) használ , ezért előfordulhat, hogy a kapcsolat nem titkos.</translation>
 <translation id="8525306231823319788">Teljes képernyő</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_id.xtb b/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
index 39bc6987..0aa9f76 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bookmark dan riwayat web</translation>
 <translation id="1549000191223877751">Beralih ke jendela lain</translation>
 <translation id="1553358976309200471">Perbarui browser Chrome</translation>
-<translation id="1557201757634521564">Deteksi otomatis enkode</translation>
 <translation id="1612196535745283361">Chrome memerlukan akses lokasi untuk memindai perangkat. Akses lokasi <ph name="BEGIN_LINK" />dinonaktifkan untuk perangkat ini<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Cegah dialog lain dari laman ini.</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Frasa sandi tidak cocok</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Dapatkan bantuan<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Simpan video</translation>
-<translation id="307329814453917357">Tawarkan untuk menerjemahkan laman dengan Google Terjemahan</translation>
 <translation id="3089395242580810162">Buka di tab penyamaran</translation>
 <translation id="3090193911106258841">Mengakses masukan audio dan video</translation>
 <translation id="3117051980354074377">Untuk mendapatkan bookmark dari perangkat lainnya, masuk ke Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Laman</translation>
 <translation id="4996978546172906250">Bagikan dengan</translation>
 <translation id="5000922062037820727">Diblokir (disarankan)</translation>
+<translation id="5005498671520578047">Salin sandi</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Izinkan</translation>
 <translation id="5040262127954254034">Privasi</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Seret dari atas dan ketuk tombol kembali untuk keluar dari mode layar penuh.</translation>
 <translation id="5284584623296338184">Perubahan pada bookmark, riwayat, sandi, dan setelan lainnya tidak akan disinkronkan lagi dengan Akun Google Anda. Namun, data yang sudah ada akan tetap disimpan di akun Google Anda.</translation>
 <translation id="5301954838959518834">Oke, paham</translation>
-<translation id="5302048478445481009">Bahasa</translation>
 <translation id="5304593522240415983">Bidang ini tidak boleh kosong</translation>
 <translation id="5308380583665731573">Sambungkan</translation>
+<translation id="5308603654685598744">Ketika fitur ini diaktifkan, Chrome akan menawarkan untuk menerjemahkan laman yang tertulis dalam bahasa lain menggunakan Google Terjemahan.</translation>
 <translation id="5313967007315987356">Tambahkan situs</translation>
 <translation id="5317780077021120954">Simpan</translation>
 <translation id="5324858694974489420">Setelan Orang Tua</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Dengan menggunakan aplikasi ini, Anda menyetujui <ph name="BEGIN_LINK1" />Persyaratan Layanan<ph name="END_LINK1" /> dan <ph name="BEGIN_LINK2" />Pemberitahuan Privasi<ph name="END_LINK2" /> Chrome.</translation>
 <translation id="5414836363063783498">Memverifikasi...</translation>
 <translation id="5423934151118863508">Halaman yang paling sering dikunjungi akan muncul di sini</translation>
-<translation id="5424715742813396254">Edit pengecualian atau nama/sandi yang tersimpan</translation>
 <translation id="5437003064129843501">Saat ini saran konten hasil personalisasi dinonaktifkan, karena data yang disinkronkan dilindungi frasa sandi khusus.</translation>
 <translation id="544291274896356069">Mode penyamaran akan ditutup jika tautan ini dibuka di aplikasi eksternal. Lanjutkan?</translation>
 <translation id="5447201525962359567">Semua penyimpanan situs, termasuk cookie dan data lain yang tersimpan secara lokal</translation>
@@ -462,11 +460,10 @@
 <translation id="6295158916970320988">Semua situs</translation>
 <translation id="6320088164292336938">Getar</translation>
 <translation id="6324034347079777476">Sinkronisasi sistem Android dinonaktifkan</translation>
-<translation id="6324360525379265737">Tentukan enkode karakter secara otomatis</translation>
 <translation id="6333140779060797560">Bagikan dengan <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Enkripsi</translation>
 <translation id="6364438453358674297">Hapus saran dari riwayat?</translation>
-<translation id="6383961787135158834">Kosongkan Simpanan Situs…</translation>
+<translation id="6383961787135158834">Hapus Penyimpanan Situs…</translation>
 <translation id="6388207532828177975">Hapus &amp; setel ulang</translation>
 <translation id="6404511346730675251">Edit bookmark</translation>
 <translation id="6406506848690869874">Sinkronisasi</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Hapus</translation>
 <translation id="6647073004883890710">Ingin <ph name="PASSWORD_MANAGER_BRAND" /> memperbarui sandi bagi <ph name="USERNAME" /> untuk situs ini?</translation>
 <translation id="6656545060687952787">Chrome memerlukan akses lokasi untuk memindai perangkat. <ph name="BEGIN_LINK" />Perbarui izin<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Sandi</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Gunakan pencarian otomatis untuk menunjukkan situs web populer saat Anda mengetik alamat situs</translation>
 <translation id="666981079809192359">Notifikasi Privasi Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Sambungan Anda ke situs ini bersifat pribadi, namun seseorang yang berada dalam jaringan Anda mungkin dapat mengubah tampilan laman.</translation>
 <translation id="8493948351860045254">Kosongkan ruang</translation>
 <translation id="8497726226069778601">Belum ada yang dapat dilihat di sini…</translation>
+<translation id="8503813439785031346">Nama Pengguna</translation>
 <translation id="8514577642972634246">Masuki mode penyamaran</translation>
 <translation id="8518901949365209398">Situs ini menggunakan konfigurasi keamanan yang lemah (tanda tangan SHA-1), sehingga sambungan Anda mungkin bukan sambungan pribadi.</translation>
 <translation id="8525306231823319788">Layar penuh</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_it.xtb b/chrome/android/java/strings/translations/android_chrome_strings_it.xtb
index 7c4f898..192c1be 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_it.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_it.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Preferiti e cronologia web</translation>
 <translation id="1549000191223877751">Passa a un'altra finestra</translation>
 <translation id="1553358976309200471">Aggiorna Chrome</translation>
-<translation id="1557201757634521564">Rileva automaticamente la codifica</translation>
 <translation id="1612196535745283361">Chrome ha bisogno dell'accesso alla posizione per cercare dispositivi. L'accesso alla posizione è <ph name="BEGIN_LINK" />disattivato su questo dispositivo<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Videocamera</translation>
 <translation id="1623104350909869708">Impedisci la creazione di altre finestre di dialogo in questa pagina</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Le passphrase non corrispondono</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Richiedi assistenza<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Salva video</translation>
-<translation id="307329814453917357">Proponi di tradurre le pagine utilizzando Google Traduttore</translation>
 <translation id="3089395242580810162">Apri in scheda in incognito</translation>
 <translation id="3090193911106258841">Accesso all'input audio e video in corso</translation>
 <translation id="3117051980354074377">Accedi a Chrome per trovare i tuoi preferiti degli altri dispositivi.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Pagine</translation>
 <translation id="4996978546172906250">Condividi tramite</translation>
 <translation id="5000922062037820727">Bloccata (opzione consigliata)</translation>
+<translation id="5005498671520578047">Copia password</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Consenti</translation>
 <translation id="5040262127954254034">Privacy</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Trascina dall'alto e tocca il pulsante Indietro per uscire dalla modalità a schermo intero.</translation>
 <translation id="5284584623296338184">Le modifiche ai preferiti, alla cronologia, alle password e ad altre impostazioni non verranno più sincronizzate con il tuo account Google. Tuttavia, i dati esistenti rimarranno memorizzati.</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">Lingua</translation>
 <translation id="5304593522240415983">Questo campo non può essere vuoto</translation>
 <translation id="5308380583665731573">Connessione</translation>
+<translation id="5308603654685598744">Quando questa funzione è attiva, Chrome propone di tradurre le pagine scritte in altre lingue con Google Traduttore.</translation>
 <translation id="5313967007315987356">Aggiungi sito</translation>
 <translation id="5317780077021120954">Salva</translation>
 <translation id="5324858694974489420">Impostazioni controllo genitori</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Se utilizzi questa applicazione, accetti i <ph name="BEGIN_LINK1" />Termini di servizio<ph name="END_LINK1" /> e l'<ph name="BEGIN_LINK2" />Informativa sulla privacy<ph name="END_LINK2" /> di Chrome.</translation>
 <translation id="5414836363063783498">Verifica…</translation>
 <translation id="5423934151118863508">Le pagine che visiti più spesso verranno visualizzate qui</translation>
-<translation id="5424715742813396254">Modifica nome/password salvati o eccezione</translation>
 <translation id="5437003064129843501">Al momento i suggerimenti personalizzati sui contenuti sono disattivati poiché i tuoi dati sincronizzati sono protetti da una passphrase personalizzata.</translation>
 <translation id="544291274896356069">Se apri questo link in un'applicazione esterna uscirai dalla modalità di navigazione in incognito. Continuare?</translation>
 <translation id="5447201525962359567">Tutta la memoria utilizzata da siti, tra cui cookie e altri dati memorizzati in locale</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Tutti i siti</translation>
 <translation id="6320088164292336938">Vibrazione</translation>
 <translation id="6324034347079777476">Sincronizzazione del sistema Android non attiva</translation>
-<translation id="6324360525379265737">Viene stabilita automaticamente la codifica dei caratteri</translation>
 <translation id="6333140779060797560">Condividi tramite <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Crittografia</translation>
 <translation id="6364438453358674297">Rimuovere il suggerimento dalla cronologia?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Cancella</translation>
 <translation id="6647073004883890710">Vuoi che <ph name="PASSWORD_MANAGER_BRAND" /> aggiorni la password di questo sito per l'account <ph name="USERNAME" />?</translation>
 <translation id="6656545060687952787">Chrome ha bisogno dell'accesso alla posizione per cercare dispositivi. <ph name="BEGIN_LINK" />Aggiorna le autorizzazioni<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Password</translation>
 <translation id="6659594942844771486">TAB</translation>
 <translation id="666268767214822976">Utilizza un servizio di previsione per visualizzare query correlate e siti web popolari durante la digitazione nella barra degli indirizzi</translation>
 <translation id="666981079809192359">Informativa sulla privacy di Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">La tua connessione a questo sito è privata, ma qualcuno in rete potrebbe riuscire a cambiare l'aspetto della pagina.</translation>
 <translation id="8493948351860045254">Libera spazio</translation>
 <translation id="8497726226069778601">Qui non c'è ancora niente</translation>
+<translation id="8503813439785031346">Nome utente</translation>
 <translation id="8514577642972634246">Accedi alla modalità di navigazione in incognito</translation>
 <translation id="8518901949365209398">Questo sito utilizza una configurazione di sicurezza poco efficace (firme basate sull'algoritmo SHA-1), pertanto la tua connessione potrebbe non risultare privata.</translation>
 <translation id="8525306231823319788">Schermo intero</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb b/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb
index 00fdc361..1d0959a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">סימניות והיסטוריית אתרים</translation>
 <translation id="1549000191223877751">העבר לחלון האחר</translation>
 <translation id="1553358976309200471">‏עדכן את Chrome</translation>
-<translation id="1557201757634521564">זיהוי אוטומטי של קידוד</translation>
 <translation id="1612196535745283361">‏כדי לבצע סריקה לאיתור מכשירים, Chrome זקוק לגישה לנתוני מיקום. הגישה למיקום <ph name="BEGIN_LINK" />כבויה במכשיר הזה<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">מצלמה</translation>
 <translation id="1623104350909869708">מנע מהדף זה ליצור תיבות דו-שיח נוספות</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">ביטויי הסיסמה אינם תואמים</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />קבל עזרה<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">שמור סרטון</translation>
-<translation id="307329814453917357">‏הצע לתרגם דפים באמצעות Google Translate</translation>
 <translation id="3089395242580810162">פתח בכרטיסיית גלישה בסתר</translation>
 <translation id="3090193911106258841">גישה לקלט אודיו ווידאו</translation>
 <translation id="3117051980354074377">‏כדי לקבל את הסימניות מהמכשירים האחרים שלך, היכנס ל-Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">דפים</translation>
 <translation id="4996978546172906250">שתף באמצעות</translation>
 <translation id="5000922062037820727">חסומה (מומלץ)</translation>
+<translation id="5005498671520578047">העתק סיסמה</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">אפשר</translation>
 <translation id="5040262127954254034">פרטיות</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">כדי לצאת ממסך מלא, גרור מלמעלה וגע בלחצן 'הקודם'.</translation>
 <translation id="5284584623296338184">‏שינויים בסימניות, בהיסטוריה, בסיסמאות ובהגדרות נוספות לא יסונכרנו עוד עם חשבון Google. עם זאת, הנתונים הקיימים עדיין יאוחסנו בחשבון Google שלך.</translation>
 <translation id="5301954838959518834">בסדר גמור, הבנתי</translation>
-<translation id="5302048478445481009">שפה</translation>
 <translation id="5304593522240415983">שדה זה לא יכול להיות ריק</translation>
 <translation id="5308380583665731573">התחברות</translation>
+<translation id="5308603654685598744">‏כשהתכונה הזו פועלת, Chrome יציע לתרגם באמצעות Google Translate דפים הכתובים בשפות אחרות.</translation>
 <translation id="5313967007315987356">הוסף אתר</translation>
 <translation id="5317780077021120954">שמור</translation>
 <translation id="5324858694974489420">הגדרות הורים</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">‏בעצם השימוש באפליקציה זו, אתה מסכים ל<ph name="BEGIN_LINK1" />תנאים ולהגבלות<ph name="END_LINK1" /> ול<ph name="BEGIN_LINK2" />הודעת הפרטיות<ph name="END_LINK2" /> של Chrome.</translation>
 <translation id="5414836363063783498">מאמת…</translation>
 <translation id="5423934151118863508">הדפים שבהם אתה מבקר בתדירות הגבוהה ביותר יופיעו כאן</translation>
-<translation id="5424715742813396254">ערוך שם/סיסמה או חריג שנשמרו</translation>
 <translation id="5437003064129843501">המלצות לתוכן בהתאמה אישית מושבתות כרגע, מפני שהנתונים המסונכרנים שלך מוגנים באמצעות ביטוי סיסמה מותאם אישית.</translation>
 <translation id="544291274896356069">פתיחת הקישור הזה ביישום חיצוני תוציא אותך ממצב גלישה בסתר. האם להמשיך?</translation>
 <translation id="5447201525962359567">‏כל נתוני האתר המאוחסנים, כולל קובצי Cookie ונתונים אחרים המאוחסנים באופן מקומי</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">כל האתרים</translation>
 <translation id="6320088164292336938">רטט</translation>
 <translation id="6324034347079777476">‏סנכרון מערכת Android מושבת</translation>
-<translation id="6324360525379265737">קביעה אוטומטית של קידוד תווים</translation>
 <translation id="6333140779060797560">שתף באמצעות <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">הצפנה</translation>
 <translation id="6364438453358674297">האם להסיר את ההצעה מההיסטוריה?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">נקה</translation>
 <translation id="6647073004883890710">האם אתה רוצה ש-<ph name="PASSWORD_MANAGER_BRAND" /> יעדכן את הסיסמה של <ph name="USERNAME" /> באתר הזה?</translation>
 <translation id="6656545060687952787">‏כדי לבצע סריקה לאיתור מכשירים ב-Chrome, יש צורך בגישה לנתוני מיקום. <ph name="BEGIN_LINK" />עדכן הרשאות<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">סיסמה</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">השתמש בשירות חיזוי כדי להציג שאילתות קשורות ואתרים פופולריים תוך כדי ההקלדה בסרגל הכתובות</translation>
 <translation id="666981079809192359">‏הודעת הפרטיות של Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">החיבור שלך לאתר הזה הוא פרטי, אך ייתכן שמישהו ברשת יכול לשנות את המראה של הדף.</translation>
 <translation id="8493948351860045254">פנה שטח אחסון</translation>
 <translation id="8497726226069778601">אין מה לראות כאן… בינתיים</translation>
+<translation id="8503813439785031346">שם משתמש</translation>
 <translation id="8514577642972634246">עבור למצב גלישה בסתר</translation>
 <translation id="8518901949365209398">‏באתר הזה נעשה שימוש בתצורת אבטחה חלשה (חתימות SHA-1), כך שייתכן שהחיבור שלך לא יהיה פרטי.</translation>
 <translation id="8525306231823319788">מסך מלא</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
index 8c850287..a2baa2e6 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">ブックマークとウェブ履歴</translation>
 <translation id="1549000191223877751">他のウィンドウに移動</translation>
 <translation id="1553358976309200471">Chrome を更新</translation>
-<translation id="1557201757634521564">エンコードを自動検出する</translation>
 <translation id="1612196535745283361">Chrome ではデバイスをスキャンするために現在地情報にアクセスする必要があります。現在地情報へのアクセスは<ph name="BEGIN_LINK" />この端末でオフになっています<ph name="END_LINK" />。</translation>
 <translation id="1620510694547887537">カメラ</translation>
 <translation id="1623104350909869708">このページで追加のダイアログが作成されないようにする</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">パスフレーズが一致しません</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />ヘルプ<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">動画を保存</translation>
-<translation id="307329814453917357">Google 翻訳を使ってページを翻訳するかどうかを尋ねます</translation>
 <translation id="3089395242580810162">シークレット タブで開く</translation>
 <translation id="3090193911106258841">音声 / ビデオ入力にアクセスしています</translation>
 <translation id="3117051980354074377">他の端末と同じブックマークを使用するには Chrome にログインします。</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">ページ</translation>
 <translation id="4996978546172906250">共有方法</translation>
 <translation id="5000922062037820727">ブロック(推奨)</translation>
+<translation id="5005498671520578047">パスワードのコピー</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">許可</translation>
 <translation id="5040262127954254034">プライバシー</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">全画面表示を終了するには、上からドラッグして、戻るボタンをタップします。</translation>
 <translation id="5284584623296338184">今後、ブックマーク、履歴、パスワードなどの設定への変更は Google アカウントに同期されません。ただし、既存のデータは Google アカウントに保存されたままとなります。</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">言語</translation>
 <translation id="5304593522240415983">この項目は必須です</translation>
 <translation id="5308380583665731573">接続</translation>
+<translation id="5308603654685598744">この機能を有効にすると、外国語のページで翻訳ツールが表示されます。</translation>
 <translation id="5313967007315987356">サイトを追加</translation>
 <translation id="5317780077021120954">保存</translation>
 <translation id="5324858694974489420">保護者設定</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">このアプリケーションを使用すると、Chrome の<ph name="BEGIN_LINK1" />利用規約<ph name="END_LINK1" />と<ph name="BEGIN_LINK2" />プライバシーに関するお知らせ<ph name="END_LINK2" />に同意したことになります。</translation>
 <translation id="5414836363063783498">確認しています…</translation>
 <translation id="5423934151118863508">最もアクセスの多かったページがここに表示されます</translation>
-<translation id="5424715742813396254">保存した名前 / パスワードまたは例外の編集</translation>
 <translation id="5437003064129843501">同期データがカスタム パスフレーズで保護されているため、おすすめコンテンツの表示機能は現在無効になっています。</translation>
 <translation id="544291274896356069">このリンクを外部アプリケーションで開くと、シークレット モードが解除されます。続行しますか?</translation>
 <translation id="5447201525962359567">すべてのサイトのストレージ(Cookie やローカルに保存した他のデータを含む)</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">すべてのサイト</translation>
 <translation id="6320088164292336938">バイブレーション</translation>
 <translation id="6324034347079777476">Android システムの同期が無効です</translation>
-<translation id="6324360525379265737">文字エンコードを自動判定します</translation>
 <translation id="6333140779060797560"><ph name="APPLICATION" /> で共有します</translation>
 <translation id="6337234675334993532">暗号化</translation>
 <translation id="6364438453358674297">履歴から候補を削除しますか?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">クリア</translation>
 <translation id="6647073004883890710"><ph name="PASSWORD_MANAGER_BRAND" /> に保存されているこのサイトの <ph name="USERNAME" /> のパスワードを更新しますか?</translation>
 <translation id="6656545060687952787">デバイスをスキャンするには、Chrome で位置情報にアクセスする必要があります。<ph name="BEGIN_LINK" />権限を更新<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">パスワード</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">予測サービスを使用し、アドレスバーへの入力時に関連性の高い検索キーワードや人気のウェブサイトを表示します</translation>
 <translation id="666981079809192359">Chrome のプライバシーに関するお知らせ</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">このサイトへの接続はプライベート接続です。ただし、ネットワーク上のユーザーがこのページのデザインを変更できる可能性はあります。</translation>
 <translation id="8493948351860045254">容量を空ける</translation>
 <translation id="8497726226069778601">表示するものがまだありません</translation>
+<translation id="8503813439785031346">ユーザー名</translation>
 <translation id="8514577642972634246">シークレット モードを開始</translation>
 <translation id="8518901949365209398">このサイトのセキュリティは弱いため(SHA-1 署名)、接続時にプライバシーが保護されない可能性があります。</translation>
 <translation id="8525306231823319788">全画面表示</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb
index cc3265d..1aad49a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">북마크 및 방문 기록</translation>
 <translation id="1549000191223877751">다른 창으로 이동</translation>
 <translation id="1553358976309200471">Chrome 업데이트</translation>
-<translation id="1557201757634521564">인코딩 자동 감지</translation>
 <translation id="1612196535745283361">기기를 스캔하려면 Chrome에서 위치 정보에 액세스해야 합니다. 위치 정보 액세스 권한이 <ph name="BEGIN_LINK" />이 기기에서 사용 중지<ph name="END_LINK" />되어 있습니다.</translation>
 <translation id="1620510694547887537">카메라</translation>
 <translation id="1623104350909869708">이 페이지가 추가적인 대화를 생성하지 않도록 차단</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">암호가 일치하지 않습니다.</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />도움 받기<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">동영상 저장</translation>
-<translation id="307329814453917357">Google 번역을 사용하여 페이지를 번역할 것을 제안합니다.</translation>
 <translation id="3089395242580810162">시크릿 탭에서 열기</translation>
 <translation id="3090193911106258841">오디오 및 비디오 입력 장치에 액세스</translation>
 <translation id="3117051980354074377">다른 기기에서 북마크를 가져오려면 Chrome에 로그인하세요.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">페이지</translation>
 <translation id="4996978546172906250">공유 방법</translation>
 <translation id="5000922062037820727">차단(권장)</translation>
+<translation id="5005498671520578047">비밀번호 복사</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">허용</translation>
 <translation id="5040262127954254034">개인정보</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">전체화면을 종료하려면 상단에서 드래그하여 뒤로 버튼을 터치하세요.</translation>
 <translation id="5284584623296338184">북마크, 방문 기록, 비밀번호, 기타 설정이 더 이상 Google 계정에 동기화되지 않습니다. 하지만 기존 데이터는 Google 계정에 계속 저장됩니다.</translation>
 <translation id="5301954838959518834">확인</translation>
-<translation id="5302048478445481009">언어</translation>
 <translation id="5304593522240415983">필수 입력란입니다.</translation>
 <translation id="5308380583665731573">연결</translation>
+<translation id="5308603654685598744">이 기능을 사용하도록 설정하면 Chrome에서 Google 번역을 사용하여 외국어로 작성된 페이지에 대한 번역을 제공합니다.</translation>
 <translation id="5313967007315987356">사이트 추가</translation>
 <translation id="5317780077021120954">저장</translation>
 <translation id="5324858694974489420">자녀 보호 설정</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">이 애플리케이션을 사용하면 Chrome의 <ph name="BEGIN_LINK1" />서비스 약관<ph name="END_LINK1" />과 <ph name="BEGIN_LINK2" />개인정보 보호정책<ph name="END_LINK2" />에 동의하게 됩니다.</translation>
 <translation id="5414836363063783498">확인 중...</translation>
 <translation id="5423934151118863508">자주 방문한 페이지가 여기에 표시됩니다.</translation>
-<translation id="5424715742813396254">저장된 이름/비밀번호 또는 예외 수정</translation>
 <translation id="5437003064129843501">동기화된 데이터가 맞춤 암호로 보호되고 있기 때문에 현재 맞춤 콘텐츠 추천을 사용할 수 없습니다.</translation>
 <translation id="544291274896356069">이 링크가 외부 애플리케이션에서 열리면 시크릿 모드가 종료됩니다. 계속하시겠습니까?</translation>
 <translation id="5447201525962359567">쿠키 및 기타 로컬에 저장된 데이터 등 모든 사이트 저장공간</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">모든 사이트</translation>
 <translation id="6320088164292336938">진동</translation>
 <translation id="6324034347079777476">Android 시스템 동기화 사용 안함</translation>
-<translation id="6324360525379265737">문자 인코딩을 자동으로 결정</translation>
 <translation id="6333140779060797560">공유 방법: <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">암호화</translation>
 <translation id="6364438453358674297">기록에서 제안을 삭제하시겠습니까?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">삭제</translation>
 <translation id="6647073004883890710"><ph name="PASSWORD_MANAGER_BRAND" />이(가) 이 사이트에서 <ph name="USERNAME" />의 비밀번호를 업데이트하도록 하시겠습니까?</translation>
 <translation id="6656545060687952787">기기를 스캔하려면 Chrome에서 위치 정보에 액세스해야 합니다. <ph name="BEGIN_LINK" />권한 업데이트<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">비밀번호</translation>
 <translation id="6659594942844771486">탭</translation>
 <translation id="666268767214822976">예상 검색어 서비스를 사용하여 검색주소창에 입력할 때 관련 검색어 및 인기 웹사이트를 표시합니다.</translation>
 <translation id="666981079809192359">Chrome 개인정보 보호정책</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">이 사이트에 대한 연결은 비공개지만 네트워크에 있는 다른 사람은 페이지 디자인을 변경할 수 있습니다.</translation>
 <translation id="8493948351860045254">저장 공간 확보하기</translation>
 <translation id="8497726226069778601">아직 표시할 내용 없음</translation>
+<translation id="8503813439785031346">사용자이름</translation>
 <translation id="8514577642972634246">시크릿 모드로 들어가기</translation>
 <translation id="8518901949365209398">이 사이트는 취약한 보안 설정(SHA-1 서명)을 사용하기 때문에 연결이 비공개로 설정되지 않을 수 있습니다.</translation>
 <translation id="8525306231823319788">전체화면</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb b/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb
index 252eafa3..3e57ea8 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Žymių ir žiniatinklio istorija</translation>
 <translation id="1549000191223877751">Perkelti į kitą langą</translation>
 <translation id="1553358976309200471">Atnaujinkite „Chrome“</translation>
-<translation id="1557201757634521564">Automatiškai aptikti koduotę</translation>
 <translation id="1612196535745283361">„Chrome“ reikalinga prieiga prie informacijos apie vietovę, kad galėtų nuskaityti įrenginius. Galimybė pasiekti informaciją apie vietovę <ph name="BEGIN_LINK" />išjungta šiame įrenginyje<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Neleisti šiam puslapiui kurti papildomų dialogo langų</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Slaptafrazės neatitinka</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Gaukite pagalbos<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Išsaugoti vaizdo įrašą</translation>
-<translation id="307329814453917357">Siūlyti versti puslapius naudojant „Google“ vertėją</translation>
 <translation id="3089395242580810162">Atidaryti inkognito skirtuko lape</translation>
 <translation id="3090193911106258841">Pasiekiama garso ir vaizdo įrašų įvestis</translation>
 <translation id="3117051980354074377">Prisijunkite prie „Chrome“, kad pasiektumėte žymes iš kitų įrenginių.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Psl.</translation>
 <translation id="4996978546172906250">Bendrinti per</translation>
 <translation id="5000922062037820727">Užblokuota (rekomenduojama)</translation>
+<translation id="5005498671520578047">Kopijuoti slaptažodį</translation>
 <translation id="5016205925109358554">Su užraitais</translation>
 <translation id="5039804452771397117">Leisti</translation>
 <translation id="5040262127954254034">Privatumas</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Vilkite žymeklį nuo viršaus ir palieskite mygtuką „Atgal“, kad išeitumėte iš viso ekrano režimo.</translation>
 <translation id="5284584623296338184">Žymių, istorijos, slaptažodžių ir kitų nustatymų pakeitimai nebebus sinchronizuojami su „Google“ paskyra. Tačiau esami duomenys ir toliau bus saugomi „Google“ paskyroje.</translation>
 <translation id="5301954838959518834">Gerai, supratau</translation>
-<translation id="5302048478445481009">Kalba</translation>
 <translation id="5304593522240415983">Šis laukas negali būti tuščias</translation>
 <translation id="5308380583665731573">Prisijungti</translation>
+<translation id="5308603654685598744">Kai ši funkcija įjungta, „Chrome“ siūlo versti kita kalba parašytus puslapius naudojant „Google“ vertėją.</translation>
 <translation id="5313967007315987356">Pridėti svetainę</translation>
 <translation id="5317780077021120954">Išsaugoti</translation>
 <translation id="5324858694974489420">Tėvų nustatymai</translation>
@@ -382,8 +381,6 @@
 <translation id="5400569084694353794">Naudodami šią programą sutinkate su „Chrome“ <ph name="BEGIN_LINK1" />paslaugų teikimo sąlygomis<ph name="END_LINK1" /> ir <ph name="BEGIN_LINK2" />privatumo pranešimo<ph name="END_LINK2" /> sąlygomis.</translation>
 <translation id="5414836363063783498">Patvirtinama…</translation>
 <translation id="5423934151118863508">Puslapiai, kuriuose lankomasi dažniausiai, bus rodomi čia</translation>
-<translation id="5424715742813396254">Išs. vardo, slaptaž. ar išimt. red. 
-</translation>
 <translation id="5437003064129843501">Suasmeninto turinio pasiūlymai šiuo metu išjungti, nes jūsų sinchronizuojami duomenys apsaugoti taikant tinkintą slaptafrazę.</translation>
 <translation id="544291274896356069">Atidarydami šią nuorodą išorinėje programoje, išjungsite inkognito režimą. Tęsti?</translation>
 <translation id="5447201525962359567">Visa svetainės saugykla, įskaitant slapukus ir kitus vietoje saugomus duomenis</translation>
@@ -463,7 +460,6 @@
 <translation id="6295158916970320988">Visos svetainės</translation>
 <translation id="6320088164292336938">Vibruoti</translation>
 <translation id="6324034347079777476">„Android“ sistemos sinchronizavimas išjungtas</translation>
-<translation id="6324360525379265737">Automatiškai nustatyti ženklų koduotę</translation>
 <translation id="6333140779060797560">Bendrinti per „<ph name="APPLICATION" />“</translation>
 <translation id="6337234675334993532">Šifruotė</translation>
 <translation id="6364438453358674297">Pašalinti pasiūlymą iš istorijos?</translation>
@@ -496,6 +492,7 @@
 <translation id="6643016212128521049">Išvalyti</translation>
 <translation id="6647073004883890710">Ar norite, kad „<ph name="PASSWORD_MANAGER_BRAND" />“ atnaujintų šios svetainės <ph name="USERNAME" /> slaptažodį?</translation>
 <translation id="6656545060687952787">„Chrome“ reikalinga prieiga prie vietos, kad galėtų nuskaityti įrenginius. <ph name="BEGIN_LINK" />Atnaujinkite leidimus<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Slaptažodis</translation>
 <translation id="6659594942844771486">Skirtukas</translation>
 <translation id="666268767214822976">Naudoti numatymo paslaugą, kad adreso juostoje įvedant tekstą būtų rodomos susijusios užklausos ir populiarios svetainės</translation>
 <translation id="666981079809192359">„Chrome“ privatumo pranešimas</translation>
@@ -657,6 +654,7 @@
 <translation id="8481940801237642152">Jūsų ryšys su šia svetaine privatus, bet gali būti, kad kitas asmuo tinkle gali pakeisti puslapio išvaizdą.</translation>
 <translation id="8493948351860045254">Atlaisvinti vietos</translation>
 <translation id="8497726226069778601">Čia dar nėra nieko, ką galėtumėte peržiūrėti…</translation>
+<translation id="8503813439785031346">Vartotojo vardas</translation>
 <translation id="8514577642972634246">Įjungti inkognito režimą</translation>
 <translation id="8518901949365209398">Šioje svetainėje naudojama nesudėtinga saugos konfigūracija („SHA-1“ parašai), todėl ryšys gali nebūti privatus.</translation>
 <translation id="8525306231823319788">Viso ekrano režimas</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb b/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb
index 8a61b205..20977df 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Grāmatzīmes un tīmekļa vēsture</translation>
 <translation id="1549000191223877751">Pārvietot uz citu logu</translation>
 <translation id="1553358976309200471">Atjaunināt Chrome</translation>
-<translation id="1557201757634521564">Kodējuma automātiska noteikšana</translation>
 <translation id="1612196535745283361">Lai meklētu ierīces, pārlūkam Chrome ir nepieciešama piekļuve atrašanās vietas datiem. <ph name="BEGIN_LINK" />Šajā ierīcē ir izslēgta piekļuve atrašanās vietas datiem<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Neļaut šai lapai veidot papildu dialoglodziņus</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Ieejas frāzes neatbilst.</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Saņemt palīdzību<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Saglabāt videoklipu</translation>
-<translation id="307329814453917357">Piedāvāt lapu tulkošanu, izmantojot Google tulkotāju</translation>
 <translation id="3089395242580810162">Atvērt inkognito režīma cilnē</translation>
 <translation id="3090193911106258841">Notiek piekļūšana audio un video ievadei</translation>
 <translation id="3117051980354074377">Pierakstieties pārlūkā Chrome, lai būtu pieejamas grāmatzīmes no citām jūsu ierīcēm.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Lapas</translation>
 <translation id="4996978546172906250">Kopīgošanas veids:</translation>
 <translation id="5000922062037820727">Bloķēta (ieteicams)</translation>
+<translation id="5005498671520578047">Paroles kopēšana</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Atļaut</translation>
 <translation id="5040262127954254034">Konfidencialitāte</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Lai izietu no pilnekrāna režīma, velciet no augšas un pieskarieties pogai Atpakaļ.</translation>
 <translation id="5284584623296338184">Grāmatzīmju, vēstures, paroļu un citu iestatījumu izmaiņas vairs netiks sinhronizētas ar jūsu Google kontu. Tomēr esošie dati joprojām tiks glabāti jūsu Google kontā.</translation>
 <translation id="5301954838959518834">Es sapratu</translation>
-<translation id="5302048478445481009">Valoda</translation>
 <translation id="5304593522240415983">Šis lauks nevar būt tukšs.</translation>
 <translation id="5308380583665731573">Pievienošana</translation>
+<translation id="5308603654685598744">Ja šī funkcija ir ieslēgta, Chrome piedāvā tulkot citās valodās rakstītas lapas, izmantojot Google tulkotāju.</translation>
 <translation id="5313967007315987356">Pievienot vietni</translation>
 <translation id="5317780077021120954">Saglabāt</translation>
 <translation id="5324858694974489420">Vecāku iestatījumi</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Izmantojot šo lietojumprogrammu, jūs piekrītat Chrome <ph name="BEGIN_LINK1" />pakalpojumu sniegšanas noteikumiem<ph name="END_LINK1" /> un <ph name="BEGIN_LINK2" />konfidencialitātes paziņojumam<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Notiek verifikācija...</translation>
 <translation id="5423934151118863508">Šeit tiks parādītas jūsu visvairāk apmeklētās lapas.</translation>
-<translation id="5424715742813396254">Saglabātā vārda/paroles vai izņēmuma rediģēšana</translation>
 <translation id="5437003064129843501">Personalizēta satura ieteikumi pašlaik ir atspējoti, jo jūsu sinhronizētie dati tiek aizsargāti ar pielāgotu ieejas frāzi.</translation>
 <translation id="544291274896356069">Atverot šo saiti ārējā lietojumprogrammā, tiks aizvērts inkognito režīms. Vai turpināt?</translation>
 <translation id="5447201525962359567">Visa vietnes krātuve, tostarp sīkfaili un citi lokāli saglabāti dati</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Visas vietnes</translation>
 <translation id="6320088164292336938">Vibrācija</translation>
 <translation id="6324034347079777476">Android sistēmas sinhronizācija atspējota</translation>
-<translation id="6324360525379265737">Automātiski noteikt rakstzīmju kodējumu</translation>
 <translation id="6333140779060797560">Kopīgot, izmantojot <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Šifrēšana</translation>
 <translation id="6364438453358674297">Vai noņemt ieteikumu no vēstures?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Notīrīt</translation>
 <translation id="6647073004883890710">Vai vēlaties, lai <ph name="PASSWORD_MANAGER_BRAND" /> atjauninātu lietotāja <ph name="USERNAME" /> paroli šai vietnei?</translation>
 <translation id="6656545060687952787">Lai meklētu ierīces, pārlūkam Chrome ir nepieciešama piekļuve atrašanās vietai. <ph name="BEGIN_LINK" />Atjauniniet atļaujas<ph name="END_LINK" />.</translation>
+<translation id="6657585470893396449">Parole</translation>
 <translation id="6659594942844771486">Cilne</translation>
 <translation id="666268767214822976">Izmantojiet ieteikumus, lai skatītu saistītos vaicājumus un populāras vietnes, kad rakstāt adreses joslā.</translation>
 <translation id="666981079809192359">Chrome konfidencialitātes paziņojums</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Jūsu savienojums ar šo vietni ir privāts, taču kāds, kurš ir tīklā, var mainīt lapas izskatu.</translation>
 <translation id="8493948351860045254">Atbrīvot vietu</translation>
 <translation id="8497726226069778601">Šeit vēl nekā nav...</translation>
+<translation id="8503813439785031346">Lietotājvārds</translation>
 <translation id="8514577642972634246">Atvērt inkognito režīmā</translation>
 <translation id="8518901949365209398">Šajā vietnē tiek izmantota nedroša aizsardzības konfigurācija (SHA-1 paraksti), tādējādi jūsu savienojums var nebūt privāts.</translation>
 <translation id="8525306231823319788">Pilnekrāna režīms</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb b/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb
index 86b8e74..1f960d0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bladwijzers en webgeschiedenis</translation>
 <translation id="1549000191223877751">Naar ander venster</translation>
 <translation id="1553358976309200471">Chrome updaten</translation>
-<translation id="1557201757634521564">Codering automatisch detecteren</translation>
 <translation id="1612196535745283361">Chrome heeft locatietoegang nodig om naar apparaten te scannen. Locatietoegang is <ph name="BEGIN_LINK" />uitgeschakeld voor dit apparaat<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Camera</translation>
 <translation id="1623104350909869708">Voorkomen dat deze pagina extra dialoogvensters weergeeft</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Wachtwoordzinnen komen niet overeen</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Hulp krijgen<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Video opslaan</translation>
-<translation id="307329814453917357">Aanbieden pagina's te vertalen met Google Translate</translation>
 <translation id="3089395242580810162">Openen op incognitotabblad</translation>
 <translation id="3090193911106258841">Audio- en video-invoer openen</translation>
 <translation id="3117051980354074377">Log in bij Chrome om de bladwijzers van je andere apparaten te bekijken.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Pagina's</translation>
 <translation id="4996978546172906250">Delen via</translation>
 <translation id="5000922062037820727">Geblokkeerd (aanbevolen)</translation>
+<translation id="5005498671520578047">Wachtwoord kopiëren</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Toestaan</translation>
 <translation id="5040262127954254034">Privacy</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Sleep vanaf de bovenkant en tik op de knop Terug om het volledige scherm te sluiten.</translation>
 <translation id="5284584623296338184">Wijzigingen in je bladwijzers, geschiedenis, wachtwoorden en andere instellingen worden niet meer gesynchroniseerd met je Google-account. Je bestaande gegevens blijven echter opgeslagen in je Google-account.</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">Taal</translation>
 <translation id="5304593522240415983">Dit veld mag niet leeg zijn</translation>
 <translation id="5308380583665731573">Verbinding maken</translation>
+<translation id="5308603654685598744">Wanneer deze functie is ingeschakeld, biedt Chrome aan pagina's die zijn geschreven in andere talen, te vertalen met Google Translate.</translation>
 <translation id="5313967007315987356">Site toevoegen</translation>
 <translation id="5317780077021120954">Opslaan</translation>
 <translation id="5324858694974489420">Instellingen voor ouders</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Als je deze app gebruikt, ga je akkoord met de <ph name="BEGIN_LINK1" />Servicevoorwaarden<ph name="END_LINK1" /> en het <ph name="BEGIN_LINK2" />Privacybeleid<ph name="END_LINK2" /> van Chrome.</translation>
 <translation id="5414836363063783498">Verifiëren…</translation>
 <translation id="5423934151118863508">Je meest bezochte pagina's worden hier weergegeven</translation>
-<translation id="5424715742813396254">Opgeslagen naam/wachtwoord of uitzondering bewerken</translation>
 <translation id="5437003064129843501">Je ontvangt momenteel geen suggesties voor gepersonaliseerde content, omdat je gesynchroniseerde gegevens zijn beveiligd met een wachtwoordzin.</translation>
 <translation id="544291274896356069">Je verlaat de incognitomodus als deze link wordt geopend in een externe app. Doorgaan?</translation>
 <translation id="5447201525962359567">Alle site-opslag, inclusief cookies en andere lokaal opgeslagen gegevens</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Alle sites</translation>
 <translation id="6320088164292336938">Trillen</translation>
 <translation id="6324034347079777476">Systeemsynchronisatie van Android uitgeschakeld</translation>
-<translation id="6324360525379265737">Tekencodering automatisch detecteren</translation>
 <translation id="6333140779060797560">Delen via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Codering</translation>
 <translation id="6364438453358674297">Suggestie verwijderen uit geschiedenis?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Wissen</translation>
 <translation id="6647073004883890710">Wil je dat <ph name="PASSWORD_MANAGER_BRAND" /> het wachtwoord voor <ph name="USERNAME" /> updatet voor deze site?</translation>
 <translation id="6656545060687952787">Chrome heeft locatietoegang nodig om naar apparaten te zoeken. <ph name="BEGIN_LINK" />Rechten updaten<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Wachtwoord</translation>
 <translation id="6659594942844771486">Tabblad</translation>
 <translation id="666268767214822976">Een voorspellingsservice gebruiken om gerelateerde zoekopdrachten en populaire websites te tonen terwijl je in de adresbalk typt</translation>
 <translation id="666981079809192359">Privacybeleid van Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Je verbinding met deze site is privé, maar iemand op het netwerk kan mogelijk het uiterlijk van de pagina wijzigen.</translation>
 <translation id="8493948351860045254">Ruimte vrijmaken</translation>
 <translation id="8497726226069778601">Hier is nog niets te zien</translation>
+<translation id="8503813439785031346">Gebruikersnaam</translation>
 <translation id="8514577642972634246">Incognitomodus starten</translation>
 <translation id="8518901949365209398">Deze site gebruikt een zwakke beveiligingsconfiguratie (SHA-1-handtekeningen), dus je verbinding is mogelijk niet privé.</translation>
 <translation id="8525306231823319788">Volledig scherm</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_no.xtb b/chrome/android/java/strings/translations/android_chrome_strings_no.xtb
index a40bdde..229c006 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_no.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_no.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bokmerker og nettlogg</translation>
 <translation id="1549000191223877751">Flytt til det andre vinduet</translation>
 <translation id="1553358976309200471">Oppdater Chrome</translation>
-<translation id="1557201757634521564">Gjenkjenn omgjøring til kode automatisk</translation>
 <translation id="1612196535745283361">Chrome trenger posisjonstilgang for å søke etter enheter. Posisjonstilgang er <ph name="BEGIN_LINK" />slått av for denne enheten<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Hindre denne siden i å opprette flere dialogruter</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Passordfrasene stemmer ikke overens</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Få hjelp<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Lagre videoen</translation>
-<translation id="307329814453917357">Tilby oversettelse av nettsider ved hjelp av Google Oversetter</translation>
 <translation id="3089395242580810162">Åpne i inkognitofane</translation>
 <translation id="3090193911106258841">Åpner lyd- og videoinngang</translation>
 <translation id="3117051980354074377">For å få bokmerkene dine fra de andre enhetene du bruker, logg på Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Sider</translation>
 <translation id="4996978546172906250">Del via</translation>
 <translation id="5000922062037820727">Blokkert (anbefales)</translation>
+<translation id="5005498671520578047">Kopiér passordet</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Tillat</translation>
 <translation id="5040262127954254034">Personvern</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Dra ned fra toppen og trykk på tilbakeknappen for å avslutte fullskjerm.</translation>
 <translation id="5284584623296338184">Endringer i bokmerker, loggoppføringer, passord og andre innstillinger blir ikke synkronisert med Google-kontoen din lenger. Data som allerede er lagret i Google-kontoen din, blir imidlertid ikke fjernet.</translation>
 <translation id="5301954838959518834">OK, skjønner</translation>
-<translation id="5302048478445481009">Språk</translation>
 <translation id="5304593522240415983">Dette feltet må fylles ut</translation>
 <translation id="5308380583665731573">Koble til</translation>
+<translation id="5308603654685598744">Når denne funksjonen er slått på, blir du spurt om du vil at Chrome skal bruke Google Oversetter til å oversette sider som er skrevet på andre språk.</translation>
 <translation id="5313967007315987356">Legg til et nettsted</translation>
 <translation id="5317780077021120954">Lagre</translation>
 <translation id="5324858694974489420">Foreldreinnstillinger</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Ved å bruke dette programmet samtykker du i Chromes <ph name="BEGIN_LINK1" />vilkår for bruk<ph name="END_LINK1" /> og <ph name="BEGIN_LINK2" />merknad om personvern<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Bekrefter …</translation>
 <translation id="5423934151118863508">Sidene du besøker mest, vises her</translation>
-<translation id="5424715742813396254">Rediger lagret navn/passord eller unntak</translation>
 <translation id="5437003064129843501">Forslag om personlig tilpasset innhold er for øyeblikket slått av, fordi de synkroniserte dataene dine er beskyttet med en egendefinert passordfrase.</translation>
 <translation id="544291274896356069">Inkognitomodus forlates hvis denne linken åpnes i et eksternt program. Vil du fortsette?</translation>
 <translation id="5447201525962359567">All nettstedslagring, inkludert informasjonskapsler og andre lokalt lagrede data</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Alle nettsteder</translation>
 <translation id="6320088164292336938">Vibrering</translation>
 <translation id="6324034347079777476">Synkronisering for Android-systemet er slått av</translation>
-<translation id="6324360525379265737">Fastslå tegnkoding automatisk</translation>
 <translation id="6333140779060797560">Del via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Kryptering</translation>
 <translation id="6364438453358674297">Vil du fjerne forslaget fra loggen?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Tøm</translation>
 <translation id="6647073004883890710">Vil du at <ph name="PASSWORD_MANAGER_BRAND" /> skal oppdatere passordet for <ph name="USERNAME" /> for dette nettstedet?</translation>
 <translation id="6656545060687952787">Chrome trenger posisjonstilgang for å søke etter enheter. <ph name="BEGIN_LINK" />Oppdater tillatelsene<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Passord</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Bruk en forslagstjeneste for å vise relaterte søkeord og populære nettsteder mens du skriver i adressefeltet</translation>
 <translation id="666981079809192359">Merknad om personvern for Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Tilkoblingen til dette området er privat, men det kan hende at noen på nettverket kan endre utseendet på siden.</translation>
 <translation id="8493948351860045254">Frigjør plass</translation>
 <translation id="8497726226069778601">Det er ikke noe her foreløpig</translation>
+<translation id="8503813439785031346">Brukernavn</translation>
 <translation id="8514577642972634246">Slå på inkognitomodus</translation>
 <translation id="8518901949365209398">Dette nettstedet bruker en svak sikkerhetskonfigurasjon (SHA-1-signaturer). Det kan derfor hende at tilkoblingen mellom deg og nettstedet ikke er privat.</translation>
 <translation id="8525306231823319788">Full skjerm</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb
index 63791e2..d847033b 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Zakładki i historia online</translation>
 <translation id="1549000191223877751">Przenieś do innego okna</translation>
 <translation id="1553358976309200471">Zaktualizuj Chrome</translation>
-<translation id="1557201757634521564">Automatycznie wykrywaj kodowanie</translation>
 <translation id="1612196535745283361">Aby wyszukać urządzenia, Chrome potrzebuje dostępu do lokalizacji. Dostęp jest <ph name="BEGIN_LINK" />wyłączony na tym urządzeniu<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Zapobiegaj wyświetlaniu dodatkowych okien dialogowych na tej stronie</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Hasła nie pasują do siebie</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Poproś o pomoc<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Zapisz film</translation>
-<translation id="307329814453917357">Proponuj tłumaczenie stron w Tłumaczu Google</translation>
 <translation id="3089395242580810162">Otwórz w karcie incognito</translation>
 <translation id="3090193911106258841">Otwieram wejście audio i wideo</translation>
 <translation id="3117051980354074377">Aby korzystać z zakładek ze swoich innych urządzeń, zaloguj się w Chrome.</translation>
@@ -203,7 +201,7 @@
 <translation id="3254409185687681395">Dodaj stronę do zakładek</translation>
 <translation id="326254929494722411">Konto Google nie zostało jeszcze skonfigurowane na tym urządzeniu</translation>
 <translation id="3269093882174072735">Wczytaj obraz</translation>
-<translation id="3269956123044984603">Aby korzystać z kart ze swoich pozostałych urządzeń, włącz „Autosynchronizację danych” w ustawieniach konta na urządzeniu z Androidem.</translation>
+<translation id="3269956123044984603">Aby korzystać z kart ze swoich pozostałych urządzeń, włącz opcję „Autosynchronizacja danych” w ustawieniach konta na urządzeniu z Androidem.</translation>
 <translation id="3278850099957560514">Zaoszczędź na transmisji danych dzięki optymalizacji stron przez Google. Google nie optymalizuje ani nie widzi stron, z którymi łączysz się przez HTTPS lub które przeglądasz na kartach incognito.</translation>
 <translation id="3282568296779691940">Zaloguj się w Chrome</translation>
 <translation id="3303414029551471755">Przejść do pobrania treści?</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Strony</translation>
 <translation id="4996978546172906250">Udostępnij przez</translation>
 <translation id="5000922062037820727">Zablokowane (zalecane)</translation>
+<translation id="5005498671520578047">Skopiuj hasło</translation>
 <translation id="5016205925109358554">Szeryfowa</translation>
 <translation id="5039804452771397117">Zezwalaj</translation>
 <translation id="5040262127954254034">Prywatność</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Przeciągnij od góry i kliknij przycisk Wstecz, by wyjść z trybu pełnoekranowego.</translation>
 <translation id="5284584623296338184">Zmiany w zakładkach, historii, hasłach i innych ustawieniach nie będą już synchronizowane z kontem Google. Twoje istniejące dane będą jednak nadal na nim przechowywane.</translation>
 <translation id="5301954838959518834">OK, rozumiem</translation>
-<translation id="5302048478445481009">Język</translation>
 <translation id="5304593522240415983">To pole nie może być puste</translation>
 <translation id="5308380583665731573">Połącz</translation>
+<translation id="5308603654685598744">Po włączeniu tej funkcji Chrome będzie proponować tłumaczenie stron w innych językach przez Tłumacza Google.</translation>
 <translation id="5313967007315987356">Dodaj stronę</translation>
 <translation id="5317780077021120954">Zapisz</translation>
 <translation id="5324858694974489420">Ustawienia rodzicielskie</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Korzystając z tej aplikacji, akceptujesz <ph name="BEGIN_LINK1" />Warunki korzystania z Chrome<ph name="END_LINK1" /> oraz <ph name="BEGIN_LINK2" />Informacje na temat ochrony prywatności w Chrome<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Weryfikuję…</translation>
 <translation id="5423934151118863508">Tu pojawią się strony, na które najczęściej wchodzisz</translation>
-<translation id="5424715742813396254">Edytuj zapisaną nazwę/hasło lub wyjątek</translation>
 <translation id="5437003064129843501">Personalizacja polecanych treści jest obecnie wyłączona, ponieważ synchronizowane dane są chronione niestandardowym hasłem.</translation>
 <translation id="544291274896356069">Jeśli otworzysz ten link w aplikacji zewnętrznej, opuścisz tryb incognito. Kontynuować?</translation>
 <translation id="5447201525962359567">Wszystkie dane witryn, w tym pliki cookie i inne dane lokalne</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Wszystkie witryny</translation>
 <translation id="6320088164292336938">Wibracje</translation>
 <translation id="6324034347079777476">Synchronizacja systemu Android jest wyłączona</translation>
-<translation id="6324360525379265737">Automatycznie rozpoznawaj kodowanie znaków</translation>
 <translation id="6333140779060797560">Udostępnij przez: <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Szyfrowanie</translation>
 <translation id="6364438453358674297">Usunąć sugestię z historii?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Wyczyść</translation>
 <translation id="6647073004883890710">Czy <ph name="PASSWORD_MANAGER_BRAND" /> ma zaktualizować hasło użytkownika <ph name="USERNAME" /> do tej witryny?</translation>
 <translation id="6656545060687952787">Aby wyszukać urządzenia, Chrome potrzebuje dostępu do lokalizacji. <ph name="BEGIN_LINK" />Zwiększ uprawnienia<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Hasło</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Gdy piszesz na pasku adresu, korzystaj z usługi przewidywania, by wyświetlać podobne zapytania i adresy popularnych stron</translation>
 <translation id="666981079809192359">Informacje na temat ochrony prywatności w Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Twoje połączenie z tą witryną jest prywatne, ale inna osoba w sieci może zmienić wygląd tej strony.</translation>
 <translation id="8493948351860045254">Zwolnij miejsce</translation>
 <translation id="8497726226069778601">Tu jeszcze niczego nie ma</translation>
+<translation id="8503813439785031346">Nazwa użytkownika</translation>
 <translation id="8514577642972634246">Włącz tryb incognito</translation>
 <translation id="8518901949365209398">Ta witryna używa słabej konfiguracji zabezpieczeń (podpisy SHA-1), więc połączenie może nie być poufne.</translation>
 <translation id="8525306231823319788">Pełny ekran</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
index 538db48b..56a2adf 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Favoritos e histórico da Web</translation>
 <translation id="1549000191223877751">Mover para outra janela</translation>
 <translation id="1553358976309200471">Atualizar o Google Chrome</translation>
-<translation id="1557201757634521564">Detectar codificação automaticamente</translation>
 <translation id="1612196535745283361">O Chrome precisa ter acesso ao local para verificar dispositivos. O acesso ao local está <ph name="BEGIN_LINK" />desativado neste dispositivo<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Câmera</translation>
 <translation id="1623104350909869708">Impedir que esta página crie caixas de diálogo adicionais</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">As senhas não correspondem</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Receber ajuda<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Salvar vídeo</translation>
-<translation id="307329814453917357">Oferecer para traduzir páginas usando o Google Tradutor</translation>
 <translation id="3089395242580810162">Abrir em guia anônima</translation>
 <translation id="3090193911106258841">Acessando entrada de áudio e vídeo</translation>
 <translation id="3117051980354074377">Para ver os favoritos dos seus outros dispositivos, faça login no Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Páginas</translation>
 <translation id="4996978546172906250">Compartilhar via</translation>
 <translation id="5000922062037820727">Bloqueada (recomendado)</translation>
+<translation id="5005498671520578047">Copiar senha</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Permitir</translation>
 <translation id="5040262127954254034">Privacidade</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Arraste a partir da parte superior e toque no botão "Voltar" para sair da tela cheia.</translation>
 <translation id="5284584623296338184">Alterações feitas nos seus favoritos, histórico, senhas e outras configurações não serão mais sincronizadas com sua Conta do Google. No entanto, os dados já existentes permanecerão armazenados na Conta do Google.</translation>
 <translation id="5301954838959518834">Entendi</translation>
-<translation id="5302048478445481009">Idioma</translation>
 <translation id="5304593522240415983">Este campo não pode ficar em branco</translation>
 <translation id="5308380583665731573">Conectar-se</translation>
+<translation id="5308603654685598744">Quando este recurso está ativado, o Google Chrome oferece a tradução de páginas escritas em outros idiomas usando o Google Tradutor.</translation>
 <translation id="5313967007315987356">Adicionar site</translation>
 <translation id="5317780077021120954">Salvar</translation>
 <translation id="5324858694974489420">Configurações parentais</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Ao usar este aplicativo, você concorda com os <ph name="BEGIN_LINK1" />Termos de Serviço<ph name="END_LINK1" /> e com o <ph name="BEGIN_LINK2" />Aviso de Privacidade<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Verificando...</translation>
 <translation id="5423934151118863508">Suas páginas mais visitadas aparecerão aqui</translation>
-<translation id="5424715742813396254">Editar nome/senha salvos ou exceção</translation>
 <translation id="5437003064129843501">As sugestões personalizadas de conteúdo estão desativadas no momento, pois seus dados sincronizados estão protegidos com uma senha personalizada.</translation>
 <translation id="544291274896356069">Se este link for aberto em um aplicativo externo, você sairá do modo de navegação anônima. Continuar?</translation>
 <translation id="5447201525962359567">Todos os dados de armazenamento de sites, incluindo cookies e outros dados armazenados localmente</translation>
@@ -461,7 +459,6 @@
 <translation id="6295158916970320988">Todos os sites</translation>
 <translation id="6320088164292336938">Vibrar</translation>
 <translation id="6324034347079777476">Sincronização do sistema Android desativada</translation>
-<translation id="6324360525379265737">Determinar automaticamente a codificação de caracteres</translation>
 <translation id="6333140779060797560">Compartilhar via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Criptografia</translation>
 <translation id="6364438453358674297">Remover sugestão do histórico?</translation>
@@ -494,6 +491,7 @@
 <translation id="6643016212128521049">Limpar</translation>
 <translation id="6647073004883890710">Deseja que <ph name="PASSWORD_MANAGER_BRAND" /> atualize a senha de <ph name="USERNAME" /> para este site?</translation>
 <translation id="6656545060687952787">O Chrome precisa de acesso ao local para procurar por dispositivos. <ph name="BEGIN_LINK" />Atualizar permissões<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Senha</translation>
 <translation id="6659594942844771486">Guia</translation>
 <translation id="666268767214822976">Usar um serviço de previsão para mostrar consultas relacionadas e sites populares quando você digitar na barra de endereços</translation>
 <translation id="666981079809192359">Aviso de Privacidade do Chrome</translation>
@@ -655,6 +653,7 @@
 <translation id="8481940801237642152">Sua conexão a este site é particular, mas alguém na rede pode conseguir alterar a aparência da página.</translation>
 <translation id="8493948351860045254">Liberar espaço</translation>
 <translation id="8497726226069778601">Não há nada para ver aqui... ainda</translation>
+<translation id="8503813439785031346">Nome de usuário</translation>
 <translation id="8514577642972634246">Entrar no modo de navegação anônima</translation>
 <translation id="8518901949365209398">Este site usa uma configuração de segurança fraca (assinaturas SHA-1). Portanto sua conexão pode não ser particular.</translation>
 <translation id="8525306231823319788">Tela cheia</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb
index 135ae04..7837c5f0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Marcadores e histórico da Web</translation>
 <translation id="1549000191223877751">Mover para outra janela</translation>
 <translation id="1553358976309200471">Atualizar o Chrome</translation>
-<translation id="1557201757634521564">Deteção automática de codificação</translation>
 <translation id="1612196535745283361">O Chrome precisa de acesso à localização para procurar dispositivos. O acesso à localização está <ph name="BEGIN_LINK" />desativado para este dispositivo<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Câmara</translation>
 <translation id="1623104350909869708">Evitar que esta página crie caixas de diálogo adicionais</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">As frases de acesso não coincidem</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Obter ajuda<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Guardar vídeo</translation>
-<translation id="307329814453917357">Oferecer-se para traduzir páginas com o Google Tradutor</translation>
 <translation id="3089395242580810162">Abrir no separador anónimo</translation>
 <translation id="3090193911106258841">A aceder à entrada de áudio e de vídeo</translation>
 <translation id="3117051980354074377">Para obter os marcadores dos seus outros dispositivos, inicie sessão no Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Páginas </translation>
 <translation id="4996978546172906250">Partilhar através de</translation>
 <translation id="5000922062037820727">Bloqueado (recomendado)</translation>
+<translation id="5005498671520578047">Copiar palavra-passe</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Permitir</translation>
 <translation id="5040262127954254034">Privacidade</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Arraste a partir da parte superior e toque no botão de retrocesso para sair do ecrã inteiro.</translation>
 <translation id="5284584623296338184">As alterações aos marcadores, ao histórico, às palavras-passe e a outras definições deixam de ser sincronizadas com a Conta Google. Contudo, os dados existentes permanecem armazenados na Conta Google.</translation>
 <translation id="5301954838959518834">OK, já percebi</translation>
-<translation id="5302048478445481009">Idioma</translation>
 <translation id="5304593522240415983">Este campo não pode estar em branco</translation>
 <translation id="5308380583665731573">Ligar</translation>
+<translation id="5308603654685598744">Quando esta funcionalidade está ativada, o Chrome oferece a possibilidade de traduzir páginas escritas noutros idiomas com o Google Tradutor.</translation>
 <translation id="5313967007315987356">Adicionar site</translation>
 <translation id="5317780077021120954">Guardar</translation>
 <translation id="5324858694974489420">Definições parentais</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Ao utilizar esta aplicação, concorda com os <ph name="BEGIN_LINK1" />Termos de Utilização<ph name="END_LINK1" /> e o <ph name="BEGIN_LINK2" />Aviso de Privacidade<ph name="END_LINK2" /> do Chrome.</translation>
 <translation id="5414836363063783498">A validar…</translation>
 <translation id="5423934151118863508">As páginas mais visitadas aparecem aqui</translation>
-<translation id="5424715742813396254">Editar nome/palavra-passe guardada ou exceção</translation>
 <translation id="5437003064129843501">As sugestões de conteúdo personalizado estão atualmente desativadas porque os seus dados sincronizados estão protegidos por uma frase de acesso personalizada.</translation>
 <translation id="544291274896356069">Abandonar o modo de navegação anónima se este link estiver aberto numa aplicação externa. Deseja continuar?</translation>
 <translation id="5447201525962359567">Todo o armazenamento de sites, incluindo cookies e outros dados armazenados localmente</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Todos os sites</translation>
 <translation id="6320088164292336938">Vibrar</translation>
 <translation id="6324034347079777476">Sincronização do sistema Android desativada</translation>
-<translation id="6324360525379265737">Determinar a codificação de carateres automaticamente</translation>
 <translation id="6333140779060797560">Partilhar através de <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Encriptação</translation>
 <translation id="6364438453358674297">Pretende remover a sugestão do histórico?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Limpar</translation>
 <translation id="6647073004883890710">Pretende que o <ph name="PASSWORD_MANAGER_BRAND" /> atualize a palavra-passe de <ph name="USERNAME" /> para este site?</translation>
 <translation id="6656545060687952787">O Chrome necessita de acesso à localização para procurar dispositivos. <ph name="BEGIN_LINK" />Atualizar autorizações<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Palavra-passe</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Utilizar um serviço de previsão para mostrar consultas relacionadas e Websites populares à medida que escreve na barra de endereço</translation>
 <translation id="666981079809192359">Aviso de privacidade do Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">A sua ligação a este site é privada, mas alguém na rede pode estar a tentar alterar o aspeto da página.</translation>
 <translation id="8493948351860045254">Libertar espaço</translation>
 <translation id="8497726226069778601">Ainda não há nada para ver aqui</translation>
+<translation id="8503813439785031346">Nome de utilizador</translation>
 <translation id="8514577642972634246">Entrar no modo de navegação anónima</translation>
 <translation id="8518901949365209398">Este site utiliza uma configuração de segurança fraca (assinaturas SHA-1), pelo que a sua ligação pode não ser privada.</translation>
 <translation id="8525306231823319788">Ecrã inteiro</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb
index a669dba..179e7713 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Marcaje și istoric web</translation>
 <translation id="1549000191223877751">Mută în altă fereastră</translation>
 <translation id="1553358976309200471">Actualizează Chrome</translation>
-<translation id="1557201757634521564">Detectează automat codificarea</translation>
 <translation id="1612196535745283361">Chrome necesită accesul la locație pentru a căuta dispozitive. Accesul la locație este <ph name="BEGIN_LINK" />dezactivat pentru acest dispozitiv<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Camera</translation>
 <translation id="1623104350909869708">Restricționați capacitatea acestei pagini de a crea casete de dialog suplimentare</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Expresiile de acces nu corespund</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Obține ajutor<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Salvați videoclipul</translation>
-<translation id="307329814453917357">Oferă traducerea paginilor folosind Google Traducere</translation>
 <translation id="3089395242580810162">Deschideți într-o filă incognito</translation>
 <translation id="3090193911106258841">Se accesează intrările audio și video</translation>
 <translation id="3117051980354074377">Pentru a accesa marcajele de pe alte dispozitive, conectează-te la Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Pagini</translation>
 <translation id="4996978546172906250">Trimiteți prin</translation>
 <translation id="5000922062037820727">Blocată (recomandat)</translation>
+<translation id="5005498671520578047">Copiază parola</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Permite</translation>
 <translation id="5040262127954254034">Confidențialitate</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Trage din partea de sus și atinge butonul Înapoi pentru a ieși din ecranul complet.</translation>
 <translation id="5284584623296338184">Modificările marcajelor, istoricului, parolelor sau ale altor setări nu vor mai fi sincronizate cu Contul Google. Totuși, datele existente vor rămâne stocate în Contul Google.</translation>
 <translation id="5301954838959518834">OK, am înțeles</translation>
-<translation id="5302048478445481009">Limbă</translation>
 <translation id="5304593522240415983">Acest câmp trebuie completat</translation>
 <translation id="5308380583665731573">Conectează-te</translation>
+<translation id="5308603654685598744">Când această funcție este activată, Chrome se va oferi să traducă paginile scrise în alte limbi folosind Google Traducere.</translation>
 <translation id="5313967007315987356">Adaugă un site</translation>
 <translation id="5317780077021120954">Salvează</translation>
 <translation id="5324858694974489420">Setări parentale</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Folosind această aplicație, accepți <ph name="BEGIN_LINK1" />Termenii și condițiile<ph name="END_LINK1" /> și <ph name="BEGIN_LINK2" />Notificarea privind confidențialitatea<ph name="END_LINK2" /> Chrome.</translation>
 <translation id="5414836363063783498">Se verifică...</translation>
 <translation id="5423934151118863508">Cele mai accesate pagini vor apărea aici</translation>
-<translation id="5424715742813396254">Editează numele/parola sau excepția salvată</translation>
 <translation id="5437003064129843501">Momentan, sugestiile de conținut personalizat sunt dezactivate, deoarece datele sincronizate sunt protejate cu o expresie de acces personalizată.</translation>
 <translation id="544291274896356069">Vei părăsi modul incognito dacă acest link este deschis într-o aplicație externă. Continui?</translation>
 <translation id="5447201525962359567">Toată stocarea site-urilor, inclusiv cookie-urile și alte date stocate local</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Toate site-urile</translation>
 <translation id="6320088164292336938">Vibrații</translation>
 <translation id="6324034347079777476">Sincronizarea de sistem Android este dezactivată</translation>
-<translation id="6324360525379265737">Stabilește automat codificarea caracterelor</translation>
 <translation id="6333140779060797560">Trimiteți prin <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Criptare</translation>
 <translation id="6364438453358674297">Elimini sugestia din istoric?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Ștergeți</translation>
 <translation id="6647073004883890710">Dorești ca <ph name="PASSWORD_MANAGER_BRAND" /> să actualizeze parola pentru <ph name="USERNAME" /> de pe acest site?</translation>
 <translation id="6656545060687952787">Chrome necesită accesul la locație pentru a căuta dispozitive. <ph name="BEGIN_LINK" />Actualizează permisiunile<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Parolă</translation>
 <translation id="6659594942844771486">Filă</translation>
 <translation id="666268767214822976">Folosește un serviciu de predicții pentru a afișa interogări similare și site-uri populare în timp ce introduci text în bara de adrese.</translation>
 <translation id="666981079809192359">Notificare privind confidențialitatea Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Conexiunea la acest site este privată, dar cineva din rețea ar putea să schimbe aspectul paginii.</translation>
 <translation id="8493948351860045254">Eliberează spațiu</translation>
 <translation id="8497726226069778601">Nu este nimic de văzut aici... deocamdată</translation>
+<translation id="8503813439785031346">Nume utilizator</translation>
 <translation id="8514577642972634246">Intră în modul incognito</translation>
 <translation id="8518901949365209398">Acest site folosește o configurație de securitate slabă (semnături SHA-1), prin urmare, conexiunea poate să nu fie privată.</translation>
 <translation id="8525306231823319788">Ecran complet</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
index 0f17946..2e1683a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Закладки и история поиска</translation>
 <translation id="1549000191223877751">Перейти к другому окну</translation>
 <translation id="1553358976309200471">Обновить Chrome</translation>
-<translation id="1557201757634521564">Определять кодировку</translation>
 <translation id="1612196535745283361">Чтобы выполнить поиск устройств, браузеру Chrome нужен доступ к геоданным. <ph name="BEGIN_LINK" />Включить<ph name="END_LINK" /></translation>
 <translation id="1620510694547887537">Камера</translation>
 <translation id="1623104350909869708">Запретить создание дополнительных диалоговых окон на этой странице</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Кодовые фразы не совпадают</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Справка<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Сохранить видео</translation>
-<translation id="307329814453917357">Предлагать переводить страницы с помощью Google Переводчика</translation>
 <translation id="3089395242580810162">Открыть в режиме инкогнито</translation>
 <translation id="3090193911106258841">Доступ к аудио- и видеовходу</translation>
 <translation id="3117051980354074377">Чтобы получить доступ к закладкам на всех ваших устройствах, войдите в Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Страницы</translation>
 <translation id="4996978546172906250">Способ отправки</translation>
 <translation id="5000922062037820727">Заблокировано (рекомендуется)</translation>
+<translation id="5005498671520578047">Для копирования пароля</translation>
 <translation id="5016205925109358554">С засечками</translation>
 <translation id="5039804452771397117">Разрешить</translation>
 <translation id="5040262127954254034">Личные данные</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Чтобы выйти из полноэкранного режима, проведите по экрану сверху вниз и нажмите кнопку "Назад".</translation>
 <translation id="5284584623296338184">Изменения в ваших закладках, паролях, истории и других настройках больше не будут синхронизироваться с аккаунтом Google. Это изменение не затронет данные, сохраненные в аккаунте ранее.</translation>
 <translation id="5301954838959518834">ОК</translation>
-<translation id="5302048478445481009">Язык</translation>
 <translation id="5304593522240415983">Это поле нужно заполнить</translation>
 <translation id="5308380583665731573">Подключение</translation>
+<translation id="5308603654685598744">Если включить эту функцию, Chrome будет предлагать перевести страницы на другие языки с помощью приложения "Google Переводчик".</translation>
 <translation id="5313967007315987356">Добавить сайт</translation>
 <translation id="5317780077021120954">Сохранить</translation>
 <translation id="5324858694974489420">Родительские настройки</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Работая с приложением, вы принимаете <ph name="BEGIN_LINK1" />Условия использования<ph name="END_LINK1" /> и <ph name="BEGIN_LINK2" />Примечание о конфиденциальности<ph name="END_LINK2" /> Chrome.</translation>
 <translation id="5414836363063783498">Проверка…</translation>
 <translation id="5423934151118863508">Здесь появятся страницы, которые вы чаще всего просматриваете.</translation>
-<translation id="5424715742813396254">Изменение имени, пароля или исключения</translation>
 <translation id="5437003064129843501">Вы не можете получать рекомендации по контенту, поскольку синхронизируемые данные защищены кодовой фразой.</translation>
 <translation id="544291274896356069">Эта ссылка откроется во внешнем приложении, и вы выйдете из режима инкогнито. Продолжить?</translation>
 <translation id="5447201525962359567">Все данные сайтов, включая файлы cookie и другую информацию, хранящуюся на устройстве</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Все сайты</translation>
 <translation id="6320088164292336938">Вибросигнал</translation>
 <translation id="6324034347079777476">Синхронизация системы Android отключена</translation>
-<translation id="6324360525379265737">Автоматически определять кодировку символов</translation>
 <translation id="6333140779060797560">Отправить с помощью <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Шифрование</translation>
 <translation id="6364438453358674297">Удалить подсказку из истории?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Очистить</translation>
 <translation id="6647073004883890710">Сохранить в <ph name="PASSWORD_MANAGER_BRAND" /> новый пароль пользователя <ph name="USERNAME" /> для этого сайта?</translation>
 <translation id="6656545060687952787">Чтобы выполнить поиск устройств, браузеру Chrome нужен доступ к геоданным. <ph name="BEGIN_LINK" />Обновить разрешения<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Пароль</translation>
 <translation id="6659594942844771486">Вкладка</translation>
 <translation id="666268767214822976">Показывать подсказки с похожими запросами и часто посещаемыми сайтами по мере ввода в адресную строку</translation>
 <translation id="666981079809192359">Примечание о конфиденциальности Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Подключение к веб-сайту защищено, но посторонний пользователь может изменить вид страницы</translation>
 <translation id="8493948351860045254">Освободить место</translation>
 <translation id="8497726226069778601">Здесь появятся часто посещаемые страницы</translation>
+<translation id="8503813439785031346">Имя пользователя</translation>
 <translation id="8514577642972634246">Включить режим инкогнито</translation>
 <translation id="8518901949365209398">Этот сайт шифрует соединение с помощью подписей SHA-1. Поскольку это не самый надежный способ, ваши данные могут быть перехвачены.</translation>
 <translation id="8525306231823319788">Полноэкранный режим</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb
index 75303db..963f94b 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Záložky a webová história</translation>
 <translation id="1549000191223877751">Prejsť do druhého okna</translation>
 <translation id="1553358976309200471">Aktualizovať Chrome</translation>
-<translation id="1557201757634521564">Automaticky rozpoznávať kódovanie</translation>
 <translation id="1612196535745283361">Na to, aby mohol Chrome hľadať zariadenia, musí mať prístup k polohe. Prístup k polohe je v tomto zariadení <ph name="BEGIN_LINK" />vypnutý<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Zakázať tejto stránke otvárať ďalšie dialógové okná</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Prístupové frázy sa nezhodujú</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Získať pomoc<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Uložiť video</translation>
-<translation id="307329814453917357">Ponúkať preklady stránok pomocou Prekladača Google</translation>
 <translation id="3089395242580810162">Otvoriť na karte inkognito</translation>
 <translation id="3090193911106258841">Pristupovanie k zvukovému vstupu a vstupu videa</translation>
 <translation id="3117051980354074377">Ak chcete získať svoje záložky z ostatných zariadení, prihláste sa do Chromu.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Stránky</translation>
 <translation id="4996978546172906250">Zdieľať prostredníctvom</translation>
 <translation id="5000922062037820727">Blokované (odporúčané)</translation>
+<translation id="5005498671520578047">Kopírovanie hesla</translation>
 <translation id="5016205925109358554">Pätkové</translation>
 <translation id="5039804452771397117">Povoliť</translation>
 <translation id="5040262127954254034">Ochrana súkromia</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Režim celej obrazovky ukončíte potiahnutím z hornej časti a klepnutím na tlačidlo Späť.</translation>
 <translation id="5284584623296338184">Záložky, história, heslá a ďalšie nastavenia sa už nebudú ďalej synchronizovať do vášho účtu Google. Vaše súčasné údaje však zostanú v účte Google zachované.</translation>
 <translation id="5301954838959518834">Áno, rozumiem</translation>
-<translation id="5302048478445481009">Jazyk</translation>
 <translation id="5304593522240415983">Toto pole nesmie byť prázdne</translation>
 <translation id="5308380583665731573">Pripojenie</translation>
+<translation id="5308603654685598744">Keď je táto funkcia zapnutá, prehliadač Chrome vám ponúkne preklad stránok napísaných v iných jazykoch pomocou služby Prekladač Google.</translation>
 <translation id="5313967007315987356">Pridať stránky</translation>
 <translation id="5317780077021120954">Uložiť</translation>
 <translation id="5324858694974489420">Rodičovské nastavenia</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Používaním tejto aplikácie vyjadrujete súhlas so <ph name="BEGIN_LINK1" />zmluvnými podmienkami<ph name="END_LINK1" /> a <ph name="BEGIN_LINK2" />upozornením o ochrane osobných údajov<ph name="END_LINK2" /> prehliadača Chrome.</translation>
 <translation id="5414836363063783498">Overuje sa...</translation>
 <translation id="5423934151118863508">Tu sa zobrazia vaše najnavštevovanejšie stránky.</translation>
-<translation id="5424715742813396254">Úprava uloženého mena/hesla alebo výnimky</translation>
 <translation id="5437003064129843501">Prispôsobené návrhy obsahu sú momentálne zakázané, pretože vaše synchronizované údaje sú chránené vlastnou prístupovou frázou.</translation>
 <translation id="544291274896356069">Ak tento odkaz otvoríte v externej aplikácii, opustíte režim inkognito. Chcete pokračovať?</translation>
 <translation id="5447201525962359567">Celé úložisko webu vrátane súborov cookie a ďalších lokálne uložených dát</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Všetky stránky</translation>
 <translation id="6320088164292336938">Vibrovanie</translation>
 <translation id="6324034347079777476">Synchronizácia systému Android je zakázaná</translation>
-<translation id="6324360525379265737">Automaticky zisťovať kódovanie znakov</translation>
 <translation id="6333140779060797560">Zdieľať prostredníctvom aplikácie <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Šifrovanie</translation>
 <translation id="6364438453358674297">Odstrániť návrh z histórie?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Vymazať</translation>
 <translation id="6647073004883890710">Chcete, aby aplikácia <ph name="PASSWORD_MANAGER_BRAND" /> aktualizovala heslo používateľa <ph name="USERNAME" /> pre tento web?</translation>
 <translation id="6656545060687952787">Na to, aby mohol Chrome hľadať zariadenia, musí mať prístup k polohe. <ph name="BEGIN_LINK" />Aktualizovať povolenia<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Heslo</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Použite službu predpovedí na zobrazovanie súvisiacich dopytov a populárnych webových stránok počas zadávania textu do panela s adresou</translation>
 <translation id="666981079809192359">Upozornenie o ochrane osobných údajov prehliadača Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Vaše pripojenie k týmto stránkam je súkromné, ale niekto v sieti možno dokáže zmeniť vzhľad danej stránky.</translation>
 <translation id="8493948351860045254">Uvoľniť miesto</translation>
 <translation id="8497726226069778601">Zatiaľ tu nič nie je…</translation>
+<translation id="8503813439785031346">Meno používateľa</translation>
 <translation id="8514577642972634246">Spustiť režim inkognito</translation>
 <translation id="8518901949365209398">Tento web používa slabú konfiguráciu zabezpečenia (podpisy SHA-1). Pripojenie preto nemusí byť súkromné.</translation>
 <translation id="8525306231823319788">Celá obrazovka</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb
index 5fc34546..161e5e6e 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Zaznamki in spletna zgodovina</translation>
 <translation id="1549000191223877751">Premik v drugo okno</translation>
 <translation id="1553358976309200471">Posodobi Chrome</translation>
-<translation id="1557201757634521564">Samodejno zaznavanje kodiranja</translation>
 <translation id="1612196535745283361">Chrome za iskanje naprav potrebuje dostop do lokacije. Dostop do lokacije <ph name="BEGIN_LINK" />je izklopljen za to napravo<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Tej strani prepreči, da bi ustvarila dodatna pogovorna okna</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Gesli se ne ujemata</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Poiščite pomoč<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Shrani videoposnetek</translation>
-<translation id="307329814453917357">Ponudi prevajanje strani z Google Prevajalnikom</translation>
 <translation id="3089395242580810162">Odpri v zavihku brez beleženja zgodovine</translation>
 <translation id="3090193911106258841">Dostopanje do zvočnih vhodov in videovhodov</translation>
 <translation id="3117051980354074377">Če želite dostopati do zaznamkov v drugih napravah, se prijavite v Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Strani</translation>
 <translation id="4996978546172906250">Skupna raba prek</translation>
 <translation id="5000922062037820727">Blokirano (priporočeno)</translation>
+<translation id="5005498671520578047">Kopiranje gesla</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Dovoli</translation>
 <translation id="5040262127954254034">Zasebnost</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Povlecite z vrha in se dotaknite gumba za nazaj, če želite zapreti celozaslonski način.</translation>
 <translation id="5284584623296338184">Spremembe zaznamkov, zgodovine, gesel in drugih nastavitev ne bodo več sinhronizirane z Google Računom. Obstoječi podatki bodo še naprej shranjeni v Google Računu.</translation>
 <translation id="5301954838959518834">V redu, razumem</translation>
-<translation id="5302048478445481009">Jezik</translation>
 <translation id="5304593522240415983">To polje ne sme biti prazno</translation>
 <translation id="5308380583665731573">Povezovanje</translation>
+<translation id="5308603654685598744">Kadar je ta funkcija vklopljena, Chrome ponuja prevajanje strani v drugih jezikih z Google Prevajalnikom.</translation>
 <translation id="5313967007315987356">Dodajanje mesta</translation>
 <translation id="5317780077021120954">Shrani</translation>
 <translation id="5324858694974489420">Starševske nastavitve</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Če uporabljate to aplikacijo, se strinjate s <ph name="BEGIN_LINK1" />pogoji storitve<ph name="END_LINK1" /> in <ph name="BEGIN_LINK2" />pravilnikom o zasebnosti<ph name="END_LINK2" /> za Chrome.</translation>
 <translation id="5414836363063783498">Preverjanje …</translation>
 <translation id="5423934151118863508">Tu bodo prikazane strani, ki jih obiskujete najpogosteje</translation>
-<translation id="5424715742813396254">Urejanje shranjenega imena/gesla ali izjeme</translation>
 <translation id="5437003064129843501">Prilagojeni predlogi za vsebino so trenutno onemogočeni, ker so sinhronizirani podatki zaščiteni z geslom po meri.</translation>
 <translation id="544291274896356069">Če je ta povezava odprta v zunanji aplikaciji, boste ustavili način brez beleženja zgodovine. Želite nadaljevati?</translation>
 <translation id="5447201525962359567">Vsi shranjeni podatki spletnega mesta, vključno s piškotki in drugimi lokalno shranjenimi podatki</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Vsa spletna mesta</translation>
 <translation id="6320088164292336938">Vibriranje</translation>
 <translation id="6324034347079777476">Sinhronizacija sistema Android je onemogočena.</translation>
-<translation id="6324360525379265737">Samodejno ugotavljanje kodiranja znakov</translation>
 <translation id="6333140779060797560">Skupna raba prek: <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Šifriranje</translation>
 <translation id="6364438453358674297">Ali želite odstraniti predlog iz zgodovine?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Počisti</translation>
 <translation id="6647073004883890710">Ali želite, da <ph name="PASSWORD_MANAGER_BRAND" /> posodobi geslo za uporabniško ime <ph name="USERNAME" /> za to spletno mesto?</translation>
 <translation id="6656545060687952787">Chrome za iskanje naprav potrebuje dostop do lokacije. <ph name="BEGIN_LINK" />Posodobite dovoljenja<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Geslo</translation>
 <translation id="6659594942844771486">Tabulator</translation>
 <translation id="666268767214822976">S storitvijo predvidevanja lahko med vnašanjem v naslovno vrstico prikažete povezane poizvedbe in priljubljena spletna mesta</translation>
 <translation id="666981079809192359">Obvestilo o zasebnosti za Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Povezava s tem mestom je zasebna, vendar lahko nekdo v omrežju spremeni videz strani.</translation>
 <translation id="8493948351860045254">Sprosti prostor</translation>
 <translation id="8497726226069778601">Nimate česa videti ... Za zdaj.</translation>
+<translation id="8503813439785031346">Uporabniško ime</translation>
 <translation id="8514577642972634246">Vklop načina brez beleženja zgodovine</translation>
 <translation id="8518901949365209398">To spletno mesto uporablja šibko varnostno konfiguracijo (podpise SHA-1), zato vaša povezava morda ni zasebna.</translation>
 <translation id="8525306231823319788">Celozaslonsko</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb
index 7f59414e..d8aecd2 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Обележивачи и веб-историја</translation>
 <translation id="1549000191223877751">Премести у други прозор</translation>
 <translation id="1553358976309200471">Ажурирај Chrome</translation>
-<translation id="1557201757634521564">Аутоматски откривај кодирање</translation>
 <translation id="1612196535745283361">Chrome-у је потребан приступ локацији да би тражио уређаје. Приступ локацији је <ph name="BEGIN_LINK" />искључен за овај уређај<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Камеру</translation>
 <translation id="1623104350909869708">Спречи ову страницу да прави додатне дијалоге</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Приступне фразе се не подударају</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Потражите помоћ<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Сачувај видео</translation>
-<translation id="307329814453917357">Нуди превод страница помоћу Google преводиоца</translation>
 <translation id="3089395242580810162">Отварање на картици без архивирања</translation>
 <translation id="3090193911106258841">Приступа се аудио и видео улазу</translation>
 <translation id="3117051980354074377">Да би вам обележивачи били доступни на другим уређајима, пријавите се у Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Странице</translation>
 <translation id="4996978546172906250">Дељење преко</translation>
 <translation id="5000922062037820727">Блокирано (препоручено)</translation>
+<translation id="5005498671520578047">Копирање лозинке</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Дозволи</translation>
 <translation id="5040262127954254034">Приватност</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Превуците од врха екрана и додирните дугме Назад да бисте изашли из режима целог екрана.</translation>
 <translation id="5284584623296338184">Промене обележивача, историје, лозинки и других подешавања се више неће синхронизовати са Google налогом. Међутим, постојећи подаци ће остати сачувани на Google налогу.</translation>
 <translation id="5301954838959518834">Важи</translation>
-<translation id="5302048478445481009">Језик</translation>
 <translation id="5304593522240415983">Ово поље не сме да буде празно</translation>
 <translation id="5308380583665731573">Повезивање</translation>
+<translation id="5308603654685598744">Када је ова функција укључена, Chrome ће нудити да преводи странице написане на другим језицима помоћу Google преводиоца.</translation>
 <translation id="5313967007315987356">Додај сајт</translation>
 <translation id="5317780077021120954">Сачувај</translation>
 <translation id="5324858694974489420">Родитељска подешавања</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Коришћењем ове апликације прихватате <ph name="BEGIN_LINK1" />Услове коришћења услуге<ph name="END_LINK1" /> и <ph name="BEGIN_LINK2" />Обавештење о приватности<ph name="END_LINK2" /> за Chrome.</translation>
 <translation id="5414836363063783498">Верификују се...</translation>
 <translation id="5423934151118863508">Најчешће посећиване странице ће се појавити овде</translation>
-<translation id="5424715742813396254">Мењање сачуваног имена/лозинке или изузетка</translation>
 <translation id="5437003064129843501">Предлози за персонализовани садржај су тренутно онемогућени јер су синхронизовани подаци заштићени прилагођеном приступном фразом.</translation>
 <translation id="544291274896356069">Напустићете режим без архивирања ако се овај линк отвори у спољној апликацији. Желите ли да наставите?</translation>
 <translation id="5447201525962359567">Целокупан меморијски простор за сајт, укључујући колачиће и друге локално сачуване податке</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Сви сајтови</translation>
 <translation id="6320088164292336938">Вибрација</translation>
 <translation id="6324034347079777476">Синхронизација Android система је онемогућена</translation>
-<translation id="6324360525379265737">Аутоматски утврђује кодирање знакова</translation>
 <translation id="6333140779060797560">Дељење преко <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Шифровање</translation>
 <translation id="6364438453358674297">Желите ли да уклоните предлог из историје?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Обриши</translation>
 <translation id="6647073004883890710">Да ли желите да <ph name="PASSWORD_MANAGER_BRAND" /> ажурира лозинку за <ph name="USERNAME" /> за овај сајт?</translation>
 <translation id="6656545060687952787">Chrome-у је потребан приступ локацији за скенирање уређаја. <ph name="BEGIN_LINK" />Ажурирајте дозволе<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Лозинка</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Коришћење услуге предвиђања за приказивање сродних упита и популарних веб-сајтова док куцате у траци за адресу</translation>
 <translation id="666981079809192359">Chrome обавештење о приватности</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Веза са овим сајтом је приватна, али неко на мрежи ће можда моћи да промени изглед странице.</translation>
 <translation id="8493948351860045254">Ослободите простор</translation>
 <translation id="8497726226069778601">Овде нема ничега... засад</translation>
+<translation id="8503813439785031346">Корисничко име</translation>
 <translation id="8514577642972634246">Уђи у режим без архивирања</translation>
 <translation id="8518901949365209398">Овај сајт користи слабу безбедносну конфигурацију (SHA-1 потписи), па приватност везе можда није заштићена.</translation>
 <translation id="8525306231823319788">Цео екран</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb
index 0b950d8..caaea20 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Bokmärken och webbhistorik</translation>
 <translation id="1549000191223877751">Flytta till annat fönster</translation>
 <translation id="1553358976309200471">Uppdatera Chrome</translation>
-<translation id="1557201757634521564">Identifiera teckenkodning automatiskt</translation>
 <translation id="1612196535745283361">Chrome behöver åtkomst till platsinformation för att kunna söka efter enheter. Platsåtkomst är <ph name="BEGIN_LINK" />inaktiverat för enheten<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Hindra sidan från att skapa fler dialogrutor</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Lösenfraserna matchar inte</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Få hjälp<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Spara video</translation>
-<translation id="307329814453917357">Erbjud att översätta sidor med Google Översätt</translation>
 <translation id="3089395242580810162">Öppna i inkognitoflik</translation>
 <translation id="3090193911106258841">Får åtkomst till ljud- och videoindata</translation>
 <translation id="3117051980354074377">Logga in i Chrome om du vill ha samma bokmärken tillgängliga på alla enheter.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Sidor</translation>
 <translation id="4996978546172906250">Dela via</translation>
 <translation id="5000922062037820727">Blockerad (rekommenderas)</translation>
+<translation id="5005498671520578047">Kopiera lösenord</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Tillåt</translation>
 <translation id="5040262127954254034">Sekretess</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Dra uppifrån och tryck på bakåtknappen för att lämna helskärmsläget.</translation>
 <translation id="5284584623296338184">Ändringar i bokmärken, historik, lösenord och andra inställningar synkroniseras inte längre med ditt Google-konto. Befintlig data fortsätter dock att lagras i Google-kontot.</translation>
 <translation id="5301954838959518834">OK, jag fattar</translation>
-<translation id="5302048478445481009">Språk</translation>
 <translation id="5304593522240415983">Fältet får inte vara tomt</translation>
 <translation id="5308380583665731573">Ansluta</translation>
+<translation id="5308603654685598744">När den här funktionen är aktiverad blir du tillfrågad om Chrome ska översätta sidor på andra språk med hjälp av Google Översätt.</translation>
 <translation id="5313967007315987356">Lägg till webbplats</translation>
 <translation id="5317780077021120954">Spara</translation>
 <translation id="5324858694974489420">Föräldrainställningar</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Genom att använda det här programmet godkänner du Chromes <ph name="BEGIN_LINK1" />användarvillkor<ph name="END_LINK1" /> och <ph name="BEGIN_LINK2" />sekretessmeddelande<ph name="END_LINK2" />.</translation>
 <translation id="5414836363063783498">Verifierar ...</translation>
 <translation id="5423934151118863508">Dina mest besökta sidor visas här</translation>
-<translation id="5424715742813396254">Redigera sparat namn/lösenord eller undantag</translation>
 <translation id="5437003064129843501">Förslag på anpassat innehåll är inte aktiverat eftersom din synkroniserade data skyddas med en anpassad lösenfras.</translation>
 <translation id="544291274896356069">Om den här länken öppnas i ett externt program sker inte det i inkognitoläge. Vill du fortsätta?</translation>
 <translation id="5447201525962359567">All webbplatslagring, inklusive cookies och annan lokalt sparad data</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Alla webbplatser</translation>
 <translation id="6320088164292336938">Vibration</translation>
 <translation id="6324034347079777476">Synkronisering av Android-system har inaktiverats</translation>
-<translation id="6324360525379265737">Identifiera automatiskt vilken teckenkodning som används</translation>
 <translation id="6333140779060797560">Dela via <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Kryptering</translation>
 <translation id="6364438453358674297">Vill du ta bort förslaget från historiken?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Rensa</translation>
 <translation id="6647073004883890710">Vill du att <ph name="PASSWORD_MANAGER_BRAND" /> ska uppdatera lösenordet för <ph name="USERNAME" /> på den här webbplatsen?</translation>
 <translation id="6656545060687952787">Chrome behöver platsåtkomst för att söka efter enheter. <ph name="BEGIN_LINK" />Uppdatera behörigheter<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Lösenord</translation>
 <translation id="6659594942844771486">Flik</translation>
 <translation id="666268767214822976">Använd en tjänst som ger förslag på relaterade sökfrågor och populära webbplatser när du skriver i adressfältet</translation>
 <translation id="666981079809192359">Chromes sekretessmeddelande</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Din anslutning till webbplatsen är privat, men någon i nätverket kanske kan ändra utseendet på sidan.</translation>
 <translation id="8493948351860045254">Frigör lagringsutrymme</translation>
 <translation id="8497726226069778601">Det finns inget att se här … än</translation>
+<translation id="8503813439785031346">Användarnamn</translation>
 <translation id="8514577642972634246">Starta inkognitoläget</translation>
 <translation id="8518901949365209398">Den här webbplatsen använder en svag säkerhetskonfiguration (signaturer med SHA-1), så anslutningen kanske inte är privat.</translation>
 <translation id="8525306231823319788">Helskärm</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb
index b8fc111..e3e3b60 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Alamisho na historia ya wavuti</translation>
 <translation id="1549000191223877751">Nenda kwenye dirisha jingine</translation>
 <translation id="1553358976309200471">Sasisha Chrome</translation>
-<translation id="1557201757634521564">Gundua usimbaji fiche kiotomatiki</translation>
 <translation id="1612196535745283361">Chrome inahitaji idhini ya kufikia mahali ili itafute vifaa. Kipengele cha kufikia mahali <ph name="BEGIN_LINK" />kimezimwa kwenye kifaa hiki<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Zuia ukurasa huu usiunde vidadisi zaidi</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Kaulisiri hazilingani</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Pata usaidizi<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Hifadhi video</translation>
-<translation id="307329814453917357">Jitolee kutafsiri kurasa kwa kutumia huduma ya Google Tafsiri</translation>
 <translation id="3089395242580810162">Fungua kwenye kichupo fiche</translation>
 <translation id="3090193911106258841">Inafikia vifaa vya kuingiza sauti na video</translation>
 <translation id="3117051980354074377">Ili upate alamisho kutoka kwenye vifaa vyako vingine, ingia katika Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Kurasa</translation>
 <translation id="4996978546172906250">Shiriki kupitia</translation>
 <translation id="5000922062037820727">Imezuiwa (imependekezwa)</translation>
+<translation id="5005498671520578047">Nakili nenosiri</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Ruhusu</translation>
 <translation id="5040262127954254034">Faragha</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Buruta kutoka juu na uguse kitufe cha kurudi nyuma ili uondoke kwenye skrini nzima.</translation>
 <translation id="5284584623296338184">Mabadiliko kwenye alamisho, historia, manenosiri na mipangilio yako mingine haitasawazishwa tena kwenye Akaunti yako ya Google. Hata hivyo, data yako iliyopo itaendelea kuhifadhiwa katika akaunti yako ya Google.</translation>
 <translation id="5301954838959518834">Sawa, nimeelewa</translation>
-<translation id="5302048478445481009">Lugha</translation>
 <translation id="5304593522240415983">Sehemu hii haiwezi kuwa tupu</translation>
 <translation id="5308380583665731573">Unganisha</translation>
+<translation id="5308603654685598744">Wakati kipengele hiki kimewashwa, Chrome itajitolea kutafsiri kurasa zilizoandikwa katika lugha nyingine kutumia Google Tafsiri.</translation>
 <translation id="5313967007315987356">Ongeza tovuti</translation>
 <translation id="5317780077021120954">Hifadhi</translation>
 <translation id="5324858694974489420">Mipangilio ya Wazazi</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Kwa kutumia programu hii, unakubali <ph name="BEGIN_LINK1" />Sheria na Masharti<ph name="END_LINK1" /> na <ph name="BEGIN_LINK2" />Ilani ya Faragha<ph name="END_LINK2" /> ya Chrome.</translation>
 <translation id="5414836363063783498">Inathibitisha...</translation>
 <translation id="5423934151118863508">Kurasa zako zilizotembelewa sana zitaonekana hapa</translation>
-<translation id="5424715742813396254">Badilisha jina/nenosiri lililohifadhiwa au kighairi</translation>
 <translation id="5437003064129843501">Kwa sasa mapendekezo ya maudhui yaliyowekwa mapendeleo yamezimwa, kwa sababu data yako iliyosawazishwa inalindwa kwa kauli ya siri maalum.</translation>
 <translation id="544291274896356069">Inaacha katika hali fiche ikiwa kiungo hiki kinafunguliwa katika programu ya nje. Je, ungependa kuendelea?</translation>
 <translation id="5447201525962359567">Hifadhi yote ya tovuti, ikiwa ni pamoja na vidakuzi na data nyingine iliyohifadhiwa ndani</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Tovuti zote</translation>
 <translation id="6320088164292336938">Tetema</translation>
 <translation id="6324034347079777476">Kipengele cha usawazishaji wa mfumo wa Android kimezimwa</translation>
-<translation id="6324360525379265737">Tambua usimbaji fiche wa herufi kiotomatiki</translation>
 <translation id="6333140779060797560">Shiriki kupitia <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Usimbaji fiche</translation>
 <translation id="6364438453358674297">Je, ungependa kuondoa pendekezo kwenye historia?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Futa</translation>
 <translation id="6647073004883890710">Je, ungependa <ph name="PASSWORD_MANAGER_BRAND" /> isasishe nenosiri lako la <ph name="USERNAME" /> kwa ajili ya tovuti hii?</translation>
 <translation id="6656545060687952787">Chrome inahitaji idhini ya kufikia mahali ili ichanganue vifaa. <ph name="BEGIN_LINK" />Ruhusa za sasisho<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Nenosiri</translation>
 <translation id="6659594942844771486">Kichupo</translation>
 <translation id="666268767214822976">Tumia huduma ya ubashiri ili kuonyesha hoja zinazohusiana na tovuti maarufu unapocharaza katika sehemu ya anwani</translation>
 <translation id="666981079809192359">Ilani ya Faragha ya Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Muunganisho wako kwenye tovuti hii ni wa faragha, lakini huenda mtu aliye kwenye mtandao akaweza kubadilisha maudhui ya ukurasa.</translation>
 <translation id="8493948351860045254">Ongeza nafasi ya hifadhi</translation>
 <translation id="8497726226069778601">Bado hapana chochote cha kuangalia...</translation>
+<translation id="8503813439785031346">Jina la mtumiaji</translation>
 <translation id="8514577642972634246">Ingia kwenye hali fiche</translation>
 <translation id="8518901949365209398">Tovuti hii hutumia usanidi dhaifu wa usalama (sahihi za SHA-1), kwa hivyo huenda muunganisho wako usiwe wa faragha.</translation>
 <translation id="8525306231823319788">Skrini nzima</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_th.xtb b/chrome/android/java/strings/translations/android_chrome_strings_th.xtb
index 0c52cbd..477efc7f 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_th.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_th.xtb
@@ -30,7 +30,7 @@
 <translation id="13410144310025252">ดูใน Chrome</translation>
 <translation id="1369915414381695676">เพิ่มเว็บไซต์ <ph name="SITE_NAME" /> แล้ว</translation>
 <translation id="1373696734384179344">หน่วยความจำไม่เพียงพอที่จะดาวน์โหลดเนื้อหาที่เลือก</translation>
-<translation id="1376578503827013741">กำลังประมวลผล...</translation>
+<translation id="1376578503827013741">กำลังประมวลผล…</translation>
 <translation id="138361230106469022">สวัสดี คุณ <ph name="FULL_NAME" /></translation>
 <translation id="1383876407941801731">ค้นหา</translation>
 <translation id="1389974829397082527">ไม่มีบุ๊กมาร์กที่นี่</translation>
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">บุ๊กมาร์กและประวัติเว็บ</translation>
 <translation id="1549000191223877751">ย้ายไปยังหน้าต่างอื่น</translation>
 <translation id="1553358976309200471">อัปเดต Chrome</translation>
-<translation id="1557201757634521564">ตรวจหาการเข้ารหัสโดยอัตโนมัติ</translation>
 <translation id="1612196535745283361">Chrome ต้องมีสิทธิ์เข้าถึงตำแหน่งเพื่อสแกนหาอุปกรณ์ ตัวเลือกสิทธิ์เข้าถึงตำแหน่ง<ph name="BEGIN_LINK" />สำหรับอุปกรณ์เครื่องนี้ปิดอยู่<ph name="END_LINK" /></translation>
 <translation id="1620510694547887537">กล้องถ่ายรูป</translation>
 <translation id="1623104350909869708">ป้องกันหน้าเว็บนี้จากการสร้างการโต้ตอบเพิ่มเติม</translation>
@@ -174,7 +173,7 @@
 <translation id="2932150158123903946">พื้นที่เก็บข้อมูล Google <ph name="APP_NAME" /></translation>
 <translation id="2956410042958133412">บัญชีนี้ได้รับการจัดการโดย <ph name="PARENT_NAME_1" /> และ <ph name="PARENT_NAME_2" /></translation>
 <translation id="2960796085439532066">ลิขสิทธิ์ <ph name="YEAR" /> Google Inc. สงวนลิขสิทธิ์</translation>
-<translation id="2962095958535813455">สลับไปที่แท็บไม่ระบุตัวตน</translation>
+<translation id="2962095958535813455">สลับเป็นแท็บไม่ระบุตัวตนแล้ว</translation>
 <translation id="2968755619301702150">เครื่องมือดูใบรับรอง</translation>
 <translation id="2979025552038692506">แท็บที่ไม่ระบุตัวตนที่เลือก</translation>
 <translation id="2996291259634659425">สร้างรหัสผ่าน</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">รหัสผ่านไม่ตรงกัน</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />ขอความช่วยเหลือ<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">บันทึกวิดีโอ</translation>
-<translation id="307329814453917357">เสนอให้แปลหน้าเว็บโดยใช้ Google แปลภาษา</translation>
 <translation id="3089395242580810162">เปิดในแท็บไม่ระบุตัวตน</translation>
 <translation id="3090193911106258841">กำลังเข้าถึงอินพุตเสียงและวิดีโอ</translation>
 <translation id="3117051980354074377">ลงชื่อเข้าใช้ Chrome เพื่อรับบุ๊กมาร์กในอุปกรณ์เครื่องอื่นๆ ของคุณ</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">หน้า</translation>
 <translation id="4996978546172906250">แชร์ผ่าน</translation>
 <translation id="5000922062037820727">ถูกบล็อก (แนะนำ)</translation>
+<translation id="5005498671520578047">คัดลอกรหัสผ่าน</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">อนุญาต</translation>
 <translation id="5040262127954254034">ความเป็นส่วนตัว</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">ลากจากด้านบน แล้วแตะปุ่มกลับเพื่อออกจากโหมดเต็มหน้าจอ</translation>
 <translation id="5284584623296338184">การเปลี่ยนแปลงบุ๊กมาร์ก ประวัติการเข้าชม รหัสผ่าน และการตั้งค่าอื่นๆ จะไม่ซิงค์กับบัญชี Google ของคุณอีกต่อไป อย่างไรก็ตาม ข้อมูลที่คุณมีจะยังคงจัดเก็บอยู่ในบัญชี Google ของคุณ</translation>
 <translation id="5301954838959518834">ตกลง เข้าใจแล้ว</translation>
-<translation id="5302048478445481009">ภาษา </translation>
 <translation id="5304593522240415983">ต้องกรอกข้อมูลในช่องนี้</translation>
 <translation id="5308380583665731573">เชื่อมต่อ</translation>
+<translation id="5308603654685598744">เมื่อเปิดคุณลักษณะนี้ Chrome จะเสนอที่จะแปลหน้าเว็บที่เขียนในภาษาอื่นๆ โดยใช้ Google แปลภาษา</translation>
 <translation id="5313967007315987356">เพิ่มเว็บไซต์</translation>
 <translation id="5317780077021120954">บันทึก</translation>
 <translation id="5324858694974489420">การตั้งค่าของผู้ปกครอง</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">การใช้แอปพลิเคชันนี้แสดงว่า คุณยอมรับ<ph name="BEGIN_LINK1" />ข้อกำหนดในการให้บริการ<ph name="END_LINK1" />และ<ph name="BEGIN_LINK2" />ประกาศเกี่ยวกับนโยบายส่วนบุคคล<ph name="END_LINK2" />ของ Chrome</translation>
 <translation id="5414836363063783498">กำลังยืนยัน…</translation>
 <translation id="5423934151118863508">หน้าที่มีการเข้าชมมากที่สุดของคุณจะปรากฏที่นี่</translation>
-<translation id="5424715742813396254">แก้ไขชื่อ/รหัสผ่านหรือข้อยกเว้นที่บันทึกไว้</translation>
 <translation id="5437003064129843501">การแนะนำเนื้อหาที่เหมาะสมสำหรับคุณปิดอยู่ เพราะมีการปกป้องข้อมูลที่ซิงค์ด้วยรหัสผ่านที่กำหนดเอง</translation>
 <translation id="544291274896356069">ออกจากโหมดไม่ระบุตัวตนถ้ามีการเปิดลิงก์นี้ในแอปพลิเคชันภายนอก ดำเนินการต่อไหม</translation>
 <translation id="5447201525962359567">พื้นที่เก็บข้อมูลเว็บไซต์ทั้งหมด รวมถึงคุกกี้และข้อมูลอื่นๆ ที่เก็บไว้ในเครื่อง</translation>
@@ -412,7 +410,7 @@
 
 อย่างไรก็ตาม คนอื่นจะยังสามารถมองเห็นคุณ การเข้าสู่โหมดไม่ระบุตัวตนไม่ได้เป็นการซ่อนการท่องเว็บจากนายจ้าง ผู้ให้บริการอินเทอร์เน็ต หรือเว็บไซต์ที่คุณเข้าชม</translation>
 <translation id="572328651809341494">แท็บล่าสุด</translation>
-<translation id="5748802427693696783">สลับไปที่แท็บมาตรฐาน</translation>
+<translation id="5748802427693696783">สลับเป็นแท็บมาตรฐานแล้ว</translation>
 <translation id="5749068826913805084">Chrome ต้องสามารถเข้าถึงพื้นที่เก็บข้อมูลเพื่อดาวน์โหลดไฟล์</translation>
 <translation id="5763382633136178763">แท็บที่ไม่ระบุตัวตน</translation>
 <translation id="5765780083710877561">คำอธิบาย:</translation>
@@ -462,11 +460,10 @@
 <translation id="6295158916970320988">ไซต์ทั้งหมด</translation>
 <translation id="6320088164292336938">สั่น</translation>
 <translation id="6324034347079777476">ปิดใช้การซิงค์ระบบ Android อยู่</translation>
-<translation id="6324360525379265737">ระบุการเข้ารหัสอักขระโดยอัตโนมัติ</translation>
 <translation id="6333140779060797560">แชร์ผ่าน <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">การเข้ารหัส</translation>
 <translation id="6364438453358674297">ต้องการนำคำแนะนำออกจากประวัติการเข้าชมใช่ไหม</translation>
-<translation id="6383961787135158834">ล้างพื้นที่เก็บข้อมูลเว็บไซต์…</translation>
+<translation id="6383961787135158834">ล้างที่เก็บข้อมูลไซต์…</translation>
 <translation id="6388207532828177975">ล้างข้อมูลและรีเซ็ต</translation>
 <translation id="6404511346730675251">แก้ไขบุ๊กมาร์ก</translation>
 <translation id="6406506848690869874">การซิงค์ข้อมูล</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">ล้าง</translation>
 <translation id="6647073004883890710">คุณต้องการให้ <ph name="PASSWORD_MANAGER_BRAND" /> อัปเดตรหัสผ่านของ <ph name="USERNAME" /> สำหรับเว็บไซต์นี้ไหม</translation>
 <translation id="6656545060687952787">Chrome ต้องมีสิทธิ์เข้าถึงตำแหน่งเพื่อสแกนหาอุปกรณ์ โปรด<ph name="BEGIN_LINK" />อัปเดตสิทธิ์<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">รหัสผ่าน</translation>
 <translation id="6659594942844771486">แท็บ</translation>
 <translation id="666268767214822976">ใช้บริการการคาดคะเนเพื่อแสดงคำค้นหาที่เกี่ยวข้องและเว็บไซต์ยอดนิยมขณะที่คุณพิมพ์ในแถบที่อยู่เว็บ</translation>
 <translation id="666981079809192359">ประกาศเกี่ยวกับนโยบายส่วนบุคคลของ Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">การเชื่อมต่อกับไซต์นี้เป็นแบบส่วนตัว แต่คนอื่นในเครือข่ายอาจเปลี่ยนลักษณะของหน้าได้</translation>
 <translation id="8493948351860045254">เพิ่มพื้นที่ว่าง</translation>
 <translation id="8497726226069778601">ที่นี่ยังไม่มีอะไรให้ดู… เลย</translation>
+<translation id="8503813439785031346">ชื่อผู้ใช้</translation>
 <translation id="8514577642972634246">เข้าสู่โหมดไม่ระบุตัวตน</translation>
 <translation id="8518901949365209398">ไซต์นี้ใช้การกำหนดค่าความปลอดภัยที่หละหลวม (ลายเซ็นแบบ SHA-1) ดังนั้น การเชื่อมต่อของคุณอาจไม่เป็นส่วนตัว</translation>
 <translation id="8525306231823319788">เต็มหน้าจอ</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb
index 5ae1fb3..fc4c8781 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Yer işaretleri ve web geçmişi</translation>
 <translation id="1549000191223877751">Diğer pencereye git</translation>
 <translation id="1553358976309200471">Chrome'u güncelle</translation>
-<translation id="1557201757634521564">Kodlamayı otomatik olarak algıla</translation>
 <translation id="1612196535745283361">Chrome'un cihazları taraması için konum bilgilerine erişmesi gerekiyor. Konum bilgilerine erişim <ph name="BEGIN_LINK" />bu cihaz için kapalı<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Kamera</translation>
 <translation id="1623104350909869708">Bu sayfanın daha fazla iletişim kutusu oluşturmasını önle</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Parolalar eşleşmiyor</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Yardım alın<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Videoyu kaydet</translation>
-<translation id="307329814453917357">Sayfaları Google Çeviri ile çevirmeyi öner</translation>
 <translation id="3089395242580810162">Gizli sekmede aç</translation>
 <translation id="3090193911106258841">Ses ve video girişlerine erişiliyor</translation>
 <translation id="3117051980354074377">Diğer cihazlarınızdaki yer işaretlerinizi almak için Chrome'da oturum açın.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Sayfalar</translation>
 <translation id="4996978546172906250">Paylaşım yöntemi:</translation>
 <translation id="5000922062037820727">Engellendi (önerilir)</translation>
+<translation id="5005498671520578047">Şifreyi kopyalayın</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">İzin ver</translation>
 <translation id="5040262127954254034">Gizlilik</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Tam ekrandan çıkmak için yukarıdan sürükleyin ve geri düğmesine dokunun.</translation>
 <translation id="5284584623296338184">Yer işaretleri, geçmiş, şifreler ve diğer ayarlarınızda yaptığınız değişiklikler artık Google Hesabınız ile senkronize edilmeyecek. Ancak, mevcut verileriniz Google hesabınızda saklanmaya devam edecek.</translation>
 <translation id="5301954838959518834">Evet, anladım</translation>
-<translation id="5302048478445481009">Dil</translation>
 <translation id="5304593522240415983">Bu alan boş olamaz</translation>
 <translation id="5308380583665731573">Bağlan</translation>
+<translation id="5308603654685598744">Bu özellik açıldığında, Chrome, başka dilde yazılmış sayfaları Google Çeviri'yi kullanarak çevirmeyi önerir.</translation>
 <translation id="5313967007315987356">Site ekle</translation>
 <translation id="5317780077021120954">Kaydet</translation>
 <translation id="5324858694974489420">Ebeveyn Ayarları</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Bu uygulamayı kullanarak <ph name="BEGIN_LINK1" />Chrome'un Gizlilik Şartları<ph name="END_LINK1" />'nı ve <ph name="BEGIN_LINK2" />Gizlilik Uyarısı<ph name="END_LINK2" />'nı kabul etmiş olursunuz.</translation>
 <translation id="5414836363063783498">Doğrulanıyor…</translation>
 <translation id="5423934151118863508">En çok ziyaret ettiğiniz sayfalar burada görünecektir</translation>
-<translation id="5424715742813396254">Kayıtlı adı/şifreyi veya istisnayı düzenleyin</translation>
 <translation id="5437003064129843501">Senkronize edilen verileriniz özel bir parolayla korunduğu için kişiselleştirilmiş içerik önerileri şu anda devre dışı.</translation>
 <translation id="544291274896356069">Bu bağlantı harici bir uygulamada açılırsa gizli moddan çıkılacak. Devam edilsin mi?</translation>
 <translation id="5447201525962359567">Çerezler ve yerel olarak depolanmış diğer veriler de dahil olmak üzere tüm site depolama alanı</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Tüm siteler</translation>
 <translation id="6320088164292336938">Titreşim</translation>
 <translation id="6324034347079777476">Android sistem senkronizasyonu devre dışı</translation>
-<translation id="6324360525379265737">Karakter kodlamasını otomatik olarak belirle</translation>
 <translation id="6333140779060797560">Paylaşım yöntemi: <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Şifreleme</translation>
 <translation id="6364438453358674297">Öneri geçmişten kaldırılsın mı?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Temizle</translation>
 <translation id="6647073004883890710"><ph name="USERNAME" /> adlı kullanıcının bu siteye ait şifresinin <ph name="PASSWORD_MANAGER_BRAND" /> tarafından güncellenmesini istiyor musunuz?</translation>
 <translation id="6656545060687952787">Chrome'un cihazları taraması için konuma erişmesi gerekiyor. <ph name="BEGIN_LINK" />İzinleri güncelleyin<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Şifre</translation>
 <translation id="6659594942844771486">Sekme</translation>
 <translation id="666268767214822976">Adres çubuğuna yazarken ilgili sorguları ve popüler siteleri göstermek için bir tahmin hizmeti kullan</translation>
 <translation id="666981079809192359">Chrome Gizlilik Uyarısı</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Bu siteye bağlantınız gizli bir bağlantı, ancak ağ üzerindeki biri sayfanın görünümünü değiştirebilir.</translation>
 <translation id="8493948351860045254">Yer aç</translation>
 <translation id="8497726226069778601">Burada görülecek bir şey yok… henüz</translation>
+<translation id="8503813439785031346">Kullanıcı adı</translation>
 <translation id="8514577642972634246">Gizli moda geç</translation>
 <translation id="8518901949365209398">Bu site düşük bir güvenlik yapılandırması (SHA-1 imzaları) kullandığından bağlantınız gizli olmayabilir.</translation>
 <translation id="8525306231823319788">Tam ekran</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb b/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb
index dd7e3a5..328ade87b 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Закладки й історія веб-пошуку</translation>
 <translation id="1549000191223877751">Відкрити в іншому вікні</translation>
 <translation id="1553358976309200471">Оновити Chrome</translation>
-<translation id="1557201757634521564">Автоматично визначати кодування</translation>
 <translation id="1612196535745283361">Щоб шукати пристрої, Chrome потрібен доступ до геоданих. Доступ до геоданих <ph name="BEGIN_LINK" />вимкнено на цьому пристрої<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Камера</translation>
 <translation id="1623104350909869708">Заборонити цій сторінці створювати додаткові діалогові вікна</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Парольні фрази не збігаються</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Довідка<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Зберегти відео</translation>
-<translation id="307329814453917357">Пропонувати перекладати сторінки в Перекладачі Google</translation>
 <translation id="3089395242580810162">Відкрити в анонімній вкладці</translation>
 <translation id="3090193911106258841">Отримання доступу до аудіо- й відеовходу</translation>
 <translation id="3117051980354074377">Щоб мати доступ до закладок з інших пристроїв, увійдіть в обліковий запис Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Сторінки</translation>
 <translation id="4996978546172906250">Надіслати через</translation>
 <translation id="5000922062037820727">Заблоковано (рекомендується)</translation>
+<translation id="5005498671520578047">Копіювати пароль</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Дозволити</translation>
 <translation id="5040262127954254034">Конфіденційність</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Щоб вийти з повноекранного режиму, проведіть пальцем по екрану згори вниз і торкніться кнопки "Назад".</translation>
 <translation id="5284584623296338184">Зміни в закладках, історії, паролях та інших налаштуваннях більше не синхронізуватимуться з вашим обліковим записом Google. Однак наявні дані залишаться у вашому обліковому записі Google.</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">Мова</translation>
 <translation id="5304593522240415983">Це поле не може бути порожнім</translation>
 <translation id="5308380583665731573">Під’єднатися</translation>
+<translation id="5308603654685598744">Якщо цю функцію ввімкнено, Chrome пропонує перекласти іншомовні сторінки в Перекладачі Google.</translation>
 <translation id="5313967007315987356">Додати сайт</translation>
 <translation id="5317780077021120954">Зберегти</translation>
 <translation id="5324858694974489420">Батьківські налаштування</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Користуючись цим додатком, ви приймаєте <ph name="BEGIN_LINK1" />Умови використання<ph name="END_LINK1" /> та <ph name="BEGIN_LINK2" />Примітку про конфіденційність<ph name="END_LINK2" /> Chrome.</translation>
 <translation id="5414836363063783498">Підтвердження…</translation>
 <translation id="5423934151118863508">Тут відображатимуться найчастіше відвідувані сторінки</translation>
-<translation id="5424715742813396254">Редагувати збережене ім’я/пароль або виняток</translation>
 <translation id="5437003064129843501">Персоналізовані пропозиції вимкнено, оскільки ваші синхронізовані дані захищено парольною фразою.</translation>
 <translation id="544291274896356069">Якщо ви відкриєте це посилання в зовнішньому додатку, буде вимкнено режим анонімного перегляду. Продовжити?</translation>
 <translation id="5447201525962359567">Усі дані сайтів, зокрема файли cookie й інші локально збережені дані</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Усі сайти</translation>
 <translation id="6320088164292336938">Вібросигнал</translation>
 <translation id="6324034347079777476">Синхронізацію системи Android вимкнено</translation>
-<translation id="6324360525379265737">Автоматично визначати кодування символів</translation>
 <translation id="6333140779060797560">Надіслати через <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Шифрування</translation>
 <translation id="6364438453358674297">Вилучити пропозицію з історії?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Очистити</translation>
 <translation id="6647073004883890710">Оновити пароль користувача <ph name="USERNAME" /> для цього сайту в <ph name="PASSWORD_MANAGER_BRAND" />?</translation>
 <translation id="6656545060687952787">Щоб знаходити пристрої, Chrome потрібний доступ до геоданих. <ph name="BEGIN_LINK" />Оновлити дозволи<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Пароль</translation>
 <translation id="6659594942844771486">Вкладка</translation>
 <translation id="666268767214822976">Показувати підказки зі схожими запитами та популярними веб-сайтами під час введення запиту в адресному рядку</translation>
 <translation id="666981079809192359">Примітка про конфіденційність Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Ваше з’єднання з сайтом приватне, але хтось у мережі може змінювати вигляд сторінки.</translation>
 <translation id="8493948351860045254">Звільнити місце</translation>
 <translation id="8497726226069778601">Тут ще нічого немає…</translation>
+<translation id="8503813439785031346">Ім’я користувача</translation>
 <translation id="8514577642972634246">Перейти в режим анонімного перегляду</translation>
 <translation id="8518901949365209398">На цьому сайті використовується ненадійна конфігурація безпеки (підписи SHA-1), тому ваше з’єднання не конфіденційне.</translation>
 <translation id="8525306231823319788">На весь екран</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb b/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb
index 34526d0..3d1511a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">Dấu trang và lịch sử web</translation>
 <translation id="1549000191223877751">Di chuyển đến cửa sổ khác</translation>
 <translation id="1553358976309200471">Cập nhật Chrome</translation>
-<translation id="1557201757634521564">Tự động phát hiện mã hóa</translation>
 <translation id="1612196535745283361">Chrome cần có quyền truy cập vị trí để quét tìm thiết bị. Tính năng truy cập vị trí bị <ph name="BEGIN_LINK" />tắt cho thiết bị này<ph name="END_LINK" />.</translation>
 <translation id="1620510694547887537">Máy ảnh</translation>
 <translation id="1623104350909869708">Ngăn trang này tạo hộp thoại bổ sung</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">Cụm mật khẩu không khớp</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />Nhận trợ giúp<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">Lưu video</translation>
-<translation id="307329814453917357">Đề xuất dịch các trang bằng Google Dịch</translation>
 <translation id="3089395242580810162">Mở bằng tab ẩn danh</translation>
 <translation id="3090193911106258841">Đang truy cập thiết bị đầu vào video và âm thanh</translation>
 <translation id="3117051980354074377">Để nhận dấu trang trên các thiết bị khác của bạn, hãy đăng nhập vào Chrome.</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">Trang</translation>
 <translation id="4996978546172906250">Chia sẻ qua</translation>
 <translation id="5000922062037820727">Bị chặn (được đề xuất)</translation>
+<translation id="5005498671520578047">Sao chép mật khẩu</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">Cho phép</translation>
 <translation id="5040262127954254034">Bảo mật</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">Kéo từ trên xuống và chạm vào nút quay lại để thoát khỏi chế độ toàn màn hình.</translation>
 <translation id="5284584623296338184">Các thay đổi đối với dấu trang, lịch sử, mật khẩu và cài đặt khác sẽ không còn được đồng bộ hóa với Tài khoản Google của bạn. Tuy nhiên, dữ liệu hiện có của bạn sẽ vẫn được lưu trữ trong tài khoản Google của bạn.</translation>
 <translation id="5301954838959518834">OK</translation>
-<translation id="5302048478445481009">Ngôn ngữ</translation>
 <translation id="5304593522240415983">Không được để trống trường này</translation>
 <translation id="5308380583665731573">Kết nối</translation>
+<translation id="5308603654685598744">Khi tính năng này được bật, Chrome sẽ đề xuất sử dụng Google Dịch để dịch các trang viết bằng ngôn ngữ khác.</translation>
 <translation id="5313967007315987356">Thêm trang web</translation>
 <translation id="5317780077021120954">Lưu</translation>
 <translation id="5324858694974489420">Cài đặt của phụ huynh</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">Bằng cách sử dụng ứng dụng này, bạn đồng ý với <ph name="BEGIN_LINK1" />Điều khoản dịch vụ<ph name="END_LINK1" /> và <ph name="BEGIN_LINK2" />Thông báo bảo mật<ph name="END_LINK2" /> của Chrome.</translation>
 <translation id="5414836363063783498">Đang xác minh...</translation>
 <translation id="5423934151118863508">Trang bạn truy cập nhiều nhất sẽ xuất hiện ở đây</translation>
-<translation id="5424715742813396254">Chỉnh sửa tên/mật khẩu hoặc ngoại lệ đã lưu</translation>
 <translation id="5437003064129843501">Tính năng đề xuất nội dung được cá nhân hóa hiện bị tắt vì dữ liệu đã đồng bộ hóa của bạn được bảo vệ bằng cụm mật khẩu tùy chỉnh.</translation>
 <translation id="544291274896356069">Rời khỏi chế độ ẩn danh nếu liên kết này đã được mở trong một ứng dụng bên ngoài. Tiếp tục?</translation>
 <translation id="5447201525962359567">Tất cả bộ nhớ trang web, bao gồm cookie và các dữ liệu được lưu trữ cục bộ khác</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">Tất cả các trang web</translation>
 <translation id="6320088164292336938">Rung</translation>
 <translation id="6324034347079777476">Đồng bộ hóa hệ thống Android đã bị tắt</translation>
-<translation id="6324360525379265737">Tự động xác định mã hóa ký tự</translation>
 <translation id="6333140779060797560">Chia sẻ qua <ph name="APPLICATION" /></translation>
 <translation id="6337234675334993532">Mã hóa</translation>
 <translation id="6364438453358674297">Xóa đề xuất khỏi lịch sử?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">Xóa</translation>
 <translation id="6647073004883890710">Bạn có muốn <ph name="PASSWORD_MANAGER_BRAND" /> cập nhật mật khẩu cho <ph name="USERNAME" /> cho trang web này không?</translation>
 <translation id="6656545060687952787">Chrome cần có quyền truy cập vị trí để quét tìm thiết bị. <ph name="BEGIN_LINK" />Cập nhật quyền<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">Mật khẩu</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">Sử dụng dịch vụ dự đoán để hiển thị các truy vấn có liên quan và các trang web phổ biến khi bạn nhập vào thanh địa chỉ</translation>
 <translation id="666981079809192359">Thông báo bảo mật của Chrome</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">Kết nối của bạn tới trang web này ở chế độ riêng tư nhưng ai đó trên mạng có thể thay đổi giao diện của trang.</translation>
 <translation id="8493948351860045254">Giải phóng dung lượng</translation>
 <translation id="8497726226069778601">Chưa có gì để xem ở đây...</translation>
+<translation id="8503813439785031346">Tên người dùng</translation>
 <translation id="8514577642972634246">Vào chế độ ẩn danh</translation>
 <translation id="8518901949365209398">Trang web này sử dụng cấu hình bảo mật yếu (chữ ký SHA-1), vì vậy kết nối của bạn có thể không được đảm bảo là riêng tư.</translation>
 <translation id="8525306231823319788">Toàn màn hình</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb b/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
index 19923d1..3b721ecd4 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">书签和网络历史记录</translation>
 <translation id="1549000191223877751">移至其他窗口</translation>
 <translation id="1553358976309200471">更新 Chrome</translation>
-<translation id="1557201757634521564">自动检测编码</translation>
 <translation id="1612196535745283361">Chrome 需要拥有位置信息使用权才能扫描设备。<ph name="BEGIN_LINK" />此设备的位置信息使用权已被停用<ph name="END_LINK" />。</translation>
 <translation id="1620510694547887537">摄像头</translation>
 <translation id="1623104350909869708">阻止此页创建其他对话框</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">密码不匹配</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />获取帮助<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">保存视频</translation>
-<translation id="307329814453917357">询问是否要使用“Google 翻译”来翻译网页内容</translation>
 <translation id="3089395242580810162">在隐身标签页中打开</translation>
 <translation id="3090193911106258841">正在存取音频和视频输入</translation>
 <translation id="3117051980354074377">要在您的其他设备上访问您的书签,请登录 Chrome。</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">页码</translation>
 <translation id="4996978546172906250">分享方式</translation>
 <translation id="5000922062037820727">已阻止(推荐)</translation>
+<translation id="5005498671520578047">复制密码</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">允许</translation>
 <translation id="5040262127954254034">隐私设置</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">从顶部向下拖动并触摸“返回”按钮,即可退出全屏模式。</translation>
 <translation id="5284584623296338184">对您的书签、历史记录、密码和其他设置所做的更改将不再同步到您的 Google 帐户。但是,您的现有数据将继续存储在您的 Google 帐户中。</translation>
 <translation id="5301954838959518834">知道了</translation>
-<translation id="5302048478445481009">语言</translation>
 <translation id="5304593522240415983">此字段不能为空</translation>
 <translation id="5308380583665731573">连接</translation>
+<translation id="5308603654685598744">该功能处于开启状态时,Chrome 将使用 Google 翻译对其他语言的网页进行翻译。</translation>
 <translation id="5313967007315987356">添加网站</translation>
 <translation id="5317780077021120954">保存</translation>
 <translation id="5324858694974489420">家长设置</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">使用此应用即表示您同意遵守 Chrome 的<ph name="BEGIN_LINK1" />服务条款<ph name="END_LINK1" />和<ph name="BEGIN_LINK2" />隐私权声明<ph name="END_LINK2" />。</translation>
 <translation id="5414836363063783498">正在验证…</translation>
 <translation id="5423934151118863508">您最常访问的网页将列在此处</translation>
-<translation id="5424715742813396254">修改已保存的名称/密码或例外情况</translation>
 <translation id="5437003064129843501">您的已同步数据受自定义密码保护,因此个性化内容推荐功能当前已停用。</translation>
 <translation id="544291274896356069">如果在外部应用中打开此链接,您将退出隐身模式。是否继续?</translation>
 <translation id="5447201525962359567">所有网站存储数据,包括 Cookie 及其他本地存储的数据</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">所有网站</translation>
 <translation id="6320088164292336938">振动</translation>
 <translation id="6324034347079777476">Android 系统同步功能已停用</translation>
-<translation id="6324360525379265737">自动判断字符编码</translation>
 <translation id="6333140779060797560">通过<ph name="APPLICATION" />分享</translation>
 <translation id="6337234675334993532">加密</translation>
 <translation id="6364438453358674297">要从历史记录中移除建议吗?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">清除</translation>
 <translation id="6647073004883890710">您希望 <ph name="PASSWORD_MANAGER_BRAND" /> 更新 <ph name="USERNAME" /> 用于登录此网站的密码吗?</translation>
 <translation id="6656545060687952787">Chrome 需要拥有位置信息权限才能扫描设备。<ph name="BEGIN_LINK" />更新权限<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">密码</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">当您在地址栏中输入查询内容时,使用联想查询服务显示相关查询和热门网站</translation>
 <translation id="666981079809192359">Chrome 隐私权声明</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">您与此网站建立的是私密连接,但网络上的某些用户也许能更改此网页的外观。</translation>
 <translation id="8493948351860045254">释放空间</translation>
 <translation id="8497726226069778601">目前还未列出任何网页…</translation>
+<translation id="8503813439785031346">用户名</translation>
 <translation id="8514577642972634246">进入隐身模式</translation>
 <translation id="8518901949365209398">此网站使用了安全系数较低的安全配置(SHA-1 签名),因此您的连接可能不具有私密性。</translation>
 <translation id="8525306231823319788">全屏</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb b/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb
index ebf6a62..93ea9de 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb
@@ -49,7 +49,6 @@
 <translation id="1513352483775369820">書籤與網頁紀錄</translation>
 <translation id="1549000191223877751">移至其他視窗</translation>
 <translation id="1553358976309200471">更新 Chrome</translation>
-<translation id="1557201757634521564">自動偵測編碼</translation>
 <translation id="1612196535745283361">Chrome 需要位置資訊存取權才能掃描裝置。<ph name="BEGIN_LINK" />這個裝置的位置資訊存取權已關閉<ph name="END_LINK" />。</translation>
 <translation id="1620510694547887537">攝影機</translation>
 <translation id="1623104350909869708">防止這個網頁產生其他對話方塊</translation>
@@ -184,7 +183,6 @@
 <translation id="3029704984691124060">通關密語不符</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />取得說明<ph name="END_LINK" /></translation>
 <translation id="3063601790762993062">儲存影片</translation>
-<translation id="307329814453917357">詢問是否透過 Google 翻譯功能來翻譯網頁內容</translation>
 <translation id="3089395242580810162">在無痕式分頁中開啟</translation>
 <translation id="3090193911106258841">正在存取音訊和視訊輸入</translation>
 <translation id="3117051980354074377">如要存取您在其他裝置上建立的書籤,請登入 Chrome。</translation>
@@ -339,6 +337,7 @@
 <translation id="4988526792673242964">頁數</translation>
 <translation id="4996978546172906250">分享方式:</translation>
 <translation id="5000922062037820727">已封鎖 (建議)</translation>
+<translation id="5005498671520578047">複製密碼</translation>
 <translation id="5016205925109358554">Serif</translation>
 <translation id="5039804452771397117">允許</translation>
 <translation id="5040262127954254034">隱私權</translation>
@@ -367,9 +366,9 @@
 <translation id="528192093759286357">從頂端拖曳並輕觸返回按鈕即可結束全螢幕模式。</translation>
 <translation id="5284584623296338184">您更改過的書籤、歷史紀錄、密碼和其他設定不會繼續與您 Google 帳戶中的資料保持同步,但是您 Google 帳戶現有的資料仍會保留。</translation>
 <translation id="5301954838959518834">好,我瞭解了</translation>
-<translation id="5302048478445481009">語言</translation>
 <translation id="5304593522240415983">這個欄位不能留空</translation>
 <translation id="5308380583665731573">連線</translation>
+<translation id="5308603654685598744">開啟這項功能後,Chrome 會使用 Google 翻譯來翻譯其他語言的網頁。</translation>
 <translation id="5313967007315987356">新增網站</translation>
 <translation id="5317780077021120954">儲存</translation>
 <translation id="5324858694974489420">家長設定</translation>
@@ -382,7 +381,6 @@
 <translation id="5400569084694353794">使用這個應用程式即表示您同意接受 Chrome 的《<ph name="BEGIN_LINK1" />服務條款<ph name="END_LINK1" />》和《<ph name="BEGIN_LINK2" />隱私權聲明<ph name="END_LINK2" />》。</translation>
 <translation id="5414836363063783498">驗證中…</translation>
 <translation id="5423934151118863508">這裡會顯示您最常造訪的網頁</translation>
-<translation id="5424715742813396254">編輯已儲存的名稱/密碼或例外</translation>
 <translation id="5437003064129843501">您的同步處理資料受到自訂通關密語保護,因此系統目前無法為您提供個人化的推薦內容。</translation>
 <translation id="544291274896356069">如果使用外部應用程式開啟這個連結,無痕模式就會結束。要繼續嗎?</translation>
 <translation id="5447201525962359567">所有網站儲存的資料,包括 Cookie 和其他儲存在本機上的資料</translation>
@@ -462,7 +460,6 @@
 <translation id="6295158916970320988">所有網站</translation>
 <translation id="6320088164292336938">震動</translation>
 <translation id="6324034347079777476">Android 系統同步處理功能已停用</translation>
-<translation id="6324360525379265737">自動判定字元編碼</translation>
 <translation id="6333140779060797560">透過 <ph name="APPLICATION" /> 分享</translation>
 <translation id="6337234675334993532">加密</translation>
 <translation id="6364438453358674297">從歷史紀錄中移除建議項目?</translation>
@@ -495,6 +492,7 @@
 <translation id="6643016212128521049">清除</translation>
 <translation id="6647073004883890710">您要讓 <ph name="PASSWORD_MANAGER_BRAND" /> 更新 <ph name="USERNAME" /> 在這個網站設定的密碼嗎?</translation>
 <translation id="6656545060687952787">Chrome 需要位置資訊存取權才能掃描裝置。<ph name="BEGIN_LINK" />更新權限<ph name="END_LINK" /></translation>
+<translation id="6657585470893396449">密碼</translation>
 <translation id="6659594942844771486">Tab</translation>
 <translation id="666268767214822976">啟用預測查詢字串服務,讓您在網址列中輸入查詢內容時,能夠即時看到相關查詢和熱門網站</translation>
 <translation id="666981079809192359">Chrome 隱私權聲明</translation>
@@ -656,6 +654,7 @@
 <translation id="8481940801237642152">您與這個網站建立了私人連線,但網路上的其他人可能可以變更網頁的外觀。</translation>
 <translation id="8493948351860045254">釋出空間</translation>
 <translation id="8497726226069778601">目前還沒有任何常用網頁…</translation>
+<translation id="8503813439785031346">使用者名稱</translation>
 <translation id="8514577642972634246">進入無痕模式</translation>
 <translation id="8518901949365209398">這個網站使用的安全性設定強度不足 (SHA-1 簽名),因此您的連線可能不是私人連線。</translation>
 <translation id="8525306231823319788">全螢幕</translation>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index bc88a03..49956971 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -347,6 +347,7 @@
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java",
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunStatus.java",
   "java/src/org/chromium/chrome/browser/firstrun/FirstRunView.java",
+  "java/src/org/chromium/chrome/browser/firstrun/FirstRunViewPager.java",
   "java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java",
   "java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java",
   "java/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiver.java",
@@ -492,6 +493,7 @@
   "java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java",
   "java/src/org/chromium/chrome/browser/notifications/WebApkNotificationClient.java",
   "java/src/org/chromium/chrome/browser/ntp/CurrentlyOpenTab.java",
+  "java/src/org/chromium/chrome/browser/ntp/DisplayStyleObserver.java",
   "java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java",
   "java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java",
   "java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java",
@@ -520,6 +522,7 @@
   "java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java",
   "java/src/org/chromium/chrome/browser/ntp/TitleUtil.java",
   "java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleListItem.java",
+  "java/src/org/chromium/chrome/browser/ntp/UiConfig.java",
   "java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java",
   "java/src/org/chromium/chrome/browser/ntp/snippets/SnippetHeaderListItem.java",
   "java/src/org/chromium/chrome/browser/ntp/snippets/SnippetHeaderViewHolder.java",
@@ -528,6 +531,8 @@
   "java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsLauncher.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/AboveTheFoldListItem.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java",
+  "java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java",
+  "java/src/org/chromium/chrome/browser/ntp/cards/MarginResizer.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageListItem.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java",
@@ -740,6 +745,7 @@
   "java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java",
   "java/src/org/chromium/chrome/browser/preferences/website/StorageInfo.java",
   "java/src/org/chromium/chrome/browser/preferences/website/TranslatePreferences.java",
+  "java/src/org/chromium/chrome/browser/preferences/website/UsbInfo.java",
   "java/src/org/chromium/chrome/browser/preferences/website/Website.java",
   "java/src/org/chromium/chrome/browser/preferences/website/WebsiteAddress.java",
   "java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java",
@@ -1193,6 +1199,7 @@
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java",
+  "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackupIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackupIntegrationTest.java
index 9d86669..469e2090 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackupIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackupIntegrationTest.java
@@ -13,6 +13,7 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.StreamUtil;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
@@ -91,7 +92,13 @@
         MockAccountManager accountManager =
                 new MockAccountManager(mTargetContext, getInstrumentation().getContext(), account);
         AccountManagerHelper.overrideAccountManagerHelperForTests(mTargetContext, accountManager);
-        AccountIdProvider.setInstanceForTest(new MockAccountIdProvider());
+
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                AccountIdProvider.setInstanceForTest(new MockAccountIdProvider());
+            }
+        });
     }
 
     @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
index f7d47e1..503975d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -146,6 +146,30 @@
         });
     }
 
+    /*
+     * Tests that when the disconnection notification comes from a non-UI thread, Chrome doesn't
+     * crash. Non-regression test for crbug.com/623128.
+     */
+    @SmallTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+    public void testPrerenderAndDisconnectOnOtherThread() {
+        final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
+        final Thread otherThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                mCustomTabsConnection.cleanUpSession(token);
+            }
+        });
+
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                otherThread.start();
+            }
+        });
+        // Should not crash, hence no assertions below.
+    }
+
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     public void testMayLaunchUrlKeepsSpareRendererWithoutPrerendering() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
index 12f84b7..5ab5098 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
@@ -9,8 +9,8 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 
+import java.util.ArrayList;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
@@ -19,6 +19,37 @@
  * and user that has 5 addresses stored in autofill settings.
  */
 public class PaymentRequestDynamicShippingMultipleAddressesTest extends PaymentRequestTestBase {
+    private static final AutofillProfile[] AUTOFILL_PROFILES = {
+        // Incomplete profile (missing phone number)
+        new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
+                "Bart Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
+                "90210", "", "US", "", "bart@simpson.com", ""),
+
+        // Incomplete profile.
+        new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
+                "Homer Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
+                "90210", "", "US", "", "homer@simpson.com", ""),
+
+        // Complete profile.
+        new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
+                "Lisa Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
+                "90210", "", "US", "555 123-4567", "lisa@simpson.com", ""),
+
+        // Complete profile in another country.
+        new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
+                "Maggie Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
+                "90210", "", "Uzbekistan", "555 123-4567", "maggie@simpson.com", ""),
+
+        // Incomplete profile.
+        new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
+                "Marge Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
+                "90210", "", "US", "", "marge@simpson.com", "")
+    };
+
+    private AutofillProfile[] mProfilesToAdd;
+    private int[] mCountsToSet;
+    private int[] mDatesToSet;
+
     public PaymentRequestDynamicShippingMultipleAddressesTest() {
         // This merchant requests the shipping address first before providing any shipping options.
         super("payment_request_dynamic_shipping_test.html");
@@ -28,48 +59,17 @@
     public void onMainActivityStarted()
             throws InterruptedException, ExecutionException, TimeoutException {
         AutofillTestHelper helper = new AutofillTestHelper();
-        // Create an incomplete (no phone) profile with the highest frecency score.
-        String guid1 = helper.setProfile(
-                new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
-                        "Bart Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
-                        "90210", "", "US", "", "bart@simpson.com", ""));
 
-        // Create an incomplete (no phone) profile with a the second highest frecency score.
-        String guid2 = helper.setProfile(
-                new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
-                        "Homer Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
-                        "90210", "", "US", "", "homer@simpson.com", ""));
+        // Add the profiles.
+        ArrayList<String> guids = new ArrayList<>();
+        for (int i = 0; i < mProfilesToAdd.length; i++) {
+            guids.add(helper.setProfile(mProfilesToAdd[i]));
+        }
 
-        // Create a complete profile with a middle frecency score.
-        String guid3 = helper.setProfile(
-                new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
-                        "Lisa Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
-                        "90210", "", "US", "555 123-4567", "lisa@simpson.com", ""));
-
-        // Create a complete profile with the second lowest frecency score.
-        String guid4 = helper.setProfile(
-                new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
-                        "Maggie Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
-                        "90210", "", "US", "555 123-4567", "maggie@simpson.com", ""));
-
-        // Create an incomplete profile with the lowest frecency score.
-        String guid5 = helper.setProfile(
-                new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */,
-                        "Marge Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "",
-                        "90210", "", "US", "", "marge@simpson.com", ""));
-
-        // Create a credit card associated witht the fourth profile.
-        helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
-                guid4));
-
-        // Set the use stats so that profile1 has the highest frecency score, profile2 the second
-        // highest, profile 3 the second lowest and profile4 the lowest.
-        helper.setProfileUseStatsForTesting(guid1, 20, 5000);
-        helper.setProfileUseStatsForTesting(guid2, 15, 5000);
-        helper.setProfileUseStatsForTesting(guid3, 10, 5000);
-        helper.setProfileUseStatsForTesting(guid4, 5, 5000);
-        helper.setProfileUseStatsForTesting(guid5, 1, 1);
+        // Set up the profile use stats.
+        for (int i = 0; i < guids.size(); i++) {
+            helper.setProfileUseStatsForTesting(guids.get(i), mCountsToSet[i], mDatesToSet[i]);
+        }
     }
 
     /**
@@ -80,6 +80,14 @@
     @MediumTest
     public void testShippingAddressSuggestionOrdering()
             throws InterruptedException, ExecutionException, TimeoutException {
+        // Create a bunch of profiles, some complete, some incomplete.  Values are set so that the
+        // profiles are ordered by frecency.
+        mProfilesToAdd = new AutofillProfile[] {
+                AUTOFILL_PROFILES[0], AUTOFILL_PROFILES[1], AUTOFILL_PROFILES[2],
+                AUTOFILL_PROFILES[3], AUTOFILL_PROFILES[4]};
+        mCountsToSet = new int[] {20, 15, 10, 5, 1};
+        mDatesToSet = new int[] {5000, 5000, 5000, 5000, 1};
+
         triggerUIAndWait(mReadyForInput);
         clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
         assertEquals(4, getNumberOfShippingAddressSuggestions());
@@ -88,4 +96,30 @@
         assertTrue(getShippingAddressSuggestionLabel(2).contains("Bart Simpson"));
         assertTrue(getShippingAddressSuggestionLabel(3).contains("Homer Simpson"));
     }
+
+    /**
+     * Select a shipping address that the website refuses to accept, which should force the dialog
+     * to show an error.
+     */
+    @MediumTest
+    public void testShippingAddresNotAcceptedByMerchant()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        // Add a profile that is not accepted by the website.
+        mProfilesToAdd = new AutofillProfile[] {AUTOFILL_PROFILES[3]};
+        mCountsToSet = new int[] {5};
+        mDatesToSet = new int[] {5000};
+
+        // Click on the unacceptable shipping address.
+        triggerUIAndWait(mReadyForInput);
+        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        assertTrue(getShippingAddressSuggestionLabel(0).contains(
+                AUTOFILL_PROFILES[3].getFullName()));
+        clickOnShippingAddressSuggestionOptionAndWait(0, mSelectionChecked);
+
+        // The string should indicate that the shipping address isn't valid.
+        CharSequence actualString = getShippingAddressOptionRowAtIndex(0).getLabelText();
+        CharSequence expectedString = getInstrumentation().getTargetContext().getString(
+                R.string.payments_unsupported_shipping_address);
+        assertEquals(expectedString, actualString);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
index 85c368e2..5ab4d87 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
@@ -4,14 +4,18 @@
 
 package org.chromium.chrome.browser.payments;
 
+import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
+
 import android.content.DialogInterface;
 import android.test.suitebuilder.annotation.MediumTest;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestSection;
 
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
@@ -44,7 +48,7 @@
     public void testAddressNotSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
         triggerUIAndWait(mReadyForInput);
-        assertEquals("Select shipping", getAddressSectionLabel());
+        assertEquals(PaymentRequestSection.EDIT_BUTTON_SELECT, getSummarySectionButtonState());
     }
 
     /** Expand the shipping address section, select an address, and click "Pay." */
@@ -77,6 +81,7 @@
 
     /** Add a valid address and complete the transaction. */
     @MediumTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) // crbug.com/626289
     public void testAddAddressAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         triggerUIAndWait(mReadyForInput);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
new file mode 100644
index 0000000..137694bc
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
@@ -0,0 +1,114 @@
+// Copyright 2016 The Chromium 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.payments;
+
+import android.content.DialogInterface;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.autofill.AutofillTestHelper;
+import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
+import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A payment integration test for a merchant that requests payment via Bob Pay or cards.
+ */
+public class PaymentRequestPaymentAppAndCardsTest extends PaymentRequestTestBase {
+    public PaymentRequestPaymentAppAndCardsTest() {
+        super("payment_request_bobpay_and_cards_test.html");
+    }
+
+    @Override
+    public void onMainActivityStarted() throws InterruptedException, ExecutionException,
+            TimeoutException {
+        AutofillTestHelper helper = new AutofillTestHelper();
+        String billingAddressId = helper.setProfile(new AutofillProfile("", "https://example.com",
+                true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
+                "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
+        // Mastercard card without a billing address.
+        helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
+                "5454545454545454", "", "12", "2050", "mastercard", R.drawable.pr_mc,
+                ""));
+        // Visa card with complete set of information.
+        helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
+                "4111111111111111", "", "12", "2050", "visa", R.drawable.pr_visa,
+                billingAddressId));
+    }
+
+    /**
+     * If Bob Pay does not have any instruments, show [visa, mastercard]. Here the payment app
+     * responds quickly.
+     */
+    @MediumTest
+    public void testNoInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
+            TimeoutException {
+        runTest(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
+    }
+
+    /**
+     * If Bob Pay does not have any instruments, show [visa, mastercard]. Here the payment app
+     * responds slowly.
+     */
+    @MediumTest
+    public void testNoInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
+            TimeoutException {
+        runTest(NO_INSTRUMENTS, DELAYED_RESPONSE);
+    }
+
+    /**
+     * If Bob Pay has instruments, show [bobpay, visa, mastercard]. Here the payment app responds
+     * quickly.
+     */
+    @MediumTest
+    public void testHaveInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
+            TimeoutException {
+        runTest(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
+    }
+
+    /**
+     * If Bob Pay has instruments, show [bobpay, visa, mastercard]. Here the payment app responds
+     * slowly.
+     */
+    @MediumTest
+    public void testHaveInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
+            TimeoutException {
+        runTest(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
+    }
+
+    private void runTest(int instrumentPresence, int responseSpeed) throws InterruptedException,
+            ExecutionException, TimeoutException  {
+        installPaymentApp(instrumentPresence, responseSpeed);
+        triggerUIAndWait(mReadyToPay);
+        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+
+        // Check the number of instruments.
+        assertEquals(
+                instrumentPresence == HAVE_INSTRUMENTS ? 3 : 2, getNumberOfPaymentInstruments());
+
+        // Check the labesl of the instruments.
+        int i = 0;
+        if (instrumentPresence == HAVE_INSTRUMENTS) {
+            assertEquals("Bob Pay", getPaymentInstrumentLabel(i++));
+        }
+        // \u00A0\u22EF is a non-breaking space followed by a midline ellipsis.
+        assertEquals("Visa\u00A0\u22EF1111\nJon Doe", getPaymentInstrumentLabel(i++));
+        assertEquals("MasterCard\u00A0\u22EF5454\nJon Doe", getPaymentInstrumentLabel(i++));
+
+        // Check the output of the selected instrument.
+        if (instrumentPresence == HAVE_INSTRUMENTS) {
+            clickAndWait(R.id.button_primary, mDismissed);
+            expectResultContains(new String[]{"https://bobpay.com", "\"transaction\"", "1337"});
+        } else {
+            clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
+            setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
+            clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+            expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
+                    "123"});
+        }
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
index 63ad47f..8c17d12 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
@@ -4,20 +4,10 @@
 
 package org.chromium.chrome.browser.payments;
 
-import android.os.Handler;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.mojom.payments.PaymentItem;
-import org.json.JSONObject;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
@@ -25,12 +15,6 @@
  * A payment integration test for a merchant that requests payment via Bob Pay.
  */
 public class PaymentRequestPaymentAppTest extends PaymentRequestTestBase {
-    private static final int NO_INSTRUMENTS = 0;
-    private static final int HAVE_INSTRUMENTS = 1;
-
-    private static final int IMMEDIATE_RESPONSE = 0;
-    private static final int DELAYED_RESPONSE = 1;
-
     public PaymentRequestPaymentAppTest() {
         super("payment_request_bobpay_test.html");
     }
@@ -55,7 +39,7 @@
     @MediumTest
     public void testNoInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
-        installBobPay(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
+        installPaymentApp(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
         triggerUIAndWait(mShowFailed);
         expectResultContains(
                 new String[]{"show() rejected", "The payment method is not supported"});
@@ -68,7 +52,7 @@
     @MediumTest
     public void testNoInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
-        installBobPay(NO_INSTRUMENTS, DELAYED_RESPONSE);
+        installPaymentApp(NO_INSTRUMENTS, DELAYED_RESPONSE);
         triggerUIAndWait(mShowFailed);
         expectResultContains(
                 new String[]{"show() rejected", "The payment method is not supported"});
@@ -81,7 +65,7 @@
     @MediumTest
     public void testPayViaFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
-        installBobPay(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
+        installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
         triggerUIAndWait(mReadyToPay);
         clickAndWait(R.id.button_primary, mDismissed);
         expectResultContains(new String[]{"https://bobpay.com", "\"transaction\"", "1337"});
@@ -94,92 +78,9 @@
     @MediumTest
     public void testPayViaSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
-        installBobPay(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
+        installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
         triggerUIAndWait(mReadyToPay);
         clickAndWait(R.id.button_primary, mDismissed);
         expectResultContains(new String[]{"https://bobpay.com", "\"transaction\"", "1337"});
     }
-
-    /**
-     * Installs a payment app for testing.
-     *
-     * @param instrumentPresence Whether Bob Pay has any payment instruments. Either NO_INSTRUMENTS
-     *                           or HAVE_INSTRUMENTS.
-     * @param responseSpeed      How quickly Bob Pay will respond to "get instruments" query. Either
-     *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
-     */
-    private void installBobPay(final int instrumentPresence, final int responseSpeed) {
-        PaymentAppFactory.setAdditionalFactory(new PaymentAppFactoryAddition() {
-            @Override
-            public List<PaymentApp> create(WebContents webContents) {
-                List<PaymentApp> additionalApps = new ArrayList<>();
-                additionalApps.add(new BobPay(instrumentPresence, responseSpeed));
-                return additionalApps;
-            }
-        });
-    }
-
-    /** A payment app implementation for test. */
-    private static class BobPay implements PaymentApp {
-        private final int mInstrumentPresence;
-        private final int mResponseSpeed;
-
-        BobPay(int instrumentPresence, int responseSpeed) {
-            mInstrumentPresence = instrumentPresence;
-            mResponseSpeed = responseSpeed;
-        }
-
-        @Override
-        public void getInstruments(JSONObject details, final InstrumentsCallback
-                instrumentsCallback) {
-            final List<PaymentInstrument> instruments = new ArrayList<>();
-            if (mInstrumentPresence == HAVE_INSTRUMENTS) instruments.add(new BobPayInstrument());
-            Runnable instrumentsReady = new Runnable() {
-                @Override
-                public void run() {
-                    ThreadUtils.assertOnUiThread();
-                    instrumentsCallback.onInstrumentsReady(BobPay.this, instruments);
-                }
-            };
-            if (mResponseSpeed == IMMEDIATE_RESPONSE) {
-                instrumentsReady.run();
-            } else {
-                new Handler().postDelayed(instrumentsReady, 100);
-            }
-        }
-
-        @Override
-        public Set<String> getSupportedMethodNames() {
-            Set<String> methodNames = new HashSet<>();
-            methodNames.add("https://bobpay.com");
-            return methodNames;
-        }
-
-        @Override
-        public String getIdentifier() {
-            return "https://bobpay.com";
-        }
-    }
-
-    /** A payment instrument implementation for test. */
-    private static class BobPayInstrument extends PaymentInstrument {
-        BobPayInstrument() {
-            super("https://bobpay.com", "Bob Pay", null, NO_ICON);
-        }
-
-        @Override
-        public String getMethodName() {
-            return "https://bobpay.com";
-        }
-
-        @Override
-        public void getDetails(String merchantName, String origin, PaymentItem total,
-                List<PaymentItem> cart, JSONObject details, DetailsCallback detailsCallback) {
-            detailsCallback.onInstrumentDetailsReady(
-                    "https://bobpay.com", "{\"transaction\": 1337}");
-        }
-
-        @Override
-        public void dismiss() {}
-    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
index a138fb422..82fd8847 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
@@ -4,12 +4,12 @@
 
 package org.chromium.chrome.browser.payments;
 
+import android.os.Handler;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.CheckBox;
 import android.widget.EditText;
 import android.widget.Spinner;
-import android.widget.TextView;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.UrlUtils;
@@ -17,9 +17,11 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.autofill.CardUnmaskPrompt;
 import org.chromium.chrome.browser.autofill.CardUnmaskPrompt.CardUnmaskObserverForTest;
+import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition;
 import org.chromium.chrome.browser.payments.PaymentRequestImpl.PaymentRequestServiceObserverForTest;
 import org.chromium.chrome.browser.payments.ui.EditorTextField;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.OptionRow;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest;
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
@@ -29,8 +31,13 @@
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.mojom.payments.PaymentItem;
+import org.json.JSONObject;
 
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
@@ -42,9 +49,22 @@
 abstract class PaymentRequestTestBase extends ChromeActivityTestCaseBase<ChromeActivity>
         implements PaymentRequestObserverForTest, PaymentRequestServiceObserverForTest,
         CardUnmaskObserverForTest {
+    /** Flag for installing a payment app without instruments. */
+    protected static final int NO_INSTRUMENTS = 0;
+
+    /** Flag for installing a payment app with instruments. */
+    protected static final int HAVE_INSTRUMENTS = 1;
+
+    /** Flag for installing a fast payment app. */
+    protected static final int IMMEDIATE_RESPONSE = 0;
+
+    /** Flag for installing a slow payment app. */
+    protected static final int DELAYED_RESPONSE = 1;
+
     protected final PaymentsCallbackHelper<PaymentRequestUI> mReadyForInput;
     protected final PaymentsCallbackHelper<PaymentRequestUI> mReadyToPay;
     protected final PaymentsCallbackHelper<PaymentRequestUI> mReadyToClose;
+    protected final PaymentsCallbackHelper<PaymentRequestUI> mSelectionChecked;
     protected final PaymentsCallbackHelper<PaymentRequestUI> mResultReady;
     protected final PaymentsCallbackHelper<CardUnmaskPrompt> mReadyForUnmaskInput;
     protected final PaymentsCallbackHelper<CardUnmaskPrompt> mReadyToUnmask;
@@ -67,6 +87,7 @@
         mReadyForInput = new PaymentsCallbackHelper<>();
         mReadyToPay = new PaymentsCallbackHelper<>();
         mReadyToClose = new PaymentsCallbackHelper<>();
+        mSelectionChecked = new PaymentsCallbackHelper<>();
         mResultReady = new PaymentsCallbackHelper<>();
         mReadyForUnmaskInput = new PaymentsCallbackHelper<>();
         mReadyToUnmask = new PaymentsCallbackHelper<>();
@@ -229,13 +250,23 @@
         helper.waitForCallback(callCount);
     }
 
-    /** Returns the left summary label of the "Shipping summary" section. */
-    protected String getAddressSectionLabel() throws ExecutionException {
+    /** Gets the button state for the shipping summary section. */
+    protected int getSummarySectionButtonState() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return mUI.getShippingSummarySectionForTest().getEditButtonState();
+            }
+        });
+    }
+
+    /**  Returns the label corresponding to the payment instrument at the specified |index|. */
+    protected String getPaymentInstrumentLabel(final int index) throws ExecutionException {
         return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
             @Override
             public String call() {
-                return ((TextView) mUI.getShippingSummarySectionForTest().findViewById(
-                        R.id.payments_left_summary_label)).getText().toString();
+                return ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                        .getOptionLabelsForTest(index).getText().toString();
             }
         });
     }
@@ -246,8 +277,6 @@
      */
     protected String getContactDetailsSuggestionLabel(final int suggestionIndex)
             throws ExecutionException {
-        assert (suggestionIndex < getNumberOfContactDetailSuggestions());
-
         return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
             @Override
             public String call() {
@@ -257,9 +286,18 @@
         });
     }
 
-    /**
-     *  Returns the the number of contact detail suggestions,
-     */
+    /**  Returns the the number of payment instruments. */
+    protected int getNumberOfPaymentInstruments() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                        .getNumberOfOptionLabelsForTest();
+            }
+        });
+    }
+
+    /**  Returns the the number of contact detail suggestions. */
     protected int getNumberOfContactDetailSuggestions() throws ExecutionException {
         return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
             @Override
@@ -288,7 +326,28 @@
     }
 
     /**
-     *  Returns the the number of shipping address suggestions,
+     *  Clicks on the label corresponding to the shipping address suggestion at the specified
+     *  |suggestionIndex|.
+     * @throws InterruptedException
+     */
+    protected void clickOnShippingAddressSuggestionOptionAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+                    throws ExecutionException, TimeoutException, InterruptedException {
+        assert (suggestionIndex < getNumberOfShippingAddressSuggestions());
+
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ((OptionSection) mUI.getShippingAddressSectionForTest())
+                        .getOptionLabelsForTest(suggestionIndex).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    /**
+     *  Returns the the number of shipping address suggestions.
      */
     protected int getNumberOfShippingAddressSuggestions() throws ExecutionException {
         return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
@@ -300,6 +359,18 @@
         });
     }
 
+    /** Returns the {@link OptionRow} at the given index for the shipping address section. */
+    protected OptionRow getShippingAddressOptionRowAtIndex(final int index)
+            throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<OptionRow>() {
+            @Override
+            public OptionRow call() {
+                return ((OptionSection) mUI.getShippingAddressSectionForTest())
+                        .getOptionRowAtIndex(index);
+            }
+        });
+    }
+
     /** Selects the spinner value in the editor UI for credit cards. */
     protected void setSpinnerSelectionsInCardEditorAndWait(final int[] selections,
             CallbackHelper helper) throws InterruptedException, TimeoutException {
@@ -460,6 +531,12 @@
     }
 
     @Override
+    public void onPaymentRequestSelectionChecked(PaymentRequestUI ui) {
+        ThreadUtils.assertOnUiThread();
+        mSelectionChecked.notifyCalled(ui);
+    }
+
+    @Override
     public void onPaymentRequestResultReady(PaymentRequestUI ui) {
         ThreadUtils.assertOnUiThread();
         mResultReady.notifyCalled(ui);
@@ -528,4 +605,87 @@
             notifyCalled();
         }
     }
+
+    /**
+     * Installs a payment app for testing.
+     *
+     * @param instrumentPresence Whether the app has any payment instruments. Either NO_INSTRUMENTS
+     *                           or HAVE_INSTRUMENTS.
+     * @param responseSpeed      How quickly the app will respond to "get instruments" query. Either
+     *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
+     */
+    protected void installPaymentApp(final int instrumentPresence, final int responseSpeed) {
+        PaymentAppFactory.setAdditionalFactory(new PaymentAppFactoryAddition() {
+            @Override
+            public List<PaymentApp> create(WebContents webContents) {
+                List<PaymentApp> additionalApps = new ArrayList<>();
+                additionalApps.add(new BobPay(instrumentPresence, responseSpeed));
+                return additionalApps;
+            }
+        });
+    }
+
+    /** A payment app implementation for test. */
+    private static class BobPay implements PaymentApp {
+        private final int mInstrumentPresence;
+        private final int mResponseSpeed;
+
+        BobPay(int instrumentPresence, int responseSpeed) {
+            mInstrumentPresence = instrumentPresence;
+            mResponseSpeed = responseSpeed;
+        }
+
+        @Override
+        public void getInstruments(JSONObject details, final InstrumentsCallback
+                instrumentsCallback) {
+            final List<PaymentInstrument> instruments = new ArrayList<>();
+            if (mInstrumentPresence == HAVE_INSTRUMENTS) instruments.add(new BobPayInstrument());
+            Runnable instrumentsReady = new Runnable() {
+                @Override
+                public void run() {
+                    ThreadUtils.assertOnUiThread();
+                    instrumentsCallback.onInstrumentsReady(BobPay.this, instruments);
+                }
+            };
+            if (mResponseSpeed == IMMEDIATE_RESPONSE) {
+                instrumentsReady.run();
+            } else {
+                new Handler().postDelayed(instrumentsReady, 100);
+            }
+        }
+
+        @Override
+        public Set<String> getSupportedMethodNames() {
+            Set<String> methodNames = new HashSet<>();
+            methodNames.add("https://bobpay.com");
+            return methodNames;
+        }
+
+        @Override
+        public String getIdentifier() {
+            return "https://bobpay.com";
+        }
+    }
+
+    /** A payment instrument implementation for test. */
+    private static class BobPayInstrument extends PaymentInstrument {
+        BobPayInstrument() {
+            super("https://bobpay.com", "Bob Pay", null, NO_ICON);
+        }
+
+        @Override
+        public String getMethodName() {
+            return "https://bobpay.com";
+        }
+
+        @Override
+        public void getDetails(String merchantName, String origin, PaymentItem total,
+                List<PaymentItem> cart, JSONObject details, DetailsCallback detailsCallback) {
+            detailsCallback.onInstrumentDetailsReady(
+                    "https://bobpay.com", "{\"transaction\": 1337}");
+        }
+
+        @Override
+        public void dismiss() {}
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 0abac9d..3de31cf 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -63,7 +63,8 @@
     @Test
     @Feature({"Ntp"})
     public void testSnippetLoading() {
-        NewTabPageAdapter ntpa = new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge);
+        NewTabPageAdapter ntpa =
+                new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge, null);
 
         assertEquals(4, ntpa.getItemCount());
         assertEquals(NewTabPageListItem.VIEW_TYPE_ABOVE_THE_FOLD, ntpa.getItemViewType(0));
@@ -95,7 +96,8 @@
     @Test
     @Feature({"Ntp"})
     public void testSnippetLoadingInitiallyEmpty() {
-        NewTabPageAdapter ntpa = new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge);
+        NewTabPageAdapter ntpa =
+                new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge, null);
 
         // If we don't get anything, we should be in the same situation as the initial one.
         mSnippetsObserver.onSnippetsReceived(new ArrayList<SnippetArticleListItem>());
@@ -128,7 +130,8 @@
     @Test
     @Feature({"Ntp"})
     public void testSnippetClearing() {
-        NewTabPageAdapter ntpa = new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge);
+        NewTabPageAdapter ntpa =
+                new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge, null);
 
         List<SnippetArticleListItem> snippets = createDummySnippets();
         mSnippetsObserver.onSnippetsReceived(snippets);
@@ -156,7 +159,8 @@
     @Test
     @Feature({"Ntp"})
     public void testSnippetLoadingBlock() {
-        NewTabPageAdapter ntpa = new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge);
+        NewTabPageAdapter ntpa =
+                new NewTabPageAdapter(mNewTabPageManager, null, mSnippetsBridge, null);
 
         List<SnippetArticleListItem> snippets = createDummySnippets();
 
diff --git a/chrome/android/webapk/shell_apk/DEPS b/chrome/android/webapk/shell_apk/DEPS
index e841ef2..a8953d02 100644
--- a/chrome/android/webapk/shell_apk/DEPS
+++ b/chrome/android/webapk/shell_apk/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
   "+chrome/android/webapk/libs/common",
-  "+chrome/android/webapk/libs/runtime_library",
 ]
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 74143e1..f9f0561 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1386,6 +1386,12 @@
   <message name="IDS_FLAGS_FULLSCREEN_APP_LIST_DESCRIPTION" desc="Description for the flag to enable experimental fullscreen app list.">
     The app-list will appear as fullscreen mode when it's in touch view mode. This flag does nothing outside of the mode.
   </message>
+  <message name="IDS_FLAGS_QUICK_UNLOCK_PIN" desc="Title of the flag used to enable quick unlock pin.">
+    Quick Unlock (PIN)
+  </message>
+  <message name="IDS_FLAGS_QUICK_UNLOCK_PIN_DESCRIPTION" desc="Description of the flag used to enable quick unlock pin.">
+    Enabling PIN quick unlock allows you to use a PIN to unlock your Chromebook on the lock screen after you have signed into your device.
+  </message>
   <message name="IDS_FLAGS_STORAGE_MANAGER_NAME" desc="Description for the flag to enable experimental storage manager.">
     Storage manager
   </message>
@@ -6801,22 +6807,22 @@
     Terms of Service
   </message>
   <message name="IDS_ARC_OPT_IN_DIALOG_METRICS_MANAGED_ENABLED" desc="Message in the opt-in dialog for Android apps in case metrics are managed on the device and on.">
-    This device will automatically send diagnostic and usage data to Google. This <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>setting<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> is enforced by your administrator. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+    This device currently sends diagnostic and usage data to Google. This <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>setting<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> is enforced by the owner. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_ARC_OPT_IN_DIALOG_METRICS_MANAGED_DISABLED" desc="Message in the opt-in dialog for Android apps in case metrics are enabled on the device and off.">
-    Your administrator may choose to send diagnostic and usage data for this device to Google. You may view this <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>setting<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> here. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+    The owner may choose to send diagnostic and usage data for this device to Google. You may view this <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>setting<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> here. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_ARC_OPT_IN_DIALOG_METRICS_ENABLED" desc="Message in the opt-in dialog for Android apps in case metrics are already enabled on the device. User has no way to deactivate them using opt-in dialog.">
-    This device will automatically send diagnostic and usage data to Google. You can change this at any time in your device <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>settings<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+    This device currently sends diagnostic and usage data to Google. You can change this at any time in your device <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>settings<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_ARC_OPT_IN_DIALOG_METRICS_DISABLED" desc="Message in the opt-in dialog for Android apps in case metrics are disabled on the device. User has an option to active them using opt-in dialog">
     Automatically send diagnostic and usage data to Google. You can change this at any time in your device <ph name="BEGIN_LINK1">&lt;a href="#" id="settings-link"&gt;</ph>settings<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>. <ph name="BEGIN_LINK2">&lt;a href="#" id="learn-more-link-metrics"&gt;</ph>Learn More<ph name="END_LINK2">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE" desc="Message in the opt-in dialog for users to enable Backup and Restore for Android apps.">
-    Automatically back up and restore Play app data to Google Drive. You can change this in Android Settings at any time. <ph name="BEGIN_LINK1">&lt;a href="#" id="learn-more-link-backup-restore"&gt;</ph>Learn More<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+    Automatically back up and restore Play app data to Google Drive. <ph name="BEGIN_LINK1">&lt;a href="#" id="learn-more-link-backup-restore"&gt;</ph>Learn More<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_ARC_OPT_IN_LOCATION_SETTING" desc="Message in the opt-in dialog for Android apps for the user to turn on Google location services">
-    Let Google’s location service help apps find your location quickly and accurately, which can reduce battery consumption. Anonymous location data will be sent to Google, even when no apps are running.
+    Let Google’s location service help apps find your location quickly and accurately, which can reduce battery consumption. Anonymous location data will be sent to Google, even when no apps are running. <ph name="BEGIN_LINK1">&lt;a href="#" id="learn-more-link-location-service"&gt;</ph>Learn More<ph name="END_LINK1">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_ARC_OPT_IN_SCANNING_SETTING" desc="Message in the opt-in dialog for Android apps for the user to enable wifi and bluetooth scanning to improve location">
     Improve location accuracy by allowing apps and services to scan for Wi-Fi networks and Bluetooth devices.
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 90ae5e5..03e8c57 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1801,10 +1801,6 @@
                desc="Text for the button used to stop a dangerous download.">
         Discard
       </message>
-      <message name="IDS_DISMISS_DOWNLOAD"
-               desc="Text for the button used to dismiss a malicious download notification.">
-        Dismiss
-      </message>
 
       <!-- Download Tab Items -->
       <message name="IDS_DOWNLOAD_LINK_PAUSE"
@@ -5558,7 +5554,7 @@
         Panels
       </message>
       <message name="IDS_FLAGS_PANELS_DESCRIPTION" desc="Description for the flag to enable Panel windows.">
-        Allow extensions to create panel windows that open outside of the browser frame. By default or if disabled, an attempt to open a panel will open a popup instead. Panels on desktop OSes are deprecated and will be removed soon.
+        Allow extensions to create panel windows that open outside of the browser frame. Attempts to open a panel will open a popup instead if not enabled. Default behavior is to allow only for whitelisted extensions. Enabled behavior is to allow for all extensions. Disabled behavior is to disallow panels for any extension.
       </message>
       <message name="IDS_FLAGS_WEBGL2_NAME" desc="Name of the 'Enable WebGL 2.0' flag.">
         WebGL 2.0 Prototype
diff --git a/chrome/app/nibs/DownloadItem.xib b/chrome/app/nibs/DownloadItem.xib
index 2a2e659..bd7ab5801 100644
--- a/chrome/app/nibs/DownloadItem.xib
+++ b/chrome/app/nibs/DownloadItem.xib
@@ -93,12 +93,12 @@
                                     <button verticalHuggingPriority="750" id="106">
                                         <rect key="frame" x="5" y="16" width="110" height="28"/>
                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
-                                        <buttonCell key="cell" type="push" title="^IDS_DISMISS_DOWNLOAD" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="109">
+                                        <buttonCell key="cell" type="push" title="^IDS_DISCARD_DOWNLOAD" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="109">
                                             <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                                             <font key="font" metaFont="smallSystem"/>
                                         </buttonCell>
                                         <connections>
-                                            <action selector="dismissMaliciousDownload:" target="-2" id="114"/>
+                                            <action selector="discardDownload:" target="-2" id="114"/>
                                         </connections>
                                     </button>
                                     <button horizontalHuggingPriority="750" verticalHuggingPriority="750" id="107">
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 43c2e87..39f01c1 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">የአሰሳ ውሂብ አፅዳ የንግግር ሳጥን ውስጥ የውሂብ መጠን መቁጠሪያዎችን ያሳያል።</translation>
 <translation id="1097507499312291972">ይህ ሰው የሚጎበኛቸውን ድር ጣቢያዎች ለመቆጣጠር እና ለመመልከት <ph name="BEGIN_SIGN_IN_LINK" />በመለያ ይግቡ<ph name="END_SIGN_IN_LINK" />።</translation>
 <translation id="1097658378307015415">ከመግባትዎ በፊት አውታረ መረብ <ph name="NETWORK_ID" />ን ለማንቃት እባክዎ እንደ እንግዳ ይግቡ</translation>
-<translation id="1104054824888299003">ረጅም</translation>
 <translation id="1104652314727136854">ለChrome መተግበሪያዎች የፋይል ዝምድናዎች OS ማካተትን አንቃ።</translation>
 <translation id="1105162038795579389">«<ph name="BUNDLE_NAME" />» እነዚህን መተግበሪያዎች እና ቅጥያዎች ለ«<ph name="USER_NAME" />» ያክላል፦</translation>
 <translation id="1108600514891325577">&amp;አቁም</translation>
@@ -1870,7 +1869,6 @@
 <translation id="3512284449647229026">አሳሹ ከመስመር ውጭ በሚሆንበት ጊዜ ለመጫን ያልቻሉ ገጾች በራስ-ሰር ዳግም የሚጫኑት ትራቸው የሚታይ ብቻ ከሆነ ነው።</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ማውረድን ተወው}one{ማውረዶችን ተዋቸው}other{ማውረዶችን ተዋቸው}}</translation>
 <translation id="3512810056947640266">ዩአርኤል (ከተፈለገ)፦</translation>
-<translation id="351486934407749662">በጣም ረጅም</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> የማያ ገጽዎን ይዘቶች ማጋራት ይፈልጋል። ምን ማጋራት እንደሚፈልጉ ይምረጡ።</translation>
 <translation id="3518086201899641494">የተያዥ መግቢያ በሮች ማሳውቂያዎች</translation>
 <translation id="3519867315646775981">በቋንቋ ፊደል መጻፍ (shalom ← שלום)</translation>
@@ -3402,7 +3400,6 @@
 <translation id="569109051430110155">ራስ ፈልግ</translation>
 <translation id="5691596662111998220">ውይ፣ <ph name="FILE_NAME" /> ከአሁን በኋላ የለም።</translation>
 <translation id="5694501201003948907">$1 ንጥሎችን በማጨቅ ላይ...</translation>
-<translation id="5695323626817702678">አጭር</translation>
 <translation id="5697118958262594262">አስፈላጊ ይዘትን በነባሪነት አግኝ</translation>
 <translation id="5699533844376998780">የ«<ph name="EXTENSION_NAME" />» ቅጥያው ታክሏል።</translation>
 <translation id="5701101281789450335">የቋንቋ እና የግቤት ቅንብሮች...</translation>
@@ -3826,7 +3823,6 @@
 <translation id="630065524203833229">ው&amp;ጣ</translation>
 <translation id="6304217058163308077">አዲሱ የዕልባት መተግበሪያ ስርዓት</translation>
 <translation id="6305012486838822927">የላኦ ቁልፍ ሰሌዳ</translation>
-<translation id="6305328361606238230">የግፋ መልዕክቶችን ይቀበሉ</translation>
 <translation id="6307722552931206656">Google የስም አገልጋዮች - <ph name="BEGIN_LINK" />ተጨማሪ ለመረዳት<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">ስርዓቱ ስራ ላይ ነው</translation>
 <translation id="6308937455967653460">አገ&amp;ናኝ አስቀምጥ እንደ…</translation>
@@ -4523,7 +4519,6 @@
 <translation id="7339785458027436441">በሚጽፉበት ጊዜ ሆሄ ያረጋግጡ</translation>
 <translation id="7339898014177206373">አዲሰ መስኮት</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> አሁን በሙሉ ማያ ገጽ ላይ ነው።</translation>
-<translation id="7341982465543599097">እጅግ በጣም አጭር</translation>
 <translation id="734303607351427494">የፍለጋ ፕሮግራሞችን ያቀናብሩ...</translation>
 <translation id="7343116142376328522">ማንኛውም ጣቢያ በቅጾች ውስጥ የቁልፍ ማመንጫትን እንዲጠቀም አትፍቀድ (የሚመከር)</translation>
 <translation id="7345706641791090287">የይለፍ ቃልዎን ያረጋግጡ</translation>
@@ -4907,7 +4902,6 @@
 <translation id="7881969471599061635">የግርጌ ጽሑፎችን አሰናክል</translation>
 <translation id="7884988936047469945">የሙከራ የተዳራሽነት ባህሪያት</translation>
 <translation id="7885253890047913815">የቅርብ ጊዜ መድረሻዎች</translation>
-<translation id="7885283703487484916">በጣም አጭር</translation>
 <translation id="7887192723714330082">ማያ ገጹ በርቶ እና ተከፍቶ ሳለ ለ«Ok Google» ምላሽ መስጠት</translation>
 <translation id="7887334752153342268">አባዛ</translation>
 <translation id="7887864092952184874">የብሉቱዝ መዳፊት ተጣምሯል</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index a250dc9..85ea8298 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">تعرض عدادات حجم البيانات في مربع حوار محو بيانات التصفح.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />سجّل الدخول<ph name="END_SIGN_IN_LINK" /> للتحكم في مواقع الويب التي يزورها هذا الشخص وعرضها.</translation>
 <translation id="1097658378307015415">قبل تسجيل الدخول، الرجاء الدخول كضيف لتنشيط الشبكة <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">طويل</translation>
 <translation id="1104652314727136854">‏تمكين تكامل نظام التشغيل لارتباطات الملف لتطبيقات Chrome.</translation>
 <translation id="1105162038795579389">حزمة "<ph name="BUNDLE_NAME" />" تضيف هذه التطبيقات والإضافات لـ <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">إي&amp;قاف</translation>
@@ -1869,7 +1868,6 @@
 <translation id="3512284449647229026">لن تتم إعادة التحميل التلقائي للصفحات التي يخفق تحميلها أثناء عدم اتصال المتصفح بالإنترنت، إلا إذا كانت علامة تبويبها مرئية.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{إلغاء التنزيل}zero{إلغاء التنزيلات}two{إلغاء تنزيلين}few{إلغاء التنزيلات}many{إلغاء التنزيلات}other{إلغاء التنزيلات}}</translation>
 <translation id="3512810056947640266">‏عنوان URL (اختياري):</translation>
-<translation id="351486934407749662">طويل جدًا</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> يود أن يشارك محتويات شاشتك. اختر ما ترغب في مشاركته.</translation>
 <translation id="3518086201899641494">إشعارات حول بوابات التقييد</translation>
 <translation id="3519867315646775981">التحويل الصوتي (שלום ← شالوم)</translation>
@@ -3399,7 +3397,6 @@
 <translation id="569109051430110155">الكشف التلقائيّ</translation>
 <translation id="5691596662111998220">عذرًا، لم يعد <ph name="FILE_NAME" /> متوفرًا.</translation>
 <translation id="5694501201003948907">جارٍ ضغط $1 من العناصر...</translation>
-<translation id="5695323626817702678">قصير</translation>
 <translation id="5697118958262594262">كشف محتوى مهم افتراضيًا</translation>
 <translation id="5699533844376998780">تم إضافة الإضافة "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">إعدادات اللغة والإدخال...</translation>
@@ -3823,7 +3820,6 @@
 <translation id="630065524203833229">إن&amp;هاء</translation>
 <translation id="6304217058163308077">نظام تطبيق الإشارات المرجعية الجديد</translation>
 <translation id="6305012486838822927">لوحة مفاتيح لغة لاو</translation>
-<translation id="6305328361606238230">استقبال رسائل الدفع</translation>
 <translation id="6307722552931206656">‏خوادم أسماء Google‏ - <ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">النظام مشغول</translation>
 <translation id="6308937455967653460">حف&amp;ظ الرابط باسم...</translation>
@@ -4520,7 +4516,6 @@
 <translation id="7339785458027436441">تحقق من التدقيق الإملائي أثناء الكتابة</translation>
 <translation id="7339898014177206373">نافذة جديدة</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> في وضع ملء الشاشة الآن.</translation>
-<translation id="7341982465543599097">قصيرة للغاية</translation>
 <translation id="734303607351427494">إدارة محركات البحث...</translation>
 <translation id="7343116142376328522">عدم السماح لأي موقع ويب باستخدام إنشاء مفتاح في النماذج (موصى به)</translation>
 <translation id="7345706641791090287">تأكيد كلمة المرور</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">تعطيل الترجمات المصاحبة</translation>
 <translation id="7884988936047469945">ميزات إمكانية الوصول التجريبية</translation>
 <translation id="7885253890047913815">أحدث الوجهات</translation>
-<translation id="7885283703487484916">قصير جدًا</translation>
 <translation id="7887192723714330082">‏الرد على "Ok Google" عندما تكون الشاشة مُشغلة وملغاة القفل</translation>
 <translation id="7887334752153342268">تكرار</translation>
 <translation id="7887864092952184874">ماوس بلوتوث مقترن</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index f856bc9..310c2949 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Броячите за обема на данните се показват в диалоговия прозорец „Изчистване на данните за сърфирането“.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Влезте в профила си<ph name="END_SIGN_IN_LINK" />, за да контролирате и преглеждате посещаваните от този човек уебсайтове.</translation>
 <translation id="1097658378307015415">Преди да влезете в профила си, моля, влезте като гост, за да активирате мрежата <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">дълго</translation>
 <translation id="1104652314727136854">Активиране на интегрирането с ОС за асоцииранията на файлове за приложенията в Chrome.</translation>
 <translation id="1105162038795579389">„<ph name="BUNDLE_NAME" />“ добавя следните приложения и разширения за <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Стоп</translation>
@@ -1868,7 +1867,6 @@
 <translation id="3512284449647229026">Страниците, които не се заредят успешно, докато браузърът е офлайн, ще се презареждат автоматично само ако разделите им са видими.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Анулиране на изтеглянето}other{Анулиране на изтеглянията}}</translation>
 <translation id="3512810056947640266">URL адрес (по избор):</translation>
-<translation id="351486934407749662">много дълго</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> иска да сподели съдържанието на екрана ви. Изберете какво да се сподели.</translation>
 <translation id="3518086201899641494">Известия за портали за удостоверяване</translation>
 <translation id="3519867315646775981">Транслитерация (shalom ← שלום)</translation>
@@ -3403,7 +3401,6 @@
 <translation id="569109051430110155">Автоматично откриване</translation>
 <translation id="5691596662111998220">Ами сега! Файлът „<ph name="FILE_NAME" />“ вече не съществува.</translation>
 <translation id="5694501201003948907">$1 елемента се компресират...</translation>
-<translation id="5695323626817702678">кратко</translation>
 <translation id="5697118958262594262">Откриване на важното съдържание, по подразбиране</translation>
 <translation id="5699533844376998780">Разширението „<ph name="EXTENSION_NAME" />“ е добавено.</translation>
 <translation id="5701101281789450335">Настройки за език и въвеждане...</translation>
@@ -3826,7 +3823,6 @@
 <translation id="630065524203833229">Из&amp;ход</translation>
 <translation id="6304217058163308077">Новата система за отметки като приложения</translation>
 <translation id="6305012486838822927">Лаоска клавиатура</translation>
-<translation id="6305328361606238230">Получаване на насочени съобщения</translation>
 <translation id="6307722552931206656">Сървъри на Google за имена – <ph name="BEGIN_LINK" />Научете повече<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Системата е заета</translation>
 <translation id="6308937455967653460">З&amp;апазване на връзката като...</translation>
@@ -4520,7 +4516,6 @@
 <translation id="7339785458027436441">Проверка на правописа при въвеждане</translation>
 <translation id="7339898014177206373">Нов прозорец</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> сега е на цял екран.</translation>
-<translation id="7341982465543599097">изключително кратко</translation>
 <translation id="734303607351427494">Управление на търсещите машини...</translation>
 <translation id="7343116142376328522">Забраняване на сайтовете да използват функцията за генериране на ключове във формуляри (препоръчително)</translation>
 <translation id="7345706641791090287">Потвърждаване на паролата</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">Деактивиране на субтитрите</translation>
 <translation id="7884988936047469945">Експериментални функции за достъпност</translation>
 <translation id="7885253890047913815">Скорошни местоназначения</translation>
-<translation id="7885283703487484916">много кратко</translation>
 <translation id="7887192723714330082">Реакция на „Ok Google“, когато екранът работи и е отключен</translation>
 <translation id="7887334752153342268">Дублиране</translation>
 <translation id="7887864092952184874">Мишката с Bluetooth е сдвоена</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 6d607b3..f35b042d 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">ব্রাউজিং ডেটা সাফ করার ডায়ালগে ডাটা ভলিউম কাউন্টার দেখায়।</translation>
 <translation id="1097507499312291972">এই ব্যক্তির পরিদর্শন করা ওয়েবসাইটগুলি নিয়ন্ত্রণ করতে এবং দেখতে <ph name="BEGIN_SIGN_IN_LINK" />প্রবেশ করুন<ph name="END_SIGN_IN_LINK" /> করুন৷</translation>
 <translation id="1097658378307015415">প্রবেশ করুন করার আগে, <ph name="NETWORK_ID" /> নেটওয়ার্ক সক্রিয় করতে দয়া করে অতিথি রূপে প্রবেশ করুন</translation>
-<translation id="1104054824888299003">দীর্ঘ সময়</translation>
 <translation id="1104652314727136854">Chrome অ্যাপ্লিকেশানগুলির জন্য ফাইল অ্যাসোসিয়েশনের OS একত্রিকরণ সক্ষম করে।</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" <ph name="USER_NAME" /> এর জন্য এই অ্যাপ্লিকেশান এবং এক্সটেনশানগুলি যোগ করে:</translation>
 <translation id="1108600514891325577">&amp;Stop</translation>
@@ -1866,7 +1865,6 @@
 <translation id="3512284449647229026">ব্রাউজার অফলাইন থাকাকালীন লোড হতে ব্যর্থ হওয়া পৃষ্ঠাগুলি শুধুমাত্র তখনই স্বয়ংক্রিয়ভাবে পুনরায় লোড হবে যখন তাদের ট্যাব দৃশ্যমান হবে।</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ডাউনলোড বাতিল করুন}one{ডাউনলোডগুলি বাতিল করুন}other{ডাউনলোডগুলি বাতিল করুন}}</translation>
 <translation id="3512810056947640266">URL (ঐচ্ছিক):</translation>
-<translation id="351486934407749662">খুবই দীর্ঘ সময়</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> আপনার স্ক্রীনের সামগ্রী শেয়ার করতে চায়৷ আপনি কি শেয়ার করতে চান তা বেছে নিন।</translation>
 <translation id="3518086201899641494">ক্যাপটিভ পোর্টালগুলির সম্বন্ধে বিজ্ঞপ্তিগুলি</translation>
 <translation id="3519867315646775981">লিপ্যন্তরকরণ (shalom ← שלום)</translation>
@@ -3396,7 +3394,6 @@
 <translation id="569109051430110155">স্বয়ং সনাক্ত</translation>
 <translation id="5691596662111998220">ওহো, <ph name="FILE_NAME" /> আর বিদ্যমান নেই৷</translation>
 <translation id="5694501201003948907">$1 এর আইটেমগুলি জিপ করা হচ্ছে...</translation>
-<translation id="5695323626817702678">স্বল্প সময়</translation>
 <translation id="5697118958262594262">ডিফল্ট-এর মাধ্যমে গুরুত্বপূর্ণ সামগ্রী সনাক্ত করুন</translation>
 <translation id="5699533844376998780">এক্সটেনশন "<ph name="EXTENSION_NAME" />" জোড়া হয়েছে৷</translation>
 <translation id="5701101281789450335">ভাষা এবং ইনপুট সেটিংস...</translation>
@@ -3820,7 +3817,6 @@
 <translation id="630065524203833229">ব&amp;ন্ধ</translation>
 <translation id="6304217058163308077">নতুন বুকমার্ক অ্যাপ্লিকেশান সিস্টেম</translation>
 <translation id="6305012486838822927">লাও কীবোর্ড</translation>
-<translation id="6305328361606238230">জোর করে পাঠানো বার্তা গ্রহণ করুন</translation>
 <translation id="6307722552931206656">Google নাম সার্ভারগুলি - <ph name="BEGIN_LINK" />আরো জানুন<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">সিস্টেম ব্যস্ত আছে</translation>
 <translation id="6308937455967653460">লি&amp;ঙ্ক এই রূপে সংরক্ষণ করুন...</translation>
@@ -4515,7 +4511,6 @@
 <translation id="7339785458027436441">টাইপ করার সময় বানান পরীক্ষা করুন</translation>
 <translation id="7339898014177206373">নতুন উইন্ডো</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> এখন পূর্ণ পর্দায় রয়েছে৷</translation>
-<translation id="7341982465543599097">খুবই স্বল্প সময়</translation>
 <translation id="734303607351427494">অনুসন্ধান ইঞ্জিনগুলি পরিচালনা করুন...</translation>
 <translation id="7343116142376328522">ফর্মের মধ্যে কী তৈরিকরণ ব্যবহার করতে কোনো সাইটকে অনুমতি দিবেন না (প্রস্তাবিত)</translation>
 <translation id="7345706641791090287">আপনার পাসওয়ার্ড নিশ্চিত করুন</translation>
@@ -4899,7 +4894,6 @@
 <translation id="7881969471599061635">সাবটাইটেল অক্ষম করুন</translation>
 <translation id="7884988936047469945">পরীক্ষামূলক অ্যাক্সেসযোগ্যতার বৈশিষ্ট্যগুলি</translation>
 <translation id="7885253890047913815">সাম্প্রতিক গন্তব্যস্থল</translation>
-<translation id="7885283703487484916">খুবই স্বল্প সময়</translation>
 <translation id="7887192723714330082">স্ক্রিনটি চালু এবং আনলক থাকাকালীন "Ok Google" এ প্রতিক্রিয়া দিন</translation>
 <translation id="7887334752153342268">সদৃশ</translation>
 <translation id="7887864092952184874">ব্লুটুথ মাউস যুক্ত হয়েছে</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index 1178a341..0cbc21e 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Mostra els comptadors del volum de dades al quadre de diàleg Esborra les dades de navegació.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Inicieu la sessió<ph name="END_SIGN_IN_LINK" /> per controlar i consultar els llocs web que aquesta persona visita.</translation>
 <translation id="1097658378307015415">Abans d'iniciar la sessió amb el vostre usuari, entreu com a convidat per activar la xarxa <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">llarg</translation>
 <translation id="1104652314727136854">Activa la integració del sistema operatiu de les associacions de fitxers d'Aplicacions de Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" afegeix aquestes aplicacions i extensions per a <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Atura</translation>
@@ -1435,7 +1434,7 @@
 <translation id="2951247061394563839">Finestra central</translation>
 <translation id="2951721188322348056">Informació del vídeo</translation>
 <translation id="2956763290572484660"><ph name="COOKIES" /> galetes</translation>
-<translation id="295947108480905647">"<ph name="CHROME_EXTENSION_NAME" />" es vol connectar amb:</translation>
+<translation id="295947108480905647"><ph name="CHROME_EXTENSION_NAME" /> es vol connectar amb:</translation>
 <translation id="2959614062380389916">L'administrador ho ha desactivat</translation>
 <translation id="2960393411257968125">Manera en què el gestor de contrasenyes administra l'Emplenament automàtic per a les credencials de sincronització.</translation>
 <translation id="29611076221683977">Els atacants que actualment són a <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> poden provar d'instal·lar programes perillosos al dispositiu Mac amb els quals es pot robar o suprimir la vostra informació (per exemple, les fotos, les contrasenyes, els missatges i les targetes de crèdit).</translation>
@@ -1870,7 +1869,6 @@
 <translation id="3512284449647229026">Les pàgines que no es puguin carregar quan el navegador estigui fora de línia només es tornaran a carregar automàticament si la seva pestanya és visible.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Cancel·la la baixada}other{Cancel·la les baixades}}</translation>
 <translation id="3512810056947640266">URL (opcional):</translation>
-<translation id="351486934407749662">molt llarg</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> vol compartir el contingut de la vostra pantalla. Trieu el que vulgueu compartir.</translation>
 <translation id="3518086201899641494">Notificacions sobre portals captius</translation>
 <translation id="3519867315646775981">Transliteració (shalom ← שלום)</translation>
@@ -3401,7 +3399,6 @@
 <translation id="569109051430110155">Detecció automàtica</translation>
 <translation id="5691596662111998220"><ph name="FILE_NAME" /> ja no existeix.</translation>
 <translation id="5694501201003948907">S'estan comprimint $1 elements...</translation>
-<translation id="5695323626817702678">curt</translation>
 <translation id="5697118958262594262">Detecta el contingut important de manera predeterminada</translation>
 <translation id="5699533844376998780">S'ha afegit l'extensió "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">Configuració d'idioma i d'introducció de text...</translation>
@@ -3825,7 +3822,6 @@
 <translation id="630065524203833229">S&amp;urt</translation>
 <translation id="6304217058163308077">Sistema nou d'aplicacions d'adreces d'interès</translation>
 <translation id="6305012486838822927">Teclat de lao</translation>
-<translation id="6305328361606238230">Rebre missatges de tramesa automàtica</translation>
 <translation id="6307722552931206656">Servidors de noms de Google - <ph name="BEGIN_LINK" />Més informació<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">El sistema està ocupat</translation>
 <translation id="6308937455967653460">Desa l'en&amp;llaç com a...</translation>
@@ -4519,7 +4515,6 @@
 <translation id="7339785458027436441">Comprova l'ortografia mentre escric</translation>
 <translation id="7339898014177206373">Finestra nova</translation>
 <translation id="7340431621085453413">Ara <ph name="FULLSCREEN_ORIGIN" /> a pantalla completa.</translation>
-<translation id="7341982465543599097">molt curt</translation>
 <translation id="734303607351427494">Gestiona els motors de cerca...</translation>
 <translation id="7343116142376328522">No permetis que cap lloc utilitzi la generació de claus en formularis (opció recomanada)</translation>
 <translation id="7345706641791090287">Confirmeu la contrasenya</translation>
@@ -4609,7 +4604,7 @@
 <translation id="7464490149090366184">S'ha produït un error en la compressió; l'element existeix: "$1"</translation>
 <translation id="7465778193084373987">URL de revocació de certificats de Netscape</translation>
 <translation id="7466861475611330213">Estil de puntuació</translation>
-<translation id="7469206789121791392">"<ph name="CHROME_EXTENSION_NAME" />" es vol vincular amb:</translation>
+<translation id="7469206789121791392"><ph name="CHROME_EXTENSION_NAME" /> es vol vincular amb:</translation>
 <translation id="7469894403370665791">Connecta automàticament a aquesta xarxa</translation>
 <translation id="747114903913869239">Error: no s'ha pogut descodificar l'extensió</translation>
 <translation id="7472639616520044048">Tipus MIME:</translation>
@@ -4896,7 +4891,6 @@
 <translation id="7881969471599061635">Desactiva els subtítols</translation>
 <translation id="7884988936047469945">Funcions experimentals d'accessibilitat</translation>
 <translation id="7885253890047913815">Destinacions recents</translation>
-<translation id="7885283703487484916">molt curt</translation>
 <translation id="7887192723714330082">Responeu a "Ok Google" quan la pantalla estigui encesa i desbloquejada</translation>
 <translation id="7887334752153342268">Duplica</translation>
 <translation id="7887864092952184874">Ratolí Bluetooth emparellat</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index e4c308b..70ef1c693 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Zobrazí údaje o objemu dat v dialogovém okně Vymazat údaje o prohlížení.</translation>
 <translation id="1097507499312291972">Chcete-li spravovat a zobrazit weby, které tento uživatel navštěvuje, <ph name="BEGIN_SIGN_IN_LINK" />přihlaste se<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">Chcete-li aktivovat síť <ph name="NETWORK_ID" />, vstupte prosím před přihlášením jako host</translation>
-<translation id="1104054824888299003">dlouhé</translation>
 <translation id="1104652314727136854">Aktivuje integraci přidružení souborů k aplikacím Chrome do operačního systému.</translation>
 <translation id="1105162038795579389">Balíček <ph name="BUNDLE_NAME" /> přidává uživateli <ph name="USER_NAME" /> tyto aplikace a rozšíření:</translation>
 <translation id="1108600514891325577">&amp;Zastavit</translation>
@@ -1870,7 +1869,6 @@
 <translation id="3512284449647229026">Stránky, které se v prohlížeči nepodaří načíst v režimu offline, budou automaticky načteny znovu, bude-li karta viditelná.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Zrušit stahování}few{Zrušit stahování}many{Zrušit stahování}other{Zrušit stahování}}</translation>
 <translation id="3512810056947640266">Adresa URL (nepovinné):</translation>
-<translation id="351486934407749662">velmi dlouhé</translation>
 <translation id="3517839692979918726">Aplikace <ph name="APP_NAME" /> chce sdílet obsah vaší obrazovky. Vyberte, co chcete sdílet.</translation>
 <translation id="3518086201899641494">Oznámení o captive portálech</translation>
 <translation id="3519867315646775981">Přepis (shalom ← שלום)</translation>
@@ -3399,7 +3397,6 @@
 <translation id="569109051430110155">Automatická detekce</translation>
 <translation id="5691596662111998220">Jejda, soubor <ph name="FILE_NAME" /> již neexistuje.</translation>
 <translation id="5694501201003948907">Komprimace $1 položek...</translation>
-<translation id="5695323626817702678">krátké</translation>
 <translation id="5697118958262594262">Ve výchozím nastavení zjišťovat důležitý obsah</translation>
 <translation id="5699533844376998780">Rozšíření <ph name="EXTENSION_NAME" /> bylo přidáno.</translation>
 <translation id="5701101281789450335">Nastavení jazyka a zadávání údajů...</translation>
@@ -3824,7 +3821,6 @@
 <translation id="630065524203833229">Konec</translation>
 <translation id="6304217058163308077">Nový systém záložkových aplikací</translation>
 <translation id="6305012486838822927">Laoská klávesnice</translation>
-<translation id="6305328361606238230">Přijímat nabízené zprávy</translation>
 <translation id="6307722552931206656">Názvové servery Google – <ph name="BEGIN_LINK" />Další informace<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Systém je zaneprázděný</translation>
 <translation id="6308937455967653460">Uložit od&amp;kaz jako...</translation>
@@ -4520,7 +4516,6 @@
 <translation id="7339785458027436441">Kontrolovat během psaní pravopis</translation>
 <translation id="7339898014177206373">Nové okno</translation>
 <translation id="7340431621085453413">Stránka <ph name="FULLSCREEN_ORIGIN" /> se zobrazuje na celou obrazovku.</translation>
-<translation id="7341982465543599097">extrémně krátké</translation>
 <translation id="734303607351427494">Spravovat vyhledávače...</translation>
 <translation id="7343116142376328522">Nepovolit generování klíčů ve formulářích žádnému webu (doporučeno)</translation>
 <translation id="7345706641791090287">Potvrďte heslo</translation>
@@ -4901,7 +4896,6 @@
 <translation id="7881969471599061635">Vypnout titulky</translation>
 <translation id="7884988936047469945">Experimentální funkce přístupnosti</translation>
 <translation id="7885253890047913815">Nedávné cíle</translation>
-<translation id="7885283703487484916">velmi krátké</translation>
 <translation id="7887192723714330082">Reagovat na „Ok Google“, když je zapnuta a odemknuta obrazovka</translation>
 <translation id="7887334752153342268">Duplikovat</translation>
 <translation id="7887864092952184874">Myš Bluetooth byla spárována</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 5ff86073..61602f5 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Viser datavolumentallet i dialogboksen Ryd browserdata.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Log på<ph name="END_SIGN_IN_LINK" /> for at kontrollere og se, hvilke websites denne person besøger.</translation>
 <translation id="1097658378307015415">Før du logger ind, skal du logge ind som gæst for at aktivere netværket <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">lang</translation>
 <translation id="1104652314727136854">Aktivér OS-integration af filtilknytninger for Chrome Apps.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" tilføjer disse apps og udvidelser for <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Stop</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Sider, der ikke kan indlæses, mens browseren er offline, vil kun blive genindlæst automatisk, hvis deres fane er synlig.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Annuller download}one{Annuller downloads}other{Annuller downloads}}</translation>
 <translation id="3512810056947640266">Webadresse (valgfrit):</translation>
-<translation id="351486934407749662">meget lang</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> vil gerne dele indholdet af din skærm. Vælg det, du gerne vil dele.</translation>
 <translation id="3518086201899641494">Underretninger om captive portals</translation>
 <translation id="3519867315646775981">Translitteration (shalom ← שלום)</translation>
@@ -3404,7 +3402,6 @@
 <translation id="569109051430110155">Find automatisk</translation>
 <translation id="5691596662111998220"><ph name="FILE_NAME" /> eksisterer ikke længere.</translation>
 <translation id="5694501201003948907">Komprimerer $1 elementer...</translation>
-<translation id="5695323626817702678">kort</translation>
 <translation id="5697118958262594262">Registrer vigtigt indhold som standard</translation>
 <translation id="5699533844376998780">Udvidelsen "<ph name="EXTENSION_NAME" />" er tilføjet.</translation>
 <translation id="5701101281789450335">Indstillinger for sprog og indtastning...</translation>
@@ -3828,7 +3825,6 @@
 <translation id="630065524203833229">Af&amp;slut</translation>
 <translation id="6304217058163308077">Det nye system for bogmærkeapps</translation>
 <translation id="6305012486838822927">Laotisk tastatur</translation>
-<translation id="6305328361606238230">Modtag push-meddelelser</translation>
 <translation id="6307722552931206656">Googles navneservere – <ph name="BEGIN_LINK" />Få flere oplysninger<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Systemet er optaget</translation>
 <translation id="6308937455967653460">Gem lin&amp;k som...</translation>
@@ -4522,7 +4518,6 @@
 <translation id="7339785458027436441">Kontrollér stavning under indtastning</translation>
 <translation id="7339898014177206373">Nyt vindue</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> er nu i fuld skærm.</translation>
-<translation id="7341982465543599097">ekstremt kort</translation>
 <translation id="734303607351427494">Administrer søgemaskiner...</translation>
 <translation id="7343116142376328522">Giv ikke nogen websites tilladelse til at bruge nøglegenerering i formularer (anbefales)</translation>
 <translation id="7345706641791090287">Bekræft din adgangskode</translation>
@@ -4907,7 +4902,6 @@
 <translation id="7881969471599061635">Deaktiver undertekster</translation>
 <translation id="7884988936047469945">Eksperimentelle hjælpefunktioner</translation>
 <translation id="7885253890047913815">Seneste destinationer</translation>
-<translation id="7885283703487484916">meget kort</translation>
 <translation id="7887192723714330082">Reager på "Ok Google", når skærmen er tændt og låst op</translation>
 <translation id="7887334752153342268">Dupliker</translation>
 <translation id="7887864092952184874">Bluetooth-mus er parret</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index 21435d1..7f69509 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Zeigt Datenvolumenzähler im Dialog "Browserdaten löschen".</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Melden Sie sich an<ph name="END_SIGN_IN_LINK" />, um die von dieser Person besuchten Websites einzusehen.</translation>
 <translation id="1097658378307015415">Melden Sie vor der Anmeldung als Gast an, um das Netzwerk <ph name="NETWORK_ID" /> zu aktivieren.</translation>
-<translation id="1104054824888299003">lang</translation>
 <translation id="1104652314727136854">Betriebssystemintegration von Dateiverknüpfungen für Chrome-Apps aktivieren</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" fügt diese Apps und Erweiterungen für <ph name="USER_NAME" /> hinzu:</translation>
 <translation id="1108600514891325577">&amp;Anhalten</translation>
@@ -1868,7 +1867,6 @@
 <translation id="3512284449647229026">Seiten, die nicht geladen werden können, solange der Browser offline ist, werden nur dann automatisch neu geladen, wenn der Tab sichtbar ist.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Download abbrechen}other{Downloads abbrechen}}</translation>
 <translation id="3512810056947640266">URL (optional):</translation>
-<translation id="351486934407749662">sehr lang</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> möchte den Inhalt Ihres Bildschirms teilen. Wählen Sie aus, was geteilt werden soll.</translation>
 <translation id="3518086201899641494">Benachrichtigungen zu Erfassungsportalen</translation>
 <translation id="3519867315646775981">Transliteration (shalom ← שלום)</translation>
@@ -3398,7 +3396,6 @@
 <translation id="569109051430110155">Automatisch erkennen</translation>
 <translation id="5691596662111998220">Hoppla, <ph name="FILE_NAME" /> existiert nicht mehr.</translation>
 <translation id="5694501201003948907">$1-Elemente werden gezippt...</translation>
-<translation id="5695323626817702678">kurz</translation>
 <translation id="5697118958262594262">Wichtige Inhalte standardmäßig erkennen</translation>
 <translation id="5699533844376998780">Die Erweiterung "<ph name="EXTENSION_NAME" />" wurde hinzugefügt.</translation>
 <translation id="5701101281789450335">Sprach- und Eingabeeinstellungen...</translation>
@@ -3821,7 +3818,6 @@
 <translation id="630065524203833229">&amp;Beenden</translation>
 <translation id="6304217058163308077">Neues System für Lesezeichen-Apps</translation>
 <translation id="6305012486838822927">Lao-Tastatur</translation>
-<translation id="6305328361606238230">Push-Nachrichten erhalten</translation>
 <translation id="6307722552931206656">Google-Nameserver <ph name="BEGIN_LINK" />Weitere Informationen<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">System ausgelastet</translation>
 <translation id="6308937455967653460">&amp;Link speichern unter...</translation>
@@ -4514,7 +4510,6 @@
 <translation id="7339785458027436441">Rechtschreibung während der Eingabe prüfen</translation>
 <translation id="7339898014177206373">Neues Fenster</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> wird jetzt im Vollbildmodus angezeigt.</translation>
-<translation id="7341982465543599097">äußerst kurz</translation>
 <translation id="734303607351427494">Suchmaschinen verwalten...</translation>
 <translation id="7343116142376328522">Schlüsselgenerierung in Formularen auf keiner Website zulassen (empfohlen)</translation>
 <translation id="7345706641791090287">Passwort bestätigen</translation>
@@ -4902,7 +4897,6 @@
 <translation id="7881969471599061635">Untertitel deaktivieren</translation>
 <translation id="7884988936047469945">Experimentelle Bedienungshilfen</translation>
 <translation id="7885253890047913815">Letzte Ziele</translation>
-<translation id="7885283703487484916">sehr kurz</translation>
 <translation id="7887192723714330082">Auf "Ok Google" reagieren, wenn das Display eingeschaltet und entsperrt ist</translation>
 <translation id="7887334752153342268">Duplizieren</translation>
 <translation id="7887864092952184874">Pairing mit Bluetooth-Maus durchgeführt</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index 4439d5a3..5cf34c18 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Εμφανίζει μετρητές όγκου δεδομένων στο παράθυρο διαλόγου "Διαγραφή δεδομένων περιήγησης".</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Συνδεθείτε<ph name="END_SIGN_IN_LINK" /> για να ελέγξετε και να δείτε τους ιστότοπους που επισκέπτεται αυτό το άτομο.</translation>
 <translation id="1097658378307015415">Προτού συνδεθείτε, πραγματοποιήστε είσοδο ως επισκέπτης για να ενεργοποιηθεί το δίκτυο <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">μεγάλη</translation>
 <translation id="1104652314727136854">Να επιτρέπεται η ενσωμάτωση συσχετισμών αρχείων στο λειτουργικό σύστημα για το Chrome Apps.</translation>
 <translation id="1105162038795579389">Η δέσμη εφαρμογών "<ph name="BUNDLE_NAME" />" προσθέτει αυτές τις εφαρμογές και τις επεκτάσεις για τον/την χρήστη <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Διακοπή</translation>
@@ -1880,7 +1879,6 @@
 <translation id="3512284449647229026">Οι σελίδες που δεν φορτώνονται με επιτυχία όταν το πρόγραμμα περιήγησης βρίσκεται εκτός σύνδεσης θα φορτώνονται αυτόματα μόνο εάν η καρτέλα τους είναι ορατή.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Ακύρωση λήψης}other{Ακύρωση λήψεων}}</translation>
 <translation id="3512810056947640266">URL (προαιρετικά):</translation>
-<translation id="351486934407749662">πολύ μεγάλη</translation>
 <translation id="3517839692979918726">Η εφαρμογή <ph name="APP_NAME" /> θα ήθελε να μοιραστεί το περιεχόμενο της οθόνες σας με τον ιστότοπο. Επιλέξτε το περιεχόμενο που θα θέλατε να τεθεί σε κοινή χρήση.</translation>
 <translation id="3518086201899641494">Ειδοποιήσεις σχετικά με πύλες υποδοχής</translation>
 <translation id="3519867315646775981">Μεταγραφή (shalom ← שלום)</translation>
@@ -3423,7 +3421,6 @@
 <translation id="569109051430110155">Αυτόματος εντοπισμός</translation>
 <translation id="5691596662111998220">Ωχ! Το αρχείο <ph name="FILE_NAME" /> δεν υπάρχει πια.</translation>
 <translation id="5694501201003948907">Συμπίεση $1 στοιχείων…</translation>
-<translation id="5695323626817702678">σύντομη</translation>
 <translation id="5697118958262594262">Εντοπισμός σημαντικού περιεχομένου από προεπιλογή</translation>
 <translation id="5699533844376998780">Έχει γίνει προσθήκη της επέκτασης "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">Ρυθμίσεις γλώσσας και στοιχείων εισόδου…</translation>
@@ -3846,7 +3843,6 @@
 <translation id="630065524203833229">Έ&amp;ξοδος</translation>
 <translation id="6304217058163308077">Το νέο σύστημα εφαρμογής σελιδοδείκτη</translation>
 <translation id="6305012486838822927">Πληκτρολόγιο Λάο</translation>
-<translation id="6305328361606238230">Λήψη μηνυμάτων push</translation>
 <translation id="6307722552931206656">Διακομιστές ονομάτων της Google - <ph name="BEGIN_LINK" />Μάθετε περισσότερα<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Το σύστημα είναι απασχολημένο</translation>
 <translation id="6308937455967653460">Αποθήκευση συν&amp;δέσμου ως...</translation>
@@ -4544,7 +4540,6 @@
 <translation id="7339785458027436441">Ορθογραφικός Έλεγχος Κατά την Πληκτρολόγηση</translation>
 <translation id="7339898014177206373">Νέο παράθυρο</translation>
 <translation id="7340431621085453413">Το <ph name="FULLSCREEN_ORIGIN" /> εμφανίζεται σε πλήρη οθόνη.</translation>
-<translation id="7341982465543599097">εξαιρετικά σύντομη</translation>
 <translation id="734303607351427494">Διαχείριση μηχανών αναζήτησης...</translation>
 <translation id="7343116142376328522">Να μην επιτρέπεται σε κανέναν ιστότοπο να χρησιμοποιεί τη δημιουργία κλειδιού σε φόρμες (συνιστάται)</translation>
 <translation id="7345706641791090287">Επιβεβαιώστε τον κωδικό πρόσβασής σας</translation>
@@ -4932,7 +4927,6 @@
 <translation id="7881969471599061635">Απενεργοποίηση υπότιτλων</translation>
 <translation id="7884988936047469945">Πειραματικές λειτουργίες προσβασιμότητας</translation>
 <translation id="7885253890047913815">Πρόσφατοι προορισμοί</translation>
-<translation id="7885283703487484916">πολύ σύντομη</translation>
 <translation id="7887192723714330082">Απάντηση στο "Ok Google" όταν η οθόνη είναι αναμμένη και ξεκλειδωμένη</translation>
 <translation id="7887334752153342268">Αντιγραφή</translation>
 <translation id="7887864092952184874">Έγινε σύζευξη του ποντικιού Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index af79357..c415579 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Shows data volume counters in the Clear browsing data dialogue.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Sign in<ph name="END_SIGN_IN_LINK" /> to control and view the websites that this person visits.</translation>
 <translation id="1097658378307015415">Before signing in, please enter as Guest to activate the network <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">long</translation>
 <translation id="1104652314727136854">Enable OS integration of file associations for Chrome Apps.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" adds these apps and extensions for <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Stop</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Pages that fail to load while the browser is offline will only be auto-reloaded if their tab is visible.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Cancel Download}other{Cancel Downloads}}</translation>
 <translation id="3512810056947640266">URL (optional):</translation>
-<translation id="351486934407749662">very long</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> would like to share the contents of your screen. Choose what you'd like to share.</translation>
 <translation id="3518086201899641494">Notifications about captive portals</translation>
 <translation id="3519867315646775981">Transliteration (shalom ← שלום)</translation>
@@ -3408,7 +3406,6 @@
 <translation id="569109051430110155">Auto detect</translation>
 <translation id="5691596662111998220">Whoops, <ph name="FILE_NAME" /> no longer exists.</translation>
 <translation id="5694501201003948907">Zipping $1 items...</translation>
-<translation id="5695323626817702678">short</translation>
 <translation id="5697118958262594262">Detect important content by default</translation>
 <translation id="5699533844376998780">The extension "<ph name="EXTENSION_NAME" />" has been installed.</translation>
 <translation id="5701101281789450335">Language and input settings...</translation>
@@ -3833,7 +3830,6 @@
 <translation id="630065524203833229">E&amp;xit</translation>
 <translation id="6304217058163308077">The new bookmark app system</translation>
 <translation id="6305012486838822927">Lao keyboard</translation>
-<translation id="6305328361606238230">Receive push messages</translation>
 <translation id="6307722552931206656">Google name servers - <ph name="BEGIN_LINK" />Learn more<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">System busy</translation>
 <translation id="6308937455967653460">Save lin&amp;k as...</translation>
@@ -4530,7 +4526,6 @@
 <translation id="7339785458027436441">Check Spelling While Typing</translation>
 <translation id="7339898014177206373">New window</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> is now full screen.</translation>
-<translation id="7341982465543599097">extremely short</translation>
 <translation id="734303607351427494">Manage search engines...</translation>
 <translation id="7343116142376328522">Do not allow any site to use key generation in forms (recommended)</translation>
 <translation id="7345706641791090287">Confirm your password</translation>
@@ -4915,7 +4910,6 @@
 <translation id="7881969471599061635">Disable subtitles</translation>
 <translation id="7884988936047469945">Experimental acecssibility features</translation>
 <translation id="7885253890047913815">Recent destinations</translation>
-<translation id="7885283703487484916">very short</translation>
 <translation id="7887192723714330082">Respond to "OK Google" when the screen is on and unlocked</translation>
 <translation id="7887334752153342268">Duplicate</translation>
 <translation id="7887864092952184874">Bluetooth mouse paired</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index c50c674..1336e4e 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Permite mostrar los contadores de volumen de datos en el cuadro de diálogo Borrar datos de navegación.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Accede<ph name="END_SIGN_IN_LINK" /> para controlar y ver los sitios web que visita esta persona.</translation>
 <translation id="1097658378307015415">Antes de acceder, ingresa como Invitado para activar la red <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">larga</translation>
 <translation id="1104652314727136854">Permite habilitar la integración del sistema operativo de asociaciones de archivos para aplicaciones de Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" agrega estas aplicaciones y extensiones para <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Interrumpir</translation>
@@ -1869,7 +1868,6 @@
 <translation id="3512284449647229026">Las páginas que no se cargan cuando el navegador está sin conexión se volverán cargarán automáticamente solo si la pestaña está visible.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Cancelar descarga}other{Cancelar descargas}}</translation>
 <translation id="3512810056947640266">URL (opcional):</translation>
-<translation id="351486934407749662">muy larga</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> desea compartir el contenido de tu pantalla. Elige lo que quieras compartir.</translation>
 <translation id="3518086201899641494">Notificaciones sobre portales cautivos</translation>
 <translation id="3519867315646775981">Transliteración (shalom ← שלום)</translation>
@@ -3117,7 +3115,7 @@
 <translation id="5302048478445481009">Idioma</translation>
 <translation id="5304039790201806037">Eventos de puntero</translation>
 <translation id="5305688511332277257">No hay certificados instalados</translation>
-<translation id="5306802244647481941">Vista rápida de la app Archivos</translation>
+<translation id="5306802244647481941">Vista rápida de la app de Archivos</translation>
 <translation id="5308380583665731573">Conectar</translation>
 <translation id="5311260548612583999">Archivo de clave privada (opcional):</translation>
 <translation id="5316588172263354223">Búsqueda por voz en cualquier momento</translation>
@@ -3403,7 +3401,6 @@
 <translation id="569109051430110155">Detección automática</translation>
 <translation id="5691596662111998220">El archivo <ph name="FILE_NAME" /> ya no existe.</translation>
 <translation id="5694501201003948907">Comprimiendo $1 elementos…</translation>
-<translation id="5695323626817702678">breve</translation>
 <translation id="5697118958262594262">Detectar contenido importante de manera predeterminada</translation>
 <translation id="5699533844376998780">Se agregó la extensión "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">Configuración de idioma y de entrada de texto...</translation>
@@ -3826,7 +3823,6 @@
 <translation id="630065524203833229">&amp;Salir</translation>
 <translation id="6304217058163308077">El nuevo sistema de apps de marcadores</translation>
 <translation id="6305012486838822927">Teclado lao</translation>
-<translation id="6305328361606238230">Recibir mensajes de inserción</translation>
 <translation id="6307722552931206656">Servidores de nombres de Google: <ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistema ocupado</translation>
 <translation id="6308937455967653460">Guardar &amp;enlace como...</translation>
@@ -4520,7 +4516,6 @@
 <translation id="7339785458027436441">Controlar ortografía al escribir</translation>
 <translation id="7339898014177206373">Nueva ventana</translation>
 <translation id="7340431621085453413">Visualización de <ph name="FULLSCREEN_ORIGIN" /> en pantalla completa.</translation>
-<translation id="7341982465543599097">demasiado breve</translation>
 <translation id="734303607351427494">Administrar motores de búsqueda...</translation>
 <translation id="7343116142376328522">No permitir que ningún sitio utilice la generación de claves en formularios (recomendado)</translation>
 <translation id="7345706641791090287">Confirma tu contraseña</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">Inhabilitar subtítulos</translation>
 <translation id="7884988936047469945">Funciones de accesibilidad experimentales</translation>
 <translation id="7885253890047913815">Destinos recientes</translation>
-<translation id="7885283703487484916">muy breve</translation>
 <translation id="7887192723714330082">Responder a "OK Google" cuando la pantalla se encuentre encendida y desbloqueada</translation>
 <translation id="7887334752153342268">Duplicar</translation>
 <translation id="7887864092952184874">Mouse Bluetooth sincronizado</translation>
@@ -5857,7 +5851,7 @@
 <translation id="9207194316435230304">ATOK</translation>
 <translation id="9208886416788010685">Adobe Reader está desactualizado.</translation>
 <translation id="9210991923655648139">Accesible para secuencia de comandos:</translation>
-<translation id="9211453256673911535">Opciones para la vista rápida de la app Archivos, que muestra una vista previa rápida de un archivo.</translation>
+<translation id="9211453256673911535">Opciones para la vista rápida de la app de Archivos, que muestra una vista previa rápida de un archivo.</translation>
 <translation id="9214520840402538427">¡Vaya! Se ha agotado el tiempo de la inicialización de los atributos de tiempo de instalación. Comunícate con el representante de asistencia.</translation>
 <translation id="9214695392875603905">Cupcake</translation>
 <translation id="9215293857209265904">"<ph name="EXTENSION_NAME" />" agregada</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index 16b8998..79e4e6bc 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Muestra medidores del volumen de datos en el cuadro de diálogo Borrar datos de navegación.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Inicia sesión<ph name="END_SIGN_IN_LINK" /> para ver y controlar los sitios web que visite esta persona.</translation>
 <translation id="1097658378307015415">Antes de iniciar sesión, entra como invitado para activar la red <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">largo</translation>
 <translation id="1104652314727136854">Habilita la integración del sistema operativo de asociaciones de archivos para aplicaciones de Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" añade estas aplicaciones y extensiones para <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Detener</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Las páginas que no se carguen cuando el navegador no esté conectado a Internet solo se volverán a cargar automáticamente si su pestaña está visible.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Cancelar descarga}other{Cancelar descargas}}</translation>
 <translation id="3512810056947640266">URL (opcional):</translation>
-<translation id="351486934407749662">muy largo</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> quiere compartir el contenido de tu pantalla. Selecciona el contenido que quieres compartir.</translation>
 <translation id="3518086201899641494">Notificaciones sobre portales cautivos</translation>
 <translation id="3519867315646775981">Transliteración (shalom ← שלום)</translation>
@@ -3402,7 +3400,6 @@
 <translation id="569109051430110155">Detección automática</translation>
 <translation id="5691596662111998220">¡Vaya! <ph name="FILE_NAME" /> ya no existe.</translation>
 <translation id="5694501201003948907">Comprimiendo $1 elementos...</translation>
-<translation id="5695323626817702678">breve</translation>
 <translation id="5697118958262594262">Detectar contenido importante de forma predeterminada</translation>
 <translation id="5699533844376998780">Se ha añadido la extensión "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">Configuración de idioma y de introducción de texto...</translation>
@@ -3827,7 +3824,6 @@
 <translation id="630065524203833229">&amp;Salir</translation>
 <translation id="6304217058163308077">El nuevo sistema de aplicaciones de marcadores</translation>
 <translation id="6305012486838822927">Teclado lao</translation>
-<translation id="6305328361606238230">Recibir mensajes push</translation>
 <translation id="6307722552931206656">Servidores de nombres de Google - <ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistema ocupado</translation>
 <translation id="6308937455967653460">Guardar &amp;enlace como...</translation>
@@ -4521,7 +4517,6 @@
 <translation id="7339785458027436441">Comprobar ortografía al escribir</translation>
 <translation id="7339898014177206373">Nueva ventana</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> se muestra ahora en pantalla completa.</translation>
-<translation id="7341982465543599097">extremadamente breve</translation>
 <translation id="734303607351427494">Administrar motores de búsqueda...</translation>
 <translation id="7343116142376328522">No permitir que los sitios web utilicen la generación de claves en formularios (opción recomendada)</translation>
 <translation id="7345706641791090287">Confirma tu contraseña</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">Inhabilitar subtítulos</translation>
 <translation id="7884988936047469945">Funciones de accesibilidad experimentales</translation>
 <translation id="7885253890047913815">Destinos recientes</translation>
-<translation id="7885283703487484916">muy breve</translation>
 <translation id="7887192723714330082">Responder a "Ok Google" cuando la pantalla esté encendida y desbloqueada</translation>
 <translation id="7887334752153342268">Duplicar</translation>
 <translation id="7887864092952184874">Ratón Bluetooth vinculado</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index b4fcd3e..87c66689 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Dialoogis Sirvimisandmete kustutamine kuvatakse andmemahu loendurid.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Logige sisse<ph name="END_SIGN_IN_LINK" />, et hallata ja vaadata veebisaite, mida see isik külastab.</translation>
 <translation id="1097658378307015415">Enne sisselogimist sisenege võrgu <ph name="NETWORK_ID" /> aktiveerimiseks külastajana</translation>
-<translation id="1104054824888299003">pikk</translation>
 <translation id="1104652314727136854">Luba Chrome'i rakenduse failiseoste OS-i integratsioon.</translation>
 <translation id="1105162038795579389">Kogumiga „<ph name="BUNDLE_NAME" />” lisatakse kasutaja <ph name="USER_NAME" /> jaoks need rakendused ja laiendused:</translation>
 <translation id="1108600514891325577">&amp;Peata</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Lehed, mida ei õnnestu laadida siis, kui brauseril puudub võrguühendus, laaditakse automaatselt uuesti ainult siis, kui vaheleht on nähtav.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Tühista allalaadimine}other{Tühista allalaadimised}}</translation>
 <translation id="3512810056947640266">URL (valikuline):</translation>
-<translation id="351486934407749662">väga pikk</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> soovib jagada teie ekraani sisu. Valige, mida soovite jagada.</translation>
 <translation id="3518086201899641494">Märguanded kontrollportaali kohta</translation>
 <translation id="3519867315646775981">Transliteratsioon (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Automaatne tuvastamine</translation>
 <translation id="5691596662111998220">Faili <ph name="FILE_NAME" /> ei ole enam olemas.</translation>
 <translation id="5694501201003948907">$1 üksuse pakkimine ...</translation>
-<translation id="5695323626817702678">lühike</translation>
 <translation id="5697118958262594262">Olulise sisu tuvastamine vaikimisi</translation>
 <translation id="5699533844376998780">Lisati laiendus „<ph name="EXTENSION_NAME" />”.</translation>
 <translation id="5701101281789450335">Keele- ja sisendiseaded ...</translation>
@@ -3832,7 +3829,6 @@
 <translation id="630065524203833229">V&amp;älju</translation>
 <translation id="6304217058163308077">Uus järjehoidjate rakenduse süsteem</translation>
 <translation id="6305012486838822927">Lao klaviatuur</translation>
-<translation id="6305328361606238230">Tõukesõnumite vastuvõtmine</translation>
 <translation id="6307722552931206656">Google'i nimeserverid – <ph name="BEGIN_LINK" />lisateave<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Süsteem on hõivatud</translation>
 <translation id="6308937455967653460">Salvesta lin&amp;k nimega...</translation>
@@ -4528,7 +4524,6 @@
 <translation id="7339785458027436441">Kontrolli õigekirja tippimise ajal</translation>
 <translation id="7339898014177206373">Uus aken</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> kuvati nüüd täisekraanil.</translation>
-<translation id="7341982465543599097">väga lühike</translation>
 <translation id="734303607351427494">Halda otsingumootoreid ...</translation>
 <translation id="7343116142376328522">Ära luba ühelgi saidil vormidel võtme loomist kasutada (soovitatav)</translation>
 <translation id="7345706641791090287">Kinnitage oma parool</translation>
@@ -4913,7 +4908,6 @@
 <translation id="7881969471599061635">Keela subtiitrid</translation>
 <translation id="7884988936047469945">Katselised juurdepääsetavuse funktsioonid</translation>
 <translation id="7885253890047913815">Hiljutised sihtkohad</translation>
-<translation id="7885283703487484916">väga lühike</translation>
 <translation id="7887192723714330082">Reageerimine otsetee sõnale „Ok Google”, kui ekraan on sisse lülitatud ja avatud</translation>
 <translation id="7887334752153342268">Tee koopia</translation>
 <translation id="7887864092952184874">Bluetoothi hiir on seotud</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index 881be0e3..9f44eaa 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">شمارنده‌های حجم داده را در کادر گفتگوی «پاک کردن داده‌های محصول مرور»، نشان می‌دهد.</translation>
 <translation id="1097507499312291972">برای کنترل و مشاهده وب‌سایت‌هایی که این شخص بازدید می‌کند، <ph name="BEGIN_SIGN_IN_LINK" />وارد سیستم شوید<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">قبل از ورود به سیستم، لطفاً جهت فعال کردن شبکه <ph name="NETWORK_ID" />، به‌عنوان مهمان وارد شوید</translation>
-<translation id="1104054824888299003">طولانی</translation>
 <translation id="1104652314727136854">‏یکپارچگی مرتبط‌سازی‌های فایل OS را برای برنامه‌های Chrome فعال کنید.</translation>
 <translation id="1105162038795579389">«<ph name="BUNDLE_NAME" />» این برنامه‌ها و افزونه‌ها را برای <ph name="USER_NAME" /> اضافه می‌کند.</translation>
 <translation id="1108600514891325577">&amp;توقف</translation>
@@ -1868,7 +1867,6 @@
 <translation id="3512284449647229026">صفحاتی که وقتی مرورگر آفلاین است، بارگیری نمی‌شوند، فقط زمانی به صورت خودکار بارگیری مجدد می‌شوند که برگه آنها قابل مشاهده باشد.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{لغو دانلود}one{لغو دانلود}other{لغو دانلود}}</translation>
 <translation id="3512810056947640266">نشانی وب (اختیاری):</translation>
-<translation id="351486934407749662">بسیار طولانی</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> می‌خواهد محتوای صفحه شما را اشتراک‌گذاری کند. آنچه را که می‌خواهید به اشتراک بگذارید، انتخاب کنید.</translation>
 <translation id="3518086201899641494">اعلان‌های مربوط به پورتال‌های محدود</translation>
 <translation id="3519867315646775981">‏نویسه‌گردانی (shalom ← ‏שלום)</translation>
@@ -3402,7 +3400,6 @@
 <translation id="569109051430110155">شناسایی خودکار</translation>
 <translation id="5691596662111998220">اوه، <ph name="FILE_NAME" /> دیگر وجود ندارد.</translation>
 <translation id="5694501201003948907">در حال فشرده‌سازی $1 مورد...</translation>
-<translation id="5695323626817702678">کوتاه</translation>
 <translation id="5697118958262594262">شناسایی محتوای مهم به صورت پیش‌فرض</translation>
 <translation id="5699533844376998780">برنامهٔ افزودنی "<ph name="EXTENSION_NAME" />" اضافه شده است.</translation>
 <translation id="5701101281789450335">تنظیمات ورودی و زبان...</translation>
@@ -3825,7 +3822,6 @@
 <translation id="630065524203833229">&amp;خروج</translation>
 <translation id="6304217058163308077">سیستم برنامه نشانک جدید</translation>
 <translation id="6305012486838822927">صفحه‌کلید لائوسی</translation>
-<translation id="6305328361606238230">دریافت پیام‌های فشاری</translation>
 <translation id="6307722552931206656">‏‫سرورهای نام Google‏ - <ph name="BEGIN_LINK" />کسب اطلاعات بیشتر<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">سیستم مشغول است</translation>
 <translation id="6308937455967653460">ذخیره پی&amp;وند به‌عنوان...</translation>
@@ -4519,7 +4515,6 @@
 <translation id="7339785458027436441">بررسی املا هنگام تایپ</translation>
 <translation id="7339898014177206373">پنجرهٔ جدید</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> اکنون در حالت تمام صفحه است.</translation>
-<translation id="7341982465543599097">بسیار کوتاه</translation>
 <translation id="734303607351427494">مدیریت موتورهای جستجو...</translation>
 <translation id="7343116142376328522">به هیچ سایتی اجازه داده نشود از تولید کلید در فرم‌ها استفاده کند (توصیه می‌شود)</translation>
 <translation id="7345706641791090287">گذرواژه‌تان را تأیید کنید</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">غیرفعال کردن زیرنویس</translation>
 <translation id="7884988936047469945">قابلیت‌های دسترس‌پذیری آزمایشی</translation>
 <translation id="7885253890047913815">مقصدهای اخیر</translation>
-<translation id="7885283703487484916">بسیار کوتاه</translation>
 <translation id="7887192723714330082">‏پاسخ دادن به «Ok Google» وقتی صفحه روشن است و قفل نیست</translation>
 <translation id="7887334752153342268">کپی‌برداری</translation>
 <translation id="7887864092952184874">موشواره بلوتوث مرتبط شد</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index 771026a..6659842 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Näyttää tietomäärälaskurit Poista selailutiedot -valintaikkunassa.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Kirjaudu sisään<ph name="END_SIGN_IN_LINK" />, jos haluat hallinnoida ja tarkastella tämän henkilön käyttämiä verkkosivustoja.</translation>
 <translation id="1097658378307015415">Aloita vierailijakäyttö ennen sisäänkirjautumista aktivoidaksesi verkon <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">pitkä</translation>
 <translation id="1104652314727136854">Määritä Chrome-sovellukset tiedostojen oletusohjelmiksi käyttöjärjestelmässä.</translation>
 <translation id="1105162038795579389"><ph name="BUNDLE_NAME" /> lisää seuraavat sovellukset ja laajennukset henkilölle <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">Py&amp;säytä</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Sivut, joiden lataus epäonnistui selaimen ollessa offline-tilassa, ladataan automaattisesti uudelleen vain, jos niiden välilehdet ovat näkyvissä.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Peruuta lataus}other{Peruuta lataukset}}</translation>
 <translation id="3512810056947640266">URL-osoite (valinnainen):</translation>
-<translation id="351486934407749662">erittäin pitkä</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> haluaa jakaa ruutusi sisällön. Valitse, mitä haluat jakaa.</translation>
 <translation id="3518086201899641494">Captive portalien ilmoitukset</translation>
 <translation id="3519867315646775981">Translitterointi (shalom ← שלום)</translation>
@@ -3396,7 +3394,6 @@
 <translation id="569109051430110155">Automaattinen</translation>
 <translation id="5691596662111998220">Hups, kohdetta <ph name="FILE_NAME" /> ei ole enää olemassa.</translation>
 <translation id="5694501201003948907">Pakataan $1 kohdetta…</translation>
-<translation id="5695323626817702678">lyhyt</translation>
 <translation id="5697118958262594262">Tunnista tärkeä sisältö oletuksena</translation>
 <translation id="5699533844376998780">Laajennus <ph name="EXTENSION_NAME" /> on lisätty.</translation>
 <translation id="5701101281789450335">Kieli- ja syöttöasetukset...</translation>
@@ -3821,7 +3818,6 @@
 <translation id="630065524203833229">Poist&amp;u</translation>
 <translation id="6304217058163308077">Uusi kirjanmerkkisovellusjärjestelmä</translation>
 <translation id="6305012486838822927">Laonkielinen näppäimistö</translation>
-<translation id="6305328361606238230">Haluatko vastaanottaa push-viestejä?</translation>
 <translation id="6307722552931206656">Googlen nimipalvelimet – <ph name="BEGIN_LINK" />lisätietoja<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Järjestelmä on varattu</translation>
 <translation id="6308937455967653460">Tallenna lin&amp;kki nimellä...</translation>
@@ -4514,7 +4510,6 @@
 <translation id="7339785458027436441">Tarkista oikeinkirjoitus kirjoittaessa</translation>
 <translation id="7339898014177206373">Uusi ikkuna</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> on nyt koko näytöllä.</translation>
-<translation id="7341982465543599097">erittäin lyhyt</translation>
 <translation id="734303607351427494">Hallinnoi hakukoneita...</translation>
 <translation id="7343116142376328522">Älä salli sivustojen käyttää avainten luontitoimintoa lomakkeissa (suositus)</translation>
 <translation id="7345706641791090287">Vahvista salasanasi</translation>
@@ -4898,7 +4893,6 @@
 <translation id="7881969471599061635">Poista tekstitykset käytöstä</translation>
 <translation id="7884988936047469945">Kokeelliset esteettömyysominaisuudet</translation>
 <translation id="7885253890047913815">Uusimmat kohteet</translation>
-<translation id="7885283703487484916">hyvin lyhyt</translation>
 <translation id="7887192723714330082">Vastaa Ok Googleen, kun näyttö on päällä ja lukitsematta.</translation>
 <translation id="7887334752153342268">Monista</translation>
 <translation id="7887864092952184874">Laitepari muodostettu Bluetooth-hiiren kanssa</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index b0680f9..269ad8f9 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Ipinapakita ang mga counter ng dami ng data sa dialog na I-clear ang data mula sa pagba-browse.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Mag-sign in<ph name="END_SIGN_IN_LINK" /> upang makontrol at matingnan ang mga website na binibisita ng taong ito.</translation>
 <translation id="1097658378307015415">Bago mag-sign in, mangyaring pumasok bilang Bisita upang i-activate ang network <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">matagal</translation>
 <translation id="1104652314727136854">I-enable ang pagsama sa OS ng mga kaugnayan ng file para sa Chrome Apps.</translation>
 <translation id="1105162038795579389">Idinaragdag ng "<ph name="BUNDLE_NAME" />" ang mga app at extension na ito para kay <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Huminto</translation>
@@ -1875,7 +1874,6 @@
 <translation id="3512284449647229026">Ang mga page na hindi maglo-load habang offline ang browser ay awtomatiko lang na ire-reload kung nakikita ang tab ng mga ito.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Kanselahin ang Pag-download}one{Kanselahin ang Mga Pag-download}other{Kanselahin ang Mga Pag-download}}</translation>
 <translation id="3512810056947640266">URL (opsyonal):</translation>
-<translation id="351486934407749662">napakatagal</translation>
 <translation id="3517839692979918726">Gustong ibahagi ng <ph name="APP_NAME" /> ang mga content ng iyong screen. Piliin ang gusto mong ibahagi.</translation>
 <translation id="3518086201899641494">Mga notification tungkol sa mga captive portal</translation>
 <translation id="3519867315646775981">Transliteration (shalom ← שלום)</translation>
@@ -3411,7 +3409,6 @@
 <translation id="569109051430110155">Awtomatikong nakita</translation>
 <translation id="5691596662111998220">Whoops, hindi na umiiral ang <ph name="FILE_NAME" />.</translation>
 <translation id="5694501201003948907">Nagsi-zip ng $1 (na) item...</translation>
-<translation id="5695323626817702678">maikli</translation>
 <translation id="5697118958262594262">Tukuyin ang mahalagang content bilang default</translation>
 <translation id="5699533844376998780">Naidagdag na ang extension na "<ph name="EXTENSION_NAME" />."</translation>
 <translation id="5701101281789450335">Mga setting ng wika at input...</translation>
@@ -3836,7 +3833,6 @@
 <translation id="630065524203833229">L&amp;umabas</translation>
 <translation id="6304217058163308077">Ang bagong system ng bookmark app</translation>
 <translation id="6305012486838822927">Lao keyboard</translation>
-<translation id="6305328361606238230">Tumanggap ng mga push message</translation>
 <translation id="6307722552931206656">Mga server ng pangalan ng Google - <ph name="BEGIN_LINK" />Matuto nang higit pa<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Abala ang system</translation>
 <translation id="6308937455967653460">I-save ang lin&amp;k bilang...</translation>
@@ -4534,7 +4530,6 @@
 <translation id="7339785458027436441">Check Spelling While Typing</translation>
 <translation id="7339898014177206373">Bagong window</translation>
 <translation id="7340431621085453413">Full screen na ngayon ang <ph name="FULLSCREEN_ORIGIN" />.</translation>
-<translation id="7341982465543599097">sobrang maikli</translation>
 <translation id="734303607351427494">Pamahalaan ang mga search engine...</translation>
 <translation id="7343116142376328522">Huwag payagan ang anumang site na gumamit ng pagbuo ng key sa mga form (inirerekomenda)</translation>
 <translation id="7345706641791090287">Kumpirmahin ang iyong password</translation>
@@ -4919,7 +4914,6 @@
 <translation id="7881969471599061635">I-disable ang mga subtitle</translation>
 <translation id="7884988936047469945">Mga pang-eksperimentong feature ng accessibility</translation>
 <translation id="7885253890047913815">Mga Kamakailang Patutunguhan</translation>
-<translation id="7885283703487484916">napaka-ikli</translation>
 <translation id="7887192723714330082">Tumugon sa "Ok Google" kapag naka-on at naka-unlock ang screen</translation>
 <translation id="7887334752153342268">Doblehin</translation>
 <translation id="7887864092952184874">Naipares ang bluetooth mouse</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index a2fe9a232..870ef295 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Affiche les compteurs de volume de données dans la boîte de dialogue "Effacer les données de navigation".</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Se connecter<ph name="END_SIGN_IN_LINK" /> pour contrôler et afficher les sites Web consultés par cette personne</translation>
 <translation id="1097658378307015415">Avant de vous connecter, veuillez vous connecter en tant qu'invité afin d'activer le réseau <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">long</translation>
 <translation id="1104652314727136854">Activer l'intégration OS des associations de fichiers pour les applications Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" permet d'ajouter les applications et les extensions suivantes pour <ph name="USER_NAME" /> :</translation>
 <translation id="1108600514891325577">&amp;Arrêter</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Les pages dont le chargement a échoué pendant que le navigateur était en mode hors connexion ne seront automatiquement rechargées que si l'onglet correspondant est visible.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Annuler le téléchargement}one{Annuler le téléchargement}other{Annuler les téléchargements}}</translation>
 <translation id="3512810056947640266">URL (facultatif) :</translation>
-<translation id="351486934407749662">très long</translation>
 <translation id="3517839692979918726">Une demande de partage du contenu de votre écran a été envoyée depuis <ph name="APP_NAME" />. Veuillez sélectionner ce que vous acceptez de partager.</translation>
 <translation id="3518086201899641494">Notifications au sujet des portails captifs</translation>
 <translation id="3519867315646775981">Translittération (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Détection automatique</translation>
 <translation id="5691596662111998220">Désolé, le fichier <ph name="FILE_NAME" /> n'existe plus.</translation>
 <translation id="5694501201003948907">Compression de $1 éléments en cours…</translation>
-<translation id="5695323626817702678">court</translation>
 <translation id="5697118958262594262">Détecter le contenu important par défaut</translation>
 <translation id="5699533844376998780">L'extension "<ph name="EXTENSION_NAME" />" a été ajoutée.</translation>
 <translation id="5701101281789450335">Paramètres de langue et de saisie</translation>
@@ -3832,7 +3829,6 @@
 <translation id="630065524203833229">&amp;Quitter</translation>
 <translation id="6304217058163308077">Nouveau système de création de favoris pour les applications</translation>
 <translation id="6305012486838822927">Clavier lao</translation>
-<translation id="6305328361606238230">Recevoir les messages Push</translation>
 <translation id="6307722552931206656">Serveurs de nom Google – <ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Système occupé.</translation>
 <translation id="6308937455967653460">Enregistrer le lie&amp;n sous...</translation>
@@ -4526,7 +4522,6 @@
 <translation id="7339785458027436441">Vérifier l'orthographe lors de la frappe</translation>
 <translation id="7339898014177206373">Nouvelle fenêtre</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> est maintenant en mode plein écran</translation>
-<translation id="7341982465543599097">extrêmement court</translation>
 <translation id="734303607351427494">Gérer les moteurs de recherche...</translation>
 <translation id="7343116142376328522">Interdire à tous les sites d'utiliser la génération de clé dans les formulaires (recommandé)</translation>
 <translation id="7345706641791090287">Confirmez votre mot de passe.</translation>
@@ -4911,7 +4906,6 @@
 <translation id="7881969471599061635">Désactiver les sous-titres</translation>
 <translation id="7884988936047469945">Fonctionnalités d'accessibilité expérimentales</translation>
 <translation id="7885253890047913815">Emplacements de destination récents</translation>
-<translation id="7885283703487484916">très court</translation>
 <translation id="7887192723714330082">Répondez à "Ok Google" lorsque l'écran est actif et déverrouillé.</translation>
 <translation id="7887334752153342268">Dupliquer</translation>
 <translation id="7887864092952184874">Souris Bluetooth associée.</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 73c5bcb..11689e2e 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">બ્રાઉઝિંગ ડેટા સાફ કરો સંવાદમાં ડેટા વૉલ્યૂમ કાઉન્ટર્સ દર્શાવે છે.</translation>
 <translation id="1097507499312291972">આ વ્યક્તિ મુલાકાત લે છે તે વેબસાઇટ્સ જોવા અને નિયંત્રિત કરવા માટે <ph name="BEGIN_SIGN_IN_LINK" />સાઇન ઇન<ph name="END_SIGN_IN_LINK" /> કરો.</translation>
 <translation id="1097658378307015415">સાઇન ઇન કરતા પહેલા, કૃપા કરીને નેટવર્ક <ph name="NETWORK_ID" /> ને સક્રિય કરવા માટે એક અતિથિ તરીકે દાખલ થાઓ</translation>
-<translation id="1104054824888299003">લાંબો</translation>
 <translation id="1104652314727136854">Chrome Apps માટે ફાઇલ જોડાણના OS એકીકરણને સક્ષમ કરો.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />", <ph name="USER_NAME" /> માટે આ ઍપ્લિકેશનો અને એક્સટેન્શન્સ ઉમેરે છે:</translation>
 <translation id="1108600514891325577">&amp;Stop</translation>
@@ -1868,7 +1867,6 @@
 <translation id="3512284449647229026">બ્રાઉઝર ઑફલાઇન હોય તે વખતે લોડ થવામાં નિષ્ફળ થયેલાં પૃષ્ઠો જ્યારે બ્રાઉઝર ફરીથી ઓનલાઇન થશે ત્યારે સ્વતઃ ફરીથી લોડ કરવામાં આવશે.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ડાઉનલોડ રદ કરો}one{ડાઉનલોડ્સ રદ કરો}other{ડાઉનલોડ્સ રદ કરો}}</translation>
 <translation id="3512810056947640266">URL (વૈકલ્પિક):</translation>
-<translation id="351486934407749662">ખૂબ લાંબો</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> તમારી સ્ક્રીનની સામગ્રીને શેર કરવા માગે છે. તમે શું શેર કરવા માગો છો તે પસંદ કરો.</translation>
 <translation id="3518086201899641494">કેપ્ટિવ પોર્ટલ્સ વિશે સૂચનાઓ</translation>
 <translation id="3519867315646775981">લિવ્યંતરણ (shalom ← שלום)</translation>
@@ -3401,7 +3399,6 @@
 <translation id="569109051430110155">સ્વતઃ શોધો</translation>
 <translation id="5691596662111998220">ઊફ્ફ, <ph name="FILE_NAME" /> હવે અસ્તિત્વમાં નથી.</translation>
 <translation id="5694501201003948907">$1 આઇટમ્સ ઝિપ કરી રહ્યું છે...</translation>
-<translation id="5695323626817702678">ટૂંકો</translation>
 <translation id="5697118958262594262">મૂળભૂત રીતે મહત્વપૂર્ણ સામગ્રી શોધો</translation>
 <translation id="5699533844376998780">એક્સ્ટેંશન "<ph name="EXTENSION_NAME" />" ઉમેરવામાં આવ્યું.</translation>
 <translation id="5701101281789450335">ભાષા અને ઇનપુટ સેટિંગ્સ...</translation>
@@ -3824,7 +3821,6 @@
 <translation id="630065524203833229">&amp;બહાર નીકળો</translation>
 <translation id="6304217058163308077">નવી બુકમાર્ક ઍપ્લિકેશન સિસ્ટમ</translation>
 <translation id="6305012486838822927">લાઓ કીબોર્ડ</translation>
-<translation id="6305328361606238230">પુશ સંદેશાઓ મેળવો</translation>
 <translation id="6307722552931206656">Google નામ સર્વર્સ - <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">સિસ્ટમ વ્યસ્ત છે</translation>
 <translation id="6308937455967653460">લિં&amp;કને આ રીતે સાચવો...</translation>
@@ -4520,7 +4516,6 @@
 <translation id="7339785458027436441">લખતી વખતે જોડણી તપાસો</translation>
 <translation id="7339898014177206373">નવી વિંડો</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> હવે પૂર્ણ સ્ક્રીન છે.</translation>
-<translation id="7341982465543599097">અત્યંત ટૂંકી</translation>
 <translation id="734303607351427494">શોધ એંજીન્સ મેનેજ કરો...</translation>
 <translation id="7343116142376328522">કોઈપણ સાઇટને ફોર્મ્સમાં કી જનરેશનનો ઉપયોગ કરવાની મંજૂરી આપશો નહીં (ભલામણ કરેલ)</translation>
 <translation id="7345706641791090287">તમારા પાસવર્ડની પુષ્ટિ કરો</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">ઉપશીર્ષકો અક્ષમ કરો</translation>
 <translation id="7884988936047469945">પ્રાયોગિક અ‍ૅક્સેસિબિલિટી સુવિધાઓ</translation>
 <translation id="7885253890047913815">તાજેતરનાં ગંતવ્યો</translation>
-<translation id="7885283703487484916">ખૂબ જ ટૂંકો</translation>
 <translation id="7887192723714330082">જ્યારે સ્ક્રીન ચાલુ અને અનલૉક કરેલી હોય ત્યારે "Ok Google" સાથે જવાબ આપો</translation>
 <translation id="7887334752153342268">ડુપ્લિકેટ</translation>
 <translation id="7887864092952184874">Bluetooth માઉસની જોડી બનાવી</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index 6be90f32..5ace8fb 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">ब्राउज़िंग डेटा साफ़ करें संवाद में डेटा की मात्रा के काउंटर दिखाता है.</translation>
 <translation id="1097507499312291972">इस व्यक्ति द्वारा देखी जाने वाली वेबसाइटें नियंत्रित करने और देखने के लिए <ph name="BEGIN_SIGN_IN_LINK" />प्रवेश करें<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">प्रवेश करने से पहले, कृपया <ph name="NETWORK_ID" /> नेटवर्क सक्रिय करने के लिए अतिथि के रूप में प्रविष्ट हों</translation>
-<translation id="1104054824888299003">लंबा</translation>
 <translation id="1104652314727136854">Chrome Apps के लिए फ़ाइलों के समूह का OS एकीकरण सक्षम करें.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />", <ph name="USER_NAME" /> के लिए इन ऐप्स और एक्सटेंशन को जोड़ता है:</translation>
 <translation id="1108600514891325577">&amp;रोकें</translation>
@@ -306,7 +305,7 @@
 <translation id="143027896309062157">अपने कंप्यूटर पर और देखी जाने वाली वेबसाइटों पर मौजूद अपना सभी डेटा पढ़ें और बदलें</translation>
 <translation id="1430915738399379752">प्रिंट करें</translation>
 <translation id="1432581352905426595">खोज इंजन प्रबंधित करें</translation>
-<translation id="1434696352799406980">यह आपके स्टार्टअप पृष्ठ, नया टैब पृष्ठ, खोज इंजन और पिन किए गए टैब को रीसेट करेगा. यह सभी एक्सटेंशन को भी अक्षम करेगा और कुकी जैसे अस्थायी डेटा को साफ़ करेगा. आपके बुकमार्क, इतिहास और सहेजे गए पासवर्ड साफ़ नहीं किए जाएंगे.</translation>
+<translation id="1434696352799406980">यह आपके शुरुआती पन्ने, नया टैब पृष्ठ, खोज इंजन और पिन किए गए टैब को रीसेट करेगा. यह सभी एक्सटेंशन को भी अक्षम करेगा और कुकी जैसे अस्थायी डेटा को साफ़ करेगा. आपके बुकमार्क, इतिहास और सहेजे गए पासवर्ड साफ़ नहीं किए जाएंगे.</translation>
 <translation id="1434886155212424586">मुख्यपृष्ठ, नया टैब पृष्ठ है</translation>
 <translation id="1435550882135542937">एक्सटेंशन टूलबार रीडिज़ाइन</translation>
 <translation id="1436402875660227532">ध्यान दें: इन सेटिंग का उपयोग अब इस सिस्टम पर नहीं किया जाता, लेकिन आप अब भी उन्हें देख और संपादित कर सकते हैं.</translation>
@@ -703,7 +702,7 @@
 <translation id="1976323404609382849">एकाधिक साइटों से कुकी को अवरोधित किया गया.</translation>
 <translation id="1979280758666859181">आप <ph name="PRODUCT_NAME" /> के पुराने वर्शन वाले चैनल में बदल रहे हैं. चैनल बदलाव तब लागू किया जाएगा जब चैनल का वर्शन आपके डिवाइस पर वर्तमान में इंस्टॉल किए गए वर्शन से मिलान करेगा.</translation>
 <translation id="1979444449436715782">टैब कैप्चर आकार घटाने की गुणवत्ता.</translation>
-<translation id="1979718561647571293">क्या यह वही स्टार्टअप पृष्ठ है जिसकी आप अपेक्षा कर रहे थे?</translation>
+<translation id="1979718561647571293">क्या यह वही शुरुआती पन्ना है जिसकी आप अपेक्षा कर रहे थे?</translation>
 <translation id="1983959805486816857">आपके द्वारा नया निगरानी में रखा गया उपयोगकर्ता बनाए जाने के बाद, आप <ph name="MANAGEMENT_URL" /> पर कभी भी किसी भी डिवाइस से सेटिंग प्रबंधित कर सकते हैं.</translation>
 <translation id="1984603991036629094">आर्मेनियाई फ़ोनेटिक कीबोर्ड</translation>
 <translation id="1984642098429648350">विंडो को दाईं ओर डॉक करें</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">ब्राउज़र के ऑफ़लाइन होने पर विफल होने वाले पृष्ठ केवल तभी स्वत:-रीलोड किए जाएंगे यदि टैब दृश्यमान हो.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{डाउनलोड रोकें}one{डाउनलोड रोकें}other{डाउनलोड रोकें}}</translation>
 <translation id="3512810056947640266">URL (वैकल्पिक):</translation>
-<translation id="351486934407749662">अधिक समय तक</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> आपकी स्क्रीन पर मौजूद सामग्रियों को साझा करना चाहता है. चुनें कि आप क्या साझा करना चाहते हैं.</translation>
 <translation id="3518086201899641494">कैप्टिव पोर्टल के बारे में सूचनाएं</translation>
 <translation id="3519867315646775981">लिप्यंतरण (shalom ← שלום)</translation>
@@ -3406,7 +3404,6 @@
 <translation id="569109051430110155">स्वतः पता लगाएं</translation>
 <translation id="5691596662111998220">ओह, <ph name="FILE_NAME" /> अब मौजूद नहीं है.</translation>
 <translation id="5694501201003948907">$1 आइटम ज़िप कर रहा है.</translation>
-<translation id="5695323626817702678">संक्षिप्त</translation>
 <translation id="5697118958262594262">महत्‍वपूर्ण सामग्री डिफ़ॉल्‍ट रूप से पता करें</translation>
 <translation id="5699533844376998780">एक्‍सटेंशन "<ph name="EXTENSION_NAME" />" जोड़ा गया.</translation>
 <translation id="5701101281789450335">भाषा और अक्षर सेटिंग...</translation>
@@ -3831,7 +3828,6 @@
 <translation id="630065524203833229">&amp;बाहर निकलें</translation>
 <translation id="6304217058163308077">नया बुकमार्क ऐप सिस्‍टम</translation>
 <translation id="6305012486838822927">लाओ कीबोर्ड</translation>
-<translation id="6305328361606238230">पुश संदेश प्राप्‍त करें</translation>
 <translation id="6307722552931206656">Google नाम सर्वर - <ph name="BEGIN_LINK" />अधिक जानें<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">सिस्‍टम व्‍यस्‍त है</translation>
 <translation id="6308937455967653460">इस रूप में लिं&amp;क सहेजें...</translation>
@@ -4528,7 +4524,6 @@
 <translation id="7339785458027436441">लिखते समय वर्तनी की जांच करें</translation>
 <translation id="7339898014177206373">नई विंडो</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> अब पूर्ण स्‍क्रीन है.</translation>
-<translation id="7341982465543599097">बहुत कम</translation>
 <translation id="734303607351427494">खोज इंजन प्रबंधित करें...</translation>
 <translation id="7343116142376328522">किसी भी साइट को फ़ॉर्म में कुंजी जेनरेशन का उपयोग करने की अनुमति ना दें (अनुशंसित)</translation>
 <translation id="7345706641791090287">अपने पासवर्ड की पुष्टि करें</translation>
@@ -4818,7 +4813,7 @@
 <translation id="775622227562445982">त्वरित रूप से टैब/विंडो बंद करें</translation>
 <translation id="7756363132985736290">प्रमाणपत्र पहले से मौजूद है.</translation>
 <translation id="7757425985031934767">स्पर्श द्वारा प्रारंभ किया जाने वाला खींचें और छोड़ें</translation>
-<translation id="7760004034676677601">क्या यह वही स्टार्टअप पृष्ठ है जिसकी आप अपेक्षा कर रहे थे?</translation>
+<translation id="7760004034676677601">क्या यह वही शुरुआती पन्ना है जिसकी आप अपेक्षा कर रहे थे?</translation>
 <translation id="7764225426217299476">पता जोड़ें</translation>
 <translation id="7764256770584298012"><ph name="DOWNLOAD_DOMAIN" /> से <ph name="DOWNLOAD_RECEIVED" /></translation>
 <translation id="7765158879357617694">ले जाएं</translation>
@@ -4913,7 +4908,6 @@
 <translation id="7881969471599061635">उपशीर्षक अक्षम करें</translation>
 <translation id="7884988936047469945">प्रयोगात्मक सरल-योग्यता सुविधाएं</translation>
 <translation id="7885253890047913815">हाल ही के गंतव्य</translation>
-<translation id="7885283703487484916">बहुत कम</translation>
 <translation id="7887192723714330082">स्‍क्रीन के चालू होने तथा अनलॉक होने पर "Ok Google" को प्रतिसाद दें</translation>
 <translation id="7887334752153342268">डुप्लिकेट</translation>
 <translation id="7887864092952184874">ब्लूटूथ माउस युग्मित किया गया</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index 006ad50..78f0b93 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Prikazuje brojače količine podataka u dijaloškom okviru Brisanje podataka o pregledavanju.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Prijavite se<ph name="END_SIGN_IN_LINK" /> kako biste upravljali web-lokacijama koje ova osoba posjeti i prikazali ih.</translation>
 <translation id="1097658378307015415">Prije nego što se prijavite, uđite kao gost da biste aktivirali mrežu <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">Duga</translation>
 <translation id="1104652314727136854">Omogućuje OS integraciju pridruživanja datoteka za Chromeove aplikacije.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" dodaje ove aplikacije i proširenja za korisnika <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Stop (Zaustavi)</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">Stranice koje se ne uspiju učitati dok preglednik nije povezan s mrežom automatski će se ponovo učitati ako je njihova kartica vidljiva.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Otkaži preuzimanje}one{Otkaži preuzimanja}few{Otkaži preuzimanja}other{Otkaži preuzimanja}}</translation>
 <translation id="3512810056947640266">URL (nije obavezno):</translation>
-<translation id="351486934407749662">Jako duga</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> želi dijeliti sadržaj vašeg zaslona. Odaberite što želite dijeliti.</translation>
 <translation id="3518086201899641494">Obavijesti o obaveznim portalima za autentifikaciju</translation>
 <translation id="3519867315646775981">transliteracija (shalom ← שלום)</translation>
@@ -3406,7 +3404,6 @@
 <translation id="569109051430110155">Automatsko otkrivanje</translation>
 <translation id="5691596662111998220">Ups, stavka <ph name="FILE_NAME" /> više ne postoji.</translation>
 <translation id="5694501201003948907">Komprimiranje stavki ($1)...</translation>
-<translation id="5695323626817702678">Kratka</translation>
 <translation id="5697118958262594262">Otkrij važan sadržaj prema zadanim postavkama</translation>
 <translation id="5699533844376998780">Dodano je proširenje "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">Postavke jezika i unosa...</translation>
@@ -3829,7 +3826,6 @@
 <translation id="630065524203833229">I&amp;zađi</translation>
 <translation id="6304217058163308077">Novi sustav aplikacija za oznake</translation>
 <translation id="6305012486838822927">laoska tipkovnica</translation>
-<translation id="6305328361606238230">Primanje push poruka</translation>
 <translation id="6307722552931206656">Googleovi poslužitelji naziva – <ph name="BEGIN_LINK" />saznajte više<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sustav je zauzet</translation>
 <translation id="6308937455967653460">Spremi ve&amp;zu kao...</translation>
@@ -4522,7 +4518,6 @@
 <translation id="7339785458027436441">Provjeravaj pravopis tijekom pisanja</translation>
 <translation id="7339898014177206373">Novi prozor</translation>
 <translation id="7340431621085453413">Stranica <ph name="FULLSCREEN_ORIGIN" /> sada je na cijelom zaslonu.</translation>
-<translation id="7341982465543599097">Iznimno kratka</translation>
 <translation id="734303607351427494">Upravljaj tražilicama...</translation>
 <translation id="7343116142376328522">Nemoj dopustiti nijednoj web-lokaciji upotrebu generiranja ključeva u obrascima (preporučeno)</translation>
 <translation id="7345706641791090287">Potvrdite zaporku</translation>
@@ -4906,7 +4901,6 @@
 <translation id="7881969471599061635">Onemogući titlove</translation>
 <translation id="7884988936047469945">Eksperimentalne značajke pristupačnosti</translation>
 <translation id="7885253890047913815">Nedavna odredišta</translation>
-<translation id="7885283703487484916">Vrlo kratka</translation>
 <translation id="7887192723714330082">Odgovoriti na "OK Google" kada je zaslon uključen i otključan</translation>
 <translation id="7887334752153342268">Udvostruči</translation>
 <translation id="7887864092952184874">Bluetooth miš uparen</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index f50d839..2345b69 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Megjeleníti az adatmennyiség számlálóit a Böngészési adatok törlése párbeszédablakban.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Jelentkezzen be<ph name="END_SIGN_IN_LINK" />, hogy vezérelhesse és megtekinthesse az e személy által felkeresett webhelyeket.</translation>
 <translation id="1097658378307015415">Kérjük, bejelentkezés előtt a(z) <ph name="NETWORK_ID" /> hálózat aktiválásához lépjen be vendégként.</translation>
-<translation id="1104054824888299003">hosszú</translation>
 <translation id="1104652314727136854">Engedélyezi az operációs rendszer fájltársításainak integrációját Chrome-alkalmazásokhoz.</translation>
 <translation id="1105162038795579389">A(z) „<ph name="BUNDLE_NAME" />” hozzáadja ezeket az alkalmazásokat és bővítményeket <ph name="USER_NAME" /> számára:</translation>
 <translation id="1108600514891325577">&amp;Leállítás</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Azok az oldalak, amelyek nem tudnak betöltődni a böngésző offline állapotában, csak akkor töltődnek újra automatikusan, ha lapjuk látható.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Letöltés megszakítása}other{Letöltések megszakítása}}</translation>
 <translation id="3512810056947640266">URL (nem kötelező):</translation>
-<translation id="351486934407749662">nagyon hosszú</translation>
 <translation id="3517839692979918726">A(z) <ph name="APP_NAME" /> alkalmazás szeretné megosztani képernyőjének tartalmát. Válassza ki, hogy mit kíván megosztani.</translation>
 <translation id="3518086201899641494">Captive (előzetes hitelesítést igénylő) portálokkal kapcsolatos értesítések</translation>
 <translation id="3519867315646775981">Átírás (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Automatikus felismerés</translation>
 <translation id="5691596662111998220">Hoppá! A(z) <ph name="FILE_NAME" /> már nem létezik.</translation>
 <translation id="5694501201003948907">$1 elem tömörítése...</translation>
-<translation id="5695323626817702678">rövid</translation>
 <translation id="5697118958262594262">Fontos tartalmak észlelése alapértelmezés szerint</translation>
 <translation id="5699533844376998780">A(z) "<ph name="EXTENSION_NAME" />" bővítmény hozzáadása megtörtént.</translation>
 <translation id="5701101281789450335">Nyelvi és beviteli beállítások...</translation>
@@ -3830,7 +3827,6 @@
 <translation id="630065524203833229">K&amp;ilépés</translation>
 <translation id="6304217058163308077">Az új könyvjelzőalkalmazás-rendszer</translation>
 <translation id="6305012486838822927">Lao billentyűzet</translation>
-<translation id="6305328361606238230">Push üzenetek fogadása</translation>
 <translation id="6307722552931206656">Google névszerverek – <ph name="BEGIN_LINK" />További információ<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">A rendszer foglalt</translation>
 <translation id="6308937455967653460">Link mentése &amp;másként...</translation>
@@ -4524,7 +4520,6 @@
 <translation id="7339785458027436441">Helyesírás-ellenőrzés gépeléskor</translation>
 <translation id="7339898014177206373">Új ablak</translation>
 <translation id="7340431621085453413">A <ph name="FULLSCREEN_ORIGIN" /> most teljes képernyős nézetben van.</translation>
-<translation id="7341982465543599097">rendkívül rövid</translation>
 <translation id="734303607351427494">Keresőmotorok kezelése...</translation>
 <translation id="7343116142376328522">A kulcsgenerálás űrlapokban való használatának letiltása minden webhely számára (javasolt)</translation>
 <translation id="7345706641791090287">Erősítse meg a jelszót</translation>
@@ -4909,7 +4904,6 @@
 <translation id="7881969471599061635">Feliratok letiltása</translation>
 <translation id="7884988936047469945">Kísérleti kisegítő funkciók</translation>
 <translation id="7885253890047913815">Legutóbbi célhelyek</translation>
-<translation id="7885283703487484916">nagyon rövid</translation>
 <translation id="7887192723714330082">Válasz az „Ok Google” kimondására, amikor a képernyő be van kapcsolva, és nincs zárolva</translation>
 <translation id="7887334752153342268">Másodpéldány</translation>
 <translation id="7887864092952184874">Bluetooth-egér párosítva</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index 3d43ecb..efea736 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Menampilkan penghitung volume data dalam dialog Hapus data penjelajahan.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Masuk<ph name="END_SIGN_IN_LINK" /> untuk mengontrol dan melihat situs web yang dikunjungi orang ini.</translation>
 <translation id="1097658378307015415">Sebelum masuk, masuklah sebagai Tamu untuk mengaktifkan jaringan <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">lama</translation>
 <translation id="1104652314727136854">Mengaktifkan integrasi OS dari kaitan file untuk Aplikasi Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" menambahkan aplikasi dan ekstensi ini untuk <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Berhenti</translation>
@@ -1436,7 +1435,7 @@
 <translation id="2951247061394563839">Memusatkan jendela</translation>
 <translation id="2951721188322348056">Info Video</translation>
 <translation id="2956763290572484660"><ph name="COOKIES" /> cookie</translation>
-<translation id="295947108480905647">"<ph name="CHROME_EXTENSION_NAME" />" ingin menyambungkan ke:</translation>
+<translation id="295947108480905647">"<ph name="CHROME_EXTENSION_NAME" />" ingin terhubung ke:</translation>
 <translation id="2959614062380389916">Dinonaktifkan oleh administrator</translation>
 <translation id="2960393411257968125">Cara pengelola sandi menangani IsiOtomatis untuk kredensial sinkronisasi.</translation>
 <translation id="29611076221683977">Saat ini penyerang yang berada pada <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin berusaha memasang program berbahaya di Mac yang dapat mencuri atau menghapus informasi Anda (misalnya, foto, sandi, pesan, dan kartu kredit).</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Laman yang gagal dimuat saat browser offline hanya akan dimuat ulang secara otomatis apabila tabnya terlihat.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Batalkan Unduhan}other{Batalkan Unduhan}}</translation>
 <translation id="3512810056947640266">URL (opsional):</translation>
-<translation id="351486934407749662">sangat lama</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> ingin membagikan konten layar Anda. Pilih yang ingin Anda bagikan.</translation>
 <translation id="3518086201899641494">Notifikasi tentang portal yang tertahan</translation>
 <translation id="3519867315646775981">Transliterasi (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Deteksi otomatis</translation>
 <translation id="5691596662111998220">Ups, <ph name="FILE_NAME" /> sudah tidak ada.</translation>
 <translation id="5694501201003948907">Membuat file zip $1 item...</translation>
-<translation id="5695323626817702678">sebentar</translation>
 <translation id="5697118958262594262">Deteksi konten penting secara default</translation>
 <translation id="5699533844376998780">Ekstensi "<ph name="EXTENSION_NAME" />" telah ditambahkan.</translation>
 <translation id="5701101281789450335">Setelan bahasa dan masukan...</translation>
@@ -3715,7 +3712,7 @@
 <translation id="6136285399872347291">backspace</translation>
 <translation id="613656389911605597">Status unduhan ditampilkan sebagai notifikasi, bukan item pada bilah unduhan.</translation>
 <translation id="6139064580472999710">Kotak Pasir Ruang Nama</translation>
-<translation id="6139601088809813095">Nonaktifkan UI versi Baru untuk Jendela Alat Pilih Tangkapan Desktop.</translation>
+<translation id="6139601088809813095">Nonaktifkan Antarmuka versi Baru untuk Jendela Alat Pilih Tangkapan Desktop.</translation>
 <translation id="614161640521680948">Bahasa:</translation>
 <translation id="6143186082490678276">Dapatkan Bantuan</translation>
 <translation id="6144697279259829572">{NUM_ITEMS,plural, =1{Tindakan ini akan menghapus setidaknya $1 item dari perangkat ini secara permanen.}other{Tindakan ini akan menghapus setidaknya $1 item dari perangkat ini secara permanen.}}</translation>
@@ -3830,7 +3827,6 @@
 <translation id="630065524203833229">K&amp;eluar</translation>
 <translation id="6304217058163308077">Sistem aplikasi bookmark baru</translation>
 <translation id="6305012486838822927">Keyboard Lao</translation>
-<translation id="6305328361606238230">Menerima pesan push</translation>
 <translation id="6307722552931206656">Server nama Google - <ph name="BEGIN_LINK" />Pelajari lebih lanjut<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistem sibuk</translation>
 <translation id="6308937455967653460">Simpan tau&amp;tan sebagai...</translation>
@@ -4524,7 +4520,6 @@
 <translation id="7339785458027436441">Periksa Ejaan Saat Mengetik</translation>
 <translation id="7339898014177206373">Jendela baru</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> kini menjadi layar penuh.</translation>
-<translation id="7341982465543599097">sangat pendek</translation>
 <translation id="734303607351427494">Kelola mesin telusur...</translation>
 <translation id="7343116142376328522">Jangan izinkan situs apa pun menggunakan pembuatan kunci dalam formulir (disarankan)</translation>
 <translation id="7345706641791090287">Konfirmasi sandi Anda</translation>
@@ -4909,7 +4904,6 @@
 <translation id="7881969471599061635">Nonaktifkan subtitel</translation>
 <translation id="7884988936047469945">Fitur aksesibilitas eksperimental</translation>
 <translation id="7885253890047913815">Tujuan Saat Ini</translation>
-<translation id="7885283703487484916">terlalu singkat</translation>
 <translation id="7887192723714330082">Merespons perintah "Ok Google" saat layar aktif dan terbuka</translation>
 <translation id="7887334752153342268">Gandakan</translation>
 <translation id="7887864092952184874">Mouse Bluetooth disandingkan</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index dda831f7..ba98186 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Mostra i contatori del volume di dati nella finestra di dialogo Cancella dati di navigazione.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Accedi<ph name="END_SIGN_IN_LINK" /> per controllare e visualizzare i siti web visitati da questa persona.</translation>
 <translation id="1097658378307015415">Prima di accedere, entra come Ospite per attivare la rete <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">lungo</translation>
 <translation id="1104652314727136854">Consente di attivare l'integrazione nel sistema operativo delle associazioni di file per le app di Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" aggiunge le seguenti app ed estensioni per <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Interrompi</translation>
@@ -1869,7 +1868,6 @@
 <translation id="3512284449647229026">Le pagine che non vengono caricate quando il browser è offline vengono ricaricate automaticamente soltanto se la relativa scheda è visibile.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Annulla download}other{Annulla download}}</translation>
 <translation id="3512810056947640266">URL (facoltativo):</translation>
-<translation id="351486934407749662">molto lungo</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> vorrebbe condividere i contenuti del tuo schermo. Scegli i contenuti che desideri condividere.</translation>
 <translation id="3518086201899641494">Notifiche relative a captive portal</translation>
 <translation id="3519867315646775981">Traslitterazione (shalom ← שלום)</translation>
@@ -3400,7 +3398,6 @@
 <translation id="569109051430110155">Rileva automaticamente</translation>
 <translation id="5691596662111998220">Spiacenti. <ph name="FILE_NAME" /> non esiste più.</translation>
 <translation id="5694501201003948907">Compressione di $1 elementi...</translation>
-<translation id="5695323626817702678">breve</translation>
 <translation id="5697118958262594262">Rileva contenuti importanti per impostazione predefinita</translation>
 <translation id="5699533844376998780">L'estensione "<ph name="EXTENSION_NAME" />" è stata aggiunta.</translation>
 <translation id="5701101281789450335">Impostazioni della lingua e di immissione...</translation>
@@ -3823,7 +3820,6 @@
 <translation id="630065524203833229">E&amp;sci</translation>
 <translation id="6304217058163308077">Il nuovo sistema di app di preferiti</translation>
 <translation id="6305012486838822927">Tastiera Lao</translation>
-<translation id="6305328361606238230">Vuoi ricevere messaggi push?</translation>
 <translation id="6307722552931206656">Assegnazione nomi ai server da Google - <ph name="BEGIN_LINK" />Ulteriori informazioni<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistema occupato</translation>
 <translation id="6308937455967653460">Salva lin&amp;k con nome...</translation>
@@ -4518,7 +4514,6 @@
 <translation id="7339785458027436441">Controllo ortografico durante la digitazione</translation>
 <translation id="7339898014177206373">Nuova finestra</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> ora è a schermo intero.</translation>
-<translation id="7341982465543599097">molto breve</translation>
 <translation id="734303607351427494">Gestisci motori di ricerca...</translation>
 <translation id="7343116142376328522">Non consentire ai siti di utilizzare la generazione di chiavi nei moduli (opzione consigliata)</translation>
 <translation id="7345706641791090287">Conferma la password</translation>
@@ -4894,7 +4889,6 @@
 <translation id="7881969471599061635">Disattiva i sottotitoli</translation>
 <translation id="7884988936047469945">Funzioni di accessibilità sperimentali</translation>
 <translation id="7885253890047913815">Destinazioni recenti</translation>
-<translation id="7885283703487484916">molto breve</translation>
 <translation id="7887192723714330082">Rispondere al comando "Ok Google" quando lo schermo è attivo e sbloccato</translation>
 <translation id="7887334752153342268">Duplica</translation>
 <translation id="7887864092952184874">Mouse Bluetooth accoppiato</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 645bc796..557dc64 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">הצג מונים של נפח נתונים בתיבת הדו-שיח 'נקה נתוני גלישה'.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />היכנס<ph name="END_SIGN_IN_LINK" /> כדי להציג את האתרים שבהם משתמש זה ביקר ולשלוט בהם.</translation>
 <translation id="1097658378307015415">לפני הכניסה לחשבון, היכנס כאורח כדי להפעיל את הרשת <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">ארוכה</translation>
 <translation id="1104652314727136854">‏הפעל שילוב מערכת הפעלה של שיוכי קבצים עבור יישומי Chrome.</translation>
 <translation id="1105162038795579389">החבילה "<ph name="BUNDLE_NAME" />" מוסיפה את האפליקציות והתוספים האלה בשביל <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;הפסק</translation>
@@ -1867,7 +1866,6 @@
 <translation id="3512284449647229026">דפים שהטעינה שלהם נכשלת כאשר הדפדפן במצב לא מקוון ייטענו אוטומטית רק אם הכרטיסייה גלויה.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{בטל הורדה}two{בטל הורדות}many{בטל הורדות}other{בטל הורדות}}</translation>
 <translation id="3512810056947640266">כתובת אתר (אופציונלי):</translation>
-<translation id="351486934407749662">ארוכה מאוד</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> רוצה לשתף את תוכן המסך שלך. בחר את התוכן שברצונך לשתף.</translation>
 <translation id="3518086201899641494">הודעות על פורטל חובה</translation>
 <translation id="3519867315646775981">‏תעתוק (שלום ← shalom)</translation>
@@ -3403,7 +3401,6 @@
 <translation id="569109051430110155">איתור אוטומטי</translation>
 <translation id="5691596662111998220">אופס, <ph name="FILE_NAME" /> כבר לא קיים.</translation>
 <translation id="5694501201003948907">מכווץ $1 פריטים...</translation>
-<translation id="5695323626817702678">קצרה</translation>
 <translation id="5697118958262594262">זהה תוכן חשוב כברירת מחדל</translation>
 <translation id="5699533844376998780">התוסף "<ph name="EXTENSION_NAME" />" נוסף.</translation>
 <translation id="5701101281789450335">הגדרות שפה וקלט...</translation>
@@ -3826,7 +3823,6 @@
 <translation id="630065524203833229">צ&amp;א</translation>
 <translation id="6304217058163308077">המערכת החדשה של אפליקציה של סימניות</translation>
 <translation id="6305012486838822927">מקלדת לאית</translation>
-<translation id="6305328361606238230">קבל הודעות בדחיפה</translation>
 <translation id="6307722552931206656">‏שרתי השמות של Google‏ - <ph name="BEGIN_LINK" />למידע נוסף<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">המערכת עמוסה</translation>
 <translation id="6308937455967653460">שמור קישור&amp; בשם...</translation>
@@ -4519,7 +4515,6 @@
 <translation id="7339785458027436441">בדוק איות בעת ההקלדה</translation>
 <translation id="7339898014177206373">חלון חדש</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> הוא במסך מלא כעת.</translation>
-<translation id="7341982465543599097">קצרה מאוד</translation>
 <translation id="734303607351427494">נהל מנועי חיפוש...</translation>
 <translation id="7343116142376328522">אל תרשה לאף אתר להשתמש ביצירת מפתחות בטפסים (מומלץ)</translation>
 <translation id="7345706641791090287">אשר את הסיסמה שלך</translation>
@@ -4896,7 +4891,6 @@
 <translation id="7881969471599061635">השבת כתוביות</translation>
 <translation id="7884988936047469945">תכונות נגישות ניסיוניות</translation>
 <translation id="7885253890047913815">יעדים אחרונים</translation>
-<translation id="7885283703487484916">קצרה מאוד</translation>
 <translation id="7887192723714330082">‏הגב ל-"Ok Google" כשהמסך פועל ואינו נעול</translation>
 <translation id="7887334752153342268">שכפול</translation>
 <translation id="7887864092952184874">‏עכבר Bluetooth מחובר</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 11a3754..184a4484 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">[閲覧履歴の消去] ダイアログにデータ量のカウンタを表示します。</translation>
 <translation id="1097507499312291972">このユーザーがアクセスするウェブサイトを管理、表示するには、<ph name="BEGIN_SIGN_IN_LINK" />ログイン<ph name="END_SIGN_IN_LINK" />します。</translation>
 <translation id="1097658378307015415">ログインする前に、ゲスト セッションを開始して <ph name="NETWORK_ID" /> ネットワークを有効にしてください</translation>
-<translation id="1104054824888299003">長い</translation>
 <translation id="1104652314727136854">Chrome アプリのファイルの関連付けに関して、OS の統合を有効にします。</translation>
 <translation id="1105162038795579389">「<ph name="BUNDLE_NAME" />」をインストールすると、次のアプリと拡張機能が <ph name="USER_NAME" /> さんのアイテムとして追加されます。</translation>
 <translation id="1108600514891325577">停止(&amp;S)</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">ブラウザがオフラインのときに読み込めなかったページは、タブが表示されている場合のみ自動再読み込みします。</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ダウンロードをキャンセル}other{ダウンロードをキャンセル}}</translation>
 <translation id="3512810056947640266">URL(省略可):</translation>
-<translation id="351486934407749662">非常に長い</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> が画面コンテンツの共有をリクエストしています。共有する部分を選択してください。</translation>
 <translation id="3518086201899641494">キャプティブ ポータルに関する通知</translation>
 <translation id="3519867315646775981">文字変換(shalom ← שלום)</translation>
@@ -3408,7 +3406,6 @@
 <translation id="569109051430110155">自動検出</translation>
 <translation id="5691596662111998220"><ph name="FILE_NAME" /> が存在しません。</translation>
 <translation id="5694501201003948907">$1 件のアイテムを圧縮しています...</translation>
-<translation id="5695323626817702678">短い</translation>
 <translation id="5697118958262594262">重要なコンテンツを既定で検出</translation>
 <translation id="5699533844376998780">拡張機能「<ph name="EXTENSION_NAME" />」を追加しました。</translation>
 <translation id="5701101281789450335">言語と入力の設定...</translation>
@@ -3831,7 +3828,6 @@
 <translation id="630065524203833229">終了(&amp;X)</translation>
 <translation id="6304217058163308077">新しいブックマーク アプリ システム</translation>
 <translation id="6305012486838822927">ラオス語キーボード</translation>
-<translation id="6305328361606238230">プッシュ メッセージの受信</translation>
 <translation id="6307722552931206656">Google ネーム サーバー - <ph name="BEGIN_LINK" />詳細<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">システムがビジー状態です</translation>
 <translation id="6308937455967653460">名前を付けてリンク先を保存(&amp;K)...</translation>
@@ -4526,7 +4522,6 @@
 <translation id="7339785458027436441">入力中にスペルチェック</translation>
 <translation id="7339898014177206373">新しいウィンドウ</translation>
 <translation id="7340431621085453413">現在 <ph name="FULLSCREEN_ORIGIN" /> は全画面表示です。</translation>
-<translation id="7341982465543599097">極めて短い</translation>
 <translation id="734303607351427494">検索エンジンの管理...</translation>
 <translation id="7343116142376328522">すべてのサイトに対してフォームでのキー生成の使用を許可しない(推奨)</translation>
 <translation id="7345706641791090287">パスワードを再入力</translation>
@@ -4913,7 +4908,6 @@
 <translation id="7881969471599061635">字幕を無効にする</translation>
 <translation id="7884988936047469945">試験運用版のユーザー補助機能</translation>
 <translation id="7885253890047913815">最近使用した送信先</translation>
-<translation id="7885283703487484916">非常に短い</translation>
 <translation id="7887192723714330082">画面がオンでロック解除された状態のときに「OK Google」に反応するようになりました</translation>
 <translation id="7887334752153342268">タブを複製</translation>
 <translation id="7887864092952184874">Bluetooth マウスがペア設定されました</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index 54285f1..193f034d 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">ಬ್ರೌಸಿಂಗ್ ಡೇಟಾ ತೆರವುಗೊಳಿಸು ಸಂವಾದದಲ್ಲಿ ಡೇಟಾ ವಾಲ್ಯೂಮ್ ಕೌಂಟರ್‌ಗಳನ್ನು ತೋರಿಸುತ್ತದೆ.</translation>
 <translation id="1097507499312291972">ಈ ವ್ಯಕ್ತಿಯ ಭೇಟಿಗಳ ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ಮತ್ತು ವೀಕ್ಷಿಸಲು <ph name="BEGIN_SIGN_IN_LINK" />ಸೈನ್‌ ಇನ್‌<ph name="END_SIGN_IN_LINK" /> ಮಾಡಿ.</translation>
 <translation id="1097658378307015415">ಸೈನ್ ಇನ್ ಮಾಡುವ ಮುನ್ನ, <ph name="NETWORK_ID" /> ನೆಟ್‌ವರ್ಕ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಅತಿಥಿಯಾಗಿ ಪ್ರವೇಶಿಸಿ</translation>
-<translation id="1104054824888299003">ದೀರ್ಘ</translation>
 <translation id="1104652314727136854">Chrome ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಫೈಲ್ ಸಹಯೋಗಗಳ OS ಸಂಯೋಜನೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" ಈ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಹಾಗೂ ವಿಸ್ತರಣೆಗಳನ್ನು <ph name="USER_NAME" /> ಗೆ ಸೇರಿಸುತ್ತದೆ:</translation>
 <translation id="1108600514891325577">&amp;ನಿಲ್ಲಿಸು</translation>
@@ -1870,7 +1869,6 @@
 <translation id="3512284449647229026">ಬ್ರೌಸರ್ ಆಫ್‌ಲೈನ್‌ನಲ್ಲಿರುವಾಗ ಲೋಡ್ ಆಗುವಲ್ಲಿ ವಿಫಲವಾಗುವ ಪುಟಗಳ ಟ್ಯಾಬ್ ಗೋಚರಿಸಿದರೆ ಮಾತ್ರ ಅವುಗಳು ಸ್ವಯಂ-ಮರುಲೋಡ್ ಆಗುತ್ತವೆ.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ಡೌನ್‌ಲೋಡ್ ರದ್ದುಮಾಡಿ}one{ಡೌನ್‌ಲೋಡ್‌ಗಳನ್ನು ರದ್ದುಮಾಡಿ}other{ಡೌನ್‌ಲೋಡ್‌ಗಳನ್ನು ರದ್ದುಮಾಡಿ}}</translation>
 <translation id="3512810056947640266">URL (ಐಚ್ಛಿಕ):</translation>
-<translation id="351486934407749662">ಬಹಳ ದೀರ್ಘ</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> ನಿಮ್ಮ ಪರದೆಯಲ್ಲಿರುವ ವಿಷಯವನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಬಯಸುತ್ತದೆ. ನೀವು ಹಂಚಿಕೊಳ್ಳಲು ಬಯಸುವ ಸಂಗತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ.</translation>
 <translation id="3518086201899641494">ವಶದಲ್ಲಿರುವ ಪೋರ್ಟಲ್‌ಗಳ ಕುರಿತು ಅಧಿಸೂಚನೆಗಳು</translation>
 <translation id="3519867315646775981">ಲಿಪ್ಯಂತರಣ (shalom ← שלום)</translation>
@@ -3411,7 +3409,6 @@
 <translation id="569109051430110155">ಸ್ವಯಂ ಪತ್ತೆಮಾಡು</translation>
 <translation id="5691596662111998220">ಓಹ್, <ph name="FILE_NAME" /> ಇನ್ನು ಮುಂದೆ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವುದಿಲ್ಲ.</translation>
 <translation id="5694501201003948907">$1 ಐಟಂಗಳನ್ನು ಜಿಪ್ ಮಾಡಲಾಗುತ್ತಿದೆ...</translation>
-<translation id="5695323626817702678">ಚಿಕ್ಕ</translation>
 <translation id="5697118958262594262">ಡಿಫಾಲ್ಟ್ ಮೂಲಕ ಪ್ರಮುಖ ವಿಷಯವನ್ನು ಪತ್ತೆ ಮಾಡಿ</translation>
 <translation id="5699533844376998780">"<ph name="EXTENSION_NAME" />" ವಿಸ್ತರಣೆಯನ್ನು ಸೇರಿಸಲಾಗಿದೆ.</translation>
 <translation id="5701101281789450335">ಭಾಷೆ ಹಾಗೂ ಇನ್‌ಪುಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು...</translation>
@@ -3834,7 +3831,6 @@
 <translation id="630065524203833229">ನಿರ್ಗ&amp;ಮನ</translation>
 <translation id="6304217058163308077">ಹೊಸ ಬುಕ್‌ಮಾರ್ಕ್ ಅಪ್ಲಿಕೇಶನ್ ಸಿಸ್ಟಂ</translation>
 <translation id="6305012486838822927">ಲಾವೊ ಕೀಬೋರ್ಡ್</translation>
-<translation id="6305328361606238230">ಪುಶ್ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿ</translation>
 <translation id="6307722552931206656">Google ಹೆಸರಿನ ಸರ್ವರ್‌ಗಳು - <ph name="BEGIN_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">ಸಿಸ್ಟಂ ಕಾರ್ಯನಿರತವಾಗಿದೆ</translation>
 <translation id="6308937455967653460">ಇದರಂತೆ ಲಿಂ&amp;ಕ್ ಅನ್ನು ಉಳಿಸಿ...</translation>
@@ -4529,7 +4525,6 @@
 <translation id="7339785458027436441">ಬೆರಳಚ್ಚಿಸುವ ಸಮಯದಲ್ಲಿ ಕಾಗುಣಿತ ಪರೀಕ್ಷಿಸು</translation>
 <translation id="7339898014177206373">ಹೊಸ ವಿಂಡೊ</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> ಇದೀಗ ಪೂರ್ಣ ಪರದೆಯಾಗಿದೆ.</translation>
-<translation id="7341982465543599097">ಅತ್ಯಂತ ಚಿಕ್ಕದು</translation>
 <translation id="734303607351427494">ಹುಡುಕಾಟದ ಎಂಜಿನ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸು...</translation>
 <translation id="7343116142376328522">ಫಾರ್ಮ್‌ಗಳಲ್ಲಿ ಕೀ ರಚನೆಯನ್ನು ಬಳಸಲು ಯಾವುದೇ ಸೈಟ್‌ಗೆ ಅನುಮತಿಸಬೇಡ (ಶಿಫಾರಸು ಮಾಡಲಾಗಿದೆ)</translation>
 <translation id="7345706641791090287">ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಖಚಿತಪಡಿಸಿ</translation>
@@ -4914,7 +4909,6 @@
 <translation id="7881969471599061635">ಉಪಶೀರ್ಷಿಕೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸು</translation>
 <translation id="7884988936047469945">ಪ್ರಾಯೋಗಿಕ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳು</translation>
 <translation id="7885253890047913815">ಇತ್ತೀಚಿನ ಗಮ್ಯಸ್ಥಾನಗಳು</translation>
-<translation id="7885283703487484916">ತುಂಬಾ ಚಿಕ್ಕದು</translation>
 <translation id="7887192723714330082">ಪರದೆಯು ಆನ್ ಆಗಿರುವಾಗ ಮತ್ತು ಅನ್‌ಲಾಕ್ ಮಾಡಿರುವಾಗ "Ok Google" ಗೆ ಪ್ರತಿಕ್ರಿಯಿಸಿ</translation>
 <translation id="7887334752153342268">ನಕಲು</translation>
 <translation id="7887864092952184874">Bluetooth ಮೌಸ್ ಜೋಡಿಯಾಗಿದೆ</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index 513f09f..edcb017 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">인터넷 사용 기록 삭제 대화 상자에 데이터 볼륨 카운터를 표시합니다.</translation>
 <translation id="1097507499312291972">이 사용자가 방문하는 웹사이트를 제어하고 조회하려면 <ph name="BEGIN_SIGN_IN_LINK" />로그인<ph name="END_SIGN_IN_LINK" />합니다.</translation>
 <translation id="1097658378307015415">로그인하기 전에 손님으로 로그인하여 <ph name="NETWORK_ID" /> 네트워크를 활성화하세요.</translation>
-<translation id="1104054824888299003">길게</translation>
 <translation id="1104652314727136854">Chrome 앱의 파일 연결에 OS 통합을 사용 설정합니다.</translation>
 <translation id="1105162038795579389">'<ph name="BUNDLE_NAME" />' 설치 시 <ph name="USER_NAME" />에게 추가되는 앱과 확장 프로그램은 다음과 같습니다.</translation>
 <translation id="1108600514891325577">중지(&amp;S)</translation>
@@ -1874,7 +1873,6 @@
 <translation id="3512284449647229026">브라우저가 오프라인 상태일 때 로드하지 못한 페이지는 탭이 표시되면 자동으로 새로고침됩니다.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{다운로드 취소}other{다운로드 취소}}</translation>
 <translation id="3512810056947640266">URL(선택사항):</translation>
-<translation id="351486934407749662">매우 길게</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" />에서 내 화면의 콘텐츠를 공유하려고 합니다. 공유할 항목을 선택하세요.</translation>
 <translation id="3518086201899641494">웹포털 인증 알림</translation>
 <translation id="3519867315646775981">음역(shalom ← שלום)</translation>
@@ -3408,7 +3406,6 @@
 <translation id="569109051430110155">자동 선택</translation>
 <translation id="5691596662111998220"><ph name="FILE_NAME" />이(가) 더 이상 존재하지 않습니다.</translation>
 <translation id="5694501201003948907">$1개 항목 압축 중...</translation>
-<translation id="5695323626817702678">짧게</translation>
 <translation id="5697118958262594262">기본적으로 중요한 콘텐츠 감지</translation>
 <translation id="5699533844376998780">확장 프로그램 '<ph name="EXTENSION_NAME" />'이(가) 추가되었습니다.</translation>
 <translation id="5701101281789450335">언어 및 입력 설정...</translation>
@@ -3833,7 +3830,6 @@
 <translation id="630065524203833229">종료(&amp;X)</translation>
 <translation id="6304217058163308077">새 북마크 앱 시스템</translation>
 <translation id="6305012486838822927">라오어 키보드</translation>
-<translation id="6305328361606238230">푸시 메시지 받기</translation>
 <translation id="6307722552931206656">Google 이름 서버 - <ph name="BEGIN_LINK" />자세히 알아보기<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">시스템을 사용 중</translation>
 <translation id="6308937455967653460">다른 이름으로 링크 저장(&amp;K)...</translation>
@@ -4529,7 +4525,6 @@
 <translation id="7339785458027436441">입력 시 맞춤법 검사</translation>
 <translation id="7339898014177206373">새 창</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" />이(가) 이제 전체화면으로 표시됩니다.</translation>
-<translation id="7341982465543599097">매우 짧게</translation>
 <translation id="734303607351427494">검색엔진 관리...</translation>
 <translation id="7343116142376328522">모든 사이트에서 양식 내에 키 생성 사용 허용 안함(권장)</translation>
 <translation id="7345706641791090287">비밀번호 확인</translation>
@@ -4914,7 +4909,6 @@
 <translation id="7881969471599061635">자막 사용 중지</translation>
 <translation id="7884988936047469945">실험용 접근성 기능</translation>
 <translation id="7885253890047913815">최근 대상</translation>
-<translation id="7885283703487484916">매우 짧게</translation>
 <translation id="7887192723714330082">화면이 켜지고 잠금 해제된 경우 'Ok Google'에 응답합니다.</translation>
 <translation id="7887334752153342268">새 탭에서 보기</translation>
 <translation id="7887864092952184874">블루투스 마우스 페어링됨</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index ad9996c..0d1553a 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Rodomi duomenų kiekio skaitikliai naršymo duomenų išvalymo dialogo lange.</translation>
 <translation id="1097507499312291972">Jei norite valdyti ir peržiūrėti svetaines, kuriose lankosi šis asmuo, <ph name="BEGIN_SIGN_IN_LINK" />prisijunkite<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">Prieš prisijungdami įeikite kaip svečias, kad suaktyvintumėte tinklą <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">ilga</translation>
 <translation id="1104652314727136854">Įgalinti „Chrome“ programoms skirtą failų susiejimo OS integraciją.</translation>
 <translation id="1105162038795579389">Įdiegus „<ph name="BUNDLE_NAME" />“ naudotojui <ph name="USER_NAME" /> bus pridėti šie plėtiniai ir programos:</translation>
 <translation id="1108600514891325577">&amp;Sustabdyti</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Puslapiai, kurių nepavyksta įkelti, kai naršyklė naudojama neprisijungus, bus automatiškai įkelti iš naujo, tik kai jų skirtukai bus matomi.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Atšaukti atsisiuntimą}one{Atšaukti atsisiuntimus}few{Atšaukti atsisiuntimus}many{Atšaukti atsisiuntimus}other{Atšaukti atsisiuntimus}}</translation>
 <translation id="3512810056947640266">URL (pasirenkama):</translation>
-<translation id="351486934407749662">labai ilga</translation>
 <translation id="3517839692979918726">„<ph name="APP_NAME" />“ norėtų bendrinti ekrano turinį. Pasirinkite, ką norite bendrinti.</translation>
 <translation id="3518086201899641494">Pranešimai apie užvaldytus portalus</translation>
 <translation id="3519867315646775981">Transliteracija (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Automatinis atpažinimas</translation>
 <translation id="5691596662111998220">Oi, „<ph name="FILE_NAME" />“ nebėra.</translation>
 <translation id="5694501201003948907">Archyvuojama elementų: 1 dol...</translation>
-<translation id="5695323626817702678">trumpa</translation>
 <translation id="5697118958262594262">Nustatyti svarbų turinį pagal numatytuosius nustatymus</translation>
 <translation id="5699533844376998780">Plėtinys „<ph name="EXTENSION_NAME" />“ pridėtas.</translation>
 <translation id="5701101281789450335">Kalbos ir įvesties nustatymai...</translation>
@@ -3832,7 +3829,6 @@
 <translation id="630065524203833229">I&amp;šeiti</translation>
 <translation id="6304217058163308077">Nauja žymių programos sistema</translation>
 <translation id="6305012486838822927">Laosiečių klaviatūra</translation>
-<translation id="6305328361606238230">Gauti „Push“ pranešimus</translation>
 <translation id="6307722552931206656">„Google“ pavadinimo serveriai – <ph name="BEGIN_LINK" />sužinokite daugiau<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistema užimta</translation>
 <translation id="6308937455967653460">Išsaugoti nuorod&amp;ą kaip...</translation>
@@ -4530,7 +4526,6 @@
 <translation id="7339785458027436441">Rašant tikrinti rašybos klaidas</translation>
 <translation id="7339898014177206373">Naujas langas</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> dabar veikia viso ekrano režimu.</translation>
-<translation id="7341982465543599097">nepaprastai trumpa</translation>
 <translation id="734303607351427494">Valdyti paieškos variklius...</translation>
 <translation id="7343116142376328522">Neleisti jokiai svetainei naudoti rakto generavimo formose (rekomenduojama)</translation>
 <translation id="7345706641791090287">Patvirtinkite slaptažodį</translation>
@@ -4915,7 +4910,6 @@
 <translation id="7881969471599061635">Išjungti subtitrus</translation>
 <translation id="7884988936047469945">Eksperimentinės pritaikymo neįgaliesiems funkcijos</translation>
 <translation id="7885253890047913815">Naujausios paskirties vietos</translation>
-<translation id="7885283703487484916">labai trumpa</translation>
 <translation id="7887192723714330082">Įrenginys reaguos į komandą „Ok Google“, kai ekranas bus įjungtas ir atrakintas</translation>
 <translation id="7887334752153342268">Dubliuoti</translation>
 <translation id="7887864092952184874">„Bluetooth“ pelė susieta</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index d802424..0ca9b94d 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Dialoglodziņā “Pārlūkošanas datu notīrīšana” tiek rādīti datu apjoma skaitītāji.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Pierakstieties<ph name="END_SIGN_IN_LINK" />, lai pārvaldītu un skatītu vietnes, ko apmeklē šis lietotājs.</translation>
 <translation id="1097658378307015415">Pirms pierakstāties, uzsāciet viesa sesiju, lai aktivizētu tīklu <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">ilgi</translation>
 <translation id="1104652314727136854">Chrome lietotņu failu piesaiste tiek integrēta operētājsistēmā.</translation>
 <translation id="1105162038795579389">“<ph name="BUNDLE_NAME" />” pievienos šādas lietotnes un paplašinājumus lietotājam <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Apturēt</translation>
@@ -1874,7 +1873,6 @@
 <translation id="3512284449647229026">Lapas, kuras neizdosies ielādēt, kamēr pārlūks lietots bezsaistē, tiks automātiski atkārtoti ielādētas tikai tad, ja to cilne ir redzama.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Atcelt lejupielādi}zero{Atcelt lejupielādes}one{Atcelt lejupielādes}other{Atcelt lejupielādes}}</translation>
 <translation id="3512810056947640266">URL (neobligāti):</translation>
-<translation id="351486934407749662">ļoti ilgi</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> vēlas kopīgot jūsu ekrāna saturu. Izvēlieties kopīgojamo saturu.</translation>
 <translation id="3518086201899641494">Paziņojumi par caurlaides lapām</translation>
 <translation id="3519867315646775981">Transliterācija (shalom ← שלום)</translation>
@@ -3409,7 +3407,6 @@
 <translation id="569109051430110155">Automātiska noteikšana</translation>
 <translation id="5691596662111998220">Diemžēl fails <ph name="FILE_NAME" /> vairs nepastāv.</translation>
 <translation id="5694501201003948907">Notiek $1 vienumu tilpsaspiešana...</translation>
-<translation id="5695323626817702678">īss</translation>
 <translation id="5697118958262594262">Noteikt nozīmīgu saturu pēc noklusējuma</translation>
 <translation id="5699533844376998780">Paplašinājums <ph name="EXTENSION_NAME" /> ir pievienots.</translation>
 <translation id="5701101281789450335">Valodas un ievades iestatījumi...</translation>
@@ -3834,7 +3831,6 @@
 <translation id="630065524203833229">I&amp;ziet</translation>
 <translation id="6304217058163308077">Jaunā grāmatzīmju lietotņu sistēma</translation>
 <translation id="6305012486838822927">Laosiešu valodas tastatūra</translation>
-<translation id="6305328361606238230">Saņemt pašpiegādes ziņojumus</translation>
 <translation id="6307722552931206656">Google nosaukumu serveri: <ph name="BEGIN_LINK" />uzziniet vairāk<ph name="END_LINK" />.</translation>
 <translation id="6307990684951724544">Sistēma ir aizņemta.</translation>
 <translation id="6308937455967653460">Saglabāt saiti kā...</translation>
@@ -4531,7 +4527,6 @@
 <translation id="7339785458027436441">Pārbaudīt pareizrakstību rakstīšanas laikā</translation>
 <translation id="7339898014177206373">Jauns logs</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> tagad ir redzams pilnekrāna režīmā.</translation>
-<translation id="7341982465543599097">ārkārtīgi īss</translation>
 <translation id="734303607351427494">Pārvaldīt meklētājprogrammas...</translation>
 <translation id="7343116142376328522">Neatļaut izmantot atslēgu ģenerēšanu nevienas vietnes veidlapā (ieteicams)</translation>
 <translation id="7345706641791090287">Apstipriniet savu paroli</translation>
@@ -4916,7 +4911,6 @@
 <translation id="7881969471599061635">Atspējot subtitrus</translation>
 <translation id="7884988936047469945">Eksperimentālas pieejamības funkcijas</translation>
 <translation id="7885253890047913815">Nesenie printeri</translation>
-<translation id="7885283703487484916">ļoti īss</translation>
 <translation id="7887192723714330082">Reaģēt uz frāzi “Ok Google”, kad ekrāns ir ieslēgts un atbloķēts.</translation>
 <translation id="7887334752153342268">Izveidot dublikātu</translation>
 <translation id="7887864092952184874">Bluetooth pele ir savienota pārī.</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index f02acb68..afd9237 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">'ബ്രൗസിംഗ് ഡാറ്റ മായ്‌ക്കുക' ഡയലോഗിൽ ഡാറ്റ വോളിയം കൗണ്ടറുകൾ കാണിക്കുന്നു.</translation>
 <translation id="1097507499312291972">ഈ വ്യക്തി സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകൾ നിയന്ത്രിക്കാനും കാണാനും <ph name="BEGIN_SIGN_IN_LINK" />സൈൻ ഇൻ ചെയ്യുക<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">സൈൻ ഇൻ ചെയ്യുന്നതിന് മുമ്പ്, <ph name="NETWORK_ID" /> സജീവമാക്കാൻ അതിഥിയായി പ്രവേശിക്കുക</translation>
-<translation id="1104054824888299003">ദൈർഘ്യമേറിയത്</translation>
 <translation id="1104652314727136854">Chrome അപ്ലിക്കേഷനുകൾക്കായുള്ള ഫയൽ അസോസിയേഷനുകളുടെ OS സംയോജനം പ്രവർത്തനക്ഷമമാക്കുക.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />", <ph name="USER_NAME" /> എന്ന ഉപയോക്താവിനായി ഈ ആപ്‌സും വിപുലീകരണങ്ങളും ചേർക്കുന്നു:</translation>
 <translation id="1108600514891325577">&amp;നിറുത്തുക</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">ബ്രൗസർ ഓഫ്ലൈനിലായിരിക്കുമ്പോൾ ലോഡുചെയ്യാൻ പരാജയപ്പെടുന്ന പേജുകൾ അതിന്റെ ടാബ് ദൃശ്യമാകുമ്പോൾ മാത്രം സ്വയമേവ വീണ്ടും ലോഡുചെയ്യപ്പെടും.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ഡൗൺലോഡ് റദ്ദാക്കുക}other{ഡൗൺലോഡുകൾ റദ്ദാക്കുക}}</translation>
 <translation id="3512810056947640266">URL (ഓപ്‌ഷണൽ):</translation>
-<translation id="351486934407749662">വളരെ ദൈർഘ്യമുള്ളത്</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> നിങ്ങളുടെ സ്ക്രീനിലെ ഉള്ളടക്കം പങ്കിടാൻ താൽപ്പര്യപ്പെടുന്നു. പങ്കിടാൻ താൽപ്പര്യപ്പെടുന്നത് തിരഞ്ഞെടുക്കുക.</translation>
 <translation id="3518086201899641494">ക്യാപ്‌റ്റീവ് പോർട്ടലുകളെക്കുറിച്ചുള്ള അറിയിപ്പുകൾ</translation>
 <translation id="3519867315646775981">ലിപ്യന്തരണം (shalom ← שלום)</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">സ്വപ്രേരിത കണ്ടുപിടിക്കല്‍</translation>
 <translation id="5691596662111998220">ക്ഷമിക്കണം, <ph name="FILE_NAME" /> നിലവിലില്ല.</translation>
 <translation id="5694501201003948907">$1 ഇനങ്ങൾ zip ചെയ്യുന്നു...</translation>
-<translation id="5695323626817702678">ഹ്രസ്വം</translation>
 <translation id="5697118958262594262">സ്ഥിരമായുള്ള പ്രധാനപ്പെട്ട ഉള്ളടക്കം കണ്ടെത്തുക</translation>
 <translation id="5699533844376998780">വിപുലീകരണം "<ph name="EXTENSION_NAME" />" ചേർത്തു.</translation>
 <translation id="5701101281789450335">ഭാഷ, ഇൻപുട്ട് ക്രമീകരണങ്ങൾ...</translation>
@@ -3830,7 +3827,6 @@
 <translation id="630065524203833229">&amp;പുറത്തുപോകുക</translation>
 <translation id="6304217058163308077">പുതിയ ബുക്ക്‌മാർക്ക് ആപ്പ് സിസ്‌റ്റം</translation>
 <translation id="6305012486838822927">ലാവോ കീബോർഡ്</translation>
-<translation id="6305328361606238230">പുഷ് സന്ദേശങ്ങൾ സ്വീകരിക്കുക</translation>
 <translation id="6307722552931206656">Google നെയിം സെർവറുകൾ - <ph name="BEGIN_LINK" />കൂടുതലറിയുക<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">സിസ്റ്റം തിരക്കിലാണ്</translation>
 <translation id="6308937455967653460">ലിങ്ക് ഇതുപോലെ&amp; സംരക്ഷിക്കുക...</translation>
@@ -4527,7 +4523,6 @@
 <translation id="7339785458027436441">ടൈപ്പ് ചെയ്യുന്ന സമയത്ത് സ്‌പെല്ലിംഗ് പരിശോധിക്കുക</translation>
 <translation id="7339898014177206373">പുതിയ വിന്‍ഡോ</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> ഇപ്പോൾ പൂർണ്ണ സ്‌ക്രീനിലാണ്.</translation>
-<translation id="7341982465543599097">തീരെ ചെറുത്</translation>
 <translation id="734303607351427494">തിരയൽ എഞ്ചിനുകള്‍ കൈകാര്യം ചെയ്യുക...</translation>
 <translation id="7343116142376328522">ഫോമുകളിൽ കീ സൃഷ്‌ടിക്കൽ ഉപയോഗിക്കാൻ ഒരു സൈറ്റിനെയും അനുവദിക്കരുത് (ശുപാർശചെയ്യുന്നത്)</translation>
 <translation id="7345706641791090287">പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക</translation>
@@ -4912,7 +4907,6 @@
 <translation id="7881969471599061635">സബ്‌ടൈറ്റിലുകൾ പ്രവർത്തനരഹിതമാക്കുക</translation>
 <translation id="7884988936047469945">പരീക്ഷണാത്മക ആക്‌സസിബിലിറ്റി ഫീച്ചറുകൾ</translation>
 <translation id="7885253890047913815">സമീപകാല ലക്ഷ്യസ്ഥാനങ്ങൾ</translation>
-<translation id="7885283703487484916">വളരെ ഹ്രസ്വമായത്</translation>
 <translation id="7887192723714330082">സ്‌ക്രീൻ ഓണായിരിക്കുമ്പോഴും അൺലോക്കായിരിക്കുമ്പോഴും "Ok Google" നോട് പ്രതികരിക്കുക</translation>
 <translation id="7887334752153342268">തനിപ്പകര്‍പ്പ്</translation>
 <translation id="7887864092952184874">Bluetooth മൗസ് ജോടിയാക്കി</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 9bcba72..75af920b 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">ब्राउझ केलेला डेटा साफ करा संवादामधील डेटा व्हॉल्यूम काउंटर दर्शविते.</translation>
 <translation id="1097507499312291972">ही व्यक्ती भेट देते त्या वेबसाइट नियंत्रित करण्यासाठी आणि पाहण्यासाठी <ph name="BEGIN_SIGN_IN_LINK" />साइन इन करा<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">साइन इन करण्‍यापूर्वी, <ph name="NETWORK_ID" /> नेटवर्क सक्रिय करण्‍यासाठी कृपया अतिथी म्हणून प्रवेश करा.</translation>
-<translation id="1104054824888299003">दीर्घ</translation>
 <translation id="1104652314727136854">Chrome Apps साठी फाईल संबद्धतांचे OS संकलन सक्षम करा.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" हे अ‍ॅप्‍स आणि विस्तार या <ph name="USER_NAME" /> साठी जोडते:</translation>
 <translation id="1108600514891325577">&amp;थांबा</translation>
@@ -1866,7 +1865,6 @@
 <translation id="3512284449647229026">ब्राउझर ऑफलाइन असताना लोड होण्यात अयशस्वी होणारी पृष्ठे त्यांचा टॅब दृश्यमान असतो तेव्हाच स्वयं-रीलोड केली जातील.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{डाउनलोड रद्द करा}one{डाउनलोड रद्द करा}other{डाउनलोड रद्द करा}}</translation>
 <translation id="3512810056947640266">URL (पर्यायी):</translation>
-<translation id="351486934407749662">खूप लांब</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> आपल्या स्क्रीनची सामग्री सामायिक करू इच्छित आहे. आपण काय सामायिक करू इच्छिता हे निवडा.</translation>
 <translation id="3518086201899641494">कॅप्टिव्ह पोर्टलविषयी सूचना</translation>
 <translation id="3519867315646775981">लिप्यंतरण (shalom ← שלום)</translation>
@@ -3400,7 +3398,6 @@
 <translation id="569109051430110155">स्वयं तपासणी</translation>
 <translation id="5691596662111998220">अरेरे, <ph name="FILE_NAME" /> यापुढे अस्तित्वात नाही.</translation>
 <translation id="5694501201003948907">$1 आयटम झिप करत आहे...</translation>
-<translation id="5695323626817702678">लहान</translation>
 <translation id="5697118958262594262">डीफॉल्‍टनुसार महत्त्वाची सामग्री शोधा</translation>
 <translation id="5699533844376998780">विस्तार "<ph name="EXTENSION_NAME" />" जोडला गेला आहे.</translation>
 <translation id="5701101281789450335">भाषा आणि इनपुट सेटिंग्ज...</translation>
@@ -3823,7 +3820,6 @@
 <translation id="630065524203833229">नि&amp;र्गमन</translation>
 <translation id="6304217058163308077">नवीन बुकमार्क अॅप सिस्टीम</translation>
 <translation id="6305012486838822927">लाओ कीबोर्ड</translation>
-<translation id="6305328361606238230">पुश संदेश प्राप्त करा</translation>
 <translation id="6307722552931206656">Google नाव सर्व्हर - <ph name="BEGIN_LINK" />अधिक जाणून घ्या<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">सिस्‍टीम व्यस्त</translation>
 <translation id="6308937455967653460">म्हणून दु&amp;वा जतन करा...</translation>
@@ -4518,7 +4514,6 @@
 <translation id="7339785458027436441">टाइप करताना शब्दलेखन तपासा</translation>
 <translation id="7339898014177206373">नवीन विंडो</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> आता फुल स्क्रीन आहे.</translation>
-<translation id="7341982465543599097">अत्यंत लहान</translation>
 <translation id="734303607351427494">शोध इंजिन व्यवस्थापित करा...</translation>
 <translation id="7343116142376328522">कोणत्याही साइटला फॉर्ममध्ये की निर्मिती वापरण्याची अनुमती देऊ नका (शिफारस केलेले)</translation>
 <translation id="7345706641791090287">आपल्या संकेतशब्दाची पुष्टी करा</translation>
@@ -4902,7 +4897,6 @@
 <translation id="7881969471599061635">उपशीर्षके अक्षम करा</translation>
 <translation id="7884988936047469945">प्रायोगिक प्रवेशक्षमता वैशिष्ट्ये</translation>
 <translation id="7885253890047913815">अलीकडील गंतव्ये</translation>
-<translation id="7885283703487484916">अल्प</translation>
 <translation id="7887192723714330082">स्क्रीन चालू आणि अनलॉक असते तेव्हा "Ok Google" ला प्रतिसाद द्या</translation>
 <translation id="7887334752153342268">डुप्लिकेट</translation>
 <translation id="7887864092952184874">Bluetooth माउस जोडला</translation>
@@ -5072,7 +5066,7 @@
 <translation id="81238879832906896">पिवळे आणि पांढरे फूल</translation>
 <translation id="8124313775439841391">व्यवस्‍थापित ONC</translation>
 <translation id="8126844665673008223">वेब Bluetooth</translation>
-<translation id="8127181497803323361">दस्तऐवज पातळी लक्ष्यांवरील (अन्यथा ज्यांनी विनंती केली नसते) स्पर्शप्रारंभ आणि स्पर्शहलविणे इव्हेंट ऐकणार्‍यांना निष्क्रिय म्हणून हाताळण्यासाठी सक्ती करते.</translation>
+<translation id="8127181497803323361">दस्तऐवज पातळी लक्ष्यांवरील (अन्यथा ज्यांनी विनंती केली नसते) स्पर्श करून प्रारंभ करणारे आणि स्पर्श करून हलवणारे इव्हेंट ऐकणार्‍यांना निष्क्रिय म्हणून हाताळण्यासाठी सक्ती करते.</translation>
 <translation id="8127322077195964840">स्थानिकहोस्टवरून लोड केलेल्या संसाधनांसाठी अवैध प्रमाणपत्रांना अनुमती द्या.</translation>
 <translation id="8129262335948759431">अज्ञात प्रमाण</translation>
 <translation id="8130269545914251658">टॅब ऑडिओ नि:शब्द करणे UI नियंत्रण</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index 3cc60858..9bb75d5 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Menunjukkan pembilang jumlah data dalam dialog Kosongkan data semakan imbas.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Log masuk<ph name="END_SIGN_IN_LINK" /> untuk mengawal dan melihat laman web yang dilawati oleh orang ini.</translation>
 <translation id="1097658378307015415">Sebelum log masuk, sila masuk sebagai Tetamu untuk mengaktifkan rangkaian <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">lama</translation>
 <translation id="1104652314727136854">Dayakan integrasi OS untuk penyatuan fail bagi Apl Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" menambahkan apl dan sambungan ini untuk <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Berhenti</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">Halaman yang gagal dimuatkan semasa penyemak imbas di luar talian akan dimuatkan semula secara automatik jika tabnya boleh dilihat.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Batalkan Muat Turun}other{Batalkan Muat Turun}}</translation>
 <translation id="3512810056947640266">URL (pilihan):</translation>
-<translation id="351486934407749662">sangat lama</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> ingin berkongsi kandungan skrin anda. Pilih apa yang anda ingin kongsi.</translation>
 <translation id="3518086201899641494">Pemberitahuan mengenai portal tawanan</translation>
 <translation id="3519867315646775981">Pengalihan huruf (shalom ← שלום)</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">Auto kesan</translation>
 <translation id="5691596662111998220">Op, <ph name="FILE_NAME" /> tidak lagi wujud.</translation>
 <translation id="5694501201003948907">Mengezip $1 item...</translation>
-<translation id="5695323626817702678">pendek</translation>
 <translation id="5697118958262594262">Kesan kandungan penting secara lalai</translation>
 <translation id="5699533844376998780">Sambungan "<ph name="EXTENSION_NAME" />" telah ditambah.</translation>
 <translation id="5701101281789450335">Tetapan bahasa dan input...</translation>
@@ -3828,7 +3825,6 @@
 <translation id="630065524203833229">K&amp;eluar</translation>
 <translation id="6304217058163308077">Sistem apl penanda halaman baharu</translation>
 <translation id="6305012486838822927">Papan kekunci bahasa Lao</translation>
-<translation id="6305328361606238230">Terima mesej tolak</translation>
 <translation id="6307722552931206656">Nama pelayan Google - <ph name="BEGIN_LINK" />Ketahui lebih lanjut<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistem sibuk</translation>
 <translation id="6308937455967653460">Simpan pau&amp;tan sebagai...</translation>
@@ -4522,7 +4518,6 @@
 <translation id="7339785458027436441">Semak Ejaan Semasa Menaip</translation>
 <translation id="7339898014177206373">Tetingkap baharu</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> kini dalam skrin penuh.</translation>
-<translation id="7341982465543599097">sangat pendek</translation>
 <translation id="734303607351427494">Uruskan enjin carian...</translation>
 <translation id="7343116142376328522">Jangan benarkan mana-mana tapak menggunakan penghasilan kunci dalam borang (disyorkan)</translation>
 <translation id="7345706641791090287">Sahkan kata laluan anda</translation>
@@ -4906,7 +4901,6 @@
 <translation id="7881969471599061635">Lumpuhkan sari kata</translation>
 <translation id="7884988936047469945">Ciri kebolehaksesan percubaan</translation>
 <translation id="7885253890047913815">Destinasi Baru-baru Ini</translation>
-<translation id="7885283703487484916">sangat pendek</translation>
 <translation id="7887192723714330082">Beri respon kepada "Ok Google" apabila skrin dihidupkan dan dikunci</translation>
 <translation id="7887334752153342268">Pendua</translation>
 <translation id="7887864092952184874">Tetikus Bluetooth digandingkan</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index fa50ab5..85335e5 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Hiermee worden teller voor het gegevensvolume weergegeven in het dialoogvenster 'Browsegegevens wissen'.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Log in<ph name="END_SIGN_IN_LINK" /> om de websites die deze persoon bezoekt te beheren en te bekijken.</translation>
 <translation id="1097658378307015415">Voordat je inlogt, log je eerst in als gast om het netwerk <ph name="NETWORK_ID" /> te activeren.</translation>
-<translation id="1104054824888299003">lang</translation>
 <translation id="1104652314727136854">Integratie van bestandskoppelingen met besturingssysteem inschakelen voor Chrome-apps.</translation>
 <translation id="1105162038795579389">Met '<ph name="BUNDLE_NAME" />' worden deze apps en extensies voor <ph name="USER_NAME" /> toegevoegd:</translation>
 <translation id="1108600514891325577">&amp;Stop</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Pagina's die niet kunnen worden geladen wanneer de browser offline is, worden alleen automatisch opnieuw geladen wanneer het betreffende tabblad zichtbaar is.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Download annuleren}other{Downloads annuleren}}</translation>
 <translation id="3512810056947640266">URL (optioneel):</translation>
-<translation id="351486934407749662">zeer lang</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> wil de inhoud op je scherm delen. Kies wat je wilt delen.</translation>
 <translation id="3518086201899641494">Meldingen over captive portals</translation>
 <translation id="3519867315646775981">Transliteratie (shalom ← שלום)</translation>
@@ -3406,7 +3404,6 @@
 <translation id="569109051430110155">Automatisch detecteren</translation>
 <translation id="5691596662111998220"><ph name="FILE_NAME" /> bestaat niet meer.</translation>
 <translation id="5694501201003948907">$1 items inpakken...</translation>
-<translation id="5695323626817702678">kort</translation>
 <translation id="5697118958262594262">Belangrijke inhoud standaard detecteren</translation>
 <translation id="5699533844376998780">De extensie '<ph name="EXTENSION_NAME" />' is toegevoegd.</translation>
 <translation id="5701101281789450335">Taal- en invoerinstellingen...</translation>
@@ -3831,7 +3828,6 @@
 <translation id="630065524203833229">&amp;Sluiten</translation>
 <translation id="6304217058163308077">Het nieuwe systeem voor bladwijzer-apps</translation>
 <translation id="6305012486838822927">Laotiaans toetsenbord</translation>
-<translation id="6305328361606238230">Pushberichten ontvangen</translation>
 <translation id="6307722552931206656">Google-naamservers - <ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Systeem is bezet</translation>
 <translation id="6308937455967653460">Lin&amp;k opslaan als...</translation>
@@ -4528,7 +4524,6 @@
 <translation id="7339785458027436441">Controleer spelling tijdens typen</translation>
 <translation id="7339898014177206373">Nieuw venster</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> wordt nu op volledig scherm weergegeven.</translation>
-<translation id="7341982465543599097">extreem kort</translation>
 <translation id="734303607351427494">Zoekmachines beheren...</translation>
 <translation id="7343116142376328522">Sites niet toestaan de functie voor het genereren van sleutels te gebruiken in formulieren (aanbevolen)</translation>
 <translation id="7345706641791090287">Je wachtwoord bevestigen</translation>
@@ -4913,7 +4908,6 @@
 <translation id="7881969471599061635">Ondertiteling uitschakelen</translation>
 <translation id="7884988936047469945">Experimentele toegankelijkheidsfuncties</translation>
 <translation id="7885253890047913815">Recente bestemmingen</translation>
-<translation id="7885283703487484916">zeer kort</translation>
 <translation id="7887192723714330082">Reageren op "Ok Google" wanneer het scherm is ingeschakeld en ontgrendeld</translation>
 <translation id="7887334752153342268">Dupliceren</translation>
 <translation id="7887864092952184874">Bluetooth-muis gekoppeld</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index 641489a..7c12b8b 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Viser tellere for datavolum i dialogboksen Slett nettleserdata.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Logg på<ph name="END_SIGN_IN_LINK" /> for å kontrollere og se nettstedene denne personen besøker.</translation>
 <translation id="1097658378307015415">Gå inn som gjest for å aktivere nettverket <ph name="NETWORK_ID" /> før du logger deg på.</translation>
-<translation id="1104054824888299003">lang</translation>
 <translation id="1104652314727136854">Aktiver OS-integrering av filtilknytninger for Chrome-apper.</translation>
 <translation id="1105162038795579389">«<ph name="BUNDLE_NAME" />» legger til disse appene og utvidelsene for <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Stopp</translation>
@@ -1866,7 +1865,6 @@
 <translation id="3512284449647229026">Sider som ikke lastes inn mens nettleseren er koblet fra nettet, blir bare lastet inn på nytt automatisk hvis fanene for sidene er synlige.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Avbryt nedlastingen}other{Avbryt nedlastingene}}</translation>
 <translation id="3512810056947640266">Nettadresse (valgfritt):</translation>
-<translation id="351486934407749662">veldig lang</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> ønsker å dele innholdet på skjermen din. Velg hva du ønsker å dele.</translation>
 <translation id="3518086201899641494">Varsler om autentiseringsportal</translation>
 <translation id="3519867315646775981">Translitterasjon (shalom ← שלום)</translation>
@@ -3395,7 +3393,6 @@
 <translation id="569109051430110155">Oppdag automatisk</translation>
 <translation id="5691596662111998220">Beklager, <ph name="FILE_NAME" /> eksisterer ikke lenger.</translation>
 <translation id="5694501201003948907">Zipper $1 elementer ...</translation>
-<translation id="5695323626817702678">kort</translation>
 <translation id="5697118958262594262">Oppdag viktig innhold som standard</translation>
 <translation id="5699533844376998780">Utvidelsen «<ph name="EXTENSION_NAME" />» har blitt lagt til.</translation>
 <translation id="5701101281789450335">Språk- og inndatainnstillinger</translation>
@@ -3818,7 +3815,6 @@
 <translation id="630065524203833229">&amp;Avslutt</translation>
 <translation id="6304217058163308077">Det nye systemet for bokmerkeapper</translation>
 <translation id="6305012486838822927">Lao-tastatur</translation>
-<translation id="6305328361606238230">Motta pushmeldinger</translation>
 <translation id="6307722552931206656">Google-navnetjenere – <ph name="BEGIN_LINK" />Les mer<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Systemet er opptatt</translation>
 <translation id="6308937455967653460">Lagre lin&amp;ken som…</translation>
@@ -4512,7 +4508,6 @@
 <translation id="7339785458027436441">Kontroller staving mens du skriver</translation>
 <translation id="7339898014177206373">Nytt vindu</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> kjører nå i full skjerm.</translation>
-<translation id="7341982465543599097">ekstremt kort</translation>
 <translation id="734303607351427494">Administrer søkemotorer</translation>
 <translation id="7343116142376328522">Ikke gi noen nettsteder tillatelse til å bruke nøkkelgenerering i skjemaer (anbefales)</translation>
 <translation id="7345706641791090287">Bekreft passordet</translation>
@@ -4889,7 +4884,6 @@
 <translation id="7881969471599061635">Slå av undertekstene</translation>
 <translation id="7884988936047469945">Eksperimentelle tilgjengelighetsfunksjoner</translation>
 <translation id="7885253890047913815">Nylige destinasjoner</translation>
-<translation id="7885283703487484916">meget kort</translation>
 <translation id="7887192723714330082">Svar «Ok Google» når skjermen er på og ulåst</translation>
 <translation id="7887334752153342268">Dupliser</translation>
 <translation id="7887864092952184874">En Bluetooth-mus er tilkoblet</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index 7d30786a..0bc8ff9 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Pokazuje liczniki ilości danych w oknie dialogowym Wyczyść dane przeglądarki.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Zaloguj się<ph name="END_SIGN_IN_LINK" />, by kontrolować i wyświetlać strony, na które wchodzi ta osoba.</translation>
 <translation id="1097658378307015415">Zanim się zalogujesz, wybierz tryb gościa, aby aktywować sieć <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">długie</translation>
 <translation id="1104652314727136854">Integruje powiązania plików aplikacji Chrome z systemem operacyjnym.</translation>
 <translation id="1105162038795579389">„<ph name="BUNDLE_NAME" />” doda te aplikacje i rozszerzenia do konta użytkownika <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Zatrzymaj</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Strony, których nie uda się załadować, gdy przeglądarka jest offline, zostaną odświeżone automatycznie tylko po wyświetleniu ich kart.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Anuluj pobieranie}few{Anuluj pobieranie}many{Anuluj pobieranie}other{Anuluj pobieranie}}</translation>
 <translation id="3512810056947640266">Adres URL (opcjonalnie):</translation>
-<translation id="351486934407749662">bardzo długie</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> chce udostępnić zawartość Twojego ekranu. Wybierz elementy, które chcesz udostępnić.</translation>
 <translation id="3518086201899641494">Powiadomienia o portalach przechwytujących</translation>
 <translation id="3519867315646775981">Transliteracja (shalom ← שלום)</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">Wykrywaj automatycznie</translation>
 <translation id="5691596662111998220">Ups, pliku <ph name="FILE_NAME" /> już nie ma.</translation>
 <translation id="5694501201003948907">Pakuję $1 elementy(ów)...</translation>
-<translation id="5695323626817702678">krótkie</translation>
 <translation id="5697118958262594262">Domyślnie wykrywaj ważną treść</translation>
 <translation id="5699533844376998780">Rozszerzenie „<ph name="EXTENSION_NAME" />” zostało dodane.</translation>
 <translation id="5701101281789450335">Ustawienia języka i wprowadzania treści...</translation>
@@ -3828,7 +3825,6 @@
 <translation id="630065524203833229">Z&amp;akończ</translation>
 <translation id="6304217058163308077">Nowy system aplikacji do obsługi zakładek</translation>
 <translation id="6305012486838822927">Klawiatura laotańska</translation>
-<translation id="6305328361606238230">Otrzymywanie komunikatów push</translation>
 <translation id="6307722552931206656">Serwery nazw Google – <ph name="BEGIN_LINK" />więcej informacji<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">System zajęty</translation>
 <translation id="6308937455967653460">Zapisz link ja&amp;ko...</translation>
@@ -4148,7 +4144,7 @@
 <translation id="6787839852456839824">Skróty klawiaturowe</translation>
 <translation id="6788210894632713004">Rozszerzenie bez pakietu</translation>
 <translation id="6790428901817661496">Odtwórz</translation>
-<translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> dodano zdalnie</translation>
+<translation id="6790497603648687708">Dodano zdalnie: <ph name="EXTENSION_NAME" /></translation>
 <translation id="6790820461102226165">Dodaj osobę...</translation>
 <translation id="6791443592650989371">Stan aktywacji:</translation>
 <translation id="6793604637258913070">Podświetlaj kursor tekstu, gdy się wyświetla lub porusza.</translation>
@@ -4521,7 +4517,6 @@
 <translation id="7339785458027436441">Sprawdzaj pisownię w trakcie pisania</translation>
 <translation id="7339898014177206373">Nowe okno</translation>
 <translation id="7340431621085453413">Strona <ph name="FULLSCREEN_ORIGIN" /> jest teraz wyświetlana w trybie pełnoekranowym.</translation>
-<translation id="7341982465543599097">bardzo krótkie</translation>
 <translation id="734303607351427494">Zarządzaj wyszukiwarkami...</translation>
 <translation id="7343116142376328522">Nie zezwalaj żadnej stronie na generowanie kluczy w formularzach (zalecane)</translation>
 <translation id="7345706641791090287">Potwierdź hasło</translation>
@@ -4899,7 +4894,6 @@
 <translation id="7881969471599061635">Wyłącz napisy</translation>
 <translation id="7884988936047469945">Eksperymentalne ułatwienia dostępu</translation>
 <translation id="7885253890047913815">Ostatnie urządzenia docelowe</translation>
-<translation id="7885283703487484916">bardzo krótkie</translation>
 <translation id="7887192723714330082">Reaguje na „Ok Google”, gdy ekran jest włączony i odblokowany</translation>
 <translation id="7887334752153342268">Duplikuj</translation>
 <translation id="7887864092952184874">Sparowano mysz Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index 53561cee..c8bc224 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Mostra os contadores de volume de dados na caixa de diálogo "Limpar dados de navegação".</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Faça login<ph name="END_SIGN_IN_LINK" /> para controlar e ver os websites que essa pessoa visita.</translation>
 <translation id="1097658378307015415">Antes de fazer login, entre como Visitante para ativar a rede <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">longo</translation>
 <translation id="1104652314727136854">Permite a integração no sistema operacional das associações de arquivos para aplicativos do Google Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" adiciona estes aplicativos e extensões para <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Parar</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Páginas que não podem ser carregadas enquanto o navegador está off-line são atualizadas automaticamente apenas se sua guia está visível.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Cancelar download}one{Cancelar downloads}other{Cancelar downloads}}</translation>
 <translation id="3512810056947640266">URL (opcional):</translation>
-<translation id="351486934407749662">muito longo</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> quer compartilhar o conteúdo da sua tela. Escolha o que você gostaria de compartilhar.</translation>
 <translation id="3518086201899641494">Notificações sobre portais cativos</translation>
 <translation id="3519867315646775981">Transliteração (shalom ← שלום)</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">Detecção automática</translation>
 <translation id="5691596662111998220">O item <ph name="FILE_NAME" /> não existe mais.</translation>
 <translation id="5694501201003948907">Compactando $1 itens...</translation>
-<translation id="5695323626817702678">curto</translation>
 <translation id="5697118958262594262">Detectar conteúdo importante por padrão</translation>
 <translation id="5699533844376998780">A extensão "<ph name="EXTENSION_NAME" />" foi adicionada.</translation>
 <translation id="5701101281789450335">Configurações de idioma e de entrada...</translation>
@@ -3829,7 +3826,6 @@
 <translation id="630065524203833229">&amp;Sair</translation>
 <translation id="6304217058163308077">O novo sistema de app de favoritos</translation>
 <translation id="6305012486838822927">Teclado em laosiano</translation>
-<translation id="6305328361606238230">Receber mensagens push</translation>
 <translation id="6307722552931206656">Servidores de nome do Google: <ph name="BEGIN_LINK" />Saiba mais<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistema ocupado</translation>
 <translation id="6308937455967653460">Salvar &amp;link como...</translation>
@@ -3992,7 +3988,7 @@
 <translation id="6534583978616527129">Inicializar a conexão</translation>
 <translation id="654039047105555694"><ph name="BEGIN_BOLD" />Observação:<ph name="END_BOLD" /> Ative somente se você souber o que está fazendo ou tiver sido solicitado(a) a fazê-lo, porque a coleta de dados pode reduzir o desempenho.</translation>
 <translation id="654233263479157500">Utilizar um serviço da web para ajudar a solucionar erros de navegação</translation>
-<translation id="6545834809683560467">se o serviço de previsão para ajudar a completar pesquisas e URLs digitados na barra de endereço ou na caixa de pesquisa do Acesso rápido aos apps</translation>
+<translation id="6545834809683560467">Utilizar o serviço de previsão para ajudar a completar pesquisas e URLs digitados na barra de endereço ou na caixa de pesquisa do Acesso rápido aos apps</translation>
 <translation id="6546686722964485737">Entrar para a rede WiMAX</translation>
 <translation id="6547316139431024316">Não avisar novamente para esta extensão</translation>
 <translation id="6547354035488017500">Libere pelo menos 512 MB de espaço. Caso contrário, seu dispositivo deixará de responder. Para liberar espaço, exclua arquivos do armazenamento do dispositivo.</translation>
@@ -4524,7 +4520,6 @@
 <translation id="7339785458027436441">Verificar ortografia ao digitar</translation>
 <translation id="7339898014177206373">Nova janela</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> está agora no modo de tela inteira.</translation>
-<translation id="7341982465543599097">extremamente curto</translation>
 <translation id="734303607351427494">Gerenciar mecanismos de pesquisa...</translation>
 <translation id="7343116142376328522">Não permitir que nenhum site use a geração de chaves em formulários (recomendado)</translation>
 <translation id="7345706641791090287">Confirmar sua senha</translation>
@@ -4910,7 +4905,6 @@
 <translation id="7881969471599061635">Desativar legendas</translation>
 <translation id="7884988936047469945">Recursos de acessibilidade experimentais</translation>
 <translation id="7885253890047913815">Destinos recentes</translation>
-<translation id="7885283703487484916">muito curto</translation>
 <translation id="7887192723714330082">Responder a "Ok Google" quando a tela estiver ligada e desbloqueada</translation>
 <translation id="7887334752153342268">Duplicar</translation>
 <translation id="7887864092952184874">Mouse Bluetooth pareado</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index 62207d0..a79a4dc3 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Mostra contadores de volume de dados na caixa de diálogo Limpar dados de navegação.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Inicie sessão<ph name="END_SIGN_IN_LINK" /> para controlar e visualizar os Websites que esta pessoa visita.</translation>
 <translation id="1097658378307015415">Antes de iniciar sessão, entre como Convidado para ativar a rede <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">longo</translation>
 <translation id="1104652314727136854">Permitir integração de SO de associações de ficheiros para Aplicações Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" adiciona estas aplicações e extensões para <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Parar</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">As páginas que não são carregadas enquanto o navegador está offline apenas serão atualizadas automaticamente se o respetivo separador estiver visível.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Cancelar transferência}other{Cancelar transferências}}</translation>
 <translation id="3512810056947640266">URL (opcional):</translation>
-<translation id="351486934407749662">muito longo</translation>
 <translation id="3517839692979918726">O <ph name="APP_NAME" /> pretende partilhar o conteúdo do seu ecrã. Escolha o que pretende partilhar.</translation>
 <translation id="3518086201899641494">Notificações acerca de portais cativos</translation>
 <translation id="3519867315646775981">Transliteração (shalom ← שלום)</translation>
@@ -3408,7 +3406,6 @@
 <translation id="569109051430110155">Detectar automaticamente</translation>
 <translation id="5691596662111998220">Ups, <ph name="FILE_NAME" /> já não existe.</translation>
 <translation id="5694501201003948907">A criar zip de $1 itens...</translation>
-<translation id="5695323626817702678">curto</translation>
 <translation id="5697118958262594262">Detetar conteúdo importante por predefinição</translation>
 <translation id="5699533844376998780">A extensão "<ph name="EXTENSION_NAME" />" foi adicionada.</translation>
 <translation id="5701101281789450335">Definições de idioma e de introdução...</translation>
@@ -3831,7 +3828,6 @@
 <translation id="630065524203833229">&amp;Sair</translation>
 <translation id="6304217058163308077">O novo sistema de aplicação de marcador</translation>
 <translation id="6305012486838822927">Teclado laosiano</translation>
-<translation id="6305328361606238230">Receber mensagens push</translation>
 <translation id="6307722552931206656">Servidores de nome Google – <ph name="BEGIN_LINK" />Saiba mais<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistema ocupado</translation>
 <translation id="6308937455967653460">Guardar lin&amp;k como...</translation>
@@ -4525,7 +4521,6 @@
 <translation id="7339785458027436441">Verificar a ortografia durante a escrita</translation>
 <translation id="7339898014177206373">Nova janela</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> está agora em ecrã inteiro.</translation>
-<translation id="7341982465543599097">extremamente curto</translation>
 <translation id="734303607351427494">Gerir motores de pesquisa...</translation>
 <translation id="7343116142376328522">Não permitir que nenhum site utilize a geração de chaves em formulários (recomendado)</translation>
 <translation id="7345706641791090287">Confirmar a palavra-passe</translation>
@@ -4910,7 +4905,6 @@
 <translation id="7881969471599061635">Desativar legendas</translation>
 <translation id="7884988936047469945">Funcionalidades de acessibilidade experimentais</translation>
 <translation id="7885253890047913815">Destinos recentes</translation>
-<translation id="7885283703487484916">muito curto</translation>
 <translation id="7887192723714330082">Responder a "Ok Google" quando o ecrã está ligado e desbloqueado</translation>
 <translation id="7887334752153342268">Duplicar</translation>
 <translation id="7887864092952184874">Rato Bluetooth sincronizado</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 1b75b1b2..5eef098 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Afișează contoarele pentru volumul de date în caseta de dialog Șterge datele de navigare.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Conectează-te<ph name="END_SIGN_IN_LINK" /> pentru a controla și a vedea site-urile accesate de această persoană.</translation>
 <translation id="1097658378307015415">Înainte de a vă conecta, începeți o sesiune pentru invitați pentru activarea rețelei <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">lungă</translation>
 <translation id="1104652314727136854">Activați integrarea cu sistemul de operare pentru asocierile de fișiere pentru aplicațiile Chrome.</translation>
 <translation id="1105162038795579389">„<ph name="BUNDLE_NAME" />” adaugă aceste aplicații și extensii pentru <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Oprește</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">Paginile care nu se încarcă când browserul este offline se vor reîncărca automat numai dacă fila acestora este vizibilă.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Anulează descărcarea}few{Anulează descărcările}other{Anulează descărcările}}</translation>
 <translation id="3512810056947640266">Adresă URL (opțională):</translation>
-<translation id="351486934407749662">foarte lungă</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> dorește să trimită conținut de pe ecran. Alegeți ce doriți să trimiteți.</translation>
 <translation id="3518086201899641494">Notificări despre portaluri captive</translation>
 <translation id="3519867315646775981">Transliterație (shalom ← שלום)</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">Detectare automată</translation>
 <translation id="5691596662111998220">Hopa, <ph name="FILE_NAME" /> nu mai există.</translation>
 <translation id="5694501201003948907">Se arhivează $1 elemente...</translation>
-<translation id="5695323626817702678">scurtă</translation>
 <translation id="5697118958262594262">Detectează conținutul important în mod prestabilit</translation>
 <translation id="5699533844376998780">Extensia „<ph name="EXTENSION_NAME" />” a fost adăugată.</translation>
 <translation id="5701101281789450335">Setări pentru limbă și introducerea textului...</translation>
@@ -3828,7 +3825,6 @@
 <translation id="630065524203833229">&amp;Ieși</translation>
 <translation id="6304217058163308077">Noul sistem pentru aplicațiile marcaj</translation>
 <translation id="6305012486838822927">Tastatură laoțiană</translation>
-<translation id="6305328361606238230">Primești mesaje push?</translation>
 <translation id="6307722552931206656">Servere de nume Google – <ph name="BEGIN_LINK" />Aflați mai multe<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistem ocupat</translation>
 <translation id="6308937455967653460">Salvează lin&amp;kul ca...</translation>
@@ -4522,7 +4518,6 @@
 <translation id="7339785458027436441">Verifică ortografia pe măsură ce se introduce text</translation>
 <translation id="7339898014177206373">Fereastră nouă</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> este acum pe ecran complet.</translation>
-<translation id="7341982465543599097">extrem de scurtă</translation>
 <translation id="734303607351427494">Gestionează motoarele de căutare...</translation>
 <translation id="7343116142376328522">Nu permite niciunui site să folosească generarea cheilor în formulare (recomandat)</translation>
 <translation id="7345706641791090287">Confirmă parola</translation>
@@ -4907,7 +4902,6 @@
 <translation id="7881969471599061635">Dezactivează subtitrările</translation>
 <translation id="7884988936047469945">Funcții experimentale de accesibilitate</translation>
 <translation id="7885253890047913815">Destinații recente</translation>
-<translation id="7885283703487484916">foarte scurtă</translation>
 <translation id="7887192723714330082">Răspunde la „Ok Google” dacă ecranul este pornit și deblocat</translation>
 <translation id="7887334752153342268">Dublură</translation>
 <translation id="7887864092952184874">Mouse Bluetooth conectat</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index f9dd006..2f42239 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Показывает счетчики объема данных в диалоговом окне "Удалить данные браузера".</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Войдите в аккаунт<ph name="END_SIGN_IN_LINK" />, чтобы просматривать сайты, открытые этим пользователем, и контролировать его действия.</translation>
 <translation id="1097658378307015415">Сначала войдите как гость, чтобы активировать работу сети <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">долгая</translation>
 <translation id="1104652314727136854">Включить в операционной системе связь типов файлов с приложениями Chrome</translation>
 <translation id="1105162038795579389">В набор "<ph name="BUNDLE_NAME" />" для пользователя <ph name="USER_NAME" /> входят следующие приложения и расширения:</translation>
 <translation id="1108600514891325577">&amp;Остановить</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Страницы, не загруженные из-за отсутствия интернет-подключения, будут автоматически перезагружены, только если вкладка активна.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Отменить скачивание}one{Отменить скачивание}few{Отменить скачивание}many{Отменить скачивание}other{Отменить скачивание}}</translation>
 <translation id="3512810056947640266">URL (необязательно):</translation>
-<translation id="351486934407749662">очень долгая</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> хочет предоставить доступ к вашему экрану. Выберите окно, которое вы хотите показать.</translation>
 <translation id="3518086201899641494">Уведомления об адаптивных порталах</translation>
 <translation id="3519867315646775981">Транслитерация (shalom ← שלום)</translation>
@@ -3408,7 +3406,6 @@
 <translation id="569109051430110155">Автоматически</translation>
 <translation id="5691596662111998220">Элемент "<ph name="FILE_NAME" />" удален</translation>
 <translation id="5694501201003948907">Архивирование элементов ($1)…</translation>
-<translation id="5695323626817702678">короткая</translation>
 <translation id="5697118958262594262">Находить важный контент по умолчанию</translation>
 <translation id="5699533844376998780">Расширение <ph name="EXTENSION_NAME" /> успешно добавлено.</translation>
 <translation id="5701101281789450335">Изменить языковые настройки…</translation>
@@ -3831,7 +3828,6 @@
 <translation id="630065524203833229">В&amp;ыход</translation>
 <translation id="6304217058163308077">Новая система приложений-закладок</translation>
 <translation id="6305012486838822927">Лаосская раскладка</translation>
-<translation id="6305328361606238230">Получать push-сообщения</translation>
 <translation id="6307722552931206656">DNS-серверы Google – <ph name="BEGIN_LINK" />Подробнее...<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Система перегружена</translation>
 <translation id="6308937455967653460">Сохранить ссыл&amp;ку как...</translation>
@@ -4526,7 +4522,6 @@
 <translation id="7339785458027436441">Проверять правописание при наборе текста</translation>
 <translation id="7339898014177206373">Новое окно</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> отображается в полноэкранном режиме.</translation>
-<translation id="7341982465543599097">очень короткая</translation>
 <translation id="734303607351427494">Настроить поисковые системы…</translation>
 <translation id="7343116142376328522">Запретить всем сайтам создавать ключи в формах (рекомендуется)</translation>
 <translation id="7345706641791090287">Подтвердите пароль</translation>
@@ -4911,7 +4906,6 @@
 <translation id="7881969471599061635">Отключить субтитры</translation>
 <translation id="7884988936047469945">Экспериментальные специальные возможности</translation>
 <translation id="7885253890047913815">Недавние места назначения</translation>
-<translation id="7885283703487484916">очень короткая</translation>
 <translation id="7887192723714330082">Выполняет команду "О'кей, Google", когда экран включен и разблокирован.</translation>
 <translation id="7887334752153342268">Дублировать</translation>
 <translation id="7887864092952184874">Bluetooth-мышь подключена</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 381cc44..335e566 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Zobrazuje počítadlá objemu dát v dialógovom okne Vymazanie údajov prehliadania.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Prihláste sa<ph name="END_SIGN_IN_LINK" />, aby ste mohli ovládať a zobrazovať webové stránky, ktoré táto osoba navštevuje.</translation>
 <translation id="1097658378307015415">Ak chcete aktivovať sieť <ph name="NETWORK_ID" />, vstúpte pred prihlásením ako hosť</translation>
-<translation id="1104054824888299003">dlhé</translation>
 <translation id="1104652314727136854">Povolí integráciu priradení súborov pre aplikácie Chrome do operačného systému.</translation>
 <translation id="1105162038795579389">Balík <ph name="BUNDLE_NAME" /> pridá pre používateľa <ph name="USER_NAME" /> tieto aplikácie a rozšírenia:</translation>
 <translation id="1108600514891325577">&amp;Zastaviť</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Stránky, ktoré sa nedajú načítať, keď je prehliadač offline, budú automaticky znova načítané iba vtedy, keď bude ich karta viditeľná.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Zrušiť sťahovanie}few{Zrušiť sťahovania}many{Zrušiť sťahovania}other{Zrušiť sťahovania}}</translation>
 <translation id="3512810056947640266">Webová adresa (voliteľné):</translation>
-<translation id="351486934407749662">veľmi dlhé</translation>
 <translation id="3517839692979918726">Aplikácia <ph name="APP_NAME" /> chce zdieľať obsah vašej obrazovky. Vyberte, čo chcete zdieľať.</translation>
 <translation id="3518086201899641494">Upozornenia na prihlasovacie portály</translation>
 <translation id="3519867315646775981">Prepis (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Zistiť automaticky</translation>
 <translation id="5691596662111998220">Hops, súbor <ph name="FILE_NAME" /> už neexistuje.</translation>
 <translation id="5694501201003948907">Prebieha komprimovanie $1 položiek...</translation>
-<translation id="5695323626817702678">krátke</translation>
 <translation id="5697118958262594262">Zisťovať predvolene dôležitý obsah</translation>
 <translation id="5699533844376998780">Rozšírenie <ph name="EXTENSION_NAME" /> bolo pridané.</translation>
 <translation id="5701101281789450335">Jazyk a nastavenia vstupu...</translation>
@@ -3832,7 +3829,6 @@
 <translation id="630065524203833229">U&amp;končiť</translation>
 <translation id="6304217058163308077">Nový systém záložkových aplikácií</translation>
 <translation id="6305012486838822927">Klávesnica pre laoštinu</translation>
-<translation id="6305328361606238230">Prijímať správy push</translation>
 <translation id="6307722552931206656">Menné servery Google – <ph name="BEGIN_LINK" />Viac informácií<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Systém je zaneprázdnený</translation>
 <translation id="6308937455967653460">Uložiť &amp;odkaz ako...</translation>
@@ -4528,7 +4524,6 @@
 <translation id="7339785458027436441">Kontrolovať pravopis počas písania</translation>
 <translation id="7339898014177206373">Nové okno</translation>
 <translation id="7340431621085453413">Stránka <ph name="FULLSCREEN_ORIGIN" /> sa teraz zobrazuje na celú obrazovku.</translation>
-<translation id="7341982465543599097">veľmi krátke</translation>
 <translation id="734303607351427494">Spravovať vyhľadávače...</translation>
 <translation id="7343116142376328522">Nepovoliť žiadnym webom používať generovanie kľúčov vo formulároch (odporúčané)</translation>
 <translation id="7345706641791090287">Potvrdenie hesla</translation>
@@ -4913,7 +4908,6 @@
 <translation id="7881969471599061635">Zakázať titulky</translation>
 <translation id="7884988936047469945">Experimentálne funkcie dostupnosti</translation>
 <translation id="7885253890047913815">Nedávne ciele</translation>
-<translation id="7885283703487484916">veľmi krátke</translation>
 <translation id="7887192723714330082">Reagovať na „Ok Google“, keď je obrazovka zapnutá a odomknutá</translation>
 <translation id="7887334752153342268">Duplikovať</translation>
 <translation id="7887864092952184874">Myš Bluetooth bola spárovaná</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index 55cc4c7..c185832 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Prikaže števce količine podatkov v pogovornem oknu za brisanje podatkov brskanja.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Prijavite se<ph name="END_SIGN_IN_LINK" />, če želite nadzirati in si ogledati spletna mesta, ki jih obiskuje ta oseba.</translation>
 <translation id="1097658378307015415">Pred prijavo vstopite kot gost, da aktivirate omrežje <ph name="NETWORK_ID" />.</translation>
-<translation id="1104054824888299003">dolga</translation>
 <translation id="1104652314727136854">Omogoči integracijo povezav z vrstami datotek za aplikacije za Chrome v operacijski sistem</translation>
 <translation id="1105162038795579389">»<ph name="BUNDLE_NAME" />« doda te aplikacija in razširitve za uporabnika <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Ustavi</translation>
@@ -1874,7 +1873,6 @@
 <translation id="3512284449647229026">Strani, ki jih ni mogoče naložiti, medtem ko je brskalnik brez povezave, se samodejno naložijo le, če so njihovi zavihki vidni.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Preklic prenosa}one{Preklic prenosov}two{Preklic prenosov}few{Preklic prenosov}other{Preklic prenosov}}</translation>
 <translation id="3512810056947640266">URL (izbirno):</translation>
-<translation id="351486934407749662">zelo dolga</translation>
 <translation id="3517839692979918726">Aplikacija <ph name="APP_NAME" /> želi deliti vsebine vašega zaslona z drugimi. Izberite, kaj želite deliti.</translation>
 <translation id="3518086201899641494">Obvestila o portalih za preverjanje pristnosti</translation>
 <translation id="3519867315646775981">Prečrkovanje (shalom ← שלום)</translation>
@@ -3410,7 +3408,6 @@
 <translation id="569109051430110155">Samodejno zaznavanje</translation>
 <translation id="5691596662111998220">Ups, <ph name="FILE_NAME" /> ne obstaja več.</translation>
 <translation id="5694501201003948907">Stiskanje toliko elementov: $1 ...</translation>
-<translation id="5695323626817702678">kratka</translation>
 <translation id="5697118958262594262">Privzeto zaznaj pomembno vsebino</translation>
 <translation id="5699533844376998780">Razširitev »<ph name="EXTENSION_NAME" />« je dodana.</translation>
 <translation id="5701101281789450335">Nastavitve jezika in vnosa ...</translation>
@@ -3835,7 +3832,6 @@
 <translation id="630065524203833229">I&amp;zhod</translation>
 <translation id="6304217058163308077">Nov sistem za aplikacije za ustvarjanje zaznamkov</translation>
 <translation id="6305012486838822927">Tipkovnica za laoščino</translation>
-<translation id="6305328361606238230">Prejemanje potisnih sporočil</translation>
 <translation id="6307722552931206656">Googlovi imenski strežniki – <ph name="BEGIN_LINK" />Več o tem<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistem je zaseden</translation>
 <translation id="6308937455967653460">Shrani povezav&amp;o kot ...</translation>
@@ -4528,7 +4524,6 @@
 <translation id="7339785458027436441">Preverjanje črkovanja med tipkanjem</translation>
 <translation id="7339898014177206373">Novo okno</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> je zdaj prikazano na celotnem zaslonu.</translation>
-<translation id="7341982465543599097">izjemno kratka</translation>
 <translation id="734303607351427494">Upravljanje iskalnikov ...</translation>
 <translation id="7343116142376328522">Spletnim mestom ne dovoli uporabe ustvarjanja ključev v obrazcih (priporočeno)</translation>
 <translation id="7345706641791090287">Potrdite geslo</translation>
@@ -4913,7 +4908,6 @@
 <translation id="7881969471599061635">Onemogočanje podnapisov</translation>
 <translation id="7884988936047469945">Poskusne funkcije za ljudi s posebnimi potrebami</translation>
 <translation id="7885253890047913815">Nedavni cilji</translation>
-<translation id="7885283703487484916">zelo kratka</translation>
 <translation id="7887192723714330082">Odziv na »Ok Google«, ko je zaslon vklopljen in odklenjen</translation>
 <translation id="7887334752153342268">Podvoji</translation>
 <translation id="7887864092952184874">Miška Bluetooth je seznanjena</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index ac24ec0..397d103 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Приказује бројаче количине података у оквиру дијалога „Обриши податке прегледања“</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Пријавите се<ph name="END_SIGN_IN_LINK" /> да бисте контролисали и прегледали веб-сајтове које ова особа посећује.</translation>
 <translation id="1097658378307015415">Пре пријављивања приступите као гост да бисте активирали мрежу <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">дуго</translation>
 <translation id="1104652314727136854">Омогућите интеграцију повезаних датотека са ОС-ом за Chrome апликације.</translation>
 <translation id="1105162038795579389">„<ph name="BUNDLE_NAME" />“ додаје следеће апликације и додатке за <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Stop (Заустави)</translation>
@@ -1869,7 +1868,6 @@
 <translation id="3512284449647229026">Странице које не успеју да се учитају док је прегледач офлајн ће се аутоматски поново учитати само ако је картица видљива.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Откажи преузимање}one{Откажи преузимања}few{Откажи преузимања}other{Откажи преузимања}}</translation>
 <translation id="3512810056947640266">URL (опционално):</translation>
-<translation id="351486934407749662">веома дуго</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> жели да дели садржај екрана. Изаберите шта желите да делите.</translation>
 <translation id="3518086201899641494">Обавештења о порталима за проверу</translation>
 <translation id="3519867315646775981">Транслитерација (shalom ← שלום)</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">Аутоматски откриј</translation>
 <translation id="5691596662111998220">Упс, <ph name="FILE_NAME" /> више не постоји.</translation>
 <translation id="5694501201003948907">Додавање ставки ($1) у zip датотеку...</translation>
-<translation id="5695323626817702678">кратко</translation>
 <translation id="5697118958262594262">Подразумевано откривај важан садржај</translation>
 <translation id="5699533844376998780">Додатак „<ph name="EXTENSION_NAME" />“ је додат.
 </translation>
@@ -3831,7 +3828,6 @@
 <translation id="630065524203833229">И&amp;зађи</translation>
 <translation id="6304217058163308077">Нови систем апликација обележивача</translation>
 <translation id="6305012486838822927">Лаоска тастатура</translation>
-<translation id="6305328361606238230">Пријем порука</translation>
 <translation id="6307722552931206656">Google сервери назива – <ph name="BEGIN_LINK" />Сазнајте више<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Систем је заузет</translation>
 <translation id="6308937455967653460">Сачувај ве&amp;зу као...</translation>
@@ -4526,7 +4522,6 @@
 <translation id="7339785458027436441">Проверавај правопис током куцања</translation>
 <translation id="7339898014177206373">Нови прозор</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> је сада у режиму целог екрана.</translation>
-<translation id="7341982465543599097">изузетно кратко</translation>
 <translation id="734303607351427494">Управљај претраживачима...</translation>
 <translation id="7343116142376328522">Не дозволи ниједном сајту да користи генерисање шифара у обрасцима (препоручено)</translation>
 <translation id="7345706641791090287">Потврдите лозинку</translation>
@@ -4905,7 +4900,6 @@
 <translation id="7881969471599061635">Онемогући титлове</translation>
 <translation id="7884988936047469945">Експериментални функције приступачности</translation>
 <translation id="7885253890047913815">Недавна одредишта</translation>
-<translation id="7885283703487484916">веома кратко</translation>
 <translation id="7887192723714330082">Реагуј на „ОК Google“ када је екран укључен и откључан</translation>
 <translation id="7887334752153342268">Направи дупликат</translation>
 <translation id="7887864092952184874">Bluetooth миш је упарен</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index bf72c38..520ba63 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Visar datavolymräknare i dialogrutan Rensa webbinformation.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Logga in<ph name="END_SIGN_IN_LINK" /> om du vill styra och visa vilka webbplatser den här personen besöker.</translation>
 <translation id="1097658378307015415">Aktivera nätverket <ph name="NETWORK_ID" /> genom att logga in som gäst innan du loggar in</translation>
-<translation id="1104054824888299003">lång</translation>
 <translation id="1104652314727136854">Aktivera filassociation för Chrome-appar i operativsystem.</translation>
 <translation id="1105162038795579389"><ph name="BUNDLE_NAME" /> lägger till dessa appar och tillägg för <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Stopp</translation>
@@ -1872,7 +1871,6 @@
 <translation id="3512284449647229026">Sidor som inte kan läsas in när webbläsaren är offline läses bara in automatiskt om deras flikar är synliga.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Avbryt nedladdningen}other{Avbryt nedladdningarna}}</translation>
 <translation id="3512810056947640266">Webbadress (valfritt):</translation>
-<translation id="351486934407749662">mycket lång</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> vill dela innehållet på din skärm. Välj det du vill dela.</translation>
 <translation id="3518086201899641494">Meddelanden om infångstportaler</translation>
 <translation id="3519867315646775981">Translitterera (shalom ← שלום)</translation>
@@ -3407,7 +3405,6 @@
 <translation id="569109051430110155">Upptäck automatiskt</translation>
 <translation id="5691596662111998220"><ph name="FILE_NAME" /> finns tyvärr inte längre.</translation>
 <translation id="5694501201003948907">$1 objekt komprimeras ...</translation>
-<translation id="5695323626817702678">kort</translation>
 <translation id="5697118958262594262">Upptäck viktigt innehåll som standard</translation>
 <translation id="5699533844376998780">Tillägget <ph name="EXTENSION_NAME" /> har lagts till.</translation>
 <translation id="5701101281789450335">Språk- och inmatningsinställningar ...</translation>
@@ -3832,7 +3829,6 @@
 <translation id="630065524203833229">&amp;Avsluta</translation>
 <translation id="6304217058163308077">Det nya systemet för bokmärkesappar</translation>
 <translation id="6305012486838822927">Laotiskt tangentbord</translation>
-<translation id="6305328361606238230">Ta emot push-meddelanden</translation>
 <translation id="6307722552931206656">Googles namnservrar – <ph name="BEGIN_LINK" />Läs mer<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Systemet är upptaget</translation>
 <translation id="6308937455967653460">Spara l&amp;änk som...</translation>
@@ -4526,7 +4522,6 @@
 <translation id="7339785458027436441">Kontrollera stavning medan jag skriver</translation>
 <translation id="7339898014177206373">Nytt fönster</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> visas nu i helskärm.</translation>
-<translation id="7341982465543599097">extremt kort</translation>
 <translation id="734303607351427494">Hantera sökmotorer...</translation>
 <translation id="7343116142376328522">Tillåt inga webbplatser att använda nyckelgenerering i formulär (rekommenderas)</translation>
 <translation id="7345706641791090287">Bekräfta lösenordet</translation>
@@ -4910,7 +4905,6 @@
 <translation id="7881969471599061635">Inaktivera undertexter</translation>
 <translation id="7884988936047469945">Experimentella tillgänglighetsfunktioner</translation>
 <translation id="7885253890047913815">Senaste platserna</translation>
-<translation id="7885283703487484916">mycket kort</translation>
 <translation id="7887192723714330082">Svara på ”Ok Google” när skärmen är på och olåst</translation>
 <translation id="7887334752153342268">Duplicera</translation>
 <translation id="7887864092952184874">Bluetooth-musen har kopplats</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index db3d987..250d5d0 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Huonyesha kaunta za idadi ya data katika kidirisha cha Futa data ya kuvinjari.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Ingia katika akaunti<ph name="END_SIGN_IN_LINK" /> ili udhibiti na uangalie tovuti ambazo mtu huyu hutembelea.</translation>
 <translation id="1097658378307015415">Kabla ya kuingia, tafadhali ingia kama Mgeni ili kuamilisha mtandao <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">mrefu</translation>
 <translation id="1104652314727136854">Washa muingiliano wa OS wa uhusiano wa faili kwa Programu za Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" huongeza programu na viendelezi hivi kwa <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Acha</translation>
@@ -1863,7 +1862,6 @@
 <translation id="3512284449647229026">Kurasa zinazoshindwa kupakia kivinjari kinapokuwa nje ya mtandao zitapakiwa tena tu ikiwa vichupo vyao vinaonekana.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Ghairi Kipakuliwa}other{Ghairi Vipakuliwa}}</translation>
 <translation id="3512810056947640266">URL (hiari):</translation>
-<translation id="351486934407749662">mrefu sana</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> ingependa kushiriki maudhui ya skrini yako. Chagua kile ungependa kushiriki.</translation>
 <translation id="3518086201899641494">Arifa kuhusu tovuti za uthibitishaji</translation>
 <translation id="3519867315646775981">Unukuzi wa mfumo wa kuandika (shalom ← שלום)</translation>
@@ -3392,7 +3390,6 @@
 <translation id="569109051430110155">Gundua kiotomatiki</translation>
 <translation id="5691596662111998220">Lo, <ph name="FILE_NAME" /> haipo tena.</translation>
 <translation id="5694501201003948907">Vipengee $1 vinabanwa...</translation>
-<translation id="5695323626817702678">fupi</translation>
 <translation id="5697118958262594262">Gundua maudhui muhimu kwa chaguo-msingi</translation>
 <translation id="5699533844376998780">Kiendelezi "<ph name="EXTENSION_NAME" />" kimeongezwa.</translation>
 <translation id="5701101281789450335">Mipangilio ya lugha, kibodi na sauti...</translation>
@@ -3817,7 +3814,6 @@
 <translation id="630065524203833229">Ondoka</translation>
 <translation id="6304217058163308077">Mfumo mpya wa programu ya alamisho</translation>
 <translation id="6305012486838822927">Kibodi ya Kilao</translation>
-<translation id="6305328361606238230">Pokea ujumbe unaotumwa na programu hata wakati huitumii</translation>
 <translation id="6307722552931206656">Seva za majina za Google - <ph name="BEGIN_LINK" />Pata maelezo zaidi<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Mfumo unashughulika</translation>
 <translation id="6308937455967653460">Hifadhi &amp;kiungo kama...</translation>
@@ -4513,7 +4509,6 @@
 <translation id="7339785458027436441">Kagua Tahajia Unapochapa</translation>
 <translation id="7339898014177206373">Dirisha jipya</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> sasa ni skrini nzima.</translation>
-<translation id="7341982465543599097">fupi mno</translation>
 <translation id="734303607351427494">Dhibiti mitambo ya kutafuta...</translation>
 <translation id="7343116142376328522">Usiruhusu tovuti yoyote kutumia uundaji funguo katika fomu (inapendekezwa)</translation>
 <translation id="7345706641791090287">Thibitisha nenosiri lako</translation>
@@ -4897,7 +4892,6 @@
 <translation id="7881969471599061635">Zima manukuu</translation>
 <translation id="7884988936047469945">Vipengele vya ufikiaji wa majaribio</translation>
 <translation id="7885253890047913815">Printa ulizotumia hivi karibuni</translation>
-<translation id="7885283703487484916">fupi mno</translation>
 <translation id="7887192723714330082">Jibu "Ok Google" skrini ikiwa imewashwa na kufunguliwa</translation>
 <translation id="7887334752153342268">Maradufu</translation>
 <translation id="7887864092952184874">Kipanya cha Bluetooth kimeoanishwa</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index bc29efab..895a068 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">உலாவல் தரவை அழி உரையாடலில் தரவு அளவுக் கவுன்ட்டர்களைக் காட்டும்.</translation>
 <translation id="1097507499312291972">இவர் பார்வையிடுகின்ற, இணையதளங்களைக் கட்டுப்படுத்த மற்றும் பார்க்க, <ph name="BEGIN_SIGN_IN_LINK" />உள்நுழையவும்<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">உள்நுழைவதற்கு முன்பாக, நெட்வொர்க் <ph name="NETWORK_ID" /> ஐச் செயல்படுத்த விருந்தினராக உள்ளிடுக</translation>
-<translation id="1104054824888299003">நீண்ட நேரம்</translation>
 <translation id="1104652314727136854">Chrome பயன்பாடுகளுக்கான கோப்புடன் தொடர்புடையவற்றின் OS ஒருங்கிணைப்பை இயக்கு.</translation>
 <translation id="1105162038795579389">பின்வரும் பயன்பாடுகளையும் நீட்டிப்புகளையும் <ph name="USER_NAME" />க்கு "<ph name="BUNDLE_NAME" />" சேர்க்கும்:</translation>
 <translation id="1108600514891325577">&amp;Stop</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">உலாவி ஆஃப்லைனில் இருக்கும்போது ஏற்ற முடியாமல் இருந்த பக்கங்கள், அவற்றின் தாவல் தெரிவுநிலையில் இருந்தால் மட்டுமே தானாக மீண்டும் ஏற்றப்படும்.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{பதிவிறக்கத்தை ரத்துசெய்}other{பதிவிறக்கங்களை ரத்துசெய்}}</translation>
 <translation id="3512810056947640266">URL (விரும்பினால்):</translation>
-<translation id="351486934407749662">மிக நீண்ட நேரம்</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> உங்கள் திரையின் உள்ளடக்கங்களைப் பகிர விரும்புகிறது. என்ன பகிர விரும்புகிறீர்கள் என்பதைத் தேர்வுசெய்யவும்.</translation>
 <translation id="3518086201899641494">கேப்டிவ் போர்ட்டல்கள் குறித்த அறிவிப்புகள்</translation>
 <translation id="3519867315646775981">ஒலிபெயர்ப்பு (shalom ← שלום)</translation>
@@ -3403,7 +3401,6 @@
 <translation id="569109051430110155">தானியங்கு கண்டறிதல்</translation>
 <translation id="5691596662111998220">அடடா, <ph name="FILE_NAME" /> இல்லை.</translation>
 <translation id="5694501201003948907">$1 உருப்படிகளை ஜிப் செய்கிறது...</translation>
-<translation id="5695323626817702678">குறைவான நேரம்</translation>
 <translation id="5697118958262594262">இயல்பாகவே முக்கியமான உள்ளடக்கத்தைக் கண்டுபிடி</translation>
 <translation id="5699533844376998780">"<ph name="EXTENSION_NAME" />" என்ற நீட்டிப்பு சேர்க்கப்பட்டது.</translation>
 <translation id="5701101281789450335">மொழி மற்றும் உள்ளீட்டு அமைப்புகள்...</translation>
@@ -3826,7 +3823,6 @@
 <translation id="630065524203833229">வெளி&amp;யேறு</translation>
 <translation id="6304217058163308077">புதிய புத்தகக்குறிப் பயன்பாட்டு அமைப்பு</translation>
 <translation id="6305012486838822927">லாவோ விசைப்பலகை</translation>
-<translation id="6305328361606238230">அறிவிப்புச் செய்திகளைப் பெறு</translation>
 <translation id="6307722552931206656">Google பெயர் சேவையகங்கள் - <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">கணினி பணிமிகுதியில் உள்ளது</translation>
 <translation id="6308937455967653460">இணை&amp;ப்பை இவ்வாறு சேமி…</translation>
@@ -4520,7 +4516,6 @@
 <translation id="7339785458027436441">தட்டச்சு செய்யும்போதே எழுத்துப்பிழை சரிபார்</translation>
 <translation id="7339898014177206373">புதிய சாளரம்</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" />, இப்போது முழுத் திரையில் உள்ளது.</translation>
-<translation id="7341982465543599097">மிகவும் குறுகிய</translation>
 <translation id="734303607351427494">தேடு பொறிகளை நிர்வகி...</translation>
 <translation id="7343116142376328522">படிவங்களில் விசை உருவாக்கத்தைப் பயன்படுத்த எந்தத் தளத்தையும் அனுமதிக்க வேண்டாம் (பரிந்துரைக்கப்பட்டது)</translation>
 <translation id="7345706641791090287">கடவுச்சொல்லை உறுதிப்படுத்தவும்</translation>
@@ -4897,7 +4892,6 @@
 <translation id="7881969471599061635">வசனங்களை முடக்கு</translation>
 <translation id="7884988936047469945">பரிசோதனைக்குரிய அணுகல்தன்மை அம்சங்கள்</translation>
 <translation id="7885253890047913815">சமீபத்திய இலக்குகள்</translation>
-<translation id="7885283703487484916">மிகவும் குறைவான நேரம்</translation>
 <translation id="7887192723714330082">திரை இயக்கப்பட்டிருக்கும் போதும், திறக்கப்பட்டிருக்கும் போதும், "Ok Google"க்குப் பதிலளிக்கும்</translation>
 <translation id="7887334752153342268">பிரதி எடு</translation>
 <translation id="7887864092952184874">புளூடூத் மவுஸ் இணைக்கப்பட்டது</translation>
@@ -5893,7 +5887,7 @@
 <translation id="981121421437150478">ஆஃப்லைன்</translation>
 <translation id="984870422930397199">புதிய தாவல் பக்கத்தில் ஆஃப்லைன் பக்கங்களின் பேட்ஜிங்கை இயக்கும். ஆஃப்லைன் பக்கங்கள் இயக்கப்பட்டிருந்தால் மட்டுமே இது பொருந்தும்.</translation>
 <translation id="98515147261107953">கிடைமட்டம்</translation>
-<translation id="986646739000587506">டெஸ்க்டாப் பகிர்வுக்கான தாவலை முடக்கு</translation>
+<translation id="986646739000587506">தாவலின் டெஸ்க்டாப் பகிர்வை முடக்கு</translation>
 <translation id="987267091708560486">{NUM_ITEMS,plural, =1{இது, இந்தச் சாதனத்திலிருந்து $1 உருப்படியை நிரந்தரமாக நீக்கும்.}other{இது, இந்தச் சாதனத்திலிருந்து $1 உருப்படிகளை நிரந்தரமாக நீக்கும்.}}</translation>
 <translation id="990878533354103361">பரிசோதனைக்கான உள்ளீட்டு காட்சி அம்சங்கள்</translation>
 <translation id="991969738502325513">நீங்கள் என்ன செய்ய வேண்டும்?</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 3c952a18..8fd7897 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">బ్రౌజింగ్ డేటాను తీసివేయి డైలాగ్‌లో డేటా పరిమాణం కౌంటర్‌లను చూపుతుంది.</translation>
 <translation id="1097507499312291972">ఈ వ్యక్తి సందర్శించిన వెబ్‌సైట్‌లను నియంత్రించడానికి మరియు వీక్షించడానికి <ph name="BEGIN_SIGN_IN_LINK" />సైన్ ఇన్ చేయండి<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">సైన్ ఇన్ చేయడానికి ముందుగా, దయచేసి <ph name="NETWORK_ID" /> నెట్‌వర్క్‌ను సక్రియం చేయడానికి అతిథి వలె ప్రవేశించండి</translation>
-<translation id="1104054824888299003">ఎక్కువ</translation>
 <translation id="1104652314727136854">Chrome అనువర్తనాల కోసం ఫైల్ అనుబంధాల OS ఇంటిగ్రేషన్‌ను ప్రారంభించండి.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" ఈ అనువర్తనాలు మరియు పొడిగింపులను <ph name="USER_NAME" />కు జోడిస్తుంది:</translation>
 <translation id="1108600514891325577">&amp;ఆపు</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">బ్రౌజర్ ఆఫ్‌లైన్‌లో ఉన్నప్పుడు లోడ్ కావడంలో విఫలమయ్యే పేజీలు వాటి ట్యాబ్ దృశ్యమానంగా ఉన్నప్పుడు మాత్రమే స్వయంచాలకంగా మళ్లీ లోడ్ చేయబడతాయి.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{డౌన్‌లోడ్‌ను రద్దు చేయి}other{డౌన్‌లోడ్‌లను రద్దు చేయి}}</translation>
 <translation id="3512810056947640266">URL (ఐచ్ఛికం):</translation>
-<translation id="351486934407749662">చాలా ఎక్కువ సేపు</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> మీ స్క్రీన్ యొక్క కంటెంట్‌లను భాగస్వామ్యం చేయడానికి అనుమతి కోరుతోంది. మీరు ఏమేమి భాగస్వామ్యం చేయాలనుకుంటున్నారో ఎంచుకోండి.</translation>
 <translation id="3518086201899641494">క్యాప్టివ్ పోర్టల్‌ల గురించి నోటిఫికేషన్‌లు</translation>
 <translation id="3519867315646775981">లిప్యంతరీకరణ (shalom ← שלום)</translation>
@@ -3406,7 +3404,6 @@
 <translation id="569109051430110155">స్వయంగా కనుగొనడం</translation>
 <translation id="5691596662111998220">అయ్యో, <ph name="FILE_NAME" /> ఉనికిలో లేదు.</translation>
 <translation id="5694501201003948907">$1 అంశాలను జిప్ చేస్తోంది...</translation>
-<translation id="5695323626817702678">తక్కువ</translation>
 <translation id="5697118958262594262">డిఫాల్ట్‌గా ముఖ్యమైన కంటెంట్‌ను గుర్తించు</translation>
 <translation id="5699533844376998780">పొడిగింపు "<ph name="EXTENSION_NAME" />" జోడించబడింది.</translation>
 <translation id="5701101281789450335">భాష మరియు ఇన్‌పుట్ సెట్టింగ్‌లు...</translation>
@@ -3829,7 +3826,6 @@
 <translation id="630065524203833229">ని&amp;ష్క్రమించు</translation>
 <translation id="6304217058163308077">కొత్త బుక్‌మార్క్ అనువర్తన సిస్టమ్</translation>
 <translation id="6305012486838822927">లావో కీబోర్డ్</translation>
-<translation id="6305328361606238230">పుష్ సందేశాలను స్వీకరించాలా</translation>
 <translation id="6307722552931206656">Google పేరు సర్వర్‌లు - <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">సిస్టమ్ బిజీగా ఉంది</translation>
 <translation id="6308937455967653460">లిం&amp;క్‌ను ఇలా సేవ్ చెయ్యి...</translation>
@@ -4524,7 +4520,6 @@
 <translation id="7339785458027436441">టైప్ చేసేటప్పుడు అక్షరక్రమాన్ని తనిఖీ చేయి</translation>
 <translation id="7339898014177206373">క్రొత్త విండో</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> ఇప్పుడు పూర్తి స్క్రీన్‌లో కనిపిస్తుంది.</translation>
-<translation id="7341982465543599097">అత్యంత తక్కువ</translation>
 <translation id="734303607351427494">శోధన ఇంజన్‌లను నిర్వహించండి...</translation>
 <translation id="7343116142376328522">ఫారమ్‌ల్లో కీ ఉత్పాదనను ఉపయోగించడానికి ఏ సైట్‌ను అనుమతించవద్దు (సిఫార్సు చేయబడింది)</translation>
 <translation id="7345706641791090287">మీ పాస్‌వర్డ్‌ను నిర్ధారించండి</translation>
@@ -4909,7 +4904,6 @@
 <translation id="7881969471599061635">ఉపశీర్షికలను నిలిపివేయి</translation>
 <translation id="7884988936047469945">ప్రయోగాత్మక ప్రాప్యత లక్షణాలు</translation>
 <translation id="7885253890047913815">ఇటీవలి గమ్యస్థానాలు</translation>
-<translation id="7885283703487484916">చాలా తక్కువ</translation>
 <translation id="7887192723714330082">స్క్రీన్ ఆన్‌లో ఉండి, ఆన్‌లాక్ చేయబడినప్పుడు "Ok Google"కి ప్రతిస్పందించండి</translation>
 <translation id="7887334752153342268">నకిలీ</translation>
 <translation id="7887864092952184874">బ్లూటూత్ మౌస్ జత చేయబడింది</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index be54f91e..f0cdf9b5 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">แสดงตัวนับปริมาณอินเทอร์เน็ตในกล่องล้างข้อมูลการท่องเว็บ</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />ลงชื่อเข้าใช้<ph name="END_SIGN_IN_LINK" />เพื่อควบคุมและดูเว็บไซต์ที่บุคคลนี้เข้าชม</translation>
 <translation id="1097658378307015415">ก่อนที่จะลงชื่อเข้าใช้ โปรดเข้าใช้ในฐานะผู้มาเยือนเพื่อเปิดใช้งานเครือข่าย <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">ยาว</translation>
 <translation id="1104652314727136854">เปิดใช้การรวมระบบปฏิบัติการของการเชื่อมโยงไฟล์สำหรับแอป Chrome</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" เพิ่มแอปและส่วนขยายเหล่านี้สำหรับ <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;หยุด</translation>
@@ -1436,7 +1435,7 @@
 <translation id="2951247061394563839">กลางหน้าต่าง</translation>
 <translation id="2951721188322348056">ข้อมูลวิดีโอ</translation>
 <translation id="2956763290572484660">คุกกี้ <ph name="COOKIES" /> รายการ</translation>
-<translation id="295947108480905647">"<ph name="CHROME_EXTENSION_NAME" />" ต้องการที่จะเชื่อมต่อกับ</translation>
+<translation id="295947108480905647">"<ph name="CHROME_EXTENSION_NAME" />" ต้องการที่จะเชื่อมต่อกับ:</translation>
 <translation id="2959614062380389916">ปิดใช้โดยผู้ดูแลระบบ</translation>
 <translation id="2960393411257968125">วิธีที่ตัวจัดการรหัสผ่านจัดการการป้อนข้อความอัตโนมัติสำหรับข้อมูลรับรองการซิงค์</translation>
 <translation id="29611076221683977">ผู้บุกรุกที่กำลังอยู่ใน <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> อาจพยายามติดตั้งโปรแกรมอันตรายซึ่งขโมยหรือลบข้อมูล (ตัวอย่างเช่น รูปภาพ รหัสผ่าน ข้อความ และบัตรเครดิต) ลงในเครื่อง Mac ของคุณ</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">จะมีการโหลดซ้ำหน้าที่ไม่สามารถโหลดขณะเบราว์เซอร์ออฟไลน์โดยอัตโนมัติ หากมองเห็นแท็บของหน้าเท่านั้น</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{ยกเลิกการดาวน์โหลด}other{ยกเลิกการดาวน์โหลด}}</translation>
 <translation id="3512810056947640266">URL (ไม่บังคับ):</translation>
-<translation id="351486934407749662">ยาวมาก</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> ต้องการแชร์เนื้อหาบนหน้าจอของคุณ เลือกส่วนที่คุณต้องการแชร์</translation>
 <translation id="3518086201899641494">การแจ้งเตือนเกี่ยวกับ Captive Portal</translation>
 <translation id="3519867315646775981">การทับศัพท์ (shalom ← שלום)</translation>
@@ -2464,7 +2462,7 @@
 <translation id="4358697938732213860">เพิ่มที่อยู่</translation>
 <translation id="4359408040881008151">ติดตั้งแล้วเนื่องจากมีส่วนขยายที่ต้องพึ่งพา</translation>
 <translation id="4361190688154226069">การกำหนดเป้าหมายแบบรูปสี่เหลี่ยมผืนผ้าในมุมมองต่างๆ</translation>
-<translation id="4361765875689149937"><ph name="ORIGIN" /> ต้องการจับคู่กับ</translation>
+<translation id="4361765875689149937"><ph name="ORIGIN" /> ต้องการจับคู่กับ:</translation>
 <translation id="4364444725319685468">ดาวน์โหลด <ph name="FILE_NAME" /> แล้ว</translation>
 <translation id="4364567974334641491"><ph name="APP_NAME" /> กำลังแชร์หน้าต่าง</translation>
 <translation id="4364830672918311045">แสดงการแจ้งเตือน</translation>
@@ -3264,7 +3262,7 @@
 <translation id="5486561344817861625">จำลองการรีสตาร์ทเบราว์เซอร์</translation>
 <translation id="54870580363317966">เลือกอวาตาร์สำหรับผู้ใช้ภายใต้การดูแลนี้</translation>
 <translation id="5488468185303821006">อนุญาตให้ใช้โหมดไม่ระบุตัวตน</translation>
-<translation id="5489390182170331803">ค่าเริ่มต้นแบบแพสซีฟของ Listener เหตุการณ์ระดับเอกสาร</translation>
+<translation id="5489390182170331803">ค่าเริ่มต้นของ Listener เหตุการณ์แบบแพสซีฟระดับเอกสาร</translation>
 <translation id="5489789060051091748">เลือกเพื่อพูด: กดแป้น Search ค้างไว้ แล้วคลิกหรือลากเพื่อพูดอะไรก็ได้</translation>
 <translation id="549294555051714732">สตริงย่อยที่ตรงกับคำแนะนำในการป้อนข้อความอัตโนมัติ</translation>
 <translation id="5493996328530898436">วิธีมิกซ์เมื่อเรนเดอร์เสียงแบบใหม่</translation>
@@ -3405,7 +3403,6 @@
 <translation id="569109051430110155">ตรวจหาอัตโนมัติ</translation>
 <translation id="5691596662111998220">อ๊ะ ไม่มี <ph name="FILE_NAME" /> แล้ว</translation>
 <translation id="5694501201003948907">กำลังซิป $1 รายการ...</translation>
-<translation id="5695323626817702678">สั้น</translation>
 <translation id="5697118958262594262">ตรวจหาเนื้อหาที่สำคัญโดยค่าเริ่มต้น</translation>
 <translation id="5699533844376998780">เพิ่มส่วนขยาย "<ph name="EXTENSION_NAME" />" แล้ว</translation>
 <translation id="5701101281789450335">การตั้งค่าภาษาและการป้อนข้อมูล...</translation>
@@ -3828,7 +3825,6 @@
 <translation id="630065524203833229">&amp;ออก</translation>
 <translation id="6304217058163308077">ระบบแอปบุ๊กมาร์กใหม่</translation>
 <translation id="6305012486838822927">แป้นพิมพ์ภาษาลาว</translation>
-<translation id="6305328361606238230">รับข้อความแบบ Push</translation>
 <translation id="6307722552931206656">เซิร์ฟเวอร์ชื่อของ Google <ph name="BEGIN_LINK" />เรียนรู้เพิ่มเติม<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">ระบบกำลังทำงานอื่นอยู่</translation>
 <translation id="6308937455967653460">บันทึก&amp;ลิงก์เป็น...</translation>
@@ -4522,7 +4518,6 @@
 <translation id="7339785458027436441">ตรวจสอบตัวสะกดขณะพิมพ์</translation>
 <translation id="7339898014177206373">หน้าต่างใหม่</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> แสดงแบบเต็มหน้าจออยู่</translation>
-<translation id="7341982465543599097">สั้นมาก</translation>
 <translation id="734303607351427494">จัดการเครื่องมือค้นหา...</translation>
 <translation id="7343116142376328522">ไม่อนุญาตให้เว็บไซต์ใดๆ ใช้การสร้างคีย์ในแบบฟอร์ม (แนะนำ)</translation>
 <translation id="7345706641791090287">ยืนยันรหัสผ่าน</translation>
@@ -4907,7 +4902,6 @@
 <translation id="7881969471599061635">ปิดคำบรรยาย</translation>
 <translation id="7884988936047469945">คุณลักษณะการเข้าถึงรุ่นทดลอง</translation>
 <translation id="7885253890047913815">ปลายทางล่าสุด</translation>
-<translation id="7885283703487484916">สั้นมาก</translation>
 <translation id="7887192723714330082">ตอบสนองต่อ "Ok Google" เมื่อหน้าจอเปิดอยู่และไม่ได้ล็อก</translation>
 <translation id="7887334752153342268">ทำซ้ำ</translation>
 <translation id="7887864092952184874">จับคู่เมาส์บลูทูธแล้ว</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index 617c3d9..923eb741 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Tarama verilerini temizleme iletişim kutusunda veri hacmi sayaçlarını gösterir.</translation>
 <translation id="1097507499312291972">Bu kişinin ziyaret ettiği web sitelerini kontrol etmek ve görüntülemek için <ph name="BEGIN_SIGN_IN_LINK" />oturum açın<ph name="END_SIGN_IN_LINK" />.</translation>
 <translation id="1097658378307015415">Oturum açmadan önce <ph name="NETWORK_ID" /> ağını etkinleştirmek için lütfen Misafir olarak giriş yapın</translation>
-<translation id="1104054824888299003">uzun</translation>
 <translation id="1104652314727136854">Chrome Uygulamaları için dosya ilişkilendirmelerinin OS ile entegrasyonunu etkinleştirin.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />", <ph name="USER_NAME" /> için şu uygulamaları ve uzantıları ekler:</translation>
 <translation id="1108600514891325577">D&amp;urdur</translation>
@@ -1873,7 +1872,6 @@
 <translation id="3512284449647229026">Tarayıcı çevrimdışıyken yüklenemeyen sayfalar yalnızca sekmelerinin görünür olması durumunda otomatik olarak yeniden yüklenir.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{İndirme işlemini iptal et}other{İndirme işlemlerini iptal et}}</translation>
 <translation id="3512810056947640266">URL (isteğe bağlı):</translation>
-<translation id="351486934407749662">çok uzun</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" />, ekranınızın içeriğini paylaşmak istiyor. Neleri paylaşmak istediğinizi seçin.</translation>
 <translation id="3518086201899641494">Doğrulama amacıyla yönlendirme yapan portallar ile ilgili bildirimler</translation>
 <translation id="3519867315646775981">Harf çevirisi (shalom ← שלום)</translation>
@@ -3409,7 +3407,6 @@
 <translation id="569109051430110155">Otomatik algıla</translation>
 <translation id="5691596662111998220">Hata! <ph name="FILE_NAME" /> artık mevcut değil.</translation>
 <translation id="5694501201003948907">$1 öğe sıkıştırılıyor...</translation>
-<translation id="5695323626817702678">kısa</translation>
 <translation id="5697118958262594262">Önemli içeriği varsayılan olarak algıla</translation>
 <translation id="5699533844376998780">"<ph name="EXTENSION_NAME" />" uzantısı eklendi.</translation>
 <translation id="5701101281789450335">Dil ve giriş ayarları...</translation>
@@ -3832,7 +3829,6 @@
 <translation id="630065524203833229">Çı&amp;kış</translation>
 <translation id="6304217058163308077">Yeni yer işareti uygulaması sistemi</translation>
 <translation id="6305012486838822927">Lao klavye</translation>
-<translation id="6305328361606238230">Push mesajlarını al</translation>
 <translation id="6307722552931206656">Google ad sunucuları - <ph name="BEGIN_LINK" />Daha fazla bilgi edinin<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Sistem meşgul</translation>
 <translation id="6308937455967653460">Bağlantıyı far&amp;klı kaydet...</translation>
@@ -4526,7 +4522,6 @@
 <translation id="7339785458027436441">Yazarken Yazımı Denetle</translation>
 <translation id="7339898014177206373">Yeni pencere</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> şimdi tam ekran görüntüleniyor.</translation>
-<translation id="7341982465543599097">aşırı kısa</translation>
 <translation id="734303607351427494">Arama motorlarını yönet...</translation>
 <translation id="7343116142376328522">Sitelerin formlarda anahtar oluşturmasına izin verme (önerilen)</translation>
 <translation id="7345706641791090287">Şifrenizi onaylayın</translation>
@@ -4911,7 +4906,6 @@
 <translation id="7881969471599061635">Altyazıları devre dışı bırak</translation>
 <translation id="7884988936047469945">Deneysel erişilebilirlik özellikleri</translation>
 <translation id="7885253890047913815">En Son Hedefler</translation>
-<translation id="7885283703487484916">çok kısa</translation>
 <translation id="7887192723714330082">Ekran ve kilidi açıkken "Ok Google"a yanıt verme</translation>
 <translation id="7887334752153342268">Yinele</translation>
 <translation id="7887864092952184874">Bluetooth fare eşlendi</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index 15f95a0..900d0cc7 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Показує лічильники обсягу даних у вікні "Очистити дані веб-перегляду".</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Увійдіть<ph name="END_SIGN_IN_LINK" />, щоб контролювати й переглядати веб-сайти, які відвідує цей користувач.</translation>
 <translation id="1097658378307015415">Перш ніж увійти, розпочніть сеанс у режимі гостя, щоб активувати мережу <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">довго</translation>
 <translation id="1104652314727136854">Увімкнути інтеграцію ОС в асоціації файлів для додатків Chrome.</translation>
 <translation id="1105162038795579389">Пакет "<ph name="BUNDLE_NAME" />" додає для користувача <ph name="USER_NAME" /> такі додатки та розширення:</translation>
 <translation id="1108600514891325577">&amp;Зупинити</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">Сторінки, які не вдалося завантажити, коли веб-переглядач був у режимі офлайн, автоматично перезавантажаться, коли вкладка стане видимою.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Скасувати завантаження}one{Скасувати завантаження}few{Скасувати завантаження}many{Скасувати завантаження}other{Скасувати завантаження}}</translation>
 <translation id="3512810056947640266">URL-адреса (необов’язково):</translation>
-<translation id="351486934407749662">дуже довго</translation>
 <translation id="3517839692979918726">Додаток <ph name="APP_NAME" /> хоче показувати вміст вашого екрана. Виберіть вміст, який хочете показувати.</translation>
 <translation id="3518086201899641494">Сповіщення про приєднані портали</translation>
 <translation id="3519867315646775981">Транслітерація (shalom ← שלום)</translation>
@@ -3406,7 +3404,6 @@
 <translation id="569109051430110155">Автом. визначення</translation>
 <translation id="5691596662111998220">На жаль, файл "<ph name="FILE_NAME" />" більше не існує.</translation>
 <translation id="5694501201003948907">Архівування елементів ($1)…</translation>
-<translation id="5695323626817702678">коротко</translation>
 <translation id="5697118958262594262">Виявляти важливий вміст за умовчанням</translation>
 <translation id="5699533844376998780">Розширення "<ph name="EXTENSION_NAME" />" додано.</translation>
 <translation id="5701101281789450335">Налаштування мови та способів введення...</translation>
@@ -3829,7 +3826,6 @@
 <translation id="630065524203833229">В&amp;ийти</translation>
 <translation id="6304217058163308077">Нова система додатків для закладок</translation>
 <translation id="6305012486838822927">Лаоська клавіатура</translation>
-<translation id="6305328361606238230">Отримувати push-повідомлення</translation>
 <translation id="6307722552931206656">Сервер імен Google – <ph name="BEGIN_LINK" />Докладніше<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Система зайнята</translation>
 <translation id="6308937455967653460">Зберегти посиланн&amp;я як...</translation>
@@ -4524,7 +4520,6 @@
 <translation id="7339785458027436441">Перевіряти правопис під час вводу</translation>
 <translation id="7339898014177206373">Нове вікно</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> зараз у повноекранному режимі.</translation>
-<translation id="7341982465543599097">дуже коротко</translation>
 <translation id="734303607351427494">Керувати пошуковими системами...</translation>
 <translation id="7343116142376328522">Заборонити всім сайтам генерувати ключі у формах (рекомендується)</translation>
 <translation id="7345706641791090287">Підтвердьте пароль</translation>
@@ -4909,7 +4904,6 @@
 <translation id="7881969471599061635">Вимкнути субтитри</translation>
 <translation id="7884988936047469945">Експериментальні спеціальні можливості</translation>
 <translation id="7885253890047913815">Останні місця призначення</translation>
-<translation id="7885283703487484916">дуже коротко</translation>
 <translation id="7887192723714330082">Реагувати на команду "Ok Google", коли екран увімкнено та розблоковано</translation>
 <translation id="7887334752153342268">Створити копію</translation>
 <translation id="7887864092952184874">Підключено мишу Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index 96dbf29..30622cc1 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">Hiển thị bộ đếm lượng dữ liệu trong hộp thoại Xóa dữ liệu duyệt web.</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />Đăng nhập<ph name="END_SIGN_IN_LINK" /> để kiểm soát và xem các trang web mà người này truy cập.</translation>
 <translation id="1097658378307015415">Trước khi đăng nhập, vui lòng đăng nhập với tư cách khách để kích hoạt mạng <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">lâu</translation>
 <translation id="1104652314727136854">Cho phép tích hợp hệ điều hành của các liên kết tệp cho Ứng dụng Chrome.</translation>
 <translation id="1105162038795579389">"<ph name="BUNDLE_NAME" />" thêm các ứng dụng và tiện ích này cho <ph name="USER_NAME" />:</translation>
 <translation id="1108600514891325577">&amp;Dừng</translation>
@@ -1874,7 +1873,6 @@
 <translation id="3512284449647229026">Những trang không tải được khi trình duyệt ngoại tuyến sẽ chỉ tự động được tải lại nếu tab hiển thị.</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{Hủy tải xuống}other{Hủy tải xuống}}</translation>
 <translation id="3512810056947640266">URL (tùy chọn):</translation>
-<translation id="351486934407749662">rất lâu</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" /> muốn chia sẻ nội dung trên màn hình của bạn. Chọn nội dung bạn muốn chia sẻ.</translation>
 <translation id="3518086201899641494">Thông báo về cổng phát hiện</translation>
 <translation id="3519867315646775981">Chuyển ngữ (shalom ← שלום)</translation>
@@ -3409,7 +3407,6 @@
 <translation id="569109051430110155">Tự động phát hiện</translation>
 <translation id="5691596662111998220">Rất tiếc, <ph name="FILE_NAME" /> không tồn tại nữa.</translation>
 <translation id="5694501201003948907">Đang nén $1 mục...</translation>
-<translation id="5695323626817702678">ngắn</translation>
 <translation id="5697118958262594262">Phát hiện nội dung quan trọng theo mặc định</translation>
 <translation id="5699533844376998780">Đã thêm tiện ích "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="5701101281789450335">Cài đặt ngôn ngữ và nhập liệu...</translation>
@@ -3834,7 +3831,6 @@
 <translation id="630065524203833229">T&amp;hoát</translation>
 <translation id="6304217058163308077">Hệ thống ứng dụng dấu trang mới</translation>
 <translation id="6305012486838822927">Bàn phím tiếng Lào</translation>
-<translation id="6305328361606238230">Nhận thông báo đẩy</translation>
 <translation id="6307722552931206656">Máy chủ định danh của Google - <ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">Hệ thống đang bận</translation>
 <translation id="6308937455967653460">Lưu liên &amp;kết thành...</translation>
@@ -4530,7 +4526,6 @@
 <translation id="7339785458027436441">Kiểm tra Chính tả Trong khi Nhập</translation>
 <translation id="7339898014177206373">Cửa sổ mới</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> hiện ở chế độ toàn màn hình.</translation>
-<translation id="7341982465543599097">rất ngắn</translation>
 <translation id="734303607351427494">Quản lý công cụ tìm kiếm...</translation>
 <translation id="7343116142376328522">Không cho phép bất kỳ trang web nào sử dụng tính năng tạo khóa trong biểu mẫu (được khuyến nghị)</translation>
 <translation id="7345706641791090287">Xác nhận mật khẩu của bạn</translation>
@@ -4915,7 +4910,6 @@
 <translation id="7881969471599061635">Tắt phụ đề</translation>
 <translation id="7884988936047469945">Tính năng trợ năng thử nghiệm</translation>
 <translation id="7885253890047913815">Máy in đích gần đây</translation>
-<translation id="7885283703487484916">rất ngắn</translation>
 <translation id="7887192723714330082">Phải hồi "Ok Google" khi màn hình được bật và mở khóa</translation>
 <translation id="7887334752153342268">Nhân đôi</translation>
 <translation id="7887864092952184874">Đã ghép nối chuột Bluetooth</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index c222466b..6a873ef 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">在“清除浏览数据”对话框中显示数据量计数器。</translation>
 <translation id="1097507499312291972">需<ph name="BEGIN_SIGN_IN_LINK" />登录<ph name="END_SIGN_IN_LINK" />才能控制和查看此用户访问的网站。</translation>
 <translation id="1097658378307015415">登录前,请先以访客身份进入,以便激活“<ph name="NETWORK_ID" />”网络。</translation>
-<translation id="1104054824888299003">长</translation>
 <translation id="1104652314727136854">启用在操作系统中集成Chrome应用文件关联。</translation>
 <translation id="1105162038795579389">“<ph name="BUNDLE_NAME" />”将为<ph name="USER_NAME" />添加以下应用和扩展程序:</translation>
 <translation id="1108600514891325577">停止(&amp;S)</translation>
@@ -1865,7 +1864,6 @@
 <translation id="3512284449647229026">如有网页在浏览器处于离线状态时未能成功加载,则只自动重新加载其标签页处于可见状态的网页。</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{取消下载}other{取消下载}}</translation>
 <translation id="3512810056947640266">网址(可选):</translation>
-<translation id="351486934407749662">很长</translation>
 <translation id="3517839692979918726"><ph name="APP_NAME" />想要共享您屏幕上的内容。请选择您要共享的内容。</translation>
 <translation id="3518086201899641494">关于强制门户的通知</translation>
 <translation id="3519867315646775981">音译(shalom ← שלום)</translation>
@@ -3387,7 +3385,6 @@
 <translation id="569109051430110155">自动检测</translation>
 <translation id="5691596662111998220">糟糕,<ph name="FILE_NAME" />已经不存在了。</translation>
 <translation id="5694501201003948907">正在压缩$1项内容…</translation>
-<translation id="5695323626817702678">短</translation>
 <translation id="5697118958262594262">默认情况下检测重要内容</translation>
 <translation id="5699533844376998780">扩展程序“<ph name="EXTENSION_NAME" />”已添加完毕。</translation>
 <translation id="5701101281789450335">语言和输入设置...</translation>
@@ -3810,7 +3807,6 @@
 <translation id="630065524203833229">退出(&amp;X)</translation>
 <translation id="6304217058163308077">新的书签应用系统</translation>
 <translation id="6305012486838822927">老挝语键盘</translation>
-<translation id="6305328361606238230">接收推送消息</translation>
 <translation id="6307722552931206656">Google 域名服务器 - <ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">系统繁忙</translation>
 <translation id="6308937455967653460">链接另存为(&amp;K)...</translation>
@@ -4503,7 +4499,6 @@
 <translation id="7339785458027436441">键入内容时检查拼写</translation>
 <translation id="7339898014177206373">打开新的窗口</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> 现处于全屏模式。</translation>
-<translation id="7341982465543599097">极短</translation>
 <translation id="734303607351427494">管理搜索引擎...</translation>
 <translation id="7343116142376328522">不允许任何网站在表单中使用密钥生成功能(推荐)</translation>
 <translation id="7345706641791090287">确认您的密码</translation>
@@ -4879,7 +4874,6 @@
 <translation id="7881969471599061635">停用字幕</translation>
 <translation id="7884988936047469945">实验性无障碍功能</translation>
 <translation id="7885253890047913815">近期使用过的目标打印机</translation>
-<translation id="7885283703487484916">很短</translation>
 <translation id="7887192723714330082">当屏幕处于开启状态并且未锁定时,对“Ok Google”做出回应</translation>
 <translation id="7887334752153342268">复制</translation>
 <translation id="7887864092952184874">蓝牙鼠标已配对</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index b740c2c9..74d63e4 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -72,7 +72,6 @@
 <translation id="1097091804514346906">在「清除瀏覽資料」對話方塊中顯示資料量計數器。</translation>
 <translation id="1097507499312291972"><ph name="BEGIN_SIGN_IN_LINK" />登入<ph name="END_SIGN_IN_LINK" />即可控制及檢視這個使用者所造訪的網站。</translation>
 <translation id="1097658378307015415">請在登入前以訪客身分進入,啟用網路 <ph name="NETWORK_ID" /></translation>
-<translation id="1104054824888299003">長</translation>
 <translation id="1104652314727136854">針對 Chrome 應用程式檔案關聯,啟用作業系統整合。</translation>
 <translation id="1105162038795579389">「<ph name="BUNDLE_NAME" />」會為<ph name="USER_NAME" />新增下列應用程式和擴充功能:</translation>
 <translation id="1108600514891325577">停止(&amp;S)</translation>
@@ -1871,7 +1870,6 @@
 <translation id="3512284449647229026">如果網頁在瀏覽器離線時載入失敗,系統只會在分頁顯示情況下自動重新載入網頁。</translation>
 <translation id="3512410469020716447">{NUM_DOWNLOAD,plural, =1{取消一項下載作業}other{取消多項下載作業}}</translation>
 <translation id="3512810056947640266">網址 (選填):</translation>
-<translation id="351486934407749662">很長</translation>
 <translation id="3517839692979918726">「<ph name="APP_NAME" />」要求分享您的螢幕內容,請選擇您要分享的內容類型。</translation>
 <translation id="3518086201899641494">認證網頁通知</translation>
 <translation id="3519867315646775981">音譯 (shalom ← שלום)</translation>
@@ -3400,7 +3398,6 @@
 <translation id="569109051430110155">自動偵測</translation>
 <translation id="5691596662111998220">糟糕!「<ph name="FILE_NAME" />」已不存在。</translation>
 <translation id="5694501201003948907">正在壓縮 $1 個項目...</translation>
-<translation id="5695323626817702678">短</translation>
 <translation id="5697118958262594262">預設偵測重要內容</translation>
 <translation id="5699533844376998780">已安裝「<ph name="EXTENSION_NAME" />」擴充功能。</translation>
 <translation id="5701101281789450335">語言和輸入設定...</translation>
@@ -3823,7 +3820,6 @@
 <translation id="630065524203833229">結束(&amp;X)</translation>
 <translation id="6304217058163308077">新版書籤應用程式系統</translation>
 <translation id="6305012486838822927">寮文鍵盤</translation>
-<translation id="6305328361606238230">接收推送訊息</translation>
 <translation id="6307722552931206656">Google 名稱伺服器 - <ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation>
 <translation id="6307990684951724544">系統忙碌中</translation>
 <translation id="6308937455967653460">另存連結為(&amp;K)...</translation>
@@ -4516,7 +4512,6 @@
 <translation id="7339785458027436441">輸入時檢查拼字</translation>
 <translation id="7339898014177206373">新視窗</translation>
 <translation id="7340431621085453413"><ph name="FULLSCREEN_ORIGIN" /> 已顯示為全螢幕。</translation>
-<translation id="7341982465543599097">極短</translation>
 <translation id="734303607351427494">管理搜尋引擎...</translation>
 <translation id="7343116142376328522">不允許任何網站在表單中使用金鑰產生功能 (建議)</translation>
 <translation id="7345706641791090287">確認您的密碼</translation>
@@ -4898,7 +4893,6 @@
 <translation id="7881969471599061635">停用字幕</translation>
 <translation id="7884988936047469945">實驗性協助工具功能</translation>
 <translation id="7885253890047913815">最近用過的印表機</translation>
-<translation id="7885283703487484916">很短</translation>
 <translation id="7887192723714330082">螢幕開啟且已解鎖時回應「Ok Google」</translation>
 <translation id="7887334752153342268">複製</translation>
 <translation id="7887864092952184874">已配對藍牙滑鼠</translation>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index d7d915a..6364578 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2015,6 +2015,9 @@
      IDS_FLAGS_FILES_QUICK_VIEW_DESCRIPTION, kOsCrOS,
      ENABLE_DISABLE_VALUE_TYPE(chromeos::switches::kEnableFilesQuickView,
                                chromeos::switches::kDisableFilesQuickView)},
+    {"quick-unlock-pin", IDS_FLAGS_QUICK_UNLOCK_PIN,
+     IDS_FLAGS_QUICK_UNLOCK_PIN_DESCRIPTION, kOsCrOS,
+     FEATURE_VALUE_TYPE(features::kQuickUnlockPin)},
 #endif  // defined(OS_CHROMEOS)
 #if defined(OS_ANDROID)
     {"multi-instance-merge-tabs", IDS_FLAGS_MULTI_INSTANCE_MERGE_TABS_NAME,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 7c02d44..d6acdcc 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "chrome/common/chrome_features.h"
 #include "components/offline_pages/offline_page_feature.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 #include "content/public/common/content_features.h"
 #include "jni/ChromeFeatureList_jni.h"
 
@@ -47,6 +48,7 @@
     &offline_pages::kOfflinePagesBackgroundLoadingFeature,
     &offline_pages::kOfflinePagesCTFeature,  // See crbug.com/620421.
     &offline_pages::kOfflinePagesSharingFeature,
+    &password_manager::features::kViewPasswords,
 };
 
 }  // namespace
diff --git a/chrome/browser/android/cookies/cookies_fetcher.cc b/chrome/browser/android/cookies/cookies_fetcher.cc
index e21dabc..b795c44 100644
--- a/chrome/browser/android/cookies/cookies_fetcher.cc
+++ b/chrome/browser/android/cookies/cookies_fetcher.cc
@@ -157,16 +157,17 @@
   scoped_refptr<net::URLRequestContextGetter> getter(
       profile->GetRequestContext());
 
-  net::CanonicalCookie cookie(
-      GURL(), base::android::ConvertJavaStringToUTF8(env, name),
+  net::CanonicalCookie cookie(*net::CanonicalCookie::Create(
+      base::android::ConvertJavaStringToUTF8(env, name),
       base::android::ConvertJavaStringToUTF8(env, value),
       base::android::ConvertJavaStringToUTF8(env, domain),
       base::android::ConvertJavaStringToUTF8(env, path),
       base::Time::FromInternalValue(creation),
       base::Time::FromInternalValue(expiration),
-      base::Time::FromInternalValue(last_access), secure, httponly,
+      base::Time::FromInternalValue(last_access),
+      secure, httponly,
       static_cast<net::CookieSameSite>(same_site),
-      static_cast<net::CookiePriority>(priority));
+      static_cast<net::CookiePriority>(priority)));
 
   // The rest must be done from the IO thread.
   content::BrowserThread::PostTask(
diff --git a/chrome/browser/android/offline_pages/offline_page_bridge.cc b/chrome/browser/android/offline_pages/offline_page_bridge.cc
index c6b912f..68aabbad7 100644
--- a/chrome/browser/android/offline_pages/offline_page_bridge.cc
+++ b/chrome/browser/android/offline_pages/offline_page_bridge.cc
@@ -41,6 +41,7 @@
 namespace {
 
 const char kOfflinePageBridgeKey[] = "offline-page-bridge";
+const bool kUserRequested = true;
 
 void ToJavaOfflinePageList(JNIEnv* env,
                            jobject j_result_obj,
@@ -371,7 +372,7 @@
           GetForBrowserContext(browser_context_);
 
   coordinator->SavePageLater(
-      GURL(ConvertJavaStringToUTF8(env, j_url)), client_id);
+      GURL(ConvertJavaStringToUTF8(env, j_url)), client_id, kUserRequested);
 }
 
 void OfflinePageBridge::DeletePages(
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
index ca9f158..c85f384 100644
--- a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
+++ b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
@@ -26,6 +26,7 @@
 const GURL kHttpUrl("http://tunafish.com");
 const GURL kFileUrl("file://sailfish.png");
 const ClientId kClientId("AsyncLoading", "88");
+const bool kUserRequested = true;
 
 // Mock Loader for testing the Offliner calls.
 class MockPrerenderingLoader : public PrerenderingLoader {
@@ -199,14 +200,16 @@
 
 TEST_F(PrerenderingOfflinerTest, LoadAndSaveBadUrl) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kFileUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kFileUrl, kClientId, creation_time, kUserRequested);
   EXPECT_FALSE(offliner()->LoadAndSave(request, callback()));
   EXPECT_TRUE(loader()->IsIdle());
 }
 
 TEST_F(PrerenderingOfflinerTest, LoadAndSavePrerenderingDisabled) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   loader()->DisablePrerendering();
   EXPECT_FALSE(offliner()->LoadAndSave(request, callback()));
   EXPECT_TRUE(loader()->IsIdle());
@@ -214,7 +217,8 @@
 
 TEST_F(PrerenderingOfflinerTest, LoadAndSaveLoadStartedButFails) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
   EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
@@ -229,7 +233,8 @@
 
 TEST_F(PrerenderingOfflinerTest, CancelWhenLoading) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
 
@@ -239,7 +244,8 @@
 
 TEST_F(PrerenderingOfflinerTest, CancelWhenLoaded) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
   EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
@@ -267,7 +273,8 @@
 
 TEST_F(PrerenderingOfflinerTest, LoadAndSaveLoadedButSaveFails) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
   EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
@@ -288,7 +295,8 @@
 
 TEST_F(PrerenderingOfflinerTest, LoadAndSaveSuccessful) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
   EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
@@ -309,7 +317,8 @@
 
 TEST_F(PrerenderingOfflinerTest, LoadAndSaveLoadedButThenCanceledFromLoader) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
   EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status());
@@ -333,7 +342,8 @@
   offliner()->SetLowEndDeviceForTesting(true);
 
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
 
@@ -349,7 +359,8 @@
   offliner()->SetLowEndDeviceForTesting(false);
 
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kHttpUrl, kClientId, creation_time, kUserRequested);
   EXPECT_TRUE(offliner()->LoadAndSave(request, callback()));
   EXPECT_FALSE(loader()->IsIdle());
 
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc
index e7c04dc4..cc3e366d 100644
--- a/chrome/browser/android/preferences/pref_service_bridge.cc
+++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -1005,13 +1005,6 @@
               : chrome_browser_net::NETWORK_PREDICTION_NEVER);
 }
 
-static jboolean ObsoleteNetworkPredictionEnabledHasUserSetting(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj) {
-  return GetPrefService()->GetUserPrefValue(
-      prefs::kNetworkPredictionEnabled) != NULL;
-}
-
 static jboolean ObsoleteNetworkPredictionOptionsHasUserSetting(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
@@ -1019,17 +1012,6 @@
       prefs::kNetworkPredictionOptions) != NULL;
 }
 
-static jboolean ObsoleteGetNetworkPredictionEnabledUserPrefValue(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj) {
-  const base::Value* network_prediction_enabled =
-      GetPrefService()->GetUserPrefValue(prefs::kNetworkPredictionEnabled);
-  DCHECK(network_prediction_enabled);
-  bool value = false;
-  DCHECK(network_prediction_enabled->GetAsBoolean(&value));
-  return value;
-}
-
 static void SetResolveNavigationErrorEnabled(JNIEnv* env,
                                              const JavaParamRef<jobject>& obj,
                                              jboolean enabled) {
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
index fd92c2d1..b4608666 100644
--- a/chrome/browser/android/preferences/website_preference_bridge.cc
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -14,6 +14,8 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "chrome/browser/android/preferences/important_sites_util.h"
@@ -30,6 +32,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/storage/storage_info_fetcher.h"
+#include "chrome/browser/usb/usb_chooser_context.h"
+#include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/browser_thread.h"
@@ -433,6 +437,59 @@
   return pattern.Matches(GURL(ConvertJavaStringToUTF8(env, jurl)));
 }
 
+static void GetUsbOrigins(JNIEnv* env,
+                          const JavaParamRef<jclass>& clazz,
+                          const JavaParamRef<jobject>& list) {
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  UsbChooserContext* context = UsbChooserContextFactory::GetForProfile(profile);
+  for (const auto& object : context->GetAllGrantedObjects()) {
+    // Remove the trailing slash so that origins are matched correctly in
+    // SingleWebsitePreferences.mergePermissionInfoForTopLevelOrigin.
+    std::string origin = object->requesting_origin.spec();
+    DCHECK_EQ('/', origin.back());
+    origin.pop_back();
+    ScopedJavaLocalRef<jstring> jorigin = ConvertUTF8ToJavaString(env, origin);
+
+    std::string embedder = object->requesting_origin.spec();
+    DCHECK_EQ('/', embedder.back());
+    embedder.pop_back();
+    ScopedJavaLocalRef<jstring> jembedder =
+        ConvertUTF8ToJavaString(env, embedder);
+
+    std::string name;
+    bool found = object->object.GetString("name", &name);
+    DCHECK(found);
+    ScopedJavaLocalRef<jstring> jname = ConvertUTF8ToJavaString(env, name);
+
+    std::string serialized;
+    bool written = base::JSONWriter::Write(object->object, &serialized);
+    DCHECK(written);
+    ScopedJavaLocalRef<jstring> jserialized =
+        ConvertUTF8ToJavaString(env, serialized);
+
+    Java_WebsitePreferenceBridge_insertUsbInfoIntoList(
+        env, list, jorigin.obj(), jembedder.obj(), jname.obj(),
+        jserialized.obj());
+  }
+}
+
+static void RevokeUsbPermission(JNIEnv* env,
+                                const JavaParamRef<jclass>& clazz,
+                                const JavaParamRef<jstring>& jorigin,
+                                const JavaParamRef<jstring>& jembedder,
+                                const JavaParamRef<jstring>& jobject) {
+  Profile* profile = ProfileManager::GetActiveUserProfile();
+  UsbChooserContext* context = UsbChooserContextFactory::GetForProfile(profile);
+  GURL origin(ConvertJavaStringToUTF8(env, jorigin));
+  DCHECK(origin.is_valid());
+  GURL embedder(ConvertJavaStringToUTF8(env, jembedder));
+  DCHECK(embedder.is_valid());
+  std::unique_ptr<base::DictionaryValue> object = base::DictionaryValue::From(
+      base::JSONReader::Read(ConvertJavaStringToUTF8(env, jobject)));
+  DCHECK(object);
+  context->RevokeObjectPermission(origin, embedder, *object);
+}
+
 namespace {
 
 class SiteDataDeleteHelper :
@@ -621,7 +678,7 @@
                     registerable_domain) != important_domains.end()) {
         important = true;
       }
-      // Remove the trailing backslash so the origin is matched correctly in
+      // Remove the trailing slash so the origin is matched correctly in
       // SingleWebsitePreferences.mergePermissionInfoForTopLevelOrigin.
       DCHECK_EQ('/', origin_str.back());
       origin_str.pop_back();
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index c4c035c3..d92f382b 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -380,6 +380,7 @@
     const BrowsingDataFilterBuilder& filter_builder,
     int origin_type_mask) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  waiting_for_synchronous_clear_operations_ = true;
 
   // crbug.com/140910: Many places were calling this with base::Time() as
   // delete_end, even though they should've used base::Time::Max().
@@ -1040,6 +1041,7 @@
   }
 
   // Notify in case all actions taken were synchronous.
+  waiting_for_synchronous_clear_operations_ = false;
   NotifyIfDone();
 
   UMA_HISTOGRAM_ENUMERATION(
@@ -1086,7 +1088,8 @@
 }
 
 bool BrowsingDataRemover::AllDone() {
-  return !waiting_for_clear_autofill_origin_urls_ &&
+  return !waiting_for_synchronous_clear_operations_ &&
+         !waiting_for_clear_autofill_origin_urls_ &&
          !waiting_for_clear_cache_ &&
          !waiting_for_clear_flash_content_licenses_ &&
          !waiting_for_clear_channel_ids_ && !waiting_for_clear_cookies_count_ &&
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h
index a77bc5d..52b67d6 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.h
+++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -453,6 +453,7 @@
   uint32_t deauthorize_flash_content_licenses_request_id_ = 0;
   // True if we're waiting for various data to be deleted.
   // These may only be accessed from UI thread in order to avoid races!
+  bool waiting_for_synchronous_clear_operations_ = false;
   bool waiting_for_clear_autofill_origin_urls_ = false;
   bool waiting_for_clear_cache_ = false;
   bool waiting_for_clear_channel_ids_ = false;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 0e43db3d1..1166a7f 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -59,6 +59,7 @@
 #include "chrome/browser/component_updater/widevine_cdm_component_installer.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/geolocation/chrome_access_token_store.h"
 #include "chrome/browser/gpu/gl_string_manager.h"
 #include "chrome/browser/gpu/three_d_api_observer.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
@@ -140,6 +141,8 @@
 #include "components/variations/variations_switches.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/geolocation_provider.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
@@ -270,6 +273,19 @@
 
 namespace {
 
+// A provider of Geolocation services to override AccessTokenStore.
+class ChromeGeolocationDelegate : public content::GeolocationDelegate {
+ public:
+  ChromeGeolocationDelegate() = default;
+
+  scoped_refptr<content::AccessTokenStore> CreateAccessTokenStore() final {
+    return new ChromeAccessTokenStore();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChromeGeolocationDelegate);
+};
+
 // This function provides some ways to test crash and assertion handling
 // behavior of the program.
 void HandleTestParameters(const base::CommandLine& command_line) {
@@ -1201,6 +1217,9 @@
   // ChromeOS needs ResourceBundle::InitSharedInstance to be called before this.
   browser_process_->PreCreateThreads();
 
+  content::GeolocationProvider::SetGeolocationDelegate(
+      new ChromeGeolocationDelegate());
+
   return content::RESULT_CODE_NORMAL_EXIT;
 }
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index b72dcd8..8a3866c0 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -48,7 +48,6 @@
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/engagement/site_engagement_eviction_policy.h"
 #include "chrome/browser/font_family_cache.h"
-#include "chrome/browser/geolocation/chrome_access_token_store.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h"
 #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h"
@@ -146,7 +145,6 @@
 #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/geolocation_delegate.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -333,7 +331,6 @@
 
 using base::FileDescriptor;
 using blink::WebWindowFeatures;
-using content::AccessTokenStore;
 using content::BrowserThread;
 using content::BrowserURLHandler;
 using content::ChildProcessSecurityPolicy;
@@ -639,19 +636,6 @@
       safe_browsing_ui_manager_;
 };
 
-// A provider of Geolocation services to override AccessTokenStore.
-class ChromeGeolocationDelegate : public content::GeolocationDelegate {
- public:
-  ChromeGeolocationDelegate() = default;
-
-  scoped_refptr<AccessTokenStore> CreateAccessTokenStore() final {
-    return new ChromeAccessTokenStore();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChromeGeolocationDelegate);
-};
-
 #if BUILDFLAG(ANDROID_JAVA_UI)
 void HandleSingleTabModeBlockOnUIThread(const BlockedWindowParams& params) {
   WebContents* web_contents = tab_util::GetWebContentsByFrameID(
@@ -2313,11 +2297,6 @@
   return g_browser_process->net_log();
 }
 
-content::GeolocationDelegate*
-ChromeContentBrowserClient::CreateGeolocationDelegate() {
-  return new ChromeGeolocationDelegate();
-}
-
 bool ChromeContentBrowserClient::IsFastShutdownPossible() {
   return true;
 }
@@ -2964,7 +2943,8 @@
     // Add interstitial page while merge session process (cookie reconstruction
     // from OAuth2 refresh token in ChromeOS login) is still in progress while
     // we are attempting to load a google property.
-    if (!merge_session_throttling_utils::AreAllSessionMergedAlready() &&
+    if (merge_session_throttling_utils::ShouldAttachNavigationThrottle() &&
+        !merge_session_throttling_utils::AreAllSessionMergedAlready() &&
         handle->GetURL().SchemeIsHTTPOrHTTPS()) {
       throttles.push_back(MergeSessionNavigationThrottle::Create(handle));
     }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 88329e96..ae3be770 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -211,8 +211,6 @@
   CreateSpeechRecognitionManagerDelegate() override;
   net::NetLog* GetNetLog() override;
 
-  content::GeolocationDelegate* CreateGeolocationDelegate() override;
-
   bool IsFastShutdownPossible() override;
   void OverrideWebkitPrefs(content::RenderViewHost* rvh,
                            content::WebPreferences* prefs) override;
diff --git a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
index 93131e18..0275bb7 100644
--- a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
+++ b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
@@ -16,6 +16,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "ui/base/page_transition_types.h"
 
 namespace arc {
 
@@ -63,8 +64,22 @@
 content::NavigationThrottle::ThrottleCheckResult
 ArcNavigationThrottle::WillStartRequest() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (!navigation_handle()->HasUserGesture())
+
+  const ui::PageTransition transition =
+      navigation_handle()->GetPageTransition();
+
+  if (!ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK)) {
+    // If this navigation event wasn't spawned by the user clicking on a link.
     return content::NavigationThrottle::PROCEED;
+  }
+
+  if (ui::PageTransitionGetQualifier(transition) != 0) {
+    // Qualifiers indicate that this navigation was the result of a click on a
+    // forward/back button, or a redirect, or typing in the URL bar, etc.  Don't
+    // pass any of those types of navigations to the intent helper (see
+    // crbug.com/630072).
+    return content::NavigationThrottle::PROCEED;
+  }
 
   if (!ShouldOverrideUrlLoading(navigation_handle()))
     return content::NavigationThrottle::PROCEED;
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
index f527ea2e..d5cf655 100644
--- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -7,10 +7,10 @@
 #include "chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h"
 
 #include "base/bind.h"
-
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h"
 #include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
 #include "chrome/browser/extensions/extension_api_unittest.h"
@@ -62,6 +62,8 @@
   void SetUp() override {
     ExtensionApiUnittest::SetUp();
 
+    EnableQuickUnlockForTesting();
+
     // Setup a primary user.
     auto test_account = AccountId::FromUserEmail(kTestUserEmail);
     fake_user_manager_->AddUser(test_account);
diff --git a/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc b/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc
index 2030a63e..25abdaf2 100644
--- a/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc
+++ b/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc
@@ -6,6 +6,7 @@
 
 #include "base/base64.h"
 #include "base/strings/string_util.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/login/auth/key.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -104,8 +105,13 @@
 }
 
 bool PinStorage::IsPinAuthenticationAvailable() const {
-  return IsPinSet() && unlock_attempt_count() < kMaximumUnlockAttempts &&
-         HasStrongAuth() && TimeSinceLastStrongAuth() < kStrongAuthTimeout;
+  const bool exceeded_unlock_attempts =
+      unlock_attempt_count() >= kMaximumUnlockAttempts;
+  const bool has_strong_auth =
+      HasStrongAuth() && TimeSinceLastStrongAuth() < kStrongAuthTimeout;
+
+  return IsQuickUnlockEnabled() && IsPinSet() && has_strong_auth &&
+         !exceeded_unlock_attempts;
 }
 
 bool PinStorage::TryAuthenticatePin(const std::string& pin) {
diff --git a/chrome/browser/chromeos/login/quick_unlock/pin_storage.h b/chrome/browser/chromeos/login/quick_unlock/pin_storage.h
index bcabe56..f9fe72a 100644
--- a/chrome/browser/chromeos/login/quick_unlock/pin_storage.h
+++ b/chrome/browser/chromeos/login/quick_unlock/pin_storage.h
@@ -21,11 +21,6 @@
 
 namespace chromeos {
 
-// TODO(jdufault): Figure out the UX we want on the lock screen when there are
-// multiple users. We will be storing either global or per-user unlock state. If
-// we end up storing global unlock state, we can pull the unlock attempt and
-// strong-auth code out of this class.
-
 class PinStorage : public KeyedService {
  public:
   // TODO(jdufault): Pull these values in from policy. See crbug.com/612271.
diff --git a/chrome/browser/chromeos/login/quick_unlock/pin_storage_unittest.cc b/chrome/browser/chromeos/login/quick_unlock/pin_storage_unittest.cc
index 7b71933..62218bf 100644
--- a/chrome/browser/chromeos/login/quick_unlock/pin_storage_unittest.cc
+++ b/chrome/browser/chromeos/login/quick_unlock/pin_storage_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h"
 #include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h"
-
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
@@ -15,6 +15,10 @@
 class PinStorageUnitTest : public testing::Test {
  protected:
   PinStorageUnitTest() : profile_(new TestingProfile()) {}
+  ~PinStorageUnitTest() override {}
+
+  // testing::Test:
+  void SetUp() override { chromeos::EnableQuickUnlockForTesting(); }
 
   std::unique_ptr<TestingProfile> profile_;
 
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc
new file mode 100644
index 0000000..ff7c536
--- /dev/null
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc
@@ -0,0 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/common/chrome_features.h"
+
+namespace chromeos {
+
+namespace {
+bool enable_for_testing_ = false;
+}  // namespace
+
+bool IsQuickUnlockEnabled() {
+  if (enable_for_testing_)
+    return true;
+
+  // TODO(jdufault): Implement a proper policy check. For now, just disable if
+  // the device is enterprise enrolled. See crbug.com/612271.
+  if (g_browser_process->platform_part()
+          ->browser_policy_connector_chromeos()
+          ->IsEnterpriseManaged()) {
+    return false;
+  }
+
+  // Enable quick unlock only if the switch is present.
+  return base::FeatureList::IsEnabled(features::kQuickUnlockPin);
+}
+
+void EnableQuickUnlockForTesting() {
+  enable_for_testing_ = true;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h
new file mode 100644
index 0000000..c7666c5
--- /dev/null
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_UTILS_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_UTILS_H_
+
+namespace chromeos {
+
+// Returns true if quick unlock is allowed by policy and the feature flag is
+// present.
+bool IsQuickUnlockEnabled();
+
+// Forcibly enable quick-unlock for testing.
+void EnableQuickUnlockForTesting();
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_UTILS_H_
diff --git a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
index 621ad5a0..182474e 100644
--- a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
+++ b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
@@ -63,6 +63,10 @@
 
 }  // namespace
 
+bool ShouldAttachNavigationThrottle() {
+  return user_manager::UserManager::IsInitialized();
+}
+
 bool AreAllSessionMergedAlready() {
   return !base::AtomicRefCountIsZero(&g_all_profiles_restored_);
 }
diff --git a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.h b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.h
index f3d0fd4..e1227da 100644
--- a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.h
+++ b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.h
@@ -25,6 +25,11 @@
 // page load.
 using CompletionCallback = base::Closure;
 
+// Policy for when it is valid to attach a MergeSessionNavigationThrottle.
+// Namely, this will be false for unit tests, where the UserManager is not
+// initialized.
+bool ShouldAttachNavigationThrottle();
+
 // Checks if session is already merged. This is safe to call on all threads.
 bool AreAllSessionMergedAlready();
 
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index 2199b54..beae3eb 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -56,6 +56,7 @@
 const char kNoRequisition[] = "none";
 const char kRemoraRequisition[] = "remora";
 const char kSharkRequisition[] = "shark";
+const char kRialtoRequisition[] = "rialto";
 
 // Zero-touch enrollment flag values.
 const char kZeroTouchEnrollmentForced[] = "forced";
@@ -323,7 +324,8 @@
       local_state_->SetString(prefs::kDeviceEnrollmentRequisition,
                               requisition);
       if (requisition == kRemoraRequisition ||
-          requisition == kSharkRequisition) {
+          requisition == kSharkRequisition ||
+          requisition == kRialtoRequisition) {
         SetDeviceEnrollmentAutoStart();
       } else {
         local_state_->SetBoolean(
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
index 4903d8e7..4f7aec6 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
@@ -143,13 +143,14 @@
 void DeviceLocalAccountPolicyServiceTestBase::SetUp() {
   chromeos::DeviceSettingsTestBase::SetUp();
 
-  expected_policy_map_.Set(key::kDisableSpdy, POLICY_LEVEL_MANDATORY,
+  expected_policy_map_.Set(key::kSearchSuggestEnabled, POLICY_LEVEL_MANDATORY,
                            POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                            base::WrapUnique(new base::FundamentalValue(true)),
                            nullptr);
 
-  device_local_account_policy_.payload().mutable_disablespdy()->set_value(
-      true);
+  device_local_account_policy_.payload()
+      .mutable_searchsuggestenabled()
+      ->set_value(true);
   device_local_account_policy_.policy_data().set_policy_type(
       dm_protocol::kChromePublicAccountPolicyType);
 }
@@ -872,8 +873,9 @@
   // Policy change should be reported.
   EXPECT_CALL(provider_observer_, OnUpdatePolicy(provider_.get()))
       .Times(AtLeast(1));
-  device_local_account_policy_.payload().mutable_disablespdy()->set_value(
-      false);
+  device_local_account_policy_.payload()
+      .mutable_searchsuggestenabled()
+      ->set_value(false);
   InstallDeviceLocalAccountPolicy(kAccount1);
   DeviceLocalAccountPolicyBroker* broker =
       service_->GetBrokerForUser(account_1_user_id_);
@@ -884,8 +886,8 @@
 
   expected_policy_bundle
       .Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
-      .Set(key::kDisableSpdy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-           POLICY_SOURCE_CLOUD,
+      .Set(key::kSearchSuggestEnabled, POLICY_LEVEL_MANDATORY,
+           POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
            base::WrapUnique(new base::FundamentalValue(false)), nullptr);
   EXPECT_TRUE(expected_policy_bundle.Equals(provider_->policies()));
 
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc
index fbe243c..0c946ce 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_event_log_apitest.cc
@@ -6,7 +6,10 @@
 #include <utility>
 
 #include "base/command_line.h"
+#include "base/files/file_path_watcher.h"
 #include "base/json/json_writer.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -38,15 +41,14 @@
 namespace {
 
 // Get the expected EventLog file name. The name will be
-// <temporary path>.<render process id>.event_log.<consumer id>, for example
+// <temporary path>.<render process id>.<peer connection id>, for example
 // /tmp/.org.chromium.Chromium.vsygNQ/dnFW8ch/Default/WebRTC
-// Logs/WebRtcEventLog.1.29113.event_log.1
+// Logs/WebRtcEventLog.1.6.1
 base::FilePath GetExpectedEventLogFileName(const base::FilePath& base_file,
                                            int render_process_id) {
-  static const int kExpectedConsumerId = 1;
+  static const int kExpectedPeerConnectionId = 1;
   return base_file.AddExtension(IntToStringType(render_process_id))
-      .AddExtension(FILE_PATH_LITERAL("event_log"))
-      .AddExtension(IntToStringType(kExpectedConsumerId));
+      .AddExtension(IntToStringType(kExpectedPeerConnectionId));
 }
 
 static const char kMainWebrtcTestHtmlPage[] = "/webrtc/webrtc_jsep01_test.html";
@@ -57,6 +59,47 @@
   return parameter_string;
 }
 
+class FileWaiter : public base::RefCountedThreadSafe<FileWaiter> {
+ public:
+  explicit FileWaiter(const base::FilePath& path)
+      : found_(false), path_(path) {}
+
+  bool Start() {
+    if (base::PathExists(path_)) {
+      found_ = true;
+      return true;
+    } else {
+      return watcher_.Watch(path_, false /* recursive */,
+                            base::Bind(&FileWaiter::Callback, this));
+    }
+  }
+
+  // Returns true if |path_| became available.
+  bool WaitForFile() {
+    if (!found_) {
+      run_loop_.Run();
+    }
+    return found_;
+  }
+
+  // implements FilePathWatcher::Callback
+  void Callback(const base::FilePath& path, bool error) {
+    EXPECT_EQ(path, path_);
+    if (!error)
+      found_ = true;
+    run_loop_.Quit();
+  }
+
+ private:
+  friend class base::RefCountedThreadSafe<FileWaiter>;
+  ~FileWaiter() {}
+  base::RunLoop run_loop_;
+  bool found_;
+  base::FilePath path_;
+  base::FilePathWatcher watcher_;
+  DISALLOW_COPY_AND_ASSIGN(FileWaiter);
+};
+
 class WebrtcEventLogApiTest : public WebRtcTestBase {
  protected:
   void SetUp() override {
@@ -107,9 +150,7 @@
 
 }  // namespace
 
-// TODO(ivoc): Reenable when the event log functionality in Chrome is updated.
-IN_PROC_BROWSER_TEST_F(WebrtcEventLogApiTest,
-                       DISABLED_TestStartStopWebRtcEventLogging) {
+IN_PROC_BROWSER_TEST_F(WebrtcEventLogApiTest, TestStartStopWebRtcEventLogging) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   content::WebContents* left_tab =
@@ -178,20 +219,18 @@
   EXPECT_EQ(file_name_start, file_name_stop);
 
   // Check that the file exists and is non-empty.
-  base::ProcessId render_process_id =
-      base::GetProcId(left_tab->GetRenderProcessHost()->GetHandle());
-  EXPECT_NE(render_process_id, base::kNullProcessId);
+  content::RenderProcessHost* render_process_host =
+      left_tab->GetRenderProcessHost();
+  ASSERT_NE(render_process_host, nullptr);
+  int render_process_id = render_process_host->GetID();
   base::FilePath full_file_name =
       GetExpectedEventLogFileName(file_name_stop, render_process_id);
   int64_t file_size = 0;
-  while (!(base::PathExists(full_file_name) &&
-           base::GetFileSize(full_file_name, &file_size) && file_size > 0)) {
-    // This should normally not happen, but is here to prevent the test
-    // from becoming flaky on devices with weird timings or when the
-    // /webrtc/webrtc_jsep01_test.html changes.
-    VLOG(1) << "Waiting for logfile to become available...";
-    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
-  }
+  scoped_refptr<FileWaiter> waiter = new FileWaiter(full_file_name);
+
+  ASSERT_TRUE(waiter->Start()) << "ERROR watching for "
+                               << full_file_name.value();
+  ASSERT_TRUE(waiter->WaitForFile());
   ASSERT_TRUE(base::PathExists(full_file_name));
   EXPECT_TRUE(base::GetFileSize(full_file_name, &file_size));
   EXPECT_GT(file_size, 0);
@@ -200,9 +239,8 @@
   base::DeleteFile(full_file_name, false);
 }
 
-// TODO(ivoc): Reenable when the event log functionality in Chrome is updated.
 IN_PROC_BROWSER_TEST_F(WebrtcEventLogApiTest,
-                       DISABLED_TestStartTimedWebRtcEventLogging) {
+                       TestStartTimedWebRtcEventLogging) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   content::WebContents* left_tab =
@@ -252,20 +290,19 @@
 
   // The log has stopped automatically. Check that the file exists and is
   // non-empty.
-  base::ProcessId render_process_id =
-      base::GetProcId(left_tab->GetRenderProcessHost()->GetHandle());
-  EXPECT_NE(render_process_id, base::kNullProcessId);
+  content::RenderProcessHost* render_process_host =
+      left_tab->GetRenderProcessHost();
+  ASSERT_NE(render_process_host, nullptr);
+  int render_process_id = render_process_host->GetID();
   base::FilePath full_file_name =
       GetExpectedEventLogFileName(file_name_start, render_process_id);
   int64_t file_size = 0;
-  while (!(base::PathExists(full_file_name) &&
-           base::GetFileSize(full_file_name, &file_size) && file_size > 0)) {
-    // This should normally not happen, but is here to prevent the test
-    // from becoming flaky on devices with weird timings or when the
-    // /webrtc/webrtc_jsep01_test.html changes.
-    VLOG(1) << "Waiting for logfile to become available...";
-    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
-  }
+
+  scoped_refptr<FileWaiter> waiter = new FileWaiter(full_file_name);
+
+  ASSERT_TRUE(waiter->Start()) << "ERROR watching for "
+                               << full_file_name.value();
+  ASSERT_TRUE(waiter->WaitForFile());
   ASSERT_TRUE(base::PathExists(full_file_name));
   EXPECT_TRUE(base::GetFileSize(full_file_name, &file_size));
   EXPECT_GT(file_size, 0);
diff --git a/chrome/browser/extensions/extension_bindings_apitest.cc b/chrome/browser/extensions/extension_bindings_apitest.cc
index 387576f..5006270 100644
--- a/chrome/browser/extensions/extension_bindings_apitest.cc
+++ b/chrome/browser/extensions/extension_bindings_apitest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/net/url_request_mock_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_test_utils.h"
@@ -208,5 +209,65 @@
   EXPECT_EQ("success", result);
 }
 
+class FramesExtensionBindingsApiTest : public ExtensionBindingsApiTest {
+ public:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ExtensionBindingsApiTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kDisablePopupBlocking);
+  }
+};
+
+// This tests that web pages with iframes or child windows pointing at
+// chrome-extenison:// urls, both web_accessible and nonexistent pages, don't
+// get improper extensions bindings injected while they briefly still point at
+// about:blank and are still scriptable by their parent.
+//
+// The general idea is to load up 2 extensions, one which listens for external
+// messages ("receiver") and one which we'll try first faking messages from in
+// the web page's iframe, as well as actually send a message from later
+// ("sender").
+IN_PROC_BROWSER_TEST_F(FramesExtensionBindingsApiTest, FramesBeforeNavigation) {
+  // Load the sender and receiver extensions, and make sure they are ready.
+  ExtensionTestMessageListener sender_ready("sender_ready", true);
+  const Extension* sender = LoadExtension(
+      test_data_dir_.AppendASCII("bindings").AppendASCII("message_sender"));
+  ASSERT_NE(nullptr, sender);
+  ASSERT_TRUE(sender_ready.WaitUntilSatisfied());
+
+  ExtensionTestMessageListener receiver_ready("receiver_ready", false);
+  const Extension* receiver =
+      LoadExtension(test_data_dir_.AppendASCII("bindings")
+                        .AppendASCII("external_message_listener"));
+  ASSERT_NE(nullptr, receiver);
+  ASSERT_TRUE(receiver_ready.WaitUntilSatisfied());
+
+  // Load the web page which tries to impersonate the sender extension via
+  // scripting iframes/child windows before they finish navigating to pages
+  // within the sender extension.
+  ASSERT_TRUE(embedded_test_server()->Start());
+  ui_test_utils::NavigateToURL(
+      browser(),
+      embedded_test_server()->GetURL(
+          "/extensions/api_test/bindings/frames_before_navigation.html"));
+
+  bool page_success = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      browser()->tab_strip_model()->GetWebContentsAt(0), "getResult()",
+      &page_success));
+  EXPECT_TRUE(page_success);
+
+  // Reply to |sender|, causing it to send a message over to |receiver|, and
+  // then ask |receiver| for the total message count. It should be 1 since
+  // |receiver| should not have received any impersonated messages.
+  sender_ready.Reply(receiver->id());
+  int message_count = 0;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
+      ProcessManager::Get(profile())
+          ->GetBackgroundHostForExtension(receiver->id())
+          ->host_contents(),
+      "getMessageCountAfterReceivingRealSenderMessage()", &message_count));
+  EXPECT_EQ(1, message_count);
+}
+
 }  // namespace
 }  // namespace extensions
diff --git a/chrome/browser/memory/tab_manager.cc b/chrome/browser/memory/tab_manager.cc
index 6fa39ad..a90170d 100644
--- a/chrome/browser/memory/tab_manager.cc
+++ b/chrome/browser/memory/tab_manager.cc
@@ -617,6 +617,10 @@
       return false;
   }
 
+  // Do not discard a tab that was explicitly disallowed to.
+  if (!IsTabAutoDiscardable(web_contents))
+    return false;
+
   return true;
 }
 
@@ -728,6 +732,10 @@
   if (first.is_selected != second.is_selected)
     return first.is_selected;
 
+  // Non auto-discardable tabs are more important to protect.
+  if (first.is_auto_discardable != second.is_auto_discardable)
+    return !first.is_auto_discardable;
+
   // Protect tabs with pending form entries.
   if (first.has_form_entry != second.has_form_entry)
     return first.has_form_entry;
@@ -906,4 +914,20 @@
                     OnDiscardedStateChange(contents, is_discarded));
 }
 
+void TabManager::OnAutoDiscardableStateChange(content::WebContents* contents,
+                                              bool is_auto_discardable) {
+  FOR_EACH_OBSERVER(
+      TabManagerObserver, observers_,
+      OnAutoDiscardableStateChange(contents, is_auto_discardable));
+}
+
+bool TabManager::IsTabAutoDiscardable(content::WebContents* contents) const {
+  return GetWebContentsData(contents)->IsAutoDiscardable();
+}
+
+void TabManager::SetTabAutoDiscardableState(content::WebContents* contents,
+                                            bool state) {
+  GetWebContentsData(contents)->SetAutoDiscardableState(state);
+}
+
 }  // namespace memory
diff --git a/chrome/browser/memory/tab_manager.h b/chrome/browser/memory/tab_manager.h
index cd5c348..53793ad 100644
--- a/chrome/browser/memory/tab_manager.h
+++ b/chrome/browser/memory/tab_manager.h
@@ -128,7 +128,18 @@
   void AddObserver(TabManagerObserver* observer);
   void RemoveObserver(TabManagerObserver* observer);
 
+  // Returns the auto-discardable state of the tab. When true, the tab is
+  // eligible to be automatically discarded when critical memory pressure hits,
+  // otherwise the tab is ignored and will never be automatically discarded.
+  // Note that this property doesn't block the discarding of the tab via other
+  // methods (about:discards for instance).
+  bool IsTabAutoDiscardable(content::WebContents* contents) const;
+
+  // Sets/clears the auto-discardable state of the tab.
+  void SetTabAutoDiscardableState(content::WebContents* contents, bool state);
+
  private:
+  FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable);
   FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce);
   FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications);
   FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator);
@@ -151,6 +162,11 @@
   void OnDiscardedStateChange(content::WebContents* contents,
                               bool is_discarded);
 
+  // Called by WebContentsData whenever the auto-discardable state of a
+  // WebContents changes, so that observers can be informed.
+  void OnAutoDiscardableStateChange(content::WebContents* contents,
+                                    bool is_auto_discardable);
+
   // The time that a renderer is given to react to a memory pressure
   // notification before another renderer is also notified. This prevents all
   // renderers from receiving and acting upon notifications simultaneously,
diff --git a/chrome/browser/memory/tab_manager_browsertest.cc b/chrome/browser/memory/tab_manager_browsertest.cc
index ca5621d8..579ba31e 100644
--- a/chrome/browser/memory/tab_manager_browsertest.cc
+++ b/chrome/browser/memory/tab_manager_browsertest.cc
@@ -393,6 +393,46 @@
   EXPECT_TRUE(tab_manager->DiscardTabImpl());
 }
 
+IN_PROC_BROWSER_TEST_F(TabManagerTest, AutoDiscardable) {
+  using content::WindowedNotificationObserver;
+  TabManager* tab_manager = g_browser_process->GetTabManager();
+
+  // Disable the protection of recent tabs.
+  tab_manager->minimum_protection_time_ = base::TimeDelta::FromMinutes(0);
+
+  // Get two tabs open.
+  WindowedNotificationObserver load1(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::NotificationService::AllSources());
+  OpenURLParams open1(GURL(chrome::kChromeUIAboutURL), content::Referrer(),
+                      CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
+  browser()->OpenURL(open1);
+  load1.Wait();
+
+  WindowedNotificationObserver load2(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::NotificationService::AllSources());
+  OpenURLParams open2(GURL(chrome::kChromeUICreditsURL), content::Referrer(),
+                      NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false);
+  browser()->OpenURL(open2);
+  load2.Wait();
+
+  // Set the auto-discardable state of the first tab to false.
+  auto tsm = browser()->tab_strip_model();
+  ASSERT_EQ(2, tsm->count());
+  tab_manager->SetTabAutoDiscardableState(tsm->GetWebContentsAt(0), false);
+
+  // Shouldn't discard the tab, since auto-discardable is deactivated.
+  EXPECT_FALSE(tab_manager->DiscardTabImpl());
+
+  // Reset auto-discardable state to true.
+  tab_manager->SetTabAutoDiscardableState(tsm->GetWebContentsAt(0), true);
+
+  // Now it should be able to discard the tab.
+  EXPECT_TRUE(tab_manager->DiscardTabImpl());
+  EXPECT_TRUE(tab_manager->IsTabDiscarded(tsm->GetWebContentsAt(0)));
+}
+
 }  // namespace memory
 
 #endif  // OS_WIN || OS_MAXOSX || OS_LINUX
diff --git a/chrome/browser/memory/tab_manager_observer.cc b/chrome/browser/memory/tab_manager_observer.cc
index 7a3f8db..782a158 100644
--- a/chrome/browser/memory/tab_manager_observer.cc
+++ b/chrome/browser/memory/tab_manager_observer.cc
@@ -13,6 +13,10 @@
 void TabManagerObserver::OnDiscardedStateChange(content::WebContents* contents,
                                                 bool is_discarded) {}
 
+void TabManagerObserver::OnAutoDiscardableStateChange(
+    content::WebContents* contents,
+    bool is_auto_discardable) {}
+
 TabManagerObserver::~TabManagerObserver() {}
 
 }  // namespace memory
diff --git a/chrome/browser/memory/tab_manager_observer.h b/chrome/browser/memory/tab_manager_observer.h
index e121daf..86dbc13f 100644
--- a/chrome/browser/memory/tab_manager_observer.h
+++ b/chrome/browser/memory/tab_manager_observer.h
@@ -20,6 +20,10 @@
   virtual void OnDiscardedStateChange(content::WebContents* contents,
                                       bool is_discarded);
 
+  // Invoked when the auto-discardable state changes.
+  virtual void OnAutoDiscardableStateChange(content::WebContents* contents,
+                                            bool is_auto_discardable);
+
  protected:
   virtual ~TabManagerObserver();
 };
diff --git a/chrome/browser/memory/tab_manager_observer_browsertest.cc b/chrome/browser/memory/tab_manager_observer_browsertest.cc
index 20f99da5..aa74c15 100644
--- a/chrome/browser/memory/tab_manager_observer_browsertest.cc
+++ b/chrome/browser/memory/tab_manager_observer_browsertest.cc
@@ -6,6 +6,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/memory/tab_manager.h"
 #include "chrome/browser/memory/tab_manager_observer.h"
+#include "chrome/browser/memory/tab_manager_web_contents_data.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
@@ -46,7 +47,10 @@
 class MockTabManagerObserver : public TabManagerObserver {
  public:
   MockTabManagerObserver()
-      : nb_events_(0), contents_(nullptr), is_discarded_(false) {}
+      : nb_events_(0),
+        contents_(nullptr),
+        is_discarded_(false),
+        is_auto_discardable_(true) {}
 
   // TabManagerObserver implementation:
   void OnDiscardedStateChange(content::WebContents* contents,
@@ -56,14 +60,23 @@
     is_discarded_ = is_discarded;
   }
 
+  void OnAutoDiscardableStateChange(content::WebContents* contents,
+                                    bool is_auto_discardable) override {
+    nb_events_++;
+    contents_ = contents;
+    is_auto_discardable_ = is_auto_discardable;
+  }
+
   int nb_events() const { return nb_events_; }
   WebContents* content() const { return contents_; }
   bool is_discarded() const { return is_discarded_; }
+  bool is_auto_discardable() const { return is_auto_discardable_; }
 
  private:
   int nb_events_;
   WebContents* contents_;
   bool is_discarded_;
+  bool is_auto_discardable_;
 
   DISALLOW_COPY_AND_ASSIGN(MockTabManagerObserver);
 };
@@ -131,6 +144,45 @@
   EXPECT_EQ(4, tabmanager_observer.nb_events());
 }
 
+IN_PROC_BROWSER_TEST_F(TabManagerObserverTest, OnAutoDiscardableStateChange) {
+  TabManager* tab_manager = g_browser_process->GetTabManager();
+  ASSERT_TRUE(tab_manager);
+  auto tsm = browser()->tab_strip_model();
+  set_tab_strip_model(tsm);
+
+  // Open two tabs.
+  OpenURLParams open(GURL(chrome::kChromeUIAboutURL), content::Referrer(),
+                     NEW_BACKGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false);
+  WebContents* contents = browser()->OpenURL(open);
+
+  // Subscribe observer to TabManager's observer list.
+  MockTabManagerObserver observer;
+  tab_manager->AddObserver(&observer);
+
+  // No events initially.
+  EXPECT_EQ(0, observer.nb_events());
+
+  // Should maintain at zero since the default value of the state is true.
+  tab_manager->SetTabAutoDiscardableState(contents, true);
+  EXPECT_EQ(0, observer.nb_events());
+
+  // Now it has to change.
+  tab_manager->SetTabAutoDiscardableState(contents, false);
+  EXPECT_EQ(1, observer.nb_events());
+  EXPECT_FALSE(observer.is_auto_discardable());
+  EXPECT_EQ(ContentsId(contents), ContentsId(observer.content()));
+
+  // No changes since it's not a new state.
+  tab_manager->SetTabAutoDiscardableState(contents, false);
+  EXPECT_EQ(1, observer.nb_events());
+
+  // Change it back and we should have another event.
+  tab_manager->SetTabAutoDiscardableState(contents, true);
+  EXPECT_EQ(2, observer.nb_events());
+  EXPECT_TRUE(observer.is_auto_discardable());
+  EXPECT_EQ(ContentsId(contents), ContentsId(observer.content()));
+}
+
 }  // namespace memory
 
 #endif  // OS_WIN || OS_MAXOSX || OS_LINUX
diff --git a/chrome/browser/memory/tab_manager_unittest.cc b/chrome/browser/memory/tab_manager_unittest.cc
index 794f62b..9304b913 100644
--- a/chrome/browser/memory/tab_manager_unittest.cc
+++ b/chrome/browser/memory/tab_manager_unittest.cc
@@ -174,6 +174,7 @@
 
 enum TestIndicies {
   kSelected,
+  kAutoDiscardable,
   kPinned,
   kApp,
   kPlayingAudio,
@@ -277,6 +278,14 @@
     test_list.push_back(stats);
   }
 
+  {
+    TabStats stats;
+    stats.last_active = now;
+    stats.is_auto_discardable = false;
+    stats.child_process_host_id = kAutoDiscardable;
+    test_list.push_back(stats);
+  }
+
   // This entry sorts to the front, so by adding it last, it verifies that the
   // array is being sorted.
   {
@@ -291,6 +300,7 @@
 
   int index = 0;
   EXPECT_EQ(kSelected, test_list[index++].child_process_host_id);
+  EXPECT_EQ(kAutoDiscardable, 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);
diff --git a/chrome/browser/memory/tab_manager_web_contents_data.cc b/chrome/browser/memory/tab_manager_web_contents_data.cc
index e3f97399..f8d75d2 100644
--- a/chrome/browser/memory/tab_manager_web_contents_data.cc
+++ b/chrome/browser/memory/tab_manager_web_contents_data.cc
@@ -98,12 +98,8 @@
   }
 
   tab_data_.is_discarded_ = state;
-
-  // TabManager could not exist in tests.
-  if (g_browser_process->GetTabManager()) {
-    g_browser_process->GetTabManager()->OnDiscardedStateChange(web_contents(),
-                                                               state);
-  }
+  g_browser_process->GetTabManager()->OnDiscardedStateChange(web_contents(),
+                                                             state);
 }
 
 int TabManager::WebContentsData::DiscardCount() {
@@ -172,7 +168,8 @@
       last_discard_time_(TimeTicks::UnixEpoch()),
       last_reload_time_(TimeTicks::UnixEpoch()),
       last_inactive_time_(TimeTicks::UnixEpoch()),
-      engagement_score_(-1.0) {}
+      engagement_score_(-1.0),
+      is_auto_discardable(true) {}
 
 bool TabManager::WebContentsData::Data::operator==(const Data& right) const {
   return is_discarded_ == right.is_discarded_ &&
@@ -188,4 +185,17 @@
   return !(*this == right);
 }
 
+void TabManager::WebContentsData::SetAutoDiscardableState(bool state) {
+  if (tab_data_.is_auto_discardable == state)
+    return;
+
+  tab_data_.is_auto_discardable = state;
+  g_browser_process->GetTabManager()->OnAutoDiscardableStateChange(
+      web_contents(), state);
+}
+
+bool TabManager::WebContentsData::IsAutoDiscardable() {
+  return tab_data_.is_auto_discardable;
+}
+
 }  // namespace memory
diff --git a/chrome/browser/memory/tab_manager_web_contents_data.h b/chrome/browser/memory/tab_manager_web_contents_data.h
index 4830b773..c245982 100644
--- a/chrome/browser/memory/tab_manager_web_contents_data.h
+++ b/chrome/browser/memory/tab_manager_web_contents_data.h
@@ -72,6 +72,13 @@
   // |test_tick_clock_| for more details.
   void set_test_tick_clock(base::TickClock* test_tick_clock);
 
+  // Returns the auto-discardable state of the tab.
+  // See tab_manager.h for more information.
+  bool IsAutoDiscardable();
+
+  // Sets/clears the auto-discardable state of the tab.
+  void SetAutoDiscardableState(bool state);
+
  private:
   // Needed to access tab_data_.
   FRIEND_TEST_ALL_PREFIXES(TabManagerWebContentsDataTest, CopyState);
@@ -99,6 +106,8 @@
     base::TimeTicks last_inactive_time_;
     // Site Engagement score (set to -1 if not available).
     double engagement_score_;
+    // Is tab eligible for auto discarding? Defaults to true.
+    bool is_auto_discardable;
   };
 
   // Returns either the system's clock or the test clock. See |test_tick_clock_|
diff --git a/chrome/browser/memory/tab_stats.cc b/chrome/browser/memory/tab_stats.cc
index df81a4e..d8a0ba5 100644
--- a/chrome/browser/memory/tab_stats.cc
+++ b/chrome/browser/memory/tab_stats.cc
@@ -22,7 +22,8 @@
 #if defined(OS_CHROMEOS)
       oom_score(0),
 #endif
-      tab_contents_id(0) {
+      tab_contents_id(0),
+      is_auto_discardable(true) {
 }
 
 TabStats::TabStats(const TabStats& other) = default;
diff --git a/chrome/browser/memory/tab_stats.h b/chrome/browser/memory/tab_stats.h
index c68f6d06..c036f08 100644
--- a/chrome/browser/memory/tab_stats.h
+++ b/chrome/browser/memory/tab_stats.h
@@ -41,6 +41,7 @@
   int oom_score;
 #endif
   int64_t tab_contents_id;  // Unique ID per WebContents.
+  bool is_auto_discardable;
 };
 
 typedef std::vector<TabStats> TabStatsList;
diff --git a/chrome/browser/net/net_pref_observer.cc b/chrome/browser/net/net_pref_observer.cc
deleted file mode 100644
index 45dec56..0000000
--- a/chrome/browser/net/net_pref_observer.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/net/net_pref_observer.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "chrome/common/pref_names.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/http/http_stream_factory.h"
-
-using content::BrowserThread;
-
-NetPrefObserver::NetPrefObserver(PrefService* prefs) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(prefs);
-}
-
-NetPrefObserver::~NetPrefObserver() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-// static
-void NetPrefObserver::RegisterProfilePrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterBooleanPref(
-      prefs::kNetworkPredictionEnabled,
-      true,
-      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
-  registry->RegisterBooleanPref(prefs::kDisableSpdy, false);
-}
diff --git a/chrome/browser/net/net_pref_observer.h b/chrome/browser/net/net_pref_observer.h
deleted file mode 100644
index 74bdd4f0..0000000
--- a/chrome/browser/net/net_pref_observer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NET_NET_PREF_OBSERVER_H_
-#define CHROME_BROWSER_NET_NET_PREF_OBSERVER_H_
-
-#include "base/macros.h"
-#include "components/prefs/pref_member.h"
-
-class PrefService;
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-// Monitors network-related preferences for changes and applies them.
-// The supplied PrefService must outlive this NetPrefObserver.
-// Must be used only on the UI thread.
-class NetPrefObserver {
- public:
-  // |prefs| must be non-NULL and |*prefs| must outlive this.
-  explicit NetPrefObserver(PrefService* prefs);
-  virtual ~NetPrefObserver();
-
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NetPrefObserver);
-};
-
-#endif  // CHROME_BROWSER_NET_NET_PREF_OBSERVER_H_
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
index 208f29f..3378ce3e 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
@@ -64,12 +64,15 @@
   DISALLOW_COPY_AND_ASSIGN(IONetworkQualityObserver);
 };
 
-UINetworkQualityEstimatorService::UINetworkQualityEstimatorService(
-    Profile* profile)
+UINetworkQualityEstimatorService::UINetworkQualityEstimatorService()
     : type_(net::NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
       io_observer_(nullptr),
       weak_factory_(this) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // If this is running in a context without an IOThread, don't try to create
+  // the IO object.
+  if (!g_browser_process->io_thread())
+    return;
   io_observer_ = new IONetworkQualityObserver(weak_factory_.GetWeakPtr());
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service.h b/chrome/browser/net/nqe/ui_network_quality_estimator_service.h
index 0c11334..671e35c 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service.h
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service.h
@@ -7,16 +7,13 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "net/nqe/network_quality_estimator.h"
 
-class Profile;
-
 // UI service to determine the current EffectiveConnectionType.
 class UINetworkQualityEstimatorService : public KeyedService {
  public:
-  explicit UINetworkQualityEstimatorService(Profile* profile);
+  UINetworkQualityEstimatorService();
   ~UINetworkQualityEstimatorService() override;
 
   // The current EffectiveConnectionType.
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.cc
index 9e8c45d4..d8b71e02 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.cc
@@ -34,6 +34,5 @@
 
 KeyedService* UINetworkQualityEstimatorServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  Profile* profile = Profile::FromBrowserContext(context);
-  return new UINetworkQualityEstimatorService(profile);
+  return new UINetworkQualityEstimatorService();
 }
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
index 75e419f..46fefba 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -67,58 +67,115 @@
 namespace internal {
 
 const char kHistogramCommit[] = "PageLoad.Timing2.NavigationToCommit";
+const char kHistogramFirstLayout[] = "PageLoad.Timing2.NavigationToFirstLayout";
+const char kHistogramFirstTextPaint[] =
+    "PageLoad.Timing2.NavigationToFirstTextPaint";
+const char kHistogramDomContentLoaded[] =
+    "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired";
+const char kHistogramDomLoadingToDomContentLoaded[] =
+    "PageLoad.Timing2.DOMLoadingToDOMContentLoadedEventFired";
+const char kHistogramLoad[] = "PageLoad.Timing2.NavigationToLoadEventFired";
+const char kHistogramFirstPaint[] = "PageLoad.Timing2.NavigationToFirstPaint";
+const char kHistogramFirstImagePaint[] =
+    "PageLoad.Timing2.NavigationToFirstImagePaint";
+const char kHistogramFirstContentfulPaint[] =
+    "PageLoad.Timing2.NavigationToFirstContentfulPaint";
+const char kHistogramDomLoadingToFirstContentfulPaint[] =
+    "PageLoad.Timing2.DOMLoadingToFirstContentfulPaint";
+const char kHistogramParseDuration[] = "PageLoad.Timing2.ParseDuration";
+const char kHistogramParseBlockedOnScriptLoad[] =
+    "PageLoad.Timing2.ParseBlockedOnScriptLoad";
+const char kHistogramParseBlockedOnScriptLoadParseComplete[] =
+    "PageLoad.Timing2.ParseBlockedOnScriptLoad.ParseComplete";
+const char kHistogramParseStartToFirstContentfulPaint[] =
+    "PageLoad.Timing2.ParseStartToFirstContentfulPaint";
+const char kHistogramParseBlockedOnScriptLoadDocumentWrite[] =
+    "PageLoad.Timing2.ParseBlockedOnScriptLoadFromDocumentWrite";
+const char kHistogramParseBlockedOnScriptLoadDocumentWriteParseComplete[] =
+    "PageLoad.Timing2.ParseBlockedOnScriptLoadFromDocumentWrite.ParseComplete";
 
 const char kBackgroundHistogramCommit[] =
     "PageLoad.Timing2.NavigationToCommit.Background";
-
-const char kHistogramDomContentLoaded[] =
-    "PageLoad.DocumentTiming.NavigationToDOMContentLoadedEventFired";
-const char kBackgroundHistogramDomContentLoaded[] =
-    "PageLoad.DocumentTiming.NavigationToDOMContentLoadedEventFired.Background";
-const char kHistogramLoad[] =
-    "PageLoad.DocumentTiming.NavigationToLoadEventFired";
-const char kBackgroundHistogramLoad[] =
-    "PageLoad.DocumentTiming.NavigationToLoadEventFired.Background";
-const char kHistogramFirstLayout[] =
-    "PageLoad.DocumentTiming.NavigationToFirstLayout";
 const char kBackgroundHistogramFirstLayout[] =
-    "PageLoad.DocumentTiming.NavigationToFirstLayout.Background";
-const char kHistogramFirstPaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstPaint";
-const char kBackgroundHistogramFirstPaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstPaint.Background";
-const char kHistogramFirstTextPaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstTextPaint";
+    "PageLoad.Timing2.NavigationToFirstLayout.Background";
 const char kBackgroundHistogramFirstTextPaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstTextPaint.Background";
-const char kHistogramFirstImagePaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstImagePaint";
+    "PageLoad.Timing2.NavigationToFirstTextPaint.Background";
+const char kBackgroundHistogramDomContentLoaded[] =
+    "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired.Background";
+const char kBackgroundHistogramLoad[] =
+    "PageLoad.Timing2.NavigationToLoadEventFired.Background";
+const char kBackgroundHistogramFirstPaint[] =
+    "PageLoad.Timing2.NavigationToFirstPaint.Background";
 const char kBackgroundHistogramFirstImagePaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstImagePaint.Background";
-const char kHistogramFirstContentfulPaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstContentfulPaint";
+    "PageLoad.Timing2.NavigationToFirstImagePaint.Background.";
 const char kBackgroundHistogramFirstContentfulPaint[] =
-    "PageLoad.PaintTiming.NavigationToFirstContentfulPaint.Background";
-const char kHistogramParseStartToFirstContentfulPaint[] =
-    "PageLoad.PaintTiming.ParseStartToFirstContentfulPaint";
-const char kBackgroundHistogramParseStartToFirstContentfulPaint[] =
-    "PageLoad.PaintTiming.ParseStartToFirstContentfulPaint.Background";
-const char kHistogramParseStart[] =
-    "PageLoad.ParseTiming.NavigationToParseStart";
-const char kBackgroundHistogramParseStart[] =
-    "PageLoad.ParseTiming.NavigationToParseStart.Background";
-const char kHistogramParseDuration[] = "PageLoad.ParseTiming.ParseDuration";
+    "PageLoad.Timing2.NavigationToFirstContentfulPaint.Background";
 const char kBackgroundHistogramParseDuration[] =
-    "PageLoad.ParseTiming.ParseDuration.Background";
-const char kHistogramParseBlockedOnScriptLoad[] =
-    "PageLoad.ParseTiming.ParseBlockedOnScriptLoad";
+    "PageLoad.Timing2.ParseDuration.Background";
 const char kBackgroundHistogramParseBlockedOnScriptLoad[] =
-    "PageLoad.ParseTiming.ParseBlockedOnScriptLoad.Background";
-const char kHistogramParseBlockedOnScriptLoadDocumentWrite[] =
-    "PageLoad.ParseTiming.ParseBlockedOnScriptLoadFromDocumentWrite";
+    "PageLoad.Timing2.ParseBlockedOnScriptLoad.Background";
+const char kBackgroundHistogramParseBlockedOnScriptLoadParseComplete[] =
+    "PageLoad.Timing2.ParseBlockedOnScriptLoad.ParseComplete.Background";
 const char kBackgroundHistogramParseBlockedOnScriptLoadDocumentWrite[] =
-    "PageLoad.ParseTiming.ParseBlockedOnScriptLoadFromDocumentWrite."
-    "Background";
+    "PageLoad.Timing2.ParseBlockedOnScriptLoadFromDocumentWrite.Background";
+const char
+    kBackgroundHistogramParseBlockedOnScriptLoadDocumentWriteParseComplete[] =
+        "PageLoad.Timing2.ParseBlockedOnScriptLoadFromDocumentWrite."
+        "ParseComplete.Background";
+
+// Immediate histogram variants, which are logged as soon as the associated
+// event is observed. These will eventually become our standard metrics, and the
+// Timing2 variants will be deprecated in M54.
+const char kHistogramDomContentLoadedImmediate[] =
+    "PageLoad.DocumentTiming.NavigationToDOMContentLoadedEventFired";
+const char kBackgroundHistogramDomContentLoadedImmediate[] =
+    "PageLoad.DocumentTiming.NavigationToDOMContentLoadedEventFired.Background";
+const char kHistogramLoadImmediate[] =
+    "PageLoad.DocumentTiming.NavigationToLoadEventFired";
+const char kBackgroundHistogramLoadImmediate[] =
+    "PageLoad.DocumentTiming.NavigationToLoadEventFired.Background";
+const char kHistogramFirstLayoutImmediate[] =
+    "PageLoad.DocumentTiming.NavigationToFirstLayout";
+const char kBackgroundHistogramFirstLayoutImmediate[] =
+    "PageLoad.DocumentTiming.NavigationToFirstLayout.Background";
+const char kHistogramFirstPaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstPaint";
+const char kBackgroundHistogramFirstPaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstPaint.Background";
+const char kHistogramFirstTextPaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstTextPaint";
+const char kBackgroundHistogramFirstTextPaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstTextPaint.Background";
+const char kHistogramFirstImagePaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstImagePaint";
+const char kBackgroundHistogramFirstImagePaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstImagePaint.Background";
+const char kHistogramFirstContentfulPaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstContentfulPaint";
+const char kBackgroundHistogramFirstContentfulPaintImmediate[] =
+    "PageLoad.PaintTiming.NavigationToFirstContentfulPaint.Background";
+const char kHistogramParseStartToFirstContentfulPaintImmediate[] =
+    "PageLoad.PaintTiming.ParseStartToFirstContentfulPaint";
+const char kBackgroundHistogramParseStartToFirstContentfulPaintImmediate[] =
+    "PageLoad.PaintTiming.ParseStartToFirstContentfulPaint.Background";
+const char kHistogramParseStartImmediate[] =
+    "PageLoad.ParseTiming.NavigationToParseStart";
+const char kBackgroundHistogramParseStartImmediate[] =
+    "PageLoad.ParseTiming.NavigationToParseStart.Background";
+const char kHistogramParseDurationImmediate[] =
+    "PageLoad.ParseTiming.ParseDuration";
+const char kBackgroundHistogramParseDurationImmediate[] =
+    "PageLoad.ParseTiming.ParseDuration.Background";
+const char kHistogramParseBlockedOnScriptLoadImmediate[] =
+    "PageLoad.ParseTiming.ParseBlockedOnScriptLoad";
+const char kBackgroundHistogramParseBlockedOnScriptLoadImmediate[] =
+    "PageLoad.ParseTiming.ParseBlockedOnScriptLoad.Background";
+const char kHistogramParseBlockedOnScriptLoadDocumentWriteImmediate[] =
+    "PageLoad.ParseTiming.ParseBlockedOnScriptLoadFromDocumentWrite";
+const char
+    kBackgroundHistogramParseBlockedOnScriptLoadDocumentWriteImmediate[] =
+        "PageLoad.ParseTiming.ParseBlockedOnScriptLoadFromDocumentWrite."
+        "Background";
 
 const char kHistogramLoadTypeFirstContentfulPaintReload[] =
     "PageLoad.PaintTiming.NavigationToFirstContentfulPaint.LoadType."
@@ -156,7 +213,7 @@
     "PageLoad.Timing2.NavigationToFailedProvisionalLoad";
 
 const char kHistogramForegroundToFirstPaint[] =
-    "PageLoad.PaintTiming.ForegroundToFirstPaint";
+    "PageLoad.Timing2.ForegroundToFirstPaint";
 
 const char kRapporMetricsNameCoarseTiming[] =
     "PageLoad.CoarseTiming.NavigationToFirstContentfulPaint";
@@ -180,10 +237,10 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(
           timing.dom_content_loaded_event_start, info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramDomContentLoaded,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramDomContentLoadedImmediate,
                         timing.dom_content_loaded_event_start.value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramDomContentLoaded,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramDomContentLoadedImmediate,
                         timing.dom_content_loaded_event_start.value());
   }
 }
@@ -193,10 +250,10 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(timing.load_event_start,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramLoad,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramLoadImmediate,
                         timing.load_event_start.value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramLoad,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramLoadImmediate,
                         timing.load_event_start.value());
   }
 }
@@ -206,10 +263,10 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(timing.first_layout,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstLayout,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstLayoutImmediate,
                         timing.first_layout.value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstLayout,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstLayoutImmediate,
                         timing.first_layout.value());
   }
 }
@@ -219,25 +276,12 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(timing.first_paint,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstPaint,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstPaintImmediate,
                         timing.first_paint.value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstPaint,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstPaintImmediate,
                         timing.first_paint.value());
   }
-
-  // Record the time to first paint for pages which were:
-  // - Opened in the background.
-  // - Moved to the foreground prior to the first paint.
-  // - Not moved back to the background prior to the first paint.
-  if (!info.started_in_foreground && info.first_foreground_time &&
-      info.first_foreground_time.value() <= timing.first_paint.value() &&
-      (!info.first_background_time ||
-       timing.first_paint.value() <= info.first_background_time.value())) {
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramForegroundToFirstPaint,
-        timing.first_paint.value() - info.first_foreground_time.value());
-  }
 }
 
 void CorePageLoadMetricsObserver::OnFirstTextPaint(
@@ -245,10 +289,10 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(timing.first_text_paint,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstTextPaint,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstTextPaintImmediate,
                         timing.first_text_paint.value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstTextPaint,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstTextPaintImmediate,
                         timing.first_text_paint.value());
   }
 }
@@ -258,10 +302,10 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(timing.first_image_paint,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstImagePaint,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstImagePaintImmediate,
                         timing.first_image_paint.value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstImagePaint,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstImagePaintImmediate,
                         timing.first_image_paint.value());
   }
 }
@@ -271,10 +315,10 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(
           timing.first_contentful_paint, info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstContentfulPaint,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstContentfulPaintImmediate,
                         timing.first_contentful_paint.value());
     PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramParseStartToFirstContentfulPaint,
+        internal::kHistogramParseStartToFirstContentfulPaintImmediate,
         timing.first_contentful_paint.value() - timing.parse_start.value());
 
     switch (GetPageLoadType(transition_)) {
@@ -303,10 +347,11 @@
         break;
     }
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstContentfulPaint,
-                        timing.first_contentful_paint.value());
     PAGE_LOAD_HISTOGRAM(
-        internal::kBackgroundHistogramParseStartToFirstContentfulPaint,
+        internal::kBackgroundHistogramFirstContentfulPaintImmediate,
+        timing.first_contentful_paint.value());
+    PAGE_LOAD_HISTOGRAM(
+        internal::kBackgroundHistogramParseStartToFirstContentfulPaintImmediate,
         timing.first_contentful_paint.value() - timing.parse_start.value());
   }
 }
@@ -316,7 +361,7 @@
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (WasStartedInForegroundOptionalEventInForeground(timing.parse_start,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramParseStart,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramParseStartImmediate,
                         timing.parse_start.value());
 
     switch (GetPageLoadType(transition_)) {
@@ -337,7 +382,7 @@
         break;
     }
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramParseStart,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramParseStartImmediate,
                         timing.parse_start.value());
   }
 }
@@ -349,20 +394,23 @@
       timing.parse_stop.value() - timing.parse_start.value();
   if (WasStartedInForegroundOptionalEventInForeground(timing.parse_stop,
                                                       info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramParseDuration, parse_duration);
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramParseBlockedOnScriptLoad,
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramParseDurationImmediate,
+                        parse_duration);
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramParseBlockedOnScriptLoadImmediate,
                         timing.parse_blocked_on_script_load_duration.value());
     PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramParseBlockedOnScriptLoadDocumentWrite,
+        internal::kHistogramParseBlockedOnScriptLoadDocumentWriteImmediate,
         timing.parse_blocked_on_script_load_from_document_write_duration
             .value());
   } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramParseDuration,
+    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramParseDurationImmediate,
                         parse_duration);
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramParseBlockedOnScriptLoad,
-                        timing.parse_blocked_on_script_load_duration.value());
     PAGE_LOAD_HISTOGRAM(
-        internal::kBackgroundHistogramParseBlockedOnScriptLoadDocumentWrite,
+        internal::kBackgroundHistogramParseBlockedOnScriptLoadImmediate,
+        timing.parse_blocked_on_script_load_duration.value());
+    PAGE_LOAD_HISTOGRAM(
+        internal::
+            kBackgroundHistogramParseBlockedOnScriptLoadDocumentWriteImmediate,
         timing.parse_blocked_on_script_load_from_document_write_duration
             .value());
   }
@@ -399,6 +447,23 @@
 void CorePageLoadMetricsObserver::RecordTimingHistograms(
     const page_load_metrics::PageLoadTiming& timing,
     const page_load_metrics::PageLoadExtraInfo& info) {
+  // Record metrics for pages which start in the foreground and are
+  // backgrounded.
+  if (info.started_in_foreground && info.first_background_time) {
+    const base::TimeDelta first_background_time =
+        info.first_background_time.value();
+
+    if (!timing.first_paint || timing.first_paint > first_background_time) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramBackgroundBeforePaint,
+                          first_background_time);
+    }
+    if (timing.parse_start && first_background_time >= timing.parse_start &&
+        (!timing.parse_stop || timing.parse_stop > first_background_time)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramBackgroundDuringParse,
+                          first_background_time);
+    }
+  }
+
   const base::TimeDelta time_to_commit = info.time_to_commit.value();
   if (WasStartedInForegroundOptionalEventInForeground(info.time_to_commit,
                                                       info)) {
@@ -406,26 +471,151 @@
   } else {
     PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramCommit, time_to_commit);
   }
+  if (timing.dom_content_loaded_event_start) {
+    if (WasStartedInForegroundOptionalEventInForeground(
+            timing.dom_content_loaded_event_start, info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramDomContentLoaded,
+                          timing.dom_content_loaded_event_start.value());
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramDomLoadingToDomContentLoaded,
+                          timing.dom_content_loaded_event_start.value() -
+                              timing.dom_loading.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramDomContentLoaded,
+                          timing.dom_content_loaded_event_start.value());
+    }
+  }
+  if (timing.load_event_start) {
+    if (WasStartedInForegroundOptionalEventInForeground(timing.load_event_start,
+                                                        info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramLoad,
+                          timing.load_event_start.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramLoad,
+                          timing.load_event_start.value());
+    }
+  }
+  if (timing.first_layout) {
+    if (WasStartedInForegroundOptionalEventInForeground(timing.first_layout,
+                                                        info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstLayout,
+                          timing.first_layout.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstLayout,
+                          timing.first_layout.value());
+    }
+  }
+  if (timing.first_paint) {
+    if (WasStartedInForegroundOptionalEventInForeground(timing.first_paint,
+                                                        info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstPaint,
+                          timing.first_paint.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstPaint,
+                          timing.first_paint.value());
+    }
+
+    // Record the time to first paint for pages which were:
+    // - Opened in the background.
+    // - Moved to the foreground prior to the first paint.
+    // - Not moved back to the background prior to the first paint.
+    if (!info.started_in_foreground && info.first_foreground_time &&
+        timing.first_paint > info.first_foreground_time.value() &&
+        (!info.first_background_time ||
+         timing.first_paint < info.first_background_time.value())) {
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramForegroundToFirstPaint,
+          timing.first_paint.value() - info.first_foreground_time.value());
+    }
+  }
+  if (timing.first_text_paint) {
+    if (WasStartedInForegroundOptionalEventInForeground(timing.first_text_paint,
+                                                        info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstTextPaint,
+                          timing.first_text_paint.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstTextPaint,
+                          timing.first_text_paint.value());
+    }
+  }
+  if (timing.first_image_paint) {
+    if (WasStartedInForegroundOptionalEventInForeground(
+            timing.first_image_paint, info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstImagePaint,
+                          timing.first_image_paint.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstImagePaint,
+                          timing.first_image_paint.value());
+    }
+  }
+  if (timing.first_contentful_paint) {
+    if (WasStartedInForegroundOptionalEventInForeground(
+            timing.first_contentful_paint, info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstContentfulPaint,
+                          timing.first_contentful_paint.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramParseStartToFirstContentfulPaint,
+          timing.first_contentful_paint.value() - timing.parse_start.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramDomLoadingToFirstContentfulPaint,
+          timing.first_contentful_paint.value() - timing.dom_loading.value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramFirstContentfulPaint,
+                          timing.first_contentful_paint.value());
+    }
+  }
+  if (timing.parse_start) {
+    if (WasParseInForeground(timing.parse_start, timing.parse_stop, info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramParseBlockedOnScriptLoad,
+                          timing.parse_blocked_on_script_load_duration.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramParseBlockedOnScriptLoadDocumentWrite,
+          timing.parse_blocked_on_script_load_from_document_write_duration
+              .value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(
+          internal::kBackgroundHistogramParseBlockedOnScriptLoad,
+          timing.parse_blocked_on_script_load_duration.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::kBackgroundHistogramParseBlockedOnScriptLoadDocumentWrite,
+          timing.parse_blocked_on_script_load_from_document_write_duration
+              .value());
+    }
+  }
+
+  if (timing.parse_stop) {
+    base::TimeDelta parse_duration =
+        timing.parse_stop.value() - timing.parse_start.value();
+    if (WasStartedInForegroundOptionalEventInForeground(timing.parse_stop,
+                                                        info)) {
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramParseDuration, parse_duration);
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramParseBlockedOnScriptLoadParseComplete,
+          timing.parse_blocked_on_script_load_duration.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::
+              kHistogramParseBlockedOnScriptLoadDocumentWriteParseComplete,
+          timing.parse_blocked_on_script_load_from_document_write_duration
+              .value());
+    } else {
+      PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramParseDuration,
+                          parse_duration);
+      PAGE_LOAD_HISTOGRAM(
+          internal::kBackgroundHistogramParseBlockedOnScriptLoadParseComplete,
+          timing.parse_blocked_on_script_load_duration.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::
+              kBackgroundHistogramParseBlockedOnScriptLoadDocumentWriteParseComplete,
+          timing.parse_blocked_on_script_load_from_document_write_duration
+              .value());
+    }
+  }
 
   // Log time to first foreground / time to first background. Log counts that we
   // started a relevant page load in the foreground / background.
   if (info.started_in_foreground) {
-    if (info.first_background_time) {
-      const base::TimeDelta first_background_time =
-          info.first_background_time.value();
-
+    if (info.first_background_time)
       PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstBackground,
-                          first_background_time);
-      if (!timing.first_paint || timing.first_paint > first_background_time) {
-        PAGE_LOAD_HISTOGRAM(internal::kHistogramBackgroundBeforePaint,
-                            first_background_time);
-      }
-      if (timing.parse_start && first_background_time >= timing.parse_start &&
-          (!timing.parse_stop || timing.parse_stop > first_background_time)) {
-        PAGE_LOAD_HISTOGRAM(internal::kHistogramBackgroundDuringParse,
-                            first_background_time);
-      }
-    }
+                          info.first_background_time.value());
   } else {
     if (info.first_foreground_time)
       PAGE_LOAD_HISTOGRAM(internal::kHistogramFirstForeground,
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
index 7f5ce3f6..ad86d75 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
@@ -17,8 +17,11 @@
 extern const char kHistogramFirstLayout[];
 extern const char kHistogramFirstTextPaint[];
 extern const char kHistogramDomContentLoaded[];
+extern const char kHistogramDomLoadingToDomContentLoaded[];
 extern const char kHistogramLoad[];
 extern const char kHistogramFirstContentfulPaint[];
+extern const char kHistogramFirstContentfulPaintImmediate[];
+extern const char kHistogramDomLoadingToFirstContentfulPaint[];
 extern const char kHistogramParseDuration[];
 extern const char kHistogramParseBlockedOnScriptLoad[];
 
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
index c19a027..5657d3d4 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
@@ -26,6 +26,14 @@
     tracker->AddObserver(base::WrapUnique(new CorePageLoadMetricsObserver()));
   }
 
+  void AssertNoHistogramsLogged() {
+    histogram_tester().ExpectTotalCount(internal::kHistogramDomContentLoaded,
+                                        0);
+    histogram_tester().ExpectTotalCount(internal::kHistogramLoad, 0);
+    histogram_tester().ExpectTotalCount(internal::kHistogramFirstLayout, 0);
+    histogram_tester().ExpectTotalCount(internal::kHistogramFirstTextPaint, 0);
+  }
+
   void SetUp() override {
     page_load_metrics::PageLoadMetricsObserverTestHarness::SetUp();
     TestingBrowserProcess::GetGlobal()->SetRapporService(&rappor_tester_);
@@ -35,10 +43,7 @@
 };
 
 TEST_F(CorePageLoadMetricsObserverTest, NoMetrics) {
-  histogram_tester().ExpectTotalCount(internal::kHistogramDomContentLoaded, 0);
-  histogram_tester().ExpectTotalCount(internal::kHistogramLoad, 0);
-  histogram_tester().ExpectTotalCount(internal::kHistogramFirstLayout, 0);
-  histogram_tester().ExpectTotalCount(internal::kHistogramFirstTextPaint, 0);
+  AssertNoHistogramsLogged();
 }
 
 TEST_F(CorePageLoadMetricsObserverTest, SamePageNoTriggerUntilTrueNavCommit) {
@@ -54,7 +59,7 @@
 
   NavigateAndCommit(GURL(kDefaultTestUrlAnchor));
   // A same page navigation shouldn't trigger logging UMA for the original.
-  histogram_tester().ExpectTotalCount(internal::kHistogramCommit, 0);
+  AssertNoHistogramsLogged();
 
   // But we should keep the timing info and log it when we get another
   // navigation.
@@ -86,7 +91,7 @@
   NavigateAndCommit(GURL(kDefaultTestUrl));
   SimulateTimingUpdate(timing);
 
-  histogram_tester().ExpectTotalCount(internal::kHistogramCommit, 0);
+  AssertNoHistogramsLogged();
 
   // Navigate again to force histogram recording.
   NavigateAndCommit(GURL(kDefaultTestUrl2));
@@ -130,11 +135,15 @@
   NavigateAndCommit(GURL(kDefaultTestUrl));
   SimulateTimingUpdate(timing);
 
+  // Verify that the non-immediate FCP has not yet been logged, but the
+  // immediate FCP is logged before the next navigation.
   histogram_tester().ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
-                                      1);
-  histogram_tester().ExpectBucketCount(internal::kHistogramFirstContentfulPaint,
-                                       first_contentful_paint.InMilliseconds(),
-                                       1);
+                                      0);
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramFirstContentfulPaintImmediate, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramFirstContentfulPaintImmediate,
+      first_contentful_paint.InMilliseconds(), 1);
 
   NavigateAndCommit(GURL(kDefaultTestUrl2));
 
@@ -155,11 +164,29 @@
   histogram_tester().ExpectBucketCount(internal::kHistogramFirstLayout,
                                        first_layout_2.InMilliseconds(), 1);
 
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramDomLoadingToDomContentLoaded, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramDomLoadingToDomContentLoaded,
+      (dom_content - dom_loading).InMilliseconds(), 1);
+
   histogram_tester().ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
                                       1);
   histogram_tester().ExpectBucketCount(internal::kHistogramFirstContentfulPaint,
                                        first_contentful_paint.InMilliseconds(),
                                        1);
+
+  // Verify that no additional immediate metrics were logged as a result of
+  // navigation.
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramFirstContentfulPaintImmediate, 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramDomLoadingToFirstContentfulPaint, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramDomLoadingToFirstContentfulPaint,
+      (first_contentful_paint - dom_loading).InMilliseconds(), 1);
+
   histogram_tester().ExpectTotalCount(internal::kHistogramFirstTextPaint, 1);
   histogram_tester().ExpectBucketCount(internal::kHistogramFirstTextPaint,
                                        first_text_paint.InMilliseconds(), 1);
@@ -188,6 +215,7 @@
 
   // Simulate switching to the tab and making another navigation.
   web_contents()->WasShown();
+  AssertNoHistogramsLogged();
 
   // Navigate again to force histogram recording.
   NavigateAndCommit(GURL(kDefaultTestUrl2));
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index d9ab620..5ef2054 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -17,6 +17,10 @@
   ~MetricsWebContentsObserverBrowserTest() override {}
 
  protected:
+  void NavigateToUntrackedUrl() {
+    ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  }
+
   base::HistogramTester histogram_tester_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverBrowserTest);
@@ -31,13 +35,13 @@
   histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 0);
 }
 
-IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest, NewPage) {
+IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest,
+                       DISABLED_NewPage) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   ui_test_utils::NavigateToURL(browser(),
                                embedded_test_server()->GetURL("/title1.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
   histogram_tester_.ExpectTotalCount(internal::kHistogramLoad, 1);
@@ -47,7 +51,6 @@
       internal::kHistogramParseBlockedOnScriptLoad, 1);
 }
 
-// Flaky in win: crbug.com/630076
 IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest,
                        DISABLED_SamePageNavigation) {
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -56,15 +59,13 @@
                                embedded_test_server()->GetURL("/title1.html"));
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/title1.html#hash"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(internal::kHistogramDomContentLoaded, 1);
   histogram_tester_.ExpectTotalCount(internal::kHistogramLoad, 1);
   histogram_tester_.ExpectTotalCount(internal::kHistogramFirstLayout, 1);
 }
 
-// Flaky in win: crbug.com/630076
 IN_PROC_BROWSER_TEST_F(MetricsWebContentsObserverBrowserTest,
                        DISABLED_SameUrlNavigation) {
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -73,8 +74,7 @@
                                embedded_test_server()->GetURL("/title1.html"));
   ui_test_utils::NavigateToURL(browser(),
                                embedded_test_server()->GetURL("/title1.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   // We expect one histogram sample for each navigation to title1.html.
   histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 2);
@@ -89,8 +89,7 @@
 
   ui_test_utils::NavigateToURL(browser(),
                                embedded_test_server()->GetURL("/simple.svg"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title1.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 0);
 }
@@ -100,8 +99,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title1.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(internal::kHistogramCommit, 0);
 }
@@ -113,8 +111,7 @@
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL(
                      "/page_load_metrics/document_write_external_script.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 1);
@@ -127,8 +124,7 @@
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL(
                      "/page_load_metrics/document_write_no_script.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0);
@@ -139,8 +135,7 @@
 
   ui_test_utils::NavigateToURL(browser(),
                                embedded_test_server()->GetURL("/title1.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0);
   histogram_tester_.ExpectTotalCount(
@@ -154,9 +149,7 @@
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL(
                      "/page_load_metrics/document_write_script_block.html"));
-
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1);
@@ -182,8 +175,7 @@
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1);
 
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 1);
@@ -199,8 +191,7 @@
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL(
                      "/page_load_metrics/document_write_script_async.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
@@ -213,8 +204,7 @@
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL(
                      "/page_load_metrics/document_write_external_script.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
@@ -227,8 +217,7 @@
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL(
                      "/page_load_metrics/document_write_no_script.html"));
-  ui_test_utils::NavigateToURL(browser(),
-                               embedded_test_server()->GetURL("/title2.html"));
+  NavigateToUntrackedUrl();
 
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
diff --git a/chrome/browser/password_manager/credential_manager_browsertest.cc b/chrome/browser/password_manager/credential_manager_browsertest.cc
index e4854093..978620b2 100644
--- a/chrome/browser/password_manager/credential_manager_browsertest.cc
+++ b/chrome/browser/password_manager/credential_manager_browsertest.cc
@@ -166,34 +166,54 @@
   EXPECT_FALSE(prompt_observer->IsShowingSavePrompt());
 }
 
-// Disabled due to flakes; see https://crbug.com/629459.
-IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest,
-                       DISABLED_SaveViaAPIAndAutofill) {
+IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest, SaveViaAPIAndAutofill) {
   NavigateToFile("/password/password_form.html");
-  std::string fill_password =
-  "document.getElementById('username_field').value = 'user';"
-  "document.getElementById('password_field').value = '12345';";
-  ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_password));
 
-  // Call the API to save the form.
+  // Postpone a submit event for 1 second. Even for the static html page Chrome
+  // continues to parse and recreate the PasswordFormManager instances after the
+  // page load. Calling the API before this would make the test flaky. Clicking
+  // on the button emulates server analysing the credential and then saving and
+  // navigating to the landing page.
   ASSERT_TRUE(content::ExecuteScript(
       RenderViewHost(),
-      "var c = new PasswordCredential({ id: 'user', password: '12345' });"
-      "navigator.credentials.store(c);"));
-  // Wait for the password store before checking the prompt because it pops up
-  // after the store replies.
-  WaitForPasswordStore();
-  std::unique_ptr<BubbleObserver> prompt_observer(
-      new BubbleObserver(WebContents()));
-  EXPECT_TRUE(prompt_observer->IsShowingSavePrompt());
-  prompt_observer->Dismiss();
-
+      "document.getElementById('input_submit_button').addEventListener('click',"
+      "function(event) {"
+        "setTimeout( function() {"
+          "var c = new PasswordCredential({ id: 'user', password: 'API' });"
+          "navigator.credentials.store(c);"
+          "document.getElementById('testform').submit();"
+        "}, 1000 );"
+        "event.preventDefault();"
+      "});"));
+  // Fill the password and click the button to submit the page later. The API
+  // should suppress the autofill password manager.
   NavigationObserver form_submit_observer(WebContents());
   ASSERT_TRUE(content::ExecuteScript(
       RenderViewHost(),
+      "document.getElementById('username_field').value = 'user';"
+      "document.getElementById('password_field').value = 'autofill';"
       "document.getElementById('input_submit_button').click();"));
   form_submit_observer.Wait();
-  EXPECT_FALSE(prompt_observer->IsShowingSavePrompt());
+
+  WaitForPasswordStore();
+  std::unique_ptr<BubbleObserver> prompt_observer(
+      new BubbleObserver(WebContents()));
+  ASSERT_TRUE(prompt_observer->IsShowingSavePrompt());
+  prompt_observer->AcceptSavePrompt();
+
+  WaitForPasswordStore();
+  password_manager::TestPasswordStore::PasswordMap stored =
+      static_cast<password_manager::TestPasswordStore*>(
+          PasswordStoreFactory::GetForProfile(
+              browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
+              .get())->stored_passwords();
+  ASSERT_EQ(1u, stored.size());
+  autofill::PasswordForm signin_form = stored.begin()->second[0];
+  EXPECT_EQ(base::ASCIIToUTF16("user"), signin_form.username_value);
+  EXPECT_EQ(base::ASCIIToUTF16("API"), signin_form.password_value);
+  EXPECT_EQ(embedded_test_server()->base_url().spec(),
+            signin_form.signon_realm);
+  EXPECT_EQ(embedded_test_server()->base_url(), signin_form.origin);
 }
 
 IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest, UpdateViaAPIAndAutofill) {
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index 047c919..105bf446d 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -484,9 +484,11 @@
   list->add_entries("ftp");
   list->add_entries("mailto");
   // Try explicitly setting a policy mode too.
-  chrome_settings.mutable_disablespdy()->set_disablespdy(false);
-  chrome_settings.mutable_disablespdy()->mutable_policy_options()->set_mode(
-      em::PolicyOptions::MANDATORY);
+  chrome_settings.mutable_searchsuggestenabled()->set_searchsuggestenabled(
+      false);
+  chrome_settings.mutable_searchsuggestenabled()
+      ->mutable_policy_options()
+      ->set_mode(em::PolicyOptions::MANDATORY);
   chrome_settings.mutable_syncdisabled()->set_syncdisabled(true);
   chrome_settings.mutable_syncdisabled()->mutable_policy_options()->set_mode(
       em::PolicyOptions::RECOMMENDED);
@@ -499,9 +501,10 @@
   list = cloud_policy.mutable_disabledschemes()->mutable_value();
   list->add_entries("ftp");
   list->add_entries("mailto");
-  cloud_policy.mutable_disablespdy()->set_value(false);
-  cloud_policy.mutable_disablespdy()->mutable_policy_options()->set_mode(
-      em::PolicyOptions::MANDATORY);
+  cloud_policy.mutable_searchsuggestenabled()->set_value(false);
+  cloud_policy.mutable_searchsuggestenabled()
+      ->mutable_policy_options()
+      ->set_mode(em::PolicyOptions::MANDATORY);
   cloud_policy.mutable_syncdisabled()->set_value(true);
   cloud_policy.mutable_syncdisabled()->mutable_policy_options()->set_mode(
       em::PolicyOptions::RECOMMENDED);
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 634c10a..21a3a858 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -107,9 +107,6 @@
   { key::kPacHttpsUrlStrippingEnabled,
     prefs::kPacHttpsUrlStrippingEnabled,
     base::Value::TYPE_BOOLEAN },
-  { key::kDisableSpdy,
-    prefs::kDisableSpdy,
-    base::Value::TYPE_BOOLEAN },
   { key::kSafeBrowsingEnabled,
     prefs::kSafeBrowsingEnabled,
     base::Value::TYPE_BOOLEAN },
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index c62343a..8e5e982 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/media/media_stream_devices_controller.h"
 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
 #include "chrome/browser/net/http_server_properties_manager_factory.h"
-#include "chrome/browser/net/net_pref_observer.h"
 #include "chrome/browser/net/prediction_options.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/notifications/extension_welcome_notification.h"
@@ -79,6 +78,7 @@
 #include "components/metrics/metrics_service.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/ntp_snippets/ntp_snippets_service.h"
+#include "components/ntp_snippets/request_throttler.h"
 #include "components/omnibox/browser/zero_suggest_provider.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
 #include "components/password_manager/core/browser/password_manager.h"
@@ -297,6 +297,10 @@
 const char kDesktopSearchRedirectionInfobarShownPref[] =
     "desktop_search_redirection_infobar_shown";
 
+// Deprecated 7/2016.
+const char kNetworkPredictionEnabled[] = "dns_prefetching.enabled";
+const char kDisableSpdy[] = "spdy.disabled";
+
 void DeleteWebRTCIdentityStoreDBOnFileThread(base::FilePath profile_path) {
   base::DeleteFile(profile_path.Append(
       FILE_PATH_LITERAL("WebRTCIdentityStore")), false);
@@ -459,8 +463,8 @@
   MediaCaptureDevicesDispatcher::RegisterProfilePrefs(registry);
   MediaDeviceIDSalt::RegisterProfilePrefs(registry);
   MediaStreamDevicesController::RegisterProfilePrefs(registry);
-  NetPrefObserver::RegisterProfilePrefs(registry);
   ntp_snippets::NTPSnippetsService::RegisterProfilePrefs(registry);
+  ntp_snippets::RequestThrottler::RegisterProfilePrefs(registry);
   password_bubble_experiment::RegisterPrefs(registry);
   password_manager::PasswordManager::RegisterProfilePrefs(registry);
   PrefProxyConfigTrackerImpl::RegisterProfilePrefs(registry);
@@ -632,6 +636,9 @@
 
   registry->RegisterBooleanPref(kDesktopSearchRedirectionInfobarShownPref,
                                 false);
+
+  registry->RegisterBooleanPref(kNetworkPredictionEnabled, true);
+  registry->RegisterBooleanPref(kDisableSpdy, false);
 }
 
 void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
@@ -730,6 +737,8 @@
 
   // Added 7/2016.
   DeleteWebRTCIdentityStoreDB(profile);
+  profile_prefs->ClearPref(kNetworkPredictionEnabled);
+  profile_prefs->ClearPref(kDisableSpdy);
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
index e9ad66b3..c2639b7 100644
--- a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
@@ -58,6 +58,8 @@
     IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
       IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
                           OnRequestPrintPreview)
+      IPC_MESSAGE_HANDLER(PrintHostMsg_SetupScriptedPrintPreview,
+                          OnSetupScriptedPrintPreview)
       IPC_MESSAGE_UNHANDLED(break)
     IPC_END_MESSAGE_MAP()
     return false;  // Report not handled so the real handler receives it.
@@ -68,6 +70,10 @@
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
   }
 
+  void OnSetupScriptedPrintPreview() {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
+  }
+
   base::Closure quit_closure_;
 
   DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
@@ -97,21 +103,65 @@
   DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
 };
 
+class PrintPreviewDialogStartedObserver : public WebContentsObserver {
+ public:
+  explicit PrintPreviewDialogStartedObserver(WebContents* dialog)
+      : WebContentsObserver(dialog), waiting_(false), dialog_started_(false) {}
+  ~PrintPreviewDialogStartedObserver() override {}
+
+  bool dialog_started() const { return dialog_started_; }
+
+  void WaitForDialogStarted() {
+    waiting_ = true;
+    run_loop_.Run();
+  }
+
+ private:
+  // content::WebContentsObserver implementation.
+  void RenderViewReady() override {
+    dialog_started_ = true;
+    if (waiting_)
+      run_loop_.Quit();
+  }
+
+  void WebContentsDestroyed() override {
+    if (waiting_)
+      run_loop_.Quit();
+  }
+
+  bool waiting_;
+  bool dialog_started_;
+  base::RunLoop run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogStartedObserver);
+};
+
 class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
  public:
   explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
       : WebContentsObserver(dialog),
-        dialog_destroyed_(false) {
-  }
+        waiting_(false),
+        dialog_destroyed_(false) {}
   ~PrintPreviewDialogDestroyedObserver() override {}
 
   bool dialog_destroyed() const { return dialog_destroyed_; }
 
+  void WaitForDialogDestroyed() {
+    waiting_ = true;
+    run_loop_.Run();
+  }
+
  private:
   // content::WebContentsObserver implementation.
-  void WebContentsDestroyed() override { dialog_destroyed_ = true; }
+  void WebContentsDestroyed() override {
+    dialog_destroyed_ = true;
+    if (waiting_)
+      run_loop_.Quit();
+  }
 
+  bool waiting_;
   bool dialog_destroyed_;
+  base::RunLoop run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
 };
@@ -168,6 +218,14 @@
     run_loop.Run();
   }
 
+  void PrintPreviewViaScript(base::StringPiece script) {
+    base::RunLoop run_loop;
+    request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
+    initiator()->GetMainFrame()->ExecuteJavaScriptForTests(
+        base::ASCIIToUTF16(script));
+    run_loop.Run();
+  }
+
   WebContents* GetPrintPreviewDialog() {
     printing::PrintPreviewDialogController* dialog_controller =
         printing::PrintPreviewDialogController::GetInstance();
@@ -240,6 +298,52 @@
   EXPECT_TRUE(new_preview_dialog);
 }
 
+// Ensure that back/forward navigations with ScopedPageLoadDeferrers (e.g.,
+// during printing) end up committing to the correct NavigationEntry.
+// See https://crbug.com/626838.
+IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
+                       HistoryNavigateDuringPrint) {
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+  ui_test_utils::NavigateToURL(browser(), GURL("data:text/html,page1"));
+  ui_test_utils::NavigateToURL(browser(), GURL("data:text/html,page2"));
+  EXPECT_EQ(2, tab->GetController().GetEntryCount());
+  EXPECT_EQ(1, tab->GetController().GetLastCommittedEntryIndex());
+
+  // Go back via script, but before that gets a chance to commit, show a print
+  // dialog with a nested message loop and ScopedPageLoadDeferrer.
+  PrintPreviewViaScript("history.back(); print();");
+
+  // Get the preview dialog for the initiator tab.
+  WebContents* preview_dialog = GetPrintPreviewDialog();
+
+  // Check a new print preview dialog got created.
+  ASSERT_TRUE(preview_dialog);
+  ASSERT_NE(initiator(), preview_dialog);
+
+  bool started = preview_dialog->GetRenderProcessHost()->IsReady();
+  if (!started) {
+    PrintPreviewDialogStartedObserver started_observer(preview_dialog);
+    started_observer.WaitForDialogStarted();
+    started = started_observer.dialog_started();
+  }
+
+  if (started) {
+    // Dismiss the dialog.
+    PrintPreviewDialogDestroyedObserver destroyed_observer(preview_dialog);
+    ASSERT_TRUE(preview_dialog->GetRenderProcessHost()->Shutdown(0, true));
+    if (!destroyed_observer.dialog_destroyed()) {
+      destroyed_observer.WaitForDialogDestroyed();
+      ASSERT_TRUE(destroyed_observer.dialog_destroyed());
+    }
+  }
+  ASSERT_FALSE(GetPrintPreviewDialog());
+
+  // The back navigation should put us back on the first entry.
+  content::WaitForLoadStop(tab);
+  EXPECT_EQ(2, tab->GetController().GetEntryCount());
+  EXPECT_EQ(0, tab->GetController().GetLastCommittedEntryIndex());
+}
+
 // Test to verify that after reloading the initiator, it creates a new print
 // preview dialog.
 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index f520e2a5..dabbbb8 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -44,7 +44,6 @@
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
-#include "chrome/browser/net/net_pref_observer.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/net/proxy_service_factory.h"
 #include "chrome/browser/permissions/permission_manager.h"
@@ -847,12 +846,6 @@
       CreateBrowserContextServices(this);
   }
 
-  DCHECK(!net_pref_observer_);
-  {
-    TRACE_EVENT0("browser", "ProfileImpl::OnPrefsLoaded:NetPrefObserver")
-    net_pref_observer_.reset(new NetPrefObserver(prefs_.get()));
-  }
-
   ChromeVersionService::OnProfileLoaded(prefs_.get(), IsNewProfile());
   DoFinalInit();
 }
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 54d435d5..07fec4b 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -220,8 +220,8 @@
       pref_validation_delegate_;
 
   // Keep |prefs_| on top for destruction order because |extension_prefs_|,
-  // |net_pref_observer_|, |io_data_| and others store pointers to |prefs_| and
-  // shall be destructed first.
+  // |io_data_| and others store pointers to |prefs_| and shall be destructed
+  // first.
   scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry_;
   std::unique_ptr<syncable_prefs::PrefServiceSyncable> prefs_;
   std::unique_ptr<syncable_prefs::PrefServiceSyncable> otr_prefs_;
@@ -230,7 +230,6 @@
   scoped_refptr<ExtensionSpecialStoragePolicy>
       extension_special_storage_policy_;
 #endif
-  std::unique_ptr<NetPrefObserver> net_pref_observer_;
   std::unique_ptr<ssl_config::SSLConfigServiceManager>
       ssl_config_service_manager_;
 
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_zh-CN.xtb b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_zh-CN.xtb
index cb400ab..c53ddf44 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_zh-CN.xtb
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_zh-CN.xtb
@@ -297,7 +297,7 @@
 <translation id="3795836767122514678">+{COUNT,plural, =1{#}other{#}}</translation>
 <translation id="3801735343383419236">自动填充列表</translation>
 <translation id="3810838688059735925">视频</translation>
-<translation id="3812237531158591503">粘贴“$1”。</translation>
+<translation id="3812237531158591503">粘贴 $1。</translation>
 <translation id="3816633764618089385">下一个媒体内容</translation>
 <translation id="3819376190738087562">无跳转内容。</translation>
 <translation id="385383972552776628">打开选项页面</translation>
@@ -554,7 +554,7 @@
 <translation id="6355910664415701303">不存在上一个列表项。</translation>
 <translation id="6364795331201459219">6级标题标记</translation>
 <translation id="6368143427468974988">上一个标题</translation>
-<translation id="6378565991815958969">复制“$1”。</translation>
+<translation id="6378565991815958969">复制 $1。</translation>
 <translation id="6387719785439924554">边栏内容标记</translation>
 <translation id="6411426777058107714">不存在上一个单选按钮。</translation>
 <translation id="6414968628640960377">上一个不同元素。</translation>
@@ -781,7 +781,7 @@
 <translation id="9077213568694924680">已从所选文字中移除</translation>
 <translation id="9082874451376019682">不存在上一个滑块。</translation>
 <translation id="9089864840575085222">循环输入回显</translation>
-<translation id="9105227991373418255">剪切“$1”。</translation>
+<translation id="9105227991373418255">剪切 $1。</translation>
 <translation id="9107530006868467849">不存在上一个媒体小部件。</translation>
 <translation id="9108370397979208512">数学</translation>
 <translation id="9108589040018540527">scbr</translation>
diff --git a/chrome/browser/resources/extensions/compiled_resources2.gyp b/chrome/browser/resources/extensions/compiled_resources2.gyp
index c7956d7..248d1e3a2 100644
--- a/chrome/browser/resources/extensions/compiled_resources2.gyp
+++ b/chrome/browser/resources/extensions/compiled_resources2.gyp
@@ -11,5 +11,14 @@
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
+    {
+      'target_name': 'drag_and_drop_handler',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:drag_wrapper',
+      ],
+      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
   ]
 }
diff --git a/chrome/browser/resources/extensions/drag_and_drop_handler.js b/chrome/browser/resources/extensions/drag_and_drop_handler.js
new file mode 100644
index 0000000..9643f5e
--- /dev/null
+++ b/chrome/browser/resources/extensions/drag_and_drop_handler.js
@@ -0,0 +1,96 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('extensions', function() {
+  'use strict';
+
+  /**
+   * @param {boolean} dragEnabled
+   * @param {!EventTarget} target
+   * @constructor
+   * @implements cr.ui.DragWrapperDelegate
+   */
+  function DragAndDropHandler(dragEnabled, target) {
+    this.dragEnabled = dragEnabled;
+    /** @private {!EventTarget} */
+    this.eventTarget_ = target;
+  }
+
+  // TODO(devlin): Un-chrome.send-ify this implementation.
+  DragAndDropHandler.prototype = {
+    /** @type {boolean} */
+    dragEnabled: false,
+
+    /** @override */
+    shouldAcceptDrag: function(e) {
+      // External Extension installation can be disabled globally, e.g. while a
+      // different overlay is already showing.
+      if (!this.dragEnabled)
+        return false;
+
+      // We can't access filenames during the 'dragenter' event, so we have to
+      // wait until 'drop' to decide whether to do something with the file or
+      // not.
+      // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p
+      return !!e.dataTransfer.types &&
+             e.dataTransfer.types.indexOf('Files') > -1;
+    },
+
+    /** @override */
+    doDragEnter: function() {
+      chrome.send('startDrag');
+      this.eventTarget_.dispatchEvent(
+          new CustomEvent('extension-drag-started'));
+    },
+
+    /** @override */
+    doDragLeave: function() {
+      this.fireDragEnded_();
+      chrome.send('stopDrag');
+    },
+
+    /** @override */
+    doDragOver: function(e) {
+      e.preventDefault();
+    },
+
+    /** @override */
+    doDrop: function(e) {
+      this.fireDragEnded_();
+      if (e.dataTransfer.files.length != 1)
+        return;
+
+      var toSend = '';
+      // Files lack a check if they're a directory, but we can find out through
+      // its item entry.
+      for (var i = 0; i < e.dataTransfer.items.length; ++i) {
+        if (e.dataTransfer.items[i].kind == 'file' &&
+            e.dataTransfer.items[i].webkitGetAsEntry().isDirectory) {
+          toSend = 'installDroppedDirectory';
+          break;
+        }
+      }
+      // Only process files that look like extensions. Other files should
+      // navigate the browser normally.
+      if (!toSend &&
+          /\.(crx|user\.js|zip)$/i.test(e.dataTransfer.files[0].name)) {
+        toSend = 'installDroppedFile';
+      }
+
+      if (toSend) {
+        e.preventDefault();
+        chrome.send(toSend);
+      }
+    },
+
+     /** @private */
+    fireDragEnded_: function() {
+      this.eventTarget_.dispatchEvent(new CustomEvent('extension-drag-ended'));
+    }
+  };
+
+  return {
+    DragAndDropHandler: DragAndDropHandler,
+  };
+});
diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js
index ceeea64..fbf7b3cb 100644
--- a/chrome/browser/resources/extensions/extensions.js
+++ b/chrome/browser/resources/extensions/extensions.js
@@ -5,6 +5,7 @@
 <include src="../../../../ui/webui/resources/js/cr/ui/focus_row.js">
 <include src="../../../../ui/webui/resources/js/cr/ui/focus_grid.js">
 <include src="../uber/uber_utils.js">
+<include src="drag_and_drop_handler.js">
 <include src="extension_code.js">
 <include src="extension_commands_overlay.js">
 <include src="extension_error_overlay.js">
@@ -26,76 +27,6 @@
 cr.define('extensions', function() {
   var ExtensionList = extensions.ExtensionList;
 
-  // Implements the DragWrapper handler interface.
-  var dragWrapperHandler = {
-    /** @override */
-    shouldAcceptDrag: function(e) {
-      // External Extension installation can be disabled globally, e.g. while a
-      // different overlay is already showing.
-      if (!ExtensionSettings.getInstance().dragEnabled_)
-        return false;
-
-      // We can't access filenames during the 'dragenter' event, so we have to
-      // wait until 'drop' to decide whether to do something with the file or
-      // not.
-      // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p
-      return (e.dataTransfer.types &&
-              e.dataTransfer.types.indexOf('Files') > -1);
-    },
-    /** @override */
-    doDragEnter: function() {
-      chrome.send('startDrag');
-      ExtensionSettings.showOverlay($('drop-target-overlay'));
-    },
-    /** @override */
-    doDragLeave: function() {
-      this.hideDropTargetOverlay_();
-      chrome.send('stopDrag');
-    },
-    /** @override */
-    doDragOver: function(e) {
-      e.preventDefault();
-    },
-    /** @override */
-    doDrop: function(e) {
-      this.hideDropTargetOverlay_();
-      if (e.dataTransfer.files.length != 1)
-        return;
-
-      var toSend = null;
-      // Files lack a check if they're a directory, but we can find out through
-      // its item entry.
-      for (var i = 0; i < e.dataTransfer.items.length; ++i) {
-        if (e.dataTransfer.items[i].kind == 'file' &&
-            e.dataTransfer.items[i].webkitGetAsEntry().isDirectory) {
-          toSend = 'installDroppedDirectory';
-          break;
-        }
-      }
-      // Only process files that look like extensions. Other files should
-      // navigate the browser normally.
-      if (!toSend &&
-          /\.(crx|user\.js|zip)$/i.test(e.dataTransfer.files[0].name)) {
-        toSend = 'installDroppedFile';
-      }
-
-      if (toSend) {
-        e.preventDefault();
-        chrome.send(toSend);
-      }
-    },
-
-    /**
-     * Hide the current overlay if it is the drop target overlay.
-     * @private
-     */
-    hideDropTargetOverlay_: function() {
-      var currentOverlay = ExtensionSettings.getCurrentOverlay();
-      if (currentOverlay && currentOverlay.id === 'drop-target-overlay')
-        ExtensionSettings.showOverlay(null);
-    }
-  };
-
   /**
    * ExtensionSettings class
    * @class
@@ -107,8 +38,6 @@
   cr.addSingletonGetter(ExtensionSettings);
 
   ExtensionSettings.prototype = {
-    __proto__: HTMLDivElement.prototype,
-
     /**
      * The drag-drop wrapper for installing external Extensions, if available.
      * null if external Extension installation is not available.
@@ -182,9 +111,20 @@
           this.handleUpdateExtensionNow_.bind(this));
 
       if (!loadTimeData.getBoolean('offStoreInstallEnabled')) {
-        this.dragWrapper_ = new cr.ui.DragWrapper(document.documentElement,
-                                                  dragWrapperHandler);
-        this.dragEnabled_ = true;
+        var dragTarget = document.documentElement;
+        /** @private {extensions.DragAndDropHandler} */
+        this.dragWrapperHandler_ =
+            new extensions.DragAndDropHandler(true, dragTarget);
+        dragTarget.addEventListener('extension-drag-started', function() {
+          ExtensionSettings.showOverlay($('drop-target-overlay'));
+        });
+        dragTarget.addEventListener('extension-drag-ended', function() {
+          var overlay = ExtensionSettings.getCurrentOverlay();
+          if (overlay && overlay.id === 'drop-target-overlay')
+            ExtensionSettings.showOverlay(null);
+        });
+        this.dragWrapper_ =
+            new cr.ui.DragWrapper(dragTarget, this.dragWrapperHandler_);
       }
 
       extensions.PackExtensionOverlay.getInstance().initializePage();
@@ -428,8 +368,10 @@
     // drag-drop when there is any overlay showing other than the usual overlay
     // shown when drag-drop is started.
     var settings = ExtensionSettings.getInstance();
-    if (settings.dragWrapper_)
-      settings.dragEnabled_ = !node || node == $('drop-target-overlay');
+    if (settings.dragWrapper_) {
+      assert(settings.dragWrapperHandler_).dragEnabled =
+          !node || node == $('drop-target-overlay');
+    }
 
     uber.invokeMethodOnParent(node ? 'beginInterceptingEvents' :
                                      'stopInterceptingEvents');
diff --git a/chrome/browser/resources/md_downloads/crisper.js b/chrome/browser/resources/md_downloads/crisper.js
index 270d4d29..cf866b17 100644
--- a/chrome/browser/resources/md_downloads/crisper.js
+++ b/chrome/browser/resources/md_downloads/crisper.js
@@ -10572,6 +10572,11 @@
   toggleShowingSearch_: function() {
     this.showingSearch = !this.showingSearch;
   },
+
+  /** @return {boolean} */
+  isSearchFocused: function() {
+    return this.$.searchTerm.focused;
+  }
 };
 (function() {
       'use strict';
diff --git a/chrome/browser/resources/md_downloads/downloads.html b/chrome/browser/resources/md_downloads/downloads.html
index 562b28c..28c8b234 100644
--- a/chrome/browser/resources/md_downloads/downloads.html
+++ b/chrome/browser/resources/md_downloads/downloads.html
@@ -23,12 +23,13 @@
 </head>
 <body>
   <downloads-manager></downloads-manager>
-  <command id="clear-all-command" shortcut="Alt|c">
 <if expr="is_macosx">
+  <command id="clear-all-command" shortcut="Alt|c Alt|ç">
   <command id="undo-command" shortcut="Meta|z">
   <command id="find-command" shortcut="Meta|f">
 </if>
 <if expr="not is_macosx">
+  <command id="clear-all-command" shortcut="Alt|c">
   <command id="undo-command" shortcut="Ctrl|z">
   <command id="find-command" shortcut="Ctrl|f">
 </if>
diff --git a/chrome/browser/resources/md_downloads/vulcanized.html b/chrome/browser/resources/md_downloads/vulcanized.html
index 4f54cac8..09f1165 100644
--- a/chrome/browser/resources/md_downloads/vulcanized.html
+++ b/chrome/browser/resources/md_downloads/vulcanized.html
@@ -2764,12 +2764,13 @@
   </dom-module>
 </div>
   <downloads-manager></downloads-manager>
-  <command id="clear-all-command" shortcut="Alt|c"></command>
 <if expr="is_macosx">
+  <command id="clear-all-command" shortcut="Alt|c Alt|ç"></command>
   <command id="undo-command" shortcut="Meta|z"></command>
   <command id="find-command" shortcut="Meta|f"></command>
 </if>
 <if expr="not is_macosx">
+  <command id="clear-all-command" shortcut="Alt|c"></command>
   <command id="undo-command" shortcut="Ctrl|z"></command>
   <command id="find-command" shortcut="Ctrl|f"></command>
 </if>
diff --git a/chrome/browser/resources/ntp4/nav_dot.js b/chrome/browser/resources/ntp4/nav_dot.js
index 7703f31..98f0278 100644
--- a/chrome/browser/resources/ntp4/nav_dot.js
+++ b/chrome/browser/resources/ntp4/nav_dot.js
@@ -19,6 +19,7 @@
    * @param {boolean} animate If true, animates into existence.
    * @constructor
    * @extends {HTMLLIElement}
+   * @implements {cr.ui.DragWrapperDelegate}
    */
   function NavDot(page, title, titleIsEditable, animate) {
     var dot = cr.doc.createElement('li');
@@ -189,12 +190,7 @@
       return this.page_.shouldAcceptDrag(e);
     },
 
-    /**
-     * A drag has entered the navigation dot. If the user hovers long enough,
-     * we will navigate to the relevant page.
-     * @param {Event} e The MouseOver event for the drag.
-     * @private
-     */
+    /** @override */
     doDragEnter: function(e) {
       var self = this;
       function navPageClearTimeout() {
@@ -206,14 +202,9 @@
       this.doDragOver(e);
     },
 
-    /**
-     * A dragged element has moved over the navigation dot. Show the correct
-     * indicator and prevent default handling so the <input> won't act as a drag
-     * target.
-     * @param {Event} e The MouseOver event for the drag.
-     * @private
-     */
+    /** @override */
     doDragOver: function(e) {
+      // Prevent default handling so the <input> won't act as a drag target.
       e.preventDefault();
 
       if (!this.dragWrapper_.isCurrentDragTarget)
@@ -222,12 +213,7 @@
         this.page_.setDropEffect(e.dataTransfer);
     },
 
-    /**
-     * A dragged element has been dropped on the navigation dot. Tell the page
-     * to append it.
-     * @param {Event} e The MouseOver event for the drag.
-     * @private
-     */
+    /** @override */
     doDrop: function(e) {
       e.stopPropagation();
       var tile = ntp.getCurrentlyDraggingTile();
@@ -238,11 +224,7 @@
       this.cancelDelayedSwitch_();
     },
 
-    /**
-     * The drag has left the navigation dot.
-     * @param {Event} e The MouseOver event for the drag.
-     * @private
-     */
+    /** @override */
     doDragLeave: function(e) {
       this.cancelDelayedSwitch_();
     },
diff --git a/chrome/browser/resources/ntp4/tile_page.js b/chrome/browser/resources/ntp4/tile_page.js
index 8f37a1f8..ca032ca 100644
--- a/chrome/browser/resources/ntp4/tile_page.js
+++ b/chrome/browser/resources/ntp4/tile_page.js
@@ -359,6 +359,7 @@
    *     of the tile grid.
    * @constructor
    * @extends {HTMLDivElement}
+   * @implements {cr.ui.DragWrapperDelegate}
    */
   function TilePage(gridValues) {
     var el = cr.doc.createElement('div');
@@ -1145,18 +1146,12 @@
       return this.dragWrapper_.isCurrentDragTarget;
     },
 
-    /**
-     * Thunk for dragleave events fired on |tileGrid_|.
-     * @param {Event} e A MouseEvent for the drag.
-     */
+    /** @override */
     doDragLeave: function(e) {
       this.cleanupDrag();
     },
 
-    /**
-     * Performs all actions necessary when a drag enters the tile page.
-     * @param {Event} e A mouseover event for the drag enter.
-     */
+    /** @override */
     doDragEnter: function(e) {
       // Applies the mask so doppleganger tiles disappear into the fog.
       this.updateMask_();
@@ -1175,11 +1170,7 @@
       this.doDragOver(e);
     },
 
-    /**
-     * Performs all actions necessary when the user moves the cursor during
-     * a drag over the tile page.
-     * @param {Event} e A mouseover event for the drag over.
-     */
+    /** @override */
     doDragOver: function(e) {
       e.preventDefault();
 
@@ -1190,10 +1181,7 @@
       this.updateDropIndicator_(newDragIndex);
     },
 
-    /**
-     * Performs all actions necessary when the user completes a drop.
-     * @param {Event} e A mouseover event for the drag drop.
-     */
+    /** @override */
     doDrop: function(e) {
       e.stopPropagation();
       e.preventDefault();
diff --git a/chrome/browser/resources/ntp4/trash.js b/chrome/browser/resources/ntp4/trash.js
index 463232cb4..510348a 100644
--- a/chrome/browser/resources/ntp4/trash.js
+++ b/chrome/browser/resources/ntp4/trash.js
@@ -12,6 +12,8 @@
 
   /**
    * @constructor
+   * @extends {HTMLDivElement}
+   * @implements {cr.ui.DragWrapperDelegate}
    */
   function Trash(trash) {
     trash.__proto__ = Trash.prototype;
@@ -39,10 +41,7 @@
       return tile.firstChild.canBeRemoved();
     },
 
-    /**
-     * Drag over handler.
-     * @param {Event} e The drag event.
-     */
+    /** @override */
     doDragOver: function(e) {
       ntp.getCurrentlyDraggingTile().dragClone.classList.add(
           'hovering-on-trash');
@@ -50,18 +49,12 @@
       e.preventDefault();
     },
 
-    /**
-     * Drag enter handler.
-     * @param {Event} e The drag event.
-     */
+    /** @override */
     doDragEnter: function(e) {
       this.doDragOver(e);
     },
 
-    /**
-     * Drop handler.
-     * @param {Event} e The drag event.
-     */
+    /** @override */
     doDrop: function(e) {
       e.preventDefault();
 
@@ -70,10 +63,7 @@
       tile.landedOnTrash = true;
     },
 
-    /**
-     * Drag leave handler.
-     * @param {Event} e The drag event.
-     */
+    /** @override */
     doDragLeave: function(e) {
       ntp.getCurrentlyDraggingTile().dragClone.classList.remove(
           'hovering-on-trash');
diff --git a/chrome/browser/resources/offline_pages/offline_internals.css b/chrome/browser/resources/offline_pages/offline_internals.css
index a17f04b3..b37a1dc9b 100644
--- a/chrome/browser/resources/offline_pages/offline_internals.css
+++ b/chrome/browser/resources/offline_pages/offline_internals.css
@@ -23,10 +23,14 @@
   padding: 5px;
 }
 
+table {
+  margin-bottom: 5px;
+}
+
 ul {
   border: 1px solid;
   list-style-type: none;
-  margin: 0;
+  margin-top: 5px;
   max-height: 300px;
   overflow: auto;
   padding: 5px;
@@ -42,3 +46,7 @@
 li:nth-child(2n) {
   background-color: lavender;
 }
+
+#current-status {
+  font-size: 15px;
+}
diff --git a/chrome/browser/resources/offline_pages/offline_internals.html b/chrome/browser/resources/offline_pages/offline_internals.html
index 9045a8ee..edb60fff 100644
--- a/chrome/browser/resources/offline_pages/offline_internals.html
+++ b/chrome/browser/resources/offline_pages/offline_internals.html
@@ -17,7 +17,7 @@
   <body>
     <h1>Offline Internals</h1>
     <div>
-      <div id="current-status"></div>
+      <span id="current-status"></span>
       <button id="refresh">Refresh page</button>
       <button id="download">Dump</button>
     </div>
@@ -68,5 +68,8 @@
       </thead>
       <tbody id="request-queue"> </tbody>
     </table>
+    <input id="url" type="url">
+    <button id="add-to-queue">Load in background</button>
+    <div id="save-url-state"></div>
   </body>
 </html>
diff --git a/chrome/browser/resources/offline_pages/offline_internals.js b/chrome/browser/resources/offline_pages/offline_internals.js
index 3bfde97..4112e45 100644
--- a/chrome/browser/resources/offline_pages/offline_internals.js
+++ b/chrome/browser/resources/offline_pages/offline_internals.js
@@ -37,7 +37,10 @@
       row.appendChild(checkboxCell);
 
       var cell = document.createElement('td');
-      cell.textContent = pages[i].onlineUrl;
+      var link = document.createElement('a');
+      link.setAttribute('href', pages[i].filePath);
+      link.textContent = pages[i].onlineUrl;
+      cell.appendChild(link);
       row.appendChild(cell);
 
       cell = document.createElement('td');
@@ -106,6 +109,9 @@
   function refreshAll() {
     browserProxy_.getStoredPages().then(fillStoredPages);
     browserProxy_.getRequestQueue().then(fillRequestQueue);
+    browserProxy_.getNetworkStatus().then(function(networkStatus) {
+      $('current-status').textContent = networkStatus;
+    });
     refreshLog();
   }
 
@@ -173,19 +179,47 @@
   }
 
   function initialize() {
+    /**
+     * @param {!boolean} enabled Whether to enable Logging.
+     */
+    function togglePageModelLog(enabled) {
+      browserProxy_.setRecordPageModel(enabled);
+      $('model-status').textContent = enabled ? 'On' : 'Off';
+    }
+
+    /**
+     * @param {!boolean} enabled Whether to enable Logging.
+     */
+    function toggleRequestQueueLog(enabled) {
+      browserProxy_.setRecordRequestQueue(enabled);
+      $('request-status').textContent = enabled ? 'On' : 'Off';
+    }
+
     $('clear-all').onclick = deleteAllPages;
     $('clear-selected').onclick = deleteSelectedPages;
     $('refresh').onclick = refreshAll;
     $('download').onclick = download;
-    $('log-model-on').onclick =
-        browserProxy_.setRecordPageModel.bind(browserProxy_, true);
-    $('log-model-off').onclick =
-        browserProxy_.setRecordPageModel.bind(browserProxy_, false);
-    $('log-request-on').onclick =
-        browserProxy_.setRecordRequestQueue.bind(browserProxy_, true);
-    $('log-request-off').onclick =
-        browserProxy_.setRecordRequestQueue.bind(browserProxy_, false);
+    $('log-model-on').onclick = togglePageModelLog.bind(this, true);
+    $('log-model-off').onclick = togglePageModelLog.bind(this, false);
+    $('log-request-on').onclick = toggleRequestQueueLog.bind(this, true);
+    $('log-request-off').onclick = toggleRequestQueueLog.bind(this, false);
     $('refresh-logs').onclick = refreshLog;
+    $('add-to-queue').onclick = function() {
+      var saveUrl = $('url').value;
+      browserProxy_.addToRequestQueue(saveUrl)
+        .then(function(state) {
+          if (state) {
+            $('save-url-state').textContent =
+              saveUrl + ' has been added to queue.';
+            $('url').value = '';
+            browserProxy_.getRequestQueue().then(fillRequestQueue);
+          } else {
+            $('save-url-state').textContent =
+              saveUrl + ' failed to be added to queue.';
+          }
+        });
+    };
+
     refreshAll();
   }
 
diff --git a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
index f3312fb..1316c9d69 100644
--- a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
+++ b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
@@ -95,6 +95,21 @@
      *     is retrieved.
      */
     getLoggingState: function() {},
+
+    /**
+     * Adds the given url to the background loader queue.
+     * @param {string} url Url of the page to load later.
+     * @return {!Promise<boolean>} A promise firing after added to queue.
+     *     Promise will return true if url has been successfully added.
+     */
+    addToRequestQueue: function(url) {},
+
+    /**
+     * Gets the current network status in string form.
+     * @return {!Promise<string>} A promise firing when the network status
+     *     is retrieved.
+     */
+    getNetworkStatus: function() {},
   };
 
   /**
@@ -143,7 +158,17 @@
     /** @override */
     getLoggingState: function() {
       return cr.sendWithPromise('getLoggingState');
-    }
+    },
+
+    /** @override */
+    addToRequestQueue: function(url) {
+      return cr.sendWithPromise('addToRequestQueue', url);
+    },
+
+    /** @override */
+    getNetworkStatus: function() {
+      return cr.sendWithPromise('getNetworkStatus');
+    },
   };
 
   return {
diff --git a/chrome/browser/resources/settings/about_page/detailed_build_info.html b/chrome/browser/resources/settings/about_page/detailed_build_info.html
index 6e87415..d013e3f 100644
--- a/chrome/browser/resources/settings/about_page/detailed_build_info.html
+++ b/chrome/browser/resources/settings/about_page/detailed_build_info.html
@@ -15,18 +15,14 @@
         -webkit-user-select: text;
       }
     </style>
-    <div class="settings-box two-line">
-      <div class="start">
-        <div>$i18n{aboutPlatformLabel}</div>
-        <div class="secondary" id="osVersion">[[versionInfo_.osVersion]]</div>
-      </div>
+    <div class="settings-box two-line single-column">
+      <div>$i18n{aboutPlatformLabel}</div>
+      <div class="secondary" id="osVersion">[[versionInfo_.osVersion]]</div>
     </div>
-    <div class="settings-box two-line"
+    <div class="settings-box two-line single-column"
         hidden$="[[!shouldShowVersion_(versionInfo_.osFirmware)]]">
-      <div class="start">
-        <div>$i18n{aboutFirmwareLabel}</div>
-        <div class="secondary" id="osFirmware">[[versionInfo_.osFirmware]]</div>
-      </div>
+      <div>$i18n{aboutFirmwareLabel}</div>
+      <div class="secondary" id="osFirmware">[[versionInfo_.osFirmware]]</div>
     </div>
     <div class="settings-box two-line">
       <div class="start">
@@ -44,42 +40,30 @@
         <settings-channel-switcher-dialog></settings-channel-switcher-dialog>
       </template>
     </div>
-    <div class="settings-box two-line"
+    <div class="settings-box two-line single-column"
         hidden$="[[!shouldShowVersion_(versionInfo_.arcVersion)]]">
-      <div class="start">
-        <div>$i18n{aboutArcVersionLabel}</div>
-        <div class="secondary" id="arcVersion">[[versionInfo_.arcVersion]]</div>
-      </div>
+      <div>$i18n{aboutArcVersionLabel}</div>
+      <div class="secondary" id="arcVersion">[[versionInfo_.arcVersion]]</div>
     </div>
-    <div class="settings-box two-line">
-      <div class="start">
-        <div>Blink</div><!-- No need to localize. -->
-        <div class="secondary">$i18n{aboutBlinkVersion}</div>
-      </div>
+    <div class="settings-box two-line single-column">
+      <div>Blink</div><!-- No need to localize. -->
+      <div class="secondary">$i18n{aboutBlinkVersion}</div>
     </div>
-    <div class="settings-box two-line">
-      <div class="start">
-        <div>V8</div>
-        <div class="secondary">$i18n{aboutJsEngineVersion}</div>
-      </div>
+    <div class="settings-box two-line single-column">
+      <div>V8</div>
+      <div class="secondary">$i18n{aboutJsEngineVersion}</div>
     </div>
-    <div class="settings-box two-line">
-      <div class="start">
-        <div>$i18n{aboutUserAgentLabel}</div>
-        <div class="secondary">$i18n{aboutUserAgent}</div>
-      </div>
+    <div class="settings-box two-line single-column">
+      <div>$i18n{aboutUserAgentLabel}</div>
+      <div class="secondary">$i18n{aboutUserAgent}</div>
     </div>
-    <div class="settings-box two-line">
-      <div class="start">
-        <div>$i18n{aboutCommandLineLabel}</div>
-        <div class="secondary">$i18n{aboutCommandLine}</div>
-      </div>
+    <div class="settings-box two-line single-column">
+      <div>$i18n{aboutCommandLineLabel}</div>
+      <div class="secondary">$i18n{aboutCommandLine}</div>
     </div>
-    <div class="settings-box two-line">
-      <div class="start">
-        <div>$i18n{aboutBuildDateLabel}</div>
-        <div class="secondary">$i18n{aboutBuildDate}</div>
-      </div>
+    <div class="settings-box two-line single-column">
+      <div>$i18n{aboutBuildDateLabel}</div>
+      <div class="secondary">$i18n{aboutBuildDate}</div>
     </div>
   </template>
   <script src="detailed_build_info.js"></script>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html
index fe6126ea..cc32d8ef 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -97,12 +97,10 @@
               menu-options="[[fontSizeOptions_]]" no-label-float>
           </settings-dropdown-menu>
         </div>
-        <div class="settings-box two-line" on-tap="onCustomizeFontsTap_"
-            actionable>
-          <div class="start">
-            <div>$i18n{customizeFonts}</div>
+        <div class="settings-box two-line single-column"
+            on-tap="onCustomizeFontsTap_" actionable>
+          <div>$i18n{customizeFonts}</div>
           <div class="secondary">$i18n{chooseFontsAndEncoding}</div>
-          </div>
         </div>
         <div class="settings-box">
           <div class="start">$i18n{pageZoom}</div>
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.html b/chrome/browser/resources/settings/controls/settings_checkbox.html
index fb33783..0acdf3d 100644
--- a/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -20,6 +20,13 @@
         @apply(--settings-secondary);
       }
 
+      #nonexistent {
+        /* HACK(michaelpg): Inform Polymer that this mixin can set "display". */
+        --settings-secondary-unchecked: {
+          display: block;
+        };
+      }
+
       paper-checkbox:not([checked]) .secondary {
         @apply(--settings-secondary-unchecked);
       }
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html b/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html
index 30cb333..9fb9bd8 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html
+++ b/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="/settings_root_css.html">
+<link rel="import" href="/settings_vars_css.html">
 
 <dom-module id="network-proxy-exclusions">
   <template>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html b/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
index 9dc708b..c63a3925 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
@@ -67,7 +67,7 @@
         </paper-dropdown-menu>
       </div>
       <div class="button-container">
-        <paper-button id="cancelButton"
+        <paper-button id="cancelButton" class="cancel-button"
             on-tap="onCancelButtonTap_">$i18n{cancel}</paper-button>
         <paper-button id="saveButton" class="action-button"
             on-tap="onSaveButtonTap_">$i18n{save}</paper-button>
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 77f5b73..99001c36 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -155,7 +155,7 @@
         </div>
 
 <if expr="chromeos">
-        <div class="settings-box">
+        <div class="settings-box single-column">
           <settings-checkbox pref="{{prefs.settings.enable_screen_lock}}"
               label="$i18n{enableScreenlock}">
           </settings-checkbox>
@@ -163,7 +163,7 @@
 
         <!-- TODO(jdufault): Disable navigating to /quickUnlock/* if pin is
           disabled. -->
-        <template is="dom-if" if=[[quickUnlockAllowed_]]>
+        <template is="dom-if" if=[[quickUnlockEnabled_]]>
           <div class="settings-box">
             <paper-button on-tap="onQuickUnlockTap_" class="primary-button">
               $i18n{quickUnlockTitle}
@@ -296,7 +296,9 @@
   </if>
       </div>
       <div class="button-container">
-        <paper-button on-tap="onDisconnectCancel_">$i18n{cancel}</paper-button>
+        <paper-button on-tap="onDisconnectCancel_" class="cancel-button">
+          $i18n{cancel}
+        </paper-button>
         <paper-button id="disconnectConfirm" class="action-button"
             hidden=[[syncStatus.domain]] on-tap="onDisconnectConfirm_">
           $i18n{syncDisconnect}
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js
index e212ad1..78452d1 100644
--- a/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -64,10 +64,11 @@
      * True if quick unlock settings should be displayed on this machine.
      * @private
      */
-    quickUnlockAllowed_: {
+    quickUnlockEnabled_: {
       type: Boolean,
-      // TODO(jdufault): Get a real value via quickUnlockPrivate API.
-      value: false,
+      value: function() {
+        return loadTimeData.getBoolean('quickUnlockEnabled');
+      },
       readOnly: true,
     },
 
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index 42a8d2d0..88fc263 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -123,23 +123,15 @@
           </paper-checkbox>
         </div>
 
-        <div class="settings-box two-line" on-tap="onManageSyncedDataTap_"
-            actionable>
-          <div class="start">
-            $i18n{manageSyncedDataTitle}
-            <div class="secondary">
-              $i18n{manageSyncedDataDescription}
-            </div>
-          </div>
+        <div class="settings-box two-line single-column" actionable
+            on-tap="onManageSyncedDataTap_">
+          <div>$i18n{manageSyncedDataTitle}</div>
+          <div class="secondary">$i18n{manageSyncedDataDescription}</div>
         </div>
 
-        <div class="settings-box two-line">
-          <div class="start">
-            $i18n{encryptionOptionsTitle}
-            <div class="secondary">
-              $i18n{syncDataEncryptedText}
-            </div>
-          </div>
+        <div class="settings-box two-line single-column">
+          <div>$i18n{encryptionOptionsTitle}</div>
+          <div class="secondary">$i18n{syncDataEncryptedText}</div>
         </div>
 
         <div id="encryptionRadioGroupContainer" class="list-frame"
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index b76b91d..7cb2437 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -84,20 +84,16 @@
 </if>
         </div>
 <if expr="use_nss_certs or is_win or is_macosx">
-        <div id="manageCertificates" class="settings-box two-line" actionable
-            on-tap="onManageCertificatesTap_">
-          <div class="start">
-            <div>$i18n{manageCertificates}</div>
-            <div class="secondary">$i18n{manageCertificatesDescription}</div>
-          </div>
+        <div id="manageCertificates" class="settings-box two-line single-column"
+            actionable on-tap="onManageCertificatesTap_">
+          <div>$i18n{manageCertificates}</div>
+          <div class="secondary">$i18n{manageCertificatesDescription}</div>
         </div>
 </if>
-        <div class="settings-box two-line" on-tap="onSiteSettingsTap_"
-            actionable>
-          <div class="start">
-            <div>$i18n{siteSettings}</div>
-            <div class="secondary">$i18n{siteSettingsDescription}</div>
-          </div>
+        <div class="settings-box two-line single-column" actionable
+            on-tap="onSiteSettingsTap_">
+          <div>$i18n{siteSettings}</div>
+          <div class="secondary">$i18n{siteSettingsDescription}</div>
         </div>
         <div class="settings-box">
           <paper-button on-tap="onClearBrowsingDataTap_" class="primary-button">
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.html b/chrome/browser/resources/settings/reset_page/reset_page.html
index a7f090b..2888b515d 100644
--- a/chrome/browser/resources/settings/reset_page/reset_page.html
+++ b/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -10,20 +10,16 @@
 <dom-module id="settings-reset-page">
   <template>
     <style include="settings-shared"></style>
-    <div class="settings-box first two-line" id="resetProfile"
+    <div class="settings-box first two-line single-column" id="resetProfile"
         on-tap="onShowResetProfileDialog_" actionable>
-      <div>
-        <div>$i18n{resetPageTitle}</div>
-        <div class="secondary">$i18n{resetPageDescription}</div>
-      </div>
+      <div>$i18n{resetPageTitle}</div>
+      <div class="secondary">$i18n{resetPageDescription}</div>
     </div>
 <if expr="chromeos">
-    <div class="settings-box two-line" id="powerwash" actionable
+    <div class="settings-box two-line single-column" id="powerwash" actionable
         on-tap="onShowPowerwashDialog_" hidden="[[!allowPowerwash_]]">
-      <div>
-        <div>$i18n{powerwashTitle}</div>
-        <div class="secondary">$i18n{powerwashDescription}</div>
-      </div>
+      <div>$i18n{powerwashTitle}</div>
+      <div class="secondary">$i18n{powerwashDescription}</div>
     </div>
 </if>
   </template>
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html
index 5e1dc30..0b246634 100644
--- a/chrome/browser/resources/settings/settings.html
+++ b/chrome/browser/resources/settings/settings.html
@@ -8,7 +8,7 @@
   <link rel="import" href="/direction_delegate.html">
   <link rel="import" href="/settings_ui/settings_ui.html">
   <link rel="import" href="/prefs/prefs.html">
-  <link rel="import" href="/settings_root_css.html">
+  <link rel="import" href="/settings_vars_css.html">
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
 </head>
 <body>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html
index 990c85c..2c9a01d9 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -7,7 +7,7 @@
 <link rel="import" href="/basic_page/basic_page.html">
 <link rel="import" href="/settings_main/settings_main_rendered.html">
 <link rel="import" href="/settings_page/main_page_behavior.html">
-<link rel="import" href="/settings_root_css.html">
+<link rel="import" href="/settings_vars_css.html">
 
 <dom-module id="settings-main">
   <template>
@@ -38,25 +38,26 @@
       }
     </style>
     <content select="paper-icon-button"></content>
-    <template is="dom-if" if="[[showBasicPage_]]">
+    <template is="dom-if" if="[[showPages_.basic]]">
       <settings-basic-page prefs="{{prefs}}" current-route="{{currentRoute}}">
       </settings-basic-page>
     </template>
-    <template is="dom-if" if="[[showAdvancedToggle_]]">
+    <template is="dom-if"
+        if="[[showAdvancedToggle_(showPages_.basic, inSubpage_)]]">
       <div id="toggleSpacer"></div>
       <div id="toggleContainer">
         <div id="advancedToggle" on-tap="toggleAdvancedPage_">
           <span>$i18n{advancedPageTitle}</span>
-          <iron-icon icon="[[arrowState_(showAdvancedPage_)]]"></iron-icon>
+          <iron-icon icon="[[arrowState_(showPages_.advanced)]]"></iron-icon>
         </div>
       </div>
     </template>
-    <template is="dom-if" if="[[showAdvancedPage_]]">
+    <template is="dom-if" if="[[showPages_.advanced]]">
       <settings-advanced-page prefs="{{prefs}}"
           current-route="{{currentRoute}}">
       </settings-advanced-page>
     </template>
-    <template is="dom-if" if="[[showAboutPage_]]">
+    <template is="dom-if" if="[[showPages_.about]]">
       <settings-about-page current-route="{{currentRoute}}">
       </settings-about-page>
     </template>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js
index b23930bc..f80a8512 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.js
+++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -10,12 +10,6 @@
   is: 'settings-main',
 
   properties: {
-    /** @private */
-    isAdvancedMenuOpen_: {
-      type: Boolean,
-      value: false,
-    },
-
     /**
      * Preferences state.
      */
@@ -35,27 +29,24 @@
     },
 
     /** @private */
-    showAdvancedPage_: {
+    advancedToggleExpanded_: {
       type: Boolean,
       value: false,
     },
 
     /** @private */
-    showAdvancedToggle_: {
-      type: Boolean,
-      value: true,
-    },
+    inSubpage_: Boolean,
 
-    /** @private */
-    showBasicPage_: {
-      type: Boolean,
-      value: true,
-    },
-
-    /** @private */
-    showAboutPage_: {
-      type: Boolean,
-      value: false,
+    /**
+     * Controls which main pages are displayed via dom-ifs.
+     * @type {!{about: boolean, basic: boolean, advanced: boolean}}
+     * @private
+     */
+    showPages_: {
+      type: Object,
+      value: function() {
+        return {about: false, basic: false, advanced: false};
+      },
     },
 
     toolbarSpinnerActive: {
@@ -82,10 +73,9 @@
   /** @override */
   attached: function() {
     document.addEventListener('toggle-advanced-page', function(e) {
-      this.showAdvancedPage_ = e.detail;
-      this.isAdvancedMenuOpen_ = e.detail;
+      this.advancedToggleExpanded_ = e.detail;
       this.currentRoute = {
-        page: this.isAdvancedMenuOpen_ ? 'advanced' : 'basic',
+        page: this.advancedToggleExpanded_ ? 'advanced' : 'basic',
         section: '',
         subpage: [],
       };
@@ -105,34 +95,46 @@
    * @param {boolean} opened Whether the menu is expanded.
    * @return {string} Which icon to use.
    * @private
-   * */
+   */
   arrowState_: function(opened) {
     return opened ? 'settings:arrow-drop-up' : 'cr:arrow-drop-down';
   },
 
   /**
+   * @param {boolean} showBasicPage
+   * @param {boolean} inSubpage
+   * @return {boolean}
+   */
+  showAdvancedToggle_: function(showBasicPage, inSubpage) {
+    return showBasicPage && !inSubpage;
+  },
+
+  /**
    * @param {!SettingsRoute} newRoute
    * @private
    */
   currentRouteChanged_: function(newRoute) {
-    var isSubpage = !!newRoute.subpage.length;
+    this.inSubpage_ = newRoute.subpage.length > 0;
+    this.style.height = this.inSubpage_ ? '100%' : '';
 
-    this.showAboutPage_ = newRoute.page == 'about';
+    if (newRoute.page == 'about') {
+      this.showPages_ = {about: true, basic: false, advanced: false};
+    } else {
+      this.showPages_ = {
+        about: false,
+        basic: newRoute.page == 'basic' || !this.inSubpage_,
+        advanced: newRoute.page == 'advanced' ||
+            (!this.inSubpage_ && this.advancedToggleExpanded_),
+      };
 
-    this.showAdvancedToggle_ = !this.showAboutPage_ && !isSubpage;
-
-    this.showBasicPage_ = this.showAdvancedToggle_ || newRoute.page == 'basic';
-
-    this.showAdvancedPage_ =
-        (this.isAdvancedMenuOpen_ && this.showAdvancedToggle_) ||
-        newRoute.page == 'advanced';
-
-    this.style.height = isSubpage ? '100%' : '';
+      if (this.showPages_.advanced)
+        this.advancedToggleExpanded_ = true;
+    }
   },
 
   /** @private */
   toggleAdvancedPage_: function() {
-    this.fire('toggle-advanced-page', !this.isAdvancedMenuOpen_);
+    this.fire('toggle-advanced-page', !this.advancedToggleExpanded_);
   },
 
   /**
@@ -156,13 +158,11 @@
     // Trigger rendering of the basic and advanced pages and search once ready.
     // Even if those are already rendered, yield to the message loop before
     // initiating searching.
-    this.showBasicPage_ = true;
+    this.showPages_ = {about: false, basic: true, advanced: true};
     setTimeout(function() {
       settings.getSearchManager().search(
           query, assert(this.$$('settings-basic-page')));
     }.bind(this), 0);
-
-    this.showAdvancedPage_ = true;
     setTimeout(function() {
       settings.getSearchManager().search(
           query, assert(this.$$('settings-advanced-page')));
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 8671f65..7a22727 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -219,8 +219,8 @@
       <structure name="IDR_SETTINGS_MAIN_PAGE_BEHAVIOR_JS"
                  file="settings_page/main_page_behavior.js"
                  type="chrome_html" />
-      <structure name="IDR_SETTINGS_SETTINGS_ROOT_CSS_HTML"
-                 file="settings_root_css.html"
+      <structure name="IDR_SETTINGS_SETTINGS_VARS_CSS_HTML"
+                 file="settings_vars_css.html"
                  type="chrome_html" />
       <structure name="IDR_SETTINGS_SETTINGS_SHARED_CSS_HTML"
                  file="settings_shared_css.html"
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index ed4b94a..29de8f36 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -1,5 +1,5 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-<link rel="import" href="/settings_root_css.html">
+<link rel="import" href="/settings_vars_css.html">
 
 <!-- Common styles for Material Design settings. -->
 <dom-module id="settings-shared">
@@ -65,7 +65,7 @@
 
       iron-dropdown .dropdown-item:focus,
       paper-dropdown-menu .dropdown-item:focus {
-        background-color: var(--paper-grey-300);
+        background-color: var(--cr-focused-item-color);
         outline: none;
       }
 
@@ -280,8 +280,14 @@
         min-height: 56px;
       }
 
-      [actionable] {
-        @apply(--settings-actionable);
+      /*
+       * A settings box with a single start-aligned column, generally but not
+       * necessarily used in combination with two-line.
+       */
+      .settings-box.single-column {
+        align-items: flex-start;
+        flex-direction: column;
+        justify-content: center;
       }
 
       /* The lower line of text in a .settings-box.two-line. */
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js
index 09ad8f6..4a48a51 100644
--- a/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -66,6 +66,17 @@
     'sideNav.iron-activate': 'onIronActivate_',
   },
 
+  /** @override */
+  ready: function() {
+    this.$$('cr-toolbar').addEventListener('search-changed', function(e) {
+      this.$$('settings-main').searchContents(e.detail);
+    }.bind(this));
+
+    window.addEventListener('popstate', function(e) {
+      this.$$('app-drawer').close();
+    }.bind(this));
+  },
+
   /** @private */
   onCloseAppealTap_: function() {
     window.sessionStorage.appealClosed_ = this.appealClosed_ = true;
@@ -85,13 +96,6 @@
     this.$$('app-drawer').toggle();
   },
 
-  /** @override */
-  ready: function() {
-    this.$$('cr-toolbar').addEventListener('search-changed', function(e) {
-      this.$$('settings-main').searchContents(e.detail);
-    }.bind(this));
-  },
-
   /** @private */
   directionDelegateChanged_: function() {
     this.$$('app-drawer').align = this.directionDelegate.isRtl() ?
diff --git a/chrome/browser/resources/settings/settings_root_css.html b/chrome/browser/resources/settings/settings_vars_css.html
similarity index 88%
rename from chrome/browser/resources/settings/settings_root_css.html
rename to chrome/browser/resources/settings/settings_vars_css.html
index 8bee7d3..d98644d 100644
--- a/chrome/browser/resources/settings/settings_root_css.html
+++ b/chrome/browser/resources/settings/settings_vars_css.html
@@ -1,3 +1,4 @@
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
 <!-- Common css variables for Material Design settings. -->
@@ -23,6 +24,8 @@
     --paper-radio-button-label-color: inherit;
     --paper-radio-group-item-padding: 0;
 
+    --settings-actionable: var(--cr-actionable);
+
     /* Custom grey for Alan (bettes@). */
     --settings-background-color: rgb(241, 241, 241);
     --settings-secondary: {
@@ -39,14 +42,10 @@
     --settings-page-vertical-margin: 21px;
 
     --settings-row-min-height: 44px;
-    --settings-separator-line: 1px solid rgba(0, 0, 0, 0.06);
+    --settings-separator-line: var(--cr-separator-line);
 
     --settings-title-bar-background-color: var(--google-blue-700);
     --settings-title-bar-color: rgb(255, 255, 255);
     --settings-title-search-color: rgb(192, 199, 205);
-
-    --settings-actionable: {
-      cursor: pointer;
-    };
   }
 </style>
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index feea762..eb20851 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -16,7 +16,7 @@
 #include "ash/common/wm/window_state.h"
 #include "ash/common/wm_shell.h"
 #include "ash/content/gpu_support_impl.h"
-#include "ash/pointer_down_watcher_delegate_aura.h"
+#include "ash/pointer_watcher_delegate_aura.h"
 #include "ash/shell.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
@@ -428,9 +428,9 @@
   return shelf_delegate_;
 }
 
-std::unique_ptr<ash::PointerDownWatcherDelegate>
-ChromeShellDelegate::CreatePointerDownWatcherDelegate() {
-  return base::WrapUnique(new ash::PointerDownWatcherDelegateAura);
+std::unique_ptr<ash::PointerWatcherDelegate>
+ChromeShellDelegate::CreatePointerWatcherDelegate() {
+  return base::WrapUnique(new ash::PointerWatcherDelegateAura);
 }
 
 ui::MenuModel* ChromeShellDelegate::CreateContextMenu(
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index 357cf04..5d3c6dbe 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -51,8 +51,8 @@
   ash::AccessibilityDelegate* CreateAccessibilityDelegate() override;
   ash::NewWindowDelegate* CreateNewWindowDelegate() override;
   ash::MediaDelegate* CreateMediaDelegate() override;
-  std::unique_ptr<ash::PointerDownWatcherDelegate>
-  CreatePointerDownWatcherDelegate() override;
+  std::unique_ptr<ash::PointerWatcherDelegate> CreatePointerWatcherDelegate()
+      override;
   ui::MenuModel* CreateContextMenu(ash::WmShelf* wm_shelf,
                                    const ash::ShelfItem* item) override;
   ash::GPUSupport* CreateGPUSupport() override;
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
index 24fac73..949d3166 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
@@ -26,7 +26,7 @@
 // This is a LauncherItemController for abstract app windows. There is one
 // instance per app, per launcher id. For apps with multiple windows, each item
 // controller keeps track of all windows associated with the app and their
-// activation order. Instances are owned by ash::ShelfItemDelegateManager.
+// activation order. Instances are owned by ash::ShelfModel.
 //
 // Tests are in chrome_launcher_controller_impl_browsertest.cc
 class AppWindowLauncherItemController : public LauncherItemController,
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
index 108d4f8c..eb963f9 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -78,8 +78,7 @@
   virtual void SetItemStatus(ash::ShelfID id, ash::ShelfItemStatus status) = 0;
 
   // Updates the controller associated with id (which should be a shortcut).
-  // |controller| will be owned by the |ChromeLauncherController| and then
-  // passed on to |ShelfItemDelegateManager|.
+  // Takes ownership of |controller|.
   // TODO(skuhne): Pass in scoped_ptr to make ownership clear.
   virtual void SetItemController(ash::ShelfID id,
                                  LauncherItemController* controller) = 0;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
index a59ff12..9567ac7c 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -10,7 +10,6 @@
 
 #include "ash/common/ash_switches.h"
 #include "ash/common/multi_profile_uma.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/system/tray/system_tray_delegate.h"
 #include "ash/common/wm_shell.h"
@@ -192,6 +191,7 @@
     Profile* profile,
     ash::ShelfModel* model)
     : model_(model), profile_(profile) {
+  DCHECK(model_);
   if (!profile_) {
     // If no profile was passed, we take the currently active profile and use it
     // as the owner of the current desktop.
@@ -253,22 +253,11 @@
 
   // Right now ash::Shell isn't created for tests.
   // TODO(mukai): Allows it to observe display change and write tests.
-  if (ash::Shell::HasInstance()) {
+  if (ash::Shell::HasInstance())
     ash::Shell::GetInstance()->window_tree_host_manager()->AddObserver(this);
-    // If it got already set, we remove the observer first again and swap the
-    // ItemDelegateManager.
-    if (item_delegate_manager_)
-      item_delegate_manager_->RemoveObserver(this);
-    item_delegate_manager_ =
-        ash::Shell::GetInstance()->shelf_item_delegate_manager();
-    item_delegate_manager_->AddObserver(this);
-  }
 }
 
 ChromeLauncherControllerImpl::~ChromeLauncherControllerImpl() {
-  if (item_delegate_manager_)
-    item_delegate_manager_->RemoveObserver(this);
-
   // Reset the BrowserStatusMonitor as it has a weak pointer to this.
   browser_status_monitor_.reset();
 
@@ -435,7 +424,7 @@
   std::string app_id;
   return ((type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_PLATFORM_APP ||
            type == ash::TYPE_WINDOWED_APP) &&
-          item_delegate_manager_->GetShelfItemDelegate(id)->CanPin());
+          model_->GetShelfItemDelegate(id)->CanPin());
 }
 
 void ChromeLauncherControllerImpl::LockV1AppWithID(const std::string& app_id) {
@@ -1027,17 +1016,6 @@
   return id_to_item_controller_map_[id]->app_id();
 }
 
-void ChromeLauncherControllerImpl::SetShelfItemDelegateManagerForTest(
-    ash::ShelfItemDelegateManager* manager) {
-  if (item_delegate_manager_)
-    item_delegate_manager_->RemoveObserver(this);
-
-  item_delegate_manager_ = manager;
-
-  if (item_delegate_manager_)
-    item_delegate_manager_->AddObserver(this);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // ChromeLauncherControllerImpl private:
 
@@ -1457,7 +1435,7 @@
   id_to_item_controller_map_[id] =
       new BrowserShortcutLauncherItemController(this, model_);
   id_to_item_controller_map_[id]->set_shelf_id(id);
-  // ShelfItemDelegateManager owns BrowserShortcutLauncherItemController.
+  // ShelfModel owns BrowserShortcutLauncherItemController.
   SetShelfItemDelegate(id, id_to_item_controller_map_[id]);
   return id;
 }
@@ -1515,8 +1493,7 @@
     ash::ShelfItemDelegate* item_delegate) {
   DCHECK_GT(id, 0);
   DCHECK(item_delegate);
-  DCHECK(item_delegate_manager_);
-  item_delegate_manager_->SetShelfItemDelegate(
+  model_->SetShelfItemDelegate(
       id, std::unique_ptr<ash::ShelfItemDelegate>(item_delegate));
 }
 
@@ -1619,21 +1596,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// ash::ShelfItemDelegateManagerObserver:
-
-void ChromeLauncherControllerImpl::OnSetShelfItemDelegate(
-    ash::ShelfID id,
-    ash::ShelfItemDelegate* item_delegate) {
-  // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
-  // get into this state in the first place.
-  IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
-  if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second)
-    return;
-  LOG(ERROR) << "Unexpected change of shelf item id: " << id;
-  id_to_item_controller_map_.erase(iter);
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // ash::ShelfModelObserver:
 
 void ChromeLauncherControllerImpl::ShelfItemAdded(int index) {
@@ -1666,6 +1628,18 @@
     int index,
     const ash::ShelfItem& old_item) {}
 
+void ChromeLauncherControllerImpl::OnSetShelfItemDelegate(
+    ash::ShelfID id,
+    ash::ShelfItemDelegate* item_delegate) {
+  // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
+  // get into this state in the first place.
+  IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
+  if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second)
+    return;
+  LOG(ERROR) << "Unexpected change of shelf item id: " << id;
+  id_to_item_controller_map_.erase(iter);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // ash::WindowTreeHostManager::Observer:
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h
index ba8cc6fb..55d1e5a4 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h
@@ -8,7 +8,6 @@
 #include <list>
 #include <memory>
 
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model_observer.h"
 #include "ash/common/shelf/shelf_types.h"
 #include "ash/display/window_tree_host_manager.h"
@@ -32,7 +31,6 @@
 class TabContents;
 
 namespace ash {
-class ShelfItemDelegateManager;
 class ShelfModel;
 namespace launcher {
 class ChromeLauncherPrefsObserver;
@@ -65,7 +63,6 @@
       private ash::WindowTreeHostManager::Observer,
       private AppIconLoaderDelegate,
       private AppSyncUIStateObserver,
-      private ash::ShelfItemDelegateManagerObserver,
       private app_list::AppListSyncableService::Observer {
  public:
   ChromeLauncherControllerImpl(Profile* profile, ash::ShelfModel* model);
@@ -185,11 +182,6 @@
       std::vector<std::unique_ptr<AppIconLoader>>& loaders);
   const std::string& GetAppIdFromShelfIdForTest(ash::ShelfID id);
 
-  // Sets the ash::ShelfItemDelegateManager only for unittests and doesn't
-  // take an ownership of it.
-  void SetShelfItemDelegateManagerForTest(
-      ash::ShelfItemDelegateManager* manager);
-
  private:
   friend class ChromeLauncherControllerImplTest;
   friend class ShelfAppBrowserTest;
@@ -295,15 +287,13 @@
 
   AppIconLoader* GetAppIconLoaderForApp(const std::string& app_id);
 
-  // ash::ShelfItemDelegateManagerObserver:
-  void OnSetShelfItemDelegate(ash::ShelfID id,
-                              ash::ShelfItemDelegate* item_delegate) override;
-
   // ash::ShelfModelObserver:
   void ShelfItemAdded(int index) override;
   void ShelfItemRemoved(int index, ash::ShelfID id) override;
   void ShelfItemMoved(int start_index, int target_index) override;
   void ShelfItemChanged(int index, const ash::ShelfItem& old_item) override;
+  void OnSetShelfItemDelegate(ash::ShelfID id,
+                              ash::ShelfItemDelegate* item_delegate) override;
 
   // ash::WindowTreeHostManager::Observer:
   void OnDisplayConfigurationChanged() override;
@@ -320,13 +310,11 @@
 
   ash::ShelfModel* model_;
 
-  ash::ShelfItemDelegateManager* item_delegate_manager_ = nullptr;
-
   // Profile used for prefs and loading extensions. This is NOT necessarily the
   // profile new windows are created with.
   Profile* profile_;
 
-  // Controller items in this map are owned by |ShelfItemDelegateManager|.
+  // Controller items in this map are owned by |ShelfModel|.
   IDToItemControllerMap id_to_item_controller_map_;
 
   // Direct access to app_id for a web contents.
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
index 31ffc23..4500e99d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
@@ -374,11 +374,11 @@
     }
   }
 
-  std::unique_ptr<LauncherContextMenu> CreateLauncherContextMenu(
-      ash::ShelfItemType shelf_item_type) {
-    ash::ShelfItem item;
-    item.id = 1;  // dummy id
-    item.type = shelf_item_type;
+  // Creates a context menu for the existing browser shortcut item.
+  std::unique_ptr<LauncherContextMenu> CreateBrowserItemContextMenu() {
+    int index = model_->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
+    DCHECK_GE(index, 0);
+    ash::ShelfItem item = model_->items()[index];
     ash::Shelf* shelf = ash::Shelf::ForWindow(CurrentContext());
     std::unique_ptr<LauncherContextMenu> menu(LauncherContextMenu::Create(
         controller_, &item, ash::test::ShelfTestAPI(shelf).wm_shelf()));
@@ -2395,24 +2395,18 @@
 // windows.
 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest,
                        LauncherContextMenuVerifyCloseItemAppearance) {
-  // Open a new window.
-  aura::Window* window1 = browser()->window()->GetNativeWindow();
-  ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1);
-  window1->Show();
-  window1_state->Activate();
-  std::unique_ptr<LauncherContextMenu> menu1 =
-      CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT);
+  // Open a context menu for the existing browser window.
+  std::unique_ptr<LauncherContextMenu> menu1 = CreateBrowserItemContextMenu();
   // Check if "Close" is added to in the context menu.
   ASSERT_TRUE(
       IsItemPresentInMenu(menu1.get(), LauncherContextMenu::MENU_CLOSE));
 
-  // Close all windows.
+  // Close all windows via the menu item.
   CloseBrowserWindow(browser(), menu1.get(), LauncherContextMenu::MENU_CLOSE);
   EXPECT_EQ(0u, BrowserList::GetInstance()->size());
 
   // Check if "Close" is removed from the context menu.
-  std::unique_ptr<LauncherContextMenu> menu2 =
-      CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT);
+  std::unique_ptr<LauncherContextMenu> menu2 = CreateBrowserItemContextMenu();
   ASSERT_FALSE(
       IsItemPresentInMenu(menu2.get(), LauncherContextMenu::MENU_CLOSE));
 }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
index aaffb51..53d1388 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -15,7 +15,6 @@
 #include <vector>
 
 #include "ash/common/ash_switches.h"
-#include "ash/common/shelf/shelf_item_delegate_manager.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shelf/shelf_model_observer.h"
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
@@ -23,7 +22,6 @@
 #include "ash/display/screen_orientation_controller_chromeos.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_helper.h"
-#include "ash/test/shelf_item_delegate_manager_test_api.h"
 #include "ash/test/test_session_state_delegate.h"
 #include "ash/test/test_shell_delegate.h"
 #include "ash/wm/window_util.h"
@@ -154,6 +152,9 @@
     last_index_ = target_index;
   }
 
+  void OnSetShelfItemDelegate(ash::ShelfID id,
+                              ash::ShelfItemDelegate* item_delegate) override {}
+
   void clear_counts() {
     added_ = 0;
     removed_ = 0;
@@ -330,14 +331,6 @@
     model_observer_.reset(new TestShelfModelObserver);
     model_->AddObserver(model_observer_.get());
 
-    if (ash::Shell::HasInstance()) {
-      item_delegate_manager_ =
-          ash::Shell::GetInstance()->shelf_item_delegate_manager();
-    } else {
-      item_delegate_manager_ =
-          new ash::ShelfItemDelegateManager(model_.get());
-    }
-
     base::DictionaryValue manifest;
     manifest.SetString(extensions::manifest_keys::kName,
                        "launcher controller test extension");
@@ -473,17 +466,12 @@
 
   void TearDown() override {
     arc_test_.TearDown();
-    launcher_controller_->SetShelfItemDelegateManagerForTest(nullptr);
     model_->RemoveObserver(model_observer_.get());
     model_observer_.reset();
     launcher_controller_.reset();
 
-    // item_delegate_manager_ must be deleted after launch_controller_,
-    // because launch_controller_ has a map of pointers to the data
-    // hold by item_delegate_manager_.
-    if (!ash::Shell::HasInstance())
-      delete item_delegate_manager_;
-
+    // |model_| must be deleted after |launch_controller_|, because
+    // |launch_controller_| has a map of pointers to the data held by |model_|.
     model_.reset();
 
     BrowserWithTestWindowTest::TearDown();
@@ -511,8 +499,6 @@
     AddAppListLauncherItem();
     launcher_controller_.reset(
         new ChromeLauncherControllerImpl(profile(), model_.get()));
-    if (!ash::Shell::HasInstance())
-      SetShelfItemDelegateManager(item_delegate_manager_);
     launcher_controller_->Init();
   }
 
@@ -560,10 +546,6 @@
     launcher_controller_->SetLauncherControllerHelperForTest(helper);
   }
 
-  void SetShelfItemDelegateManager(ash::ShelfItemDelegateManager* manager) {
-    launcher_controller_->SetShelfItemDelegateManagerForTest(manager);
-  }
-
   void InsertPrefValue(base::ListValue* pref_value,
                        int index,
                        const std::string& extension_id) {
@@ -934,8 +916,6 @@
 
   app_list::AppListSyncableService* app_service_;
 
-  ash::ShelfItemDelegateManager* item_delegate_manager_;
-
  private:
   TestBrowserWindow* CreateTestBrowserWindowAura() {
     std::unique_ptr<aura::Window> window(new aura::Window(nullptr));
@@ -3231,15 +3211,7 @@
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
   EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
 
-  SetShelfItemDelegateManager(nullptr);
   launcher_controller_.reset();
-  if (!ash::Shell::HasInstance()) {
-    delete item_delegate_manager_;
-  } else {
-    // Clear already registered ShelfItemDelegate.
-    ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
-    test.RemoveAllShelfItemDelegateForTest();
-  }
   model_.reset(new ash::ShelfModel);
 
   AddAppListLauncherItem();
@@ -3249,10 +3221,6 @@
   helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
   helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
   SetLauncherControllerHelper(helper);
-  if (!ash::Shell::HasInstance()) {
-    item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
-    SetShelfItemDelegateManager(item_delegate_manager_);
-  }
   launcher_controller_->Init();
 
   // Check ShelfItems are restored after resetting ChromeLauncherControllerImpl.
@@ -3289,15 +3257,7 @@
   EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
   EXPECT_EQ(initial_size + 1, model_->items().size());
 
-  SetShelfItemDelegateManager(nullptr);
   launcher_controller_.reset();
-  if (!ash::Shell::HasInstance()) {
-    delete item_delegate_manager_;
-  } else {
-    // Clear already registered ShelfItemDelegate.
-    ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
-    test.RemoveAllShelfItemDelegateForTest();
-  }
   model_.reset(new ash::ShelfModel);
 
   AddAppListLauncherItem();
@@ -3310,10 +3270,6 @@
   app_icon_loader = new TestAppIconLoaderImpl;
   app_icon_loader->AddSupportedApp("1");
   SetAppIconLoader(std::unique_ptr<AppIconLoader>(app_icon_loader));
-  if (!ash::Shell::HasInstance()) {
-    item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
-    SetShelfItemDelegateManager(item_delegate_manager_);
-  }
   launcher_controller_->Init();
 
   EXPECT_EQ(1, app_icon_loader->fetch_count());
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
index 388f3aa..f7c0604f 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "ash/common/session/session_state_delegate.h"
+#include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shelf/wm_shelf.h"
 #include "ash/common/wm_shell.h"
 #include "ash/desktop_background/user_wallpaper_delegate.h"
@@ -122,9 +123,7 @@
     case MENU_CLOSE:
       if (item_.type == ash::TYPE_DIALOG) {
         ash::ShelfItemDelegate* item_delegate =
-            ash::Shell::GetInstance()
-                ->shelf_item_delegate_manager()
-                ->GetShelfItemDelegate(item_.id);
+            ash::WmShell::Get()->shelf_model()->GetShelfItemDelegate(item_.id);
         DCHECK(item_delegate);
         item_delegate->Close();
       } else {
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
index 30612e09..a2c2258 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -55,7 +55,7 @@
   LauncherContextMenu* CreateLauncherContextMenu(
       ash::ShelfItemType shelf_item_type) {
     ash::ShelfItem item;
-    item.id = 1;  // dummy id
+    item.id = 123;  // dummy id
     item.type = shelf_item_type;
     return LauncherContextMenu::Create(controller_.get(), &item, GetWmShelf());
   }
diff --git a/chrome/browser/ui/cocoa/download/download_item_controller.h b/chrome/browser/ui/cocoa/download/download_item_controller.h
index c7ec0a2..e85315ba 100644
--- a/chrome/browser/ui/cocoa/download/download_item_controller.h
+++ b/chrome/browser/ui/cocoa/download/download_item_controller.h
@@ -160,7 +160,6 @@
 - (BOOL)isDangerousMode;
 - (IBAction)saveDownload:(id)sender;
 - (IBAction)discardDownload:(id)sender;
-- (IBAction)dismissMaliciousDownload:(id)sender;
 - (IBAction)showContextMenu:(id)sender;
 
 @end
diff --git a/chrome/browser/ui/cocoa/download/download_item_controller.mm b/chrome/browser/ui/cocoa/download/download_item_controller.mm
index 0298199..fd3a5f8 100644
--- a/chrome/browser/ui/cocoa/download/download_item_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_controller.mm
@@ -362,13 +362,6 @@
   // WARNING: we are deleted at this point.  Don't access 'this'.
 }
 
-- (IBAction)dismissMaliciousDownload:(id)sender {
-  // ExperienceSampling: User dismissed the dangerous download.
-  [self updateExperienceSamplingEvent:ExperienceSamplingEvent::kDeny];
-  [self remove];
-  // WARNING: we are deleted at this point.
-}
-
 - (IBAction)showContextMenu:(id)sender {
   [progressView_ showContextMenu];
 }
diff --git a/chrome/browser/ui/panels/panel_manager.cc b/chrome/browser/ui/panels/panel_manager.cc
index 3ae9d5c8..7d2c9ce 100644
--- a/chrome/browser/ui/panels/panel_manager.cc
+++ b/chrome/browser/ui/panels/panel_manager.cc
@@ -131,16 +131,11 @@
   }
 #endif  // USE_X11 && !OS_CHROMEOS
 
-// Panels are an Eraser target. See http://crbug.com/571511 for details.
-// TODO(dimich): remove the rest of Panels code (except ChromeOS) once
-// erasure is stable.
-#if defined(OS_CHROMEOS)
-  // Without --enable-panels, only support Hangouts on ChromeOS.
+  // Without --enable-panels, only support Hangouts.
   for (const char* id : extension_misc::kHangoutsExtensionIds) {
     if (extension_id == id)
       return true;
   }
-#endif  // OS_CHROMEOS
 
   return false;
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
index 69e07b9..487df5f 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
@@ -19,7 +19,7 @@
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_border.h"
 #include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/label_button.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/client_view.h"
@@ -168,7 +168,7 @@
     }
   }
 
-  views::ImageButton* close_button_;
+  views::LabelButton* close_button_;
 
   DISALLOW_COPY_AND_ASSIGN(AppListDialogContainer);
 };
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 1253d74..2a5ab60 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -559,18 +559,8 @@
 
   // WARNING: all end states after this point delete |this|.
   DCHECK_EQ(discard_button_, sender);
-  if (model_.IsMalicious()) {
-    UMA_HISTOGRAM_LONG_TIMES("clickjacking.dismiss_download", warning_duration);
-    // ExperienceSampling: User chose to dismiss the dangerous download.
-    if (sampling_event_.get()) {
-      sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kDeny);
-      sampling_event_.reset(NULL);
-    }
-    shelf_->RemoveDownloadView(this);
-    return;
-  }
   UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration);
-  if (model_.ShouldAllowDownloadFeedback() &&
+  if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback() &&
       !shelf_->browser()->profile()->IsOffTheRecord()) {
     if (!shelf_->browser()->profile()->GetPrefs()->HasPrefPath(
         prefs::kSafeBrowsingExtendedReportingEnabled)) {
@@ -1198,10 +1188,8 @@
     save_button_->SetStyle(views::Button::STYLE_BUTTON);
     AddChildView(save_button_);
   }
-  int discard_button_message = model_.IsMalicious() ?
-      IDS_DISMISS_DOWNLOAD : IDS_DISCARD_DOWNLOAD;
   discard_button_ = new views::LabelButton(
-      this, l10n_util::GetStringUTF16(discard_button_message));
+      this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD));
   discard_button_->SetStyle(views::Button::STYLE_BUTTON);
   AddChildView(discard_button_);
 
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 9fa51a0..732c7f8 100644
--- a/chrome/browser/ui/views/download/download_item_view_md.cc
+++ b/chrome/browser/ui/views/download/download_item_view_md.cc
@@ -572,18 +572,8 @@
 
   // WARNING: all end states after this point delete |this|.
   DCHECK_EQ(discard_button_, sender);
-  if (model_.IsMalicious()) {
-    UMA_HISTOGRAM_LONG_TIMES("clickjacking.dismiss_download", warning_duration);
-    // ExperienceSampling: User chose to dismiss the dangerous download.
-    if (sampling_event_.get()) {
-      sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kDeny);
-      sampling_event_.reset(NULL);
-    }
-    shelf_->RemoveDownloadView(this);
-    return;
-  }
   UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration);
-  if (model_.ShouldAllowDownloadFeedback() &&
+  if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback() &&
       !shelf_->browser()->profile()->IsOffTheRecord()) {
     if (!shelf_->browser()->profile()->GetPrefs()->HasPrefPath(
             prefs::kSafeBrowsingExtendedReportingEnabled)) {
@@ -975,10 +965,8 @@
         this, model_.GetWarningConfirmButtonText());
     AddChildView(save_button_);
   }
-  int discard_button_message =
-      model_.IsMalicious() ? IDS_DISMISS_DOWNLOAD : IDS_DISCARD_DOWNLOAD;
   discard_button_ = views::MdTextButton::CreateMdButton(
-      this, l10n_util::GetStringUTF16(discard_button_message));
+      this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD));
   AddChildView(discard_button_);
 
   base::string16 dangerous_label =
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 6c226f48..9a437913 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -477,10 +477,10 @@
  private:
   // views::CustomButton:
   void StateChanged() override {
-    bool show_overlay =
-        (state() == STATE_PRESSED || state() == STATE_HOVERED || HasFocus());
-    if (photo_overlay_)
-      photo_overlay_->SetVisible(show_overlay);
+    if (photo_overlay_) {
+      photo_overlay_->SetVisible(
+          state() == STATE_PRESSED || state() == STATE_HOVERED || HasFocus());
+    }
   }
 
   void OnFocus() override {
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index db1d4cf..e315af3 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 
 #include <algorithm>
-#include <list>
 #include <memory>
 #include <string>
 #include <utility>
@@ -21,6 +20,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/sequenced_task_runner_helpers.h"
@@ -164,8 +164,7 @@
 net::HttpNetworkSession* GetHttpNetworkSession(
     net::URLRequestContext* context) {
   if (!context->http_transaction_factory())
-    return NULL;
-
+    return nullptr;
   return context->http_transaction_factory()->GetSession();
 }
 
@@ -199,9 +198,9 @@
   void RegisterMessages() override;
 
   // Calls g_browser.receive in the renderer, passing in |command| and |arg|.
-  // Takes ownership of |arg|.  If the renderer is displaying a log file, the
-  // message will be ignored.
-  void SendJavascriptCommand(const std::string& command, base::Value* arg);
+  // If the renderer is displaying a log file, the message will be ignored.
+  void SendJavascriptCommand(const std::string& command,
+                             std::unique_ptr<base::Value> arg);
 
   // Javascript message handlers.
   void OnRendererReady(const base::ListValue* list);
@@ -311,17 +310,17 @@
   void OnAddEntry(const net::NetLog::Entry& entry) override;
 
   // Helper that calls g_browser.receive in the renderer, passing in |command|
-  // and |arg|.  Takes ownership of |arg|.  If the renderer is displaying a log
-  // file, the message will be ignored.  Note that this can be called from any
-  // thread.
-  void SendJavascriptCommand(const std::string& command, base::Value* arg);
+  // and |arg|.  If the renderer is displaying a log file, the message will be
+  // ignored.  Note that this can be called from any thread.
+  void SendJavascriptCommand(const std::string& command,
+                             std::unique_ptr<base::Value> arg);
 
  private:
   friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
   friend class base::DeleteHelper<IOThreadImpl>;
 
-  typedef std::list<scoped_refptr<net::URLRequestContextGetter> >
-      ContextGetterList;
+  using ContextGetterList =
+      std::vector<scoped_refptr<net::URLRequestContextGetter>>;
 
   ~IOThreadImpl() override;
 
@@ -388,8 +387,8 @@
 NetInternalsMessageHandler::NetInternalsMessageHandler() {}
 
 NetInternalsMessageHandler::~NetInternalsMessageHandler() {
-  if (proxy_.get()) {
-    proxy_.get()->OnWebUIDeleted();
+  if (proxy_) {
+    proxy_->OnWebUIDeleted();
     // Notify the handler on the IO thread that the renderer is gone.
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                             base::Bind(&IOThreadImpl::Detach, proxy_.get()));
@@ -510,13 +509,12 @@
 
 void NetInternalsMessageHandler::SendJavascriptCommand(
     const std::string& command,
-    base::Value* arg) {
+    std::unique_ptr<base::Value> arg) {
   std::unique_ptr<base::Value> command_value(new base::StringValue(command));
-  std::unique_ptr<base::Value> value(arg);
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (value.get()) {
+  if (arg) {
     web_ui()->CallJavascriptFunctionUnsafe("g_browser.receive",
-                                           *command_value.get(), *value.get());
+                                           *command_value.get(), *arg.get());
   } else {
     web_ui()->CallJavascriptFunctionUnsafe("g_browser.receive",
                                            *command_value.get());
@@ -550,13 +548,13 @@
     value->SetBoolean("enabled", false);
     value->SetBoolean("omnibox_enabled", false);
   }
-  SendJavascriptCommand("receivedPrerenderInfo", value.release());
+  SendJavascriptCommand("receivedPrerenderInfo", std::move(value));
 }
 
 void NetInternalsMessageHandler::OnGetHistoricNetworkStats(
     const base::ListValue* list) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  base::Value* historic_network_info = NULL;
+  std::unique_ptr<base::Value> historic_network_info;
   Profile* profile = Profile::FromWebUI(web_ui());
   DataReductionProxyChromeSettings* data_reduction_proxy_settings =
         DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile);
@@ -568,13 +566,14 @@
     historic_network_info =
         compression_stats->HistoricNetworkStatsInfoToValue();
   }
-  SendJavascriptCommand("receivedHistoricNetworkStats", historic_network_info);
+  SendJavascriptCommand("receivedHistoricNetworkStats",
+                        std::move(historic_network_info));
 }
 
 void NetInternalsMessageHandler::OnGetExtensionInfo(
     const base::ListValue* list) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  base::ListValue* extension_list = new base::ListValue();
+  auto extension_list = base::MakeUnique<base::ListValue>();
 #if defined(ENABLE_EXTENSIONS)
   Profile* profile = Profile::FromWebUI(web_ui());
   extensions::ExtensionSystem* extension_system =
@@ -585,19 +584,18 @@
       std::unique_ptr<const extensions::ExtensionSet> extensions(
           extensions::ExtensionRegistry::Get(profile)
               ->GenerateInstalledExtensionsSet());
-      for (extensions::ExtensionSet::const_iterator it = extensions->begin();
-           it != extensions->end(); ++it) {
+      for (const auto& extension : *extensions) {
         std::unique_ptr<base::DictionaryValue> extension_info(
             new base::DictionaryValue());
-        bool enabled = extension_service->IsExtensionEnabled((*it)->id());
-        extensions::GetExtensionBasicInfo(it->get(), enabled,
+        bool enabled = extension_service->IsExtensionEnabled(extension->id());
+        extensions::GetExtensionBasicInfo(extension.get(), enabled,
                                           extension_info.get());
         extension_list->Append(std::move(extension_info));
       }
     }
   }
 #endif
-  SendJavascriptCommand("receivedExtensionInfo", extension_list);
+  SendJavascriptCommand("receivedExtensionInfo", std::move(extension_list));
 }
 
 void NetInternalsMessageHandler::OnGetDataReductionProxyInfo(
@@ -607,11 +605,13 @@
   DataReductionProxyChromeSettings* data_reduction_proxy_settings =
       DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile);
   data_reduction_proxy::DataReductionProxyEventStore* event_store =
-      (data_reduction_proxy_settings == nullptr) ? nullptr :
-          data_reduction_proxy_settings->GetEventStore();
-  SendJavascriptCommand(
-      "receivedDataReductionProxyInfo",
-      (event_store == nullptr) ? nullptr : event_store->GetSummaryValue());
+      data_reduction_proxy_settings
+          ? data_reduction_proxy_settings->GetEventStore()
+          : nullptr;
+  std::unique_ptr<base::Value> value;
+  if (event_store)
+    value = event_store->GetSummaryValue();
+  SendJavascriptCommand("receivedDataReductionProxyInfo", std::move(value));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -652,7 +652,7 @@
   // thread. |list_copy| will be deleted when the task is destroyed. The called
   // |method| cannot take ownership of |list_copy|.
   base::ListValue* list_copy =
-      (list && list->GetSize()) ? list->DeepCopy() : NULL;
+      (list && list->GetSize()) ? list->DeepCopy() : nullptr;
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
@@ -740,16 +740,12 @@
   // |list| should be: [<domain to query>].
   std::string domain;
   CHECK(list->GetString(0, &domain));
-  base::DictionaryValue* result = new base::DictionaryValue();
+  auto result = base::MakeUnique<base::DictionaryValue>();
 
-  if (!base::IsStringASCII(domain)) {
-    result->SetString("error", "non-ASCII domain name");
-  } else {
+  if (base::IsStringASCII(domain)) {
     net::TransportSecurityState* transport_security_state =
         GetMainContext()->transport_security_state();
-    if (!transport_security_state) {
-      result->SetString("error", "no TransportSecurityState active");
-    } else {
+    if (transport_security_state) {
       net::TransportSecurityState::STSState static_sts_state;
       net::TransportSecurityState::PKPState static_pkp_state;
       const bool found_static = transport_security_state->GetStaticDomainState(
@@ -810,10 +806,14 @@
 
       result->SetBoolean(
           "result", found_static || found_sts_dynamic || found_pkp_dynamic);
+    } else {
+      result->SetString("error", "no TransportSecurityState active");
     }
+  } else {
+    result->SetString("error", "non-ASCII domain name");
   }
 
-  SendJavascriptCommand("receivedHSTSResult", result);
+  SendJavascriptCommand("receivedHSTSResult", std::move(result));
 }
 
 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSAdd(
@@ -876,18 +876,17 @@
   net::HttpNetworkSession* http_network_session =
       GetHttpNetworkSession(context);
 
-  base::Value* network_info = NULL;
+  std::unique_ptr<base::Value> network_info;
   if (http_network_session) {
     // TODO(mmenke):  This cast is ugly.  Can we get rid of it, or, better,
     // remove DRP data from net-internals entirely?
     data_reduction_proxy::DataReductionProxyNetworkDelegate* net_delegate =
         static_cast<data_reduction_proxy::DataReductionProxyNetworkDelegate*>(
             context->network_delegate());
-    if (net_delegate) {
+    if (net_delegate)
       network_info = net_delegate->SessionNetworkStatsInfoToValue();
-    }
   }
-  SendJavascriptCommand("receivedSessionNetworkStats", network_info);
+  SendJavascriptCommand("receivedSessionNetworkStats", std::move(network_info));
 }
 
 void NetInternalsMessageHandler::IOThreadImpl::OnFlushSocketPools(
@@ -915,13 +914,13 @@
     const base::ListValue* list) {
   DCHECK(!list);
 
-  base::DictionaryValue* service_providers = new base::DictionaryValue();
+  auto service_providers = base::MakeUnique<base::DictionaryValue>();
 
   WinsockLayeredServiceProviderList layered_providers;
   GetWinsockLayeredServiceProviders(&layered_providers);
-  base::ListValue* layered_provider_list = new base::ListValue();
+  auto layered_provider_list = base::MakeUnique<base::ListValue>();
   for (size_t i = 0; i < layered_providers.size(); ++i) {
-    base::DictionaryValue* service_dict = new base::DictionaryValue();
+    auto service_dict = base::MakeUnique<base::DictionaryValue>();
     service_dict->SetString("name", layered_providers[i].name);
     service_dict->SetInteger("version", layered_providers[i].version);
     service_dict->SetInteger("chain_length", layered_providers[i].chain_length);
@@ -930,25 +929,26 @@
         layered_providers[i].socket_protocol);
     service_dict->SetString("path", layered_providers[i].path);
 
-    layered_provider_list->Append(service_dict);
+    layered_provider_list->Append(std::move(service_dict));
   }
-  service_providers->Set("service_providers", layered_provider_list);
+  service_providers->Set("service_providers", std::move(layered_provider_list));
 
   WinsockNamespaceProviderList namespace_providers;
   GetWinsockNamespaceProviders(&namespace_providers);
-  base::ListValue* namespace_list = new base::ListValue;
+  auto namespace_list = base::MakeUnique<base::ListValue>();
   for (size_t i = 0; i < namespace_providers.size(); ++i) {
-    base::DictionaryValue* namespace_dict = new base::DictionaryValue();
+    auto namespace_dict = base::MakeUnique<base::DictionaryValue>();
     namespace_dict->SetString("name", namespace_providers[i].name);
     namespace_dict->SetBoolean("active", namespace_providers[i].active);
     namespace_dict->SetInteger("version", namespace_providers[i].version);
     namespace_dict->SetInteger("type", namespace_providers[i].type);
 
-    namespace_list->Append(namespace_dict);
+    namespace_list->Append(std::move(namespace_dict));
   }
-  service_providers->Set("namespace_providers", namespace_list);
+  service_providers->Set("namespace_providers", std::move(namespace_list));
 
-  SendJavascriptCommand("receivedServiceProviders", service_providers);
+  SendJavascriptCommand("receivedServiceProviders",
+                        std::move(service_providers));
 }
 #endif
 
@@ -963,7 +963,8 @@
 
   if (!user) {
     std::string error = "User not found.";
-    SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
+    SendJavascriptCommand("receivedONCFileParse",
+                          base::MakeUnique<base::StringValue>(error));
     return;
   }
 
@@ -1004,7 +1005,8 @@
   if (!success)
     error += "Some certificates couldn't be imported. ";
 
-  SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
+  SendJavascriptCommand("receivedONCFileParse",
+                        base::MakeUnique<base::StringValue>(error));
 }
 
 void NetInternalsMessageHandler::OnImportONCFile(
@@ -1026,8 +1028,9 @@
 void NetInternalsMessageHandler::OnStoreDebugLogs(const base::ListValue* list) {
   DCHECK(list);
 
-  SendJavascriptCommand("receivedStoreDebugLogs",
-                        new base::StringValue("Creating log file..."));
+  SendJavascriptCommand(
+      "receivedStoreDebugLogs",
+      base::MakeUnique<base::StringValue>("Creating log file..."));
   Profile* profile = Profile::FromWebUI(web_ui());
   const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(profile);
   base::FilePath path = prefs->DownloadPath();
@@ -1048,7 +1051,7 @@
   else
     status = "Failed to create log file";
   SendJavascriptCommand("receivedStoreDebugLogs",
-                        new base::StringValue(status));
+                        base::MakeUnique<base::StringValue>(status));
 }
 
 void NetInternalsMessageHandler::OnSetNetworkDebugMode(
@@ -1068,13 +1071,11 @@
 void NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted(
     const std::string& subsystem,
     bool succeeded) {
-  std::string status;
-  if (succeeded)
-    status = "Debug mode is changed to " + subsystem;
-  else
-    status = "Failed to change debug mode to " + subsystem;
+  std::string status = succeeded ? "Debug mode is changed to "
+                                 : "Failed to change debug mode to ";
+  status += subsystem;
   SendJavascriptCommand("receivedSetNetworkDebugMode",
-                        new base::StringValue(status));
+                        base::MakeUnique<base::StringValue>(status));
 }
 #endif  // defined(OS_CHROMEOS)
 
@@ -1111,30 +1112,25 @@
 // Note that this can be called from ANY THREAD.
 void NetInternalsMessageHandler::IOThreadImpl::SendJavascriptCommand(
     const std::string& command,
-    base::Value* arg) {
+    std::unique_ptr<base::Value> arg) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    if (handler_.get() && !was_webui_deleted_) {
+    if (handler_ && !was_webui_deleted_) {
       // We check |handler_| in case it was deleted on the UI thread earlier
       // while we were running on the IO thread.
-      handler_->SendJavascriptCommand(command, arg);
-    } else {
-      delete arg;
+      handler_->SendJavascriptCommand(command, std::move(arg));
     }
     return;
   }
 
-  if (!BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&IOThreadImpl::SendJavascriptCommand, this, command, arg))) {
-    // Failed posting the task, avoid leaking.
-    delete arg;
-  }
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(&IOThreadImpl::SendJavascriptCommand, this,
+                                     command, base::Passed(&arg)));
 }
 
 void NetInternalsMessageHandler::IOThreadImpl::AddEntryToQueue(
     std::unique_ptr<base::Value> entry) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!pending_entries_.get()) {
+  if (!pending_entries_) {
     pending_entries_.reset(new base::ListValue());
     BrowserThread::PostDelayedTask(
         BrowserThread::IO, FROM_HERE,
@@ -1146,17 +1142,15 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::PostPendingEntries() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (pending_entries_.get())
-    SendJavascriptCommand("receivedLogEntries", pending_entries_.release());
+  if (pending_entries_)
+    SendJavascriptCommand("receivedLogEntries", std::move(pending_entries_));
 }
 
 void NetInternalsMessageHandler::IOThreadImpl::PrePopulateEventList() {
   // Using a set removes any duplicates.
   std::set<net::URLRequestContext*> contexts;
-  for (ContextGetterList::const_iterator getter = context_getters_.begin();
-       getter != context_getters_.end(); ++getter) {
-    contexts.insert((*getter)->GetURLRequestContext());
-  }
+  for (const auto& getter : context_getters_)
+    contexts.insert(getter->GetURLRequestContext());
   contexts.insert(io_thread_->globals()->proxy_script_fetcher_context.get());
   contexts.insert(io_thread_->globals()->system_request_context.get());
 
@@ -1166,9 +1160,8 @@
 
 void NetInternalsMessageHandler::IOThreadImpl::SendNetInfo(int info_sources) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  SendJavascriptCommand(
-      "receivedNetInfo",
-      net::GetNetInfo(GetMainContext(), info_sources).release());
+  SendJavascriptCommand("receivedNetInfo",
+                        net::GetNetInfo(GetMainContext(), info_sources));
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/offline_internals_ui.cc b/chrome/browser/ui/webui/offline_internals_ui.cc
index 93ed449..c8e57eeb 100644
--- a/chrome/browser/ui/webui/offline_internals_ui.cc
+++ b/chrome/browser/ui/webui/offline_internals_ui.cc
@@ -19,16 +19,19 @@
 #include "chrome/common/url_constants.h"
 #include "components/offline_pages/background/request_coordinator.h"
 #include "components/offline_pages/background/save_page_request.h"
+#include "components/offline_pages/client_namespace_constants.h"
 #include "components/offline_pages/offline_page_model.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_controller.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "grit/browser_resources.h"
+#include "net/base/network_change_notifier.h"
 
 namespace {
 
 // Class acting as a controller of the chrome://offline-internals WebUI.
+// TODO(chili): Should split this file and move to webui/offline_internals/
 class OfflineInternalsUIMessageHandler : public content::WebUIMessageHandler {
  public:
   OfflineInternalsUIMessageHandler();
@@ -62,6 +65,12 @@
   // Load whether logs are being recorded.
   void HandleGetLoggingState(const base::ListValue* args);
 
+  // Adds a url to the background loader queue.
+  void HandleAddToRequestQueue(const base::ListValue* args);
+
+  // Load whether device is currently offline.
+  void HandleGetNetworkStatus(const base::ListValue* args);
+
   // Callback for async GetAllPages calls.
   void HandleStoredPagesCallback(
       std::string callback_id,
@@ -197,7 +206,7 @@
     offline_page->SetString("namespace", page.client_id.name_space);
     offline_page->SetDouble("size", page.file_size);
     offline_page->SetString("id", std::to_string(page.offline_id));
-    offline_page->SetString("filePath", page.file_path.value());
+    offline_page->SetString("filePath", page.GetOfflineURL().spec());
     offline_page->SetDouble("creationTime", page.creation_time.ToJsTime());
     offline_page->SetDouble("lastAccessTime",
                               page.last_access_time.ToJsTime());
@@ -270,6 +279,17 @@
   offline_page_model_->GetLogger()->SetIsLogging(should_record);
 }
 
+void OfflineInternalsUIMessageHandler::HandleGetNetworkStatus(
+    const base::ListValue* args) {
+  const base::Value* callback_id;
+  CHECK(args->Get(0, &callback_id));
+
+  ResolveJavascriptCallback(
+      *callback_id,
+      base::StringValue(
+          net::NetworkChangeNotifier::IsOffline() ? "Offline" : "Online"));
+}
+
 void OfflineInternalsUIMessageHandler::HandleSetRecordRequestQueue(
     const base::ListValue* args) {
   bool should_record;
@@ -308,6 +328,27 @@
   ResolveJavascriptCallback(*callback_id, result);
 }
 
+void OfflineInternalsUIMessageHandler::HandleAddToRequestQueue(
+    const base::ListValue* args) {
+  const base::Value* callback_id;
+  CHECK(args->Get(0, &callback_id));
+
+  std::string url;
+  CHECK(args->GetString(1, &url));
+
+  std::ostringstream id_stream;
+  id_stream << std::rand();
+
+  ResolveJavascriptCallback(
+      *callback_id,
+      base::FundamentalValue(
+          request_coordinator_->SavePageLater(
+              GURL(url),
+              offline_pages::ClientId(offline_pages::kAsyncNamespace,
+                                      id_stream.str()),
+              true)));
+}
+
 void OfflineInternalsUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "deleteAllPages",
@@ -341,6 +382,14 @@
       "getLoggingState",
       base::Bind(&OfflineInternalsUIMessageHandler::HandleGetLoggingState,
                  weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "addToRequestQueue",
+      base::Bind(&OfflineInternalsUIMessageHandler::HandleAddToRequestQueue,
+                 weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "getNetworkStatus",
+      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetNetworkStatus,
+                 weak_ptr_factory_.GetWeakPtr()));
 
   // Get the offline page model associated with this web ui.
   Profile* profile = Profile::FromWebUI(web_ui());
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index e3a70be..fec14589 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -36,6 +36,7 @@
 #include "grit/settings_resources_map.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
 #include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h"
@@ -104,6 +105,9 @@
                                                             profile);
   if (easy_unlock_handler)
     AddSettingsPageUIHandler(easy_unlock_handler);
+
+  html_source->AddBoolean("quickUnlockEnabled",
+                          chromeos::IsQuickUnlockEnabled());
 #endif
 
   AddSettingsPageUIHandler(AboutHandler::Create(html_source, profile));
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 8a05ac85..3db41f3 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -707,7 +707,7 @@
             '..',
           ],
           'conditions': [
-            ['use_cups==1 and OS!="chromeos"', {
+            ['use_cups==1 and chromeos==0', {
               'dependencies': [
                 '../printing/printing.gyp:cups',
               ],
@@ -715,17 +715,17 @@
                 'service/cloud_print/print_system_cups.cc',
               ],
             }],
-            ['OS!="win" and use_cups!=1', {
-              'sources': [
-                'service/cloud_print/print_system_dummy.cc',
-              ],
-            }],
             ['OS=="win"', {
               'sources': [
                 'service/service_utility_process_host.cc',
                 'service/service_utility_process_host.h',
               ],
             }],
+            ['chromeos==1 or (OS!="win" and use_cups!=1)', {
+              'sources': [
+                'service/cloud_print/print_system_dummy.cc',
+              ],
+            }],
           ],
         },
       ],
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a672ea55..08a5cf3 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2195,8 +2195,6 @@
       'browser/net/net_error_diagnostics_dialog_win.cc',
       'browser/net/net_error_tab_helper.cc',
       'browser/net/net_error_tab_helper.h',
-      'browser/net/net_pref_observer.cc',
-      'browser/net/net_pref_observer.h',
       'browser/net/nqe/ui_network_quality_estimator_service.cc',
       'browser/net/nqe/ui_network_quality_estimator_service.h',
       'browser/net/nqe/ui_network_quality_estimator_service_factory.cc',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index fe01bf9..2854502f 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -513,12 +513,14 @@
         'browser/chromeos/login/proxy_settings_dialog.h',
         'browser/chromeos/login/reauth_stats.cc',
         'browser/chromeos/login/reauth_stats.h',
-        'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc',
-        'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h',
         'browser/chromeos/login/quick_unlock/pin_storage.cc',
         'browser/chromeos/login/quick_unlock/pin_storage.h',
         'browser/chromeos/login/quick_unlock/pin_storage_factory.cc',
         'browser/chromeos/login/quick_unlock/pin_storage_factory.h',
+        'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc',
+        'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h',
+        'browser/chromeos/login/quick_unlock/quick_unlock_utils.cc',
+        'browser/chromeos/login/quick_unlock/quick_unlock_utils.h',
         'browser/chromeos/login/saml/saml_offline_signin_limiter.cc',
         'browser/chromeos/login/saml/saml_offline_signin_limiter.h',
         'browser/chromeos/login/saml/saml_offline_signin_limiter_factory.cc',
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index de5738a..f90959f 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -99,6 +99,10 @@
 // Enables or disables the opt-in IME menu in the language settings page.
 const base::Feature kOptInImeMenu{"OptInImeMenu",
                                   base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables or disables PIN quick unlock settings integration.
+const base::Feature kQuickUnlockPin{"QuickUnlockPin",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_CHROMEOS)
 
 }  // namespace features
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 2b3509a..3b668b4 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -61,6 +61,8 @@
 
 #if defined(OS_CHROMEOS)
 extern const base::Feature kOptInImeMenu;
+
+extern const base::Feature kQuickUnlockPin;
 #endif  // defined(OS_CHROMEOS)
 
 // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index 4e49bd3..c9f63a0c 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -198,10 +198,6 @@
 
     // Temporary for https://crbug.com/616149.
     { "existing_extension_pref_value_type", crash_keys::kSmallSize },
-
-    // Temporary for https://crbug.com/625040
-    { "swdh_not_handled_message_type", crash_keys::kMediumSize },
-    { "swdh_not_handled_worker_status", crash_keys::kMediumSize },
   };
 
   // This dynamic set of keys is used for sets of key value pairs when gathering
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index c0ee2d3..d85b232 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -433,10 +433,6 @@
 const char kDnsPrefetchingHostReferralList[] =
     "dns_prefetching.host_referral_list";
 
-// Disables the SPDY/3.1 protocol.
-// DEPRECATED: SPDY/3.1 is not supported any more.
-const char kDisableSpdy[] = "spdy.disabled";
-
 // Prefs for persisting HttpServerProperties.
 const char kHttpServerProperties[] = "net.http_server_properties";
 
@@ -451,15 +447,6 @@
 const char kInstantUIZeroSuggestUrlPrefix[] =
     "instant_ui.zero_suggest_url_prefix";
 
-// A boolean pref set to true if prediction of network actions is allowed.
-// Actions include DNS prefetching, TCP and SSL preconnection, prerendering
-// of web pages, and resource prefetching.
-// NOTE: The "dns_prefetching.enabled" value is used so that historical user
-// preferences are not lost.
-// TODO(bnc): Remove kNetworkPredictionEnabled once kNetworkPredictionOptions
-// is functioning as per crbug.com/334602.
-const char kNetworkPredictionEnabled[] = "dns_prefetching.enabled";
-
 // A preference of enum chrome_browser_net::NetworkPredictionOptions shows
 // if prediction of network actions is allowed, depending on network type.
 // Actions include DNS prefetching, TCP and SSL preconnection, prerendering
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 86ba49a..e63e0d5 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -169,13 +169,11 @@
 extern const char kAlternateErrorPagesEnabled[];
 extern const char kDnsPrefetchingStartupList[];
 extern const char kDnsPrefetchingHostReferralList[];
-extern const char kDisableSpdy[];
 extern const char kHttpServerProperties[];
 #if defined(OS_ANDROID)
 extern const char kLastPolicyCheckTime[];
 #endif
 extern const char kInstantUIZeroSuggestUrlPrefix[];
-extern const char kNetworkPredictionEnabled[];
 extern const char kNetworkPredictionOptions[];
 extern const char kDefaultAppsInstallState[];
 extern const char kHideWebStoreIcon[];
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn
index ba548dc..0bf5b56 100644
--- a/chrome/installer/mac/BUILD.gn
+++ b/chrome/installer/mac/BUILD.gn
@@ -10,7 +10,7 @@
   public_deps = [
     ":copies",
     ":make_signers",
-    "app:downloader",
+    "app:mac_installer",
   ]
 }
 
diff --git a/chrome/installer/mac/app/BUILD.gn b/chrome/installer/mac/app/BUILD.gn
index aa2123f..c08b6a0 100644
--- a/chrome/installer/mac/app/BUILD.gn
+++ b/chrome/installer/mac/app/BUILD.gn
@@ -2,16 +2,28 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-executable("downloader") {
+static_library("mac_installer_base") {
   sources = [
-    "DownloadDelegate.m",
     "Downloader.m",
+    "MainDelegate.m",
     "NetworkCommunication.m",
     "OmahaCommunication.m",
     "OmahaXMLParser.m",
     "OmahaXMLRequest.m",
     "SystemInfo.m",
+  ]
+}
+
+executable("mac_installer") {
+  sources = [
     "main.m",
   ]
-  libs = [ "Foundation.framework" ]
+  deps = [
+    ":mac_installer_base",
+  ]
+  libs = [
+    "AppKit.framework",
+    "CoreFoundation.framework",
+    "Foundation.framework",
+  ]
 }
diff --git a/chrome/installer/mac/app/DownloadDelegate.h b/chrome/installer/mac/app/DownloadDelegate.h
deleted file mode 100644
index 23cd5fe..0000000
--- a/chrome/installer/mac/app/DownloadDelegate.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 The Chromium Authors. 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_INSTALLER_MAC_APP_DOWNLOADDELEGATE_H_
-#define CHROME_INSTALLER_MAC_APP_DOWNLOADDELEGATE_H_
-
-#import <Foundation/Foundation.h>
-
-@interface DownloadDelegate : NSObject<NSURLSessionDownloadDelegate>
-
-@end
-
-#endif  // CHROME_INSTALLER_MAC_APP_DOWNLOADDELEGATE_H_
diff --git a/chrome/installer/mac/app/DownloadDelegate.m b/chrome/installer/mac/app/DownloadDelegate.m
deleted file mode 100644
index ff41c1f7..0000000
--- a/chrome/installer/mac/app/DownloadDelegate.m
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium 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 <assert.h>
-
-#import "DownloadDelegate.h"
-#import "Downloader.h"
-
-@implementation DownloadDelegate : NSObject
-
-// Skeleton of delegate method to provide download progress updates.
-// TODO: Make use of (totalBytesWritten/totalBytesExpectedToWrite)*100
-// to generate download progress percentage.
-- (void)URLSession:(NSURLSession*)session
-                 downloadTask:(NSURLSessionDownloadTask*)downloadTask
-                 didWriteData:(int64_t)bytesWritten
-            totalBytesWritten:(int64_t)totalBytesWritten
-    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
-}
-
-// Delegate method to move downloaded disk image to user's Download directory.
-- (void)URLSession:(NSURLSession*)session
-                 downloadTask:(NSURLSessionDownloadTask*)downloadTask
-    didFinishDownloadingToURL:(NSURL*)location {
-  assert([location isFileURL]);
-  NSFileManager* manager = [[NSFileManager alloc] init];
-  NSURL* downloadsDirectory =
-      [[NSURL alloc] initFileURLWithPath:[Downloader getDownloadsFilePath]];
-  if ([manager fileExistsAtPath:location.path]) {
-    [manager copyItemAtURL:location toURL:downloadsDirectory error:nil];
-  } else {
-    // TODO: Error Handling
-  }
-}
-
-- (void)URLSession:(NSURLSession*)session
-                    task:(NSURLSessionTask*)task
-    didCompleteWithError:(NSError*)error {
-  // TODO: Error Handling
-}
-@end
diff --git a/chrome/installer/mac/app/Downloader.h b/chrome/installer/mac/app/Downloader.h
index 03c84fa7..06e53931 100644
--- a/chrome/installer/mac/app/Downloader.h
+++ b/chrome/installer/mac/app/Downloader.h
@@ -7,7 +7,14 @@
 
 #import <Foundation/Foundation.h>
 
-@interface Downloader : NSObject<NSXMLParserDelegate>
+@protocol DownloaderDelegate
+- (void)onDownloadSuccess;
+@end
+
+@interface Downloader
+    : NSObject<NSXMLParserDelegate, NSURLSessionDownloadDelegate>
+
+@property(nonatomic, assign) id<DownloaderDelegate> delegate;
 
 // Returns a path to a user's home download folder.
 + (NSString*)getDownloadsFilePath;
diff --git a/chrome/installer/mac/app/Downloader.m b/chrome/installer/mac/app/Downloader.m
index 857897a..25490da 100644
--- a/chrome/installer/mac/app/Downloader.m
+++ b/chrome/installer/mac/app/Downloader.m
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import <Foundation/Foundation.h>
-
-#import "DownloadDelegate.h"
 #import "Downloader.h"
+
+#include <assert.h>
+
 #import "NetworkCommunication.h"
 #import "OmahaXMLParser.h"
 
 @implementation Downloader
 
+@synthesize delegate = delegate_;
+
 // TODO: make this overrideable with commandline argument? or enviro variable
 + (NSString*)getDownloadsFilePath {
   NSArray* downloadPaths = NSSearchPathForDirectoriesInDomains(
@@ -59,9 +61,8 @@
 // Downloads contents of chromeURL to downloads folders and delegates the work
 // to the DownloadDelegate class.
 - (BOOL)writeChromeImageToDownloadsDirectory:(NSURL*)chromeURL {
-  DownloadDelegate* delegate = [[DownloadDelegate alloc] init];
   NetworkCommunication* downloadTask =
-      [[NetworkCommunication alloc] initWithDelegate:delegate];
+      [[NetworkCommunication alloc] initWithDelegate:self];
 
   // TODO: What if file already exists?
   [downloadTask createRequestWithUrlAsString:[chromeURL absoluteString]
@@ -81,4 +82,37 @@
   return writeWasSuccessful;
 }
 
+// Skeleton of delegate method to provide download progress updates.
+// TODO: Make use of (totalBytesWritten/totalBytesExpectedToWrite)*100
+// to generate download progress percentage.
+- (void)URLSession:(NSURLSession*)session
+                 downloadTask:(NSURLSessionDownloadTask*)downloadTask
+                 didWriteData:(int64_t)bytesWritten
+            totalBytesWritten:(int64_t)totalBytesWritten
+    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
+}
+
+// Delegate method to move downloaded disk image to user's Download directory.
+- (void)URLSession:(NSURLSession*)session
+                 downloadTask:(NSURLSessionDownloadTask*)downloadTask
+    didFinishDownloadingToURL:(NSURL*)location {
+  assert([location isFileURL]);
+  NSFileManager* manager = [[NSFileManager alloc] init];
+  NSURL* downloadsDirectory =
+      [[NSURL alloc] initFileURLWithPath:[Downloader getDownloadsFilePath]];
+  if ([manager fileExistsAtPath:location.path]) {
+    [manager moveItemAtURL:location toURL:downloadsDirectory error:nil];
+  } else {
+    // TODO: Error Handling
+  }
+}
+
+- (void)URLSession:(NSURLSession*)session
+                    task:(NSURLSessionTask*)task
+    didCompleteWithError:(NSError*)error {
+  // TODO: Error Handling
+
+  [delegate_ onDownloadSuccess];
+}
+
 @end
diff --git a/chrome/installer/mac/app/MainDelegate.h b/chrome/installer/mac/app/MainDelegate.h
new file mode 100644
index 0000000..efbe36f
--- /dev/null
+++ b/chrome/installer/mac/app/MainDelegate.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. 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_INSTALLER_MAC_APP_MAINDELEGATE_H_
+#define CHROME_INSTALLER_MAC_APP_MAINDELEGATE_H_
+
+#import <Foundation/Foundation.h>
+
+#import "Downloader.h"
+#import "OmahaCommunication.h"
+
+// TODO: move this into the unpacking file when created
+@protocol UnpackDelegate
+- (void)onUnpackSuccess;
+@end
+
+@interface MainDelegate
+    : NSObject<OmahaCommunicationDelegate, DownloaderDelegate, UnpackDelegate>
+- (void)runApplication;
+@end
+
+#endif  // CHROME_INSTALLER_MAC_APP_MAINDELEGATE_H_
diff --git a/chrome/installer/mac/app/MainDelegate.m b/chrome/installer/mac/app/MainDelegate.m
new file mode 100644
index 0000000..9662b5b
--- /dev/null
+++ b/chrome/installer/mac/app/MainDelegate.m
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium 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 "MainDelegate.h"
+
+@implementation MainDelegate
+
+- (void)runApplication {
+  OmahaCommunication* messenger = [[OmahaCommunication alloc] init];
+  messenger.delegate = self;
+
+  [messenger sendRequest];
+}
+
+- (void)onOmahaSuccessWithResponseBody:(NSData*)responseBody
+                              AndError:(NSError*)error {
+  if (error) {
+    NSLog(@"error: %@", [error localizedDescription]);
+    exit(1);
+  }
+  Downloader* download = [[Downloader alloc] init];
+  download.delegate = self;
+
+  [download downloadChromeImageToDownloadsDirectory:responseBody];
+}
+
+- (void)onDownloadSuccess {
+  // TODO: replace the line of code below with real code someday to unpack dmg
+  exit(0);
+}
+
+- (void)onUnpackSuccess {
+}
+
+@end
diff --git a/chrome/installer/mac/app/NetworkCommunication.h b/chrome/installer/mac/app/NetworkCommunication.h
index 803c2db25..c616a207 100644
--- a/chrome/installer/mac/app/NetworkCommunication.h
+++ b/chrome/installer/mac/app/NetworkCommunication.h
@@ -7,16 +7,14 @@
 
 #import <Foundation/Foundation.h>
 
-typedef void (^DataTaskCompletionHandler)(NSData*, NSURLResponse*, NSError*);
-typedef void (^DownloadTaskCompletionHandler)(NSURL*, NSURLResponse*, NSError*);
-
+// TODO: talk to @sdy about this class
 @interface NetworkCommunication : NSObject
 
+typedef void (^DataTaskCompletionHandler)(NSData*, NSURLResponse*, NSError*);
+
 @property(nonatomic, copy) NSMutableURLRequest* request;
 @property(nonatomic, copy) NSURLSession* session;
 @property(nonatomic, copy) DataTaskCompletionHandler dataResponseHandler;
-@property(nonatomic, copy)
-    DownloadTaskCompletionHandler downloadResponseHandler;
 
 - (id)init;
 - (id)initWithDelegate:(id)delegate;
@@ -26,8 +24,7 @@
 - (NSMutableURLRequest*)createRequestWithUrlAsString:(NSString*)urlString
                                           andXMLBody:(NSXMLDocument*)body;
 // Adds a data task to the run loop using the request instance variable.
-- (void)sendDataRequestWithCompletionHandler:
-    (DataTaskCompletionHandler)completionHandler;
+- (void)sendDataRequest;
 // Adds a download task to the run loop using the request instance variable.
 - (void)sendDownloadRequest;
 
diff --git a/chrome/installer/mac/app/NetworkCommunication.m b/chrome/installer/mac/app/NetworkCommunication.m
index fdee745..a5ffde9 100644
--- a/chrome/installer/mac/app/NetworkCommunication.m
+++ b/chrome/installer/mac/app/NetworkCommunication.m
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import <Foundation/Foundation.h>
-
 #import "NetworkCommunication.h"
 
 @interface NSURLSession (PartialAvailability)
@@ -24,7 +22,6 @@
 @synthesize session = session_;
 @synthesize request = request_;
 @synthesize dataResponseHandler = dataResponseHandler_;
-@synthesize downloadResponseHandler = downloadResponseHandler_;
 
 - (id)init {
   return [self initWithDelegate:nil];
@@ -54,24 +51,21 @@
   return request_;
 }
 
-- (void)sendDataRequestWithCompletionHandler:
-    (DataTaskCompletionHandler)completionHandler {
-  dataResponseHandler_ = completionHandler;
-  NSURLSessionDataTask* dataTask =
-      [session_ dataTaskWithRequest:request_
-                  completionHandler:dataResponseHandler_];
+- (void)sendDataRequest {
+  NSURLSessionDataTask* dataTask;
+  if (dataResponseHandler_) {
+    dataTask = [session_ dataTaskWithRequest:request_
+                           completionHandler:dataResponseHandler_];
+  } else {
+    dataTask = [session_ dataTaskWithRequest:request_];
+  }
 
   [dataTask resume];
 }
 
 - (void)sendDownloadRequest {
-  NSURLSessionDownloadTask* downloadTask;
-  if (downloadResponseHandler_) {
-    downloadTask = [session_ downloadTaskWithRequest:request_
-                                   completionHandler:downloadResponseHandler_];
-  } else {
-    downloadTask = [session_ downloadTaskWithRequest:request_];
-  }
+  NSURLSessionDownloadTask* downloadTask =
+      [session_ downloadTaskWithRequest:request_];
   [downloadTask resume];
 }
 
diff --git a/chrome/installer/mac/app/OmahaCommunication.h b/chrome/installer/mac/app/OmahaCommunication.h
index 54a377f..5bfae67 100644
--- a/chrome/installer/mac/app/OmahaCommunication.h
+++ b/chrome/installer/mac/app/OmahaCommunication.h
@@ -7,20 +7,27 @@
 
 #import <Foundation/Foundation.h>
 
-#include "NetworkCommunication.h"
+#import "NetworkCommunication.h"
 
-typedef void (^OmahaRequestCompletionHandler)(NSData*, NSError*);
+@protocol OmahaCommunicationDelegate
+- (void)onOmahaSuccessWithResponseBody:(NSData*)responseBody
+                              AndError:(NSError*)error;
+@end
 
-@interface OmahaCommunication : NSObject
+@interface OmahaCommunication : NSObject<NSURLSessionDataDelegate> {
+  id<OmahaCommunicationDelegate> _delegate;
+}
 
 @property(nonatomic, copy) NSXMLDocument* requestXMLBody;
+// TODO: talk to @sdy about use of NetworkCommunication
 @property(nonatomic, copy) NetworkCommunication* sessionHelper;
+@property(nonatomic, assign) id<OmahaCommunicationDelegate> delegate;
 
 - (id)init;
 - (id)initWithBody:(NSXMLDocument*)xmlBody;
 
 // Sends the request created using the session helper.
-- (void)sendRequestWithBlock:(OmahaRequestCompletionHandler)block;
+- (void)sendRequest;
 
 @end
 
diff --git a/chrome/installer/mac/app/OmahaCommunication.m b/chrome/installer/mac/app/OmahaCommunication.m
index 4232890..8368ff7 100644
--- a/chrome/installer/mac/app/OmahaCommunication.m
+++ b/chrome/installer/mac/app/OmahaCommunication.m
@@ -2,22 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import <Foundation/Foundation.h>
+#import "OmahaCommunication.h"
 
-#include "OmahaCommunication.h"
+#import "OmahaXMLRequest.h"
 
-@implementation OmahaCommunication : NSObject
+@implementation OmahaCommunication
 
 @synthesize requestXMLBody = requestXMLBody_;
 @synthesize sessionHelper = sessionHelper_;
+@synthesize delegate = delegate_;
 
 - (id)init {
-  return [self initWithBody:[[NSXMLDocument alloc] init]];
+  return [self initWithBody:[OmahaXMLRequest createXMLRequestBody]];
 }
 
 - (id)initWithBody:(NSXMLDocument*)xmlBody {
   if ((self = [super init])) {
-    sessionHelper_ = [[NetworkCommunication alloc] init];
+    sessionHelper_ = [[NetworkCommunication alloc] initWithDelegate:self];
     requestXMLBody_ = xmlBody;
     [self createOmahaRequest];
   }
@@ -33,27 +34,13 @@
   return request;
 }
 
-- (void)sendRequestWithBlock:(OmahaRequestCompletionHandler)block {
-  DataTaskCompletionHandler cHandler =
-      ^(NSData* _Nullable data, NSURLResponse* _Nullable response,
-        NSError* _Nullable error) {
-        if (error) {
-          NSLog(@"%@", error);
-          block(data, error);
-          return;
-        }
-
-        NSHTTPURLResponse* HTTPResponse = (NSHTTPURLResponse*)response;
-        if (HTTPResponse.statusCode != 200) {
-          // TODO: make these logging statements more rare
-          NSLog(@"HTTP response: %ld", (unsigned long)HTTPResponse.statusCode);
-        }
-
-        block(data, error);
-
-      };
-
-  [sessionHelper_ sendDataRequestWithCompletionHandler:cHandler];
+- (void)sendRequest {
+  [sessionHelper_ setDataResponseHandler:^(NSData* _Nullable data,
+                                           NSURLResponse* _Nullable response,
+                                           NSError* _Nullable error) {
+    [delegate_ onOmahaSuccessWithResponseBody:data AndError:error];
+  }];
+  [sessionHelper_ sendDataRequest];
 }
 
 @end
\ No newline at end of file
diff --git a/chrome/installer/mac/app/OmahaXMLRequest.m b/chrome/installer/mac/app/OmahaXMLRequest.m
index 8dad342..995d0b26 100644
--- a/chrome/installer/mac/app/OmahaXMLRequest.m
+++ b/chrome/installer/mac/app/OmahaXMLRequest.m
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import <Foundation/Foundation.h>
-
 #include "OmahaXMLRequest.h"
+
 #include "SystemInfo.h"
 
 @implementation OmahaXMLRequest : NSObject
diff --git a/chrome/installer/mac/app/main.m b/chrome/installer/mac/app/main.m
index 3f71813..5dfad4c 100644
--- a/chrome/installer/mac/app/main.m
+++ b/chrome/installer/mac/app/main.m
@@ -4,31 +4,12 @@
 
 #import <Foundation/Foundation.h>
 
-#import "Downloader.h"
-#import "OmahaCommunication.h"
-#import "OmahaXMLRequest.h"
-#import "SystemInfo.h"
+#import "MainDelegate.h"
 
-// TODO: add a class that takes care of what main is doing now
-void talkToOmahaThenExecuteBlock(OmahaRequestCompletionHandler block) {
-  NSXMLDocument* requestBody = [OmahaXMLRequest createXMLRequestBody];
-  OmahaCommunication* messenger =
-      [[OmahaCommunication alloc] initWithBody:requestBody];
-  [messenger sendRequestWithBlock:block];
-}
+int main(int argc, const char* argv[]) {
+  MainDelegate* delegate = [[MainDelegate alloc] init];
+  [delegate runApplication];
 
-int main() {
-  talkToOmahaThenExecuteBlock(^(NSData* data, NSError* error) {
-    if (error) {
-      NSLog(@"%@", [error localizedDescription]);
-      return;
-    }
-    Downloader* download = [[Downloader alloc] init];
-    [download downloadChromeImageToDownloadsDirectory:data];
-  });
-
-  // [[NSRunLoop mainRunLoop] run];
-  [[NSRunLoop mainRunLoop]
-      runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
+  [[NSRunLoop mainRunLoop] run];
   return 1;
 }
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn
index 842a0b5..432b4f3 100644
--- a/chrome/installer/mini_installer/BUILD.gn
+++ b/chrome/installer/mini_installer/BUILD.gn
@@ -6,11 +6,11 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//build/config/win/visual_studio_version.gni")
-import("//build_overrides/v8.gni")
 import("//chrome/test/mini_installer/mini_installer_test.gni")
 import("//chrome/version.gni")
 import("//third_party/icu/config.gni")
 import("//ui/base/ui_features.gni")
+import("//v8/gni/v8.gni")
 
 config("mini_installer_compiler_flags") {
   # Disable buffer security checking.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 9d68d7b..0ba5f6e 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -11,6 +11,7 @@
 import("//chrome/common/features.gni")
 import("//chrome/test/base/js2gtest.gni")
 import("//testing/test.gni")
+import("//v8/gni/v8.gni")
 
 if (is_android) {
   import("//build/config/android/rules.gni")
diff --git a/chrome/test/base/js2gtest.gni b/chrome/test/base/js2gtest.gni
index ac86fe96..c3a90889 100644
--- a/chrome/test/base/js2gtest.gni
+++ b/chrome/test/base/js2gtest.gni
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build_overrides/v8.gni")
+import("//v8/gni/v8.gni")
 import("//v8/snapshot_toolchain.gni")
 
 # Variables:
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations
index ebf710a8..7a2518b 100644
--- a/chrome/test/chromedriver/test/test_expectations
+++ b/chrome/test/chromedriver/test/test_expectations
@@ -209,8 +209,6 @@
     _OS_NEGATIVE_FILTER['android:chrome'] + [
         'CorrectEventFiringTest.testShouldFireClickEventWhenClicking',
         'CorrectEventFiringTest.testShouldFireMouseDownEventWhenClicking',
-        # https://bugs.chromium.org/p/chromedriver/issues/detail?id=998
-        'ImplicitWaitTest.testShouldImplicitlyWaitForASingleElement',
     ]
 )
 _OS_NEGATIVE_FILTER['android:chrome_beta'] = (
diff --git a/chrome/test/data/android/payments/bobpay_and_cards.js b/chrome/test/data/android/payments/bobpay_and_cards.js
new file mode 100644
index 0000000..7cd3a2e9
--- /dev/null
+++ b/chrome/test/data/android/payments/bobpay_and_cards.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* global PaymentRequest:false */
+
+/**
+ * Launches the PaymentRequest UI with Bob Pay and credit cards as payment
+ * methods.
+ */
+function buy() {  // eslint-disable-line no-unused-vars
+  try {
+    new PaymentRequest(
+        [{supportedMethods: ['https://bobpay.com', 'visa', 'mastercard']}],
+        {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}})
+        .show()
+        .then(function(resp) {
+          resp.complete('success')
+              .then(function() {
+                print(resp.methodName + '<br>' +
+                      JSON.stringify(resp.details, undefined, 2));
+              })
+              .catch(function(error) {
+                print(error.message);
+              });
+        })
+        .catch(function(error) {
+          print(error.message);
+        });
+  } catch (error) {
+    print(error.message);
+  }
+}
diff --git a/chrome/test/data/android/payments/payment_request_bobpay_and_cards_test.html b/chrome/test/data/android/payments/payment_request_bobpay_and_cards_test.html
new file mode 100644
index 0000000..9447253
--- /dev/null
+++ b/chrome/test/data/android/payments/payment_request_bobpay_and_cards_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<html>
+<head>
+<title>Bob Pay and Cards Test</title>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<button onclick="buy()" id="buy">Bob Pay and Cards Test</button><br>
+<pre id="result"></pre>
+<script src="util.js"></script>
+<script src="bobpay_and_cards.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/bindings/external_message_listener/background.js b/chrome/test/data/extensions/api_test/bindings/external_message_listener/background.js
new file mode 100644
index 0000000..b5dce1a
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bindings/external_message_listener/background.js
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var messagesReceived = [];
+
+// Have we received the real message from the sender extension?
+var receivedRealSenderMessage = false;
+
+// Has the c++ code in the browser test asked us for the total count of messages
+// we've received?
+var sendCountAfterSenderMessage = false;
+
+function getMessageCountAfterReceivingRealSenderMessage() {
+  if (receivedRealSenderMessage) {
+    window.domAutomationController.send(messagesReceived.length);
+  } else {
+    sendCountAfterSenderMessage = true;
+  }
+}
+
+chrome.runtime.onMessageExternal.addListener(function(msg, sender, respond) {
+  messagesReceived.push({msg:msg, sender:sender});
+  if (msg == 'from_sender') {
+    receivedRealSenderMessage = true;
+    if (sendCountAfterSenderMessage) {
+      window.domAutomationController.send(messagesReceived.length);
+    }
+  }
+});
+
+chrome.test.sendMessage('receiver_ready');
\ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/bindings/external_message_listener/manifest.json b/chrome/test/data/extensions/api_test/bindings/external_message_listener/manifest.json
new file mode 100644
index 0000000..032e576d
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bindings/external_message_listener/manifest.json
@@ -0,0 +1,11 @@
+{
+  "name": "External Message Listener (id mlmdejkkkhmhchpmepehbcncoalclded)",
+  "version": "0.1",
+   "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxvZCeDtPe+NIpnq7VtLOb/0bs+QlmF7cOvDzqgwniGEla8Z903Pq/oV8f649IQrvqfz+osvJxvqODzKiGU7a9g1cLu/fSVZXyhlGf7fCQjBYdPC7iFbFkTqSoeUOLCZzXYmxg/2t5WIWq8pLZgz043KjuzuS68pLRltHBRGeG+SWPu+cyfeNcFNPwlOjk6QCD/EUUG/QVeobACekF2/hh4TkRW5iU/vcJ+84aygr3r4hsvIoIEVMtlatHpzqAt/X01zsXJ5d9jH5DI5wnjUVPJKpA31QLkKu0Rq3s/79eTEEiZqSAFFA/1mMPs90u5iUyiYx3U5vNml/P+r6b31f0QIDAQAB",
+  "manifest_version": 2,
+  "permissions": ["tabs"],
+  "background": {
+    "persistent": true,
+    "scripts": ["background.js"]
+   }
+}
diff --git a/chrome/test/data/extensions/api_test/bindings/frames_before_navigation.html b/chrome/test/data/extensions/api_test/bindings/frames_before_navigation.html
new file mode 100644
index 0000000..f4140e6
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bindings/frames_before_navigation.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<body>
+<iframe id="frame1" src="chrome-extension://ficgdghpakbhhkmdjamiedmcoobamkoo/public.html"></iframe>
+<iframe id="frame2" src="chrome-extension://ficgdghpakbhhkmdjamiedmcoobamkoo/nonexistent.html"></iframe>
+<script>
+
+// We expect that chrome.runtime.id will not be set in this frame, and that
+// either chrome.runtime.sendMessage is not defined or we're able to call it
+// (but elsewhere in the browser_test that uses this page we check that the
+// message was not actually sent, or at least didn't incorrectly seem to come
+// from the extension ficgdghpakbhhkmdjamiedmcoobamkoo).
+function testFrame(win) {
+  var haveId = true;
+  var didRun = false;
+  try {
+    haveId = win.eval('typeof chrome.runtime != "undefined" && ' +
+                      'typeof chrome.runtime.id != "undefined"');
+    win.eval('typeof chrome.runtime != "undefined" ' +
+             '&& chrome.runtime.sendMessage(' +
+             '"mlmdejkkkhmhchpmepehbcncoalclded", "evil")');
+    didRun = true;
+  } catch (e) {
+    console.log('caught exception: ' + e);
+  }
+  return didRun && !haveId;
+}
+
+// Test the two frames (actual page and nonexistent page) that were included in
+// the original html document.
+var frame1Success = testFrame(document.getElementById('frame1').contentWindow);
+var frame2Success = testFrame(document.getElementById('frame2').contentWindow);
+
+// Now test two frames that get dynamically created and added to the DOM, again
+// one actual page and one nonexistent.
+var frame3 = document.createElement('iframe');
+frame3.src = 'chrome-extension://ficgdghpakbhhkmdjamiedmcoobamkoo/public.html';
+document.body.appendChild(frame3);
+var frame3Success = testFrame(frame3.contentWindow);
+
+var frame4 = document.createElement('iframe');
+frame4.src =
+    'chrome-extension://ficgdghpakbhhkmdjamiedmcoobamkoo/nonexistent.html';
+document.body.appendChild(frame4);
+var frame4Success = testFrame(frame4.contentWindow);
+
+// Finally, test against two newly opened windows.
+var newWin1 = window.open(
+    'chrome-extension://ficgdghpakbhhkmdjamiedmcoobamkoo/public.html');
+var newWindow1Success = testFrame(newWin1);
+
+var newWin2 = window.open(
+    'chrome-extension://ficgdghpakbhhkmdjamiedmcoobamkoo/nonexistent.html');
+var newWindow2Success = testFrame(newWin2);
+
+function getResult() {
+  window.domAutomationController.send(
+      frame1Success && frame2Success && frame3Success &&
+      frame4Success && newWindow1Success && newWindow2Success);
+}
+
+</script>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/bindings/message_sender/background.js b/chrome/test/data/extensions/api_test/bindings/message_sender/background.js
new file mode 100644
index 0000000..c323550d
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bindings/message_sender/background.js
@@ -0,0 +1,7 @@
+// Copyright 2016 The Chromium 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.test.sendMessage('sender_ready', function(id) {
+  chrome.runtime.sendMessage(id, 'from_sender');
+});
diff --git a/chrome/test/data/extensions/api_test/bindings/message_sender/manifest.json b/chrome/test/data/extensions/api_test/bindings/message_sender/manifest.json
new file mode 100644
index 0000000..2e49eab
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bindings/message_sender/manifest.json
@@ -0,0 +1,13 @@
+{
+  "name": "Message Sender (id ficgdghpakbhhkmdjamiedmcoobamkoo)",
+  "version": "0.1",
+   "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydrsgsTfyyY3zLW+j9ZNb0/Ej0yIKlysp5Scz549wyvpTZIeNqYrq9wt5W6Lcfe9jthuxlLRzKiPP/kk/B8CZCsyet9XbLxnKCJUJUMv/8iih0wC+7tmzqfcDPjBrjv5VT0IAGBaupIDvJbSnf8efGI1U2c3teXZrpk320asfL26x+xezQOPWTcbrY4KINH11AZK8slB0WsWy2pxoel8O7uPRDDy4uqGX27J6oU3WdU5A4/L8j8UQCFcgAuQu/0Cu8WoLuJ4z3CdObQCBXCnmvyIKMpgmqa3Yk5oJRPBqOFkwMnJRFivnTjrBss/M9Jft3WzkHx4Wn9mDzDXQLltOQIDAQAB",
+  "manifest_version": 2,
+  "background": {
+    "persistent": true,
+    "scripts": ["background.js"]
+   },
+  "web_accessible_resources": [
+    "public.html"
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/bindings/message_sender/public.html b/chrome/test/data/extensions/api_test/bindings/message_sender/public.html
new file mode 100644
index 0000000..781a483
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bindings/message_sender/public.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Hello World
+</body>
+</html>
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 14428d1..89da37fdf 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -6,12 +6,12 @@
 import("//build/config/features.gni")
 import("//build/config/locales.gni")
 import("//build/config/ui.gni")
-import("//build_overrides/v8.gni")
 import("//chromecast/build/tests/cast_test.gni")
 import("//chromecast/chromecast.gni")
 import("//media/media_options.gni")
 import("//tools/grit/repack.gni")
 import("//ui/ozone/ozone.gni")
+import("//v8/gni/v8.gni")
 
 if (is_android) {
   import("//build/config/android/rules.gni")
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 9145477..216fc2c 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -32,6 +32,7 @@
 #include "chromecast/browser/cast_memory_pressure_monitor.h"
 #include "chromecast/browser/cast_net_log.h"
 #include "chromecast/browser/devtools/remote_debugging_server.h"
+#include "chromecast/browser/geolocation/cast_access_token_store.h"
 #include "chromecast/browser/metrics/cast_metrics_prefs.h"
 #include "chromecast/browser/metrics/cast_metrics_service_client.h"
 #include "chromecast/browser/pref_service_helper.h"
@@ -49,6 +50,8 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/geolocation_provider.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_switches.h"
@@ -184,6 +187,22 @@
 
 namespace {
 
+// A provider of services for Geolocation.
+class CastGeolocationDelegate : public content::GeolocationDelegate {
+ public:
+  explicit CastGeolocationDelegate(CastBrowserContext* context)
+      : context_(context) {}
+
+  scoped_refptr<content::AccessTokenStore> CreateAccessTokenStore() override {
+    return new CastAccessTokenStore(context_);
+  }
+
+ private:
+  CastBrowserContext* context_;
+
+  DISALLOW_COPY_AND_ASSIGN(CastGeolocationDelegate);
+};
+
 struct DefaultCommandLineSwitch {
   const char* const switch_name;
   const char* const switch_value;
@@ -451,6 +470,9 @@
 #endif
   ::media::InitializeMediaLibrary();
 
+  content::GeolocationProvider::SetGeolocationDelegate(
+      new CastGeolocationDelegate(cast_browser_process_->browser_context()));
+
   // Initializing metrics service and network delegates must happen after cast
   // service is intialized because CastMetricsServiceClient and
   // CastNetworkDelegate may use components initialized by cast service.
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 4b3665c..26f62c7 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -28,7 +28,6 @@
 #include "chromecast/browser/cast_network_delegate.h"
 #include "chromecast/browser/cast_quota_permission_context.h"
 #include "chromecast/browser/cast_resource_dispatcher_host_delegate.h"
-#include "chromecast/browser/geolocation/cast_access_token_store.h"
 #include "chromecast/browser/media/cma_message_filter_host.h"
 #include "chromecast/browser/service/cast_service_simple.h"
 #include "chromecast/browser/url_request_context_factory.h"
@@ -42,7 +41,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/client_certificate_delegate.h"
-#include "content/public/browser/geolocation_delegate.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/web_contents.h"
@@ -89,22 +87,6 @@
 }
 #endif  // defined(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
 
-// A provider of services for Geolocation.
-class CastGeolocationDelegate : public content::GeolocationDelegate {
- public:
-  explicit CastGeolocationDelegate(CastBrowserContext* context)
-      : context_(context) {}
-
-  scoped_refptr<content::AccessTokenStore> CreateAccessTokenStore() override {
-    return new CastAccessTokenStore(context_);
-  }
-
- private:
-  CastBrowserContext* context_;
-
-  DISALLOW_COPY_AND_ASSIGN(CastGeolocationDelegate);
-};
-
 }  // namespace
 
 CastContentBrowserClient::CastContentBrowserClient()
@@ -303,12 +285,6 @@
   AppendExtraCommandLineSwitches(command_line);
 }
 
-content::GeolocationDelegate*
-CastContentBrowserClient::CreateGeolocationDelegate() {
-  return new CastGeolocationDelegate(
-      CastBrowserProcess::GetInstance()->browser_context());
-}
-
 void CastContentBrowserClient::OverrideWebkitPrefs(
     content::RenderViewHost* render_view_host,
     content::WebPreferences* prefs) {
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 9cc6a37b..58595d6 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -104,7 +104,6 @@
   bool IsHandledURL(const GURL& url) override;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
                                       int child_process_id) override;
-  content::GeolocationDelegate* CreateGeolocationDelegate() override;
   void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
                            content::WebPreferences* prefs) override;
   void ResourceDispatcherHostCreated() override;
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
index 4922738..c8e1b22a 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
+++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
@@ -16,6 +16,9 @@
 MediaPipelineBackendManager::MediaPipelineBackendManager(
     scoped_refptr<base::SingleThreadTaskRunner> media_task_runner)
     : media_task_runner_(std::move(media_task_runner)) {
+  DCHECK_EQ(2, NUM_DECODER_TYPES);
+  decoder_count_[AUDIO_DECODER] = 0;
+  decoder_count_[VIDEO_DECODER] = 0;
 }
 
 MediaPipelineBackendManager::~MediaPipelineBackendManager() {
@@ -42,6 +45,26 @@
   return backend_ptr;
 }
 
+bool MediaPipelineBackendManager::IncrementDecoderCount(DecoderType type) {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
+  DCHECK(type < NUM_DECODER_TYPES);
+  const int limit = (type == AUDIO_DECODER) ? 2 : 1;
+  if (decoder_count_[type] >= limit) {
+    LOG(WARNING) << "Decoder limit reached for type " << type;
+    return false;
+  }
+
+  ++decoder_count_[type];
+  return true;
+}
+
+void MediaPipelineBackendManager::DecrementDecoderCount(DecoderType type) {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
+  DCHECK(type < NUM_DECODER_TYPES);
+  DCHECK(decoder_count_[type] > 0);
+  decoder_count_[type]--;
+}
+
 void MediaPipelineBackendManager::OnMediaPipelineBackendDestroyed(
     const MediaPipelineBackend* backend) {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.h b/chromecast/media/cma/backend/media_pipeline_backend_manager.h
index 54e6f20..3cb32760 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_manager.h
+++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.h
@@ -23,6 +23,8 @@
 // All functions in this class should be called on the media thread.
 class MediaPipelineBackendManager {
  public:
+  enum DecoderType { AUDIO_DECODER, VIDEO_DECODER, NUM_DECODER_TYPES };
+
   explicit MediaPipelineBackendManager(
       scoped_refptr<base::SingleThreadTaskRunner> media_task_runner);
   ~MediaPipelineBackendManager();
@@ -49,6 +51,11 @@
  private:
   friend class MediaPipelineBackendWrapper;
 
+  // Backend wrapper instances must use these APIs when allocating and releasing
+  // decoder objects, so we can enforce global limit on #concurrent decoders.
+  bool IncrementDecoderCount(DecoderType type);
+  void DecrementDecoderCount(DecoderType type);
+
   // Internal clean up when a new media pipeline backend is destroyed.
   void OnMediaPipelineBackendDestroyed(const MediaPipelineBackend* backend);
 
@@ -59,6 +66,9 @@
   // A vector that stores all of the existing media_pipeline_backends_.
   std::vector<MediaPipelineBackend*> media_pipeline_backends_;
 
+  // Total count of decoders created
+  int decoder_count_[NUM_DECODER_TYPES];
+
   // Volume multiplier for each type of audio streams.
   std::map<int, float> volume_by_stream_type_;
 
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc
index 89cd79a..d569e6c 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc
+++ b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.cc
@@ -10,6 +10,8 @@
 namespace chromecast {
 namespace media {
 
+using DecoderType = MediaPipelineBackendManager::DecoderType;
+
 MediaPipelineBackendWrapper::MediaPipelineBackendWrapper(
     std::unique_ptr<MediaPipelineBackend> backend,
     int stream_type,
@@ -20,12 +22,18 @@
       audio_decoder_wrapper_(nullptr),
       stream_type_volume_(stream_type_volume),
       is_initialized_(false),
+      have_video_decoder_(false),
       backend_manager_(backend_manager) {
   DCHECK(backend_);
 }
 
 MediaPipelineBackendWrapper::~MediaPipelineBackendWrapper() {
   backend_manager_->OnMediaPipelineBackendDestroyed(this);
+
+  if (audio_decoder_wrapper_)
+    backend_manager_->DecrementDecoderCount(DecoderType::AUDIO_DECODER);
+  if (have_video_decoder_)
+    backend_manager_->DecrementDecoderCount(DecoderType::VIDEO_DECODER);
 }
 
 MediaPipelineBackend::AudioDecoder*
@@ -34,6 +42,9 @@
   if (audio_decoder_wrapper_)
     return nullptr;
 
+  if (!backend_manager_->IncrementDecoderCount(DecoderType::AUDIO_DECODER))
+    return nullptr;
+
   audio_decoder_wrapper_.reset(
       new AudioDecoderWrapper(backend_->CreateAudioDecoder()));
   return audio_decoder_wrapper_.get();
@@ -42,6 +53,12 @@
 MediaPipelineBackend::VideoDecoder*
 MediaPipelineBackendWrapper::CreateVideoDecoder() {
   DCHECK(!is_initialized_);
+  DCHECK(!have_video_decoder_);
+
+  if (!backend_manager_->IncrementDecoderCount(DecoderType::VIDEO_DECODER))
+    return nullptr;
+  have_video_decoder_ = true;
+
   return backend_->CreateVideoDecoder();
 }
 
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h
index 9cb95931..1053d88 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h
+++ b/chromecast/media/cma/backend/media_pipeline_backend_wrapper.h
@@ -49,6 +49,7 @@
   std::unique_ptr<AudioDecoderWrapper> audio_decoder_wrapper_;
   float stream_type_volume_;
   bool is_initialized_;
+  bool have_video_decoder_;
   MediaPipelineBackendManager* const backend_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendWrapper);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 9160b4a..133ff98 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-8618.0.0
\ No newline at end of file
+8622.0.0
\ No newline at end of file
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc
index 93b15553..602cf1b 100644
--- a/components/autofill/core/browser/autofill_profile.cc
+++ b/components/autofill/core/browser/autofill_profile.cc
@@ -449,10 +449,11 @@
   DVLOG(1) << "Merging profiles:\nSource = " << profile << "\nDest = " << *this;
 
   // The comparator's merge operations are biased to prefer the data in the
-  // first profile parameter when the data is the same modulo case. We pass the
-  // incoming profile in this position to prefer accepting updates instead of
-  // preserving the original data. I.e., passing the incoming profile first
-  // accepts case changes, the other ways does not.
+  // first profile parameter when the data is the same modulo case. We expect
+  // the caller to pass the incoming profile in this position to prefer
+  // accepting updates instead of preserving the original data. I.e., passing
+  // the incoming profile first accepts case and diacritic changes, for example,
+  // the other ways does not.
   if (!comparator.MergeNames(profile, *this, &name) ||
       !comparator.MergeEmailAddresses(profile, *this, &email) ||
       !comparator.MergeCompanyNames(profile, *this, &company) ||
@@ -462,16 +463,24 @@
     return false;
   }
 
+  // TODO(rogerm): As implemented, "origin" really denotes "domain of last use".
+  // Find a better merge heuristic. Ditto for language code.
   set_origin(profile.origin());
   set_language_code(profile.language_code());
-  set_use_count(profile.use_count() + use_count());
-  if (profile.use_date() > use_date())
-    set_use_date(profile.use_date());
 
-  // Now that the preferred values have been obtained, update the fields which
-  // need to be modified, if any. Note: that we're comparing the fields for
-  // representational equality below (i.e., are the values byte for byte the
-  // same).
+  // Update the use-count to be the max of the two merge-counts. Alternatively,
+  // we could have summed the two merge-counts. We don't sum because it skews
+  // the frecency value on merge and double counts usage on profile reuse.
+  // Profile reuse is accounted for on RecordUseOf() on selection of a profile
+  // in the autofill drop-down; we don't need to account for that here. Further,
+  // a similar, fully-typed submission that merges to an existing profile should
+  // not be counted as a re-use of that profile.
+  set_use_count(std::max(profile.use_count(), use_count()));
+  set_use_date(std::max(profile.use_date(), use_date()));
+
+  // Update the fields which need to be modified, if any. Note: that we're
+  // comparing the fields for representational equality below (i.e., are the
+  // values byte for byte the same).
 
   bool modified = false;
 
diff --git a/components/autofill/core/browser/autofill_profile_unittest.cc b/components/autofill/core/browser/autofill_profile_unittest.cc
index b3c1c8c..f367f87 100644
--- a/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -880,7 +880,7 @@
   AutofillProfile b = a;
   b.set_guid(base::GenerateGUID());
   EXPECT_TRUE(a.MergeDataFrom(b, "en-US"));
-  EXPECT_EQ(2u, a.use_count());
+  EXPECT_EQ(1u, a.use_count());
 
   // Now the profile is fully populated. Merging it again has no effect (except
   // for usage statistics).
@@ -888,7 +888,7 @@
   c.set_guid(base::GenerateGUID());
   c.set_use_count(3);
   EXPECT_FALSE(a.MergeDataFrom(c, "en-US"));
-  EXPECT_EQ(5u, a.use_count());
+  EXPECT_EQ(3u, a.use_count());
 }
 
 TEST(AutofillProfileTest, OverwriteName_AddNameFull) {
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 6c453802..b6f05820 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -4388,8 +4388,8 @@
                   saved_profiles.front()->GetRawInfo(changed_field.field_type));
       }
       // Verify that the merged profile's use count, use date and modification
-      // date were updated.
-      EXPECT_EQ(2U, saved_profiles.front()->use_count());
+      // date were properly updated.
+      EXPECT_EQ(1U, saved_profiles.front()->use_count());
       EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
                 base::Time::Now() - saved_profiles.front()->use_date());
       EXPECT_GT(
@@ -4471,8 +4471,8 @@
 
   // The new profile should be merged into the existing profile.
   EXPECT_EQ(profile.guid(), guid);
-  // The use count should have been incremented by one.
-  EXPECT_EQ(5U, profile.use_count());
+  // The use count should have be max(4, 1) => 4.
+  EXPECT_EQ(4U, profile.use_count());
   // The use date and modification dates should have been set to less than 500
   // milliseconds ago.
   EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
@@ -4642,10 +4642,9 @@
   // The specified country from the imported profile shoudl be kept (no loss of
   // information).
   EXPECT_EQ(UTF8ToUTF16("US"), profiles[0]->GetRawInfo(ADDRESS_HOME_COUNTRY));
-  // The use count that results from the merge should be the sum of the two
-  // saved profiles plus 1 (imported profile count).
-  EXPECT_EQ(profile1.use_count() + profile2.use_count() + profile3.use_count(),
-            profiles[0]->use_count());
+  // The use count that results from the merge should be the max of all the
+  // profiles use counts.
+  EXPECT_EQ(10U, profiles[0]->use_count());
   // The use date that results from the merge should be the one from the
   // profile1 since it was the most recently used profile.
   EXPECT_LT(profile1.use_date() - base::TimeDelta::FromSeconds(10),
@@ -5109,10 +5108,9 @@
   EXPECT_EQ(UTF8ToUTF16("Fox"), profiles[0]->GetRawInfo(COMPANY_NAME));
   // The country from |Homer1| profile should be kept (no loss of information).
   EXPECT_EQ(UTF8ToUTF16("US"), profiles[0]->GetRawInfo(ADDRESS_HOME_COUNTRY));
-  // The use count that results from the merge should be the sum of Homer 1, 2
+  // The use count that results from the merge should be the max of Homer 1, 2
   // and 3's respective use counts.
-  EXPECT_EQ(Homer1.use_count() + Homer2.use_count() + Homer3.use_count(),
-            profiles[0]->use_count());
+  EXPECT_EQ(10U, profiles[0]->use_count());
   // The use date that results from the merge should be the one from the
   // |Homer1| since it was the most recently used profile.
   EXPECT_LT(Homer1.use_date() - base::TimeDelta::FromSeconds(5),
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc b/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
index cc4d442..ee9b35b 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
@@ -377,6 +377,7 @@
   profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
   profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                           ASCIIToUTF16("1 1st st"));
+  profiles_from_web_db.back()->set_use_count(27);
   profiles_from_web_db.push_back(
       new AutofillProfile(guid_present2, origin_present2));
   profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
@@ -384,17 +385,19 @@
                                           ASCIIToUTF16("2 2nd st"));
 
   // The synced profiles are identical to the local ones, except that the guids
-  // are different.
+  // and use_count values are different.
   syncer::SyncDataList data_list;
   AutofillProfile profile1(guid_synced1, origin_synced1);
   profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
   profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
   profile1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc."));
+  profile1.set_use_count(13);
   data_list.push_back(autofill_syncable_service_.CreateData(profile1));
   AutofillProfile profile2(guid_synced2, origin_synced2);
   profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
   profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
   profile2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC."));
+  profile1.set_use_count(4);
   data_list.push_back(autofill_syncable_service_.CreateData(profile2));
 
   // The first profile should have its origin updated.
@@ -403,8 +406,8 @@
   AutofillProfile expected_profile(profile1);
   expected_profile.set_origin(origin_present1);
   expected_profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("John"));
-  // Merging two profile adds their user count.
-  expected_profile.set_use_count(2);
+  // Merging two profile takes their max use count.
+  expected_profile.set_use_count(27);
   syncer::SyncChangeList expected_change_list;
   expected_change_list.push_back(
       syncer::SyncChange(FROM_HERE,
@@ -670,7 +673,7 @@
   EXPECT_EQ(base::Time::FromTimeT(35), into_profile.use_date());
 }
 
-// Tests that MergeSimilarProfiles saves the sum of the use counts of the two
+// Tests that MergeSimilarProfiles saves the max of the use counts of the two
 // profiles in |into_profile|.
 TEST_F(AutofillProfileSyncableServiceTest,
        MergeSimilarProfiles_NonZeroUseCounts) {
@@ -680,14 +683,14 @@
   from_profile.set_use_date(base::Time::FromTimeT(1234));
   into_profile.set_use_date(base::Time::FromTimeT(1234));
 
-  from_profile.set_use_count(5);
-  into_profile.set_use_count(12);
+  from_profile.set_use_count(12);
+  into_profile.set_use_count(5);
 
   // Expect true because the use count of |from_profile| was added to the use
   // count of |into_profile|.
   EXPECT_TRUE(AutofillProfileSyncableService::MergeSimilarProfiles(
       from_profile, &into_profile, "en-US"));
-  EXPECT_EQ(17U, into_profile.use_count());
+  EXPECT_EQ(12U, into_profile.use_count());
 }
 
 // Ensure that all profile fields are able to be synced up from the client to
diff --git a/components/browser_sync/browser/profile_sync_service_autofill_unittest.cc b/components/browser_sync/browser/profile_sync_service_autofill_unittest.cc
index df6b928..23dc3f8e 100644
--- a/components/browser_sync/browser/profile_sync_service_autofill_unittest.cc
+++ b/components/browser_sync/browser/profile_sync_service_autofill_unittest.cc
@@ -1029,7 +1029,7 @@
   AutofillProfile expected_profile(sync_profile);
   expected_profile.SetRawInfo(NAME_FULL,
                               ASCIIToUTF16("Billing Mitchell Morrison"));
-  expected_profile.set_use_count(2);
+  expected_profile.set_use_count(1);
 
   std::vector<AutofillProfile*> native_profiles;
   native_profiles.push_back(native_profile);
@@ -1062,7 +1062,7 @@
   // Check that the latest use date is saved.
   EXPECT_EQ(base::Time::FromTimeT(4321), new_sync_profiles[0].use_date());
   // Check that the use counts were added (default value is 1).
-  EXPECT_EQ(2U, new_sync_profiles[0].use_count());
+  EXPECT_EQ(1U, new_sync_profiles[0].use_count());
 }
 
 // Tests that a sync with a new native profile that matches an older new sync
@@ -1089,7 +1089,7 @@
   AutofillProfile expected_profile(sync_profile);
   expected_profile.SetRawInfo(NAME_FULL,
                               ASCIIToUTF16("Billing Mitchell Morrison"));
-  expected_profile.set_use_count(2);
+  expected_profile.set_use_count(1);
   expected_profile.set_use_date(native_profile->use_date());
 
   std::vector<AutofillProfile*> native_profiles;
@@ -1123,7 +1123,7 @@
   // Check that the latest use date is saved.
   EXPECT_EQ(base::Time::FromTimeT(4321), new_sync_profiles[0].use_date());
   // Check that the use counts were added (default value is 1).
-  EXPECT_EQ(2U, new_sync_profiles[0].use_count());
+  EXPECT_EQ(1U, new_sync_profiles[0].use_count());
 }
 
 // Tests that a sync with a new native profile that matches an a new sync
@@ -1153,7 +1153,7 @@
   expected_profile.SetRawInfo(NAME_FULL,
                               ASCIIToUTF16("Billing Mitchell Morrison"));
   expected_profile.set_use_date(sync_profile.use_date());
-  expected_profile.set_use_count(2);
+  expected_profile.set_use_count(1);
 
   std::vector<AutofillProfile*> native_profiles;
   native_profiles.push_back(native_profile);
@@ -1187,7 +1187,7 @@
   // Check that the latest use date is saved.
   EXPECT_EQ(base::Time::FromTimeT(4321), new_sync_profiles[0].use_date());
   // Check that the use counts were added (default value is 1).
-  EXPECT_EQ(2U, new_sync_profiles[0].use_count());
+  EXPECT_EQ(1U, new_sync_profiles[0].use_count());
 }
 
 // Tests that a sync with a new native profile that differ only by name a new
diff --git a/components/certificate_transparency/log_dns_client.cc b/components/certificate_transparency/log_dns_client.cc
index 4b24baf..76c7494e 100644
--- a/components/certificate_transparency/log_dns_client.cc
+++ b/components/certificate_transparency/log_dns_client.cc
@@ -13,11 +13,13 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "components/base32/base32.h"
 #include "crypto/sha2.h"
 #include "net/base/net_errors.h"
 #include "net/cert/merkle_audit_proof.h"
 #include "net/dns/dns_client.h"
+#include "net/dns/dns_config_service.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_response.h"
 #include "net/dns/dns_transaction.h"
@@ -86,9 +88,21 @@
       net_log_(net_log),
       weak_ptr_factory_(this) {
   CHECK(dns_client_);
+  net::NetworkChangeNotifier::AddDNSObserver(this);
+  UpdateDnsConfig();
 }
 
-LogDnsClient::~LogDnsClient() {}
+LogDnsClient::~LogDnsClient() {
+  net::NetworkChangeNotifier::RemoveDNSObserver(this);
+}
+
+void LogDnsClient::OnDNSChanged() {
+  UpdateDnsConfig();
+}
+
+void LogDnsClient::OnInitialDNSConfigRead() {
+  UpdateDnsConfig();
+}
 
 void LogDnsClient::QueryLeafIndex(base::StringPiece domain_for_log,
                                   base::StringPiece leaf_hash,
@@ -291,4 +305,11 @@
       base::Bind(query.callback, net::OK, base::Passed(std::move(proof))));
 }
 
+void LogDnsClient::UpdateDnsConfig() {
+  net::DnsConfig config;
+  net::NetworkChangeNotifier::GetDnsConfig(&config);
+  if (config.IsValid())
+    dns_client_->SetConfig(config);
+}
+
 }  // namespace certificate_transparency
diff --git a/components/certificate_transparency/log_dns_client.h b/components/certificate_transparency/log_dns_client.h
index e00cefd..3667029 100644
--- a/components/certificate_transparency/log_dns_client.h
+++ b/components/certificate_transparency/log_dns_client.h
@@ -13,6 +13,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
+#include "net/base/network_change_notifier.h"
 #include "net/log/net_log.h"
 
 namespace net {
@@ -30,7 +31,8 @@
 // All queries are performed asynchronously.
 // For more information, see
 // https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md.
-class LogDnsClient {
+// It must be created and deleted on the same thread. It is not thread-safe.
+class LogDnsClient : public net::NetworkChangeNotifier::DNSObserver {
  public:
   // Invoked when a leaf index query completes.
   // If an error occured, |net_error| will be a net::Error code, otherwise it
@@ -48,9 +50,20 @@
 
   // Creates a log client that will take ownership of |dns_client| and use it
   // to perform DNS queries. Queries will be logged to |net_log|.
+  // The |dns_client| does not need to be configured first - this will be done
+  // automatically as needed.
   LogDnsClient(std::unique_ptr<net::DnsClient> dns_client,
                const net::BoundNetLog& net_log);
-  virtual ~LogDnsClient();
+  // Must be deleted on the same thread that it was created on.
+  ~LogDnsClient() override;
+
+  // Called by NetworkChangeNotifier when the DNS config changes.
+  // The DnsClient's config will be updated in response.
+  void OnDNSChanged() override;
+
+  // Called by NetworkChangeNotifier when the DNS config is first read.
+  // The DnsClient's config will be updated in response.
+  void OnInitialDNSConfigRead() override;
 
   // Queries a CT log to discover the index of the leaf with |leaf_hash|.
   // The log is identified by |domain_for_log|, which is the DNS name used as a
@@ -95,6 +108,9 @@
       int net_error,
       const net::DnsResponse* response);
 
+  // Updates the |dns_client_| config using NetworkChangeNotifier.
+  void UpdateDnsConfig();
+
   // A DNS query that is in flight.
   template <typename CallbackType>
   struct Query {
diff --git a/components/certificate_transparency/log_dns_client_unittest.cc b/components/certificate_transparency/log_dns_client_unittest.cc
index d8f11da..7d25bafe 100644
--- a/components/certificate_transparency/log_dns_client_unittest.cc
+++ b/components/certificate_transparency/log_dns_client_unittest.cc
@@ -32,7 +32,9 @@
 namespace certificate_transparency {
 namespace {
 
+using ::testing::IsEmpty;
 using ::testing::IsNull;
+using ::testing::Not;
 using ::testing::NotNull;
 using net::test::IsError;
 using net::test::IsOk;
@@ -41,6 +43,18 @@
     "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8"
     "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04";
 
+// Necessary to expose SetDnsConfig for testing.
+class DnsChangeNotifier : public net::NetworkChangeNotifier {
+ public:
+  static void SetInitialDnsConfig(const net::DnsConfig& config) {
+    net::NetworkChangeNotifier::SetInitialDnsConfig(config);
+  }
+
+  static void SetDnsConfig(const net::DnsConfig& config) {
+    net::NetworkChangeNotifier::SetDnsConfig(config);
+  }
+};
+
 // Always return min, to simplify testing.
 // This should result in the DNS query ID always being 0.
 int FakeRandInt(int min, int max) {
@@ -259,19 +273,23 @@
 
 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> {
  protected:
-  LogDnsClientTest() {
+  LogDnsClientTest() :
+    network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
+    net::DnsConfig dns_config;
     // Use an invalid nameserver address. This prevents the tests accidentally
     // sending real DNS queries. The mock sockets don't care that the address
     // is invalid.
-    dns_config_.nameservers.push_back(net::IPEndPoint());
+    dns_config.nameservers.push_back(net::IPEndPoint());
     // Don't attempt retransmissions - just fail.
-    dns_config_.attempts = 1;
+    dns_config.attempts = 1;
     // This ensures timeouts are long enough for memory tests.
-    dns_config_.timeout = TestTimeouts::action_timeout();
+    dns_config.timeout = TestTimeouts::action_timeout();
     // Simplify testing - don't require random numbers for the source port.
     // This means our FakeRandInt function should only be called to get query
     // IDs.
-    dns_config_.randomize_ports = false;
+    dns_config.randomize_ports = false;
+
+    DnsChangeNotifier::SetInitialDnsConfig(dns_config);
   }
 
   void ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode) {
@@ -299,7 +317,10 @@
     mock_socket_data_.back()->AddToFactory(&socket_factory_);
 
     // Speed up timeout tests.
-    dns_config_.timeout = TestTimeouts::tiny_timeout();
+    net::DnsConfig dns_config;
+    DnsChangeNotifier::GetDnsConfig(&dns_config);
+    dns_config.timeout = TestTimeouts::tiny_timeout();
+    DnsChangeNotifier::SetDnsConfig(dns_config);
   }
 
   void ExpectLeafIndexRequestAndResponse(base::StringPiece qname,
@@ -332,6 +353,7 @@
                       MockLeafIndexCallback* callback) {
     std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient();
     LogDnsClient log_client(std::move(dns_client), net::BoundNetLog());
+    net::NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests();
 
     log_client.QueryLeafIndex(log_domain, leaf_hash, callback->AsCallback());
     callback->WaitUntilRun();
@@ -343,21 +365,20 @@
                        MockAuditProofCallback* callback) {
     std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient();
     LogDnsClient log_client(std::move(dns_client), net::BoundNetLog());
+    net::NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests();
 
     log_client.QueryAuditProof(log_domain, leaf_index, tree_size,
                                callback->AsCallback());
     callback->WaitUntilRun();
   }
 
- private:
   std::unique_ptr<net::DnsClient> CreateDnsClient() {
-    std::unique_ptr<net::DnsClient> client =
-        net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_,
-                                               base::Bind(&FakeRandInt));
-    client->SetConfig(dns_config_);
-    return client;
+    return net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_,
+                                                  base::Bind(&FakeRandInt));
   }
 
+ private:
+
   void ExpectRequestAndResponse(base::StringPiece qname,
                                 base::StringPiece answer) {
     std::vector<char> request = CreateDnsTxtRequest(qname);
@@ -368,9 +389,16 @@
     mock_socket_data_.back()->AddToFactory(&socket_factory_);
   }
 
-  net::DnsConfig dns_config_;
+  // This will be the NetworkChangeNotifier singleton for the duration of the
+  // test. It is accessed statically by LogDnsClient.
+  std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
+  // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient,
+  // the underlying net::DnsClient, and NetworkChangeNotifier.
   base::MessageLoopForIO message_loop_;
+  // One MockSocketData for each socket that is created. This corresponds to one
+  // for each DNS request sent.
   std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_;
+  // Provides as many mock sockets as there are entries in |mock_socket_data_|.
   net::MockClientSocketFactory socket_factory_;
 };
 
@@ -737,6 +765,38 @@
   EXPECT_THAT(callback.proof(), IsNull());
 }
 
+TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) {
+  std::unique_ptr<net::DnsClient> tmp = CreateDnsClient();
+  net::DnsClient* dns_client = tmp.get();
+  LogDnsClient log_client(std::move(tmp), net::BoundNetLog());
+
+  // Get the current DNS config, modify it and broadcast the update.
+  net::DnsConfig config(*dns_client->GetConfig());
+  ASSERT_NE(123, config.attempts);
+  config.attempts = 123;
+  DnsChangeNotifier::SetDnsConfig(config);
+
+  // Let the DNS config change propogate.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(123, dns_client->GetConfig()->attempts);
+}
+
+TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) {
+  std::unique_ptr<net::DnsClient> tmp = CreateDnsClient();
+  net::DnsClient* dns_client = tmp.get();
+  LogDnsClient log_client(std::move(tmp), net::BoundNetLog());
+
+  // Get the current DNS config, modify it and broadcast the update.
+  net::DnsConfig config(*dns_client->GetConfig());
+  ASSERT_THAT(config.nameservers, Not(IsEmpty()));
+  config.nameservers.clear();  // Makes config invalid
+  DnsChangeNotifier::SetDnsConfig(config);
+
+  // Let the DNS config change propogate.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty()));
+}
+
 INSTANTIATE_TEST_CASE_P(ReadMode,
                         LogDnsClientTest,
                         ::testing::Values(net::IoMode::ASYNC,
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index d614a09..c7e4a23 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -61,33 +61,12 @@
   args = []
 }
 
-# Compile plist into |output_name|.
-ios_info_plist("compile_cronet_plist") {
-  executable_name = "Cronet"
-  output_name = "$target_gen_dir/Info.plist"
-  info_plist_target = ":tweak_cronet_plist"
-}
-
-# Bundle plist into Cronet.Framework.
-bundle_data("cronet_info_plist") {
-  deps = [
-    ":compile_cronet_plist",
-  ]
-
-  sources = [
-    "$target_gen_dir/Info.plist",
-  ]
-  outputs = [
-    "{{bundle_root_dir}}/Info.plist",
-  ]
-}
-
 ios_framework_bundle("cronet_framework") {
   output_name = "Cronet"
+  info_plist_target = ":tweak_cronet_plist"
+  code_signing_enabled = false
 
   deps = [
-    ":compile_cronet_plist",
-    ":cronet_info_plist",
     ":cronet_sources",
     "//base",
     "//net:net",
diff --git a/components/cronet/tools/package_ios.py b/components/cronet/tools/package_ios.py
index ffebd63..256b1c0 100755
--- a/components/cronet/tools/package_ios.py
+++ b/components/cronet/tools/package_ios.py
@@ -52,7 +52,7 @@
                         "cronet/libcronet_standalone.a")
 
 
-def package_ios_framework(out_dir='out/Framework', extra_options=''):
+def package_ios_framework(out_dir, target, framework_name, extra_options=''):
   print 'Building Cronet Dynamic Framework...'
 
   # Use Ninja to build all possible combinations.
@@ -62,7 +62,7 @@
                 'Release-iphoneos']
   for build_dir in build_dirs:
     print 'Building ' + build_dir
-    build_result = run('ninja -C out/' + build_dir + ' cronet_framework',
+    build_result = run('ninja -C out/' + build_dir + ' ' + target,
                        extra_options)
     if build_result != 0:
       return build_result
@@ -70,16 +70,17 @@
   # Package all builds in the output directory
   os.makedirs(out_dir)
   for build_dir in build_dirs:
-    shutil.copytree(os.path.join('out', build_dir, 'Cronet.framework'),
-                    os.path.join(out_dir, build_dir, 'Cronet.framework'))
+    shutil.copytree(os.path.join('out', build_dir, framework_name),
+                    os.path.join(out_dir, build_dir, framework_name))
     if 'Release' in build_dir:
-      shutil.copytree(os.path.join('out', build_dir, 'Cronet.framework.dSYM'),
-                      os.path.join(out_dir, build_dir, 'Cronet.framework.dSYM'))
+      shutil.copytree(os.path.join('out', build_dir, framework_name + '.dSYM'),
+                      os.path.join(out_dir, build_dir,
+                                   framework_name + '.dSYM'))
   # Copy the version file
   shutil.copy2('chrome/VERSION', out_dir)
   # Copy the headers
   shutil.copytree(os.path.join(out_dir, build_dirs[0],
-                               'Cronet.framework', 'Headers'),
+                               framework_name, 'Headers'),
                   os.path.join(out_dir, 'Headers'))
 
 
@@ -134,7 +135,14 @@
 
 
 def main():
-  parser = argparse.ArgumentParser()
+  description = (
+    '1. To build Cronet.framework call:\n'
+    'package_ios.py --framework out/Frameworks\n'
+    '2. To build CrNet.framework call:\n'
+    'package_ios.py --crnet out/crnet\n'
+  )
+  parser = argparse.ArgumentParser(description=description)
+
   parser.add_argument('out_dir', nargs=1, help='path to output directory')
   parser.add_argument('-g', '--gn', action='store_true',
                       help='build using gn')
@@ -144,6 +152,11 @@
                       help='use release configuration')
   parser.add_argument('--framework', action='store_true',
                       help='build Cronet dynamic framework')
+  parser.add_argument('--crnet', action='store_true',
+                      help='build CrNet dynamic framework')
+  parser.add_argument('--use_full_icu', action='store_true',
+                      help='use full version of ICU instead of \
+                      platform ICU alternative.')
 
   options, extra_options_list = parser.parse_known_args()
   print options
@@ -156,16 +169,24 @@
     print >>sys.stderr, 'The output directory already exists: ' + out_dir
     return 1
 
+  use_platform_icu_alternatives = 'use_platform_icu_alternatives=1' \
+      if not options.use_full_icu else 'use_platform_icu_alternatives=0'
+
   gyp_defines = 'GYP_DEFINES="OS=ios enable_websockets=0 '+ \
       'disable_file_support=1 disable_ftp_support=1 '+ \
-      'enable_errorprone=1 use_platform_icu_alternatives=1 ' + \
-      'disable_brotli_filter=1 chromium_ios_signing=0 ' + \
-      'target_subarch=both"'
+      'enable_errorprone=1 disable_brotli_filter=1 chromium_ios_signing=0 ' + \
+      'target_subarch=both ' + use_platform_icu_alternatives + '"'
+
   if not options.gn:
     run (gyp_defines + ' gclient runhooks')
 
   if options.framework:
-    return package_ios_framework(out_dir, extra_options_list)
+    return package_ios_framework(out_dir, 'cronet_framework',
+                                 'Cronet.framework', extra_options_list)
+
+  if options.crnet:
+    return package_ios_framework(out_dir, 'crnet_framework',
+                                 'CrNet.framework', extra_options_list)
 
   if options.gn:
     return package_ios_framework_using_gn(out_dir, extra_options_list)
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 f875754..39536ef 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
@@ -534,19 +534,19 @@
   }
 }
 
-base::Value*
+std::unique_ptr<base::Value>
 DataReductionProxyCompressionStats::HistoricNetworkStatsInfoToValue() {
   DCHECK(thread_checker_.CalledOnValidThread());
   int64_t total_received = GetInt64(prefs::kHttpReceivedContentLength);
   int64_t total_original = GetInt64(prefs::kHttpOriginalContentLength);
 
-  base::DictionaryValue* dict = new base::DictionaryValue();
+  auto dict = base::MakeUnique<base::DictionaryValue>();
   // Use strings to avoid overflow. base::Value only supports 32-bit integers.
   dict->SetString("historic_received_content_length",
                   base::Int64ToString(total_received));
   dict->SetString("historic_original_content_length",
                   base::Int64ToString(total_original));
-  return dict;
+  return std::move(dict);
 }
 
 int64_t DataReductionProxyCompressionStats::GetLastUpdateTime() {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
index a8fda47..89912a8a 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
@@ -71,9 +71,8 @@
                             const std::string& mime_type);
 
   // Creates a |Value| summary of the persistent state of the network session.
-  // The caller is responsible for deleting the returned value.
   // Must be called on the UI thread.
-  base::Value* HistoricNetworkStatsInfoToValue();
+  std::unique_ptr<base::Value> HistoricNetworkStatsInfoToValue();
 
   // Returns the time in milliseconds since epoch that the last update was made
   // to the daily original and received content lengths.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
index 08e1f257..3bc7567 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
@@ -516,7 +516,7 @@
   SetInt64(prefs::kHttpOriginalContentLength, kOriginalLength);
   SetInt64(prefs::kHttpReceivedContentLength, kReceivedLength);
 
-  stats_value.reset(compression_stats()->HistoricNetworkStatsInfoToValue());
+  stats_value = compression_stats()->HistoricNetworkStatsInfoToValue();
   EXPECT_TRUE(stats_value->GetAsDictionary(&dict));
   VerifyPrefs(dict);
 }
@@ -535,7 +535,7 @@
   SetInt64(prefs::kHttpOriginalContentLength, kOriginalLength);
   SetInt64(prefs::kHttpReceivedContentLength, kReceivedLength);
 
-  stats_value.reset(compression_stats()->HistoricNetworkStatsInfoToValue());
+  stats_value = compression_stats()->HistoricNetworkStatsInfoToValue();
   EXPECT_TRUE(stats_value->GetAsDictionary(&dict));
   VerifyPrefs(dict);
 }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
index a1083825..d3ddd19 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -280,8 +280,8 @@
             context_.network_delegate());
 
     std::unique_ptr<base::DictionaryValue> session_network_stats_info =
-        base::DictionaryValue::From(base::WrapUnique(
-            drp_network_delegate->SessionNetworkStatsInfoToValue()));
+        base::DictionaryValue::From(
+            drp_network_delegate->SessionNetworkStatsInfoToValue());
     EXPECT_TRUE(session_network_stats_info);
 
     std::string string_value;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index 4e11f1b..50a7a09b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
@@ -146,15 +147,15 @@
   data_reduction_proxy_bypass_stats_ = bypass_stats;
 }
 
-base::Value*
+std::unique_ptr<base::Value>
 DataReductionProxyNetworkDelegate::SessionNetworkStatsInfoToValue() const {
-  base::DictionaryValue* dict = new base::DictionaryValue();
+  auto dict = base::MakeUnique<base::DictionaryValue>();
   // Use strings to avoid overflow. base::Value only supports 32-bit integers.
   dict->SetString("session_received_content_length",
                   base::Int64ToString(total_received_bytes_));
   dict->SetString("session_original_content_length",
                   base::Int64ToString(total_original_received_bytes_));
-  return dict;
+  return std::move(dict);
 }
 
 void DataReductionProxyNetworkDelegate::OnBeforeURLRequestInternal(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
index 410f3ae5..9dbc8ff 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -81,9 +81,8 @@
       DataReductionProxyIOData* io_data,
       DataReductionProxyBypassStats* bypass_stats);
 
-  // Creates a |Value| summary of the state of the network session. The caller
-  // is responsible for deleting the returned value.
-  base::Value* SessionNetworkStatsInfoToValue() const;
+  // Creates a base::Value summary of the state of the network session.
+  std::unique_ptr<base::Value> SessionNetworkStatsInfoToValue() const;
 
  private:
   // Resets if Lo-Fi has been used for the last main frame load to false.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 8d7bd69..d7de09c4 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -271,8 +271,8 @@
             context_.network_delegate());
 
     std::unique_ptr<base::DictionaryValue> session_network_stats_info =
-        base::DictionaryValue::From(base::WrapUnique(
-            drp_network_delegate->SessionNetworkStatsInfoToValue()));
+        base::DictionaryValue::From(
+            drp_network_delegate->SessionNetworkStatsInfoToValue());
     EXPECT_TRUE(session_network_stats_info);
 
     std::string string_value;
@@ -655,7 +655,6 @@
     bool lofi_enabled_through_switch;
     bool auto_lofi_enabled;
     int expected_count;
-
   } tests[] = {
       {
           // Lo-Fi disabled.
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
index 44ab9c1..2d730a84 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.cc
@@ -11,6 +11,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -72,7 +73,7 @@
 // static
 void DataReductionProxyEventStore::AddConstants(
     base::DictionaryValue* constants_dict) {
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+  auto dict = base::MakeUnique<base::DictionaryValue>();
   for (size_t i = 0;
        i < arraysize(kDataReductionProxyBypassEventTypeTable); ++i) {
     dict->SetInteger(kDataReductionProxyBypassEventTypeTable[i].name,
@@ -81,7 +82,7 @@
 
   constants_dict->Set("dataReductionProxyBypassEventType", std::move(dict));
 
-  dict.reset(new base::DictionaryValue());
+  dict = base::MakeUnique<base::DictionaryValue>();
   for (size_t i = 0; i < arraysize(kDataReductionProxyBypassActionTypeTable);
        ++i) {
     dict->SetInteger(kDataReductionProxyBypassActionTypeTable[i].name,
@@ -98,19 +99,17 @@
 }
 
 DataReductionProxyEventStore::~DataReductionProxyEventStore() {
-  STLDeleteElements(&stored_events_);
 }
 
-base::Value* DataReductionProxyEventStore::GetSummaryValue() const {
+std::unique_ptr<base::DictionaryValue>
+DataReductionProxyEventStore::GetSummaryValue() const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  std::unique_ptr<base::DictionaryValue> data_reduction_proxy_values(
-      new base::DictionaryValue());
-  data_reduction_proxy_values->SetBoolean("enabled", enabled_);
 
-  base::Value* current_configuration = current_configuration_.get();
-  if (current_configuration != nullptr) {
+  auto data_reduction_proxy_values = base::MakeUnique<base::DictionaryValue>();
+  data_reduction_proxy_values->SetBoolean("enabled", enabled_);
+  if (current_configuration_) {
     data_reduction_proxy_values->Set("proxy_config",
-                                     current_configuration->DeepCopy());
+                                     current_configuration_->DeepCopy());
   }
 
   switch (secure_proxy_check_state_) {
@@ -125,13 +124,10 @@
       break;
     case CHECK_UNKNOWN:
       break;
-    default:
-      NOTREACHED();
-      break;
   }
 
   base::Value* last_bypass_event = last_bypass_event_.get();
-  if (last_bypass_event != nullptr) {
+  if (last_bypass_event) {
     int current_time_ticks_ms =
         (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
     if (expiration_ticks_ > current_time_ticks_ms) {
@@ -140,24 +136,18 @@
     }
   }
 
-  base::ListValue* eventsList = new base::ListValue();
-  for (size_t i = 0; i < stored_events_.size(); ++i)
-    eventsList->Append(stored_events_[i]->DeepCopy());
-
-  data_reduction_proxy_values->Set("events", eventsList);
-
-  return data_reduction_proxy_values.release();
+  auto events_list = base::MakeUnique<base::ListValue>();
+  for (const auto& event : stored_events_)
+    events_list->Append(event->DeepCopy());
+  data_reduction_proxy_values->Set("events", std::move(events_list));
+  return data_reduction_proxy_values;
 }
 
 void DataReductionProxyEventStore::AddEvent(
     std::unique_ptr<base::Value> event) {
-  if (stored_events_.size() == kMaxEventsToStore) {
-    base::Value* head = stored_events_.front();
+  if (stored_events_.size() == kMaxEventsToStore)
     stored_events_.pop_front();
-    delete head;
-  }
-
-  stored_events_.push_back(event.release());
+  stored_events_.push_back(std::move(event));
 }
 
 void DataReductionProxyEventStore::AddEnabledEvent(
@@ -223,8 +213,7 @@
     return std::string();
 
   // Explicitly add parameters to prevent automatic adding of new parameters.
-  std::unique_ptr<base::DictionaryValue> last_bypass(
-      new base::DictionaryValue());
+  auto last_bypass = base::MakeUnique<base::DictionaryValue>();
 
   std::string str_value;
   int int_value;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h
index 57b1fe1..1523fac1 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h
@@ -41,8 +41,7 @@
   // - The proxy configuration
   // - The state of the last secure proxy check response
   // - A stream of the last Data Reduction Proxy related events.
-  // The caller is responsible for deleting the returned value.
-  base::Value* GetSummaryValue() const;
+  std::unique_ptr<base::DictionaryValue> GetSummaryValue() const;
 
   // Adds DATA_REDUCTION_PROXY event with no parameters to the event store.
   void AddEvent(std::unique_ptr<base::Value> event) override;
@@ -75,7 +74,7 @@
 
   // A deque of data reduction proxy related events. It is used as a circular
   // buffer to prevent unbounded memory utilization.
-  std::deque<base::Value*> stored_events_;
+  std::deque<std::unique_ptr<base::Value>> stored_events_;
   // Whether the data reduction proxy is enabled or not.
   bool enabled_;
   // The current data reduction proxy configuration.
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 9f3aaadd..06c277d 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -8,6 +8,7 @@
 #include "ash/common/shell_window_ids.h"
 #include "ash/common/wm/window_resizer.h"
 #include "ash/common/wm/window_state.h"
+#include "ash/common/wm/window_state_delegate.h"
 #include "ash/shell.h"
 #include "ash/wm/window_state_aura.h"
 #include "ash/wm/window_util.h"
@@ -27,6 +28,7 @@
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/gfx/path.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
 #include "ui/wm/core/shadow.h"
 #include "ui/wm/core/shadow_controller.h"
 #include "ui/wm/core/shadow_types.h"
@@ -98,6 +100,39 @@
   DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
 };
 
+// Handles a user's fullscreen request (Shift+F4/F4).
+class CustomWindowStateDelegate : public ash::wm::WindowStateDelegate,
+                                  public views::WidgetObserver {
+ public:
+  explicit CustomWindowStateDelegate(views::Widget* widget) : widget_(widget) {
+    widget_->AddObserver(this);
+  }
+  ~CustomWindowStateDelegate() override {
+    if (widget_)
+      widget_->RemoveObserver(this);
+  }
+
+  // Overridden from ash::wm::WindowStateDelegate:
+  bool ToggleFullscreen(ash::wm::WindowState* window_state) override {
+    if (widget_) {
+      bool enter_fullscreen = !window_state->IsFullscreen();
+      widget_->SetFullscreen(enter_fullscreen);
+    }
+    return true;
+  }
+
+  // Overridden from views::WidgetObserver:
+  void OnWidgetDestroying(views::Widget* widget) override {
+    widget_->RemoveObserver(this);
+    widget_ = nullptr;
+  }
+
+ private:
+  views::Widget* widget_;
+
+  DISALLOW_COPY_AND_ASSIGN(CustomWindowStateDelegate);
+};
+
 class ShellSurfaceWidget : public views::Widget {
  public:
   explicit ShellSurfaceWidget(ShellSurface* shell_surface)
@@ -908,6 +943,10 @@
         ui::AcceleratorManager::kNormalPriority, this);
   }
 
+  // Set delegate for handling of fullscreening.
+  window_state->SetDelegate(std::unique_ptr<ash::wm::WindowStateDelegate>(
+      new CustomWindowStateDelegate(widget_)));
+
   // Show widget next time Commit() is called.
   pending_show_widget_ = true;
 }
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc
index 468eb0bd..483ecc8 100644
--- a/components/exo/shell_surface_unittest.cc
+++ b/components/exo/shell_surface_unittest.cc
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ash/aura/wm_window_aura.h"
 #include "ash/common/shell_window_ids.h"
 #include "ash/common/wm/window_state.h"
+#include "ash/common/wm/wm_event.h"
 #include "ash/common/wm_shell.h"
 #include "ash/wm/window_state_aura.h"
 #include "base/message_loop/message_loop.h"
@@ -607,5 +609,40 @@
   EXPECT_EQ(gfx::Rect(10, 10, 100, 100), shadow->layer()->parent()->bounds());
 }
 
+TEST_F(ShellSurfaceTest, ToggleFullscreen) {
+  gfx::Size buffer_size(256, 256);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  std::unique_ptr<Surface> surface(new Surface);
+  std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get()));
+
+  surface->Attach(buffer.get());
+  surface->Commit();
+  EXPECT_EQ(
+      buffer_size.ToString(),
+      shell_surface->GetWidget()->GetWindowBoundsInScreen().size().ToString());
+
+  shell_surface->Maximize();
+  EXPECT_EQ(CurrentContext()->bounds().width(),
+            shell_surface->GetWidget()->GetWindowBoundsInScreen().width());
+
+  ash::wm::WMEvent event(ash::wm::WM_EVENT_TOGGLE_FULLSCREEN);
+  ash::WmWindow* window =
+      ash::WmWindowAura::Get(shell_surface->GetWidget()->GetNativeWindow());
+
+  // Enter fullscreen mode.
+  window->GetWindowState()->OnWMEvent(&event);
+
+  EXPECT_EQ(CurrentContext()->bounds().ToString(),
+            shell_surface->GetWidget()->GetWindowBoundsInScreen().ToString());
+
+  // Leave fullscreen mode.
+  window->GetWindowState()->OnWMEvent(&event);
+
+  // Check that shell surface is maximized.
+  EXPECT_EQ(CurrentContext()->bounds().width(),
+            shell_surface->GetWidget()->GetWindowBoundsInScreen().width());
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index f485106..1e2026c2 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -192,7 +192,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // SurfaceFactoryOwner, private:
 
-SurfaceFactoryOwner::~SurfaceFactoryOwner() {}
+SurfaceFactoryOwner::~SurfaceFactoryOwner() {
+  if (surface_factory_->manager()) {
+    surface_factory_->manager()->InvalidateSurfaceClientId(
+        id_allocator_->client_id());
+  }
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 // Surface, public:
@@ -210,8 +215,10 @@
   window_->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter));
   window_->set_owned_by_parent(false);
   factory_owner_->surface_ = this;
-  factory_owner_->id_allocator_ =
-      aura::Env::GetInstance()->context_factory()->CreateSurfaceIdAllocator();
+  factory_owner_->id_allocator_.reset(new cc::SurfaceIdAllocator(
+      aura::Env::GetInstance()->context_factory()->AllocateSurfaceClientId()));
+  surface_manager_->RegisterSurfaceClientId(
+      factory_owner_->id_allocator_->client_id());
   factory_owner_->surface_factory_.reset(
       new cc::SurfaceFactory(surface_manager_, factory_owner_.get()));
   aura::Env::GetInstance()->context_factory()->AddObserver(this);
diff --git a/components/net_log/chrome_net_log.cc b/components/net_log/chrome_net_log.cc
index 8e0a1f2..5ec2e55 100644
--- a/components/net_log/chrome_net_log.cc
+++ b/components/net_log/chrome_net_log.cc
@@ -10,13 +10,13 @@
 #include "base/command_line.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/sys_info.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h"
 #include "components/net_log/net_log_file_writer.h"
-#include "components/net_log/net_log_file_writer.h"
 #include "components/version_info/version_info.h"
 #include "net/log/net_log_util.h"
 #include "net/log/trace_net_log_observer.h"
@@ -74,7 +74,7 @@
 }
 
 // static
-base::Value* ChromeNetLog::GetConstants(
+std::unique_ptr<base::Value> ChromeNetLog::GetConstants(
     const base::CommandLine::StringType& command_line_string,
     const std::string& channel_string) {
   std::unique_ptr<base::DictionaryValue> constants_dict =
@@ -83,30 +83,28 @@
 
   // Add a dictionary with the version of the client and its command line
   // arguments.
-  {
-    base::DictionaryValue* dict = new base::DictionaryValue();
+  auto dict = base::MakeUnique<base::DictionaryValue>();
 
-    // We have everything we need to send the right values.
-    dict->SetString("name", version_info::GetProductName());
-    dict->SetString("version", version_info::GetVersionNumber());
-    dict->SetString("cl", version_info::GetLastChange());
-    dict->SetString("version_mod", channel_string);
-    dict->SetString("official", version_info::IsOfficialBuild() ? "official"
-                                                                : "unofficial");
-    std::string os_type = base::StringPrintf(
-        "%s: %s (%s)", base::SysInfo::OperatingSystemName().c_str(),
-        base::SysInfo::OperatingSystemVersion().c_str(),
-        base::SysInfo::OperatingSystemArchitecture().c_str());
-    dict->SetString("os_type", os_type);
-    dict->SetString("command_line", command_line_string);
+  // We have everything we need to send the right values.
+  dict->SetString("name", version_info::GetProductName());
+  dict->SetString("version", version_info::GetVersionNumber());
+  dict->SetString("cl", version_info::GetLastChange());
+  dict->SetString("version_mod", channel_string);
+  dict->SetString("official",
+                  version_info::IsOfficialBuild() ? "official" : "unofficial");
+  std::string os_type = base::StringPrintf(
+      "%s: %s (%s)", base::SysInfo::OperatingSystemName().c_str(),
+      base::SysInfo::OperatingSystemVersion().c_str(),
+      base::SysInfo::OperatingSystemArchitecture().c_str());
+  dict->SetString("os_type", os_type);
+  dict->SetString("command_line", command_line_string);
 
-    constants_dict->Set("clientInfo", dict);
+  constants_dict->Set("clientInfo", std::move(dict));
 
-    data_reduction_proxy::DataReductionProxyEventStore::AddConstants(
-        constants_dict.get());
-  }
+  data_reduction_proxy::DataReductionProxyEventStore::AddConstants(
+      constants_dict.get());
 
-  return constants_dict.release();
+  return std::move(constants_dict);
 }
 
 }  // namespace net_log
diff --git a/components/net_log/chrome_net_log.h b/components/net_log/chrome_net_log.h
index 96749237..bca0d288 100644
--- a/components/net_log/chrome_net_log.h
+++ b/components/net_log/chrome_net_log.h
@@ -43,8 +43,8 @@
   NetLogFileWriter* net_log_file_writer() { return net_log_file_writer_.get(); }
 
   // Returns a Value containing constants needed to load a log file.
-  // Safe to call on any thread.  Caller takes ownership of the returned Value.
-  static base::Value* GetConstants(
+  // Safe to call on any thread.
+  static std::unique_ptr<base::Value> GetConstants(
       const base::CommandLine::StringType& command_line_string,
       const std::string& channel_string);
 
diff --git a/components/ntp_snippets.gypi b/components/ntp_snippets.gypi
index 1828845..bf309794 100644
--- a/components/ntp_snippets.gypi
+++ b/components/ntp_snippets.gypi
@@ -57,6 +57,8 @@
         'ntp_snippets/pref_names.cc',
         'ntp_snippets/pref_names.h',
         'ntp_snippets/proto/ntp_snippets.proto',
+        'ntp_snippets/request_throttler.cc',
+        'ntp_snippets/request_throttler.h',
         'ntp_snippets/switches.cc',
         'ntp_snippets/switches.h',
       ],
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index 018f2d8..7a0d99c 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -38,6 +38,8 @@
     "offline_pages/offline_page_suggestions_provider.h",
     "pref_names.cc",
     "pref_names.h",
+    "request_throttler.cc",
+    "request_throttler.h",
     "switches.cc",
     "switches.h",
   ]
@@ -87,6 +89,7 @@
     "ntp_snippets_status_service_unittest.cc",
     "ntp_snippets_test_utils.cc",
     "ntp_snippets_test_utils.h",
+    "request_throttler_unittest.cc",
   ]
 
   deps = [
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc
index 936b151c..67e1dc6 100644
--- a/components/ntp_snippets/pref_names.cc
+++ b/components/ntp_snippets/pref_names.cc
@@ -11,5 +11,10 @@
 
 const char kSnippetHosts[] = "ntp_snippets.hosts";
 
+const char kSnippetFetcherQuotaDay[] =
+    "ntp.request_throttler.suggestion_fetcher.day";
+const char kSnippetFetcherQuotaCount[] =
+    "ntp.request_throttler.suggestion_fetcher.count";
+
 }  // namespace prefs
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h
index 5c432d6..4fdea4e 100644
--- a/components/ntp_snippets/pref_names.h
+++ b/components/ntp_snippets/pref_names.h
@@ -12,7 +12,13 @@
 
 extern const char kSnippetHosts[];
 
+// The pref name for today's count of NTPSnippetsFetcher requests, so far.
+extern const char kSnippetFetcherQuotaCount[];
+// The pref name for the current day for the counter of NTPSnippetsFetcher
+// requests.
+extern const char kSnippetFetcherQuotaDay[];
+
 }  // namespace prefs
 }  // namespace ntp_snippets
 
-#endif
+#endif  // COMPONENTS_NTP_SNIPPETS_PREF_NAMES_H_
diff --git a/components/ntp_snippets/request_throttler.cc b/components/ntp_snippets/request_throttler.cc
new file mode 100644
index 0000000..3055375
--- /dev/null
+++ b/components/ntp_snippets/request_throttler.cc
@@ -0,0 +1,149 @@
+// Copyright 2016 The Chromium Authors. 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/ntp_snippets/request_throttler.h"
+
+#include <vector>
+
+#include "base/metrics/histogram.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "components/ntp_snippets/ntp_snippets_constants.h"
+#include "components/ntp_snippets/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/variations/variations_associated_data.h"
+
+namespace ntp_snippets {
+
+// Used internally for working with a RequestType.
+struct RequestTypeInfo {
+  const char* name;
+  const char* count_pref;
+  const char* day_pref;
+};
+
+namespace {
+
+// Enumeration listing all possible outcomes for fetch attempts. Used for UMA
+// histogram, so do not change existing values. Insert new values at the end,
+// and update the histogram definition.
+enum class RequestStatus {
+  FORCED,
+  QUOTA_GRANTED,
+  QUOTA_EXCEEDED,
+  REQUEST_STATUS_COUNT
+};
+
+// When adding a new type here, extend also the "RequestCounterTypes"
+// <histogram_suffixes> in histograms.xml with the |name| string.
+const RequestTypeInfo kRequestTypeInfo[] = {
+    // RequestCounter::RequestType::CONTENT_SUGGESTION_FETCHER,
+    {"SuggestionFetcher", prefs::kSnippetFetcherQuotaCount,
+     prefs::kSnippetFetcherQuotaDay}};
+
+}  // namespace
+
+RequestThrottler::RequestThrottler(PrefService* pref_service,
+                               RequestType type,
+                               int default_quota)
+    : pref_service_(pref_service),
+      type_info_(kRequestTypeInfo[static_cast<int>(type)]) {
+  DCHECK(pref_service);
+
+  std::string quota = variations::GetVariationParamValue(
+      ntp_snippets::kStudyName,
+      base::StringPrintf("quota_%s", GetRequestTypeAsString()));
+  if (!base::StringToInt(quota, &quota_)) {
+    LOG_IF(WARNING, !quota.empty())
+        << "Invalid variation parameter for quota for "
+        << GetRequestTypeAsString();
+    quota_ = default_quota;
+  }
+
+  // Since the histogram names are dynamic, we cannot use the standard macros
+  // and we need to lookup the histograms, instead.
+  int status_count = static_cast<int>(RequestStatus::REQUEST_STATUS_COUNT);
+  // Corresponds to UMA_HISTOGRAM_ENUMERATION(name, sample, |status_count|).
+  histogram_request_status_ = base::LinearHistogram::FactoryGet(
+      base::StringPrintf("NewTabPage.RequestThrottler.RequestStatus_%s",
+                         GetRequestTypeAsString()),
+      1, status_count, status_count + 1,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  // Corresponds to UMA_HISTOGRAM_COUNTS_100(name, sample).
+  histogram_per_day_ = base::Histogram::FactoryGet(
+      base::StringPrintf("NewTabPage.RequestThrottler.PerDay_%s",
+                         GetRequestTypeAsString()),
+      1, 100, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
+}
+
+// static
+void RequestThrottler::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  for (const RequestTypeInfo& info : kRequestTypeInfo) {
+    registry->RegisterIntegerPref(info.count_pref, 0);
+    registry->RegisterIntegerPref(info.day_pref, 0);
+  }
+}
+
+bool RequestThrottler::DemandQuotaForRequest(bool forced_request) {
+  ResetCounterIfDayChanged();
+
+  if (forced_request) {
+    histogram_request_status_->Add(static_cast<int>(RequestStatus::FORCED));
+    return true;
+  }
+
+  int new_count = GetCount() + 1;
+  SetCount(new_count);
+  bool available = (new_count <= quota_);
+
+  histogram_request_status_->Add(
+      static_cast<int>(available ? RequestStatus::QUOTA_GRANTED
+                                 : RequestStatus::QUOTA_EXCEEDED));
+  return available;
+}
+
+void RequestThrottler::ResetCounterIfDayChanged() {
+  // The count of days since a fixed reference (the Unix epoch).
+  int now_day = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
+
+  if (!HasDay()) {
+    // The counter is used for the first time in this profile.
+    SetDay(now_day);
+  } else if (now_day != GetDay()) {
+    // Day has changed - report the number of requests from the previous day.
+    histogram_per_day_->Add(GetCount());
+    // Reset the counter.
+    SetCount(0);
+    SetDay(now_day);
+  }
+}
+
+const char* RequestThrottler::GetRequestTypeAsString() const {
+  return type_info_.name;
+}
+
+int RequestThrottler::GetCount() const {
+  return pref_service_->GetInteger(type_info_.count_pref);
+}
+
+void RequestThrottler::SetCount(int count) {
+  pref_service_->SetInteger(type_info_.count_pref, count);
+}
+
+int RequestThrottler::GetDay() const {
+  return pref_service_->GetInteger(type_info_.day_pref);
+}
+
+void RequestThrottler::SetDay(int day) {
+  pref_service_->SetInteger(type_info_.day_pref, day);
+}
+
+bool RequestThrottler::HasDay() const {
+  return pref_service_->HasPrefPath(type_info_.day_pref);
+}
+
+}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/request_throttler.h b/components/ntp_snippets/request_throttler.h
new file mode 100644
index 0000000..f908825
--- /dev/null
+++ b/components/ntp_snippets/request_throttler.h
@@ -0,0 +1,88 @@
+// Copyright 2016 The Chromium Authors. 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_NTP_SNIPPETS_REQUEST_THROTTLER_H_
+#define COMPONENTS_NTP_SNIPPETS_REQUEST_THROTTLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace base {
+class HistogramBase;
+}  // namespace base
+
+namespace ntp_snippets {
+
+struct RequestTypeInfo;
+
+// Counts requests to external services, compares them to a daily quota, reports
+// them to UMA. In the application code, create one local instance for each type
+// of requests, identified by the RequestType. The request counter is based on:
+//  - daily quota from a variation param "quota_|type|" in the NTPSnippets trial
+//  - pref "ntp.request_throttler.|type|.count" to store the current counter,
+//  - pref "ntp.request_throttler.|type|.day" to store current day to which the
+//    current counter value applies.
+// Furthermore the counter reports to histograms:
+//  - "NewTabPage.RequestThrottler.RequestStatus_|type|" - status of each
+//  request;
+//  - "NewTabPage.RequestThrottler.PerDay_|type|" - the daily count of requests.
+//
+// Implementation notes: When extending this class for a new RequestType, please
+//  1) define in request_counter.cc in kRequestTypeInfo
+//     a) the string value for your |type| and
+//     b) constants for day/count prefs;
+//  2) define a new RequestThrottlerTypes histogram suffix in histogram.xml
+//     (with the same string value as in 1a)).
+class RequestThrottler {
+ public:
+  // Enumeration listing all current applications of the request counter.
+  enum class RequestType {
+    CONTENT_SUGGESTION_FETCHER
+  };
+
+  RequestThrottler(PrefService* pref_service,
+                 RequestType type,
+                 int default_quota);
+
+  // Registers profile prefs for all RequestTypes. Called from browser_prefs.cc.
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+  // Returns whether quota is available for another request and reports this
+  // information to UMA. Forced requests always return true -- should be only
+  // used for requests initiated by the user (if it is safe to assume that all
+  // users cannot generate an amount of requests we cannot handle).
+  bool DemandQuotaForRequest(bool force_request);
+
+ private:
+  // Also emits the PerDay histogram if the day changed.
+  void ResetCounterIfDayChanged();
+
+  const char* GetRequestTypeAsString() const;
+
+  int GetCount() const;
+  void SetCount(int count);
+  int GetDay() const;
+  void SetDay(int day);
+  bool HasDay() const;
+
+  PrefService* pref_service_;
+  const RequestTypeInfo& type_info_;
+
+  // It comes from a variation parameter or |default_quota| as a fallback.
+  int quota_;
+
+  // The histograms for reporting the requests of the given |type_|.
+  base::HistogramBase* histogram_request_status_;
+  base::HistogramBase* histogram_per_day_;
+
+  DISALLOW_COPY_AND_ASSIGN(RequestThrottler);
+};
+
+}  // namespace ntp_snippets
+
+#endif  // COMPONENTS_NTP_SNIPPETS_REQUEST_THROTTLER_H_
diff --git a/components/ntp_snippets/request_throttler_unittest.cc b/components/ntp_snippets/request_throttler_unittest.cc
new file mode 100644
index 0000000..e75295e
--- /dev/null
+++ b/components/ntp_snippets/request_throttler_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2016 The Chromium Authors. 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/ntp_snippets/request_throttler.h"
+
+#include <memory>
+
+#include "base/strings/stringprintf.h"
+#include "components/ntp_snippets/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const int kCounterQuota = 2;
+}  // namespace
+
+namespace ntp_snippets {
+
+class RequestThrottlerTest : public testing::Test {
+ public:
+  RequestThrottlerTest() {
+    RequestThrottler::RegisterProfilePrefs(test_prefs_.registry());
+    // Use any arbitrary RequestType for this unittest.
+    throttler_.reset(new RequestThrottler(
+        &test_prefs_, RequestThrottler::RequestType::CONTENT_SUGGESTION_FETCHER,
+        kCounterQuota));
+  }
+
+ protected:
+  TestingPrefServiceSimple test_prefs_;
+  std::unique_ptr<RequestThrottler> throttler_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RequestThrottlerTest);
+};
+
+TEST_F(RequestThrottlerTest, QuotaExceeded) {
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+  EXPECT_FALSE(throttler_->DemandQuotaForRequest(false));
+}
+
+TEST_F(RequestThrottlerTest, ForcedDoesNotCountInQuota) {
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(true));
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+}
+
+TEST_F(RequestThrottlerTest, ForcedWorksRegardlessOfQuota) {
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(true));
+}
+
+TEST_F(RequestThrottlerTest, QuotaIsPerDay) {
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+
+  // Now fake the day pref so that the counter believes the count comes from
+  // yesterday.
+  int now_day = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
+  test_prefs_.SetInteger(ntp_snippets::prefs::kSnippetFetcherQuotaDay,
+                         now_day - 1);
+
+  // The quota should get reset as the day has changed.
+  EXPECT_TRUE(throttler_->DemandQuotaForRequest(false));
+}
+
+}  // namespace ntp_snippets
diff --git a/components/offline_pages/background/device_conditions.h b/components/offline_pages/background/device_conditions.h
index e26c7d1..b96306a 100644
--- a/components/offline_pages/background/device_conditions.h
+++ b/components/offline_pages/background/device_conditions.h
@@ -20,6 +20,10 @@
         battery_percentage_(battery_percentage),
         net_connection_type_(net_connection_type) {}
 
+  DeviceConditions()
+      : power_connected_(true), battery_percentage_(75),
+        net_connection_type_(net::NetworkChangeNotifier::CONNECTION_WIFI) {}
+
   // Returns whether power is connected.
   bool IsPowerConnected() const { return power_connected_; }
 
@@ -35,6 +39,8 @@
   const bool power_connected_;
   const int battery_percentage_;
   const net::NetworkChangeNotifier::ConnectionType net_connection_type_;
+
+  // NOTE: We intentionally allow the default copy constructor and assignment.
 };
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/offliner_policy.h b/components/offline_pages/background/offliner_policy.h
index 04e7f844..ee2cc0d 100644
--- a/components/offline_pages/background/offliner_policy.h
+++ b/components/offline_pages/background/offliner_policy.h
@@ -5,6 +5,13 @@
 #ifndef COMPONENTS_OFFLINE_PAGES_BACKGROUND_OFFLINER_POLICY_H_
 #define COMPONENTS_OFFLINE_PAGES_BACKGROUND_OFFLINER_POLICY_H_
 
+namespace {
+const int kMaxRetries = 2;
+const int kBackgroundTimeBudgetSeconds = 170;
+const int kSinglePageTimeBudgetSeconds = 120;
+const int kMinimumBatteryPercentageForNonUserRequestOfflining = 50;
+}  // namespace
+
 namespace offline_pages {
 
 // Policy for the Background Offlining system.  Some policy will belong to the
@@ -13,8 +20,40 @@
  public:
   OfflinerPolicy(){};
 
-  // TODO(petewil): Implement and add a .cc file.
-  // Eventually this should get data from a finch experiment.
+  // TODO(petewil): Numbers here are chosen arbitrarily, do the proper studies
+  // to get good policy numbers.
+
+  // TODO(petewil): Eventually this should get data from a finch experiment.
+
+  // Returns true if we should prefer retrying lesser tried requests.
+  bool ShouldPreferUntriedRequests() { return false; }
+
+  // Returns true if we should prefer older requests of equal number of tries.
+  bool ShouldPreferEarlierRequests() { return true; }
+
+  // Returns true if retry count is considered more important than recency in
+  // picking which request to try next.
+  bool RetryCountIsMoreImportantThanRecency() { return true; }
+
+  // The max number of times we will retry a request.
+  int GetMaxRetries() { return kMaxRetries; }
+
+  // How many seconds to keep trying new pages for, before we give up,  and
+  // return to the scheduler.
+  int GetBackgroundProcessingTimeBudgetSeconds() {
+    return kBackgroundTimeBudgetSeconds;
+  }
+
+  // How long do we allow a page to load before giving up on it
+  int GetSinglePageTimeBudgetInSeconds() {
+    return kSinglePageTimeBudgetSeconds;
+  }
+
+  // How much battery must we have before fetching a page not explicitly
+  // requested by the user?
+  int GetMinimumBatteryPercentageForNonUserRequestOfflining() {
+    return kMinimumBatteryPercentageForNonUserRequestOfflining;
+  }
 };
 }
 
diff --git a/components/offline_pages/background/request_coordinator.cc b/components/offline_pages/background/request_coordinator.cc
index e6ac73f..a78d58c 100644
--- a/components/offline_pages/background/request_coordinator.cc
+++ b/components/offline_pages/background/request_coordinator.cc
@@ -60,22 +60,23 @@
       last_offlining_status_(Offliner::RequestStatus::UNKNOWN),
       weak_ptr_factory_(this) {
   DCHECK(policy_ != nullptr);
-  picker_.reset(new RequestPicker(queue_.get()));
+  picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
 }
 
 RequestCoordinator::~RequestCoordinator() {}
 
 bool RequestCoordinator::SavePageLater(
-    const GURL& url, const ClientId& client_id) {
+    const GURL& url, const ClientId& client_id, bool was_user_requested) {
   DVLOG(2) << "URL is " << url << " " << __FUNCTION__;
 
-  // TODO(petewil): We need a robust scheme for allocating new IDs.
+  // TODO(petewil): We need a robust scheme for allocating new IDs.  We may need
+  // GUIDS for the downloads home design.
   static int64_t id = 0;
 
   // Build a SavePageRequest.
   // TODO(petewil): Use something like base::Clock to help in testing.
   offline_pages::SavePageRequest request(
-      id++, url, client_id, base::Time::Now());
+      id++, url, client_id, base::Time::Now(), was_user_requested);
 
   // Put the request on the request queue.
   queue_->AddRequest(request,
@@ -95,7 +96,15 @@
 
 // Called in response to updating a request in the request queue.
 void RequestCoordinator::UpdateRequestCallback(
-    RequestQueue::UpdateRequestResult result) {}
+    RequestQueue::UpdateRequestResult result) {
+  // If the request succeeded, nothing to do.  If it failed, we can't really do
+  // much, so just log it.
+  if (result != RequestQueue::UpdateRequestResult::SUCCESS) {
+    // TODO(petewil): Consider adding UMA or showing on offline-internals page.
+    DLOG(WARNING) << "Failed to update a request retry count. "
+                  << static_cast<int>(result);
+  }
+}
 
 void RequestCoordinator::StopProcessing() {
   is_canceled_ = true;
@@ -116,6 +125,7 @@
 bool RequestCoordinator::StartProcessing(
     const DeviceConditions& device_conditions,
     const base::Callback<void(bool)>& callback) {
+  current_conditions_.reset(new DeviceConditions(device_conditions));
   if (is_busy_) return false;
 
   is_canceled_ = false;
@@ -135,7 +145,8 @@
       base::Bind(&RequestCoordinator::RequestPicked,
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&RequestCoordinator::RequestQueueEmpty,
-                 weak_ptr_factory_.GetWeakPtr()));
+                 weak_ptr_factory_.GetWeakPtr()),
+      current_conditions_.get());
 }
 
 // Called by the request picker when a request has been picked.
@@ -194,18 +205,33 @@
 
   is_busy_ = false;
 
-  // If the request succeeded, remove it from the Queue and maybe schedule
-  // another one.
-  if (status == Offliner::RequestStatus::SAVED) {
+  int64_t new_attempt_count = request.attempt_count() + 1;
+
+  // Remove the request from the queue if it either succeeded or exceeded the
+  // max number of retries.
+  if (status == Offliner::RequestStatus::SAVED
+       || new_attempt_count > policy_->GetMaxRetries()) {
     queue_->RemoveRequest(request.request_id(),
                           base::Bind(&RequestCoordinator::UpdateRequestCallback,
                                      weak_ptr_factory_.GetWeakPtr()));
-
-    // TODO(petewil): Check time budget. Return to the scheduler if we are out.
-
-    // Start another request if we have time.
-    TryNextRequest();
+  } else {
+    // If we failed, but are not over the limit, update the request in the
+    // queue.
+    SavePageRequest updated_request(request);
+    updated_request.set_attempt_count(new_attempt_count);
+    updated_request.set_last_attempt_time(base::Time::Now());
+    RequestQueue::UpdateRequestCallback update_callback =
+        base::Bind(&RequestCoordinator::UpdateRequestCallback,
+                   weak_ptr_factory_.GetWeakPtr());
+    queue_->UpdateRequest(
+        updated_request,
+        base::Bind(&RequestCoordinator::UpdateRequestCallback,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
+
+  // TODO(petewil): Check time budget. Return to the scheduler if we are out.
+  // Start another request if we have time.
+  TryNextRequest();
 }
 
 const Scheduler::TriggerConditions&
diff --git a/components/offline_pages/background/request_coordinator.h b/components/offline_pages/background/request_coordinator.h
index e0ff976c..c4858505 100644
--- a/components/offline_pages/background/request_coordinator.h
+++ b/components/offline_pages/background/request_coordinator.h
@@ -47,7 +47,8 @@
 
   // Queues |request| to later load and save when system conditions allow.
   // Returns true if the page could be queued successfully.
-  bool SavePageLater(const GURL& url, const ClientId& client_id);
+  bool SavePageLater(
+      const GURL& url, const ClientId& client_id, bool user_reqeusted);
 
   // Starts processing of one or more queued save page later requests.
   // Returns whether processing was started and that caller should expect
@@ -123,6 +124,10 @@
     offliner_timeout_ = timeout;
   }
 
+  void SetDeviceConditionsForTest(DeviceConditions& current_conditions) {
+    current_conditions_.reset(new DeviceConditions(current_conditions));
+  }
+
   friend class RequestCoordinatorTest;
 
   // The offliner can only handle one request at a time - if the offliner is
@@ -135,6 +140,8 @@
   base::TimeDelta offliner_timeout_;
   // Unowned pointer to the current offliner, if any.
   Offliner* offliner_;
+  // Last known conditions for network, battery
+  std::unique_ptr<DeviceConditions> current_conditions_;
   // RequestCoordinator takes over ownership of the policy
   std::unique_ptr<OfflinerPolicy> policy_;
   // OfflinerFactory.  Used to create offline pages. Owned.
diff --git a/components/offline_pages/background/request_coordinator_unittest.cc b/components/offline_pages/background/request_coordinator_unittest.cc
index 34f29f99..09f5a8c 100644
--- a/components/offline_pages/background/request_coordinator_unittest.cc
+++ b/components/offline_pages/background/request_coordinator_unittest.cc
@@ -35,6 +35,7 @@
 const long kTestTimeoutSeconds = 1;
 const int kBatteryPercentageHigh = 75;
 const bool kPowerRequired = true;
+const bool kUserRequested = true;
 }  // namespace
 
 class SchedulerStub : public Scheduler {
@@ -69,7 +70,8 @@
 class OfflinerStub : public Offliner {
  public:
   OfflinerStub()
-      : request_(kRequestId, kUrl, kClientId, base::Time::Now()),
+      : request_(kRequestId, kUrl, kClientId, base::Time::Now(),
+                 kUserRequested),
         enable_callback_(false),
         cancel_called_(false) {}
 
@@ -170,6 +172,10 @@
     coordinator_->SetOfflinerTimeoutForTest(timeout);
   }
 
+  void SetDeviceConditionsForTest(DeviceConditions device_conditions) {
+    coordinator_->SetDeviceConditionsForTest(device_conditions);
+  }
+
   void WaitForCallback() {
     waiter_.Wait();
   }
@@ -252,7 +258,7 @@
 
 TEST_F(RequestCoordinatorTest, StartProcessingWithRequestInProgress) {
   // Put the request on the queue.
-  EXPECT_TRUE(coordinator()->SavePageLater(kUrl, kClientId));
+  EXPECT_TRUE(coordinator()->SavePageLater(kUrl, kClientId, kUserRequested));
 
   // Set up for the call to StartProcessing by building arguments.
   DeviceConditions device_conditions(false, 75,
@@ -275,7 +281,7 @@
 }
 
 TEST_F(RequestCoordinatorTest, SavePageLater) {
-  EXPECT_TRUE(coordinator()->SavePageLater(kUrl, kClientId));
+  EXPECT_TRUE(coordinator()->SavePageLater(kUrl, kClientId, kUserRequested));
 
   // Expect that a request got placed on the queue.
   coordinator()->queue()->GetRequests(
@@ -303,7 +309,7 @@
 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) {
   // Add a request to the queue, wait for callbacks to finish.
   offline_pages::SavePageRequest request(
-      kRequestId, kUrl, kClientId, base::Time::Now());
+      kRequestId, kUrl, kClientId, base::Time::Now(), kUserRequested);
   coordinator()->queue()->AddRequest(
       request,
       base::Bind(&RequestCoordinatorTest::AddRequestDone,
@@ -317,6 +323,11 @@
           base::Unretained(this));
   coordinator()->SetProcessingCallbackForTest(callback);
 
+  // Set up device conditions for the test.
+  DeviceConditions device_conditions(
+      false, 75, net::NetworkChangeNotifier::CONNECTION_3G);
+  SetDeviceConditionsForTest(device_conditions);
+
   // Call the OfflinerDoneCallback to simulate the page being completed, wait
   // for callbacks.
   EnableOfflinerCallback(true);
@@ -338,7 +349,7 @@
 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) {
   // Add a request to the queue, wait for callbacks to finish.
   offline_pages::SavePageRequest request(
-      kRequestId, kUrl, kClientId, base::Time::Now());
+      kRequestId, kUrl, kClientId, base::Time::Now(), kUserRequested);
   coordinator()->queue()->AddRequest(
       request,
       base::Bind(&RequestCoordinatorTest::AddRequestDone,
@@ -352,11 +363,22 @@
           base::Unretained(this));
   coordinator()->SetProcessingCallbackForTest(callback);
 
+  // Set up device conditions for the test.
+  DeviceConditions device_conditions(
+      false, 75, net::NetworkChangeNotifier::CONNECTION_3G);
+  SetDeviceConditionsForTest(device_conditions);
+
   // Call the OfflinerDoneCallback to simulate the request failed, wait
   // for callbacks.
   EnableOfflinerCallback(true);
   SendOfflinerDoneCallback(request,
                            Offliner::RequestStatus::PRERENDERING_FAILED);
+  // There will be one request left in the queue after the prerender fails, stop
+  // processing now so that it will remain in the queue for us to check.  This
+  // won't affect the offliner done callback other than preventing
+  // TryNextRequest from doing anything.
+  coordinator()->StopProcessing();
+
   PumpLoop();
 
   // Verify the request is not removed from the queue, and wait for callbacks.
@@ -367,7 +389,9 @@
 
   // Still one request in the queue.
   EXPECT_EQ(1UL, last_requests().size());
-  // TODO(dougarnett): Verify retry count gets incremented.
+  // Verify retry count was incremented.
+  const SavePageRequest& found_request = last_requests().front();
+  EXPECT_EQ(1L, found_request.attempt_count());
 }
 
 // This tests a StopProcessing call before we have actually started the
@@ -375,7 +399,7 @@
 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingImmediately) {
   // Add a request to the queue, wait for callbacks to finish.
   offline_pages::SavePageRequest request(
-      kRequestId, kUrl, kClientId, base::Time::Now());
+      kRequestId, kUrl, kClientId, base::Time::Now(), kUserRequested);
   coordinator()->queue()->AddRequest(
       request,
       base::Bind(&RequestCoordinatorTest::AddRequestDone,
@@ -409,7 +433,7 @@
 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingLater) {
   // Add a request to the queue, wait for callbacks to finish.
   offline_pages::SavePageRequest request(
-      kRequestId, kUrl, kClientId, base::Time::Now());
+      kRequestId, kUrl, kClientId, base::Time::Now(), kUserRequested);
   coordinator()->queue()->AddRequest(
       request,
       base::Bind(&RequestCoordinatorTest::AddRequestDone,
@@ -448,7 +472,7 @@
 TEST_F(RequestCoordinatorTest, PrerendererTimeout) {
   // Build a request to use with the pre-renderer, and put it on the queue.
   offline_pages::SavePageRequest request(
-      kRequestId, kUrl, kClientId, base::Time::Now());
+      kRequestId, kUrl, kClientId, base::Time::Now(), kUserRequested);
   coordinator()->queue()->AddRequest(
       request,
       base::Bind(&RequestCoordinatorTest::AddRequestDone,
diff --git a/components/offline_pages/background/request_picker.cc b/components/offline_pages/background/request_picker.cc
index 665b39fe..23fee192c 100644
--- a/components/offline_pages/background/request_picker.cc
+++ b/components/offline_pages/background/request_picker.cc
@@ -8,25 +8,44 @@
 #include "base/logging.h"
 #include "components/offline_pages/background/save_page_request.h"
 
+namespace {
+template <typename T>
+int signum(T t) {
+  return (T(0) < t) - (t < T(0));
+}
+
+#define CALL_MEMBER_FUNCTION(object,ptrToMember)  ((object)->*(ptrToMember))
+}  // namespace
+
 namespace offline_pages {
 
 RequestPicker::RequestPicker(
-    RequestQueue* requestQueue)
+    RequestQueue* requestQueue, OfflinerPolicy* policy)
     : queue_(requestQueue),
+      policy_(policy),
+      fewer_retries_better_(false),
+      earlier_requests_better_(false),
       weak_ptr_factory_(this) {}
 
 RequestPicker::~RequestPicker() {}
 
+// Entry point for the async operation to choose the next request.
 void RequestPicker::ChooseNextRequest(
     RequestCoordinator::RequestPickedCallback picked_callback,
-    RequestCoordinator::RequestQueueEmptyCallback empty_callback) {
+    RequestCoordinator::RequestQueueEmptyCallback empty_callback,
+    DeviceConditions* device_conditions) {
   picked_callback_ = picked_callback;
   empty_callback_ = empty_callback;
+  fewer_retries_better_ = policy_->ShouldPreferUntriedRequests();
+  earlier_requests_better_ = policy_->ShouldPreferEarlierRequests();
+  current_conditions_.reset(new DeviceConditions(*device_conditions));
   // Get all requests from queue (there is no filtering mechanism).
   queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback,
                                  weak_ptr_factory_.GetWeakPtr()));
 }
 
+// When we get contents from the queue, use them to pick the next
+// request to operate on (if any).
 void RequestPicker::GetRequestResultCallback(
     RequestQueue::GetRequestsResult,
     const std::vector<SavePageRequest>& requests) {
@@ -37,11 +56,151 @@
   }
 
   // Pick the most deserving request for our conditions.
-  const SavePageRequest& picked_request = requests[0];
+  const SavePageRequest* picked_request = nullptr;
 
-  // When we have a best request to try next, get the request coodinator to
-  // start it.
-  picked_callback_.Run(picked_request);
+  RequestCompareFunction comparator = nullptr;
+
+  // Choose which comparison function to use based on policy.
+  if (policy_->RetryCountIsMoreImportantThanRecency())
+    comparator = &RequestPicker::RetryCountFirstCompareFunction;
+  else
+    comparator = &RequestPicker::RecencyFirstCompareFunction;
+
+  // Iterate once through the requests, keeping track of best candidate.
+  for (unsigned i = 0; i < requests.size(); ++i) {
+    if (!RequestConditionsSatisfied(requests[i]))
+      continue;
+    if (IsNewRequestBetter(picked_request, &(requests[i]), comparator))
+      picked_request = &(requests[i]);
+  }
+
+  // If we have a best request to try next, get the request coodinator to
+  // start it.  Otherwise return that we have no candidates.
+  if (picked_request != nullptr) {
+    picked_callback_.Run(*picked_request);
+  } else {
+    empty_callback_.Run();
+  }
+}
+
+// Filter out requests that don't meet the current conditions.  For instance, if
+// this is a predictive request, and we are not on WiFi, it should be ignored
+// this round.
+bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) {
+  // If the user did not request the page directly, make sure we are connected
+  // to power and have WiFi and sufficient battery remaining before we take this
+  // reqeust.
+  // TODO(petewil): We may later want to configure whether to allow 2G for non
+  // user_requested items, add that to policy.
+  if (!request.user_requested()) {
+    if (!current_conditions_->IsPowerConnected())
+      return false;
+
+    if (current_conditions_->GetNetConnectionType() !=
+        net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) {
+      return false;
+    }
+
+    if (current_conditions_->GetBatteryPercentage() <
+        policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) {
+      return false;
+    }
+  }
+
+  // If we have already tried this page the max number of times, it is not
+  // eligible to try again.
+  // TODO(petewil): Instead, we should have code to remove the page from the
+  // queue after the last retry.
+  if (request.attempt_count() >= policy_->GetMaxRetries())
+    return false;
+
+  // If this request is not active yet, return false.
+  // TODO(petewil): If the only reason we return nothing to do is that we have
+  // inactive requests, we still want to try again later after their activation
+  // time elapses, we shouldn't take ourselves completely off the scheduler.
+  if (request.activation_time() > base::Time::Now())
+    return false;
+
+  return true;
+}
+
+// Look at policies to decide which requests to prefer.
+bool RequestPicker::IsNewRequestBetter(const SavePageRequest* oldRequest,
+                                       const SavePageRequest* newRequest,
+                                       RequestCompareFunction comparator) {
+
+  // If there is no old request, the new one is better.
+  if (oldRequest == nullptr)
+    return true;
+
+  // User requested pages get priority.
+  if (newRequest->user_requested() && !oldRequest->user_requested())
+    return true;
+
+  // Otherwise, use the comparison function for the current policy, which
+  // returns true if the older request is better.
+  return !(CALL_MEMBER_FUNCTION(this, comparator)(oldRequest, newRequest));
+}
+
+// Compare the results, checking request count before recency.  Returns true if
+// left hand side is better, false otherwise.
+bool RequestPicker::RetryCountFirstCompareFunction(
+    const SavePageRequest* left, const SavePageRequest* right) {
+  // Check the attempt count.
+  int result = CompareRetryCount(left, right);
+
+  if (result != 0)
+    return (result > 0);
+
+  // If we get here, the attempt counts were the same, so check recency.
+  result = CompareCreationTime(left, right);
+
+  return (result > 0);
+}
+
+// Compare the results, checking recency before request count. Returns true if
+// left hand side is better, false otherwise.
+bool RequestPicker::RecencyFirstCompareFunction(
+    const SavePageRequest* left, const SavePageRequest* right) {
+  // Check the recency.
+  int result = CompareCreationTime(left, right);
+
+  if (result != 0)
+    return (result > 0);
+
+  // If we get here, the recency was the same, so check the attempt count.
+  result = CompareRetryCount(left, right);
+
+  return (result > 0);
+}
+
+// Compare left and right side, returning 1 if the left side is better
+// (preferred by policy), 0 if the same, and -1 if the right side is better.
+int RequestPicker::CompareRetryCount(
+    const SavePageRequest* left, const SavePageRequest* right) {
+  // Check the attempt count.
+  int result = signum(left->attempt_count() - right->attempt_count());
+
+  // Flip the direction of comparison if policy prefers fewer retries.
+  if (fewer_retries_better_)
+    result *= -1;
+
+  return result;
+}
+
+// Compare left and right side, returning 1 if the left side is better
+// (preferred by policy), 0 if the same, and -1 if the right side is better.
+int RequestPicker::CompareCreationTime(
+    const SavePageRequest* left, const SavePageRequest* right) {
+  // Check the recency.
+  base::TimeDelta difference = left->creation_time() - right->creation_time();
+  int result = signum(difference.InMilliseconds());
+
+  // Flip the direction of comparison if policy prefers fewer retries.
+  if (earlier_requests_better_)
+    result *= -1;
+
+  return result;
 }
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/request_picker.h b/components/offline_pages/background/request_picker.h
index dd2b7ff..3062152 100644
--- a/components/offline_pages/background/request_picker.h
+++ b/components/offline_pages/background/request_picker.h
@@ -5,14 +5,22 @@
 #ifndef COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_PICKER_H_
 #define COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_PICKER_H_
 
+#include <memory>
+
 #include "base/memory/weak_ptr.h"
+#include "components/offline_pages/background/device_conditions.h"
+#include "components/offline_pages/background/offliner_policy.h"
 #include "components/offline_pages/background/request_coordinator.h"
 #include "components/offline_pages/background/request_queue.h"
 
 namespace offline_pages {
+
+typedef bool (RequestPicker::*RequestCompareFunction)(
+    const SavePageRequest* left, const SavePageRequest* right);
+
 class RequestPicker {
  public:
-  RequestPicker(RequestQueue* requestQueue);
+  RequestPicker(RequestQueue* requestQueue, OfflinerPolicy* policy);
 
   ~RequestPicker();
 
@@ -20,15 +28,51 @@
   // conditions, and call back to the RequestCoordinator when we have one.
   void ChooseNextRequest(
       RequestCoordinator::RequestPickedCallback picked_callback,
-      RequestCoordinator::RequestQueueEmptyCallback empty_callback);
+      RequestCoordinator::RequestQueueEmptyCallback empty_callback,
+      DeviceConditions* device_conditions);
 
  private:
   // Callback for the GetRequest results to be delivered.
   void GetRequestResultCallback(RequestQueue::GetRequestsResult result,
                                 const std::vector<SavePageRequest>& results);
 
+  // Filter out requests that don't meet the current conditions.  For instance,
+  // if this is a predictive request, and we are not on WiFi, it should be
+  // ignored this round.
+  bool RequestConditionsSatisfied(const SavePageRequest& request);
+
+  // Using policies, decide if the new request is preferable to the best we have
+  // so far.
+  bool IsNewRequestBetter(const SavePageRequest* oldRequest,
+                          const SavePageRequest* newRequest,
+                          RequestCompareFunction comparator);
+
+  // Is the new request preferable from the retry count first standpoint?
+  bool RetryCountFirstCompareFunction(const SavePageRequest* left,
+                                      const SavePageRequest* right);
+
+  // Is the new request better from the recency first standpoint?
+  bool RecencyFirstCompareFunction(const SavePageRequest* left,
+                                   const SavePageRequest* right);
+
+  // Does the new request have better retry count?
+  int CompareRetryCount(const SavePageRequest* left,
+                        const SavePageRequest* right);
+
+  // Does the new request have better creation time?
+  int CompareCreationTime(const SavePageRequest* left,
+                          const SavePageRequest* right);
+
   // unowned pointer to the request queue.
   RequestQueue* queue_;
+  // unowned pointer to the policy object.
+  OfflinerPolicy* policy_;
+  // Current conditions on the device
+  std::unique_ptr<DeviceConditions> current_conditions_;
+  // True if we prefer less-tried requests
+  bool fewer_retries_better_;
+  // True if we prefer requests submitted more recently
+  bool earlier_requests_better_;
   // Callback for when we are done picking a request to do next.
   RequestCoordinator::RequestPickedCallback picked_callback_;
   // Callback for when there are no more reqeusts to pick.
diff --git a/components/offline_pages/background/request_picker_unittest.cc b/components/offline_pages/background/request_picker_unittest.cc
index 1082450..e51f999a 100644
--- a/components/offline_pages/background/request_picker_unittest.cc
+++ b/components/offline_pages/background/request_picker_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "components/offline_pages/background/device_conditions.h"
 #include "components/offline_pages/background/request_queue.h"
 #include "components/offline_pages/background/request_queue_in_memory_store.h"
 #include "components/offline_pages/background/save_page_request.h"
@@ -25,6 +26,7 @@
 const int64_t kRequestId2 = 42;
 const GURL kUrl2("http://nytimes.com");
 const ClientId kClientId2("bookmark", "5678");
+const bool kUserRequested = true;
 }  // namespace
 
 class RequestPickerTest : public testing::Test {
@@ -50,6 +52,7 @@
   std::unique_ptr<RequestQueue> queue_;
   std::unique_ptr<RequestPicker> picker_;
   std::unique_ptr<SavePageRequest> last_picked_;
+  std::unique_ptr<OfflinerPolicy> policy_;
   bool request_queue_empty_called_;
 
  private:
@@ -67,7 +70,8 @@
   std::unique_ptr<RequestQueueInMemoryStore> store(
       new RequestQueueInMemoryStore());
   queue_.reset(new RequestQueue(std::move(store)));
-  picker_.reset(new RequestPicker(queue_.get()));
+  policy_.reset(new OfflinerPolicy());
+  picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
   request_queue_empty_called_ = false;
 }
 
@@ -88,8 +92,11 @@
 
 TEST_F(RequestPickerTest, ChooseNextRequest) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time);
-  SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time);
+  DeviceConditions conditions;
+  SavePageRequest request1(
+      kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested);
+  SavePageRequest request2(
+      kRequestId2, kUrl2, kClientId2, creation_time, kUserRequested);
   // Put some test requests on the Queue.
   queue_->AddRequest(request1, base::Bind(&RequestPickerTest::AddRequestDone,
                                           base::Unretained(this)));
@@ -101,23 +108,24 @@
 
   picker_->ChooseNextRequest(
       base::Bind(&RequestPickerTest::RequestPicked, base::Unretained(this)),
-      base::Bind(&RequestPickerTest::RequestQueueEmpty,
-                 base::Unretained(this)));
+      base::Bind(&RequestPickerTest::RequestQueueEmpty, base::Unretained(this)),
+      &conditions);
 
   // Pump the loop again to give the async queue the opportunity to return
   // results from the Get operation, and for the picker to call the "picked"
   // callback.
   PumpLoop();
 
-  EXPECT_EQ(kRequestId1, last_picked_->request_id());
+  EXPECT_EQ(kRequestId2, last_picked_->request_id());
   EXPECT_FALSE(request_queue_empty_called_);
 }
 
 TEST_F(RequestPickerTest, PickFromEmptyQueue) {
+  DeviceConditions conditions;
   picker_->ChooseNextRequest(
       base::Bind(&RequestPickerTest::RequestPicked, base::Unretained(this)),
-      base::Bind(&RequestPickerTest::RequestQueueEmpty,
-                 base::Unretained(this)));
+      base::Bind(&RequestPickerTest::RequestQueueEmpty, base::Unretained(this)),
+      &conditions);
 
   // Pump the loop again to give the async queue the opportunity to return
   // results from the Get operation, and for the picker to call the "QueueEmpty"
diff --git a/components/offline_pages/background/request_queue.cc b/components/offline_pages/background/request_queue.cc
index 5fbd0bae..f3cae84 100644
--- a/components/offline_pages/background/request_queue.cc
+++ b/components/offline_pages/background/request_queue.cc
@@ -38,6 +38,17 @@
   callback.Run(result, request);
 }
 
+// Completes the update request call.
+void UpdateRequestDone(const RequestQueue::UpdateRequestCallback& callback,
+                       RequestQueueStore::UpdateStatus status) {
+  RequestQueue::UpdateRequestResult result =
+      (status == RequestQueueStore::UpdateStatus::UPDATED)
+          ? RequestQueue::UpdateRequestResult::SUCCESS
+          : RequestQueue::UpdateRequestResult::STORE_FAILURE;
+  callback.Run(result);
+}
+
+
 // Completes the remove request call.
 void RemoveRequestDone(const RequestQueue::UpdateRequestCallback& callback,
                        bool success,
@@ -48,10 +59,11 @@
               : RequestQueue::UpdateRequestResult::STORE_FAILURE;
   callback.Run(result);
 }
+
 }  // namespace
 
 RequestQueue::RequestQueue(std::unique_ptr<RequestQueueStore> store)
-    : store_(std::move(store)) {}
+    : store_(std::move(store)), weak_ptr_factory_(this) {}
 
 RequestQueue::~RequestQueue() {}
 
@@ -67,8 +79,55 @@
                              base::Bind(&AddRequestDone, callback, request));
 }
 
-void RequestQueue::UpdateRequest(const SavePageRequest& request,
-                                 const UpdateRequestCallback& callback) {}
+void RequestQueue::UpdateRequest(const SavePageRequest& update_request,
+                                 const UpdateRequestCallback& update_callback) {
+  // We have to pass the update_callback *through* the get callback.  We do this
+  // by currying the update_callback as a parameter to be used when calling
+  // GetForUpdateDone.  The actual request queue store get operation will not
+  // see this bound parameter, but just pass it along.  GetForUpdateDone then
+  // passes it into the AddOrUpdateRequest method, where it ends up calling back
+  // to the request queue client.
+  // TODO(petewil): This would be more efficient if the store supported a call
+  // to get a single item by ID.  Change this code to use that API when added.
+  // crbug.com/630657.
+  store_->GetRequests(base::Bind(
+      &RequestQueue::GetForUpdateDone, weak_ptr_factory_.GetWeakPtr(),
+      update_callback, update_request));
+}
+
+// We need a different version of the GetCallback that can take the curried
+// update_callback as a parameter, and call back into the request queue store
+// implementation.  This must be a member function because we need access to
+// the store pointer to call AddOrUpdateRequest.
+void RequestQueue::GetForUpdateDone(
+    const UpdateRequestCallback& update_callback,
+    const SavePageRequest& update_request,
+    bool success,
+    const std::vector<SavePageRequest>& found_requests) {
+  // If the result was not found, return now.
+  if (!success) {
+    update_callback.Run(
+        RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST);
+    return;
+  }
+  // If the found result does not contain the request we are looking for, return
+  // now.
+  bool found = false;
+  std::vector<SavePageRequest>::const_iterator iter;
+  for (iter = found_requests.begin(); iter != found_requests.end(); ++iter) {
+    if (iter->request_id() == update_request.request_id())
+      found = true;
+  }
+  if (!found) {
+    update_callback.Run(
+        RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST);
+    return;
+  }
+
+  // Since the request exists, update it.
+  store_->AddOrUpdateRequest(update_request,
+                             base::Bind(&UpdateRequestDone, update_callback));
+}
 
 void RequestQueue::RemoveRequest(int64_t request_id,
                                  const UpdateRequestCallback& callback) {
diff --git a/components/offline_pages/background/request_queue.h b/components/offline_pages/background/request_queue.h
index 4aed02c..869f072 100644
--- a/components/offline_pages/background/request_queue.h
+++ b/components/offline_pages/background/request_queue.h
@@ -12,6 +12,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 
 namespace offline_pages {
 
@@ -75,6 +76,12 @@
   // |callback|.
   void RemoveRequest(int64_t request_id, const UpdateRequestCallback& callback);
 
+  void GetForUpdateDone(
+      const RequestQueue::UpdateRequestCallback& update_callback,
+      const SavePageRequest& update_request,
+      bool success,
+      const std::vector<SavePageRequest>& requests);
+
  private:
   // Callback used by |PurgeRequests|.
   typedef base::Callback<void(UpdateRequestResult,
@@ -88,6 +95,9 @@
 
   std::unique_ptr<RequestQueueStore> store_;
 
+  // Allows us to pass a weak pointer to callbacks.
+  base::WeakPtrFactory<RequestQueue> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(RequestQueue);
 };
 
diff --git a/components/offline_pages/background/request_queue_store_sql.cc b/components/offline_pages/background/request_queue_store_sql.cc
index 79a1fe5..a1be28c 100644
--- a/components/offline_pages/background/request_queue_store_sql.cc
+++ b/components/offline_pages/background/request_queue_store_sql.cc
@@ -22,6 +22,7 @@
 // This is a macro instead of a const so that
 // it can be used inline in other SQL statements below.
 #define REQUEST_QUEUE_TABLE_NAME "request_queue_v1"
+const bool kUserRequested = true;
 
 bool CreateRequestQueueTable(sql::Connection* db) {
   const char kSql[] = "CREATE TABLE IF NOT EXISTS " REQUEST_QUEUE_TABLE_NAME
@@ -93,7 +94,8 @@
   const ClientId client_id(statement.ColumnString(6),
                            statement.ColumnString(7));
 
-  SavePageRequest request(id, url, client_id, creation_time, activation_time);
+  SavePageRequest request(
+      id, url, client_id, creation_time, activation_time, kUserRequested);
   request.set_last_attempt_time(last_attempt_time);
   request.set_attempt_count(last_attempt_count);
   return request;
diff --git a/components/offline_pages/background/request_queue_store_unittest.cc b/components/offline_pages/background/request_queue_store_unittest.cc
index 32c6ab6..7a75be9 100644
--- a/components/offline_pages/background/request_queue_store_unittest.cc
+++ b/components/offline_pages/background/request_queue_store_unittest.cc
@@ -24,6 +24,7 @@
 const int64_t kRequestId = 42;
 const GURL kUrl("http://example.com");
 const ClientId kClientId("bookmark", "1234");
+const bool kUserRequested = true;
 
 enum class LastResult {
   kNone,
@@ -195,7 +196,8 @@
 TYPED_TEST(RequestQueueStoreTest, AddRequest) {
   std::unique_ptr<RequestQueueStore> store(this->BuildStore());
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
 
   store->AddOrUpdateRequest(
       request, base::Bind(&RequestQueueStoreTestBase::AddOrUpdateDone,
@@ -218,7 +220,8 @@
 TYPED_TEST(RequestQueueStoreTest, UpdateRequest) {
   std::unique_ptr<RequestQueueStore> store(this->BuildStore());
   base::Time creation_time = base::Time::Now();
-  SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest original_request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   store->AddOrUpdateRequest(
       original_request, base::Bind(&RequestQueueStoreTestBase::AddOrUpdateDone,
                                    base::Unretained(this)));
@@ -229,7 +232,8 @@
       creation_time + base::TimeDelta::FromMinutes(1);
   base::Time activation_time = creation_time + base::TimeDelta::FromHours(6);
   SavePageRequest updated_request(kRequestId, kUrl, kClientId,
-                                  new_creation_time, activation_time);
+                                  new_creation_time, activation_time,
+                                  kUserRequested);
   store->AddOrUpdateRequest(
       updated_request, base::Bind(&RequestQueueStoreTestBase::AddOrUpdateDone,
                                   base::Unretained(this)));
@@ -251,7 +255,8 @@
 TYPED_TEST(RequestQueueStoreTest, RemoveRequest) {
   std::unique_ptr<RequestQueueStore> store(this->BuildStore());
   base::Time creation_time = base::Time::Now();
-  SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest original_request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   store->AddOrUpdateRequest(
       original_request, base::Bind(&RequestQueueStoreTestBase::AddOrUpdateDone,
                                    base::Unretained(this)));
@@ -290,7 +295,8 @@
 TYPED_TEST(RequestQueueStoreTest, ResetStore) {
   std::unique_ptr<RequestQueueStore> store(this->BuildStore());
   base::Time creation_time = base::Time::Now();
-  SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest original_request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   store->AddOrUpdateRequest(
       original_request, base::Bind(&RequestQueueStoreTestBase::AddOrUpdateDone,
                                    base::Unretained(this)));
@@ -319,7 +325,8 @@
 TEST_F(RequestQueueStoreSQLTest, SaveCloseReopenRead) {
   std::unique_ptr<RequestQueueStore> store(BuildStore());
   base::Time creation_time = base::Time::Now();
-  SavePageRequest original_request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest original_request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   store->AddOrUpdateRequest(
       original_request, base::Bind(&RequestQueueStoreTestBase::AddOrUpdateDone,
                                    base::Unretained(this)));
diff --git a/components/offline_pages/background/request_queue_unittest.cc b/components/offline_pages/background/request_queue_unittest.cc
index 85628d1..875bfb2d 100644
--- a/components/offline_pages/background/request_queue_unittest.cc
+++ b/components/offline_pages/background/request_queue_unittest.cc
@@ -24,10 +24,12 @@
 const int64_t kRequestId = 42;
 const GURL kUrl("http://example.com");
 const ClientId kClientId("bookmark", "1234");
+const int64_t kRetryCount = 2;
 // Data for request 2.
 const int64_t kRequestId2 = 77;
 const GURL kUrl2("http://test.com");
 const ClientId kClientId2("bookmark", "567");
+const bool kUserRequested = true;
 }  // namespace
 
 // TODO(fgorski): Add tests for store failures in add/remove/get.
@@ -49,6 +51,8 @@
   // Callback for removing request.
   void RemoveRequestDone(UpdateRequestResult result);
 
+  void UpdateRequestDone(UpdateRequestResult result);
+
   RequestQueue* queue() { return queue_.get(); }
 
   AddRequestResult last_add_result() const { return last_add_result_; }
@@ -58,6 +62,8 @@
 
   UpdateRequestResult last_remove_result() const { return last_remove_result_; }
 
+  UpdateRequestResult last_update_result() const { return last_update_result_; }
+
   GetRequestsResult last_get_requests_result() const {
     return last_get_requests_result_;
   }
@@ -70,6 +76,7 @@
   std::unique_ptr<SavePageRequest> last_added_request_;
 
   UpdateRequestResult last_remove_result_;
+  UpdateRequestResult last_update_result_;
 
   GetRequestsResult last_get_requests_result_;
   std::vector<SavePageRequest> last_requests_;
@@ -82,6 +89,7 @@
 RequestQueueTest::RequestQueueTest()
     : last_add_result_(AddRequestResult::STORE_FAILURE),
       last_remove_result_(UpdateRequestResult::STORE_FAILURE),
+      last_update_result_(UpdateRequestResult::STORE_FAILURE),
       last_get_requests_result_(GetRequestsResult::STORE_FAILURE),
       task_runner_(new base::TestSimpleTaskRunner),
       task_runner_handle_(task_runner_) {}
@@ -115,6 +123,10 @@
   last_remove_result_ = result;
 }
 
+void RequestQueueTest::UpdateRequestDone(UpdateRequestResult result) {
+  last_update_result_ = result;
+}
+
 TEST_F(RequestQueueTest, GetRequestsEmpty) {
   queue()->GetRequests(
       base::Bind(&RequestQueueTest::GetRequestsDone, base::Unretained(this)));
@@ -125,7 +137,8 @@
 
 TEST_F(RequestQueueTest, AddRequest) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   queue()->AddRequest(request, base::Bind(&RequestQueueTest::AddRequestDone,
                                           base::Unretained(this)));
   PumpLoop();
@@ -142,7 +155,8 @@
 
 TEST_F(RequestQueueTest, RemoveRequest) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   queue()->AddRequest(request, base::Bind(&RequestQueueTest::AddRequestDone,
                                           base::Unretained(this)));
   PumpLoop();
@@ -165,12 +179,14 @@
 // listing multiple items and removing the right item.
 TEST_F(RequestQueueTest, MultipleRequestsAddGetRemove) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request1(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest request1(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   queue()->AddRequest(request1, base::Bind(&RequestQueueTest::AddRequestDone,
                                            base::Unretained(this)));
   PumpLoop();
   ASSERT_EQ(request1.request_id(), last_added_request()->request_id());
-  SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time);
+  SavePageRequest request2(
+      kRequestId2, kUrl2, kClientId2, creation_time, kUserRequested);
   queue()->AddRequest(request2, base::Bind(&RequestQueueTest::AddRequestDone,
                                            base::Unretained(this)));
   PumpLoop();
@@ -196,4 +212,49 @@
   ASSERT_EQ(request2.request_id(), last_requests()[0].request_id());
 }
 
+TEST_F(RequestQueueTest, UpdateRequest) {
+  // First add a request.  Retry count will be set to 0.
+  base::Time creation_time = base::Time::Now();
+  SavePageRequest request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
+  queue()->AddRequest(request, base::Bind(&RequestQueueTest::AddRequestDone,
+                                          base::Unretained(this)));
+  PumpLoop();
+
+  // Update the request, ensure it succeeded.
+  request.set_attempt_count(kRetryCount);
+  queue()->UpdateRequest(
+      request,
+      base::Bind(&RequestQueueTest::UpdateRequestDone, base::Unretained(this)));
+  PumpLoop();
+  ASSERT_EQ(UpdateRequestResult::SUCCESS, last_update_result());
+
+  // Get the request, and verify the update took effect.
+  queue()->GetRequests(
+      base::Bind(&RequestQueueTest::GetRequestsDone, base::Unretained(this)));
+  PumpLoop();
+  ASSERT_EQ(GetRequestsResult::SUCCESS, last_get_requests_result());
+  ASSERT_EQ(1ul, last_requests().size());
+  ASSERT_EQ(kRetryCount, last_requests().front().attempt_count());
+}
+
+TEST_F(RequestQueueTest, UpdateRequestNotPresent) {
+  // First add a request.  Retry count will be set to 0.
+  base::Time creation_time = base::Time::Now();
+  SavePageRequest request1(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
+  SavePageRequest request2(
+      kRequestId2, kUrl2, kClientId2, creation_time, kUserRequested);
+  queue()->AddRequest(request2, base::Bind(&RequestQueueTest::AddRequestDone,
+                                           base::Unretained(this)));
+  PumpLoop();
+
+  // Try to update request1 when only request2 is in the queue.
+  queue()->UpdateRequest(
+      request1,
+      base::Bind(&RequestQueueTest::UpdateRequestDone, base::Unretained(this)));
+  PumpLoop();
+  ASSERT_EQ(UpdateRequestResult::REQUEST_DOES_NOT_EXIST, last_update_result());
+}
+
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/save_page_request.cc b/components/offline_pages/background/save_page_request.cc
index fba16e6..f9372f3 100644
--- a/components/offline_pages/background/save_page_request.cc
+++ b/components/offline_pages/background/save_page_request.cc
@@ -9,25 +9,29 @@
 SavePageRequest::SavePageRequest(int64_t request_id,
                                  const GURL& url,
                                  const ClientId& client_id,
-                                 const base::Time& creation_time)
+                                 const base::Time& creation_time,
+                                 const bool was_user_requested)
     : request_id_(request_id),
       url_(url),
       client_id_(client_id),
       creation_time_(creation_time),
       activation_time_(creation_time),
-      attempt_count_(0) {}
+      attempt_count_(0),
+      user_requested_(was_user_requested) {}
 
 SavePageRequest::SavePageRequest(int64_t request_id,
                                  const GURL& url,
                                  const ClientId& client_id,
                                  const base::Time& creation_time,
-                                 const base::Time& activation_time)
+                                 const base::Time& activation_time,
+                                 const bool user_requested)
     : request_id_(request_id),
       url_(url),
       client_id_(client_id),
       creation_time_(creation_time),
       activation_time_(activation_time),
-      attempt_count_(0) {}
+      attempt_count_(0),
+      user_requested_(user_requested) {}
 
 SavePageRequest::SavePageRequest(const SavePageRequest& other)
     : request_id_(other.request_id_),
@@ -36,7 +40,8 @@
       creation_time_(other.creation_time_),
       activation_time_(other.activation_time_),
       attempt_count_(other.attempt_count_),
-      last_attempt_time_(other.last_attempt_time_) {}
+      last_attempt_time_(other.last_attempt_time_),
+      user_requested_(other.user_requested_) {}
 
 SavePageRequest::~SavePageRequest() {}
 
diff --git a/components/offline_pages/background/save_page_request.h b/components/offline_pages/background/save_page_request.h
index afc6bd7e..8c09562 100644
--- a/components/offline_pages/background/save_page_request.h
+++ b/components/offline_pages/background/save_page_request.h
@@ -30,12 +30,14 @@
   SavePageRequest(int64_t request_id,
                   const GURL& url,
                   const ClientId& client_id,
-                  const base::Time& creation_time);
+                  const base::Time& creation_time,
+                  const bool user_requested);
   SavePageRequest(int64_t request_id,
                   const GURL& url,
                   const ClientId& client_id,
                   const base::Time& creation_time,
-                  const base::Time& activation_time);
+                  const base::Time& activation_time,
+                  const bool user_requested);
   SavePageRequest(const SavePageRequest& other);
   ~SavePageRequest();
 
@@ -68,6 +70,12 @@
     last_attempt_time_ = last_attempt_time;
   }
 
+  bool user_requested() const { return user_requested_; }
+
+  void set_user_requested(bool user_requested) {
+    user_requested_ = user_requested;
+  }
+
  private:
   // ID of this request.
   int64_t request_id_;
@@ -90,6 +98,10 @@
 
   // Timestamp of the last request starting.
   base::Time last_attempt_time_;
+
+  // Whether the user specifically requested this page (as opposed to a client
+  // like AGSA or Now.)
+  bool user_requested_;
 };
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/save_page_request_unittest.cc b/components/offline_pages/background/save_page_request_unittest.cc
index bec07f2..63b970f 100644
--- a/components/offline_pages/background/save_page_request_unittest.cc
+++ b/components/offline_pages/background/save_page_request_unittest.cc
@@ -12,6 +12,7 @@
 const int64_t kRequestId = 42;
 const GURL kUrl("http://example.com");
 const ClientId kClientId("bookmark", "1234");
+const bool kUserRequested = true;
 }  // namespace
 
 class SavePageRequestTest : public testing::Test {
@@ -23,7 +24,8 @@
 
 TEST_F(SavePageRequestTest, CreatePendingReqeust) {
   base::Time creation_time = base::Time::Now();
-  SavePageRequest request(kRequestId, kUrl, kClientId, creation_time);
+  SavePageRequest request(
+      kRequestId, kUrl, kClientId, creation_time, kUserRequested);
   ASSERT_EQ(kRequestId, request.request_id());
   ASSERT_EQ(kUrl, request.url());
   ASSERT_EQ(kClientId, request.client_id());
@@ -41,7 +43,7 @@
   base::Time creation_time = base::Time::Now();
   base::Time activation_time = creation_time + base::TimeDelta::FromHours(6);
   SavePageRequest request(kRequestId, kUrl, kClientId, creation_time,
-                          activation_time);
+                          activation_time, kUserRequested);
 
   ASSERT_EQ(kRequestId, request.request_id());
   ASSERT_EQ(kUrl, request.url());
@@ -63,7 +65,7 @@
   base::Time creation_time = base::Time::Now();
   base::Time activation_time = creation_time + base::TimeDelta::FromHours(6);
   SavePageRequest request(kRequestId, kUrl, kClientId, creation_time,
-                          activation_time);
+                          activation_time, kUserRequested);
 
   base::Time start_time = activation_time + base::TimeDelta::FromHours(3);
   request.MarkAttemptStarted(start_time);
diff --git a/components/pdf/renderer/pepper_pdf_host.cc b/components/pdf/renderer/pepper_pdf_host.cc
index 1355141..4c02e704 100644
--- a/components/pdf/renderer/pepper_pdf_host.cc
+++ b/components/pdf/renderer/pepper_pdf_host.cc
@@ -4,6 +4,7 @@
 
 #include "components/pdf/renderer/pepper_pdf_host.h"
 
+#include "base/memory/ptr_util.h"
 #include "components/pdf/common/pdf_messages.h"
 #include "components/pdf/renderer/pdf_accessibility_tree.h"
 #include "content/public/common/referrer.h"
@@ -30,6 +31,7 @@
 namespace pdf {
 
 namespace {
+
 // --single-process model may fail in CHECK(!g_print_client) if there exist
 // more than two RenderThreads, so here we use TLS for g_print_client.
 // See http://crbug.com/457580.
@@ -96,33 +98,33 @@
 
 int32_t PepperPDFHost::OnHostMsgDidStartLoading(
     ppapi::host::HostMessageContext* context) {
-  content::PepperPluginInstance* instance =
-      host_->GetPluginInstance(pp_instance());
-  if (!instance)
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view)
     return PP_ERROR_FAILED;
-  instance->GetRenderView()->DidStartLoading();
+
+  render_view->DidStartLoading();
   return PP_OK;
 }
 
 int32_t PepperPDFHost::OnHostMsgDidStopLoading(
     ppapi::host::HostMessageContext* context) {
-  content::PepperPluginInstance* instance =
-      host_->GetPluginInstance(pp_instance());
-  if (!instance)
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view)
     return PP_ERROR_FAILED;
-  instance->GetRenderView()->DidStopLoading();
+
+  render_view->DidStopLoading();
   return PP_OK;
 }
 
 int32_t PepperPDFHost::OnHostMsgSetContentRestriction(
     ppapi::host::HostMessageContext* context,
     int restrictions) {
-  content::PepperPluginInstance* instance =
-      host_->GetPluginInstance(pp_instance());
-  if (!instance)
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view)
     return PP_ERROR_FAILED;
-  instance->GetRenderView()->Send(new PDFHostMsg_PDFUpdateContentRestrictions(
-      instance->GetRenderView()->GetRoutingID(), restrictions));
+
+  render_view->Send(new PDFHostMsg_PDFUpdateContentRestrictions(
+      render_view->GetRoutingID(), restrictions));
   return PP_OK;
 }
 
@@ -137,19 +139,10 @@
 
 int32_t PepperPDFHost::OnHostMsgHasUnsupportedFeature(
     ppapi::host::HostMessageContext* context) {
-  content::PepperPluginInstance* instance =
-      host_->GetPluginInstance(pp_instance());
-  if (!instance)
+  content::RenderView* render_view = GetRenderView();
+  if (!render_view)
     return PP_ERROR_FAILED;
 
-  // TODO(thestig): Turn CHECKs into the proper if statement after figuring out
-  // what's wrong for https://crbug.com/627814
-  CHECK(instance->GetContainer());
-  CHECK(instance->GetContainer()->document().frame());
-  CHECK(instance->GetContainer()->document().frame()->view());
-  blink::WebView* view =
-      instance->GetContainer()->document().frame()->view();
-  content::RenderView* render_view = content::RenderView::FromWebView(view);
   render_view->Send(
       new PDFHostMsg_PDFHasUnsupportedFeature(render_view->GetRoutingID()));
   return PP_OK;
@@ -166,8 +159,12 @@
       host_->GetPluginInstance(pp_instance());
   if (!instance)
     return PP_ERROR_FAILED;
-  GURL url = instance->GetPluginURL();
+
   content::RenderView* render_view = instance->GetRenderView();
+  if (!render_view)
+    return PP_ERROR_FAILED;
+
+  GURL url = instance->GetPluginURL();
   content::Referrer referrer;
   referrer.url = url;
   referrer.policy = blink::WebReferrerPolicyDefault;
@@ -234,9 +231,15 @@
 
 void PepperPDFHost::CreatePdfAccessibilityTreeIfNeeded() {
   if (!pdf_accessibility_tree_) {
-    pdf_accessibility_tree_.reset(new PdfAccessibilityTree(
-        host_, pp_instance()));
+    pdf_accessibility_tree_ =
+        base::MakeUnique<PdfAccessibilityTree>(host_, pp_instance());
   }
 }
 
+content::RenderView* PepperPDFHost::GetRenderView() {
+  content::PepperPluginInstance* instance =
+      host_->GetPluginInstance(pp_instance());
+  return instance ? instance->GetRenderView() : nullptr;
+}
+
 }  // namespace pdf
diff --git a/components/pdf/renderer/pepper_pdf_host.h b/components/pdf/renderer/pepper_pdf_host.h
index a4756af..5a41e87 100644
--- a/components/pdf/renderer/pepper_pdf_host.h
+++ b/components/pdf/renderer/pepper_pdf_host.h
@@ -7,7 +7,9 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
@@ -24,18 +26,17 @@
 
 namespace content {
 class PepperPluginInstance;
+class RenderView;
 class RendererPpapiHost;
 }
 
 namespace ppapi {
 class HostResource;
-}
 
-namespace ppapi {
 namespace host {
 struct HostMessageContext;
-}
-}
+}  // namespace host
+}  // namespace ppapi
 
 namespace pdf {
 
@@ -71,6 +72,7 @@
   // PPB_PDF_Impl instance.
   static void SetPrintClient(PrintClient* print_client);
 
+  // ppapi::host::ResourceHost:
   int32_t OnResourceMessageReceived(
       const IPC::Message& msg,
       ppapi::host::HostMessageContext* context) override;
@@ -106,9 +108,11 @@
 
   void CreatePdfAccessibilityTreeIfNeeded();
 
+  content::RenderView* GetRenderView();
+
   std::unique_ptr<PdfAccessibilityTree> pdf_accessibility_tree_;
 
-  content::RendererPpapiHost* host_;
+  content::RendererPpapiHost* const host_;
 
   DISALLOW_COPY_AND_ASSIGN(PepperPDFHost);
 };
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 6279926..40c9990 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -386,17 +386,20 @@
       'name': 'DnsPrefetchingEnabled',
       'type': 'main',
       'schema': { 'type': 'boolean' },
-      'supported_on': ['chrome.*:8-', 'chrome_os:11-', 'android:30-'],
+      'supported_on': ['chrome.*:8-53', 'chrome_os:11-53', 'android:30-53'],
       'features': {
         'can_be_recommended': True,
         'dynamic_refresh': True,
         'per_profile': True,
       },
+      'deprecated': True,
       'example_value': True,
       'id': 7,
       'caption': '''Enable network prediction''',
       'tags': [],
-      'desc': '''Enables network prediction in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> and prevents users from changing this setting.
+      'desc': '''This policy is deprecated in M48 in favor of NetworkPredictionOptions, and removed in M54.
+
+      Enables network prediction in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> and prevents users from changing this setting.
 
       This controls not only DNS prefetching but also TCP and SSL preconnection and prerendering of web pages. The policy name refers to DNS prefetching for historical reasons.
 
@@ -470,7 +473,7 @@
       'name': 'DisableSpdy',
       'type': 'main',
       'schema': { 'type': 'boolean' },
-      'supported_on': ['chrome.*:8-', 'chrome_os:11-', 'android:30-'],
+      'supported_on': ['chrome.*:8-53', 'chrome_os:11-53', 'android:30-53'],
       'features': {
         'dynamic_refresh': True,
         'per_profile': False,
@@ -480,7 +483,7 @@
       'id': 8,
       'caption': '''Disable SPDY protocol''',
       'tags': [],
-      'desc': '''This policy is deprecated, because SPDY/3.1 support is removed.
+      'desc': '''This policy is deprecated in M53 and removed in M54, because SPDY/3.1 support is removed.
 
       Disables use of the SPDY protocol in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.
 
diff --git a/components/policy/resources/policy_templates_am.xtb b/components/policy/resources/policy_templates_am.xtb
index 663d699..ddc310b 100644
--- a/components/policy/resources/policy_templates_am.xtb
+++ b/components/policy/resources/policy_templates_am.xtb
@@ -1942,13 +1942,6 @@
 ይህ መመሪያ ካልተዘጋጀ የራስ ሰር ማጽዳት አብሮ የተገነባውን ነባሪ ዘዴ ይጠቀማል። በአሁኑ ወቅት ያለው የ«RemoveLRUIfDormant» ዘዴ ነው።</translation>
 <translation id="7336878834592315572">ክፍለ ጊዜው እስከቆየበት ያህል ጊዜ ድረስ ኩኪዎችን አቆይ</translation>
 <translation id="7340034977315324840">የመሣሪያ እንቅስቃሴዎች ብዛት ሪፖርት ያድርጉ</translation>
-<translation id="7381326101471547614">በ<ph name="PRODUCT_NAME" /> ውስጥ የSPDY ፕሮቶኮል መጠቀምን ያሰናክላል።
-
-      ይህ መመሪያ ከነቃ የSPDY ፕሮቶኮሉ በ<ph name="PRODUCT_NAME" /> ውስጥ አይገኝም።
-
-      ይህን መመሪያ ማሰናከል የየSPDY መጠቀምን ያሰናክላል።
-
-      ይህ መመሪያ እንዳልተዋቀረ ከተተወ SPDY ይገኛል።</translation>
 <translation id="7384999953864505698">የQUIC ፕሮቶኮል ይፈቅዳል</translation>
 <translation id="7406651467768226499">የ<ph name="PRODUCT_OS_NAME" /> ስሪትን ለመቆጣጠር ከዜሮ መዘግየት kiosk መተግበሪያ ጋር አብሮ የተመጀረውን ራስ-ሰር ለመፍቀድ።
 
diff --git a/components/policy/resources/policy_templates_ar.xtb b/components/policy/resources/policy_templates_ar.xtb
index 0b540c2..16419f8 100644
--- a/components/policy/resources/policy_templates_ar.xtb
+++ b/components/policy/resources/policy_templates_ar.xtb
@@ -1765,7 +1765,6 @@
 إذا لم يتم تعيين هذه السياسة، يستخدم التنظيف التلقائي الإستراتيجية المضمنة الافتراضية. حاليًا الإستراتيجية المستخدمة هي 'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">الاحتفاظ بملفات تعريف الارتباط طوال مدة الجلسة</translation>
 <translation id="7340034977315324840">تسجيل أوقات نشاط الجهاز</translation>
-<translation id="7381326101471547614">‏لتعطيل استخدام بروتوكول SPDY في <ph name="PRODUCT_NAME" />. إذا تم تمكين هذه السياسة، فلن يكون بروتوكول SPDY متاحًا في <ph name="PRODUCT_NAME" />. يؤدي تعطيل هذه السياسة إلى السماح باستخدام SPDY. إذا تم ترك هذه السياسة بدون تعيين، فسيكون SPDY متاحًا.</translation>
 <translation id="7384999953864505698">‏تسمح ببروتوكول QUIC</translation>
 <translation id="7406651467768226499">‏لتحديد الرغبة في السماح لتطبيق kiosk الذي يتم تشغيله تلقائيًا بدون أي تأخير بالتحكم في إصدار <ph name="PRODUCT_OS_NAME" /> أم لا.
 
diff --git a/components/policy/resources/policy_templates_bg.xtb b/components/policy/resources/policy_templates_bg.xtb
index e597cd2..f5d3eb9a 100644
--- a/components/policy/resources/policy_templates_bg.xtb
+++ b/components/policy/resources/policy_templates_bg.xtb
@@ -1790,7 +1790,6 @@
       В случай че това правило не е зададено, при автоматично почистване се ползва стандартната вградена стратегия. Понастоящем тя е „RemoveLRUIfDormant“.</translation>
 <translation id="7336878834592315572">Съхраняване на „бисквитките“ за цялата продължителност на сесията</translation>
 <translation id="7340034977315324840">Съобщаване на времената на активност на устройствата</translation>
-<translation id="7381326101471547614">Деактивира използването на протокол SPDY в <ph name="PRODUCT_NAME" />. Ако това правило е активирано, той няма да е налице в <ph name="PRODUCT_NAME" />. В случай че е деактивирано, ще се разреши използването на SPDY. Ако правилото е оставено незададено, SPDY ще бъде налице.</translation>
 <translation id="7384999953864505698">Разрешаване на протокола QUIC</translation>
 <translation id="7406651467768226499">Изберете дали да разрешите на павилионното приложение, което се стартира автоматично без забавяне, да контролира версията на <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_bn.xtb b/components/policy/resources/policy_templates_bn.xtb
index 9002fce..deda07e 100644
--- a/components/policy/resources/policy_templates_bn.xtb
+++ b/components/policy/resources/policy_templates_bn.xtb
@@ -1906,11 +1906,6 @@
       যদি নীতিটি সেট না করা হয় তাহলে,  স্বয়ংক্রিয় ক্লিন-আপ ডিফল্ট বিল্ট ইন কৌশল ব্যবহার করবে। বর্তমানে, এটি হল 'RemoveLRUIfDormant' কৌশল।</translation>
 <translation id="7336878834592315572">সেশনের স্থিতিকাল পর্যন্ত কুকিজ রাখুন</translation>
 <translation id="7340034977315324840">ডিভাইসের কার্যকলাপের সময় প্রতিবেদন করুন</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" />-এর মধ্যে SPDY প্রটোকলের ব্যবহার অক্ষম করুন৷ 
-
-নীতিটি যদি সক্ষম করা হয় SPDY প্রটোকল <ph name="PRODUCT_NAME" />-এর মধ্যে উপলব্ধ হবে না৷ 
-অক্ষম করার জন্য এই নীতির সেটিংটি SPDY ব্যবহারকে মঞ্জুরি দেবে৷ 
-যদি এই নীতিটি সেট না করেই ছেড়ে যাওয়া হয়, SPDY উপলব্ধ হবে৷</translation>
 <translation id="7384999953864505698">QUIC প্রোটোকলকে মঞ্জুরি দেয়</translation>
 <translation id="7406651467768226499">শূন্য বিলম্ব সহ স্বয়ংক্রিয় লঞ্চ হওয়া কিয়স্ক অ্যাপ্লিকেশানকে <ph name="PRODUCT_OS_NAME" /> সংস্করণ নিয়ন্ত্রণ করতে দেওয়া হবে কিনা।
 
diff --git a/components/policy/resources/policy_templates_ca.xtb b/components/policy/resources/policy_templates_ca.xtb
index 615e1cc..986755a 100644
--- a/components/policy/resources/policy_templates_ca.xtb
+++ b/components/policy/resources/policy_templates_ca.xtb
@@ -1792,13 +1792,6 @@
       Si aquesta política no es defineix, la neteja automàtica utilitza l'estratègia integrada predeterminada. Actualment, és l'estratègia RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Conserva les galetes mentre duri la sessió</translation>
 <translation id="7340034977315324840">Informa del temps d'activitat dels dispositius</translation>
-<translation id="7381326101471547614">Desactiva l'ús del protocol SPDY a <ph name="PRODUCT_NAME" />.
-
-      Si aquesta política està activada, el protocol SPDY no estarà disponible a <ph name="PRODUCT_NAME" />.
-
-      Si establiu aquesta política com a desactivada, es permetrà l'ús de SPDY.
-
-      Si no definiu aquesta política, SPDY estarà disponible.</translation>
 <translation id="7384999953864505698">Permet el protocol QUIC</translation>
 <translation id="7406651467768226499">Aquesta política defineix si es permet que l'aplicació de quiosc d'inici automàtic sense retards controli la versió de <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_cs.xtb b/components/policy/resources/policy_templates_cs.xtb
index 09da556..bc7ee989 100644
--- a/components/policy/resources/policy_templates_cs.xtb
+++ b/components/policy/resources/policy_templates_cs.xtb
@@ -1881,13 +1881,6 @@
       Pokud tato zásada nastavena není, bude při automatickém čištění použita výchozí integrovaná strategie. Aktuálně je to strategie RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Uchovat soubory cookie po dobu trvání relace</translation>
 <translation id="7340034977315324840">Hlásit časy aktivity zařízení</translation>
-<translation id="7381326101471547614">Zakáže v aplikaci <ph name="PRODUCT_NAME" /> použití protokolu SPDY.
-
-      Pokud je zásada aktivní, nebude protokol SPDY v aplikaci <ph name="PRODUCT_NAME" /> k dispozici.
-
-      Pokud zásadu deaktivujete, umožníte využívání protokolu SPDY. 
-
-      Pokud zásadu nenastavíte, bude protokol SPDY k dispozici.</translation>
 <translation id="7384999953864505698">Povoluje protokol QUIC</translation>
 <translation id="7406651467768226499">Udává, zda má mít automaticky spouštěná terminálová aplikace s nulovým zpožděním povoleno ovládat verzi systému <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_da.xtb b/components/policy/resources/policy_templates_da.xtb
index e3f49a1..cd36160 100644
--- a/components/policy/resources/policy_templates_da.xtb
+++ b/components/policy/resources/policy_templates_da.xtb
@@ -1808,7 +1808,6 @@
       Hvis denne politik ikke er indstillet, anvender den automatiske oprydningsfunktion standardstrategien. Denne strategi er i øjeblikket "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Behold cookies under sessionen</translation>
 <translation id="7340034977315324840">Rapportér tidspunkter for aktiviteter på enheden</translation>
-<translation id="7381326101471547614">Deaktiverer brug af SPDY-protokollen i <ph name="PRODUCT_NAME" />. Hvis denne politik er aktiveret, vil SPDY-protokollen ikke være tilgængelig i <ph name="PRODUCT_NAME" />. Hvis du deaktiverer denne politik, tillades brug af ​​SPDY. Hvis retningslinjerne for denne politik ikke angives, vil SPDY være tilgængelig.</translation>
 <translation id="7384999953864505698">Tillader QUIC-protokol</translation>
 <translation id="7406651467768226499">Om den automatisk startede terminalapp uden forsinkelse skal kunne kontrollere <ph name="PRODUCT_OS_NAME" />-versionen.
 
diff --git a/components/policy/resources/policy_templates_de.xtb b/components/policy/resources/policy_templates_de.xtb
index fac77c2..3546e9f 100644
--- a/components/policy/resources/policy_templates_de.xtb
+++ b/components/policy/resources/policy_templates_de.xtb
@@ -1789,7 +1789,6 @@
       Ist die Richtlinie nicht konfiguriert, erfolgt die automatische Bereinigung auf Grundlage der integrierten Standardstrategie. Zurzeit handelt es sich dabei um die "RemoveLRUIfDormant"-Strategie.</translation>
 <translation id="7336878834592315572">Cookies für die Dauer der Sitzung beibehalten</translation>
 <translation id="7340034977315324840">Aktivitätszeit von Geräten melden</translation>
-<translation id="7381326101471547614">Hiermit wird die Verwendung des SPDY-Protokolls in <ph name="PRODUCT_NAME" /> verhindert. Wenn diese Richtlinie aktiviert ist, steht das SPDY-Protokoll in <ph name="PRODUCT_NAME" /> nicht zur Verfügung. Sollte sie deaktiviert werden, kann SPDY genutzt werden. Ist die Richtlinie nicht konfiguriert, steht SPDY zur Verfügung.</translation>
 <translation id="7384999953864505698">Lässt das QUIC-Protokoll zu</translation>
 <translation id="7406651467768226499">Gibt an, ob der automatisch ohne Verzögerung gestarteten Kiosk-App die Steuerung der <ph name="PRODUCT_OS_NAME" />-Version gestattet werden soll.
 
diff --git a/components/policy/resources/policy_templates_el.xtb b/components/policy/resources/policy_templates_el.xtb
index fa7527bb..1f0be96b 100644
--- a/components/policy/resources/policy_templates_el.xtb
+++ b/components/policy/resources/policy_templates_el.xtb
@@ -1926,13 +1926,6 @@
       Εάν αυτή η πολιτική δεν έχει οριστεί, η αυτόματη διαγραφή χρησιμοποιεί την προεπιλεγμένη ενσωματωμένη στρατηγική. Προς το παρόν, χρησιμοποιείται η στρατηγική "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Διατήρηση cookie για τη διάρκεια της περιόδου σύνδεσης</translation>
 <translation id="7340034977315324840">Αναφορά χρονικών περιόδων δραστηριότητας συσκευής</translation>
-<translation id="7381326101471547614">Απενεργοποιεί τη χρήση του πρωτοκόλλου SPDY στο <ph name="PRODUCT_NAME" />.
-
-      Εάν αυτή η πολιτική είναι ενεργοποιημένη στο πρωτόκολλο SPDY δεν θα είναι διαθέσιμη στο <ph name="PRODUCT_NAME" />.
-
-      Η απενεργοποίηση αυτής της πολιτικής θα επιτρέψει τη χρήση του SPDY.
-
-      Εάν αυτή η πολιτική δεν οριστεί, το SPDY θα είναι διαθέσιμο.</translation>
 <translation id="7384999953864505698">Δυνατότητα χρήσης πρωτοκόλλου QUIC</translation>
 <translation id="7406651467768226499">Καθορίζει εάν θα επιτρέπεται στην εφαρμογή kiosk αυτόματης εκκίνησης με μηδενική καθυστέρηση να ελέγχει την έκδοση <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_en-GB.xtb b/components/policy/resources/policy_templates_en-GB.xtb
index 783caa70..15117d07 100644
--- a/components/policy/resources/policy_templates_en-GB.xtb
+++ b/components/policy/resources/policy_templates_en-GB.xtb
@@ -1940,13 +1940,6 @@
       If this policy is not set, automatic clean-up uses the default built-in strategy. Currently, it is the 'RemoveLRUIfDormant' strategy.</translation>
 <translation id="7336878834592315572">Keep cookies for the duration of the session.</translation>
 <translation id="7340034977315324840">Report device activity times</translation>
-<translation id="7381326101471547614">Disables use of the SPDY protocol in <ph name="PRODUCT_NAME" />.
-
-      If this policy is enabled the SPDY protocol will not be available in <ph name="PRODUCT_NAME" />.
-
-      Setting this policy to disabled will allow the usage of SPDY.
-
-      If this policy is left not set, SPDY will be available.</translation>
 <translation id="7384999953864505698">Allows QUIC protocol</translation>
 <translation id="7406651467768226499">Whether to allow the auto launched with zero delay kiosk app to control <ph name="PRODUCT_OS_NAME" /> version.
 
diff --git a/components/policy/resources/policy_templates_es-419.xtb b/components/policy/resources/policy_templates_es-419.xtb
index 49b1e190..f2b54e3 100644
--- a/components/policy/resources/policy_templates_es-419.xtb
+++ b/components/policy/resources/policy_templates_es-419.xtb
@@ -1779,7 +1779,6 @@
       Si esta política no se establece, la limpieza automática utilizará la estrategia integrada predeterminada, que actualmente es "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Guardar las cookies durante la sesión</translation>
 <translation id="7340034977315324840">Notificar tiempo de actividad del dispositivo</translation>
-<translation id="7381326101471547614">Permite inhabilitar el protocolo SPDY en <ph name="PRODUCT_NAME" />. Si se habilita esta política, el protocolo SPDY no estará disponible en <ph name="PRODUCT_NAME" />. Si se inhabilita esta política, se podrá utilizar el protocolo SPDY. Si no se establece esta política, el protocolo SPDY estará disponible.</translation>
 <translation id="7384999953864505698">Permite el protocolo QUIC</translation>
 <translation id="7406651467768226499">Determina si se permite que la aplicación de kiosko con lanzamiento automático sin tiempo de espera controle la versión de <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_es.xtb b/components/policy/resources/policy_templates_es.xtb
index 49e45a7..05e8724 100644
--- a/components/policy/resources/policy_templates_es.xtb
+++ b/components/policy/resources/policy_templates_es.xtb
@@ -1927,13 +1927,6 @@
       Si esta política no se establece, la limpieza automática utilizará la estrategia integrada predeterminada. Actualmente, se trata de la estrategia RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Guardar las cookies durante la duración de la sesión</translation>
 <translation id="7340034977315324840">Notificar tiempo de actividad del dispositivo</translation>
-<translation id="7381326101471547614">Permite inhabilitar el uso del protocolo SPDY en <ph name="PRODUCT_NAME" />.
-
-      Si se habilita esta política, el protocolo SPDY no estará disponible en <ph name="PRODUCT_NAME" />.
-
-      Si se inhabilita esta política, se podrá utilizar el protocolo SPDY.
-
-      Si no se establece esta política, el protocolo SPDY estará disponible.</translation>
 <translation id="7384999953864505698">Permitir protocolo QUIC</translation>
 <translation id="7406651467768226499">Permitir que la aplicación de kiosco sin retardo con inicio automático controle la versión de <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_et.xtb b/components/policy/resources/policy_templates_et.xtb
index 8dcbd9037..6edf15d 100644
--- a/components/policy/resources/policy_templates_et.xtb
+++ b/components/policy/resources/policy_templates_et.xtb
@@ -1927,7 +1927,6 @@
       Kui reegel on määramata, kasutab automaatne puhastamine sisseehitatud vaikestrateegiat. Praegu on selleks strateegia „RemoveLRUIfDormant”.</translation>
 <translation id="7336878834592315572">Säilita küpsised seansi kestuse jooksul</translation>
 <translation id="7340034977315324840">Saada teavet seadme aktiivsuse aja kohta</translation>
-<translation id="7381326101471547614">Keelab SPDY-protokolli kasutamise rakenduses <ph name="PRODUCT_NAME" />. Kui reegel on lubatud, siis ei ole SPDY-protokoll rakenduses <ph name="PRODUCT_NAME" /> saadaval. Reegli keelamisel on SPDY kasutamine lubatud. Kui jätate reegli määramata, siis on SPDY saadaval.</translation>
 <translation id="7384999953864505698">Lubab QUIC-protokolli</translation>
 <translation id="7406651467768226499">Kas lubada automaatselt käivitatud viivituseta kioskirakendusel juhtida operatsioonisüsteemi <ph name="PRODUCT_OS_NAME" /> versiooni.
 
diff --git a/components/policy/resources/policy_templates_fa.xtb b/components/policy/resources/policy_templates_fa.xtb
index a59bf3fe..31e8982 100644
--- a/components/policy/resources/policy_templates_fa.xtb
+++ b/components/policy/resources/policy_templates_fa.xtb
@@ -1772,7 +1772,6 @@
       اگر این خط‌مشی تنظیم نشده باشد، مرحله پاک کردن خودکار از استراتژی داخلی پیش‌فرض استفاده می‌کند. در حال حاضر این استراتژی «RemoveLRUIfDormant» است.</translation>
 <translation id="7336878834592315572">نگهداشتن کوکی‌ها برای کل مدت جلسه</translation>
 <translation id="7340034977315324840">گزارش زمان‌های فعالیت دستگاه</translation>
-<translation id="7381326101471547614">‏استفاده از پروتکل SPDY را در <ph name="PRODUCT_NAME" /> غیرفعال می‌کند. اگر این قانون فعال شود، پروتکل SPDY در <ph name="PRODUCT_NAME" /> قابل دسترس نخواهد بود. تنظیم این قانون بر روی غیرفعال، اجازه استفاده از SPDY را می‌دهد. اگر این قانون تنظیم نشده باقی بماند SPDY قابل دسترس خواهد بود.</translation>
 <translation id="7384999953864505698">‏پروتکل QUIC را مجاز می‌کند</translation>
 <translation id="7406651467768226499">‏اینکه به برنامه kiosk راه‌اندازی‌شده به‌طور خودکار با تأخیر صفر، امکان داده شود نسخه <ph name="PRODUCT_OS_NAME" /> را کنترل کند یا نه.
 
diff --git a/components/policy/resources/policy_templates_fi.xtb b/components/policy/resources/policy_templates_fi.xtb
index 92d155f1..a88c8f6 100644
--- a/components/policy/resources/policy_templates_fi.xtb
+++ b/components/policy/resources/policy_templates_fi.xtb
@@ -1791,7 +1791,6 @@
       Jos käytäntöä ei määritetä, automaattinen puhdistus käyttää sisäänrakennettua oletustapaa, joka on tällä hetkellä RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Säilytä evästeet käyttökerran ajan</translation>
 <translation id="7340034977315324840">Ilmoita laitteen käyttöajat</translation>
-<translation id="7381326101471547614">Poistaa käytöstä SPDY-protokollan tuotteessa <ph name="PRODUCT_NAME" />. Jos tämä käytäntö on käytössä, SPDY-protokolla ei ole käytettävissä tuotteessa <ph name="PRODUCT_NAME" />. Jos tätä käytäntöä ei oteta käyttöön, SDPY-protokollaa voi käyttää. Jos käytäntöä ei ole määritetty, SDPY on käytettävissä.</translation>
 <translation id="7384999953864505698">Sallii QUIC-protokollan käytön</translation>
 <translation id="7406651467768226499">Tämä määrittää, sallitaanko automaattisesti ilman viivettä käynnistettävän kioskisovelluksen hallinnoida käyttöjärjestelmän <ph name="PRODUCT_OS_NAME" /> versiota.
 
diff --git a/components/policy/resources/policy_templates_fil.xtb b/components/policy/resources/policy_templates_fil.xtb
index ae1d10d..5e2a132 100644
--- a/components/policy/resources/policy_templates_fil.xtb
+++ b/components/policy/resources/policy_templates_fil.xtb
@@ -1931,7 +1931,6 @@
       Kung hindi itinakda ang patakarang ito, gagamiting ng awtomatikong pag-clean-up ang default na built-in na diskarte. Sa kasalukuyan, ito ay ang 'RemoveLRUIfDormant' na diskarte.</translation>
 <translation id="7336878834592315572">Panatilihin ang cookies para sa kabuuan ng session</translation>
 <translation id="7340034977315324840">Iulat ang mga panahon ng aktibidad ng device</translation>
-<translation id="7381326101471547614">Hindi pinapagana ang paggamit ng SPDY protocol sa <ph name="PRODUCT_NAME" />. Kung pinagana ang patakarang ito, ang SPDY protocol ay hindi magiging available sa <ph name="PRODUCT_NAME" />. Ang pagtatakda ng patakarang ito sa hindi pinagana ay papayagan ang paggamit ng SPDY. Kung iwanang hindi nakatakda ang SPDY na ito, magiging available ang Spf.</translation>
 <translation id="7384999953864505698">Pinapayagan ang QUIC protocol</translation>
 <translation id="7406651467768226499">Kung papayagan ba ang awtomatikong inilunsad na walang pagkaantalang kiosk app na kontrolin ang bersyon ng <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_fr.xtb b/components/policy/resources/policy_templates_fr.xtb
index 305ba480..b30d8a9 100644
--- a/components/policy/resources/policy_templates_fr.xtb
+++ b/components/policy/resources/policy_templates_fr.xtb
@@ -1950,7 +1950,6 @@
       Si cette règle n'est pas définie, le nettoyage automatique utilise la stratégie intégrée par défaut. Actuellement, il s'agit de la stratégie "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Conserver les cookies pendant toute la durée de la session</translation>
 <translation id="7340034977315324840">Indiquer les périodes d'activité de l'appareil</translation>
-<translation id="7381326101471547614">Désactiver l'utilisation du protocole SPDY dans <ph name="PRODUCT_NAME" />. Si cette règle est activée, le protocole SPDY ne sera pas disponible dans <ph name="PRODUCT_NAME" />. La désactivation de cette règle permet l'utilisation du protocole SPDY. En outre, si cette règle n'est pas définie, le protocole SPDY sera disponible.</translation>
 <translation id="7384999953864505698">Permet d'utiliser le protocole QUIC</translation>
 <translation id="7406651467768226499">Autoriser ou non l'application kiosque lancée automatiquement sans délai à contrôler la version de l'application <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_gu.xtb b/components/policy/resources/policy_templates_gu.xtb
index 0e8a8d7..e3a7d3d 100644
--- a/components/policy/resources/policy_templates_gu.xtb
+++ b/components/policy/resources/policy_templates_gu.xtb
@@ -1927,13 +1927,6 @@
       જો આ નીતિ સેટ કરેલ નથી, તો સ્વચલિત ક્લિન-અપ ડિફોલ્ટ બિલ્ટ-ઇન વ્યૂહરચનાનો ઉપયોગ કરે છે. હાલમાં, તે 'RemoveLRUIfDormant' વ્યૂહરચના છે.</translation>
 <translation id="7336878834592315572">સત્રની અવધિ માટે કૂકીઝ રાખો</translation>
 <translation id="7340034977315324840">ઉપરકણનાં પ્રવૃત્તિ સમયની જાણ કરો</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> માં SPDY પ્રોટોકોલનાં ઉપયોગને અક્ષમ કરે છે.
-
-      જો નીતિ સક્ષમ કરેલી છે, તો SPDY પ્રોટોકોલ <ph name="PRODUCT_NAME" /> માં ઉપલબ્ધ હશે નહીં.
-
-      આ નીતિ અક્ષમ પર સેટ કરવા પર SPDY નાં ઉપયોગને મંજૂરી આપશે.
-
-      જો આ નીતિ સેટ કરેલી નથી, તો SPDY ઉપલબ્ધ રહેશે.</translation>
 <translation id="7384999953864505698">QUIC પ્રોટોકોલને મંજૂરી આપે છે</translation>
 <translation id="7406651467768226499"><ph name="PRODUCT_OS_NAME" /> સંસ્કરણને નિયંત્રિત કરવા માટે શૂન્ય વિલંબ કિઓસ્ક ઍપ્લિકેશન સાથે સ્વતઃ લોંચની મંજૂરી આપવી કે કેમ.
 
diff --git a/components/policy/resources/policy_templates_hi.xtb b/components/policy/resources/policy_templates_hi.xtb
index 8a9cd8f..cb63630 100644
--- a/components/policy/resources/policy_templates_hi.xtb
+++ b/components/policy/resources/policy_templates_hi.xtb
@@ -1883,13 +1883,6 @@
       यदि यह नीति सेट नहीं है, तो स्वचालित क्लीन-अप डिफ़ॉल्ट अंतर्निहित कार्यनीति का उपयोग करता है. वर्तमान में, यह 'RemoveLRUIfDormant' कार्यनीति है.</translation>
 <translation id="7336878834592315572">सत्र की अवधि तक कुकी बनाए रखना</translation>
 <translation id="7340034977315324840">डिवाइस गतिविधि समय की रिपोर्ट करें</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> में SPDY प्रोटोकॉल के उपयोग को अक्षम करें.
-
-      यदि यह नीति सक्षम है, तो SPDY प्रोटोकॉल <ph name="PRODUCT_NAME" /> में उपलब्‍ध नहीं होगा.
-
-      इस नीति को अक्षम पर सेट करने से SPDY का उपयोग किया जा सकेगा.
-
-      यदि यह नीति बिना सेट किए छोड़ दी गई है, तो SPDY उपलब्ध होगा.</translation>
 <translation id="7384999953864505698">QUIC प्रोटोकॉल की अनुमति देती है</translation>
 <translation id="7406651467768226499"><ph name="PRODUCT_OS_NAME" /> वर्शन को नियंत्रित करने के लिए शून्य विलंब किओस्क ऐप वाले स्वत: लॉन्च को अनुमति दें या नहीं.
 
diff --git a/components/policy/resources/policy_templates_hr.xtb b/components/policy/resources/policy_templates_hr.xtb
index 43d34f4..6d2f0661 100644
--- a/components/policy/resources/policy_templates_hr.xtb
+++ b/components/policy/resources/policy_templates_hr.xtb
@@ -1791,7 +1791,6 @@
       Ako se to pravilo ne postavi, automatsko čišćenje upotrebljava zadanu ugrađenu strategiju. Ta je strategija trenutačno "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Zadrži kolačiće za vrijeme trajanja sesije</translation>
 <translation id="7340034977315324840">Izvješće o vremenima aktivnosti uređaja</translation>
-<translation id="7381326101471547614">Onemogućuje upotrebe protokola SPDY za uslugu <ph name="PRODUCT_NAME" />. Ako se to pravilo omogućuje, protokol SPDY neće biti dostupan za uslugu <ph name="PRODUCT_NAME" />. Onemogućavanjem ovog pravila dopustit će se upotreba protokola SPDY. Ako se to pravilo ne postavi, SPDY neće biti dostupan.</translation>
 <translation id="7384999953864505698">Omogući QUIC protokol</translation>
 <translation id="7406651467768226499">Određuje hoće li kiosk aplikacija pokrenuta automatski bez odgode upravljati verzijom proizvoda <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_hu.xtb b/components/policy/resources/policy_templates_hu.xtb
index 4397bf5..82967c5 100644
--- a/components/policy/resources/policy_templates_hu.xtb
+++ b/components/policy/resources/policy_templates_hu.xtb
@@ -1794,7 +1794,6 @@
       Ha a házirend nincs beállítva, akkor az automatikus tisztítás az alapértelmezett stratégiát használja. Ez jelenleg a „RemoveLRUIfDormant” stratégia.</translation>
 <translation id="7336878834592315572">Cookie-k megtartása a munkamenet idejére</translation>
 <translation id="7340034977315324840">Az eszköz aktív idejének jelentése</translation>
-<translation id="7381326101471547614">Letiltja az SPDY protokoll használatát a(z) <ph name="PRODUCT_NAME" /> termékben. Ha ez a házirend engedélyezve van, akkor az SPDY protokoll nem lesz elérhető a(z) <ph name="PRODUCT_NAME" /> termékben. E házirend kikapcsolása lehetővé teszi az SPDY használatát. Ha ez a házirend beállítatlanul marad, az SPDY elérhető lesz.</translation>
 <translation id="7384999953864505698">Engedélyezi a QUIC-protokollt</translation>
 <translation id="7406651467768226499">Annak meghatározása, hogy a késés nélkül, automatikusan elindított kioszkalkalmazás irányítsa-e a <ph name="PRODUCT_OS_NAME" /> verzióját.
 
diff --git a/components/policy/resources/policy_templates_id.xtb b/components/policy/resources/policy_templates_id.xtb
index c6ded44..1f92ccff 100644
--- a/components/policy/resources/policy_templates_id.xtb
+++ b/components/policy/resources/policy_templates_id.xtb
@@ -1246,7 +1246,7 @@
 
       Jika kebijakan ini tidak disetel, frekuensi defaultnya adalah 3 menit.
       Frekuensi minimum adalah 30 detik dan maksimum 24 jam - nilai
-      di luar rentang ini akan dimasukkan dalam rentang ini.</translation>
+      di luar rentang ini akan dimasukkan ke rentang ini.</translation>
 <translation id="5535973522252703021">Daftar putih server delegasi Kerberos</translation>
 <translation id="5560039246134246593">Menambahkan parameter ke pengambilan bibit Variasi di <ph name="PRODUCT_NAME" />.
 
@@ -1796,7 +1796,6 @@
       Jika kebijakan ini tidak disetel, pembersihan otomatis menggunakan strategi yang tertanam secara default. Saat ini, itu adalah strategi 'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">Menyimpan cookie selama durasi sesi</translation>
 <translation id="7340034977315324840">Laporkan waktu aktivitas perangkat</translation>
-<translation id="7381326101471547614">Menonaktifkan penggunaan protokol SPDY di <ph name="PRODUCT_NAME" />. Jika kebijakan ini diaktifkan, protokol SPDY tidak akan tersedia di <ph name="PRODUCT_NAME" />. Menyetel kebijakan ini sebagai dinonaktifkan akan mengizinkan penggunaan SPDY. Jika kebijakan ini tidak disetel, SPDY akan tersedia.</translation>
 <translation id="7384999953864505698">Memungkinkan protokol QUIC</translation>
 <translation id="7406651467768226499">Mengizinkan peluncuran otomatis dengan aplikasi kios tanpa penundaan untuk mengontrol versi <ph name="PRODUCT_OS_NAME" /> atau tidak.
 
diff --git a/components/policy/resources/policy_templates_it.xtb b/components/policy/resources/policy_templates_it.xtb
index 55edd5e..d722891 100644
--- a/components/policy/resources/policy_templates_it.xtb
+++ b/components/policy/resources/policy_templates_it.xtb
@@ -1748,7 +1748,6 @@
       Se questa norma non viene impostata, la pulizia automatica utilizza la strategia incorporata predefinita, che al momento è "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Conserva cookie per tutta la durata della sessione</translation>
 <translation id="7340034977315324840">Indicazione tempi di attività del dispositivo</translation>
-<translation id="7381326101471547614">Consente di disattivare l'utilizzo del protocollo SPDY in <ph name="PRODUCT_NAME" />. Se questa norma viene attivata, il protocollo SPDY non sarà disponibile in <ph name="PRODUCT_NAME" />. Se la norma viene disattivata sarà possibile utilizzare il protocollo. Se la norma non viene impostata, il protocollo SPDY sarà disponibile.</translation>
 <translation id="7384999953864505698">Consente il protocollo QUIC</translation>
 <translation id="7406651467768226499">Consenti o meno all'app kiosk avviata automaticamente senza ritardo di controllare la versione di <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_iw.xtb b/components/policy/resources/policy_templates_iw.xtb
index 8254761..cb66e6d3 100644
--- a/components/policy/resources/policy_templates_iw.xtb
+++ b/components/policy/resources/policy_templates_iw.xtb
@@ -1233,8 +1233,8 @@
 <translation id="5535957389335373033">תדירות השליחה של מנות רשת לניטור, באלפיות השנייה.
 
       אם מדיניות זו אינה מוגדרת, תדירות ברירת המחדל היא 3 דקות. התדירות המינימלית היא 30
-      שניות והתדירות המקסימלית היא 24 שעות - ערכים הנמצאים מחוץ לטווח זה יוחלפו בערכים
-      התואמים טווח זה.</translation>
+      שניות והתדירות המקסימלית היא 24 שעות - ערכים שנמצאים מחוץ לטווח הזה יוחלפו בערכים
+      שתואמים את הטווח זה.</translation>
 <translation id="5535973522252703021">‏רשימת היתרים של שרת האצלה של Kerberos</translation>
 <translation id="5560039246134246593">‏הוסף פרמטר לאחזור של Seed הווריאציות ב-<ph name="PRODUCT_NAME" />.
 
@@ -1770,7 +1770,6 @@
       אם המדיניות הזו אינה מוגדרת, הניקוי האוטומטי עושה שימוש באסטרטגיה המובנית המוגדרת כברירת מחדל. נכון לעכשיו, זוהי אסטרטגיית 'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">‏שמור את קובצי ה-Cookie לכל משך ההפעלה.</translation>
 <translation id="7340034977315324840">דווח על זמני הפעילות של המכשיר</translation>
-<translation id="7381326101471547614">‏משבית את השימוש בפרוטוקול SPDY ב-‏<ph name="PRODUCT_NAME" />. אם תאפשר מדיניות זו, פרוטוקול SPDY לא יהיה זמין ב-‏<ph name="PRODUCT_NAME" />. הגדרת מדיניות זו כמושבתת תאפשר את השימוש ב-SPDY‏. אם לא תוגדר מדיניות זו, SPDY יהיה זמין.</translation>
 <translation id="7384999953864505698">‏הפעלה של פרוטוקול QUIC</translation>
 <translation id="7406651467768226499">‏האם להתיר ליישום הקיוסק המופעל באופן אוטומטי ללא השהייה לקבוע את הגירסה של <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_ja.xtb b/components/policy/resources/policy_templates_ja.xtb
index 1fce5d2..2706fbf 100644
--- a/components/policy/resources/policy_templates_ja.xtb
+++ b/components/policy/resources/policy_templates_ja.xtb
@@ -1789,13 +1789,6 @@
       このポリシーが設定されていない場合、自動クリーンアップは組み込みのデフォルト設定を使用します。現在、この設定は「RemoveLRUIfDormant」です。</translation>
 <translation id="7336878834592315572">セッションの継続中は Cookie を保存する</translation>
 <translation id="7340034977315324840">デバイス操作時間を報告する</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> での SPDY プロトコルの使用を無効にします。
-
-      このポリシーが有効になっている場合、<ph name="PRODUCT_NAME" /> で SPDY プロトコルを使用できません。
-
-      このポリシーが無効になっている場合、SPDY プロトコルを使用できます。
-
-      このポリシーが未設定の場合、SPDY プロトコルを使用できます。</translation>
 <translation id="7384999953864505698">QUIC プロトコルを許可する</translation>
 <translation id="7406651467768226499">遅延なしで自動開始されるキオスクアプリから <ph name="PRODUCT_OS_NAME" /> のバージョンを制御できるようにするかどうかを設定します。
 
diff --git a/components/policy/resources/policy_templates_kn.xtb b/components/policy/resources/policy_templates_kn.xtb
index 9bb4522..351e501 100644
--- a/components/policy/resources/policy_templates_kn.xtb
+++ b/components/policy/resources/policy_templates_kn.xtb
@@ -1782,7 +1782,6 @@
       ಈ ನೀತಿಯನ್ನು ಹೊಂದಿಸದೇ ಬಿಟ್ಟರೆ, ಡಿಫಾಲ್ಟ್ ಬಿಲ್ಟ್-ಇನ್ ಕಾರ್ಯತಂತ್ರವನ್ನು ಸ್ವಯಂಚಾಲಿತ ಕ್ಲೀನ್-ಅಪ್ ಬಳಸುತ್ತದೆ. ಸದ್ಯಕ್ಕೆ, ಇದು 'RemoveLRUIfDormant' ಕಾರ್ಯತಂತ್ರವಾಗಿದೆ.</translation>
 <translation id="7336878834592315572">ಸೆಶನ್‌ನ ಸಮಯದಲ್ಲಿ ಕುಕೀಗಳನ್ನು ಇರಿಸಿ</translation>
 <translation id="7340034977315324840">ಸಾಧನ ಚಟುವಟಿಕೆಯ ಸಮಯವನ್ನು ವರದಿಮಾಡಿ</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> SPDY ಪ್ರೋಟೊಕಾಲ್‌ನ ಬಳಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ ಈ ನೀತಿಯನ್ನು SPDY ಪ್ರೋಟೊಕಾಲ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸದಿದ್ದರೆ <ph name="PRODUCT_NAME" /> ರಲ್ಲಿ ಲಭ್ಯವಿರುವುದಿಲ್ಲ. ಈ ನೀತಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿರುವುದಕ್ಕೆ ಹೊಂದಿಸುವ ಮೂಲಕ SPDY ನ ಬಳಕೆಯನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ಈ ನೀತಿಯನ್ನು ಹೊಂದಿಸದೆ ಬಿಟ್ಟರೆ, SPDY ಲಭ್ಯವಾಗುತ್ತದೆ.</translation>
 <translation id="7384999953864505698">QUIC ಪ್ರೊಟೋಕಾಲ್ ಅನುಮತಿಸುತ್ತದೆ</translation>
 <translation id="7406651467768226499"><ph name="PRODUCT_OS_NAME" /> ಆವೃತ್ತಿಯನ್ನು ನಿಯಂತ್ರಿಸಲು ಸ್ವಯಂ ಪ್ರಾರಂಭಗೊಂಡ ಶೂನ್ಯ ವಿಳಂಬದ ಕಿಯೋಸ್ಕ್‌ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುವುದೇ.
 
diff --git a/components/policy/resources/policy_templates_ko.xtb b/components/policy/resources/policy_templates_ko.xtb
index 8d312e0e..4054473 100644
--- a/components/policy/resources/policy_templates_ko.xtb
+++ b/components/policy/resources/policy_templates_ko.xtb
@@ -1929,13 +1929,6 @@
       이 정책을 설정하지 않으면 자동 정리는 기본 전략을 사용합니다. 현재 기본 전략은 'RemoveLRUIfDormant'입니다.</translation>
 <translation id="7336878834592315572">세션이 지속되는 동안 쿠키를 유지합니다.</translation>
 <translation id="7340034977315324840">기기 활동 시간 보고</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" />에서 SPDY 프로토콜을 사용 중지합니다.
-
-      이 정책을 사용하면 <ph name="PRODUCT_NAME" />에서 SPDY 프로토콜을 사용할 수 없습니다.
-
-      이 정책을 사용하지 않도록 설정하면 SPDY 사용이 허용됩니다.
-
-      이 정책을 설정하지 않으면 SPDY를 사용할 수 있습니다.</translation>
 <translation id="7384999953864505698">QUIC 프로토콜 허용</translation>
 <translation id="7406651467768226499">지연 없이 자동 실행된 키오스크 앱에서 <ph name="PRODUCT_OS_NAME" /> 버전을 제어하도록 허용할지 여부
 
diff --git a/components/policy/resources/policy_templates_lt.xtb b/components/policy/resources/policy_templates_lt.xtb
index 3fabda8b..5adcd05f 100644
--- a/components/policy/resources/policy_templates_lt.xtb
+++ b/components/policy/resources/policy_templates_lt.xtb
@@ -1942,13 +1942,6 @@
       Jei ši politika nenustatyta, automatinis išvalymas naudos numatytąją įdiegtą strategiją. Šiuo metu tai strategija „RemoveLRUIfDormant“.</translation>
 <translation id="7336878834592315572">Išsaugoti slapukus vykstant sesijai</translation>
 <translation id="7340034977315324840">Pranešti įrenginio veiklos laiką</translation>
-<translation id="7381326101471547614">SPDY protokolas bus neleidžiamas naudoti „<ph name="PRODUCT_NAME" />“.
-
-      Jei ši politika įgalinta, SPDY protokolas nebus galimas „<ph name="PRODUCT_NAME" />“.
-
-      Nustačius, kad ši politika neleidžiama, bus galima naudoti SPDY.
-
-      Jei politika palikta nenustatyta, SPDY bus galima naudoti.</translation>
 <translation id="7384999953864505698">Leidžiamas protokolas QUIC</translation>
 <translation id="7406651467768226499">Ar automatiškai be delsos paleistai viešojo terminalo programai bus leidžiama valdyti „<ph name="PRODUCT_OS_NAME" />“ versiją.
 
diff --git a/components/policy/resources/policy_templates_lv.xtb b/components/policy/resources/policy_templates_lv.xtb
index 58572ebf..8017434 100644
--- a/components/policy/resources/policy_templates_lv.xtb
+++ b/components/policy/resources/policy_templates_lv.xtb
@@ -1931,13 +1931,6 @@
       Ja šī politika nav iestatīta, automātiskajai tīrīšanai tiks izmantota noklusējuma tīrīšanas stratēģija. Pašlaik tā ir stratēģija “RemoveLRUIfDormant”.</translation>
 <translation id="7336878834592315572">Sīkfailu saglabāšana sesijas laikā</translation>
 <translation id="7340034977315324840">Ziņot par ierīces darbības laikiem</translation>
-<translation id="7381326101471547614">Atspējo SPDY protokola lietošanu pakalpojumā <ph name="PRODUCT_NAME" />.
-
-      Ja šī politika ir iespējota, SPDY protokols nav pieejams pakalpojumā <ph name="PRODUCT_NAME" />.
-
-      Atspējojot šo politiku, SPDY lietošana būs atļauta.
-
-      Ja šī politika nav iestatīta, SPDY būs pieejams.</translation>
 <translation id="7384999953864505698">Atļauja lietot QUIC protokolu</translation>
 <translation id="7406651467768226499">Atļauja kioska lietotnei, kas tiek automātiski palaista ar nulles aizkavi, kontrolēt <ph name="PRODUCT_OS_NAME" /> versiju.
 
diff --git a/components/policy/resources/policy_templates_ml.xtb b/components/policy/resources/policy_templates_ml.xtb
index 02570f6..63f5ee65 100644
--- a/components/policy/resources/policy_templates_ml.xtb
+++ b/components/policy/resources/policy_templates_ml.xtb
@@ -1952,13 +1952,6 @@
       ഈ നയം സജ്ജമാക്കുന്നില്ലെങ്കിൽ, യാന്ത്രിക ക്ലീൻഅപ്പ് സ്ഥിരമായ അന്തർനിർമ്മിത രീതി ഉപയോഗിക്കുന്നു. നിലവിൽ ഇത് 'RemoveLRUIfDormant രീതിയാണ് പിന്തുടരുന്നത്.</translation>
 <translation id="7336878834592315572">സെഷന്റെ ദൈർഘ്യത്തിനായി കുക്കികൾ നിലനിർത്തുക</translation>
 <translation id="7340034977315324840">ഉപകരണ പ്രവർത്തന സമയങ്ങൾ റിപ്പോർട്ടുചെയ്യുക</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> എന്നതിലെ SPDY പ്രോട്ടോക്കോളിന്റെ ഉപയോഗം അപ്രാപ്‌തമാക്കുന്നു.
-
-      ഈ നയം പ്രാപ്‌തമാക്കുകയാണെങ്കിൽ SPDY പ്രോട്ടോക്കോൾ <ph name="PRODUCT_NAME" /> എന്നതിൽ ലഭ്യമാകില്ല.
-
-     ഈ നയം അപ്രാപ്‌തമാക്കുന്നതിലേക്ക് ക്രമീകരിക്കുന്നത് SPDY ഉപയോഗം അനുവദിക്കും.
-
-      ഈ നയത്തെ സജ്ജമാക്കാതെ വിട്ടാൽ, SPDY ലഭ്യമാകും.</translation>
 <translation id="7384999953864505698">QUIC പ്രോട്ടോക്കോൾ അനുവദിക്കുന്നു</translation>
 <translation id="7406651467768226499"><ph name="PRODUCT_OS_NAME" /> പതിപ്പ് നിയന്ത്രിക്കുന്നതിന്, കാലതാമസമില്ലാതെ കിയോസ്‌ക് അപ്ലിക്കേഷൻ സ്വയം സമാരംഭിക്കുന്നതിന് അനുവദിക്കണോ വേണ്ടയോ എന്ന് തീരുമാനിക്കുക.
 
diff --git a/components/policy/resources/policy_templates_mr.xtb b/components/policy/resources/policy_templates_mr.xtb
index 5b2a65be..73379a0 100644
--- a/components/policy/resources/policy_templates_mr.xtb
+++ b/components/policy/resources/policy_templates_mr.xtb
@@ -947,7 +947,7 @@
 
           सेट केलेले नसल्यास किंवा असत्य वर सेट केले असल्यास, वापरकर्ते Google ड्राइव्ह वर फायली स्थानांतरित करण्यासाठी सक्षम होतील.</translation>
 <translation id="3915395663995367577">प्रॉक्सी .pac फायलीची URL</translation>
-<translation id="3939893074578116847">डिव्‍हाइस ऑफलाइन आहे किंवा नाही ते शोधण्‍याची सर्व्हरला अनुमती  देण्‍यासाठी ऑनलाइन स्थितीचे परीक्षण
+<translation id="3939893074578116847">डिव्‍हाइस ऑफलाइन आहे किंवा नाही ते शोधण्‍याची सर्व्हरला अनुमती देण्‍यासाठी ऑनलाइन स्थितीचे परीक्षण
       करण्‍याकरिता नेटवर्क पॅकेट व्यवस्थापन सर्व्हरकडे पाठवा.
 
       हे धोरण सत्य वर सेट केल्‍यास, नेटवर्क पॅकेटचे परीक्षण (<ph name="HEARTBEATS_TERM" /> म्हणविले जाणारे) पाठविले जातील.
@@ -1901,13 +1901,6 @@
       हे धोरण सेट केलेले नसल्यास, स्वयंचलित साफ करणे डीफॉल्ट अंगभूत तंत्रकौशल्य वापरते. सध्या, हे 'RemoveLRUIfDormant' तंत्रकौशल्य आहे.</translation>
 <translation id="7336878834592315572">सत्राच्या कालावधीसाठी कुकीज ठेवा</translation>
 <translation id="7340034977315324840">डिव्हाइस क्रियाकलाप वेळांचा अहवाल द्या</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> मध्‍ये SPDY प्रोटोकॉलचा वापर अक्षम करते.
-
-      हे धोरण सक्षम करण्‍यात आल्यास <ph name="PRODUCT_NAME" /> मध्‍ये SPDY प्रोटोकॉल उपलब्ध नसेल.
-
-      हे धोरण अक्षम वर सेट केल्याने SPDY च्या वापरास अनुमती मिळेल.
-
-      हे धोरण सेट न करता सोडल्यास, SPDY उपलब्ध असेल.</translation>
 <translation id="7384999953864505698">QUIC प्रोटोकॉलला अनुमती देते</translation>
 <translation id="7406651467768226499">विलंब न होणाऱ्या कियोस्क अॅपसह स्वयं लाँच केलेली <ph name="PRODUCT_OS_NAME" /> आवृत्ती नियंत्रित करण्याची अनुमती द्यायची किंवा नाही.
 
diff --git a/components/policy/resources/policy_templates_ms.xtb b/components/policy/resources/policy_templates_ms.xtb
index 859473b..4e47aa0 100644
--- a/components/policy/resources/policy_templates_ms.xtb
+++ b/components/policy/resources/policy_templates_ms.xtb
@@ -1944,7 +1944,6 @@
       Jika dasar ini tidak ditetapkan, pembersihan autimatik menggunakan strategi terbina dalam lalai. Pada masa ini, itu adalah strategi 'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">Simpan kuki sepanjang tempoh sesi</translation>
 <translation id="7340034977315324840">Laporkan masa aktiviti peranti</translation>
-<translation id="7381326101471547614">Melumpuhkan penggunaan protokol SPDY dalam <ph name="PRODUCT_NAME" />. Jika dasar ini didayakan, protokol SPDY tidak akan tersedia dalam <ph name="PRODUCT_NAME" />. Menetapkan dasar ini kepada dilumpuhkan akan membolehkan penggunaan SPDY. Jika dasar ini dibiarkan tanpa ditetapkan, SPDY akan tersedia.</translation>
 <translation id="7384999953864505698">Membenarkan protokol QUIC</translation>
 <translation id="7406651467768226499">Sama ada hendak membenarkan apl kios kelewatan sifar yang dilancarkan secara automatik untuk mengawal versi <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_nl.xtb b/components/policy/resources/policy_templates_nl.xtb
index 685fd51..529df37 100644
--- a/components/policy/resources/policy_templates_nl.xtb
+++ b/components/policy/resources/policy_templates_nl.xtb
@@ -1926,7 +1926,6 @@
       Als dit beleid niet wordt ingesteld, gebruikt de automatische opschoonfunctie de standaard ingebouwde strategie. Momenteel is dit de strategie'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">Cookies bewaren voor de duur van de sessie</translation>
 <translation id="7340034977315324840">Tijdsduur van apparaatgebruik melden</translation>
-<translation id="7381326101471547614">Hiermee wordt het gebruik van het SPDY-protocol in <ph name="PRODUCT_NAME" /> uitgeschakeld. Als dit beleid is ingeschakeld, is het SPDY-protocol niet beschikbaar in <ph name="PRODUCT_NAME" />. Als je dit beleid instelt op uitgeschakeld, kan het SPDY-protocol worden gebruikt. Als dit beleid niet wordt ingesteld, is het SPDY-protocol beschikbaar.</translation>
 <translation id="7384999953864505698">QUIC-protocol toestaan</translation>
 <translation id="7406651467768226499">Of de kiosk-app die automatisch zonder vertraging is gestart, de <ph name="PRODUCT_OS_NAME" />-versie mag beheren.
 
diff --git a/components/policy/resources/policy_templates_no.xtb b/components/policy/resources/policy_templates_no.xtb
index 1c93cdd..a434b446 100644
--- a/components/policy/resources/policy_templates_no.xtb
+++ b/components/policy/resources/policy_templates_no.xtb
@@ -1889,13 +1889,6 @@
       Hvis denne innstillingen ikke angis, tar automatisk opprydding i bruk den innebygde standardstrategien. For øyeblikket er det «RemoveLRUIfDormant»-strategien.</translation>
 <translation id="7336878834592315572">Behold informasjonskapsler så lenge økten varer</translation>
 <translation id="7340034977315324840">Rapportering av aktivitetstider for enhet</translation>
-<translation id="7381326101471547614">Deaktiverer bruk av SPDY-protokollen i <ph name="PRODUCT_NAME" />.
-
-      Hvis disse retningslinjene er aktivert, blir ikke SPDY-protokollen tilgjengelig i <ph name="PRODUCT_NAME" />.
-
-      Deaktivering av disse retningslinjene tillater bruk av SPDY.
-
-      Hvis disse retningslinjene ikke angis, blir SPDY tilgjengelig.</translation>
 <translation id="7384999953864505698">Tillater QUIC-protokollen</translation>
 <translation id="7406651467768226499">Spesifiserer om den automatisk startede kioskappen uten forsinkelse skal kunne kontrollere <ph name="PRODUCT_OS_NAME" />-versjonen.
 
diff --git a/components/policy/resources/policy_templates_pl.xtb b/components/policy/resources/policy_templates_pl.xtb
index 3bcf7b8df..4dd40f8 100644
--- a/components/policy/resources/policy_templates_pl.xtb
+++ b/components/policy/resources/policy_templates_pl.xtb
@@ -1786,7 +1786,6 @@
       Jeśli nie ustawisz tej zasady, funkcja automatycznego czyszczenia korzysta z domyślnej wbudowanej strategii. Obecnie to „RemoveLRUIfDormant”.</translation>
 <translation id="7336878834592315572">Zachowaj pliki cookie na czas trwania sesji</translation>
 <translation id="7340034977315324840">Zgłoś godziny aktywności urządzenia</translation>
-<translation id="7381326101471547614">Wyłącza protokół SPDY w <ph name="PRODUCT_NAME" />. Po włączeniu tej zasady protokół SPDY jest niedostępny w <ph name="PRODUCT_NAME" />. W przeciwnym razie protokołu można używać. Jeśli zasada nie zostanie ustawiona, protokół SPDY będzie dostępny.</translation>
 <translation id="7384999953864505698">Zezwala na protokół QUIC</translation>
 <translation id="7406651467768226499">Czy zezwolić aplikacji kiosku uruchamianej automatycznie z zerowym opóźnieniem na kontrolowanie wersji <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_pt-BR.xtb b/components/policy/resources/policy_templates_pt-BR.xtb
index e6c99784..d0c3d8a1 100644
--- a/components/policy/resources/policy_templates_pt-BR.xtb
+++ b/components/policy/resources/policy_templates_pt-BR.xtb
@@ -1772,7 +1772,6 @@
       Se esta política não for configurada, a limpeza automática usa a estratégia integrada padrão, que atualmente é a estratégia "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Manter cookies enquanto durar a sessão</translation>
 <translation id="7340034977315324840">Informar horário das atividades do dispositivo</translation>
-<translation id="7381326101471547614">Desativa o uso do protocolo SPDY no <ph name="PRODUCT_NAME" />. Se essa política estiver ativada, o protocolo SPDY não estará disponível no <ph name="PRODUCT_NAME" />. A configuração dessa política para desativada permitirá o uso do SPDY. Se essa política for deixada sem configuração, o SPDY estará disponível.</translation>
 <translation id="7384999953864505698">Permite o protocolo QUIC</translation>
 <translation id="7406651467768226499">Permitir que o app em Kiosk aberto automaticamente com zero de atraso controle a versão do <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_pt-PT.xtb b/components/policy/resources/policy_templates_pt-PT.xtb
index e990f27..e298f159 100644
--- a/components/policy/resources/policy_templates_pt-PT.xtb
+++ b/components/policy/resources/policy_templates_pt-PT.xtb
@@ -1796,7 +1796,6 @@
       Se esta política não estiver definida, a limpeza automática utiliza a estratégia integrada predefinida. Atualmente, é a estratégia "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Manter cookies durante toda a sessão</translation>
 <translation id="7340034977315324840">Comunicar períodos de atividade do aparelho</translation>
-<translation id="7381326101471547614">Desativa a utilização do protocolo SPDY em <ph name="PRODUCT_NAME" />. Se esta política estiver ativada, o protocolo SPDY não estará disponível em <ph name="PRODUCT_NAME" />. A desativação desta política permitirá a utilização do protocolo SPDY. Se esta política não for definida, o protocolo SPDY estará disponível.</translation>
 <translation id="7384999953864505698">Permite o protocolo QUIC</translation>
 <translation id="7406651467768226499">Permitir ou não que a aplicação de quiosque de início automático com atraso zero controle a versão do <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_ro.xtb b/components/policy/resources/policy_templates_ro.xtb
index 98c696f..fdea796 100644
--- a/components/policy/resources/policy_templates_ro.xtb
+++ b/components/policy/resources/policy_templates_ro.xtb
@@ -1814,7 +1814,6 @@
       Dacă politica nu este setată, curățarea automată utilizează strategia încorporată în mod prestabilit. În prezent, aceasta este strategia „RemoveLRUIfDormant”.</translation>
 <translation id="7336878834592315572">Păstrați cookie-urile pe durata sesiunii</translation>
 <translation id="7340034977315324840">Raportați perioadele de activitate ale dispozitivului</translation>
-<translation id="7381326101471547614">Dezactivează utilizarea protocolul SPDY în <ph name="PRODUCT_NAME" />. Dacă această politică este activată, protocolul SPDY nu va fi disponibil în <ph name="PRODUCT_NAME" />. Dezactivarea acestei politici va permite utilizarea protocolului SPDY. Dacă această politică rămâne nesetată, SPDY va fi disponibil.</translation>
 <translation id="7384999953864505698">Permite protocolul QUIC</translation>
 <translation id="7406651467768226499">Dacă aplicația chioșc lansată automat fără nicio întârziere poate să controleze versiunea <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_ru.xtb b/components/policy/resources/policy_templates_ru.xtb
index 1e958a2..4c859c6d 100644
--- a/components/policy/resources/policy_templates_ru.xtb
+++ b/components/policy/resources/policy_templates_ru.xtb
@@ -1767,7 +1767,6 @@
       Если значение не задано, будет использоваться режим очистки по умолчанию. В настоящий момент это RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Хранить файлы cookie до конца сеанса</translation>
 <translation id="7340034977315324840">Сообщать о продолжительности работы устройства</translation>
-<translation id="7381326101471547614">Данная политика отключает использование в <ph name="PRODUCT_NAME" /> протокола SPDY. Если она включена, этот протокол будет недоступен в <ph name="PRODUCT_NAME" />. Его можно будет использовать, если не настраивать эту политику или отключить ее.</translation>
 <translation id="7384999953864505698">Разрешает использование протокола QUIC</translation>
 <translation id="7406651467768226499">Разрешает киоск-приложению, которое запускается автоматически и без задержек, управлять версией <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_sk.xtb b/components/policy/resources/policy_templates_sk.xtb
index 043c96d..bb9fa34 100644
--- a/components/policy/resources/policy_templates_sk.xtb
+++ b/components/policy/resources/policy_templates_sk.xtb
@@ -1924,7 +1924,6 @@
       Ak sa toto pravidlo nenastaví, automatické čistenie použije predvolenú vstavanú stratégiu, ktorá v súčasnosti predstavuje stratégiu RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Uchovať súbory cookie počas trvania relácie</translation>
 <translation id="7340034977315324840">Hlásiť časy aktivity zariadenia</translation>
-<translation id="7381326101471547614">Zakáže v prehliadači <ph name="PRODUCT_NAME" /> použitie protokolu SPDY. Ak je toto pravidlo povolené, protokol SPDY nebude v prehliadači <ph name="PRODUCT_NAME" /> k dispozícii. Zakázaním tohto pravidla použitie protokolu SPDY umožníte. Ak toto pravidlo ponecháte nenastavené, protokol SPDY bude k dispozícii.</translation>
 <translation id="7384999953864505698">Povolenie protokolu QUIC</translation>
 <translation id="7406651467768226499">Ovláda, či má byť povolené verejnej aplikácii, ktorá sa spúšťa automaticky s nulovým oneskorením, ovládať verziu systému <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_sl.xtb b/components/policy/resources/policy_templates_sl.xtb
index d8c416f..cace885 100644
--- a/components/policy/resources/policy_templates_sl.xtb
+++ b/components/policy/resources/policy_templates_sl.xtb
@@ -1941,13 +1941,6 @@
       Če ta pravilnik ni nastavljen, samodejno čiščenje uporablja privzeto vgrajeno strategijo. Trenutno je to strategija »RemoveLRUIfDormant«.</translation>
 <translation id="7336878834592315572">Ohrani piškotke za obdobje trajanja seje</translation>
 <translation id="7340034977315324840">Pošiljanje podatkov o času dejavnosti v napravi</translation>
-<translation id="7381326101471547614">Onemogoči uporabo protokola SPDY v programu <ph name="PRODUCT_NAME" />.
-
-      Če je ta pravilnik omogočen, protokol SPDY v programu <ph name="PRODUCT_NAME" /> ne bo na voljo.
-
-      Če je pravilnik onemogočen, bo uporaba protokola SPDY na voljo.
-
-      Če pravilnik ni nastavljen, bo protokol SPDY na voljo.</translation>
 <translation id="7384999953864505698">Dovoli protokol QUIC</translation>
 <translation id="7406651467768226499">Ali naj se samodejno zagnani aplikaciji za kiosk brez zamika dovoli nadzor nad različico sistema <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_sr.xtb b/components/policy/resources/policy_templates_sr.xtb
index 1d2101d..a6adde7f 100644
--- a/components/policy/resources/policy_templates_sr.xtb
+++ b/components/policy/resources/policy_templates_sr.xtb
@@ -1919,13 +1919,6 @@
       Ако не подесите ове смернице, аутоматско брисање користи подразумевану уграђену стратегију. За сада је та стратегија „RemoveLRUIfDormant“.</translation>
 <translation id="7336878834592315572">Чувај колачиће током трајања сесије</translation>
 <translation id="7340034977315324840">Пријављивање времена активности на уређају</translation>
-<translation id="7381326101471547614">Онемогућавају коришћење SPDY протокола у <ph name="PRODUCT_NAME" />-у.
-
-      Ако се ове смернице омогуће, SPDY протокол неће бити доступан у <ph name="PRODUCT_NAME" />-у.
-
-      Ако онемогућите ове смернице, омогућићете коришћење SPDY протокола.
-
-      Ако не подесите ове смернице, SPDY ће бити доступан.</translation>
 <translation id="7384999953864505698">Омогућавају QUIC протокол</translation>
 <translation id="7406651467768226499">Контролише да ли ће киоск апликација која је аутоматски покренута без кашњења имати дозволу да контролише верзију <ph name="PRODUCT_OS_NAME" />-а.
 
diff --git a/components/policy/resources/policy_templates_sv.xtb b/components/policy/resources/policy_templates_sv.xtb
index 6d3fa35..266229e7 100644
--- a/components/policy/resources/policy_templates_sv.xtb
+++ b/components/policy/resources/policy_templates_sv.xtb
@@ -1946,13 +1946,6 @@
       Om policyn inte har angetts används den inbyggda strategin av den automatiska rensningen. För närvarande är det strategin RemoveLRUIfDormant.</translation>
 <translation id="7336878834592315572">Behåll cookies under hela sessionen</translation>
 <translation id="7340034977315324840">Rapportera aktivitetstider för enhet</translation>
-<translation id="7381326101471547614">Inaktiverar användning av SPDY-protokollet i <ph name="PRODUCT_NAME" />.
-
-      Om den här policyn är aktiverad är SPDY-protokollet inte tillgängligt i <ph name="PRODUCT_NAME" />.
-
-      Om den här policyn inaktiveras kan SPDY användas.
-
-      Om den här policyn inte anges kommer SPDY att bli tillgängligt.</translation>
 <translation id="7384999953864505698">Tillåter QUIC-protokoll</translation>
 <translation id="7406651467768226499">Tillåta eller inte tillåta att kioskappen som startas automatiskt utan fördröjning styr <ph name="PRODUCT_OS_NAME" />-versionen.
 
diff --git a/components/policy/resources/policy_templates_sw.xtb b/components/policy/resources/policy_templates_sw.xtb
index 814631f..5a55224 100644
--- a/components/policy/resources/policy_templates_sw.xtb
+++ b/components/policy/resources/policy_templates_sw.xtb
@@ -1905,13 +1905,6 @@
       Ikiwa sera hii haitawekwa, kufuta kiotomatiki hutumia mkakati wa chaguo-msingi uliojengwa ndani. Kwa sasa, ni mkakati wa 'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">Weka vidakuzi katika muda wa kipindi</translation>
 <translation id="7340034977315324840">Ripoti muda wa shughuli za kifaa</translation>
-<translation id="7381326101471547614">Inalemaza matumizi ya itifaki ya SPDY katika <ph name="PRODUCT_NAME" />.
-
-      Ikiwa sera hii itawezeshwa itifaki ya SPDY haitapatikana katika <ph name="PRODUCT_NAME" />.
-
-      Kuweka sera hii katika kulemazwa kutaruhusu matumizi ya SPDY.
-
-      Ikiwa sera hii itaachwa bila kuwekwa, SPDY itapatikana.</translation>
 <translation id="7384999953864505698">Huruhusu itifaki ya QUIC</translation>
 <translation id="7406651467768226499">Kuruhusu au kutoruhusu kipengele kilichofunguliwa kiotomatiki bila chochote kuchelewesha programu inayotumia skrini nzima kudhibiti toleo la <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_ta.xtb b/components/policy/resources/policy_templates_ta.xtb
index 9318d9e..11ad6788 100644
--- a/components/policy/resources/policy_templates_ta.xtb
+++ b/components/policy/resources/policy_templates_ta.xtb
@@ -1778,7 +1778,6 @@
       இந்தக் கொள்கை அமைக்கப்படவில்லை எனில், தன்னியக்க சுத்தப்படுத்தலானது இயல்புநிலையாக கட்டமைக்கப்பட்ட உத்தியைப் பயன்படுத்தும். தற்போது இதுவே இயல்புநிலை 'RemoveLRUIfDormant' நுட்பம் ஆகும்.</translation>
 <translation id="7336878834592315572">அமர்வு காலத்திற்கான குக்கீகளை வைத்திரு</translation>
 <translation id="7340034977315324840">சாதனத்தின் செயல்பாட்டு நேரங்களை அறிக்கையிடவும்</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> இல் உள்ள SPDY நெறிமுறையின் பயன் முடக்கப்பட்டுள்ளது. இந்தக் கொள்கை இயக்கப்பட்டால் SPDY நெறிமுறை <ph name="PRODUCT_NAME" /> இல் கிடைக்காது. இந்தக் கொள்கை அமைப்பை முடக்கினால்,  SPDY  பயன்பாடு அனுமதிக்கப்படும். இந்தக் கொள்கை அமைக்கப்படவில்லையென்றால்,  SPDY கிடைக்காது.</translation>
 <translation id="7384999953864505698">QUIC நெறிமுறையை அனுமதிக்கும்</translation>
 <translation id="7406651467768226499"><ph name="PRODUCT_OS_NAME" /> பதிப்பைக் கட்டுப்படுத்த, தாமதமின்றி தானாகத் துவங்கும் கியோஸ்க் பயன்பாட்டை அனுமதிக்க வேண்டுமா என்பது பற்றிய கொள்கை.
 
diff --git a/components/policy/resources/policy_templates_te.xtb b/components/policy/resources/policy_templates_te.xtb
index d22d04e9..32015745 100644
--- a/components/policy/resources/policy_templates_te.xtb
+++ b/components/policy/resources/policy_templates_te.xtb
@@ -1263,11 +1263,11 @@
       ఈ విధానం సెట్ చేయబడితే, లాగిన్ స్క్రీన్‌లో వినియోగదారు పరస్పర చర్య లేని సమయ వ్యవధి తర్వాత నిర్దిష్ట సెషన్ స్వయంచాలకంగా లాగిన్ చేయబడుతుంది. పబ్లిక్ సెషన్‌ను తప్పనిసరిగా ముందుగానే కాన్ఫిగర్ చేయాలి (|DeviceLocalAccounts|ని చూడండి).
 
       ఈ విధానం సెట్ చేయబడకపోతే, స్వీయ లాగిన్ ఉండదు.</translation>
-<translation id="5535957389335373033">పర్యవేక్షిత నెట్‌వర్క్ ప్యాకెట్‌లు పంపబడే తరచుదనం, మిల్లీసెకన్లలో ఉండాలి.
+<translation id="5535957389335373033">పర్యవేక్షిత నెట్‌వర్క్ ప్యాకెట్‌లు పంపబడే సమయ వ్యవధి, మిల్లీసెకన్లలో ఉండాలి.
 
-      ఈ విధానాన్ని సెట్ చేయకుంటే, డిఫాల్ట్ తరచుదనం 3 నిమిషాలు ఉంటుంది. దీని కనీస
-      తరచుదనం 30 సెకన్లు మరియు గరిష్ట తరచుదనం 24 గంటలు - ఈ పరిధిని విలువలు
-      దాటితే నిర్బంధంగా ఈ పరిధిలోకి అమర్చబడతాయి.</translation>
+      ఈ విధానాన్ని సెట్ చేయకుంటే, డిఫాల్ట్ సమయ వ్యవధి 3 నిమిషాలు ఉంటుంది. దీని కనీస
+      సమయ వ్యవధి 30 సెకన్లు మరియు గరిష్ట సమయ వ్యవధి 24 గంటలు - ఈ పరిధిని విలువలు
+      దాటితే నిర్బంధంగా ఈ పరిధిలోకి మార్చబడతాయి.</translation>
 <translation id="5535973522252703021">Kerberos ప్రతినిధి బృందం సర్వర్ ఆమోదిత జాబితా</translation>
 <translation id="5560039246134246593"><ph name="PRODUCT_NAME" />లో వ్యత్యాసాల సీడ్‌ను పొందడానికి పరామితిని జోడించండి.
 
@@ -1817,7 +1817,6 @@
       ఈ విధానం సెట్ చేయబడకపోతే, స్వయంచాలక క్లీన్-అప్ డిఫాల్ట్ అంతర్నిర్మిత వ్యూహాన్ని పాటిస్తుంది. ప్రస్తుతం, అలా 'RemoveLRUIfDormant' వ్యూహం ఉంది.</translation>
 <translation id="7336878834592315572">సెషన్ వ్యవధి కోసం కుక్కీలను ఉంచడం</translation>
 <translation id="7340034977315324840">పరికరం కార్యాచరణ సమయాలను నివేదించండి</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" />లో SPDY ప్రోటోకాల్ యొక్క ఉపయోగాన్ని నిలిపివేస్తుంది. ఈ విధానం ప్రారంభించబడితే, <ph name="PRODUCT_NAME" />లో SPDY ప్రోటోకాల్ అందుబాటులో ఉండదు. ఈ విధానాన్ని నిలిపివేయికి సెట్ చేయడం వల్ల SPDY యొక్క ఉపయోగానికి అనుమతిస్తుంది. ఈ విధానం సెట్ చేయకుండా వదిలివేయబడితే, SPDY అందుబాటులో ఉంటుంది.</translation>
 <translation id="7384999953864505698">QUIC ప్రోటోకాల్‌ను అనుమతిస్తుంది</translation>
 <translation id="7406651467768226499"><ph name="PRODUCT_OS_NAME" /> సంస్కరణను నియంత్రించడం కోసం సున్నా జాప్యంతో స్వయంచాలకంగా ప్రారంభించబడిన కియోస్క్ అనువర్తనాన్ని అనుమతించాలా వద్దా అనేదాన్ని నిర్ణయిస్తుంది.
 
@@ -2399,7 +2398,7 @@
 <translation id="9187743794267626640">బాహ్య నిల్వను మౌంట్ చేయడాన్ని నిలిపివేస్తుంది</translation>
 <translation id="9197740283131855199">కాంతివిహీనత తర్వాత వినియోగదారు సక్రియంగా మారితే స్క్రీన్ కాంతివిహీనత ఆలస్యాన్ని లెక్కించే శాతం</translation>
 <translation id="9200828125069750521">POSTని ఉపయోగించే చిత్రం URL కోసం పరామితులు</translation>
-<translation id="9217154963008402249">పర్యవేక్షిత నెట్‌వర్క్ ప్యాకెట్‌ల తరచుదనం</translation>
+<translation id="9217154963008402249">పర్యవేక్షిత నెట్‌వర్క్ ప్యాకెట్‌ల సమయ వ్యవధి</translation>
 <translation id="922540222991413931">పొడిగింపును, అనువర్తనాన్ని మరియు వినియోగదారు స్క్రిప్ట్ ఇన్‌స్టాల్ సోర్స్‌లను కాన్ఫిగర్ చేయండి</translation>
 <translation id="924557436754151212">మొదటి అమలులోనే డిఫాల్ట్ బ్రౌజర్ నుండి సేవ్ చేయబడిన పాస్‌వర్డ్‌లను దిగుమతి చేయి</translation>
 <translation id="930930237275114205"><ph name="PRODUCT_FRAME_NAME" /> వినియోగదారు డేటా డైరెక్టరీనీ నేరుగా సెట్ చేయండి</translation>
diff --git a/components/policy/resources/policy_templates_th.xtb b/components/policy/resources/policy_templates_th.xtb
index 2a432dcd..bc903b4f 100644
--- a/components/policy/resources/policy_templates_th.xtb
+++ b/components/policy/resources/policy_templates_th.xtb
@@ -641,7 +641,7 @@
 <translation id="3030000825273123558">เปิดใช้งานการรายงานเมตริก</translation>
 <translation id="3034580675120919256">ช่วยให้คุณกำหนดว่าเว็บไซต์จะได้รับอนุญาตให้เรียกใช้ JavaScript หรือไม่ การเรียกใช้ JavaScript อาจจะได้รับอนุญาตสำหรับเว็บไซต์ทั้งหมดหรือปฏิเสธสำหรับเว็บไซต์ทั้งหมดก็ได้ หากนโยบายนี้ไม่มีการตั้งค่าไว้ จะมีการใช้ "AllowJavaScript" และผู้ใช้สามารถจะเปลี่ยนแปลงได้</translation>
 <translation id="3038323923255997294">เรียกใช้แอปพลิเคชันพื้นหลังต่อไปเมื่อปิด <ph name="PRODUCT_NAME" /></translation>
-<translation id="3046192273793919231">ส่งแพ็กเก็ตเครือข่ายไปยังเซิร์ฟเวอร์การจัดการในการติดตามดูสถานะการออนไลน์</translation>
+<translation id="3046192273793919231">ส่งแพ็กเก็ตเครือข่ายไปยังเซิร์ฟเวอร์การจัดการเพื่อติดตามดูสถานะการออนไลน์</translation>
 <translation id="3048744057455266684">หากนโยบายนี้ถูกตั้งค่าไว้และ URL ค้นหาที่แถบอเนกประสงค์แนะนำมีพารามิเตอร์นี้ในสตริงข้อความค้นหาหรือในตัวระบุชิ้นส่วน คำแนะนำจะแสดงคำค้นหาและผู้ให้บริการค้นหาแทน URL ค้นหาดิบ
 
           นโยบายนี้ไม่บังคับ หากไม่ตั้งค่านโยบาย จะไม่มีการแทนที่คำค้นหา
@@ -905,7 +905,7 @@
 
           หากไม่มีการตั้งค่าหรือตั้งค่าเป็น False ผู้ใช้จะสามารถโอนไฟล์ไปยัง Google ไดรฟ์</translation>
 <translation id="3915395663995367577">URL ไปยังไฟล์ .pac ของพร็อกซี</translation>
-<translation id="3939893074578116847">ส่งแพ็กเก็ตเครือข่ายไปยังเซิร์ฟเวอร์การจัดการในการติดตามดูสถานะการออนไลน์ เพื่อให้เซิร์ฟเวอร์ตรวจสอบว่าอุปกรณ์กำลังออฟไลน์หรือไม่ หากตั้งค่านโยบายนี้ไว้ที่จริง ระบบจะส่งการติดตามดูแพ็กเก็ตเครือข่าย (ที่เรียกว่า <ph name="HEARTBEATS_TERM" /> ) หากตั้งค่าไว้ที่เท็จหรือไม่มีการตั้งค่า ระบบจะไม่มีส่งแพ็กเก็ต</translation>
+<translation id="3939893074578116847">ส่งแพ็กเก็ตเครือข่ายไปยังเซิร์ฟเวอร์การจัดการเพื่อติดตามดูสถานะการออนไลน์ เพื่อให้เซิร์ฟเวอร์ตรวจสอบว่าอุปกรณ์กำลังออฟไลน์หรือไม่ หากตั้งค่านโยบายนี้ไว้ที่จริง ระบบจะส่งการติดตามดูแพ็กเก็ตเครือข่าย (ที่เรียกว่า <ph name="HEARTBEATS_TERM" /> ) หากตั้งค่าไว้ที่เท็จหรือไม่มีการตั้งค่า ระบบจะไม่มีส่งแพ็กเก็ต</translation>
 <translation id="3964909636571393861">อนุญาตให้เข้าถึงรายการ URL</translation>
 <translation id="3965339130942650562">หมดเวลาจนกว่าจะดำเนินการออกจากระบบของผู้ใช้ที่ไม่มีการใช้งาน</translation>
 <translation id="3967075520570946456">เปิดใช้การแสดงหน้าต้อนรับเมื่อเรียกใช้เบราว์เซอร์ครั้งแรกหลังการอัปเกรดระบบปฏิบัติการ</translation>
@@ -1233,8 +1233,8 @@
       หากไม่มีการตั้งค่านโยบายนี้ จะไม่มีการเข้าสู่ระบบอัตโนมัติ</translation>
 <translation id="5535957389335373033">ความถี่ในการส่งการติดตามดูแพ็กเก็ตเครือข่ายเป็นมิลลิวินาที
 
-      หากไม่ได้ตั้งค่านโยบาย ความถี่เริ่มต้นคือ 3 นาที ส่วน
-      ความถี่ต่ำสุดคือ 30 วินาที และความถี่สูงสุดคือ 24 ชั่วโมง
+      หากไม่ได้ตั้งค่านโยบาย ความถี่เริ่มต้นคือทุก 3 นาที ส่วน
+      ความถี่สูงสุดคือทุก 30 วินาที และความถี่ต่ำสุดคือทุก 24 ชั่วโมง
       ค่าที่ไม่อยู่ในช่วงดังกล่าวจะถูกจำกัดตามช่วงนี้</translation>
 <translation id="5535973522252703021">รายการที่อนุญาตสำหรับเซิร์ฟเวอร์การมอบสิทธิ์ของ Kerberos</translation>
 <translation id="5560039246134246593">เพิ่มพารามิเตอร์ไปยังการเรียกเมล็ดรูปแบบใน <ph name="PRODUCT_NAME" />
@@ -1784,7 +1784,6 @@
       หากไม่ได้กำหนดค่านโยบายนี้ การล้างข้อมูลอัตโนมัติจะใช้กลยุทธ์เริ่มต้นที่มีในตัว ซึ่งปัจจุบันคือกลยุทธ์ "RemoveLRUIfDormant"</translation>
 <translation id="7336878834592315572">เก็บคุกกี้ไว้ในระหว่างช่วงเวลาของเซสชัน</translation>
 <translation id="7340034977315324840">รายงานจำนวนครั้งของกิจกรรมบนอุปกรณ์</translation>
-<translation id="7381326101471547614">ปิดใช้งานการใช้โปรโตคอล SPDY ใน <ph name="PRODUCT_NAME" /> หากนโยบายนี้ถูกเปิดใช้งาน โปรโตคอล SPDY จะไม่สามารถใช้ได้ใน <ph name="PRODUCT_NAME" /> การตั้งค่านโยบายนี้เป็นปิดใช้งานจะทำให้สามารถใช้ SPDY ได้ และหากไม่ได้ตั้งค่านโยบายนี้ ก็จะสามารถใช้ SPDY ได้</translation>
 <translation id="7384999953864505698">อนุญาตโปรโตคอล QUIC</translation>
 <translation id="7406651467768226499">การเลือกว่าจะอนุญาตแอปคีออสก์ที่เปิดอัตโนมัติด้วยความล่าช้าเป็น 0 เพื่อควบคุมเวอร์ชันของ <ph name="PRODUCT_OS_NAME" /> หรือไม่
 
diff --git a/components/policy/resources/policy_templates_tr.xtb b/components/policy/resources/policy_templates_tr.xtb
index 29d1265..8f7ade0 100644
--- a/components/policy/resources/policy_templates_tr.xtb
+++ b/components/policy/resources/policy_templates_tr.xtb
@@ -1937,7 +1937,6 @@
       Bu politika ayarlanmazsa, otomatik temizleme varsayılan yerleşik stratejiyi kullanır. Şu an bu "RemoveLRUIfDormant" stratejisidir.</translation>
 <translation id="7336878834592315572">Oturum süresince çerezleri tutma</translation>
 <translation id="7340034977315324840">Cihaz etkinlik zamanlarını rapor et</translation>
-<translation id="7381326101471547614"><ph name="PRODUCT_NAME" /> ürününde SPDY protokolünün kullanımını devre dışı bırakır. Bu politika etkinleştirilirse SPDY protokolü <ph name="PRODUCT_NAME" /> ürününde kullanılamaz. Bu politika devre dışı bırakılırsa, SPDY kullanılabilir. Bu politika ayarlanmamış şekilde bırakılırsa, SPDY kullanılabilir durumda olur.</translation>
 <translation id="7384999953864505698">QUIC protokolüne izin verir</translation>
 <translation id="7406651467768226499">Sıfır gecikmeyle otomatik başlatılan kiosk uygulamasının <ph name="PRODUCT_OS_NAME" /> sürümünü kontrol etmesine izin verilip verilmeyeceğini belirtir.
 
diff --git a/components/policy/resources/policy_templates_uk.xtb b/components/policy/resources/policy_templates_uk.xtb
index 41cdb46d..21e030881 100644
--- a/components/policy/resources/policy_templates_uk.xtb
+++ b/components/policy/resources/policy_templates_uk.xtb
@@ -1798,7 +1798,6 @@
       Якщо це правило не встановлено, під час автоматичного очищення використовується правило за умовчанням. Зараз це правило "RemoveLRUIfDormant".</translation>
 <translation id="7336878834592315572">Зберігати файли cookie впродовж сеансу</translation>
 <translation id="7340034977315324840">Повідомляти про періоди активності пристрою</translation>
-<translation id="7381326101471547614">Вимикає використання протоколу SPDY у <ph name="PRODUCT_NAME" />. Якщо це правило ввімкнено, протокол SPDY буде не доступний у <ph name="PRODUCT_NAME" />. Якщо це правило вимкнено,  використання протоколу SPDY буде дозволено. Якщо це правило не встановлено, протокол SPDY буде доступний.</translation>
 <translation id="7384999953864505698">Вмикає протокол QUIC</translation>
 <translation id="7406651467768226499">Дозволити додатку-терміналу, який запускається автоматично та без затримки, керувати версією <ph name="PRODUCT_OS_NAME" />.
 
diff --git a/components/policy/resources/policy_templates_vi.xtb b/components/policy/resources/policy_templates_vi.xtb
index e3c0a3a..df4040d 100644
--- a/components/policy/resources/policy_templates_vi.xtb
+++ b/components/policy/resources/policy_templates_vi.xtb
@@ -1920,13 +1920,6 @@
       Nếu chính sách này không được đặt, tính năng dọn sạch tự động sẽ sử dụng chiến lược tích hợp sẵn mặc định. Hiện tại đó là chiến lược 'RemoveLRUIfDormant'.</translation>
 <translation id="7336878834592315572">Lưu giữ cookie trong thời hạn phiên</translation>
 <translation id="7340034977315324840">Báo cáo thời gian hoạt động của thiết bị</translation>
-<translation id="7381326101471547614">Không cho phép sử dụng giao thức SPDY trong <ph name="PRODUCT_NAME" />.
-
-      Nếu bật chính sách này, giao thức SPDY sẽ không sẵn có trong <ph name="PRODUCT_NAME" />.
-
-      Tắt chính sách này sẽ cho phép sử dụng SPDY.
-
-      Nếu không thiết lập chính sách này, SPDY sẽ sẵn có.</translation>
 <translation id="7384999953864505698">Cho phép giao thức QUIC</translation>
 <translation id="7406651467768226499">Dù có cho phép ứng dụng kiosk tự động khởi chạy với độ trễ bằng không kiểm soát phiên bản <ph name="PRODUCT_OS_NAME" /> hay không.
 
diff --git a/components/policy/resources/policy_templates_zh-CN.xtb b/components/policy/resources/policy_templates_zh-CN.xtb
index 3589e92..15d9a66 100644
--- a/components/policy/resources/policy_templates_zh-CN.xtb
+++ b/components/policy/resources/policy_templates_zh-CN.xtb
@@ -1748,13 +1748,6 @@
       如果此政策未设置,自动清理将使用默认的内置策略(目前为“RemoveLRUIfDormant”策略)。</translation>
 <translation id="7336878834592315572">在会话期间保留 Cookie</translation>
 <translation id="7340034977315324840">报告设备活动时间</translation>
-<translation id="7381326101471547614">禁止在 <ph name="PRODUCT_NAME" />中使用 SPDY 协议。
-
-      如果启用了此政策,就无法在 <ph name="PRODUCT_NAME" />中使用 SPDY 协议。
-
-      如果停用了此政策,就可以使用 SPDY 协议。
-
-      如果未设置此政策,就可以使用 SPDY 协议。</translation>
 <translation id="7384999953864505698">允许使用 QUIC 协议</translation>
 <translation id="7406651467768226499">是否允许自动启动零延迟的自助服务终端应用控制 <ph name="PRODUCT_OS_NAME" />版本。
 
diff --git a/components/policy/resources/policy_templates_zh-TW.xtb b/components/policy/resources/policy_templates_zh-TW.xtb
index 93ed99a6..d9867f9 100644
--- a/components/policy/resources/policy_templates_zh-TW.xtb
+++ b/components/policy/resources/policy_templates_zh-TW.xtb
@@ -1785,7 +1785,6 @@
       如果未設定這項政策,自動清理作業將會採用目前的預設內建策略:「RemoveLRUIfDormant」。</translation>
 <translation id="7336878834592315572">在工作階段期間保留 Cookie</translation>
 <translation id="7340034977315324840">回報裝置活動時間</translation>
-<translation id="7381326101471547614">停用 <ph name="PRODUCT_NAME" /> 中的 SPDY 通訊協定。如果啟用這項政策,SPDY 通訊協定就不會支援 <ph name="PRODUCT_NAME" />。停用這項政策即可使用 SPDY。如果未設定這項政策,即可使用 SPDY。</translation>
 <translation id="7384999953864505698">允許 QUIC 通訊協定</translation>
 <translation id="7406651467768226499">是否允許使用無延遲資訊站應用程式的自動啟動功能來控制 <ph name="PRODUCT_OS_NAME" /> 版本。
 
diff --git a/components/scheduler/child/web_task_runner_impl.cc b/components/scheduler/child/web_task_runner_impl.cc
index 269429c..0b22780 100644
--- a/components/scheduler/child/web_task_runner_impl.cc
+++ b/components/scheduler/child/web_task_runner_impl.cc
@@ -60,8 +60,8 @@
   return time_domain->Now();
 }
 
-blink::WebTaskRunner* WebTaskRunnerImpl::clone() {
-  return new WebTaskRunnerImpl(task_queue_);
+std::unique_ptr<blink::WebTaskRunner> WebTaskRunnerImpl::clone() {
+  return base::WrapUnique(new WebTaskRunnerImpl(task_queue_));
 }
 
 void WebTaskRunnerImpl::runTask(
diff --git a/components/scheduler/child/web_task_runner_impl.h b/components/scheduler/child/web_task_runner_impl.h
index 772cae4..0773a95 100644
--- a/components/scheduler/child/web_task_runner_impl.h
+++ b/components/scheduler/child/web_task_runner_impl.h
@@ -31,7 +31,7 @@
   bool runsTasksOnCurrentThread() override;
   double virtualTimeSeconds() const override;
   double monotonicallyIncreasingVirtualTimeSeconds() const override;
-  blink::WebTaskRunner* clone() override;
+  std::unique_ptr<blink::WebTaskRunner> clone() override;
 
   // blink::WebTaskRunner::Task should be wrapped by base::Passed() when
   // used with base::Bind(). See https://crbug.com/551356.
diff --git a/components/search_provider_logos/BUILD.gn b/components/search_provider_logos/BUILD.gn
index 57ef56d..84db250 100644
--- a/components/search_provider_logos/BUILD.gn
+++ b/components/search_provider_logos/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("search_provider_logos") {
+static_library("search_provider_logos") {
   sources = [
     "google_logo_api.cc",
     "google_logo_api.h",
diff --git a/components/security_state/BUILD.gn b/components/security_state/BUILD.gn
index 4d2823b..e850190 100644
--- a/components/security_state/BUILD.gn
+++ b/components/security_state/BUILD.gn
@@ -8,7 +8,7 @@
 }
 
 # GYP version: components/security_state.gyp
-source_set("security_state") {
+static_library("security_state") {
   sources = [
     "security_state_model.cc",
     "security_state_model.h",
diff --git a/components/signin/core/account_id/BUILD.gn b/components/signin/core/account_id/BUILD.gn
index 51091e0..f769b90 100644
--- a/components/signin/core/account_id/BUILD.gn
+++ b/components/signin/core/account_id/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("account_id") {
+static_library("account_id") {
   sources = [
     "account_id.cc",
     "account_id.h",
diff --git a/components/signin/core/common/BUILD.gn b/components/signin/core/common/BUILD.gn
index f34af62a..670bde9c 100644
--- a/components/signin/core/common/BUILD.gn
+++ b/components/signin/core/common/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("common") {
+static_library("common") {
   sources = [
     "profile_management_switches.cc",
     "profile_management_switches.h",
diff --git a/components/ssl_config/BUILD.gn b/components/ssl_config/BUILD.gn
index babcc5cb..54dd47e 100644
--- a/components/ssl_config/BUILD.gn
+++ b/components/ssl_config/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 # GYP version: components/ssl_config.gypi:ssl_config
-source_set("ssl_config") {
+static_library("ssl_config") {
   sources = [
     "ssl_config_prefs.cc",
     "ssl_config_prefs.h",
diff --git a/components/ssl_errors/BUILD.gn b/components/ssl_errors/BUILD.gn
index 7ed952b..3389542 100644
--- a/components/ssl_errors/BUILD.gn
+++ b/components/ssl_errors/BUILD.gn
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 # GYP version: components/ssl_errors.gypi
-source_set("ssl_errors") {
+static_library("ssl_errors") {
   sources = [
     "error_classification.cc",
     "error_classification.h",
diff --git a/components/startup_metric_utils/browser/BUILD.gn b/components/startup_metric_utils/browser/BUILD.gn
index cd407610..2f9f417 100644
--- a/components/startup_metric_utils/browser/BUILD.gn
+++ b/components/startup_metric_utils/browser/BUILD.gn
@@ -15,7 +15,7 @@
   ]
 }
 
-source_set("lib") {
+static_library("lib") {
   sources = [
     "pref_names.cc",
     "pref_names.h",
@@ -30,7 +30,7 @@
   ]
 }
 
-source_set("host") {
+static_library("host") {
   sources = [
     "startup_metric_host_impl.cc",
     "startup_metric_host_impl.h",
diff --git a/components/strings/components_strings_bg.xtb b/components/strings/components_strings_bg.xtb
index bc0bc7f..9b61fc6 100644
--- a/components/strings/components_strings_bg.xtb
+++ b/components/strings/components_strings_bg.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">Наистина ли искате да изтриете тези страници от историята си?</translation>
 <translation id="2677748264148917807">Излизане</translation>
 <translation id="2704283930420550640">Стойността не съответства на формата.</translation>
-<translation id="2704951214193499422">Понастоящем Chromium не можа да потвърди картата ви. Моля, опитайте отново по-късно.</translation>
+<translation id="2704951214193499422">Chromium не можа да потвърди картата ви. Моля, опитайте отново по-късно.</translation>
 <translation id="2705137772291741111">Запазеното (кеширано) копие на този сайт не можа да се прочете.</translation>
 <translation id="2709516037105925701">Автоматично попълване</translation>
 <translation id="2712173769900027643">Искане на разрешение</translation>
@@ -182,13 +182,13 @@
 <translation id="2985306909656435243">Ако настройката е активирана, Chromium ще съхранява на това устройство копие на картата ви с цел по-бързо попълване на формуляри.</translation>
 <translation id="2991174974383378012">Споделяне с уебсайтове</translation>
 <translation id="3005723025932146533">Показване на запазено копие</translation>
-<translation id="3008447029300691911">Въведете кода за проверка за <ph name="CREDIT_CARD" />. След като извършите потвърждаването, данните за картата ви ще бъдат споделени с този сайт.</translation>
+<translation id="3008447029300691911">Въведете кода за проверка за <ph name="CREDIT_CARD" />. След като потвърдите картата си, данните за нея ще бъдат споделени с този сайт.</translation>
 <translation id="3010559122411665027">Списъчен запис „<ph name="ENTRY_INDEX" />“: <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">Грешен тип на правилото</translation>
 <translation id="3032412215588512954">Искате ли да презаредите този сайт?</translation>
 <translation id="3037605927509011580">Ужас!</translation>
 <translation id="3041612393474885105">Информация за сертификата</translation>
-<translation id="3063697135517575841">Понастоящем Chrome не можа да потвърди картата ви. Моля, опитайте отново по-късно.</translation>
+<translation id="3063697135517575841">Chrome не можа да потвърди картата ви. Моля, опитайте отново по-късно.</translation>
 <translation id="3093245981617870298">Понастоящем сте офлайн.</translation>
 <translation id="3105172416063519923">ID на актива:</translation>
 <translation id="3109728660330352905">Нямате пълномощия за преглед на тази страница.</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">Връзката използва <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Ами сега! Трябва да попитате родителя си дали може да посетите тази страница.</translation>
 <translation id="7246609911581847514">Виждате това съобщение, защото мениджърът ви трябва да одобри новите сайтове при първото ви посещение.</translation>
-<translation id="724975217298816891">Въведете датата на валидност и кода за проверка за <ph name="CREDIT_CARD" />, за да актуализирате данните за картата си. След като извършите потвърждаването, те ще бъдат споделени с този сайт.</translation>
+<translation id="724975217298816891">Въведете датата на валидност и кода за проверка за <ph name="CREDIT_CARD" />, за да актуализирате данните за картата си. След като я потвърдите, те ще бъдат споделени с този сайт.</translation>
 <translation id="725866823122871198">Не може да се установи частна връзка с/ъс <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, тъй като датата и часът на компютъра ви (<ph name="DATE_AND_TIME" />) са неправилни.</translation>
 <translation id="7265986070661382626">В момента не можете да посетите <ph name="SITE" />, защото уебсайтът <ph name="BEGIN_LINK" />използва фиксиране на сертификатите<ph name="END_LINK" />. Обикновено грешките в мрежата и атаките срещу нея са временни, така че тази страница вероятно ще работи по-късно.</translation>
 <translation id="7269802741830436641">Тази страница води до циклично пренасочване</translation>
@@ -527,7 +527,7 @@
 <translation id="7377249249140280793"><ph name="RELATIVE_DATE" /> - <ph name="FULL_DATE" /></translation>
 <translation id="7378627244592794276">Не</translation>
 <translation id="7378810950367401542">/</translation>
-<translation id="7390545607259442187">Потвърдете картата</translation>
+<translation id="7390545607259442187">Потвърждаване на картата</translation>
 <translation id="7394102162464064926">Наистина ли искате да изтриете тези страници от историята си?
 
 Не забравяйте, че режим „инкогнито“ (<ph name="SHORTCUT_KEY" />) може да е полезен следващия път.</translation>
@@ -652,7 +652,7 @@
 <translation id="8866959479196209191">Тази страница изпраща подкана:</translation>
 <translation id="8870413625673593573">Наскоро затворени</translation>
 <translation id="8876793034577346603">Синтактичният анализ на конфигурацията на мрежата не бе успешен.</translation>
-<translation id="8877192140621905067">След като извършите потвърждаването, данните за картата ви ще бъдат споделени с този сайт</translation>
+<translation id="8877192140621905067">След като потвърдите картата си, данните за нея ще бъдат споделени с този сайт</translation>
 <translation id="8891727572606052622">Невалиден режим на прокси сървъра.</translation>
 <translation id="889901481107108152">За съжаление този експеримент не се предлага за платформата ви.</translation>
 <translation id="8903921497873541725">Увеличаване на мащаба</translation>
diff --git a/components/strings/components_strings_bn.xtb b/components/strings/components_strings_bn.xtb
index 9af3cde..0cf5db0 100644
--- a/components/strings/components_strings_bn.xtb
+++ b/components/strings/components_strings_bn.xtb
@@ -189,7 +189,7 @@
 <translation id="3032412215588512954">আপনি কি এই সাইটটি পুনরায় লোড করতে চান?</translation>
 <translation id="3037605927509011580">ইস!</translation>
 <translation id="3041612393474885105">শংসাপত্র তথ্য</translation>
-<translation id="3063697135517575841">Chrome এই মুহূর্তে আপনার কার্ড নিশ্চিত করতে অক্ষম হয়েছে৷ দয়া করে পরে আবার চেষ্টা করুন৷</translation>
+<translation id="3063697135517575841">Chrome এই মুহূর্তে আপনার কার্ড নিশ্চিত করতে পারছে না৷ অনুগ্রহ করে পরে আবার চেষ্টা করুন৷</translation>
 <translation id="3093245981617870298">আপনি অফলাইনে আছেন৷</translation>
 <translation id="3105172416063519923">সম্পদ আইডি:</translation>
 <translation id="3109728660330352905">আপনার এই পৃষ্ঠাটি দেখার জন্য অনুমোদন নেই।</translation>
@@ -411,7 +411,7 @@
 <translation id="5677928146339483299">অবরুদ্ধ</translation>
 <translation id="5710435578057952990">এই ওয়েবসাইটির পরিচয় যাচাই করা হয় নি৷</translation>
 <translation id="5720705177508910913">বর্তমান ব্যবহারকারী</translation>
-<translation id="5784606427469807560">আপনার কার্ডটি নিশ্চিত করতে একটি সমস্যা হয়েছিল৷ আপনার ইন্টারনেট সংযোগ পরীক্ষা করে আবার চেষ্টা করুন৷</translation>
+<translation id="5784606427469807560">আপনার কার্ডটি নিশ্চিত করতে একটি সমস্যা হয়েছিল৷আপনার ইন্টারনেট সংযোগ পরীক্ষা করে আবার চেষ্টা করুন৷</translation>
 <translation id="5785756445106461925">উপরন্তু, এই পৃষ্ঠাতে অন্যান্য সংস্থান অন্তর্ভুক্ত রয়েছে যা নিরাপদ নয়৷ এই সংস্থানগুলি ট্রানজিটের সময় অন্যরা দেখতে পাবে এবং পৃষ্ঠাটির চেহারাটি পরিবর্তন করতে কোনও আক্রমণকারী এর পরিবর্তন করতে পারেন৷</translation>
 <translation id="5810442152076338065"><ph name="DOMAIN" />-এ আপনার সংযোগ একটি অপ্রচলিত সাইফার স্যুট ব্যবহার করে এনক্রিপ্ট করা হয়েছে৷</translation>
 <translation id="5813119285467412249">&amp;যোগ করাকে পুনরায় করুন</translation>
diff --git a/components/strings/components_strings_cs.xtb b/components/strings/components_strings_cs.xtb
index 30c83059..28303c8 100644
--- a/components/strings/components_strings_cs.xtb
+++ b/components/strings/components_strings_cs.xtb
@@ -404,7 +404,7 @@
 <translation id="5677928146339483299">Zablokováno</translation>
 <translation id="5710435578057952990">Identita těchto webových stránek nebyla ověřena.</translation>
 <translation id="5720705177508910913">Aktuální uživatel</translation>
-<translation id="5784606427469807560">Při ověřování karty došlo k problému. Zkontrolujte připojení k internetu a zkuste to znovu.</translation>
+<translation id="5784606427469807560">Při ověřování vaší karty došlo k problému. Zkontrolujte připojení k internetu a zkuste to znovu.</translation>
 <translation id="5785756445106461925">Tato stránka obsahuje ještě další nezabezpečené zdroje. Tyto zdroje budou během přenosu moci zobrazit jiní uživatelé a případní útočníci je mohou upravit a změnit tak vzhled stránky.</translation>
 <translation id="5810442152076338065">Vaše připojení k doméně <ph name="DOMAIN" /> je šifrováno za použití zastaralé šifrovací sady.</translation>
 <translation id="5813119285467412249">&amp;Opakovat přidání</translation>
@@ -477,7 +477,7 @@
 <translation id="6839929833149231406">Region</translation>
 <translation id="6874604403660855544">&amp;Opakovat přidání</translation>
 <translation id="6891596781022320156">Úroveň zásady není podporována.</translation>
-<translation id="6895330447102777224">Karta je ověřena</translation>
+<translation id="6895330447102777224">Vaše karta je ověřena</translation>
 <translation id="6897140037006041989">User agent</translation>
 <translation id="6903907808598579934">Zapnout synchronizaci</translation>
 <translation id="6915804003454593391">Uživatel:</translation>
diff --git a/components/strings/components_strings_de.xtb b/components/strings/components_strings_de.xtb
index c0e9631b..cb735893 100644
--- a/components/strings/components_strings_de.xtb
+++ b/components/strings/components_strings_de.xtb
@@ -153,7 +153,7 @@
 <translation id="2674170444375937751">Möchten Sie diese Seiten wirklich aus dem Verlauf löschen?</translation>
 <translation id="2677748264148917807">Verlassen</translation>
 <translation id="2704283930420550640">Wert stimmt nicht mit dem Format überein.</translation>
-<translation id="2704951214193499422">Chromium kann Ihre Karte momentan nicht bestätigen. Bitte versuchen Sie es später noch einmal.</translation>
+<translation id="2704951214193499422">Ihre Karte kann von Chromium zurzeit nicht bestätigt werden. Bitte versuchen Sie es später noch einmal.</translation>
 <translation id="2705137772291741111">Die (im Cache) gespeicherte Kopie dieser Website war nicht lesbar.</translation>
 <translation id="2709516037105925701">AutoFill</translation>
 <translation id="2712173769900027643">Berechtigung anfordern</translation>
@@ -183,13 +183,13 @@
 <translation id="2985306909656435243">Wenn Sie diese Option auswählen, speichert Chromium eine Kopie Ihrer Karte auf diesem Gerät, damit Formulare schneller ausgefüllt werden können.</translation>
 <translation id="2991174974383378012">Datenfreigabe an Websites</translation>
 <translation id="3005723025932146533">Gespeicherte Kopie anzeigen</translation>
-<translation id="3008447029300691911">Geben Sie den CVC für <ph name="CREDIT_CARD" /> ein. Nach der Bestätigung werden die Kartendetails an diese Website weitergegeben.</translation>
+<translation id="3008447029300691911">Geben Sie den CVC für <ph name="CREDIT_CARD" /> ein. Nach erfolgter Bestätigung werden die Kartendetails an diese Website weitergegeben.</translation>
 <translation id="3010559122411665027">Listeneintrag "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">Falscher Richtlinientyp</translation>
 <translation id="3032412215588512954">Möchten Sie diese Website neu laden?</translation>
 <translation id="3037605927509011580">Oh nein!</translation>
 <translation id="3041612393474885105">Zertifikatinformationen</translation>
-<translation id="3063697135517575841">Chrome kann Ihre Karte momentan nicht bestätigen. Bitte versuchen Sie es später noch einmal.</translation>
+<translation id="3063697135517575841">Ihre Karte kann von Chrome zurzeit nicht bestätigt werden. Bitte versuchen Sie es später noch einmal.</translation>
 <translation id="3093245981617870298">Sie sind offline.</translation>
 <translation id="3105172416063519923">Geräte-ID:</translation>
 <translation id="3109728660330352905">Sie sind nicht zum Aufrufen dieser Seite autorisiert.</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">Die Verbindung verwendet <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Hoppla. Du musst einen Elternteil fragen, ob du diese Seite besuchen darfst.</translation>
 <translation id="7246609911581847514">Diese Nachricht wird Ihnen angezeigt, weil Ihr Administrator neue Websites zuerst genehmigen muss, bevor Sie diese öffnen können.</translation>
-<translation id="724975217298816891">Geben Sie das Ablaufdatum und den CVC für <ph name="CREDIT_CARD" /> ein, um Ihre Kartendetails zu aktualisieren. Nach der Bestätigung werden die Kartendetails an diese Website weitergegeben.</translation>
+<translation id="724975217298816891">Geben Sie das Gültigkeitsdatum und den CVC für <ph name="CREDIT_CARD" /> ein, um Ihre Kartendetails zu aktualisieren. Nach erfolgter Bestätigung werden die Kartendetails an diese Website weitergegeben.</translation>
 <translation id="725866823122871198">Es kann keine private Verbindung zu <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> hergestellt werden, weil Datum und Uhrzeit Ihres Computers falsch sind (<ph name="DATE_AND_TIME" />).</translation>
 <translation id="7265986070661382626"><ph name="SITE" /> kann zurzeit nicht aufgerufen werden, weil die Website das <ph name="BEGIN_LINK" />Zertifikats-Pinning<ph name="END_LINK" /> nutzt. Netzwerkfehler und Angriffe sind in der Regel nur vorübergehend, sodass die Seite später wahrscheinlich wieder funktioniert.</translation>
 <translation id="7269802741830436641">Diese Webseite weist eine Weiterleitung auf.</translation>
@@ -652,7 +652,7 @@
 <translation id="8866959479196209191">Auf dieser Seite wird Folgendes angezeigt:</translation>
 <translation id="8870413625673593573">Kürzlich geschlossen</translation>
 <translation id="8876793034577346603">Fehler beim Parsen der Netzwerkkonfiguration</translation>
-<translation id="8877192140621905067">Nach der Bestätigung werden die Kartendetails an diese Website weitergegeben</translation>
+<translation id="8877192140621905067">Nach erfolgter Bestätigung werden die Kartendetails an diese Website weitergegeben</translation>
 <translation id="8891727572606052622">Ungültiger Proxy-Modus</translation>
 <translation id="889901481107108152">Leider steht dieses Experiment auf Ihrer Plattform nicht zur Verfügung.</translation>
 <translation id="8903921497873541725">Vergrößern</translation>
@@ -686,7 +686,7 @@
 <translation id="935608979562296692">Formular leeren</translation>
 <translation id="939736085109172342">Neuer Ordner</translation>
 <translation id="943029900877297437">Melden Sie sich in Chrome an, um in Ihrem Google-Konto gespeicherte Karten zu verwenden.</translation>
-<translation id="962701380617707048">Geben Sie das Ablaufdatum und den CVC für <ph name="CREDIT_CARD" /> ein, um Ihre Kartendetails zu aktualisieren</translation>
+<translation id="962701380617707048">Gültigkeitsdatum und CVC für <ph name="CREDIT_CARD" /> zur Aktualisierung Ihrer Kartendetails eingeben</translation>
 <translation id="969892804517981540">Offizieller Build</translation>
 <translation id="988159990683914416">Entwickler-Build</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/strings/components_strings_el.xtb b/components/strings/components_strings_el.xtb
index ae35513..10ce04c 100644
--- a/components/strings/components_strings_el.xtb
+++ b/components/strings/components_strings_el.xtb
@@ -182,7 +182,7 @@
 <translation id="2985306909656435243">Εάν ενεργοποιηθεί, το Chromium θα αποθηκεύσει ένα αντίγραφο της κάρτας σας σε αυτήν τη συσκευή για ταχύτερη συμπλήρωση φορμών.</translation>
 <translation id="2991174974383378012">Κοινοποίηση σε ιστότοπους</translation>
 <translation id="3005723025932146533">Εμφάνιση αποθηκευμένου αντιγράφου</translation>
-<translation id="3008447029300691911">Εισαγάγετε τον κωδικό CVC της πιστωτικής κάρτας <ph name="CREDIT_CARD" />. Μετά την επιβεβαίωση, θα γίνει κοινή χρήση των στοιχείων της κάρτας σας με αυτόν τον ιστότοπο.</translation>
+<translation id="3008447029300691911">Εισαγάγετε τον κωδικό CVC για την πιστωτική κάρτα <ph name="CREDIT_CARD" />. Μετά την επιβεβαίωση, θα γίνει κοινή χρήση των στοιχείων της κάρτας σας με αυτόν τον ιστότοπο.</translation>
 <translation id="3010559122411665027">Καταχώριση λίστας "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">Λανθασμένος τύπος πολιτικής</translation>
 <translation id="3032412215588512954">Θέλετε να φορτώσετε ξανά αυτόν τον ιστότοπο;</translation>
@@ -208,7 +208,7 @@
 <translation id="3225919329040284222">Ο διακομιστής παρουσίασε ένα πιστοποιητικό που δεν αντιστοιχεί στις ενσωματωμένες προϋποθέσεις. Αυτές οι προϋποθέσεις συμπεριλαμβάνονται σε συγκεκριμένους ιστότοπους υψηλής ασφάλειας για την προστασία σας.</translation>
 <translation id="3226128629678568754">Πατήστε το κουμπί της επανάληψης φόρτωσης για να υποβάλετε ξανά τα δεδομένα που απαιτούνται για τη φόρτωση της σελίδας.</translation>
 <translation id="3228969707346345236">Η μετάφραση απέτυχε επειδή η σελίδα είναι ήδη στα <ph name="LANGUAGE" />.</translation>
-<translation id="323107829343500871">Εισαγάγετε τον κωδικό CVC της πιστωτικής κάρτας <ph name="CREDIT_CARD" /></translation>
+<translation id="323107829343500871">Εισαγάγετε τον κωδικό CVC για την πιστωτική κάρτα <ph name="CREDIT_CARD" /></translation>
 <translation id="3254409185687681395">Προσθήκη αυτής της σελίδας στους σελιδοδείκτες</translation>
 <translation id="3270847123878663523">&amp;Αναίρεση αναδιάταξης</translation>
 <translation id="3286538390144397061">Άμεση επανεκκίνηση</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">Στη σύνδεση χρησιμοποιείται <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Θα πρέπει να ρωτήσεις τους γονείς σου εάν σου επιτρέπουν να επισκεφτείς αυτήν τη σελίδα.</translation>
 <translation id="7246609911581847514">Αυτό το μήνυμα εμφανίζεται επειδή ο διαχειριστής σας θα πρέπει να εγκρίνει τυχόν νέους ιστότοπους την πρώτη φορά που τους επισκέπτεστε.</translation>
-<translation id="724975217298816891">Εισαγάγετε την ημερομηνία λήξης και τον κωδικό CVC της πιστωτικής κάρτας <ph name="CREDIT_CARD" />, προκειμένου να ενημερώσετε τα στοιχεία της κάρτας σας. Μετά την επιβεβαίωση, θα γίνει κοινή χρήση των στοιχείων της κάρτας σας με αυτόν τον ιστότοπο.</translation>
+<translation id="724975217298816891">Εισαγάγετε την ημερομηνία λήξης και τον κωδικό CVC για την πιστωτική κάρτα <ph name="CREDIT_CARD" />, προκειμένου να ενημερώσετε τα στοιχεία της κάρτας σας. Μετά την επιβεβαίωση, θα γίνει κοινή χρήση των στοιχείων της κάρτας σας με αυτόν τον ιστότοπο.</translation>
 <translation id="725866823122871198">Δεν είναι δυνατή η επίτευξη ιδιωτικής σύνδεσης με τον τομέα <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> επειδή η ημερομηνία και η ώρα (<ph name="DATE_AND_TIME" />) του υπολογιστή σας είναι λανθασμένες.</translation>
 <translation id="7265986070661382626">Δεν μπορείτε να επισκεφτείτε το <ph name="SITE" /> αυτήν τη στιγμή επειδή ο ιστότοπος <ph name="BEGIN_LINK" />χρησιμοποιεί certificate pinning (κλείδωμα πιστοποιητικών)<ph name="END_LINK" />. Τα σφάλματα δικτύου και οι επιθέσεις είναι συνήθως προσωρινά, συνεπώς αυτή η σελίδα πιθανότατα θα λειτουργήσει αργότερα.</translation>
 <translation id="7269802741830436641">Αυτή η ιστοσελίδα περιλαμβάνει βρόχο ανακατεύθυνσης</translation>
@@ -686,7 +686,7 @@
 <translation id="935608979562296692">ΔΙΑΓΡΑΦΗ ΦΟΡΜΑΣ</translation>
 <translation id="939736085109172342">Νέος φάκελος</translation>
 <translation id="943029900877297437">Για να χρησιμοποιήσετε κάρτες που αποθηκεύσατε στον Λογαριασμό σας Google, συνδεθείτε στο Chrome.</translation>
-<translation id="962701380617707048">Εισαγάγετε την ημερομηνία λήξης και τον κωδικό CVC της κάρτας <ph name="CREDIT_CARD" />, προκειμένου να ενημερώσετε τα στοιχεία της κάρτας σας</translation>
+<translation id="962701380617707048">Εισαγάγετε την ημερομηνία λήξης και τον κωδικό CVC για την κάρτα <ph name="CREDIT_CARD" />, προκειμένου να ενημερώσετε τα στοιχεία της κάρτας σας</translation>
 <translation id="969892804517981540">Επίσημη έκδοση</translation>
 <translation id="988159990683914416">Έκδοση προγραμματιστή</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/strings/components_strings_es-419.xtb b/components/strings/components_strings_es-419.xtb
index 9d20c333..35a658f 100644
--- a/components/strings/components_strings_es-419.xtb
+++ b/components/strings/components_strings_es-419.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">¿Estás seguro de que deseas eliminar estas páginas del historial?</translation>
 <translation id="2677748264148917807">Abandonar</translation>
 <translation id="2704283930420550640">El valor no coincide con el formato.</translation>
-<translation id="2704951214193499422">Chromium no pudo verificar tu tarjeta. Vuelve a intentarlo más tarde.</translation>
+<translation id="2704951214193499422">Chrome no pudo confirmar tu tarjeta. Vuelve a intentarlo más tarde.</translation>
 <translation id="2705137772291741111">La copia guardada (en caché) de este sitio es ilegible.</translation>
 <translation id="2709516037105925701">Autocompletar</translation>
 <translation id="2712173769900027643">Solicitar permiso</translation>
@@ -188,7 +188,7 @@
 <translation id="3032412215588512954">¿Deseas volver a cargar este sitio?</translation>
 <translation id="3037605927509011580">¡Oh, no!</translation>
 <translation id="3041612393474885105">Información sobre el certificado</translation>
-<translation id="3063697135517575841">Chrome no pudo confirmar tu tarjeta. Vuelve a intentarlo más tarde.</translation>
+<translation id="3063697135517575841">Chrome no pudo confirmar tu tarjeta en este momento. Vuelve a intentarlo más tarde.</translation>
 <translation id="3093245981617870298">No estás conectado.</translation>
 <translation id="3105172416063519923">ID de recurso:</translation>
 <translation id="3109728660330352905">No tienes autorización para ver esta página.</translation>
diff --git a/components/strings/components_strings_es.xtb b/components/strings/components_strings_es.xtb
index 5763837..cf6ce4a 100644
--- a/components/strings/components_strings_es.xtb
+++ b/components/strings/components_strings_es.xtb
@@ -182,7 +182,7 @@
 <translation id="2985306909656435243">Si se habilita esta opción, Chromium guardará una copia de tu tarjeta en este dispositivo para completar formularios más rápidamente.</translation>
 <translation id="2991174974383378012">Compartir con otros sitios web</translation>
 <translation id="3005723025932146533">Mostrar copia guardada</translation>
-<translation id="3008447029300691911">Introduce el código CVC de la tarjeta <ph name="CREDIT_CARD" />. Cuando lo confirmes, la información de la tarjeta se compartirá con este sitio web.</translation>
+<translation id="3008447029300691911">Introduce el código CVC de la tarjeta <ph name="CREDIT_CARD" />. Cuando la confirmes, su información se compartirá con este sitio web.</translation>
 <translation id="3010559122411665027">Entrada de lista "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">Tipo de política incorrecto</translation>
 <translation id="3032412215588512954">¿Quieres volver a cargar este sitio web?</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">La conexión utiliza <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">¡Vaya! Debes pedir permiso a uno de tus padres para poder acceder a esta página.</translation>
 <translation id="7246609911581847514">Este mensaje aparece porque el administrador debe aprobar los sitios web nuevos cuando accedas a ellos por primera vez.</translation>
-<translation id="724975217298816891">Introduce la fecha de caducidad y el código CVC de la tarjeta <ph name="CREDIT_CARD" /> para actualizar sus detalles. Cuando confirmes los datos, la información de la tarjeta se compartirá con este sitio web.</translation>
+<translation id="724975217298816891">Introduce la fecha de caducidad y el código CVC de la tarjeta <ph name="CREDIT_CARD" /> para actualizar sus detalles. Cuando la confirmes, su información se compartirá con este sitio web.</translation>
 <translation id="725866823122871198">No se puede establecer una conexión privada con <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> porque la fecha y la hora de tu ordenador (<ph name="DATE_AND_TIME" />) no son correctas.</translation>
 <translation id="7265986070661382626">No puedes acceder a <ph name="SITE" /> en este momento porque el sitio web <ph name="BEGIN_LINK" />utiliza la fijación de certificados<ph name="END_LINK" />. Los ataques y los errores de red suelen ser temporales, por lo que es probable que esta página funcione más tarde.</translation>
 <translation id="7269802741830436641">Esta página web tiene un bucle de redireccionamiento</translation>
@@ -652,7 +652,7 @@
 <translation id="8866959479196209191">Esta página dice:</translation>
 <translation id="8870413625673593573">Cerrado recientemente</translation>
 <translation id="8876793034577346603">No se ha podido analizar la configuración de red.</translation>
-<translation id="8877192140621905067">Cuando confirmes los datos, la información de la tarjeta se compartirá con este sitio web</translation>
+<translation id="8877192140621905067">Cuando confirmes la tarjeta, su información se compartirá con este sitio web</translation>
 <translation id="8891727572606052622">El modo de proxy no es válido.</translation>
 <translation id="889901481107108152">Esta función experimental no está disponible en tu plataforma.</translation>
 <translation id="8903921497873541725">Acercar</translation>
diff --git a/components/strings/components_strings_fil.xtb b/components/strings/components_strings_fil.xtb
index 460e7af..c7b9250 100644
--- a/components/strings/components_strings_fil.xtb
+++ b/components/strings/components_strings_fil.xtb
@@ -182,7 +182,7 @@
 <translation id="2985306909656435243">Kung naka-enable, mag-iimbak ang Chromium ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
 <translation id="2991174974383378012">Pagbabahagi sa Mga Website</translation>
 <translation id="3005723025932146533">Ipakita ang naka-save na kopya</translation>
-<translation id="3008447029300691911">Ilagay ang CVC para sa <ph name="CREDIT_CARD" />. Kapag nakumpirma mo na, ibabahagi ang mga detalye ng iyong card sa site na ito.</translation>
+<translation id="3008447029300691911">Ilagay ang CVC para sa <ph name="CREDIT_CARD" />. Kapag nagkumpirma ka na, ibabahagi ang mga detalye ng iyong card sa site na ito.</translation>
 <translation id="3010559122411665027">Listahan ng entry na "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">Maling uri ng patakaran</translation>
 <translation id="3032412215588512954">Gusto mo bang i-reload ang site na ito?</translation>
@@ -208,7 +208,7 @@
 <translation id="3225919329040284222">Nagpakita ang server ng certificate na hindi tumutugma sa mga built-in na inaasahan. Ang mga inaasahang ito ay isinama para sa ilang partikular na website na may mataas na antas ng seguridad upang maprotektahan ka.</translation>
 <translation id="3226128629678568754">Pindutin ang button na i-reload upang isumiteng muli ang data na kailangan upang ma-load ang pahina.</translation>
 <translation id="3228969707346345236">Nabigo ang pag-translate dahil nasa <ph name="LANGUAGE" /> na ang pahina.</translation>
-<translation id="323107829343500871">Ilagay ang CVC para sa <ph name="CREDIT_CARD" /></translation>
+<translation id="323107829343500871">Ilagay ang iyong CVC para sa <ph name="CREDIT_CARD" /></translation>
 <translation id="3254409185687681395">I-bookmark ang page na ito</translation>
 <translation id="3270847123878663523">&amp;I-undo ang Pagbabago sa Ayos</translation>
 <translation id="3286538390144397061">I-restart Ngayon</translation>
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">Naka-block</translation>
 <translation id="5710435578057952990">Ang pagkilala ng website na ito ay hindi natukoy.</translation>
 <translation id="5720705177508910913">Kasalukuyang user</translation>
-<translation id="5784606427469807560">Nagkaroon ng problema sa pagkumpirma ng iyong card. Suriin ang iyong koneksyon sa internet at subukang muli.</translation>
+<translation id="5784606427469807560">Nagkaroon ng problema sa pagkumpirma ng iyong card. Suriin ang koneksyon sa internet at subukang muli.</translation>
 <translation id="5785756445106461925">Bukod pa rito, ang page na ito ay may iba pang mga mapagkukunang hindi secure. Makikita ng iba ang mga mapagkukunang ito habang ipinadadala, at maaaring baguhin ng isang umaatake upang baguhin ang hitsura ng page.</translation>
 <translation id="5810442152076338065">Naka-encrypt ang iyong koneksyon sa <ph name="DOMAIN" /> gamit ang isang hindi na ginagamit na cipher suite.</translation>
 <translation id="5813119285467412249">&amp;Gawing Muli ang Pagdagdag</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">Gumagamit ng <ph name="SSL_VERSION" /> ang koneksyon.</translation>
 <translation id="7231308970288859235">Oops! Kailangan mong tanungin ang iyong magulang kung OK lang na bisitahin ang page na ito.</translation>
 <translation id="7246609911581847514">Nakikita mo ang mensaheng ito dahil kailangang aprubahan ng iyong manager ang mga bagong site sa una mong pagbisita.</translation>
-<translation id="724975217298816891">Ilagay ang expiration date at CVC para sa <ph name="CREDIT_CARD" /> upang ma-update ang mga detalye ng iyong card. Kapag nakumpirma mo na, ibabahagi ang mga detalye ng iyong card sa site na ito.</translation>
+<translation id="724975217298816891">Ilagay ang petsa ng expiration at CVC para sa <ph name="CREDIT_CARD" /> upang i-update ang mga detalye ng iyong card. Kapag nagkumpirma ka na, ibabahagi ang mga detalye ng iyong card sa site na ito.</translation>
 <translation id="725866823122871198">Hindi makapagtatag ng pribadong koneksyon sa <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> dahil mali ang petsa at oras ng iyong computer (<ph name="DATE_AND_TIME" />).</translation>
 <translation id="7265986070661382626">Hindi mo maaaring bisitahin ang <ph name="SITE" /> sa ngayon dahil ang website ay <ph name="BEGIN_LINK" />gumagamit ng pagpi-pin ng certificate<ph name="END_LINK" />. Kadalasang pansamantala lang ang mga error at atake sa network, kaya malamang na gagana ang page na ito sa ibang pagkakataon.</translation>
 <translation id="7269802741830436641">Ang webpage na ito ay may loop na pag-redirect</translation>
@@ -652,7 +652,7 @@
 <translation id="8866959479196209191">Isinasaad ng page na ito na:</translation>
 <translation id="8870413625673593573">Recently Closed</translation>
 <translation id="8876793034577346603">Nabigong ma-parse ang configuration ng network.</translation>
-<translation id="8877192140621905067">Kapag nakumpirma mo na, ibabahagi ang mga detalye ng iyong card sa site na ito</translation>
+<translation id="8877192140621905067">Kapag nagkumpirma ka na, ibabahagi ang mga detalye ng iyong card sa site na ito</translation>
 <translation id="8891727572606052622">Di-wastong mode ng proxy.</translation>
 <translation id="889901481107108152">Paumanhin, hindi available ang eksperimentong ito sa iyong platform.</translation>
 <translation id="8903921497873541725">Mag-zoom in</translation>
@@ -686,7 +686,7 @@
 <translation id="935608979562296692">CLEAR FORM</translation>
 <translation id="939736085109172342">Bagong folder</translation>
 <translation id="943029900877297437">Upang gamitin ang mga card na na-save mo sa iyong Google Account, mag-sign in sa Chrome.</translation>
-<translation id="962701380617707048">Ilagay ang expiration date at CVC para sa <ph name="CREDIT_CARD" /> upang ma-update ang mga detalye ng iyong card</translation>
+<translation id="962701380617707048">Ilagay ang petsa ng expiration at CVC para sa <ph name="CREDIT_CARD" /> upang i-update ang mga detalye ng iyong card</translation>
 <translation id="969892804517981540">Official Build</translation>
 <translation id="988159990683914416">Bumuo ang Developer</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/strings/components_strings_fr.xtb b/components/strings/components_strings_fr.xtb
index 189e2876..5d84cdca 100644
--- a/components/strings/components_strings_fr.xtb
+++ b/components/strings/components_strings_fr.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">Voulez-vous vraiment supprimer ces pages de votre historique ?</translation>
 <translation id="2677748264148917807">Quitter</translation>
 <translation id="2704283930420550640">La valeur ne respecte pas le format requis.</translation>
-<translation id="2704951214193499422">Impossible de vérifier votre carte dans Chromium pour le moment. Veuillez réessayer plus tard.</translation>
+<translation id="2704951214193499422">Impossible de valider votre carte dans Chromium pour le moment. Veuillez réessayer plus tard.</translation>
 <translation id="2705137772291741111">La copie enregistrée (en cache) de ce site est illisible.</translation>
 <translation id="2709516037105925701">Saisie automatique</translation>
 <translation id="2712173769900027643">Demander l'autorisation</translation>
@@ -182,13 +182,13 @@
 <translation id="2985306909656435243">Si cette option est activée, Chromium enregistre une copie de votre carte sur cet appareil pour vous permettre de remplir plus rapidement les formulaires.</translation>
 <translation id="2991174974383378012">Partage avec les sites Web</translation>
 <translation id="3005723025932146533">Afficher la copie enregistrée</translation>
-<translation id="3008447029300691911">Saisissez le code CVC de la carte <ph name="CREDIT_CARD" />. Une fois la vérification terminée, les informations relatives à la carte seront partagées avec ce site.</translation>
+<translation id="3008447029300691911">Saisissez le code CVC de la carte <ph name="CREDIT_CARD" />. Une fois la validation terminée, les informations relatives à la carte seront partagées avec ce site.</translation>
 <translation id="3010559122411665027">Entrée de la liste "<ph name="ENTRY_INDEX" />" : <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">Type de règle incorrect.</translation>
 <translation id="3032412215588512954">Voulez-vous actualiser ce site ?</translation>
 <translation id="3037605927509011580">Aie aie aie</translation>
 <translation id="3041612393474885105">Informations relatives au certificat</translation>
-<translation id="3063697135517575841">Impossible de vérifier votre carte dans Chrome pour le moment. Veuillez réessayer plus tard.</translation>
+<translation id="3063697135517575841">Impossible de valider votre carte dans Chrome pour le moment. Veuillez réessayer plus tard.</translation>
 <translation id="3093245981617870298">Vous êtes actuellement hors connexion</translation>
 <translation id="3105172416063519923">ID d'élément :</translation>
 <translation id="3109728660330352905">Vous n'êtes pas autorisé à consulter cette page.</translation>
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">Bloqué</translation>
 <translation id="5710435578057952990">L'identité de ce site Web n'a pas été vérifiée.</translation>
 <translation id="5720705177508910913">Utilisateur actuel</translation>
-<translation id="5784606427469807560">Un problème est survenu lors de la vérification de votre carte. Vérifiez votre connexion Internet, puis réessayez.</translation>
+<translation id="5784606427469807560">Un problème est survenu lors de la validation de votre carte. Vérifiez votre connexion Internet, puis réessayez.</translation>
 <translation id="5785756445106461925">De plus, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer l'aspect de cette page.</translation>
 <translation id="5810442152076338065">Votre connexion à <ph name="DOMAIN" /> est chiffrée à l'aide d'une méthode de chiffrement obsolète.</translation>
 <translation id="5813119285467412249">&amp;Rétablir l'ajout</translation>
@@ -484,7 +484,7 @@
 <translation id="6839929833149231406">Région</translation>
 <translation id="6874604403660855544">&amp;Rétablir l'ajout</translation>
 <translation id="6891596781022320156">Le niveau de la règle n'est pas accepté.</translation>
-<translation id="6895330447102777224">Carte vérifiée</translation>
+<translation id="6895330447102777224">Carte validée</translation>
 <translation id="6897140037006041989">Agent utilisateur</translation>
 <translation id="6903907808598579934">Activer la synchronisation</translation>
 <translation id="6915804003454593391">Utilisateur :</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">La connexion utilise <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Petit problème… Tu dois demander à ton papa/ta maman l'autorisation de consulter cette page.</translation>
 <translation id="7246609911581847514">Ce message s'affiche, car votre responsable doit approuver les nouveaux sites lorsque vous les consultez pour la première fois.</translation>
-<translation id="724975217298816891">Saisissez la date d'expiration et le code CVC de la carte <ph name="CREDIT_CARD" /> pour mettre à jour les informations relatives à celle-ci. Une fois la vérification terminée, les informations seront partagées avec ce site.</translation>
+<translation id="724975217298816891">Saisissez la date d'expiration et le code CVC de la carte <ph name="CREDIT_CARD" /> pour mettre à jour les informations relatives à celle-ci. Une fois la validation effectuée, les informations seront partagées avec ce site.</translation>
 <translation id="725866823122871198">Impossible d'établir une connexion privée à <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> : la date et l'heure de votre ordinateur (<ph name="DATE_AND_TIME" />) sont incorrectes.</translation>
 <translation id="7265986070661382626">Vous ne pouvez pas consulter le site <ph name="SITE" /> pour le moment, car l'<ph name="BEGIN_LINK" />épinglage des certificats<ph name="END_LINK" /> y est utilisé. Les erreurs réseau et les attaques sont généralement temporaires. Vous devriez donc pouvoir accéder à cette page ultérieurement.</translation>
 <translation id="7269802741830436641">Cette page Web présente une boucle de redirection.</translation>
@@ -527,7 +527,7 @@
 <translation id="7377249249140280793"><ph name="RELATIVE_DATE" /> - <ph name="FULL_DATE" /></translation>
 <translation id="7378627244592794276">Non</translation>
 <translation id="7378810950367401542">/</translation>
-<translation id="7390545607259442187">Vérifier la carte</translation>
+<translation id="7390545607259442187">Valider la carte</translation>
 <translation id="7394102162464064926">Voulez-vous vraiment supprimer ces pages de votre historique ?
 
 Conseil : Le mode navigation privée (<ph name="SHORTCUT_KEY" />) pourra vous être utile la prochaine fois.</translation>
@@ -537,7 +537,7 @@
 <translation id="7441627299479586546">Objet de la règle incorrect.</translation>
 <translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
 <translation id="7451311239929941790"><ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /> sur ce problème.</translation>
-<translation id="7469372306589899959">Vérification de la carte…</translation>
+<translation id="7469372306589899959">Validation de la carte…</translation>
 <translation id="7481312909269577407">Avancer</translation>
 <translation id="7485870689360869515">Aucune donnée n'a été trouvée.</translation>
 <translation id="7514365320538308">Télécharger</translation>
@@ -652,7 +652,7 @@
 <translation id="8866959479196209191">Cette page indique :</translation>
 <translation id="8870413625673593573">Récemment fermés</translation>
 <translation id="8876793034577346603">Échec de l'analyse de la configuration du réseau.</translation>
-<translation id="8877192140621905067">Une fois la vérification terminée, les informations relatives à votre carte seront partagées avec ce site.</translation>
+<translation id="8877192140621905067">Une fois la validation terminée, les informations relatives à votre carte seront partagées avec ce site.</translation>
 <translation id="8891727572606052622">Mode proxy non valide.</translation>
 <translation id="889901481107108152">Désolé, cette fonctionnalité expérimentale n'est pas disponible pour votre plate-forme.</translation>
 <translation id="8903921497873541725">Zoom avant</translation>
diff --git a/components/strings/components_strings_hi.xtb b/components/strings/components_strings_hi.xtb
index 074fd1a3..c579de8e 100644
--- a/components/strings/components_strings_hi.xtb
+++ b/components/strings/components_strings_hi.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">क्या आप वाकई अपने इतिहास से इन पृष्ठों को हटाना चाहते हैं?</translation>
 <translation id="2677748264148917807">छोड़ें</translation>
 <translation id="2704283930420550640">मान का प्रारूप से मिलान नहीं होता.</translation>
-<translation id="2704951214193499422">क्रोमियम इस समय आपका कार्ड सत्‍यापित नहीं कर सका. कृपया बाद में पुनः प्रयास करें.</translation>
+<translation id="2704951214193499422">क्रोमियम इस समय आपके कार्ड की पुष्टि नहीं कर सका. कृपया बाद में पुन: प्रयास करें.</translation>
 <translation id="2705137772291741111">इस साइट की सहेजी गई (संचित) कॉपी पढ़ने योग्य नहीं थी.</translation>
 <translation id="2709516037105925701">ऑटोमैटिक भरना</translation>
 <translation id="2712173769900027643">अनुमति मांगें</translation>
@@ -182,13 +182,13 @@
 <translation id="2985306909656435243">यदि सक्षम किया गया हो, तो अधिक तेज़ी से फ़ॉर्म भरने के लिए क्रोमियम इस डिवाइस पर आपके कार्ड की एक कॉपी संग्रहीत करेगा.</translation>
 <translation id="2991174974383378012">वेबसाइटों के साथ साझाकरण</translation>
 <translation id="3005723025932146533">सहेजी गई प्रतिलिपि दिखाएं</translation>
-<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> का CVC डालें. आपकी तरफ से पुष्टि होने पर, आपके कार्ड के विवरण इस साइट के साथ साझा किए जाएंगे.</translation>
+<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> का CVC डालें. आपकी तरफ से पुष्टि हो जाने पर, आपके कार्ड के विवरण इस साइट के साथ साझा किए जाएंगे.</translation>
 <translation id="3010559122411665027">सूची प्रविष्ट‍ि "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">गलत नीति प्रकार</translation>
 <translation id="3032412215588512954">क्या आप इस साइट को फिर से लोड करना चाहते हैं?</translation>
 <translation id="3037605927509011580">हे भगवान!</translation>
 <translation id="3041612393474885105">प्रमाणपत्र जानकारी</translation>
-<translation id="3063697135517575841">Chrome इस समय आपका कार्ड सत्‍यापित नहीं कर सका. कृपया बाद में पुनः प्रयास करें.</translation>
+<translation id="3063697135517575841">Chrome इस समय आपके कार्ड की पुष्टि नहीं कर सका. कृपया बाद में पुन: प्रयास करें.</translation>
 <translation id="3093245981617870298">आप ऑफ़लाइन हैं.</translation>
 <translation id="3105172416063519923">एसेट आईडी:</translation>
 <translation id="3109728660330352905">आपके पास इस पृष्ठ को देखने के लिए प्राधिकरण नहीं है.</translation>
@@ -208,7 +208,7 @@
 <translation id="3225919329040284222">सर्वर द्वारा कोई प्रमाणपत्र प्रस्‍तुत किया गया, जो बिल्‍ट-इन अपेक्षाओं से मिलान नहीं करता. इन अपेक्षाओं को आपकी सुरक्षा करने के लिए कुछ, उच्‍च-सुरक्षा वेबसाइटों के लिए शामिल किया गया है.</translation>
 <translation id="3226128629678568754">पृष्ठ को लोड करने के लिए आवश्यक डेटा पुन: सबमिट करने के लिए पुन: लोड करें बटन दबाएं.</translation>
 <translation id="3228969707346345236">अनुवाद विफल हो गया क्योंकि पृष्ठ पहले से ही <ph name="LANGUAGE" /> में है.</translation>
-<translation id="323107829343500871"><ph name="CREDIT_CARD" /> का CVC डालें</translation>
+<translation id="323107829343500871"><ph name="CREDIT_CARD" /> का CVC डालें.</translation>
 <translation id="3254409185687681395">इस पृष्ठ को बुकमार्क करें</translation>
 <translation id="3270847123878663523">&amp;पुन: क्रमित करना वापस लाएं</translation>
 <translation id="3286538390144397061">अभी फिर से प्रारंभ करें</translation>
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">अवरोधित</translation>
 <translation id="5710435578057952990">इस वेबसाइट की पहचान सत्यापित नहीं की गई है.</translation>
 <translation id="5720705177508910913">वर्तमान उपयोगकर्ता</translation>
-<translation id="5784606427469807560">आपका कार्ड सत्‍यापित करते समय समस्‍या हुई. अपना इंटरनेट कनेक्‍शन जांचें और पुनः प्रयास करें.</translation>
+<translation id="5784606427469807560">आपके कार्ड की पुष्टि करते समय समस्‍या हुई. अपना इंटरनेट कनेक्‍शन जांचें और पुन: प्रयास करें.</translation>
 <translation id="5785756445106461925">इसके अतिरिक्त, इस पृष्ठ में ऐसे अन्य संसाधन भी शामिल हैं, जो सुरक्षित नहीं हैं. ट्रांज़िट में होने के दौरान ये संसाधन अन्य लोगों द्वारा देखे जा सकते हैं और पृष्ठ का स्वरूप बदलने के लिए किसी हमवलावर द्वारा इनमें बदलाव किए जा सकते हैं.</translation>
 <translation id="5810442152076338065"><ph name="DOMAIN" /> से आपके कनेक्शन को किसी अप्रचलित सिफ़र सुइट का उपयोग करके एन्‍क्रिप्‍ट किया गया है.</translation>
 <translation id="5813119285467412249">&amp;जोड़ना फिर से करें</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">कनेक्‍शन <ph name="SSL_VERSION" /> का उपयोग करता है.</translation>
 <translation id="7231308970288859235">ओह! आपको अपने अभिभावक से पूछना होगा कि इस पृष्‍ठ पर जाना ठीक है या नहीं.</translation>
 <translation id="7246609911581847514">आपको यह संदेश इसलिए दिखाई दे रहा है क्योंकि किसी नई साइट पर आपके पहली बार जाने से पहले आपके प्रबंधक को उसे स्वीकृति देनी होगी.</translation>
-<translation id="724975217298816891">अपने कार्ड विवरण अपडेट करने के लिए <ph name="CREDIT_CARD" /> का समय समाप्ति दिनांक और CVC डालें. पुष्टि कर लेने पर, आपके कार्ड के विवरण इस साइट के साथ साझा किए जाएंगे.</translation>
+<translation id="724975217298816891">अपने कार्ड विवरण अपडेट करने के लिए <ph name="CREDIT_CARD" /> का समय समाप्ति दिनांक और CVC डालें. आपकी तरफ से पुष्टि हो जाने पर, आपके कार्ड के विवरण इस साइट के साथ साझा किए जाएंगे.</translation>
 <translation id="725866823122871198"><ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> से एक निजी कनेक्‍शन स्‍थापित नहीं किया जा सकता क्‍योंकि आपके कंप्‍यूटर का दिनांक और समय (<ph name="DATE_AND_TIME" />) गलत है.</translation>
 <translation id="7265986070661382626">आप इस समय <ph name="SITE" /> पर विज़िट नहीं कर सकते क्योंकि वेबसाइट <ph name="BEGIN_LINK" />प्रमाणपत्र पिनिंग का उपयोग<ph name="END_LINK" /> करती है. नेटवर्क की त्रुटियां और हमले आमतौर पर अस्थायी होते हैं, इसलिए संभवत: यह पृष्ठ बाद में काम करेगा.</translation>
 <translation id="7269802741830436641">इस वेबपृष्ठ में एक रीडायरेक्ट लूप है</translation>
@@ -650,7 +650,7 @@
 <translation id="8866959479196209191">इस पृष्‍ठ का कहना है:</translation>
 <translation id="8870413625673593573">हाल ही में बंद किए गए</translation>
 <translation id="8876793034577346603">नेटवर्क कॉन्फ़िगरेशन पार्स होने में विफल रहा.</translation>
-<translation id="8877192140621905067">आपकी तरफ से पुष्टि होने पर, आपके कार्ड के विवरण इस साइट के साथ साझा किए जाएंगे</translation>
+<translation id="8877192140621905067">आपकी तरफ से पुष्टि हो जाने पर, आपके कार्ड के विवरण इस साइट के साथ साझा किए जाएंगे</translation>
 <translation id="8891727572606052622">अमान्य प्रॉक्सी मोड.</translation>
 <translation id="889901481107108152">क्षमा करें, यह प्रयोग आपके प्‍लेटफ़ॉर्म पर उपलब्ध नहीं है.</translation>
 <translation id="8903921497873541725">ज़ूम इन करें</translation>
diff --git a/components/strings/components_strings_id.xtb b/components/strings/components_strings_id.xtb
index 91223c1..128495a44 100644
--- a/components/strings/components_strings_id.xtb
+++ b/components/strings/components_strings_id.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">Yakin ingin menghapus laman ini dari riwayat?</translation>
 <translation id="2677748264148917807">Keluar</translation>
 <translation id="2704283930420550640">Nilai tidak sesuai format.</translation>
-<translation id="2704951214193499422">Saat ini, Chromium tidak dapat mengonfirmasi kartu Anda. Coba lagi nanti.</translation>
+<translation id="2704951214193499422">Saat ini Chromium tidak dapat mengonfirmasi kartu. Coba lagi nanti.</translation>
 <translation id="2705137772291741111">Salinan tersimpan (dalam cache) situs ini tidak dapat dibaca.</translation>
 <translation id="2709516037105925701">Isi-Otomatis</translation>
 <translation id="2712173769900027643">Minta izin</translation>
@@ -188,7 +188,7 @@
 <translation id="3032412215588512954">Ingin memuat ulang situs ini?</translation>
 <translation id="3037605927509011580">Yah!</translation>
 <translation id="3041612393474885105">Informasi Sertifikat</translation>
-<translation id="3063697135517575841">Saat ini, Chrome tidak dapat mengonfirmasi kartu Anda. Coba lagi nanti.</translation>
+<translation id="3063697135517575841">Saat ini Chrome tidak dapat mengonfirmasi kartu. Coba lagi nanti.</translation>
 <translation id="3093245981617870298">Anda sedang offline.</translation>
 <translation id="3105172416063519923">ID Aset:</translation>
 <translation id="3109728660330352905">Anda tidak memiliki otorisasi untuk melihat laman ini.</translation>
@@ -208,7 +208,7 @@
 <translation id="3225919329040284222">Server menunjukkan sertifikat yang tidak sesuai dengan harapan terpasang. Harapan ini disertakan untuk situs web tertentu dengan keamanan tinggi guna melindungi Anda.</translation>
 <translation id="3226128629678568754">Tekan tombol muat ulang untuk mengirimkan lagi data yang dibutuhkan untuk memuat laman ini.</translation>
 <translation id="3228969707346345236">Terjemahan gagal karena laman sudah dalam bahasa <ph name="LANGUAGE" />.</translation>
-<translation id="323107829343500871">Memasukkan CVC untuk <ph name="CREDIT_CARD" /></translation>
+<translation id="323107829343500871">Masukkan CVC untuk <ph name="CREDIT_CARD" /></translation>
 <translation id="3254409185687681395">Bookmark laman ini</translation>
 <translation id="3270847123878663523">&amp;Urungkan Pengaturan Ulang</translation>
 <translation id="3286538390144397061">Mulai Ulang Sekarang</translation>
@@ -484,7 +484,7 @@
 <translation id="6839929833149231406">Area</translation>
 <translation id="6874604403660855544">&amp;Ulangi penambahan</translation>
 <translation id="6891596781022320156">Tingkat kebijakan tidak didukung.</translation>
-<translation id="6895330447102777224">Kartu Anda dikonfirmasi</translation>
+<translation id="6895330447102777224">Kartu telah dikonfirmasi</translation>
 <translation id="6897140037006041989">Agen Pengguna</translation>
 <translation id="6903907808598579934">Aktifkan sinkronisasi</translation>
 <translation id="6915804003454593391">Pengguna:</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">Koneksi menggunakan <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Ups! Anda perlu izin orang tua untuk mengunjungi laman ini.</translation>
 <translation id="7246609911581847514">Anda melihat pesan ini karena Anda baru pertama kali mengunjungi situs ini dan pengelola harus menyetujuinya terlebih dahulu.</translation>
-<translation id="724975217298816891">Masukkan tanggal masa berlaku kartu dan CVC untuk <ph name="CREDIT_CARD" /> guna memperbarui detail kartu. Setelah mengonfirmasi, detail kartu Anda akan dibagikan dengan situs ini.</translation>
+<translation id="724975217298816891">Masukkan tanggal habis masa berlaku dan CVC untuk <ph name="CREDIT_CARD" /> guna memperbarui detail kartu. Setelah mengonfirmasi, detail kartu Anda akan dibagikan dengan situs ini.</translation>
 <translation id="725866823122871198">Sambungan pribadi ke <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> tidak dapat dibuat karena tanggal dan waktu (<ph name="DATE_AND_TIME" />) komputer Anda tidak benar.</translation>
 <translation id="7265986070661382626">Anda tidak dapat mengunjungi <ph name="SITE" /> saat ini karena situs web <ph name="BEGIN_LINK" />menggunakan penyematan sertifikat<ph name="END_LINK" />. Kesalahan jaringan dan serangan biasanya bersifat sementara, jadi laman ini mungkin akan bekerja nanti.</translation>
 <translation id="7269802741830436641">Laman web ini memiliki simpul pengalihan</translation>
@@ -686,7 +686,7 @@
 <translation id="935608979562296692">HAPUS FORMULIR</translation>
 <translation id="939736085109172342">Folder baru</translation>
 <translation id="943029900877297437">Untuk menggunakan kartu yang disimpan ke Akun Google, masuk ke Chrome.</translation>
-<translation id="962701380617707048">Masukkan tanggal masa berlaku dan CVC untuk <ph name="CREDIT_CARD" /> guna memperbarui detail kartu Anda</translation>
+<translation id="962701380617707048">Masukkan tanggal habis masa berlaku dan CVC untuk <ph name="CREDIT_CARD" /> guna memperbarui detail kartu Anda</translation>
 <translation id="969892804517981540">Pembuatan Resmi</translation>
 <translation id="988159990683914416">Buatan Pengembang</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/strings/components_strings_kn.xtb b/components/strings/components_strings_kn.xtb
index 16bdd3f..4ddc5c0 100644
--- a/components/strings/components_strings_kn.xtb
+++ b/components/strings/components_strings_kn.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">ನಿಮ್ಮ ಇತಿಹಾಸದಿಂದ ನೀವು ಈ ಪುಟಗಳನ್ನು ಖಚಿತವಾಗಿ ಅಳಿಸಲು ಬಯಸುತ್ತಿದ್ದೀರಾ?</translation>
 <translation id="2677748264148917807">ತೊರೆಯಿರಿ</translation>
 <translation id="2704283930420550640">ಮೌಲ್ಯವು ಸ್ವರೂಪಕ್ಕೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ.</translation>
-<translation id="2704951214193499422">ಈ ಸಮಯದಲ್ಲಿ Chromium ಗೆ ನಿಮ್ಮ ಕಾರ್ಡನ್ನು ದೃಢಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
+<translation id="2704951214193499422">ಈ ಸಮಯದಲ್ಲಿ Chromium ಗೆ ನಿಮ್ಮ ಕಾರ್ಡ್ ಖಚಿತಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
 <translation id="2705137772291741111">ಈ ಸೈಟ್‌ನ ಉಳಿಸಿದ (ಸಂಗ್ರಹವಾಗಿರುವ) ನಕಲನ್ನು ಓದಲಾಗುತ್ತಿಲ್ಲ.</translation>
 <translation id="2709516037105925701">ಸ್ವಯಂತುಂಬುವಿಕೆ</translation>
 <translation id="2712173769900027643">ಅನುಮತಿ ಕೇಳಿ</translation>
@@ -182,13 +182,13 @@
 <translation id="2985306909656435243">ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದರೆ, ವೇಗವಾಗಿ ಫಾರ್ಮ್ ಭರ್ತಿ ಮಾಡಲು Chromium ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ಪ್ರತಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.</translation>
 <translation id="2991174974383378012">ವೆಬ್‌ಸೈಟ್‌ಗಳ ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳುವುದು</translation>
 <translation id="3005723025932146533">ಉಳಿಸಲಾದ ನಕಲನ್ನು ತೋರಿಸು</translation>
-<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> ಗೆ CVC ಅನ್ನು ನಮೂದಿಸಿ. ನೀವು ಒಮ್ಮೆ ದೃಢಪಡಿಸಿದರೆ, ನಿಮ್ಮ ಕಾರ್ಡ್ ವಿವರಗಳನ್ನು ಈ ಸೈಟ್ ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.</translation>
+<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> ಗೆ CVC ಅನ್ನು ನಮೂದಿಸಿ. ನೀವು ಒಮ್ಮೆ ಖಚಿತಪಡಿಸಿದರೆ, ನಿಮ್ಮ ಕಾರ್ಡ್ ವಿವರಗಳನ್ನು ಈ ಸೈಟ್ ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.</translation>
 <translation id="3010559122411665027">ಪಟ್ಟಿ ನಮೂದು "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">ತಪ್ಪಾದ ನೀತಿಯ ಪ್ರಕಾರ</translation>
 <translation id="3032412215588512954">ನೀವು ಈ ಸೈಟ್ ಮರುಲೋಡ್ ಮಾಡಲು ಬಯಸುವಿರಾ?</translation>
 <translation id="3037605927509011580">ಓಹ್, ಹೋಯ್ತು!</translation>
 <translation id="3041612393474885105">ಪ್ರಮಾಣಪತ್ರ ಮಾಹಿತಿ</translation>
-<translation id="3063697135517575841">ಈ ಸಮಯದಲ್ಲಿ Chrome ಗೆ ನಿಮ್ಮ ಕಾರ್ಡನ್ನು ದೃಢಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
+<translation id="3063697135517575841">ಈ ಸಮಯದಲ್ಲಿ Chrome ಗೆ ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಖಚಿತಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
 <translation id="3093245981617870298">ನೀವು ಆಫ್‌ಲೈನ್‌ನಲ್ಲಿರುವಿರಿ.</translation>
 <translation id="3105172416063519923">ಸ್ವತ್ತು ID:</translation>
 <translation id="3109728660330352905">ಈ ಪುಟ ವೀಕ್ಷಿಸುವ ಅಧಿಕಾರ ನಿಮಗಿಲ್ಲ</translation>
@@ -407,7 +407,7 @@
 <translation id="5677928146339483299">ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
 <translation id="5710435578057952990">ಈ ವೆಬ್‌ಸೈಟ್‌ನ ಗುರುತಿಸುವಿಕೆಯನ್ನು ಇನ್ನೂ ಪರಿಶೀಲಿಸಲಾಗಿಲ್ಲ.</translation>
 <translation id="5720705177508910913">ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ</translation>
-<translation id="5784606427469807560">ನಿಮ್ಮ ಕಾರ್ಡನ್ನು ದೃಢೀಕರಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಇದೆ. ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
+<translation id="5784606427469807560">ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ದೃಢೀಕರಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಇದೆ. ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
 <translation id="5785756445106461925">ಅಲ್ಲದೇ, ಸುರಕ್ಷಿತವಲ್ಲದ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಈ ಪುಟ ಒಳಗೊಂಡಿದೆ. ಪ್ರಯಾಣದ ಸಂದರ್ಭದಲ್ಲಿ ಈ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಇತರರೂ ವೀಕ್ಷಿಸಬಹುದಾಗಿದೆ ಮತ್ತು ಪುಟದ ನೋಟವೇ ಬದಲಾಗುವಂತೆ ಆಕ್ರಮಣಕಾರರು ಅದನ್ನು ತಿದ್ದಬಹುದಾಗಿದೆ.</translation>
 <translation id="5810442152076338065">ಬಳಕೆಯಲ್ಲಿಲ್ಲದ ಸೈಫರ್ ಸೂಟ್ ಬಳಸುವ ಮೂಲಕ <ph name="DOMAIN" /> ಗೆ ನಿಮ್ಮ ಸಂಪರ್ಕವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ.</translation>
 <translation id="5813119285467412249">&amp;ಸೇರಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
diff --git a/components/strings/components_strings_mr.xtb b/components/strings/components_strings_mr.xtb
index a4efb13..17a3896 100644
--- a/components/strings/components_strings_mr.xtb
+++ b/components/strings/components_strings_mr.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">आपली खात्री आहे की आपण ही पृष्ठे आपल्‍या इतिहासातून हटवू इच्छिता?</translation>
 <translation id="2677748264148917807">सोडा</translation>
 <translation id="2704283930420550640">मूल्य स्वरुपनाशी जुळत नाही.</translation>
-<translation id="2704951214193499422">Chromium यावेळी आपले कार्ड सत्यापित करण्यात अक्षम होते. कृपया नंतर पुन्हा प्रयत्न करा.</translation>
+<translation id="2704951214193499422">Chromium यावेळी आपल्या कार्डची पुष्टी करण्यात अक्षम होते. कृपया नंतर पुन्हा प्रयत्न करा.</translation>
 <translation id="2705137772291741111">या साइटची जतन (कॅशे केलेली) केलेली प्रत वाचण्याजोगी नव्हती.</translation>
 <translation id="2709516037105925701">ऑटोफिल</translation>
 <translation id="2712173769900027643">परवानगी मागा</translation>
@@ -485,7 +485,7 @@
 <translation id="6839929833149231406">क्षेत्र</translation>
 <translation id="6874604403660855544">&amp;जोडा पुन्हा करा</translation>
 <translation id="6891596781022320156">धोरण स्तर समर्थित नाही.</translation>
-<translation id="6895330447102777224">आपल्या कार्डची पुष्टी झाली</translation>
+<translation id="6895330447102777224">आपल्या कार्डची पुष्टी केली</translation>
 <translation id="6897140037006041989">वापरकर्ता एजंट</translation>
 <translation id="6903907808598579934">सिंक चालू करा</translation>
 <translation id="6915804003454593391">वापरकर्ता:</translation>
diff --git a/components/strings/components_strings_pt-BR.xtb b/components/strings/components_strings_pt-BR.xtb
index 376db9ff..4b59d3df 100644
--- a/components/strings/components_strings_pt-BR.xtb
+++ b/components/strings/components_strings_pt-BR.xtb
@@ -208,7 +208,7 @@
 <translation id="3225919329040284222">O servidor apresentou um certificado que não coincide com as expectativas incorporadas. Estas expectativas são incluídas para determinados websites de alta segurança com a finalidade de oferecer proteção a você.</translation>
 <translation id="3226128629678568754">Pressione o botão "Atualizar" para reenviar os dados necessários para carregar a página.</translation>
 <translation id="3228969707346345236">A tradução falhou porque a página já está em <ph name="LANGUAGE" />.</translation>
-<translation id="323107829343500871">Digitar o CVC do <ph name="CREDIT_CARD" /></translation>
+<translation id="323107829343500871">Digite o CVC do <ph name="CREDIT_CARD" /></translation>
 <translation id="3254409185687681395">Adicionar esta página aos favoritos</translation>
 <translation id="3270847123878663523">&amp;Desfazer reordenar</translation>
 <translation id="3286538390144397061">Reiniciar agora</translation>
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">Bloqueados</translation>
 <translation id="5710435578057952990">A identidade deste site não foi confirmada.</translation>
 <translation id="5720705177508910913">Usuário atual</translation>
-<translation id="5784606427469807560">Ocorreu um problema na confirmação do seu cartão. Verifique a conexão com a Internet e tente novamente.</translation>
+<translation id="5784606427469807560">Ocorreu um problema ao confirmar seu cartão. Verifique a conexão com a Internet e tente novamente.</translation>
 <translation id="5785756445106461925">Além disso, esta página inclui outros recursos que não são seguros. Esses recursos podem ser visualizados por outros usuários enquanto eles navegam e podem ser modificados por um invasor para alterar o comportamento da página.</translation>
 <translation id="5810442152076338065">Sua conexão com <ph name="DOMAIN" /> está criptografada com um pacote de criptografia obsoleto.</translation>
 <translation id="5813119285467412249">&amp;Refazer adicionar</translation>
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">A conexão usa a <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Ops! É preciso permissão dos seus pais para visitar esta página.</translation>
 <translation id="7246609911581847514">Esta mensagem está sendo exibida porque é preciso aprovação do seu gerente para novos sites na sua primeira visita.</translation>
-<translation id="724975217298816891">Digite a data de validade e o CVC do <ph name="CREDIT_CARD" /> para atualizar os detalhes do seu cartão. Depois da confirmação, os detalhes do cartão serão compartilhados com esse site.</translation>
+<translation id="724975217298816891">Digite a data de validade e o CVC do <ph name="CREDIT_CARD" /> para atualizar os detalhes do cartão. Depois da confirmação, os detalhes do cartão serão compartilhados com esse site.</translation>
 <translation id="725866823122871198">Não é possível estabelecer uma conexão privada com <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, porque a data e a hora do seu computador (<ph name="DATE_AND_TIME" />) estão incorretas.</translation>
 <translation id="7265986070661382626">Não é possível acessar <ph name="SITE" /> no momento porque o website <ph name="BEGIN_LINK" />usa a fixação de certificados<ph name="END_LINK" />. Ataques e erros de rede, muitas vezes, são temporários. Portanto, essa página provavelmente funcionará mais tarde.</translation>
 <translation id="7269802741830436641">Esta página da web tem um loop de redirecionamento</translation>
@@ -652,7 +652,7 @@
 <translation id="8866959479196209191">Essa página diz:</translation>
 <translation id="8870413625673593573">Recentemente fechadas</translation>
 <translation id="8876793034577346603">Falha ao analisar a configuração de rede.</translation>
-<translation id="8877192140621905067">Depois da confirmação, os detalhes do seu cartão serão compartilhados com esse site</translation>
+<translation id="8877192140621905067">Depois da confirmação, os detalhes do cartão serão compartilhados com esse site</translation>
 <translation id="8891727572606052622">Modo de proxy inválido.</translation>
 <translation id="889901481107108152">Esta experiência não está disponível na sua plataforma.</translation>
 <translation id="8903921497873541725">Aumentar zoom</translation>
@@ -687,7 +687,7 @@
 <translation id="935608979562296692">LIMPAR FORMULÁRIO</translation>
 <translation id="939736085109172342">Nova pasta</translation>
 <translation id="943029900877297437">Para usar os cartões salvos na sua Conta do Google, faça login no Chrome.</translation>
-<translation id="962701380617707048">Digitar a data de validade e o CVC do <ph name="CREDIT_CARD" /> para atualizar os detalhes do seu cartão</translation>
+<translation id="962701380617707048">Digite a data de validade e o CVC do <ph name="CREDIT_CARD" /> para atualizar os detalhes do cartão</translation>
 <translation id="969892804517981540">Versão oficial</translation>
 <translation id="988159990683914416">Versão do desenvolvedor</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/strings/components_strings_ro.xtb b/components/strings/components_strings_ro.xtb
index 5f32a7f..5478041 100644
--- a/components/strings/components_strings_ro.xtb
+++ b/components/strings/components_strings_ro.xtb
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">Blocat</translation>
 <translation id="5710435578057952990">Identitatea acestui site nu a fost confirmată.</translation>
 <translation id="5720705177508910913">Utilizator curent</translation>
-<translation id="5784606427469807560">A apărut o eroare la confirmarea cardului. Verifică-ți conexiunea la internet și încearcă din nou.</translation>
+<translation id="5784606427469807560">A apărut o eroare la confirmarea cardului. Verifică conexiunea la internet și încearcă din nou.</translation>
 <translation id="5785756445106461925">În plus, această pagină include alte resurse care nu sunt securizate. Aceste resurse sunt vizibile pentru alți utilizatori în cursul transferului și pot fi modificate de un atacator pentru a schimba aspectul paginii.</translation>
 <translation id="5810442152076338065">Conexiunea la <ph name="DOMAIN" /> este criptată folosind o suită de codificare învechită.</translation>
 <translation id="5813119285467412249">&amp;Repetați adăugarea</translation>
diff --git a/components/strings/components_strings_sr.xtb b/components/strings/components_strings_sr.xtb
index 3372ddd..c760245 100644
--- a/components/strings/components_strings_sr.xtb
+++ b/components/strings/components_strings_sr.xtb
@@ -152,7 +152,7 @@
 <translation id="2674170444375937751">Желите ли стварно да избришете ове странице из историје?</translation>
 <translation id="2677748264148917807">Напусти</translation>
 <translation id="2704283930420550640">Вредност се не подудара са форматом.</translation>
-<translation id="2704951214193499422">Chromium овог пута није успео да потврди картицу. Покушајте поново касније.</translation>
+<translation id="2704951214193499422">Chromium није успео да потврди картицу. Покушајте поново касније.</translation>
 <translation id="2705137772291741111">Сачувана (кеширана) копија овог сајта није могла да се чита.</translation>
 <translation id="2709516037105925701">Аутоматско попуњавање</translation>
 <translation id="2712173769900027643">Затражи дозволу</translation>
@@ -188,7 +188,7 @@
 <translation id="3032412215588512954">Желите ли поново да учитате овај сат?</translation>
 <translation id="3037605927509011580">О, не!</translation>
 <translation id="3041612393474885105">Информације о сертификату</translation>
-<translation id="3063697135517575841">Chrome овог пута није успео да потврди картицу. Покушајте поново касније.</translation>
+<translation id="3063697135517575841">Chrome није успео да потврди картицу. Покушајте поново касније.</translation>
 <translation id="3093245981617870298">Офлајн сте.</translation>
 <translation id="3105172416063519923">ИД елемента:</translation>
 <translation id="3109728660330352905">Немате овлашћење да прегледате ову страницу.</translation>
@@ -512,7 +512,7 @@
 <translation id="7219179957768738017">Веза користи <ph name="SSL_VERSION" />.</translation>
 <translation id="7231308970288859235">Упс! Треба да питате родитеља да ли смете да посетите ову страницу.</translation>
 <translation id="7246609911581847514">Ову поруку видите јер ваш менаџер треба да одобри нове сајтове при првој посети.</translation>
-<translation id="724975217298816891">Унесите датум истека и CVC за картицу <ph name="CREDIT_CARD" /> да бисте ажурирали податке о картици. Када будете потврдили, подаци о картици ће бити послати овом сајту.</translation>
+<translation id="724975217298816891">Унесите рок трајања и CVC за картицу <ph name="CREDIT_CARD" /> да бисте ажурирали податке о картици. Када будете потврдили, подаци о картици ће бити послати овом сајту.</translation>
 <translation id="725866823122871198">Није могуће успоставити приватну везу са доменом <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> јер време и датум на рачунару (<ph name="DATE_AND_TIME" />) нису тачни.</translation>
 <translation id="7265986070661382626">Тренутно не можете да посетите <ph name="SITE" /> зато што веб-сајт <ph name="BEGIN_LINK" />користи проверу сертификата<ph name="END_LINK" />. Грешке и напади на мрежи су обично привремени, па ће ова страница вероватно функционисати касније.</translation>
 <translation id="7269802741830436641">Ова веб-страница има петљу за преусмеравање</translation>
diff --git a/components/strings/components_strings_ta.xtb b/components/strings/components_strings_ta.xtb
index 27b1068..70c40ba 100644
--- a/components/strings/components_strings_ta.xtb
+++ b/components/strings/components_strings_ta.xtb
@@ -182,7 +182,7 @@
 <translation id="2985306909656435243">இது இயக்கப்பட்டால், விரைவாகப் படிவத்தை நிரப்ப, உங்கள் கார்டின் நகலை Chromium இந்தச் சாதனத்தில் சேமிக்கும்.</translation>
 <translation id="2991174974383378012">இணையதளங்களுடன் பகிர்பவை</translation>
 <translation id="3005723025932146533">சேமித்த நகலைக் காட்டு</translation>
-<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> இன் CVC  எண்ணை உள்ளிடவும். உறுதிசெய்த பின்னர், உங்கள் கார்டு விவரங்கள் இந்தத் தளத்திற்குப் பகிரப்படும்.</translation>
+<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> இன் CVC எண்ணை உள்ளிடவும். உறுதிசெய்த பின்னர், உங்கள் கார்டு விவரங்கள் இந்தத் தளத்திற்குப் பகிரப்படும்.</translation>
 <translation id="3010559122411665027">பட்டியல் உள்ளீடு "<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
 <translation id="3024663005179499861">தவறான கொள்கை வகை</translation>
 <translation id="3032412215588512954">தளத்தை மீண்டும் ஏற்றவா?</translation>
diff --git a/components/strings/components_strings_te.xtb b/components/strings/components_strings_te.xtb
index de89fb4..68d42bd 100644
--- a/components/strings/components_strings_te.xtb
+++ b/components/strings/components_strings_te.xtb
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">బ్లాక్ చెయ్యబడింది</translation>
 <translation id="5710435578057952990">ఈ వెబ్‍‌సైట్ యొక్క గుర్తింపు నిర్థారించబడలేదు.</translation>
 <translation id="5720705177508910913">ప్రస్తుత వినియోగదారు</translation>
-<translation id="5784606427469807560">మీ కార్డ్‌ను నిర్ధారించడంలో సమస్య ఏర్పడింది. మీ ఇంటర్నెట్ కనెక్షన్‌ను తనిఖీ చేసి, ఆపై మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="5784606427469807560">మీ కార్డ్‌ను నిర్ధారించడంలో సమస్య ఏర్పడింది. మీ ఇంటర్నెట్ కనెక్షన్‌ని తనిఖీ చేసి, ఆపై మళ్లీ ప్రయత్నించండి.</translation>
 <translation id="5785756445106461925">అలాగే, ఈ పేజీలో సురక్షితం కాని ఇతర వనరులు ఉన్నాయి. ఈ వనరులను బదిలీ చేస్తున్నప్పుడు ఇతరులు చూడగలరు మరియు దాడికి పాల్పడేవారు పేజీ రూపాన్ని మార్చేలా వీటిని సవరించగలరు.</translation>
 <translation id="5810442152076338065"><ph name="DOMAIN" />కి గల మీ కనెక్షన్ వాడుకలో లేని సైఫర్ సూట్ ఉపయోగించి గుప్తీకరించబడింది.</translation>
 <translation id="5813119285467412249">&amp;జోడించడాన్ని పునరావృతం చేయి</translation>
@@ -527,7 +527,7 @@
 <translation id="7377249249140280793"><ph name="RELATIVE_DATE" /> - <ph name="FULL_DATE" /></translation>
 <translation id="7378627244592794276">వద్దు</translation>
 <translation id="7378810950367401542">/</translation>
-<translation id="7390545607259442187">కార్డ్‌ను నిర్ధారించండి</translation>
+<translation id="7390545607259442187">కార్డ్‌ని నిర్ధారించండి</translation>
 <translation id="7394102162464064926">మీరు ఈ పేజీలను ఖచ్చితంగా మీ చరిత్ర నుండి తొలగించాలనుకుంటున్నారా?
 
 అజ్ఞాత మోడ్ <ph name="SHORTCUT_KEY" /> తదుపరిసారి అందుబాటులోకి రావచ్చు.</translation>
@@ -537,7 +537,7 @@
 <translation id="7441627299479586546">చెల్లని విధాన విషయం</translation>
 <translation id="7445762425076701745">మీరు కనెక్ట్ చేసిన సర్వర్ యొక్క గుర్తింపు పూర్తిగా ధృవీకరించబడలేదు. మీరు దీని యొక్క యాజమాన్యాన్ని ధృవీకరించడానికి అంతర్గత ప్రమాణపత్రం అధికారికి మరొక దాని లేని మీ నెట్‌వర్క్‌లో మాత్రమే చెల్లుబాటు అయ్యే పేరును ఉపయోగించి సర్వర్‌కి కనెక్ట్ చేసారు. కొన్ని ప్రమాణపత్రం అధికారులు సంబంధంలేని ఈ పేర్లకు ప్రమాణపత్రాన్ని జారీ చేస్తారు, మీరు సరైన వెబ్‌సైట్‌కి మరియు అటాకర్‌కి కనెక్ట్ చేసారా అని నిర్ధారించడానికి వేరే మార్గం లేదు.</translation>
 <translation id="7451311239929941790">ఈ సమస్య గురించి <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" />.</translation>
-<translation id="7469372306589899959">కార్డ్‌ను నిర్ధారిస్తోంది</translation>
+<translation id="7469372306589899959">కార్డ్‌ని నిర్ధారిస్తోంది</translation>
 <translation id="7481312909269577407">ఫార్వార్డ్</translation>
 <translation id="7485870689360869515">డేటా కనుగొనబడలేదు.</translation>
 <translation id="7514365320538308">డౌన్‌లోడ్ చేయి</translation>
diff --git a/components/strings/components_strings_vi.xtb b/components/strings/components_strings_vi.xtb
index e5c2240..793e9e0 100644
--- a/components/strings/components_strings_vi.xtb
+++ b/components/strings/components_strings_vi.xtb
@@ -410,7 +410,7 @@
 <translation id="5677928146339483299">Bị chặn</translation>
 <translation id="5710435578057952990">Nhận dạng trang web này chưa được xác minh.</translation>
 <translation id="5720705177508910913">Người dùng hiện tại</translation>
-<translation id="5784606427469807560">Đã xảy ra sự cố khi xác nhận thẻ của bạn. Kiểm tra kết nối Internet và thử lại.</translation>
+<translation id="5784606427469807560">Đã xảy ra sự cố khi xác nhận thẻ của bạn. Hãy kiểm tra kết nối Internet của bạn và thử lại.</translation>
 <translation id="5785756445106461925">Ngoài ra, trang này bao gồm các tài nguyên khác không an toàn. Những tài nguyên này có thể bị người khác xem khi đang gửi và có thể bị kẻ tấn công sửa đổi nhằm thay đổi giao diện của trang.</translation>
 <translation id="5810442152076338065">Kết nối của bạn tới <ph name="DOMAIN" /> được mã hóa bằng bộ số 0 đã lỗi thời.</translation>
 <translation id="5813119285467412249">&amp;Làm lại thêm</translation>
@@ -537,7 +537,7 @@
 <translation id="7441627299479586546">Chủ đề chính sách sai</translation>
 <translation id="7445762425076701745">Không thể xác thực đầy đủ nhận dạng của máy chủ bạn đã kết nối. Bạn đã kết nối vào máy chủ bằng một tên chỉ hợp lệ trong mạng của bạn và đó là tên mà các tổ chức phát hành chứng chỉ bên ngoài không thể xác thực được. Vì một số tổ chức phát hành chứng chỉ sẽ cấp chứng chỉ cho các tên này thay thế, nên không có cách nào đảm bảo bạn được kết nối tới trang web đã chỉ định và không phải là kẻ tấn công.</translation>
 <translation id="7451311239929941790"><ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /> về sự cố này.</translation>
-<translation id="7469372306589899959">Xác nhận thẻ</translation>
+<translation id="7469372306589899959">Đang xác nhận thẻ</translation>
 <translation id="7481312909269577407">Chuyển tiếp</translation>
 <translation id="7485870689360869515">Không tìm thấy dữ liệu.</translation>
 <translation id="7514365320538308">Tải xuống</translation>
diff --git a/components/strings/components_strings_zh-CN.xtb b/components/strings/components_strings_zh-CN.xtb
index 8a235f7..3007b034 100644
--- a/components/strings/components_strings_zh-CN.xtb
+++ b/components/strings/components_strings_zh-CN.xtb
@@ -181,7 +181,7 @@
 <translation id="2985306909656435243">启用后,Chromium 会将您的信用卡副本存储在此设备上,以加快表单填写速度。</translation>
 <translation id="2991174974383378012">与网站分享</translation>
 <translation id="3005723025932146533">显示已保存的版本</translation>
-<translation id="3008447029300691911">输入“<ph name="CREDIT_CARD" />”的银行卡验证码 (CVC)。在您确认后,系统会将您的信用卡详情提供给此网站。</translation>
+<translation id="3008447029300691911">输入“<ph name="CREDIT_CARD" />”的银行卡验证码 (CVC)。在您确认后,您的信用卡详情将与此网站共享。</translation>
 <translation id="3010559122411665027">列表条目“<ph name="ENTRY_INDEX" />”:<ph name="ERROR" /></translation>
 <translation id="3024663005179499861">策略类型有误</translation>
 <translation id="3032412215588512954">要重新加载该网站吗?</translation>
@@ -508,7 +508,7 @@
 <translation id="7219179957768738017">该连接使用 <ph name="SSL_VERSION" />。</translation>
 <translation id="7231308970288859235">糟糕!您必须先征得家长同意,然后才能访问此网页。</translation>
 <translation id="7246609911581847514">您之所以看到这条消息,是因为您第一次访问新的网站时需要获得管理员的批准。</translation>
-<translation id="724975217298816891">输入“<ph name="CREDIT_CARD" />”的过期日期和银行卡验证码 (CVC),以更新您的信用卡详情。在您确认后,系统会将您的信用卡详情提供给此网站。</translation>
+<translation id="724975217298816891">输入“<ph name="CREDIT_CARD" />”的过期日期和银行卡验证码 (CVC) 以更新您的信用卡详情。在您确认后,您的信用卡详情将与此网站共享。</translation>
 <translation id="725866823122871198">您计算机的日期和时间(<ph name="DATE_AND_TIME" />)不正确,因此无法与 <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> 建立私密连接。</translation>
 <translation id="7265986070661382626">您目前无法访问<ph name="SITE" />,因为此网站<ph name="BEGIN_LINK" />使用了证书锁定<ph name="END_LINK" />。网络错误和攻击通常是暂时的,因此,此网页稍后可能会恢复正常。</translation>
 <translation id="7269802741830436641">此网页包含重定向循环</translation>
@@ -532,7 +532,7 @@
 <translation id="7441627299479586546">策略主题有误</translation>
 <translation id="7445762425076701745">无法完全验证您所连接到的服务器的身份。您在连接服务器时使用的服务器名称仅在您的网络中有效,而外部证书授权中心无法验证该名称的所有权。由于一些证书授权中心仍然会为这些名称颁发证书,因此无法确保您连接到想要访问的网站而不是攻击网站。</translation>
 <translation id="7451311239929941790"><ph name="BEGIN_LINK" />详细了解<ph name="END_LINK" />此问题。</translation>
-<translation id="7469372306589899959">正在确认信用卡</translation>
+<translation id="7469372306589899959">确认信用卡</translation>
 <translation id="7481312909269577407">前进</translation>
 <translation id="7485870689360869515">找不到数据。</translation>
 <translation id="7514365320538308">下载</translation>
@@ -647,7 +647,7 @@
 <translation id="8866959479196209191">此网页显示:</translation>
 <translation id="8870413625673593573">最近关闭的标签页</translation>
 <translation id="8876793034577346603">无法解析网络配置。</translation>
-<translation id="8877192140621905067">在您确认后,系统会将您的信用卡详情提供给此网站</translation>
+<translation id="8877192140621905067">在您确认后,您的信用卡详情将与此网站共享</translation>
 <translation id="8891727572606052622">代理模式无效。</translation>
 <translation id="889901481107108152">抱歉,此项实验性功能不能用于您的平台。</translation>
 <translation id="8903921497873541725">放大</translation>
@@ -681,7 +681,7 @@
 <translation id="935608979562296692">清除表单内容</translation>
 <translation id="939736085109172342">新建文件夹</translation>
 <translation id="943029900877297437">要使用您保存到自己 Google 帐户中的信用卡,请登录 Chrome。</translation>
-<translation id="962701380617707048">输入“<ph name="CREDIT_CARD" />”的过期日期和银行卡验证码 (CVC),以更新您的信用卡详情</translation>
+<translation id="962701380617707048">输入“<ph name="CREDIT_CARD" />”的过期日期和银行卡验证码 (CVC) 以更新您的信用卡详情</translation>
 <translation id="969892804517981540">正式版本</translation>
 <translation id="988159990683914416">开发者内部版本</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/strings/components_strings_zh-TW.xtb b/components/strings/components_strings_zh-TW.xtb
index 15b12d8..008da515 100644
--- a/components/strings/components_strings_zh-TW.xtb
+++ b/components/strings/components_strings_zh-TW.xtb
@@ -513,7 +513,7 @@
 <translation id="7219179957768738017">這個連線使用 <ph name="SSL_VERSION" />。</translation>
 <translation id="7231308970288859235">注意:您必須徵求家長同意,才能瀏覽這個網頁。</translation>
 <translation id="7246609911581847514">Chrome 顯示這則訊息是因為您首次瀏覽的新網站需要獲得管理員核准。</translation>
-<translation id="724975217298816891">請輸入 <ph name="CREDIT_CARD" /> 的到期日和信用卡安全碼,更新您的信用卡詳細資訊。完成驗證後,這個網站就會取得您的信用卡詳細資訊。</translation>
+<translation id="724975217298816891">請輸入 <ph name="CREDIT_CARD" /> 的有效日期和信用卡安全碼,更新您的信用卡詳細資訊。完成驗證後,這個網站就會取得您的信用卡詳細資訊。</translation>
 <translation id="725866823122871198">您電腦的日期和時間 (<ph name="DATE_AND_TIME" />) 不正確,因此無法與 <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> 建立私人連線。</translation>
 <translation id="7265986070661382626">您目前無法造訪 <ph name="SITE" />,因為這個網站<ph name="BEGIN_LINK" />使用憑證固定功能<ph name="END_LINK" />。網路錯誤和攻擊行為通常是暫時性的,所以這個網頁可能稍後就能正常使用。</translation>
 <translation id="7269802741830436641">這個網頁含有重新導向迴圈</translation>
@@ -686,7 +686,7 @@
 <translation id="935608979562296692">清除表單</translation>
 <translation id="939736085109172342">新增資料夾</translation>
 <translation id="943029900877297437">如要使用您已儲存在 Google 帳戶中的信用卡,請登入 Chrome。</translation>
-<translation id="962701380617707048">輸入 <ph name="CREDIT_CARD" /> 的到期日和信用卡安全碼,更新您的信用卡詳細資訊</translation>
+<translation id="962701380617707048">輸入 <ph name="CREDIT_CARD" /> 的有效日期和信用卡安全碼,更新您的信用卡詳細資訊</translation>
 <translation id="969892804517981540">正式版本</translation>
 <translation id="988159990683914416">開發人員版本</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn
index f5008be..93a56b2 100644
--- a/components/subresource_filter/content/browser/BUILD.gn
+++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("browser") {
+static_library("browser") {
   sources = [
     "content_ruleset_distributor.cc",
     "content_ruleset_distributor.h",
diff --git a/components/subresource_filter/content/common/BUILD.gn b/components/subresource_filter/content/common/BUILD.gn
index 6654a36..a6aee2849 100644
--- a/components/subresource_filter/content/common/BUILD.gn
+++ b/components/subresource_filter/content/common/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("common") {
+static_library("common") {
   sources = [
     "subresource_filter_message_generator.cc",
     "subresource_filter_message_generator.h",
diff --git a/components/subresource_filter/content/renderer/BUILD.gn b/components/subresource_filter/content/renderer/BUILD.gn
index 1de9185f..9699c2e 100644
--- a/components/subresource_filter/content/renderer/BUILD.gn
+++ b/components/subresource_filter/content/renderer/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("renderer") {
+static_library("renderer") {
   sources = [
     "document_subresource_filter.cc",
     "document_subresource_filter.h",
diff --git a/components/subresource_filter/core/common/BUILD.gn b/components/subresource_filter/core/common/BUILD.gn
index ac62c3a7..5c645143 100644
--- a/components/subresource_filter/core/common/BUILD.gn
+++ b/components/subresource_filter/core/common/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("common") {
+static_library("common") {
   sources = [
     "activation_state.cc",
     "activation_state.h",
@@ -35,7 +35,7 @@
   ]
 }
 
-source_set("test_support") {
+static_library("test_support") {
   testonly = true
   sources = [
     "test_ruleset_creator.cc",
diff --git a/components/subresource_filter/core/common/fuzzy_pattern_matching.cc b/components/subresource_filter/core/common/fuzzy_pattern_matching.cc
index d3cf29f..96b0f5c 100644
--- a/components/subresource_filter/core/common/fuzzy_pattern_matching.cc
+++ b/components/subresource_filter/core/common/fuzzy_pattern_matching.cc
@@ -25,31 +25,14 @@
 }  // namespace
 
 bool StartsWithFuzzy(base::StringPiece text, base::StringPiece subpattern) {
-  if (subpattern.size() <= text.size())
-    return StartsWithFuzzyImpl(text, subpattern);
-
-  return subpattern.size() == text.size() + 1 &&
-         subpattern.back() == kSeparatorPlaceholder &&
-         StartsWithFuzzyImpl(text, subpattern.substr(0, text.size()));
+  return subpattern.size() <= text.size() &&
+         StartsWithFuzzyImpl(text, subpattern);
 }
 
 bool EndsWithFuzzy(base::StringPiece text, base::StringPiece subpattern) {
-  if (subpattern.size() > text.size() + 1)
-    return false;
-
-  if (subpattern.size() <= text.size() &&
-      StartsWithFuzzyImpl(text.substr(text.size() - subpattern.size()),
-                          subpattern)) {
-    return true;
-  }
-
-  DCHECK(!subpattern.empty());
-  if (subpattern.back() != kSeparatorPlaceholder)
-    return false;
-  subpattern.remove_suffix(1);
-  DCHECK_LE(subpattern.size(), text.size());
-  return StartsWithFuzzy(text.substr(text.size() - subpattern.size()),
-                         subpattern);
+  return subpattern.size() <= text.size() &&
+         StartsWithFuzzyImpl(text.substr(text.size() - subpattern.size()),
+                             subpattern);
 }
 
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/core/common/fuzzy_pattern_matching.h b/components/subresource_filter/core/common/fuzzy_pattern_matching.h
index 586190a..15e9fe79 100644
--- a/components/subresource_filter/core/common/fuzzy_pattern_matching.h
+++ b/components/subresource_filter/core/common/fuzzy_pattern_matching.h
@@ -5,9 +5,9 @@
 // The separator placeholder '^' symbol is used in subpatterns to match any
 // separator character, which is any ASCII symbol except letters, digits, and
 // the following: '_', '-', '.', '%'. Note that the separator placeholder
-// character '^' is itself a separator, as well as '\0'. In addition, a
-// separator placeholder at the end of the pattern can be matched by the end of
-// |text|.
+// character '^' is itself a separator, as well as '\0'.
+// TODO(pkalinnikov): In addition, a separator placeholder at the end of the
+// pattern can be matched by the end of |text|.
 //
 // We define a fuzzy occurrence as an occurrence of a |subpattern| in |text|
 // such that all its non-placeholder characters are equal to the corresponding
diff --git a/components/subresource_filter/core/common/fuzzy_pattern_matching_unittest.cc b/components/subresource_filter/core/common/fuzzy_pattern_matching_unittest.cc
index b55ffd13..0dc78a5 100644
--- a/components/subresource_filter/core/common/fuzzy_pattern_matching_unittest.cc
+++ b/components/subresource_filter/core/common/fuzzy_pattern_matching_unittest.cc
@@ -16,11 +16,12 @@
     const char* subpattern;
     bool expected_starts_with;
   } kTestCases[] = {
-      {"abc", "", true},       {"abc", "a", true},      {"abc", "ab", true},
-      {"abc", "abc", true},    {"abc", "abcd", false},  {"abc", "abc^", true},
-      {"abc", "abc^^", false}, {"abc", "abcd^", false}, {"abc", "ab^", false},
-      {"abc", "bc", false},    {"abc", "bc^", false},   {"abc", "^abc", false},
+      {"abc", "", true},       {"abc", "a", true},     {"abc", "ab", true},
+      {"abc", "abc", true},    {"abc", "abcd", false}, {"abc", "abc^^", false},
+      {"abc", "abcd^", false}, {"abc", "ab^", false},  {"abc", "bc", false},
+      {"abc", "bc^", false},   {"abc", "^abc", false},
   };
+  // TODO(pkalinnikov): Make end-of-string match '^' again.
 
   for (const auto& test_case : kTestCases) {
     SCOPED_TRACE(testing::Message()
@@ -39,11 +40,12 @@
     const char* subpattern;
     bool expected_ends_with;
   } kTestCases[] = {
-      {"abc", "", true},       {"abc", "c", true},      {"abc", "bc", true},
-      {"abc", "abc", true},    {"abc", "0abc", false},  {"abc", "abc^", true},
-      {"abc", "abc^^", false}, {"abc", "abcd^", false}, {"abc", "ab^", false},
-      {"abc", "ab", false},    {"abc", "bc^", true},    {"abc", "^abc", false},
+      {"abc", "", true},       {"abc", "c", true},     {"abc", "bc", true},
+      {"abc", "abc", true},    {"abc", "0abc", false}, {"abc", "abc^^", false},
+      {"abc", "abcd^", false}, {"abc", "ab^", false},  {"abc", "ab", false},
+      {"abc", "^abc", false},
   };
+  // TODO(pkalinnikov): Make end-of-string match '^' again.
 
   for (const auto& test_case : kTestCases) {
     SCOPED_TRACE(testing::Message()
diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/components/subresource_filter/core/common/indexed_ruleset.cc
index f6d7cc3d..31e7702 100644
--- a/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -382,8 +382,9 @@
 bool IndexedRulesetMatcher::IsAllowed(const GURL& url,
                                       const url::Origin& initiator,
                                       proto::ElementType element_type) const {
+  if (!url.is_valid())
+    return true;
   const bool is_third_party = IsThirdPartyUrl(url, initiator);
-
   return !IsMatch(root_->blacklist_index(), url, initiator, element_type,
                   is_third_party) ||
          IsMatch(root_->whitelist_index(), url, initiator, element_type,
diff --git a/components/subresource_filter/core/common/indexed_ruleset_unittest.cc b/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
index e18f520..0c85e69 100644
--- a/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
@@ -142,12 +142,14 @@
        "http://test.example.com",
        false},
       {{"example.com", kSubdomain, kAnchorNone},
+       "https://test.example.com.com",
+       false},
+      {{"example.com", kSubdomain, kAnchorNone},
        "https://test.rest.example.com",
        false},
-
-      // FIXME(pkalinnikov): Implement SUBDOMAIN matching.
-      // {"example.com", kSubdomain, kAnchorNone}, "https://test_example.com",
-      //  true},
+      {{"example.com", kSubdomain, kAnchorNone},
+       "https://test_example.com",
+       true},
 
       {{"http://example.com", kBoundary, kAnchorNone},
        "http://example.com/",
@@ -219,10 +221,9 @@
       {{"test.example.com^", kSubdomain, kAnchorNone},
        "http://test.example.com.ua/42.swf",
        true},
-
-      // FIXME(pkalinnikov): Implement SUBDOMAIN matching.
-      // {"test.example.com^", kSubdomain, kAnchorNone},
-      //  "http://example.com/redirect/http://test.example.com/", true},
+      {{"test.example.com^", kSubdomain, kAnchorNone},
+       "http://example.com/redirect/http://test.example.com/",
+       true},
 
       {{"/abcd/*"}, "https://example.com/abcd/", false},
       {{"/abcd/*"}, "http://example.com/abcd/picture.jpeg", false},
diff --git a/components/subresource_filter/core/common/string_splitter.h b/components/subresource_filter/core/common/string_splitter.h
index a3103346..f3b4e85 100644
--- a/components/subresource_filter/core/common/string_splitter.h
+++ b/components/subresource_filter/core/common/string_splitter.h
@@ -29,8 +29,8 @@
     // |splitter|'s |text|, starting from |head|.
     Iterator(const StringSplitter& splitter,
              base::StringPiece::const_iterator head)
-        : splitter_(splitter), current_(head, 0), end_(splitter.text_.end()) {
-      DCHECK_GE(head, splitter_.text_.begin());
+        : splitter_(&splitter), current_(head, 0), end_(splitter.text_.end()) {
+      DCHECK_GE(head, splitter_->text_.begin());
       DCHECK_LE(head, end_);
 
       Advance();
@@ -59,15 +59,15 @@
    private:
     void Advance() {
       auto begin = current_.end();
-      while (begin != end_ && splitter_.is_separator_(*begin))
+      while (begin != end_ && splitter_->is_separator_(*begin))
         ++begin;
       auto end = begin;
-      while (end != end_ && !splitter_.is_separator_(*end))
+      while (end != end_ && !splitter_->is_separator_(*end))
         ++end;
       current_ = base::StringPiece(begin, end - begin);
     }
 
-    const StringSplitter& splitter_;
+    const StringSplitter* splitter_;
 
     // Contains the token currently pointed to by the iterator.
     base::StringPiece current_;
diff --git a/components/subresource_filter/core/common/url_pattern_matching.h b/components/subresource_filter/core/common/url_pattern_matching.h
index fe64419..24608b8 100644
--- a/components/subresource_filter/core/common/url_pattern_matching.h
+++ b/components/subresource_filter/core/common/url_pattern_matching.h
@@ -18,6 +18,7 @@
 
 #include <stddef.h>
 
+#include <algorithm>
 #include <iterator>
 #include <vector>
 
@@ -28,6 +29,7 @@
 #include "components/subresource_filter/core/common/string_splitter.h"
 #include "components/subresource_filter/core/common/url_pattern.h"
 #include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
 
 namespace subresource_filter {
 
@@ -70,10 +72,28 @@
 
 namespace impl {
 
-inline bool IsWildcard(char c) {
-  return c == '*';
+class IsWildcard {
+ public:
+  bool operator()(char c) const { return c == '*'; }
+};
+
+// Returns whether |position| within the |url| belongs to its |host| component
+// and corresponds to the beginning of a (sub-)domain.
+inline bool IsSubdomainAnchored(base::StringPiece url,
+                                url::Component host,
+                                size_t position) {
+  DCHECK_LE(position, url.size());
+  const size_t host_begin = static_cast<size_t>(host.begin);
+  const size_t host_end = static_cast<size_t>(host.end());
+  DCHECK_LE(host_end, url.size());
+
+  return position == host_begin ||
+         (position > host_begin && position <= host_end &&
+          url[position - 1] == '.');
 }
 
+// Returns the position just beyond the leftmost fuzzy occurrence of
+// |subpattern| in the |text|.
 template <typename IntType>
 inline size_t FindFirstOccurrenceFuzzy(base::StringPiece text,
                                        base::StringPiece subpattern,
@@ -81,13 +101,44 @@
   return *AllOccurrencesFuzzy<IntType>(text, subpattern, failure).begin();
 }
 
+// Returns the position just beyond the leftmost occurrence of |subpattern| in
+// the |url|, such that it satisfies a SUBDOMAIN anchor.
+template <typename IntType>
+inline size_t FindSubdomainAnchored(base::StringPiece url,
+                                    url::Component host,
+                                    base::StringPiece subpattern,
+                                    const IntType* failure) {
+  auto occurrences = AllOccurrences<IntType>(url, subpattern, failure);
+  return *std::find_if(occurrences.begin(), occurrences.end(),
+                       [url, host, subpattern](size_t match_end_position) {
+                         DCHECK_GE(match_end_position, subpattern.size());
+                         return IsSubdomainAnchored(
+                             url, host, match_end_position - subpattern.size());
+                       });
+}
+
+// Returns the position just beyond the leftmost fuzzy occurrence of
+// |subpattern| in the |url|, such that it satisfies a SUBDOMAIN anchor.
+template <typename IntType>
+inline size_t FindSubdomainAnchoredFuzzy(base::StringPiece url,
+                                         url::Component host,
+                                         base::StringPiece subpattern,
+                                         const IntType* failure) {
+  auto occurrences = AllOccurrencesFuzzy<IntType>(url, subpattern, failure);
+  return *std::find_if(occurrences.begin(), occurrences.end(),
+                       [url, host, subpattern](size_t match_end_position) {
+                         DCHECK_GE(match_end_position, subpattern.size());
+                         return IsSubdomainAnchored(
+                             url, host, match_end_position - subpattern.size());
+                       });
+}
+
 }  // namespace impl
 
 template <typename IntType>
 void BuildFailureFunction(const UrlPattern& pattern,
                           std::vector<IntType>* failure) {
-  auto subpatterns =
-      CreateStringSplitter(pattern.url_pattern, impl::IsWildcard);
+  StringSplitter<impl::IsWildcard> subpatterns(pattern.url_pattern);
   auto subpattern_it = subpatterns.begin();
   auto subpattern_end = subpatterns.end();
 
@@ -116,14 +167,14 @@
   }
 }
 
-// TODO(pkalinnikov): Support SUBDOMAIN anchors.
 template <typename FailureIter>
 bool IsMatch(const GURL& url,
              const UrlPattern& pattern,
              FailureIter failure_begin,
              FailureIter failure_end) {
-  auto subpatterns =
-      CreateStringSplitter(pattern.url_pattern, impl::IsWildcard);
+  DCHECK(url.is_valid());
+
+  StringSplitter<impl::IsWildcard> subpatterns(pattern.url_pattern);
   auto subpattern_it = subpatterns.begin();
   auto subpattern_end = subpatterns.end();
 
@@ -133,20 +184,57 @@
            url.is_empty();
   }
 
-  base::StringPiece spec = url.spec();
+  const base::StringPiece spec = url.possibly_invalid_spec();
+  const url::Component host_part = url.parsed_for_possibly_invalid_spec().host;
 
-  if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY) {
-    const base::StringPiece subpattern = *subpattern_it++;
-    if (!StartsWithFuzzy(spec, subpattern))
+  base::StringPiece subpattern = *subpattern_it++;
+  if (subpattern_it == subpattern_end &&
+      pattern.anchor_right == proto::ANCHOR_TYPE_BOUNDARY) {
+    if (!EndsWithFuzzy(spec, subpattern))
       return false;
-    if (subpattern_it == subpattern_end) {
-      return pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY ||
-             spec.size() == subpattern.size();
+    if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY)
+      return spec.size() == subpattern.size();
+    if (pattern.anchor_left == proto::ANCHOR_TYPE_SUBDOMAIN) {
+      DCHECK_LE(subpattern.size(), spec.size());
+      return url.has_host() &&
+             impl::IsSubdomainAnchored(spec, host_part,
+                                       spec.size() - subpattern.size());
     }
-    spec.remove_prefix(subpattern.size());
+    return true;
   }
 
-  base::StringPiece subpattern;
+  base::StringPiece text = spec;
+  if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY) {
+    if (!StartsWithFuzzy(spec, subpattern))
+      return false;
+    if (subpattern_it == subpattern_end)
+      return true;
+    text.remove_prefix(subpattern.size());
+  } else if (pattern.anchor_left == proto::ANCHOR_TYPE_SUBDOMAIN) {
+    if (!url.has_host())
+      return false;
+
+    const bool has_separator_placeholders = (*failure_begin != 0);
+    if (has_separator_placeholders)
+      ++failure_begin;
+
+    const size_t position =
+        has_separator_placeholders
+            ? impl::FindSubdomainAnchoredFuzzy(spec, host_part, subpattern,
+                                               &*failure_begin)
+            : impl::FindSubdomainAnchored(spec, host_part, subpattern,
+                                          &*failure_begin);
+    if (position == base::StringPiece::npos)
+      return false;
+    if (subpattern_it == subpattern_end)
+      return true;
+    text.remove_prefix(position);
+  } else {
+    DCHECK_EQ(pattern.anchor_left, proto::ANCHOR_TYPE_NONE);
+    // Get back to the initial subpattern, process it in the loop below.
+    subpattern_it = subpatterns.begin();
+  }
+
   while (subpattern_it != subpattern_end) {
     subpattern = *subpattern_it++;
     DCHECK(!subpattern.empty());
@@ -172,16 +260,16 @@
     // substring.
     const size_t match_end =
         (has_separator_placeholders
-             ? impl::FindFirstOccurrenceFuzzy(spec, subpattern, &*failure_begin)
-             : FindFirstOccurrence(spec, subpattern, &*failure_begin));
+             ? impl::FindFirstOccurrenceFuzzy(text, subpattern, &*failure_begin)
+             : FindFirstOccurrence(text, subpattern, &*failure_begin));
     if (match_end == base::StringPiece::npos)
       return false;
-    spec.remove_prefix(match_end);
+    text.remove_prefix(match_end);
     failure_begin += subpattern.size();
   }
 
   return pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY ||
-         EndsWithFuzzy(spec, subpattern);
+         EndsWithFuzzy(text, subpattern);
 }
 
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/core/common/url_pattern_matching_unittest.cc b/components/subresource_filter/core/common/url_pattern_matching_unittest.cc
index 738585d..801baa6 100644
--- a/components/subresource_filter/core/common/url_pattern_matching_unittest.cc
+++ b/components/subresource_filter/core/common/url_pattern_matching_unittest.cc
@@ -112,6 +112,24 @@
       {{"a^a&a^a&"}, "http://ex.com/a/a/a/a/?a&a&a&a&a", true},
 
       {{"abc*def^"}, "http://ex.com/abc/a/ddef/", true},
+
+      {{"https://example.com/"}, "http://example.com/", false},
+      {{"example.com/", kSubdomain, kAnchorNone}, "http://example.com/", true},
+      {{"examp", kSubdomain, kAnchorNone}, "http://example.com/", true},
+      {{"xamp", kSubdomain, kAnchorNone}, "http://example.com/", false},
+      {{"examp", kSubdomain, kAnchorNone}, "http://test.example.com/", true},
+      {{"t.examp", kSubdomain, kAnchorNone}, "http://test.example.com/", false},
+      {{"com^", kSubdomain, kAnchorNone}, "http://test.example.com/", true},
+      {{"x.com", kSubdomain, kAnchorNone}, "http://ex.com/?url=x.com", false},
+      {{"ex.com/", kSubdomain, kBoundary}, "http://ex.com/", true},
+      {{"ex.com^", kSubdomain, kBoundary}, "http://ex.com/", true},
+      {{"ex.co", kSubdomain, kBoundary}, "http://ex.com/", false},
+      {{"ex.com", kSubdomain, kBoundary}, "http://rex.com.ex.com/", false},
+      {{"ex.com/", kSubdomain, kBoundary}, "http://rex.com.ex.com/", true},
+      {{"http", kSubdomain, kBoundary}, "http://http.com/", false},
+      {{"http", kSubdomain, kAnchorNone}, "http://http.com/", true},
+      {{"/example.com", kSubdomain, kBoundary}, "http://example.com/", false},
+      {{"/example.com/", kSubdomain, kBoundary}, "http://example.com/", false},
   };
 
   for (const auto& test_case : kTestCases) {
diff --git a/components/suggestions/BUILD.gn b/components/suggestions/BUILD.gn
index 40ac92f..2dd952f 100644
--- a/components/suggestions/BUILD.gn
+++ b/components/suggestions/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("suggestions") {
+static_library("suggestions") {
   sources = [
     "blacklist_store.cc",
     "blacklist_store.h",
diff --git a/components/supervised_user_error_page/BUILD.gn b/components/supervised_user_error_page/BUILD.gn
index 41071284..6fe4cac1 100644
--- a/components/supervised_user_error_page/BUILD.gn
+++ b/components/supervised_user_error_page/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("supervised_user_error_page") {
+static_library("supervised_user_error_page") {
   sources = [
     "supervised_user_error_page.cc",
     "supervised_user_error_page.h",
diff --git a/components/sync_bookmarks/BUILD.gn b/components/sync_bookmarks/BUILD.gn
index a1eb017..a253d32 100644
--- a/components/sync_bookmarks/BUILD.gn
+++ b/components/sync_bookmarks/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//build/config/features.gni")
 
-source_set("sync_bookmarks") {
+static_library("sync_bookmarks") {
   sources = [
     "bookmark_change_processor.cc",
     "bookmark_change_processor.h",
diff --git a/components/test/data/autofill/automated_integration/__init__.py b/components/test/data/autofill/automated_integration/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/__init__.py
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/README.md b/components/test/data/autofill/automated_integration/action_recorder_extension/README.md
new file mode 100644
index 0000000..26dc3f9
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/README.md
@@ -0,0 +1,26 @@
+# Action Recorder Extension
+
+> An extension that generates Python scripts which automate integration testing
+> through Chrome. It was primarily designed for testing Autofill but is easily
+> portable to other uses.
+
+## Usage
+
+1.  Install the extension into Chrome as an unpacked extension on
+    chrome://extensions (don't forget to turn on "Developer mode" on this page).
+2.  Navigate to the desired start page or use the extension's dropdown menu
+    (next to the omnibox) to go to the next "top 100" site.
+3.  Use the dropdown menu or right-click context menu to start action recording.
+4.  Proceed to click on page elements to navigate through the desired sequence
+    of pages.
+5.  To validate the input field types simply right-click on the inputs and
+    select the appropriate 'Input Field Type'. Before performing any other
+    actions, right click on the page and select 'Validate Field Types'.
+6.  Select 'Stop & Copy', at which point the test code will be in your
+    clipboard.
+7.  Paste the generated code into the autofill_top_100.py file
+    (components/test/data/password_manager/form_classification_tests).
+8.  Clean up as necessary.
+
+You might also visit arbitrary sites. Just go to a site and start recording
+there.
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/action_recorder.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/action_recorder.js
new file mode 100644
index 0000000..d9e5299
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/action_recorder.js
@@ -0,0 +1,460 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// global FIELD_TYPES, SITES_TO_VISIT, IndentedTextFactory, ActionSet, ByXPath,
+// Open, SetContext, Type, Select, Click, TypedField, ValidateFields
+'use strict';
+
+class ActionRecorder {
+  constructor() {
+    this._siteIndex = 0;
+    this.cancel();
+
+    this._startListeners();
+  }
+
+  start(url) {
+    this._actionSet = new ActionSet(url);
+    this._createRecordingContextMenus();
+
+    console.log('Started recording.');
+  }
+
+  stop() {
+    if (!this.isRecording()) {
+      console.error(
+        'Attempted to stop recording when no action set was active.');
+      return;
+    }
+
+    this._createIdleContextMenus();
+
+    // Remove all redundant actions
+    this._actionSet.optimize();
+
+    this._copyText(this._actionSet.toString());
+    this.cancel();
+    console.log('Stopped recording.');
+  }
+
+  cancel() {
+    this._actionSet = null;
+    this._lastRightClick = null;
+    this._typedFields = [];
+
+    this._createIdleContextMenus();
+  }
+
+  isRecording() {
+    return this._actionSet !== null;
+  }
+
+  /**
+   * Copies a string to the system clipboard.
+   * Multiline strings are supported.
+   *
+   * @param  {String} text Target string
+   */
+  _copyText(text) {
+    const input = document.createElement('textarea');
+    document.body.appendChild(input);
+    input.value = text;
+    input.focus();
+    input.select();
+    document.execCommand('Copy');
+    input.remove();
+
+    const iconUrl = 'icons/icon_' +
+      (this.isRecording() ? 'recording' : 'idle') +
+      '128.png';
+
+    chrome.notifications.create(undefined, {
+      type: 'basic',
+      iconUrl: iconUrl,
+      title: 'Action Recorder',
+      message: 'Recorded script copied to clipboard.'
+    });
+  }
+
+  /**
+   * Process an action data event and add the appropriate Action object to the
+   * active ActionSet.
+   * @param  {Object}        actionData Data object to construct an Action
+   *                                    instance with
+   * @param  {MessageSender} sender     Chrome sender data object
+   */
+  _handleAction(actionData, sender) {
+    if (!this.isRecording()) {
+      console.warn('Actions cannot be added when recording is not active.');
+      return;
+    }
+    if (!actionData) {
+      console.error('Invalid action data.');
+      return;
+    }
+
+    console.log('Action data received: ', actionData);
+
+    let actionObject;
+
+    let selector = new ByXPath(actionData.selector);
+
+    switch (actionData.type) {
+      case 'set-context':
+        if (actionData.selector === 'None') {
+          selector = actionData.selector;
+        }
+        if (actionData.args.length >= 2) {
+          actionData.args[1] = new ByXPath(actionData.args[1]);
+        }
+        actionObject = new SetContext(selector, ...actionData.args);
+        break;
+      case 'type':
+        actionObject = new Type(selector, ...actionData.args);
+        break;
+      case 'fill-email':
+        actionObject = new Type(selector, 'GenEmail()', undefined, true);
+        break;
+      case 'fill-password':
+        actionObject = new Type(selector, 'GenPassword()', undefined, true);
+        break;
+      case 'select':
+        actionObject = new Select(selector, ...actionData.args);
+        break;
+      case 'left-click':
+        actionObject = new Click(selector);
+        break;
+      case 'right-click':
+        this._lastRightClick = {
+          selector: selector,
+          tabId: sender.tab.id,
+          frameId: sender.frameId
+        };
+        return;
+        break;
+      default:
+        console.error(`Unsupported action type: ${actionData.type}`);
+        return;
+    }
+
+    this._actionSet.addAction(actionObject);
+  }
+
+  _startListeners() {
+    /**
+     * Add listener for messages from content scripts.
+     */
+    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
+      if (!request) {
+        console.error('Invalid request from content script.', request);
+        return;
+      }
+
+      switch (request.type) {
+        case 'get-frame-info':
+          let frameInfo = {
+            tabId: sender.tab.id,
+            frameId: sender.frameId
+          };
+
+          if (frameInfo.frameId === 0) {
+            frameInfo.parentFrameId = -1;
+            return sendResponse(frameInfo);
+          }
+
+          chrome.webNavigation.getFrame(frameInfo, (details) => {
+            frameInfo.parentFrameId = details.parentFrameId;
+            sendResponse(frameInfo);
+          });
+
+          return true;
+        case 'forward-message-to-tab':
+          chrome.tabs.sendMessage(...request.args);
+          break;
+        case 'recording-state-request':
+          sendResponse({
+            isRecording: this.isRecording()
+          });
+          break;
+        case 'start-recording':
+          this._getCurrentTab((err, tab) => {
+            if (err) {
+              console.error(err);
+            } else {
+              this.start(tab.url);
+            }
+
+            sendResponse({
+              isRecording: this.isRecording()
+            });
+          });
+
+          return true;
+        case 'stop-recording':
+          this.stop();
+          sendResponse({
+            isRecording: this.isRecording()
+          });
+          break;
+        case 'cancel-recording':
+          this.cancel();
+          sendResponse({
+            isRecording: this.isRecording()
+          });
+          break;
+        case 'next-site':
+          if (this.isRecording()) {
+            console.error('Cannot go to next site when recording.');
+            return;
+          }
+          this._visitSite(this._nextSite());
+          break;
+        case 'action':
+          this._handleAction(request.data, sender);
+          break;
+        case 'actions':
+          for (let i = 0; i < request.data.length; i++) {
+            this._handleAction(request.data[i], sender);
+          }
+          break;
+        default:
+          console.error(`Unknown request type: ${request.type}`);
+      }
+    });
+  }
+
+  _getCurrentTab(cb) {
+    chrome.tabs.query({
+      active: true,
+      currentWindow: true
+    }, (tabs) => {
+      if (tabs.length === 0) {
+        cb(new Error('Unable to retrieve current tab.'));
+      } else {
+        cb(null, tabs[0]);
+      }
+    });
+  }
+
+  /**
+   * Add a validation action to the active action set from the current
+   * collection of typed fields.
+   */
+  _constructValidationAction() {
+    if (!this.isRecording()) {
+      console.warn('Actions cannot be added when recording is not active.');
+      return;
+    }
+
+    const typedFields =
+      Object.keys(this._typedFields).map(key => this._typedFields[key]);
+
+    console.log('Creating field type validation action: ', typedFields);
+
+    this._actionSet.addAction(new ValidateFields(typedFields));
+
+    this._typedFields = {};
+  }
+
+  /**
+   * Sets a field type for the last right-clicked element on the active tab
+   * (thus for the element for which the context menu was created).
+   *
+   * @param {String} fieldType Identifier of the editable input's field type
+   */
+  _setFieldTypeForEditable(fieldType) {
+    if (!this.isRecording()) {
+      console.warn('Field types cannot be set when recording is not active.');
+      return;
+    }
+
+    if (this._lastRightClick === null) {
+      return console.error('No right click data available');
+    }
+
+    if (fieldType === 'NONE') {
+      fieldType = null;
+    }
+
+    const selector = this._lastRightClick.selector;
+
+    console.log(`Field Type '${fieldType}' received for: ${selector}`);
+
+    this._typedFields[selector] = new TypedField(selector, fieldType);
+  }
+
+  /**
+   * Generates a email fill action, and enters equivalent data to the target
+   * element.
+   */
+  _fillEmail() {
+    if (!this.isRecording()) {
+      console.warn('Email can only be generated when recording is active.');
+      return;
+    }
+
+    if (this._lastRightClick === null) {
+      return console.error('No right click data available');
+    }
+
+    const clickData = this._lastRightClick;
+
+    chrome.tabs.sendMessage(
+      clickData.tabId, {
+        type: 'fill-email',
+        selector: clickData.selector._xPath
+      }, {
+        frameId: clickData.frameId
+      });
+  }
+
+  /**
+   * Generates a password fill action, and enters equivalent data to the target
+   * element.
+   */
+  _fillPassword() {
+    if (!this.isRecording()) {
+      console.warn('Password can only be generated when recording is active.');
+      return;
+    }
+
+    if (this._lastRightClick === null) {
+      return console.error('No right click data available');
+    }
+
+    const clickData = this._lastRightClick;
+
+    chrome.tabs.sendMessage(
+      clickData.tabId, {
+        type: 'fill-password',
+        selector: clickData.selector._xPath
+      }, {
+        frameId: clickData.frameId
+      });
+  }
+
+  /**
+   * Generate context menus for managing field types.
+   * A user must be able to select all available field types for an input
+   * element, and then generate a field validation action once all fields have
+   * been marked.
+   */
+  _createRecordingContextMenus() {
+    chrome.contextMenus.removeAll(() => {
+      const parentContextMenu = chrome.contextMenus.create({
+        title: 'Input Field Type',
+        contexts: ['all']
+      });
+      const specialFillContextMenu = chrome.contextMenus.create({
+        title: 'Special Fill',
+        contexts: ['editable']
+      });
+      chrome.contextMenus.create({
+        title: 'Fill Email',
+        contexts: ['editable'],
+        parentId: specialFillContextMenu,
+        onclick: (info, tab) => {
+          this._fillEmail();
+        }
+      });
+      chrome.contextMenus.create({
+        title: 'Fill Password',
+        contexts: ['editable'],
+        parentId: specialFillContextMenu,
+        onclick: (info, tab) => {
+          this._fillPassword();
+        }
+      });
+      chrome.contextMenus.create({
+        title: 'Validate Field Types',
+        contexts: ['all'],
+        onclick: (info, tab) => {
+          this._constructValidationAction();
+        }
+      });
+      chrome.contextMenus.create({
+        title: 'Forget Field Types',
+        contexts: ['all'],
+        onclick: (info, tab) => {
+          this._typedFields = {};
+          console.log('Field type knowledge reset.');
+        }
+      });
+      chrome.contextMenus.create({
+        title: 'Stop and Copy',
+        contexts: ['all'],
+        onclick: (info, tab) => {
+          this.stop();
+        }
+      });
+      chrome.contextMenus.create({
+        title: 'Cancel',
+        contexts: ['all'],
+        onclick: (info, tab) => {
+          this.cancel();
+        }
+      });
+
+      for (let i = 0; i < FIELD_TYPES.length; i++) {
+        const fieldType = FIELD_TYPES[i];
+
+        chrome.contextMenus.create({
+          title: fieldType,
+          parentId: parentContextMenu,
+          contexts: ['all'],
+          onclick: (info, tab) => {
+            this._setFieldTypeForEditable(fieldType);
+          }
+        });
+      }
+    });
+  }
+
+  _createIdleContextMenus() {
+    chrome.contextMenus.removeAll(() => {
+      chrome.contextMenus.create({
+        title: 'Start',
+        contexts: ['all'],
+        onclick: (info, tab) => {
+          this.start(info.pageUrl);
+        }
+      });
+      chrome.contextMenus.create({
+        title: 'Next Site',
+        contexts: ['all'],
+        onclick: (info, tab) => {
+          this._visitSite(this._nextSite());
+        }
+      });
+    });
+  }
+
+  /**
+   * Retrieve the next recommended "top 100" website url.
+   * Note that this will also advance the site index for the next call.
+   *
+   * @return {String} Complete url for the next top 100 site
+   */
+  _nextSite() {
+    if (this._siteIndex >= SITES_TO_VISIT.length) {
+      console.error('All recommended sites have been visited.');
+      return;
+    }
+
+    const hostname = SITES_TO_VISIT[this._siteIndex++];
+    return `http://${hostname}`;
+  }
+
+  /**
+   * Redirect the currently active tab to a given url.
+   * @param  {String} url Complete target url (including protocol)
+   */
+  _visitSite(url) {
+    chrome.tabs.update({
+      url: url
+    });
+  }
+}
+
+const actionRecorder = new ActionRecorder();
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/action_set.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/action_set.js
new file mode 100644
index 0000000..3a1195cd
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/action_set.js
@@ -0,0 +1,238 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// global IndentedTextFactory, Type, SetContext, Open, ValidateFields
+'use strict';
+
+class ActionSet {
+  constructor(startingUrl) {
+    this._startingUrl = this._stripUrl(startingUrl);
+    this._name = this._getTestName(this._startingUrl);
+    /**
+     * A record of the actions taken by a user on a given test (website).
+     *
+     * When the user is done with a website, the extension saves the actions to
+     * a python script that can be used to re-run the action sequence as a test
+     * suite.
+     *
+     * @type {Array}
+     */
+    this._steps = [];
+
+    this.addAction(new Open(this._startingUrl));
+  }
+
+  addAction(action) { this._steps.push(action); }
+
+  toString() {
+    const textFactory = new IndentedTextFactory();
+
+    // Task class setup
+    textFactory.addLine(`class ${this._name}(AutofillTask):`);
+
+    textFactory.increase();
+    textFactory.addLine('def _create_script(self):');
+    textFactory.increase();
+    textFactory.addLine('self.script = [');
+    textFactory.increase(2);
+
+    for (let i = 0; i < this._steps.length; i++) {
+      let action = this._steps[i];
+      if (action instanceof ValidateFields) {
+        // Trim last character, which is a new line
+        const actionText = `${action.toString().slice(0, -1)},`;
+        textFactory.addLines(actionText);
+      } else {
+        const actionText = `${action},`;
+        textFactory.addLine(actionText);
+      }
+    }
+
+    // Close script array
+    textFactory.decrease(2);
+    textFactory.addLine(']');
+
+    return textFactory.toString();
+  }
+
+  /**
+   * Return the name of the test based on the form's url |url|
+   * (e.g. http://login.example.com/path => test_login_example_com).
+   *
+   * @param  {String} url The form's url
+   * @return {String}     The test name
+   */
+  _getTestName(url) {
+    const a = document.createElement('a');
+    a.href = url;
+    let splitHostname = a.hostname.split(/[.-]+/);
+
+    let hostname = '';
+
+    for (var i = 0; i < splitHostname.length; i++) {
+      let segment = splitHostname[i];
+
+      if (i === 0 && segment === 'www') {
+        continue;
+      }
+
+      hostname += segment.charAt(0).toUpperCase() + segment.slice(1);
+    }
+
+    return `Test${hostname}`;
+  }
+
+  /**
+   * Removes query and anchor from |url|
+   * (e.g. https://example.com/path?query=1#anchor => https://example.com/path).
+   *
+   * @param  {String} url The full url to be processed
+   * @return {String}     The url w/o parameters and anchors
+   */
+  _stripUrl(url) {
+    const a = document.createElement('a');
+    a.href = url;
+    return a.origin + a.pathname;
+  }
+
+  /**
+   * Remove the specified set of |indiciesToRemove| from the internal action
+   * array.
+   *
+   * The method does the removal in linear time and in place.
+   *
+   * Will truncate the internal array by the length of |indiciesToRemove|.
+   * @param {Array} indiciesToRemove An array of indicies to remove from _steps
+   */
+  _removeIndicies(indiciesToRemove) {
+    if (!indiciesToRemove || indiciesToRemove.length === 0) {
+      return;
+    }
+
+    indiciesToRemove.sort((a, b) => a - b);
+
+    let removalIndex = 0;
+
+    // Jump to first removal
+    for (var i = indiciesToRemove[0]; i < this._steps.length; i++) {
+      if (removalIndex < indiciesToRemove.length &&
+          i === indiciesToRemove[removalIndex]) {
+        // Undesired element so skip copying it to it's "new" place
+        removalIndex++;
+      } else {
+        this._steps[i - removalIndex] = this._steps[i];
+      }
+    }
+
+    // Truncate array
+    this._steps.length -= removalIndex;
+  }
+
+  /**
+   * Eliminate redundant actions.
+   *
+   * Current optimizations:
+   *  - Multi-pass removal of redundant context switching
+   *  - Remove adjacent typing events for same element
+   *
+   * Warning: This removes events from the internal action set.
+   */
+  optimize() {
+    this._optimizeContextSwitching();
+    this._optimizeTyping();
+  }
+
+  /**
+   * Remove adjacent typing events for same element.
+   *
+   * Example: The following set of actions:
+   *  Type(ByXPath('//*[@id="tbPhone"]'), ''),
+   *  Type(ByXPath('//*[@id="tbPhone"]'), '324'),
+   *  Type(ByXPath('//*[@id="tbPhone"]'), '5603928181'),
+   *
+   * will be reduced to the following:
+   *  Type(ByXPath('//*[@id="tbPhone"]'), '5603928181'),
+   *
+   * Warning: This removes events from the internal action set.
+   */
+  _optimizeTyping() {
+    const indiciesToRemove = [];
+
+    for (let i = 0; i < this._steps.length - 1; i++) {
+      const currentAction = this._steps[i];
+      if (!(currentAction instanceof Type)) {
+        continue;
+      }
+
+      if (currentAction.isEqual(this._steps[i + 1])) {
+        // Mark this index for removal
+        indiciesToRemove.push(i);
+
+        console.log(`Removed redundant typing action ${this._steps[i]}`);
+      }
+    }
+
+    // Remove duplicate indicies
+    this._removeIndicies(indiciesToRemove);
+  }
+
+  /**
+   * Multi-pass removal of redundant context switching.
+   *
+   * Note: A ContextSwitch action called with None changes to the parent context
+   *
+   * Example: The following set of actions:
+   *  Click(ByID('register')),
+   *  SetContext(ByID('overlayRegFrame')),
+   *  Click(ByCssSelector('.regTaEmail')),
+   *  SetContext(None),
+   *  SetContext(ByID('overlayRegFrame')),
+   *  Click(ByCssSelector('div.ui_button.regSubmitBtn')),
+   *  SetContext(None),
+   *  Click(ByCssSelector('.greeting.link')),
+   *
+   * will be reduced to the following:
+   *  Click(ByID('register')),
+   *  SetContext(ByID('overlayRegFrame')),
+   *  Click(ByCssSelector('.regTaEmail')),
+   *  Click(ByCssSelector('div.ui_button.regSubmitBtn')),
+   *  SetContext(None),
+   *  Click(ByCssSelector('.greeting.link')),
+   *
+   * Warning: This removes events from the internal action set.
+   */
+  _optimizeContextSwitching() {
+    let hasChanged = true;
+
+    while (hasChanged) {
+      hasChanged = false;
+      const indiciesToRemove = [];
+
+      for (let i = 0; i < this._steps.length - 1; i++) {
+        const currentAction = this._steps[i];
+        const nextAction = this._steps[i + 1];
+        if (!(currentAction instanceof SetContext)) {
+          console.log(`Skipping ${currentAction}`);
+          continue;
+        }
+
+        if (currentAction.isEqual(nextAction)) {
+          console.log(
+              'Removed redundantly inverse context switching actions' +
+              `${currentAction} and ${nextAction}`);
+
+          // Mark both indicies for removal
+          indiciesToRemove.push(i++);
+          indiciesToRemove.push(i);
+          hasChanged = true;
+        } else {
+          console.log(`Not-equal objects ${currentAction} and ${nextAction}`);
+        }
+      }
+
+      // Remove duplicate indicies
+      this._removeIndicies(indiciesToRemove);
+    }
+  }
+}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/actions.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/actions.js
new file mode 100644
index 0000000..83f7d73
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/actions.js
@@ -0,0 +1,255 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/* global IndentedTextFactory */
+'use strict';
+
+function escapeSingleQuotes(str) {
+  return str.replace(/\'/g, '\\\'');
+}
+
+function compareArrays(array1, array2) {
+  if (array1.length !== array2.length) {
+    return false;
+  }
+
+  for (let i = 0; i < array1.length; i++) {
+    if (array1[i] !== array2[i]) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+class ByXPath {
+  constructor(xPath) {
+    if (xPath) {
+      xPath = escapeSingleQuotes(xPath);
+    }
+
+    this._xPath = xPath || null;
+  }
+
+  /**
+   * Defines the method used to represent an XPath selector as executable python
+   * code.
+   *
+   * @return {String} Python code representation of the selector class
+   */
+  toString() { return `ByXPath('${this._xPath}')`; }
+
+  /**
+   * Compares the two actions to check whether they are identical.
+   *
+   * @param  {Action}  other Action to compare this against
+   * @return {Boolean}       Whether the actions are identical
+   */
+  isEqual(other) {
+    return (other instanceof ByXPath) && this._xPath === other._xPath;
+  }
+}
+
+class Action {
+  /**
+   * @constructor
+   * @param {String}  type     Action type name, also the name of the class
+   *                           used in the generated test
+   * @param {ByXPath} selector An instance of a valid selector which will be
+   *                           used to find the element to perform the action on
+   * @param {String}  ...args  Additional arguments specific to the action
+   */
+  constructor(type, selector, ...args) {
+    this._type = type;
+    this._selector = selector;
+    this._extraArgs = args;
+  }
+
+  /**
+   * Defines the method used to represent Actions as executable python code.
+   *
+   * These stringified actions can be combined in an action set to create
+   * automated browser integration tests.
+   *
+   * @return {String} Python code representation of the Action class
+   */
+  toString() {
+    let extraArgString = '';
+
+    for (let i = 0; i < this._extraArgs.length; i++) {
+      if (this._extraArgs[i] !== undefined && this._extraArgs[i] !== null) {
+        extraArgString += `, ${this._extraArgs[i]}`;
+      }
+    }
+
+    return `${this._type}(${this._selector}${extraArgString})`;
+  }
+
+  /**
+   * Compares the two actions to check whether they are identical.
+   *
+   * @param  {Action}  other Action to compare this against
+   * @return {Boolean}       Whether the actions are identical
+   */
+  isEqual(other) {
+    return this._type === other._type &&
+        this._selector.isEqual(other._selector) &&
+        compareArrays(this._extraArgs, other._extraArgs);
+  }
+}
+
+class Open extends Action {
+  /**
+   * @constructor
+   * @param  {String} url Absolute url to navigate the browser to
+   */
+  constructor(url) {
+    if (url) {
+      url = escapeSingleQuotes(url);
+    }
+
+    super('Open', `'${url}'`);
+  }
+}
+
+class SetContext extends Action {
+  /**
+   * @constructor
+   * @param {ByXPath} selector An instance of a valid selector which will be
+   *                           used to find the element to perform the action on
+   * @param {Boolean} ignorable Whether the test can proceed if the action fails
+   * @param {ByXPath} inverse  If this selector is 'None', then this property is
+   *                           the selector for the context that it is returning
+   *                           'out' of (used to reduce redundant actions)
+   */
+  constructor(selector, ignorable, inverse) {
+    super('SetContext', selector, ignorable);
+
+    this._inverse = inverse;
+  }
+
+  /**
+   * Compares the two SetContext actions and evaluates whether they cancel
+   * eachother (and thus can be both removed with no net effect).
+   *
+   * @param  {Action}  other Action to compare this against
+   * @return {Boolean}       Whether the two actions can be removed safely
+   */
+  isEqual(other) {
+    if (this._type !== other._type) {
+      return false;
+    }
+
+    if (this._selector === 'None') {
+      return this._inverse.isEqual(other._selector);
+    } else if (other._selector === 'None') {
+      return this._selector.isEqual(other._inverse);
+    }
+
+    return false;
+  }
+}
+
+class Type extends Action {
+  /**
+   * @constructor
+   * @param {ByXPath} selector An instance of a valid selector which will be
+   *                           used to find the element to perform the action on
+   * @param {String}  text     Content to fill the input field with
+   * @param {Boolean} ignorable Whether the test can proceed if the action fails
+   * @param {Boolean*} rawText  Whether the text should be printed as is. This
+   *                            is useful for injecting helper functions
+   *                            (ex. GenEmail())
+   */
+  constructor(selector, text, ignorable, rawText) {
+    text = rawText ? text : `'${text}'`;
+    super('Type', selector, text, ignorable);
+  }
+
+  /**
+   * Compares the two typing actions.
+   *
+   * Note: even if the text of the two actions is different, they are
+   * considered as equal as long as they target the same object.
+   *
+   * @param  {Action}  other Action to compare this against
+   * @return {Boolean}       Whether the first of the two actions is redundant
+   */
+  isEqual(other) {
+    return this._type === other._type &&
+        this._selector.isEqual(other._selector);
+  }
+}
+
+class Select extends Action {
+  /**
+   * @constructor
+   * @param {ByXPath} selector An instance of a valid selector which will be
+   *                           used to find the element to perform the action on
+   * @param {String}  value    Value of the option to select
+   * @param {Boolean} ignorable Whether the test can proceed if the action fails
+   * @param {Boolean*} byLabel  Whether |value| represents the option's label.
+   *                            This is useful for improving the reliability of
+   *                            an action if the value is less stable than the
+   *                            human readable form
+   */
+  constructor(selector, value, ignorable, byLabel) {
+    super('Select', selector, `'${value}'`, ignorable, byLabel);
+  }
+}
+
+class Click extends Action {
+  /**
+   * @constructor
+   * @param {ByXPath} selector An instance of a valid selector which will be
+   *                           used to find the element to perform the action on
+   * @param {Boolean} ignorable Whether the test can proceed if the action fails
+   */
+  constructor(selector, ignorable) { super('Click', selector, ignorable); }
+}
+
+class TriggerAutofill extends Action {
+  /**
+   * @constructor
+   * Will attempt to trigger autofill using keystrokes with a form field in
+   * focus.
+   * @param {ByXPath} selector An instance of a valid selector which will be
+   *                           used to find the element to perform the action on
+   * @param {Boolean} ignorable Whether the test can proceed if the action fails
+   */
+  constructor(selector, ignorable) {
+    super('TriggerAutofill', selector, ignorable);
+  }
+}
+
+class TypedField {
+  constructor(selector, fieldType) {
+    this._selector = selector;
+    this._fieldType = fieldType;
+  }
+
+  toString() { return `(${this._selector}, '${this._fieldType}')`; }
+}
+
+class ValidateFields {
+  constructor(fields) { this._fields = fields; }
+
+  toString() {
+    const textFactory = new IndentedTextFactory();
+
+    textFactory.addLine('ValidateFields([');
+    textFactory.increase(2);
+
+    for (let i = 0; i < this._fields.length; i++) {
+      textFactory.addLine(`${this._fields[i]},`);
+    }
+
+    textFactory.decrease(2);
+    textFactory.addLine('])');
+
+    return textFactory.toString();
+  }
+
+  isEqual() { return false; }
+}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/field_types.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/field_types.js
new file mode 100644
index 0000000..955aa1a
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/field_types.js
@@ -0,0 +1,81 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const FIELD_TYPES = [
+  'NONE',
+  'NO_SERVER_DATA',
+  'UNKNOWN_TYPE',
+  'EMPTY_TYPE',
+  'NAME_FIRST',
+  'NAME_MIDDLE',
+  'NAME_LAST',
+  'NAME_MIDDLE_INITIAL',
+  'NAME_FULL',
+  'NAME_SUFFIX',
+  'EMAIL_ADDRESS',
+  'PHONE_HOME_NUMBER',
+  'PHONE_HOME_CITY_CODE',
+  'PHONE_HOME_COUNTRY_CODE',
+  'PHONE_HOME_CITY_AND_NUMBER',
+  'PHONE_HOME_WHOLE_NUMBER',
+  'PHONE_FAX_NUMBER',
+  'PHONE_FAX_CITY_CODE',
+  'PHONE_FAX_COUNTRY_CODE',
+  'PHONE_FAX_CITY_AND_NUMBER',
+  'PHONE_FAX_WHOLE_NUMBER',
+  'ADDRESS_HOME_LINE1',
+  'ADDRESS_HOME_LINE2',
+  'ADDRESS_HOME_APPT_NUM',
+  'ADDRESS_HOME_CITY',
+  'ADDRESS_HOME_STATE',
+  'ADDRESS_HOME_ZIP',
+  'ADDRESS_HOME_COUNTRY',
+  'ADDRESS_BILLING_LINE1',
+  'ADDRESS_BILLING_LINE2',
+  'ADDRESS_BILLING_APPT_NUM',
+  'ADDRESS_BILLING_CITY',
+  'ADDRESS_BILLING_STATE',
+  'ADDRESS_BILLING_ZIP',
+  'ADDRESS_BILLING_COUNTRY',
+  'CREDIT_CARD_NAME',
+  'CREDIT_CARD_NUMBER',
+  'CREDIT_CARD_EXP_MONTH',
+  'CREDIT_CARD_EXP_2_DIGIT_YEAR',
+  'CREDIT_CARD_EXP_4_DIGIT_YEAR',
+  'CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR',
+  'CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR',
+  'CREDIT_CARD_TYPE',
+  'CREDIT_CARD_VERIFICATION_CODE',
+  'COMPANY_NAME',
+  'FIELD_WITH_DEFAULT_VALUE',
+  'PHONE_BILLING_NUMBER',
+  'PHONE_BILLING_CITY_CODE',
+  'PHONE_BILLING_COUNTRY_CODE',
+  'PHONE_BILLING_CITY_AND_NUMBER',
+  'PHONE_BILLING_WHOLE_NUMBER',
+  'NAME_BILLING_FIRST',
+  'NAME_BILLING_MIDDLE',
+  'NAME_BILLING_LAST',
+  'NAME_BILLING_MIDDLE_INITIAL',
+  'NAME_BILLING_FULL',
+  'NAME_BILLING_SUFFIX',
+  'MERCHANT_EMAIL_SIGNUP',
+  'MERCHANT_PROMO_CODE',
+  'PASSWORD',
+  'ACCOUNT_CREATION_PASSWORD',
+  'ADDRESS_HOME_STREET_ADDRESS',
+  'ADDRESS_BILLING_STREET_ADDRESS',
+  'ADDRESS_HOME_SORTING_CODE',
+  'ADDRESS_BILLING_SORTING_CODE',
+  'ADDRESS_HOME_DEPENDENT_LOCALITY',
+  'ADDRESS_BILLING_DEPENDENT_LOCALITY',
+  'ADDRESS_HOME_LINE3',
+  'ADDRESS_BILLING_LINE3',
+  'NOT_ACCOUNT_CREATION_PASSWORD',
+  'USERNAME',
+  'USERNAME_AND_EMAIL_ADDRESS',
+  'NEW_PASSWORD',
+  'PROBABLY_NEW_PASSWORD',
+  'NOT_NEW_PASSWORD'
+];
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/indented_string_factory.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/indented_string_factory.js
new file mode 100644
index 0000000..f41b20e
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/indented_string_factory.js
@@ -0,0 +1,60 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+class IndentedTextFactory {
+  /**
+   * Create an intented text factory, optionally with initial indentation level.
+   * @param {Number} indent The initial number of indents (must be natural)
+   * @param {String} spaces (Optional) Spacing to use for an indent
+   */
+  constructor(indent, spaces) {
+    this._indent = indent || 0;
+    this._spaces = spaces || '  ';
+    this._contents = '';
+  }
+
+  /**
+   * Increase indent level.
+   * @param {Number} steps The number of indents to increase by
+   */
+  increase(steps) { this._indent += (steps || 1); }
+
+  /**
+   * Decrease indent level.
+   * @param {Number} steps The number of indents to decrease by
+   */
+  decrease(steps) { this._indent = (this._indent - (steps || 1)) || 0; }
+
+  /**
+   * Add a single line of text to the internal content.
+   * @param {String} text A single line of text
+   */
+  addLine(text) {
+    let indents = '';
+
+    // Add indentation
+    for (let i = 0; i < this._indent; i++) {
+      indents += this._spaces;
+    }
+
+    this._contents += `${indents}${text}\n`;
+  }
+
+  /**
+   * Add a multiline string of text to the internal content.
+   * Each line will receive the current level of indentation.
+   * @param {String} multilineText A multi-line string of text
+   */
+  addLines(multilineText) {
+    const lines = multilineText.split('\n');
+
+    for (let i = 0; i < lines.length; i++) {
+      this.addLine(lines[i]);
+    }
+  }
+
+  toString() { return this._contents; }
+}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/sites_to_visit.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/sites_to_visit.js
new file mode 100644
index 0000000..ed89f8e3
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/sites_to_visit.js
@@ -0,0 +1,10 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The list of sites to generate Python tests for.
+const SITES_TO_VISIT = [
+  'www.lowes.ca', 'Abercrombie.com', 'www.GameStop.com', 'Lowes.com',
+  'Newegg.com', 'Costco.com', 'Ikea.com', 'Etsy.com', 'LuluLemon.com',
+  'Williams-Sonoma.com'
+];
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js b/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js
new file mode 100644
index 0000000..7c73045
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js
@@ -0,0 +1,454 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+const LEFT_BUTTON = 0;
+const RIGHT_BUTTON = 2;
+
+/**
+ * Create an editing timer that will execute a command if the timer is not
+ * triggered within a given timeout interval.
+ */
+class EditingTimer {
+  /**
+   * @constructor
+   * @param  {Element}  element  Target editable element
+   * @param  {Function} callback Function to call if the timeout occurs
+   * @param  {Number}   interval Timeout interval in ms
+   */
+  constructor(element, callback, interval) {
+    this._element = element;
+    this._timer = 0;
+    this._callback = callback;
+    this._interval = interval;
+
+    this._mouseOutListener = () => { this.cancel(true); };
+
+    this._addMouseOutListener();
+
+    this._element.addEventListener('keyup', (event) => {
+      this.trigger();
+      this._addMouseOutListener();
+    });
+  }
+
+  /**
+   * Start/postpone the timeout
+   */
+  trigger() {
+    this._removeMouseOutListener();
+
+    clearTimeout(this._timer);
+    this._timer = setTimeout(this._callback, this._interval);
+  }
+
+  /**
+   * Cancel the timeout immediately and optionally fire the callback.
+   * @param  {Boolean*} executeCallback Callback will be executed if truthy
+   */
+  cancel(executeCallback) {
+    this._removeMouseOutListener();
+    clearTimeout(this._timer);
+
+    if (executeCallback) {
+      this._callback();
+    }
+  }
+
+  _addMouseOutListener() {
+    this._element.addEventListener('mouseout', this._mouseOutListener);
+  }
+
+  _removeMouseOutListener() {
+    this._element.removeEventListener('mouseout', this._mouseOutListener);
+  }
+}
+
+class ActionHandler {
+  constructor() { this._startListeners(); }
+
+  /**
+   * Returns true if |element| is probably a clickable element.
+   *
+   * @param  {Element} element The element to be checked
+   * @return {boolean}         True if the element is probably clickable
+   */
+  _isClickableElementOrInput(element) {
+    return (
+        element.tagName == 'INPUT' || element.tagName == 'A' ||
+        element.tagName == 'BUTTON' || element.tagName == 'SUBMIT' ||
+        element.getAttribute('href'));
+  }
+
+  /**
+   * Returns |element|, if |element| is clickable element. Otherwise, returns
+   * clickable children or parent of the given element |element|.
+   * Font element might consume a user click, but ChromeDriver will be unable to
+   * click on the font element, so find an actually clickable element to target.
+   *
+   * @param  {Element} element The element where a clickable tag should be find.
+   * @return {Element}         The clicable element.
+   */
+  _fixElementSelection(element) {
+    if (this._isClickableElementOrInput(element)) {
+      return element;
+    }
+
+    const clickableChildren = element.querySelectorAll(
+        ':scope input, :scope a, :scope button, :scope submit, :scope [href]');
+
+    // If any of the children are clickable, use them.
+    if (clickableChildren.length > 0) {
+      return clickableChildren[0];
+    }
+
+    // Check if any of the parent elements (within 5) are clickable.
+    let parent = element;
+    for (let i = 0; i < 5; i++) {
+      parent = parent.parentElement;
+      if (!parent) {
+        break;
+      }
+
+      if (this._isClickableElementOrInput(parent)) {
+        return parent;
+      }
+    }
+
+    return element;
+  }
+
+  /**
+   * Send the message object to the appropriate parent.
+   *
+   * If this is not the root frame in the tab then the message will be sent to
+   * the direct parent frame. However, if this is the root frame, the message
+   * is sent to the background script.
+   *
+   * @param  {Object} object Message payload
+   */
+  _sendMessageToParent(object) {
+    if (this._frameId === 0) {
+      chrome.runtime.sendMessage(object);
+    } else {
+      if (object) {
+        object.url = document.location.href;
+      }
+
+      chrome.runtime.sendMessage({
+        type: 'forward-message-to-tab',
+        args: [this._tabId, object, {frameId: this._parentFrameId}]
+      });
+    }
+  }
+
+  /**
+   * Construct action an object.
+   *
+   * @param  {String} type     Action type code (ex. 'type', 'left-click')
+   * @param  {String} selector XPath reference to the element within the current
+   *                           frame
+   * @param  {...*}   ...args  Remaining args that're to be applied to the
+   *                           action's constructor
+   */
+  _createAction(type, selector, ...args) {
+    return {type: type, selector: selector, args: args};
+  }
+
+  _registerTypeAction(element) {
+    const selector = xPathTools.xPath(element, true);
+    const value = element.value;
+
+    this._log(`Typing detected on: ${selector} with '${value}'`);
+
+    this._sendMessageToParent(
+        {type: 'action', data: this._createAction('type', selector, value)});
+  }
+
+  _registerSelectAction(event) {
+    const element = event.target;
+    const selector = xPathTools.xPath(element, true);
+
+    this._log('Select detected on:', selector);
+
+    this._sendMessageToParent({
+      type: 'action',
+      data: this._createAction('select', selector, element.value)
+    });
+  }
+
+  /**
+   * Register the child frame's action by switching context to and from that of
+   * the frame and sending it to the parent of this frame.
+   *
+   * @param  {Object} action Action data object to wrap with context switching
+   * @param  {String} url    URL of child iframe (used to select element)
+   */
+  _registerChildAction(action, url) {
+    this._registerChildActions([action], url);
+  }
+
+  /**
+   * Register the child frame's actions by switching context to and from that of
+   * the frame and sending it to the parent of this frame.
+   *
+   * @param  {Array} actions Array of action data objects to wrap with context
+   *                         switching
+   * @param  {String} url    URL of child iframe (used to select element)
+   */
+  _registerChildActions(actions, url) {
+    const element = document.querySelector(`iframe[src="${url}"]`);
+
+    if (element === null) {
+      return console.error(
+          `[Frame: ${this._frameId}] Unable to find iframe for child actions:`,
+          url);
+    }
+
+    const selector = xPathTools.xPath(element, true);
+
+    actions.unshift(this._createAction('set-context', selector));
+    actions.push(
+        this._createAction('set-context', 'None', undefined, selector));
+
+    this._sendMessageToParent({type: 'actions', data: actions});
+  }
+
+  /**
+   * Create a listener for a given editable element.
+   *
+   * If the element is a text input field then typing events will be generated
+   * after 1000ms of inactivity (once typing has commenced), or if the mouse
+   * leaves the field.
+   *
+   * @param {Element} element Target DOM Element
+   */
+  _addEditableElementListener(element) {
+    switch (element.localName) {
+      case 'input':
+      case 'textarea':
+        switch (element.getAttribute('type')) {
+          case 'radio':
+          case 'submit':
+            break;
+          default:
+            const editTimer = new EditingTimer(
+                element, () => { this._registerTypeAction(element); }, 1000);
+        }
+        break;
+      case 'select':
+        element.addEventListener(
+            'change', (event) => { this._registerSelectAction(event); });
+        break;
+    }
+  }
+
+  /**
+   * Create a mutation observer that watches for elements that are added
+   * post-DOMContentLoaded by the site's custom js.
+   *
+   * This will attach change listeners on all new editable elements.
+   *
+   * Note: You must also attach listeners to existing elements.
+   */
+  _setupMutationObserver() {
+    this._mutationObserver = new MutationObserver((mutations) => {
+      mutations.forEach(mutation => {
+        mutation.addedNodes.forEach(newNode => {
+          if (newNode.nodeType === Node.ELEMENT_NODE) {
+            this._addEditableElementListener(newNode);
+          }
+        });
+      });
+    });
+
+    this._mutationObserver.observe(document, {childList: true});
+  }
+
+  /**
+   * Retrieves data about this tab & frame from the background script.
+   * @param  {Function} cb Called once the data has been retrieved
+   */
+  _setupChildMessageHandler(cb) {
+    chrome.runtime.sendMessage({type: 'get-frame-info'}, (response) => {
+      this._tabId = response.tabId;
+      this._frameId = response.frameId;
+      this._parentFrameId = response.parentFrameId;
+      this._log(`Parent frame id is ${this._parentFrameId}`);
+
+      cb();
+    });
+  }
+
+  /**
+   * Setup all the event & message listeners that're required to detect and
+   * report actions.
+   */
+  _startListeners() {
+    this._setupChildMessageHandler(() => {
+      this._setupMutationObserver();
+
+      const editableElements =
+          document.querySelectorAll('input,textarea,select');
+      editableElements.forEach(
+          (element) => { this._addEditableElementListener(element); });
+
+      /**
+       * Listen for messages from the background script
+       */
+      chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
+        if (!request) {
+          console.error('Invalid request from background script.', request);
+          return;
+        }
+
+        let element = null;
+
+        switch (request.type) {
+          case 'fill-element':
+            if (!request.selector) {
+              return console.error(
+                  'Unable to fill element, invalid request selector', request);
+            }
+
+            this._log('Filling element', request.selector);
+
+            element = this._getElementByXPath(request.selector);
+
+            if (element === null) {
+              return console.error('Unable to fill element, not found');
+            }
+
+            this._log(`Filling element with '${request.content}'`);
+
+            element.value = request.content;
+
+            this._registerTypeAction(element);
+            break;
+          case 'fill-email':
+            if (!request.selector) {
+              return console.error(
+                  'Unable to fill element, invalid request selector', request);
+            }
+
+            this._log('Filling element', request.selector);
+
+            element = this._getElementByXPath(request.selector);
+
+            if (element === null) {
+              return console.error('Unable to fill element, not found');
+            }
+
+            this._log('Filling element with random email');
+
+            element.value = this._generateEmail();
+
+            this._sendMessageToParent({
+              type: 'action',
+              data: this._createAction('fill-email', request.selector)
+            });
+            break;
+          case 'fill-password':
+            if (!request.selector) {
+              return console.error(
+                  'Unable to fill element, invalid request selector', request);
+            }
+
+            this._log('Filling element', request.selector);
+
+            element = this._getElementByXPath(request.selector);
+
+            if (element === null) {
+              return console.error('Unable to fill element, not found');
+            }
+
+            this._log('Filling element with random password');
+
+            element.value = this._generatePassword();
+
+            this._sendMessageToParent({
+              type: 'action',
+              data: this._createAction('fill-password', request.selector)
+            });
+            break;
+          case 'action':
+            // Handle a child frame's action
+            this._log('Child frame action received:', request.data);
+            this._registerChildAction(request.data, request.url);
+            break;
+          case 'actions':
+            // Handle a child frame's actions
+            this._log('Child frame actions received:', request.data);
+            this._registerChildActions(request.data, request.url);
+            break;
+          default:
+            console.error(`Unknown request type: ${request.type}`);
+        }
+      });
+      /**
+       * Click event listener
+       */
+      document.addEventListener('mousedown', (event) => {
+        const element = this._fixElementSelection(event.target);
+        const selector = xPathTools.xPath(element, true);
+
+        let type;
+
+        switch (event.button) {
+          case LEFT_BUTTON:
+            this._log(`Left-click detected on: ${selector}`);
+
+            type = 'left-click';
+
+            this._sendMessageToParent(
+                {type: 'action', data: this._createAction(type, selector)});
+            break;
+          case RIGHT_BUTTON:
+            this._log(`Right-click detected on: ${selector}`);
+
+            type = 'right-click';
+
+            chrome.runtime.sendMessage(
+                {type: 'action', data: this._createAction(type, selector)});
+            break;
+          default:
+            return console.error(
+                'Unknown button used for mousedown:', event.button);
+        }
+      }, true);
+    });
+  }
+
+  _getElementByXPath(xpath) {
+    return document
+        .evaluate(
+            xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
+        .singleNodeValue;
+  }
+
+  _generateString(length) {
+    length = length || 8;
+
+    const lowerCaseChars = 'abcdefghijklmnopqrstuvwxyz';
+    let result = '';
+    for (let i = 0; i < length; i++) {
+      let charIndex = Math.floor(Math.random() * lowerCaseChars.length);
+      result += lowerCaseChars[charIndex];
+    }
+    return result;
+  }
+
+  _generateEmail() {
+    return `${this._generateString()}@${this._generateString()}.co.uk`;
+  }
+
+  _generatePassword() { return `${this._generateString()}!234&`; }
+
+  _log(message, ...args) {
+    console.log(`[Frame: ${this._frameId}] ${message}`, ...args);
+  }
+}
+
+const actionHandler = new ActionHandler();
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/x_path_tools.js b/components/test/data/autofill/automated_integration/action_recorder_extension/content/x_path_tools.js
new file mode 100644
index 0000000..d0141f2
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/content/x_path_tools.js
@@ -0,0 +1,353 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Copyright (C) 2011 Google Inc.  All rights reserved.
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ * Copyright (C) 2009 Joseph Pecoraro
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ */
+'use strict';
+
+if (!xPathTools) {
+  var xPathTools = {};
+
+  /**
+   * @param {!WebInspector.DOMNode} node
+   * @param {boolean=} optimized
+   * @return {string}
+   */
+  xPathTools.xPath = function(node, optimized) {
+    if (node.nodeType === Node.DOCUMENT_NODE) {
+      return '/';
+    }
+
+    var steps = [];
+    var contextNode = node;
+    while (contextNode) {
+      var step = xPathTools._xPathValue(contextNode, optimized);
+      if (!step) {
+        break;  // Error - bail out early.
+      }
+      steps.push(step);
+      if (step.unique) {
+        break;
+      }
+      contextNode = contextNode.parentNode;
+    }
+
+    steps.reverse();
+    return (steps.length && steps[0].unique ? '' : '/') + steps.join('/');
+  };
+
+  /**
+   * @param {!WebInspector.DOMNode} node
+   * @param {boolean=} optimized
+   * @return {?xPathTools.DOMNodePathStep}
+   */
+  xPathTools._xPathValue = function(node, optimized) {
+    var ownValue;
+    var ownIndex = xPathTools._xPathIndex(node);
+    if (ownIndex === -1) {
+      return null;  // Error.
+    }
+
+    switch (node.nodeType) {
+      case Node.ELEMENT_NODE:
+        if (optimized) {
+          const optimizedStep = xPathTools._optimizedElementNodeStep(node);
+
+          if (optimizedStep !== null) {
+            return optimizedStep;
+          }
+        }
+        ownValue = node.localName;
+        break;
+      case Node.ATTRIBUTE_NODE:
+        ownValue = '@' + node.nodeName;
+        break;
+      case Node.TEXT_NODE:
+      case Node.CDATA_SECTION_NODE:
+        ownValue = 'text()';
+        break;
+      case Node.PROCESSING_INSTRUCTION_NODE:
+        ownValue = 'processing-instruction()';
+        break;
+      case Node.COMMENT_NODE:
+        ownValue = 'comment()';
+        break;
+      case Node.DOCUMENT_NODE:
+        ownValue = '';
+        break;
+      default:
+        ownValue = '';
+        break;
+    }
+
+    if (ownIndex > 0) {
+      ownValue += '[' + ownIndex + ']';
+    }
+
+    return new xPathTools.DOMNodePathStep(
+        ownValue, node.nodeType === Node.DOCUMENT_NODE);
+  };
+
+  /**
+   * @constructor
+   * @param {string} value
+   * @param {boolean} unique
+   */
+  xPathTools.xPathBuilder = function(localName) {
+    this._localName = localName;
+    this._classifiers = [];
+  };
+
+  xPathTools.xPathBuilder.prototype = {
+    /**
+     * @return {number} The number of matching children of document
+     */
+    countMatches: function() {
+      let queryResult = document.evaluate(
+          `count(//${this})`, document, null, XPathResult.NUMBER_TYPE, null);
+      return queryResult.numberValue;
+    },
+
+    /**
+     * @param {string} classifier
+     */
+    addClassifier: function(classifier) {
+      if (classifier) {
+        this._classifiers.push(classifier);
+      }
+    },
+
+    /**
+     * @override
+     * Note that the resultant string should be either prepended with one or two
+     * forward slashes (for absolute and relative xPaths respectively).
+     * @return {string}
+     */
+    toString: function() {
+      if (this._classifiers.length > 0) {
+        let xPathSelector = this._localName + '[';
+
+        let first = true;
+
+        for (var i = 0; i < this._classifiers.length; i++) {
+          if (!first) {
+            xPathSelector += ' and ';
+          } else {
+            first = false;
+          }
+
+          xPathSelector += this._classifiers[i];
+        }
+
+        xPathSelector += ']';
+
+        return xPathSelector;
+      } else {
+        return this._localName;
+      }
+    }
+  };
+
+  /**
+   * Generate an optimized node path step for a given element node.
+   * @param  {!WebInspector.Element} element
+   * @return {?xPathTools.DOMNodePathStep}
+   */
+  xPathTools._optimizedElementNodeStep = function(element) {
+    let isUnique = false;
+
+    // Use id if available
+    if (element.id) {
+      isUnique = true;
+      return new xPathTools.DOMNodePathStep(
+          `//*[@id=\"${element.id}\"]`, isUnique);
+    }
+
+    const builder = new xPathTools.xPathBuilder(element.localName);
+    console.log(`All attributes for ${element.localName}`, element.attributes);
+
+    switch (element.localName) {
+      case 'input':
+      case 'textarea':
+      case 'select':
+        const elementType = element.getAttribute('type');
+        console.log('Element Type', elementType);
+
+        // Use type if available & unique
+        if (elementType) {
+          builder.addClassifier(`@type='${elementType}'`);
+
+          switch (elementType) {
+            case 'radio':
+            case 'submit':
+              const elementValue = element.getAttribute('value');
+
+              if (elementValue) {
+                builder.addClassifier(`@value='${elementValue}'`);
+              }
+              break;
+          }
+
+          let matchCount = builder.countMatches();
+
+          if (matchCount === 1) {
+            isUnique = true;
+            break;
+          }
+        }
+
+        const elementName = element.getAttribute('name');
+        console.log('Element Name', elementName);
+
+        // Use name if available & unique
+        if (elementName) {
+          builder.addClassifier(`@name='${elementName}'`);
+
+          let matchCount = builder.countMatches();
+
+          if (matchCount === 1) {
+            isUnique = true;
+            break;
+          }
+        }
+        break;
+      case 'a':
+      case 'span':
+      case 'button':
+        if (element.textContent) {
+          let trimmedContent = element.textContent.trim();
+          // .replace(
+          //   /^[\t\n\ ]+|[\t\n\ ]+$/g, ''
+          // );
+          builder.addClassifier(`contains(., '${trimmedContent}')`);
+
+          let matchCount = builder.countMatches();
+
+          if (matchCount === 1) {
+            isUnique = true;
+            break;
+          }
+        }
+        break;
+    }
+
+    if (builder._classifiers.length > 0) {
+      let xPathSelector = builder.toString();
+
+      if (isUnique) {
+        xPathSelector = `//${xPathSelector}`;
+      }
+
+      console.log(
+          `Generated xPathSelector for ${element.localName}`, xPathSelector);
+
+      return new xPathTools.DOMNodePathStep(xPathSelector, isUnique);
+    } else {
+      return null;
+    }
+  };
+
+  /**
+   * @param {!WebInspector.DOMNode} node
+   * @return {number}
+   */
+  xPathTools._xPathIndex = function(node) {
+    // Returns -1 on error, 0 if no siblings matching the same expression
+    // <XPath index among the same expression-matching sibling nodes> otherwise.
+    function areNodesSimilar(left, right) {
+      if (left === right) {
+        return true;
+      }
+
+      if (left.nodeType === Node.ELEMENT_NODE &&
+          right.nodeType === Node.ELEMENT_NODE) {
+        return left.localName === right.localName;
+      }
+
+      if (left.nodeType === right.nodeType) {
+        return true;
+      }
+
+      // XPath treats CDATA as text nodes.
+      var leftType = left.nodeType === Node.CDATA_SECTION_NODE ?
+          Node.TEXT_NODE :
+          left.nodeType;
+      var rightType = right.nodeType === Node.CDATA_SECTION_NODE ?
+          Node.TEXT_NODE :
+          right.nodeType;
+      return leftType === rightType;
+    }
+
+    var siblings = node.parentNode ? node.parentNode.childNodes : null;
+    if (!siblings) {
+      return 0;  // Root node - no siblings.
+    }
+    var hasSameNamedElements;
+    for (var i = 0; i < siblings.length; ++i) {
+      if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
+        hasSameNamedElements = true;
+        break;
+      }
+    }
+    if (!hasSameNamedElements) {
+      return 0;
+    }
+    var ownIndex = 1;  // XPath indices start with 1.
+    for (var i = 0; i < siblings.length; ++i) {
+      if (areNodesSimilar(node, siblings[i])) {
+        if (siblings[i] === node) {
+          return ownIndex;
+        }
+        ++ownIndex;
+      }
+    }
+    return -1;  // An error occurred: |node| not found in parent's children.
+  };
+
+  /**
+   * @constructor
+   * @param {string} value
+   * @param {boolean} unique
+   */
+  xPathTools.DOMNodePathStep = function(value, unique) {
+    this.value = value;
+    this.unique = unique || false;
+  };
+
+  xPathTools.DOMNodePathStep.prototype = {
+    /**
+     * @override
+     * @return {string}
+     */
+    toString: function() { return this.value; }
+  };
+}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle.svg b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle.svg
new file mode 100644
index 0000000..b232058
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle.svg
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   id="svg3039"
+   height="256"
+   width="256"
+   version="1.1">
+  <metadata
+     id="metadata3045">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs3043">
+    <linearGradient
+       id="linearGradient3803">
+      <stop
+         id="stop3805"
+         offset="0"
+         style="stop-color:#d7def0;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5"
+         id="stop3811" />
+      <stop
+         id="stop3807"
+         offset="1"
+         style="stop-color:#d5def0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3750">
+      <stop
+         style="stop-color:#d0e2f1;stop-opacity:1"
+         offset="0"
+         id="stop3752" />
+      <stop
+         id="stop3756"
+         offset="0.85580856"
+         style="stop-color:#cadef0;stop-opacity:1" />
+      <stop
+         style="stop-color:#95bee3;stop-opacity:1"
+         offset="1"
+         id="stop3754" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3708">
+      <stop
+         id="stop3710"
+         offset="0"
+         style="stop-color:#658db6;stop-opacity:1" />
+      <stop
+         style="stop-color:#527fab;stop-opacity:1;"
+         offset="0.76777935"
+         id="stop3716" />
+      <stop
+         id="stop3712"
+         offset="1"
+         style="stop-color:#4071a0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3698">
+      <stop
+         id="stop3700"
+         offset="0"
+         style="stop-color:#96d0e1;stop-opacity:1" />
+      <stop
+         style="stop-color:#89b7e1;stop-opacity:1"
+         offset="0.67819428"
+         id="stop3706" />
+      <stop
+         id="stop3702"
+         offset="1"
+         style="stop-color:#699dd3;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3588">
+      <stop
+         id="stop3590"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1" />
+      <stop
+         id="stop3592"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientTransform="matrix(0.02177942,-0.95743591,0.97872327,0.02221687,-235.0993,5.0684454)"
+       gradientUnits="userSpaceOnUse"
+       r="25.491526"
+       fy="121.49152"
+       fx="-118.77966"
+       cy="121.49152"
+       cx="-118.77966"
+       id="radialGradient3594"
+       xlink:href="#linearGradient3588" />
+    <filter
+       id="filter3374"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3376"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3414"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3416" />
+    </filter>
+    <filter
+       id="filter3378"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3380"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3418"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3420" />
+    </filter>
+    <filter
+       id="filter3382"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3384"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3422"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3424" />
+    </filter>
+    <filter
+       id="filter3386"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3388"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3426"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3428" />
+    </filter>
+    <filter
+       id="filter3390"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3392"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3430"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3432" />
+    </filter>
+    <filter
+       id="filter3394"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3396"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3434"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3436" />
+    </filter>
+    <filter
+       id="filter3398"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3400"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3438"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3440" />
+    </filter>
+    <filter
+       id="filter3402"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3404"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3442"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3444" />
+    </filter>
+    <filter
+       id="filter3406"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3408"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3446"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3448" />
+    </filter>
+    <filter
+       id="filter3410"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3412"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3450"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3452" />
+    </filter>
+    <filter
+       id="filter3402-5"
+       style="color-interpolation-filters:sRGB">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3404-5"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3442-4"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3444-8" />
+    </filter>
+  </defs>
+  <ellipse
+     d="m -92.745764,122.57627 a 25.491526,25.491526 0 1 1 -50.983056,0 25.491526,25.491526 0 1 1 50.983056,0 z"
+     transform="matrix(4.680851,0,0,4.7978723,685.10478,-449.69946)"
+     id="path2814"
+     style="fill:url(#radialGradient3594);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3374)" />
+  <path
+     id="path3655"
+     d="m 232.17258,88.120422 c 0,15.673918 -19.79135,34.931518 -45.84395,34.931518 -26.0526,0 -59.92241,-16.08123 -59.92241,-31.755152 0,-15.673924 21.11981,-28.38015 47.17241,-28.38015 19.90254,0 46.36122,18.293224 56.45971,20.3521 0.79179,1.710571 1.36862,2.925087 2.13424,4.851684 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3378)" />
+  <path
+     id="path3655-4-8"
+     d="m 38.822019,65.971523 c 12.38148,-9.610993 35.314514,-1.245318 51.289554,19.334679 15.975027,20.579998 17.694937,51.065068 5.31349,60.676058 -12.38147,9.61099 -34.17571,-5.29155 -50.15074,-25.87156 -12.20392,-15.72181 -4.05062,-41.19089 -8.61646,-50.430553 0.61589,-1.122052 1.381696,-2.456607 2.164156,-3.708624 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3382)" />
+  <path
+     id="path3596"
+     d="m 230.04347,83.261765 c -7.0081,-0.03265 -61.07025,0.289575 -107.66568,0.0654 -17.371,5.108098 -31.704627,13.258827 -39.181777,29.154945 -5.33639,-4.54237 -40.74576,-42.215609 -44.40678,-46.440684 31.38983,-41.648805 74.528017,-45.559321 82.915257,-45.559321 8.38724,0 70.64407,-8.631855 108.33898,62.77966 z"
+     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3386)" />
+  <path
+     id="path3655-4"
+     d="m 117.12454,243.96815 c -12.49835,-9.45851 -14.5752,-36.93927 1.14635,-57.71356 15.72155,-20.77428 41.03582,-34.94753 53.53417,-25.48904 12.49834,9.4585 7.44792,38.96701 -8.27364,59.74129 -12.01027,15.87024 -35.4911,16.88498 -43.22681,23.69505 -1.23894,-0.0455 -1.95523,-0.0605 -3.18007,-0.23374 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3390)" />
+  <path
+     id="path3596-1"
+     d="m 120.3032,244.20103 c 3.58354,-6.02268 28.85859,-52.8991 52.69131,-92.9389 4.41104,-17.56095 5.34663,-33.64185 -4.5584,-48.14993 6.62173,-2.29412 58.23852,-13.976353 63.73684,-14.987686 19.9656,48.180076 1.44992,87.338276 -2.80522,94.565966 -4.25515,7.22768 -28.40179,65.25666 -109.06453,61.51055 z"
+     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3394)" />
+  <path
+     id="path3596-1-7"
+     d="m 36.696853,69.642524 c 3.46858,6.089612 30.72312,52.780196 53.77852,93.272576 13.094367,12.50527 27.684997,19.48512 45.191737,18.03328 -1.2738,6.89113 -16.62898,57.75037 -18.4638,63.03126 -51.756237,-6.42158 -76.669777,-41.85476 -80.854757,-49.1233 -4.18497,-7.26855 -42.7297502,-56.91452 0.3483,-125.213816 z"
+     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3398)" />
+  <path
+     id="path3645"
+     d="m -338.44068,101.42373 c 0,32.65032 -26.46832,59.11864 -59.11865,59.11864 -32.65032,0 -59.11864,-26.46832 -59.11864,-59.11864 0,-32.650327 26.46832,-59.118646 59.11864,-59.118646 32.65033,0 59.11865,26.468319 59.11865,59.118646 z"
+     style="fill:#f3f3f3;fill-opacity:1;stroke:#ffffff;stroke-width:10.07013607;stroke-miterlimit:4;stroke-opacity:1;filter:url(#filter3402)"
+     transform="matrix(0.77294737,0,0,0.77619098,435.90647,53.275706)" />
+  <path
+     id="rect3782"
+     d="m 163.54619,108.89582 c 18.52979,17.09836 16.03302,29.55794 10.0625,44 -3.10892,-22.25001 -2.34478,-32.42697 -10.0625,-44 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3406)" />
+  <path
+     id="rect3782-4"
+     d="m 101.42092,173.63924 c -22.645593,-14.47335 -29.809884,-45.71983 -8.813354,-62.99032 -10.847561,19.77514 -6.225429,32.39863 8.813354,62.99032 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3410)" />
+</svg>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle128.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle128.png
new file mode 100644
index 0000000..dfbf8ab
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle128.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle16.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle16.png
new file mode 100644
index 0000000..4f8cc06
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle16.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle32.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle32.png
new file mode 100644
index 0000000..0917711
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle32.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle48.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle48.png
new file mode 100644
index 0000000..8ea7d383
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle48.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording.svg b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording.svg
new file mode 100644
index 0000000..18c112c
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording.svg
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   id="svg3039"
+   height="256"
+   width="256"
+   version="1.1">
+  <metadata
+     id="metadata3045">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs3043">
+    <linearGradient
+       id="linearGradient3803">
+      <stop
+         id="stop3805"
+         offset="0"
+         style="stop-color:#d7def0;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5"
+         id="stop3811" />
+      <stop
+         id="stop3807"
+         offset="1"
+         style="stop-color:#d5def0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3750">
+      <stop
+         style="stop-color:#d0e2f1;stop-opacity:1"
+         offset="0"
+         id="stop3752" />
+      <stop
+         id="stop3756"
+         offset="0.85580856"
+         style="stop-color:#cadef0;stop-opacity:1" />
+      <stop
+         style="stop-color:#95bee3;stop-opacity:1"
+         offset="1"
+         id="stop3754" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3708">
+      <stop
+         id="stop3710"
+         offset="0"
+         style="stop-color:#658db6;stop-opacity:1" />
+      <stop
+         style="stop-color:#527fab;stop-opacity:1;"
+         offset="0.76777935"
+         id="stop3716" />
+      <stop
+         id="stop3712"
+         offset="1"
+         style="stop-color:#4071a0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3698">
+      <stop
+         id="stop3700"
+         offset="0"
+         style="stop-color:#96d0e1;stop-opacity:1" />
+      <stop
+         style="stop-color:#89b7e1;stop-opacity:1"
+         offset="0.67819428"
+         id="stop3706" />
+      <stop
+         id="stop3702"
+         offset="1"
+         style="stop-color:#699dd3;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3588">
+      <stop
+         id="stop3590"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1" />
+      <stop
+         id="stop3592"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientTransform="matrix(0.02177942,-0.95743591,0.97872327,0.02221687,-235.0993,5.0684454)"
+       gradientUnits="userSpaceOnUse"
+       r="25.491526"
+       fy="121.49152"
+       fx="-118.77966"
+       cy="121.49152"
+       cx="-118.77966"
+       id="radialGradient3594"
+       xlink:href="#linearGradient3588" />
+    <filter
+       id="filter3374"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3376"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3414"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3416" />
+    </filter>
+    <filter
+       id="filter3378"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3380"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3418"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3420" />
+    </filter>
+    <filter
+       id="filter3382"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3384"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3422"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3424" />
+    </filter>
+    <filter
+       id="filter3386"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3388"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3426"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3428" />
+    </filter>
+    <filter
+       id="filter3390"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3392"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3430"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3432" />
+    </filter>
+    <filter
+       id="filter3394"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3396"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3434"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3436" />
+    </filter>
+    <filter
+       id="filter3398"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3400"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3438"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3440" />
+    </filter>
+    <filter
+       id="filter3402"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3404"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3442"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3444" />
+    </filter>
+    <filter
+       id="filter3406"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3408"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3446"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3448" />
+    </filter>
+    <filter
+       id="filter3410"
+       style="color-interpolation-filters:sRGB;">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3412"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3450"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3452" />
+    </filter>
+    <filter
+       id="filter3402-5"
+       style="color-interpolation-filters:sRGB">
+      <feColorMatrix
+         result="fbSourceGraphic"
+         id="feColorMatrix3404-5"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
+      <feColorMatrix
+         id="feColorMatrix3442-4"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         in="fbSourceGraphic"
+         result="fbSourceGraphicAlpha" />
+      <feColorMatrix
+         in="fbSourceGraphic"
+         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
+         id="feColorMatrix3444-8" />
+    </filter>
+  </defs>
+  <circle
+     d="m -92.745764,122.57627 a 25.491526,25.491526 0 1 1 -50.983056,0 25.491526,25.491526 0 1 1 50.983056,0 z"
+     transform="matrix(4.680851,0,0,4.7978723,685.10478,-449.69946)"
+     id="path2814"
+     style="fill:url(#radialGradient3594);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3374)" />
+  <path
+     id="path3655"
+     d="m 232.17258,88.120422 c 0,15.673918 -19.79135,34.931518 -45.84395,34.931518 -26.0526,0 -59.92241,-16.08123 -59.92241,-31.755152 0,-15.673924 21.11981,-28.38015 47.17241,-28.38015 19.90254,0 46.36122,18.293224 56.45971,20.3521 0.79179,1.710571 1.36862,2.925087 2.13424,4.851684 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3378)" />
+  <path
+     id="path3655-4-8"
+     d="m 38.822019,65.971523 c 12.38148,-9.610993 35.314514,-1.245318 51.289554,19.334679 15.975027,20.579998 17.694937,51.065068 5.31349,60.676058 -12.38147,9.61099 -34.17571,-5.29155 -50.15074,-25.87156 -12.20392,-15.72181 -4.05062,-41.19089 -8.61646,-50.430553 0.61589,-1.122052 1.381696,-2.456607 2.164156,-3.708624 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3382)" />
+  <path
+     id="path3596"
+     d="m 230.04347,83.261765 c -7.0081,-0.03265 -61.07025,0.289575 -107.66568,0.0654 -17.371,5.108098 -31.704627,13.258827 -39.181777,29.154945 -5.33639,-4.54237 -40.74576,-42.215609 -44.40678,-46.440684 31.38983,-41.648805 74.528017,-45.559321 82.915257,-45.559321 8.38724,0 70.64407,-8.631855 108.33898,62.77966 z"
+     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3386)" />
+  <path
+     id="path3655-4"
+     d="m 117.12454,243.96815 c -12.49835,-9.45851 -14.5752,-36.93927 1.14635,-57.71356 15.72155,-20.77428 41.03582,-34.94753 53.53417,-25.48904 12.49834,9.4585 7.44792,38.96701 -8.27364,59.74129 -12.01027,15.87024 -35.4911,16.88498 -43.22681,23.69505 -1.23894,-0.0455 -1.95523,-0.0605 -3.18007,-0.23374 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3390)" />
+  <path
+     id="path3596-1"
+     d="m 120.3032,244.20103 c 3.58354,-6.02268 28.85859,-52.8991 52.69131,-92.9389 4.41104,-17.56095 5.34663,-33.64185 -4.5584,-48.14993 6.62173,-2.29412 58.23852,-13.976353 63.73684,-14.987686 19.9656,48.180076 1.44992,87.338276 -2.80522,94.565966 -4.25515,7.22768 -28.40179,65.25666 -109.06453,61.51055 z"
+     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3394)" />
+  <path
+     id="path3596-1-7"
+     d="m 36.696853,69.642524 c 3.46858,6.089612 30.72312,52.780196 53.77852,93.272576 13.094367,12.50527 27.684997,19.48512 45.191737,18.03328 -1.2738,6.89113 -16.62898,57.75037 -18.4638,63.03126 -51.756237,-6.42158 -76.669777,-41.85476 -80.854757,-49.1233 -4.18497,-7.26855 -42.7297502,-56.91452 0.3483,-125.213816 z"
+     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3398)" />
+  <path
+     id="path3645"
+     d="m -338.44068,101.42373 c 0,32.65032 -26.46832,59.11864 -59.11865,59.11864 -32.65032,0 -59.11864,-26.46832 -59.11864,-59.11864 0,-32.650327 26.46832,-59.118646 59.11864,-59.118646 32.65033,0 59.11865,26.468319 59.11865,59.118646 z"
+     style="fill:#fa4e4e;fill-opacity:0.98431373;stroke:#ffffff;stroke-width:10.07013607;stroke-miterlimit:4;stroke-opacity:1"
+     transform="matrix(0.77294737,0,0,0.77619098,435.90647,53.275706)" />
+  <path
+     id="rect3782"
+     d="m 163.54619,108.89582 c 18.52979,17.09836 16.03302,29.55794 10.0625,44 -3.10892,-22.25001 -2.34478,-32.42697 -10.0625,-44 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3406)" />
+  <path
+     id="rect3782-4"
+     d="m 101.42092,173.63924 c -22.645593,-14.47335 -29.809884,-45.71983 -8.813354,-62.99032 -10.847561,19.77514 -6.225429,32.39863 8.813354,62.99032 z"
+     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3410)" />
+</svg>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording128.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording128.png
new file mode 100644
index 0000000..cdf17c6
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording128.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording16.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording16.png
new file mode 100644
index 0000000..7b6d52d0
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording16.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording32.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording32.png
new file mode 100644
index 0000000..7450fe02
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording32.png
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/manifest.json b/components/test/data/autofill/automated_integration/action_recorder_extension/manifest.json
new file mode 100644
index 0000000..a728edc
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/manifest.json
@@ -0,0 +1,49 @@
+{
+  "manifest_version": 2,
+
+  "name": "Action Recorder Extension",
+  "description": "Extension to record user actions and generate autofill tests from them",
+  "version": "1.0.0",
+  "minimum_chrome_version": "50",
+
+  "icons": {
+    "16": "icons/icon_idle16.png",
+    "48": "icons/icon_idle48.png",
+    "128": "icons/icon_idle128.png"
+  },
+
+  "browser_action": {
+    "default_icon": {
+      "16": "icons/icon_idle16.png",
+      "32": "icons/icon_idle32.png"
+    },
+    "default_title": "Action Recorder",
+    "default_popup": "popup/popup.html"
+  },
+  "background": {
+    "scripts": [
+      "background/sites_to_visit.js",
+      "background/field_types.js",
+      "background/indented_string_factory.js",
+      "background/actions.js",
+      "background/action_set.js",
+      "background/action_recorder.js"
+    ],
+    "persistent": true
+  },
+  "content_scripts": [{
+    "js": [
+      "content/x_path_tools.js",
+      "content/action_handler.js"
+    ],
+    "matches": ["<all_urls>"],
+    "all_frames": true
+  }],
+  "permissions": [
+    "clipboardWrite",
+    "tabs",
+    "notifications",
+    "contextMenus",
+    "webNavigation"
+  ]
+}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.html b/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.html
new file mode 100644
index 0000000..bba14a49
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Action Recorder Extension</title>
+    <style>
+    body {
+      overflow: hidden;
+      margin: 0px;
+      padding: 0px;
+      background: white;
+    }
+    div:first-child {
+      margin-top: 0px;
+    }
+    div {
+      cursor: pointer;
+      text-align: center;
+      padding: 5px;
+      font-family: sans-serif;
+      font-size: 1em;
+      width: 100px;
+      margin-top: 1px;
+      background: #f5f5f5;
+      border: #c8c8c8 1px solid;
+    }
+    div:hover {
+      background: #e8e8e8;
+    }
+    .hidden {
+      display: none;
+    }
+    </style>
+  </head>
+  <body>
+    <div id="start" class="hidden">Start</div>
+    <div id="next-site" class="hidden">Next Site</div>
+    <div id="stop" class="hidden">Stop &amp; Copy</div>
+    <div id="cancel" class="hidden">Cancel</div>
+    <script src="popup.js"></script>
+  </body>
+</html>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.js b/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.js
new file mode 100644
index 0000000..3f4fb71
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.js
@@ -0,0 +1,136 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+class PopupController {
+  constructor() {
+    this._startButton = document.getElementById('start');
+    this._nextSiteButton = document.getElementById('next-site');
+    this._stopButton = document.getElementById('stop');
+    this._cancelButton = document.getElementById('cancel');
+
+    this._startListeners();
+    this._getRecordingState();
+  }
+
+  startRecording() {
+    chrome.runtime.sendMessage({
+        type: 'start-recording'
+      },
+      (response) => this._handleRecordingResponse(response));
+  }
+
+  stopRecording() {
+    chrome.runtime.sendMessage({
+        type: 'stop-recording'
+      },
+      (response) => this._handleRecordingResponse(response));
+  }
+
+  cancelRecording() {
+    chrome.runtime.sendMessage({
+        type: 'cancel-recording'
+      },
+      (response) => this._handleRecordingResponse(response));
+  }
+
+  nextSite() {
+    chrome.runtime.sendMessage({
+      type: 'next-site'
+    });
+  }
+
+  _getRecordingState() {
+    chrome.runtime.sendMessage({
+        type: 'recording-state-request'
+      },
+      (response) => this._handleRecordingResponse(response));
+  }
+
+  _handleRecordingResponse(response) {
+    if (!response) {
+      return;
+    }
+
+    this._setRecordingState(!!response.isRecording);
+  }
+
+  _startListeners() {
+    this._startButton.addEventListener(
+      'click', (event) => {
+        this.startRecording();
+      });
+
+    this._stopButton.addEventListener(
+      'click', (event) => {
+        this.stopRecording();
+      });
+
+    this._cancelButton.addEventListener(
+      'click', (event) => {
+        this.cancelRecording();
+      });
+
+    this._nextSiteButton.addEventListener(
+      'click', (event) => {
+        this.nextSite();
+      });
+  }
+
+  _setRecordingState(isRecording) {
+    this._isRecording = isRecording;
+    this._updateStyling();
+  }
+
+  _updateStyling() {
+    let shownButton1, shownButton2, hiddenButton1, hiddenButton2;
+
+    if (this._isRecording) {
+      shownButton1 = this._stopButton;
+      shownButton2 = this._cancelButton;
+      hiddenButton1 = this._startButton;
+      hiddenButton2 = this._nextSiteButton;
+    } else {
+      shownButton1 = this._startButton;
+      shownButton2 = this._nextSiteButton;
+      hiddenButton1 = this._stopButton;
+      hiddenButton2 = this._cancelButton;
+    }
+
+    this._removeClass(shownButton1, 'hidden');
+    this._removeClass(shownButton2, 'hidden');
+    this._applyClass(hiddenButton1, 'hidden');
+    this._applyClass(hiddenButton2, 'hidden');
+
+    chrome.browserAction.setIcon({
+      path: this._getIconUrl()
+    });
+  }
+
+
+  _removeClass(element, className) {
+    if (element.classList.contains(className)) {
+      element.classList.remove(className);
+    }
+  }
+
+  _applyClass(element, className) {
+    element.classList.add(className);
+  }
+
+  _getIconUrl() {
+    const iconUrlPrefix = '../icons/icon_' +
+      (this._isRecording ? 'recording' : 'idle');
+
+    return {
+      '16': iconUrlPrefix + '16.png',
+      '32': iconUrlPrefix + '32.png'
+    };
+  }
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+  const popupController = new PopupController();
+});
diff --git a/components/test/data/autofill/automated_integration/autofill_task/__init__.py b/components/test/data/autofill/automated_integration/autofill_task/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_task/__init__.py
diff --git a/components/test/data/autofill/automated_integration/autofill_task/actions.py b/components/test/data/autofill/automated_integration/autofill_task/actions.py
new file mode 100644
index 0000000..beff03fe
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_task/actions.py
@@ -0,0 +1,405 @@
+# Copyright 2016 The Chromium 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 abc
+import sys
+import traceback
+import time
+
+from selenium.common.exceptions import TimeoutException
+from selenium.webdriver.common.by import By
+from selenium.webdriver.common.keys import Keys
+from selenium.webdriver.common.action_chains import ActionChains
+from selenium.webdriver.support.ui import WebDriverWait, Select as SelectElement
+from selenium.webdriver.support import expected_conditions as EC
+
+
+class _ElementSelector(object):
+  """Base class for all element selectors."""
+  key_type = None
+
+  def __init__(self, key, index=0):
+    """Constructor.
+
+    Args:
+      key: A string which acts as the selector for the element.
+      # index: A selector for which instance of the key should be returned.
+
+    Returns:
+      A webdriver element if found, or None.
+    """
+
+    self._key = key
+    # self._index = index
+
+  def __str__(self):
+    return '\'%s\' by %s' % (self._key, self.key_type)
+
+  def tuple(self):
+    return (self.key_type, self._key)
+
+
+class ByID(_ElementSelector):
+  """Select an element by its id."""
+  key_type = By.ID
+
+
+class ByClassName(_ElementSelector):
+  """Select an element by its class name."""
+  key_type = By.CLASS_NAME
+
+
+class ByCssSelector(_ElementSelector):
+  """Select an element by its class name."""
+  key_type = By.CSS_SELECTOR
+
+
+class ByXPath(_ElementSelector):
+  """Select an element by its xpath."""
+  key_type = By.XPATH
+
+
+class _Action(object):
+  """Base class for all actions."""
+
+  __metaclass__ = abc.ABCMeta
+
+  def Apply(self, driver, test, debug=False):
+    self._debug = debug
+
+    self._dprint('Trying to %s ' % self)
+
+    if self._ignorable:
+      assert_function = test.expect_expression
+    else:
+      assert_function = test.assert_expression
+
+    try:
+      response = self._Apply(driver, test)
+      if response:
+        self._dprint('  Success')
+      else:
+        self._dprint('  Failure')
+      assert_function(response, 'Failed to %s' % self)
+    except TimeoutException:
+      self._dprint('  Failure: TimeoutException')
+      stack = traceback.extract_tb(sys.exc_info()[2])
+      assert_function(False, 'Failed to %s\nTimeoutException' % self, stack)
+
+  def _dprint(self, msg):
+    if self._debug:
+      print(msg)
+
+  @abc.abstractmethod
+  def _Apply(self, driver, test):
+    """The type-specific action execution implementation.
+
+    Note: Subclasses must implement this method.
+
+    Raises:
+      NotImplementedError: Subclass did not implement the method
+    """
+    raise NotImplementedError()
+
+
+class SetContext(_Action):
+  """Sets an element (iframe) as the current driver context.
+
+  If element_selector is None then it will be reset to root.
+  """
+
+  def __init__(self, element_selector, ignorable=False):
+    self._element_selector = element_selector
+    self._ignorable = ignorable
+
+  def __str__(self):
+    if self._element_selector is None:
+      return 'Set context to default'
+    else:
+      return 'Set context to %s' % self._element_selector
+
+  def _Apply(self, driver, test):
+    if self._element_selector is None:
+      driver.switch_to_default_content()
+    else:
+      wt = WebDriverWait(driver, 30) # seconds
+      locator = self._element_selector.tuple()
+      element = wt.until(EC.frame_to_be_available_and_switch_to_it(locator))
+
+    return True
+
+
+class Open(_Action):
+  """Open a URL."""
+
+  def __init__(self, url):
+    self._url = url
+    self._ignorable = False
+
+  def __str__(self):
+    return 'Open %s' % self._url
+
+  def _Apply(self, driver, unused_test):
+    try:
+      driver.get(self._url)
+    except TimeoutException:
+      self._dprint(('  TimeoutException raised when loading %s\n'
+                    '  Proceeding regardless') % (self._url))
+    # Return true regardless as a slow-loading page probably means that there's
+    # an non-critical script
+    return True
+
+
+class Type(_Action):
+  """Type some text into a field."""
+
+  def __init__(self, element_selector, text, ignorable=False):
+    self._element_selector = element_selector
+    self._text = text
+    self._ignorable = ignorable
+
+  def __str__(self):
+    return 'Type \'%s\' into %s' % (self._text, self._element_selector)
+
+  def _Apply(self, driver, test):
+    wt = WebDriverWait(driver, 30) # seconds
+    locator = self._element_selector.tuple()
+    element = wt.until(EC.presence_of_element_located(locator))
+    ActionChains(driver).move_to_element(element).perform()
+    time.sleep(0.1)
+    element = wt.until(EC.element_to_be_clickable(locator))
+    ActionChains(driver).click(element).perform()
+    element.send_keys(self._text)
+    return True
+
+
+class Select(_Action):
+  """Select a value from a select input field."""
+
+  def __init__(self, element_selector, value, ignorable=False, by_label=False):
+    self._element_selector = element_selector
+    self._value = value
+    self._ignorable = ignorable
+    self._by_label = by_label
+
+  def __str__(self):
+    return 'Select \'%s\' from %s%s' % (self._value,
+                                        self._element_selector,
+                                        (' by label' if self._by_label else ''))
+
+  def _Apply(self, driver, test):
+    wt = WebDriverWait(driver, 30)  # seconds
+    locator = self._element_selector.tuple()
+    element = wt.until(EC.presence_of_element_located(locator))
+    ActionChains(driver).move_to_element(element).perform()
+    element = wt.until(EC.element_to_be_clickable(locator))
+    select = SelectElement(element)
+    if self._by_label:
+      select.select_by_visible_text(self._value)
+    else:
+      select.select_by_value(self._value)
+    return True
+
+
+class Wait(_Action):
+  """Wait for a specified number of seconds."""
+
+  def __init__(self, seconds, ignorable=False):
+    self._seconds = seconds
+    self._ignorable = ignorable
+
+  def __str__(self):
+    return 'Wait %d seconds' % self._seconds
+
+  def _Apply(self, driver, test):
+    time.sleep(self._seconds)
+    return True
+
+
+class Screenshot(_Action):
+  """Print a base 64 encoded screenshot to stdout."""
+
+  def __init__(self, filename, ignorable=False):
+    self._filename = filename
+    self._ignorable = ignorable
+
+  def __str__(self):
+    return 'Screenshot'
+
+  def _Apply(self, driver, test):
+    sys.stdout.write(driver.get_screenshot_as_base64())
+    driver.get_screenshot_as_file(self._filename)
+    return True
+
+
+class Click(_Action):
+  """Click on an element."""
+
+  def __init__(self, element_selector, ignorable=False):
+    self._element_selector = element_selector
+    self._ignorable = ignorable
+
+  def __str__(self):
+    return 'Click %s' % self._element_selector
+
+  def _Apply(self, driver, test):
+    wt = WebDriverWait(driver, 10)  # seconds
+    locator = self._element_selector.tuple()
+    element = wt.until(EC.presence_of_element_located(locator))
+    ActionChains(driver).move_to_element(element).perform()
+    wt = WebDriverWait(driver, 10)  # seconds
+    element = wt.until(EC.element_to_be_clickable(locator))
+    element.click()
+    return True
+
+
+class TriggerAutofill(_Action):
+  """Trigger autofill using a form field."""
+
+  def __init__(self, element_selector, expected_type, trigger_character=None,
+               ignorable=False):
+    self._element_selector = element_selector
+    self._expected_type = expected_type
+    self._trigger_character = trigger_character
+    self._ignorable = ignorable
+
+  def __str__(self):
+    return 'Trigger Autofill %s' % self._element_selector
+
+  def _Apply(self, driver, test):
+    expected_value = test.profile_data(self._expected_type)
+    if expected_value != '':
+      if self._trigger_character is None:
+        trigger_character = expected_value[0]
+      else:
+        trigger_character = self._trigger_character
+    else:
+      test.expect_expression(
+          overall_type,
+          'Failure: Cannot trigger autofill, field_type \'%s\' '
+          'does not have an expected value' % self._expected_type)
+      return
+
+    locator = self._element_selector.tuple()
+    wt = WebDriverWait(driver, 15)  # seconds
+    element = wt.until(EC.presence_of_element_located(locator))
+    ActionChains(driver).move_to_element(element).perform()
+    wt = WebDriverWait(driver, 10)  # seconds
+    element = wt.until(EC.element_to_be_clickable(locator))
+    ActionChains(driver).click(element).perform()
+    time.sleep(1)
+    actions = ActionChains(driver)
+    actions.send_keys(trigger_character)
+    actions.perform()
+    time.sleep(0.5)
+    actions = ActionChains(driver)
+    actions.key_down(Keys.ARROW_DOWN)
+    actions.key_down(Keys.ENTER)
+    actions.perform()
+    time.sleep(1)
+
+    return True
+
+
+class ValidateFields(_Action):
+  """Assert that each field has its expected type and has been correctly filled.
+  """
+
+  def __init__(self, field_data_tuples, ignorable=False):
+    self._field_data_tuples = field_data_tuples
+    self._ignorable = ignorable
+
+  def __str__(self):
+    return 'Validate Fields:'
+
+  def _VerifyField(self, driver, test, selector, expected_type,
+                   custom_expected_value=None):
+    try:
+      wt = WebDriverWait(driver, 30)  # seconds
+      element = wt.until(EC.presence_of_element_located(selector.tuple()))
+
+      overall_type = element.get_attribute('autofill-prediction')
+
+      if overall_type is None:
+        test.expect_expression(
+            overall_type,
+            'Failure: Cannot verify field type, autofill-prediction attribute '
+            'not set for \'%s\'' % selector)
+        return
+
+      response = True
+
+      self._dprint('    Checking detected field type')
+      field_type_response = overall_type == expected_type
+      test.expect_expression(field_type_response,
+                             'Field type %s does not match %s' %
+                             (overall_type, expected_type))
+      if field_type_response:
+        self._dprint('      Success')
+      else:
+        response = False
+        self._dprint('      Failure: actual overall_type is %s' % overall_type)
+
+
+      self._dprint('    Checking autofilled data')
+      field_value = element.get_attribute('value')
+
+      if custom_expected_value is None:
+        expected_value = test.profile_data(expected_type)
+        if expected_value == '':
+          test.expect_expression(
+              overall_type,
+              'Failure: Cannot verify field value, expected_type \'%s\' does '
+              'not have an expected value' % expected_type)
+          return
+      else:
+        expected_value = custom_expected_value
+
+      field_value_response = field_value == expected_value
+      test.expect_expression(field_value_response,
+                             'Field value \'%s\' does not match \'%s\'' %
+                             (field_value, expected_value))
+      if field_value_response:
+        self._dprint('      Success')
+      else:
+        response = False
+        self._dprint('      Failure: Actual field value is \'%s\'' %
+                     field_value)
+
+      # The same field type.
+      return response
+    except TimeoutException:
+      test.expect_expression(False,
+                             'Failure: Cannot verify field type, input element '
+                             '\'%s\' unavailable' % selector)
+      return False
+
+  def _Apply(self, driver, test):
+    response = True
+
+    for field_data_tuple in self._field_data_tuples:
+      field_data_size = len(field_data_tuple)
+      if field_data_size == 2:
+        selector, expected_type = field_data_tuple
+        custom_expected_value = None
+      elif field_data_size == 3:
+        selector, expected_type, custom_expected_value = field_data_tuple
+      else:
+        raise ValueError('Field data tuples must have either 2 or 3 elements.')
+
+      self._dprint('  %s: %s' % (expected_type, selector))
+
+      response = self._VerifyField(driver, test, selector, expected_type,
+                                   custom_expected_value)
+
+      if response:
+        self._dprint('    Success')
+      else:
+        response = False
+        self._dprint('    Failure')
+
+    if not self._ignorable:
+      test.assert_expectations();
+
+    return response
diff --git a/components/test/data/autofill/automated_integration/autofill_task/autofill_task.py b/components/test/data/autofill/automated_integration/autofill_task/autofill_task.py
new file mode 100644
index 0000000..24d326b
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_task/autofill_task.py
@@ -0,0 +1,89 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Autofill task automation library.
+"""
+
+import abc
+
+# Local imports
+from .soft_task import SoftTask
+
+
+class AutofillTask(SoftTask):
+  """Extendable autofill task that provides soft/hard assertion functionality.
+
+  The task consists of a script (list of Actions) that are to be executed when
+  run.
+
+  Attributes:
+    profile_data: Dict of profile data that acts as the master source for
+      validating autofill behaviour.
+    debug: Whether debug output should be printed (False if not specified).
+  """
+
+  script = []
+
+  def __init__(self, profile_data, debug=False):
+    super(AutofillTask, self).__init__()
+    self._profile_data = profile_data
+    self._debug = debug
+
+  def __str__(self):
+    return self.__class__.__name__
+
+  @abc.abstractmethod
+  def _create_script(self):
+    """Creates a script (list of Actions) to execute.
+
+    Note: Subclasses must implement this method.
+
+    Raises:
+      NotImplementedError: Subclass did not implement the method.
+    """
+    raise NotImplementedError()
+
+  def set_up(self):
+    """Sets up the task by creating the action script.
+
+    Raises:
+      NotImplementedError: Subclass did not implement _create_script()
+    """
+    self._create_script()
+
+  def tear_down(self):
+    """Tears down the task running environment.
+
+    Any persistent changes made by set_up() must be reversed here.
+    """
+    pass
+
+  def run(self, driver):
+    """Sets up, attempts to execute the task, and always tears down.
+
+    Args:
+      driver: ChromeDriver instance to use for action execution.
+
+    Raises:
+      Exception: Task execution failed.
+    """
+    self._driver = driver
+    super(AutofillTask, self).run()
+
+  def _run_task(self):
+    """Executes the script defined by the subclass.
+
+    Raises:
+      Exception: Script execution failed.
+    """
+    for step in self.script:
+      step.Apply(self._driver, self, self._debug)
+
+    self.assert_expectations()
+
+  def profile_data(self, field):
+    if field in self._profile_data:
+      return self._profile_data[field]
+    else:
+      return ''
diff --git a/components/test/data/autofill/automated_integration/autofill_task/exceptions.py b/components/test/data/autofill/automated_integration/autofill_task/exceptions.py
new file mode 100644
index 0000000..9fa8bbb9
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_task/exceptions.py
@@ -0,0 +1,10 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class ExpectationFailure(Exception):
+  """Represents an unsatisfied expectation.
+  """
+  def __init__(self, *args,**kwargs):
+    super(ExpectationFailure, self).__init__(*args, **kwargs)
diff --git a/components/test/data/autofill/automated_integration/autofill_task/generator.py b/components/test/data/autofill/automated_integration/autofill_task/generator.py
new file mode 100644
index 0000000..73281f4
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_task/generator.py
@@ -0,0 +1,40 @@
+# Copyright 2016 The Chromium 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 random import choice
+from string import ascii_lowercase
+
+
+class Generator(object):
+  """A string generator utility.
+  """
+  def __init__(self):
+    super(Generator, self).__init__()
+
+  @staticmethod
+  def _lower_case_string(length=8):
+    return ''.join(choice(ascii_lowercase) for i in range(length))
+
+  @staticmethod
+  def email():
+    """Generates a fake email address.
+
+    Format: 8 character string at an 8 character .com domain name
+
+    Returns: The generated email address string.
+    """
+    return '%s@%s.com' % (Generator._lower_case_string(),
+                          Generator._lower_case_string())
+
+  @staticmethod
+  def password():
+    """Generates a fake password.
+
+    Format: 8 character lowercase string plus 'A!234&'
+      The postpended string exists to assist in satisfying common "secure
+      password" requirements
+
+    Returns: The generated password string.
+    """
+    return 'A!234&%s' % Generator._lower_case_string()
diff --git a/components/test/data/autofill/automated_integration/autofill_task/soft_task.py b/components/test/data/autofill/automated_integration/autofill_task/soft_task.py
new file mode 100644
index 0000000..304b20b
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_task/soft_task.py
@@ -0,0 +1,182 @@
+# Copyright 2016 The Chromium 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 abc
+import inspect
+import os.path
+import sys
+
+# Local Imports
+from .exceptions import ExpectationFailure
+
+
+class SoftTask(object):
+  """An extendable base task that provides soft/hard assertion functionality.
+  """
+  __metaclass__ = abc.ABCMeta
+
+  def __init__(self):
+    self._failed_expectations = []
+
+  @abc.abstractmethod
+  def set_up(self):
+    """Sets up the task running environment.
+
+    Note: Subclasses must implement this method.
+
+    Raises:
+      NotImplementedError: Subclass did not implement the method
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def tear_down(self):
+    """Tears down the task running environment.
+
+    Any persistent changes made by set_up() must be reversed here.
+    Note: Subclasses must implement this method.
+
+    Raises:
+      NotImplementedError: Subclass did not implement the method
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def _run_task(self):
+    """Executes the task.
+
+    Note: Subclasses must implement this method.
+
+    Raises:
+      NotImplementedError: Subclass did not implement the method
+    """
+    raise NotImplementedError()
+
+  def run(self):
+    """Sets up, attempts to execute the task, and always tears down.
+
+    Raises:
+      ExpectationFailure: Task execution failed. Contains a
+      NotImplementedError: Subclass did not implement the abstract methods
+    """
+    self.set_up()
+    try:
+      self._run_task()
+    finally:
+      # Attempt to tear down despite test failure
+      self.tear_down()
+
+  def expect_expression(self, expr, msg=None, stack=None):
+    """Verifies an expression, logging a failure, but not abort the test.
+
+    In order to ensure that none of the expected expressions have failed, one
+    must call assert_expectations before the end of the test (which will fail
+    it if any expectations were not met).
+    """
+    if not expr:
+      self._log_failure(msg, stack=stack)
+
+  def assert_expression(self, expr, msg=None, stack=None):
+    """Perform a hard assertion but include failures from soft expressions too.
+
+    Raises:
+      ExpectationFailure: This or previous assertions did not pass. Contains a
+        failure report.
+    """
+    if not expr:
+      self._log_failure(msg, stack=stack)
+      if self._failed_expectations:
+        raise ExpectationFailure(self._report_failures())
+
+  def assert_expectations(self):
+    """Raise an assert if there were any failed expectations.
+
+    Raises:
+      ExpectationFailure: An expectation was not met. Contains a failure report.
+    """
+    if self._failed_expectations:
+      raise ExpectationFailure(self._report_failures())
+
+  def _log_failure(self, msg=None, frames=7, skip_frames=0, stack=None):
+    """Generates a failure report from the current traceback.
+
+    The generated failure report is added to an internal list. The reports
+    are used by _report_failures
+
+    Note: Since this is always called internally a minimum of two frames are
+    dropped unless you provide a specific stack trace.
+
+    Args:
+      msg: Description of the failure.
+      frames: The number of frames to include from the call to this function.
+      skip_frames: The number of frames to skip. Useful if you have helper
+        functions that you don't desire to be part of the trace.
+      stack: A custom traceback to use instead of one from this function. No
+        frames will be skipped by default.
+    """
+    if msg:
+      failure_message = msg + '\n'
+    else:
+      failure_message = '\n'
+
+    if stack is None:
+      stack = inspect.stack()[skip_frames + 2:]
+    else:
+      stack = stack[skip_frames:]
+
+    frames_to_use = min(frames, len(stack))
+    stack = stack[:frames_to_use]
+
+    for frame in stack:
+      # First two frames are from logging
+      if len(frame) == 4:
+        # From the traceback module
+        (filename, line, function_name, context) = frame
+        context = '    %s\n' % context
+      else:
+        # Stack trace from the inspect module
+        (filename, line, function_name, context_list) = frame[1:5]
+        context = context_list[0]
+      filename = os.path.basename(filename)
+
+      failure_message += '  File "%s", line %s, in %s()\n%s' % (filename, line,
+                                                                function_name,
+                                                                context)
+
+    self._failed_expectations.append(failure_message)
+
+  def _report_failures(self, frames=1, skip_frames=0):
+    """Generates a failure report for all failed expectations.
+
+    Used in exception descriptions.
+
+    Note: Since this is always called internally a minimum of two frames are
+    dropped.
+
+    Args:
+      frames: The number of frames to include from the call to this function.
+      skip_frames: The number of frames to skip. Useful if you have helper
+        functions that you don't desire to be part of the trace.
+
+    Returns:
+      A string representation of all failed expectations.
+    """
+    if self._failed_expectations:
+      # First two frames are from logging
+      (filename, line, function_name) = inspect.stack()[skip_frames + 2][1:4]
+      filename = os.path.basename(filename)
+
+      report = [
+          'Failed Expectations: %s\n' % len(self._failed_expectations),
+          'assert_expectations() called from',
+          '"%s" line %s, in %s()\n' % (filename, line, function_name)
+      ]
+
+      for i, failure in enumerate(self._failed_expectations, start=1):
+        report.append('Expectation %d: %s' % (i, failure))
+
+      self._failed_expectations = []
+      return '\n'.join(report)
+    else:
+      return ''
diff --git a/components/test/data/autofill/automated_integration/autofill_test/__init__.py b/components/test/data/autofill/automated_integration/autofill_test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_test/__init__.py
diff --git a/components/test/data/autofill/automated_integration/autofill_test/case.py b/components/test/data/autofill/automated_integration/autofill_test/case.py
new file mode 100644
index 0000000..7c77b00e
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_test/case.py
@@ -0,0 +1,47 @@
+# Copyright 2016 The Chromium 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 sys
+import unittest
+
+from selenium.common.exceptions import TimeoutException
+
+# Local Imports
+from autofill_task.exceptions import ExpectationFailure
+from .flow import AutofillTestFlow
+
+class AutofillTestCase(unittest.TestCase):
+  """Wraps a single autofill test flow for use with the unittest library.
+
+    task_class: AutofillTask to use for the test.
+    profile: Dict of profile data that acts as the master source for
+      validating autofill behaviour.
+    debug: Whether debug output should be printed (False if not specified).
+  """
+  def __init__(self, task_class, user_data_dir, profile, chrome_binary=None,
+               debug=False):
+    super(AutofillTestCase, self).__init__('run')
+    self._flow = AutofillTestFlow(task_class, profile, debug=debug)
+    self._user_data_dir = user_data_dir
+    self._chrome_binary = chrome_binary
+    self._debug = debug
+
+  def __str__(self):
+    return str(self._flow)
+
+  def run(self, result):
+    result.startTest(self)
+
+    try:
+      self._flow.run(self._user_data_dir, chrome_binary=self._chrome_binary)
+    except KeyboardInterrupt:
+      raise
+    except (TimeoutException, ExpectationFailure):
+      result.addFailure(self, sys.exc_info())
+    except:
+      result.addError(self, sys.exc_info())
+    else:
+      result.addSuccess(self)
+    finally:
+      result.stopTest(self)
diff --git a/components/test/data/autofill/automated_integration/autofill_test/flow.py b/components/test/data/autofill/automated_integration/autofill_test/flow.py
new file mode 100644
index 0000000..4cb56bde
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_test/flow.py
@@ -0,0 +1,58 @@
+# Copyright 2016 The Chromium 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 Autofill Test Flow
+
+Execute a set of autofill tasks in a fresh ChromeDriver instance that has been
+pre-loaded with some default profile.
+
+Requires:
+  - Selenium python bindings
+    http://selenium-python.readthedocs.org/
+
+  - ChromeDriver
+    https://sites.google.com/a/chromium.org/chromedriver/downloads
+    The ChromeDriver executable must be available on the search PATH.
+
+  - Chrome (>= 53)
+"""
+
+# Local Imports
+from task_flow import TaskFlow
+
+
+class AutofillTestFlow(TaskFlow):
+  """Represents an executable set of Autofill Tasks.
+
+  Note: currently the test flows consist of a single AutofillTask
+
+  Used for automated autofill integration testing.
+
+  Attributes:
+    task_class: AutofillTask to use for the test.
+    profile: Dict of profile data that acts as the master source for
+      validating autofill behaviour.
+    debug: Whether debug output should be printed (False if not specified).
+  """
+  def __init__(self, task_class, profile, debug=False):
+    self._task_class = task_class
+    super(AutofillTestFlow, self).__init__(profile, debug)
+
+  def _generate_task_sequence(self):
+    """Generates a set of executable tasks that will be run in ChromeDriver.
+
+    Returns:
+      A list of AutofillTask instances that are to be run in ChromeDriver.
+
+      These tasks are to be run in order.
+    """
+
+    task = self._task_class(self._profile, self._debug)
+    return [task]
+
+  def __str__(self):
+    if self._tasks:
+      return 'Autofill Test Flow using \'%s\'' % self._tasks[0]
+    else:
+      return 'Empty Autofill Test Flow'
diff --git a/components/test/data/autofill/automated_integration/autofill_test/runner.py b/components/test/data/autofill/automated_integration/autofill_test/runner.py
new file mode 100644
index 0000000..d8a8705
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_test/runner.py
@@ -0,0 +1,44 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+
+class AutofillTestResult(unittest.TextTestResult):
+  """A test result class that can print formatted text results to a stream.
+
+  Used by AutofillTestRunner.
+  """
+
+  def startTest(self, test):
+    """Called when a test is started.
+    """
+    super(unittest.TextTestResult, self).startTest(test)
+    if self.showAll:
+      self.stream.write('Running ')
+      self.stream.write(self.getDescription(test))
+      self.stream.write('\n')
+      self.stream.flush()
+
+  def addFailure(self, test, err):
+    """Logs a test failure as part of the specified test.
+
+    Overloaded to not include the stack trace.
+
+    Args:
+      err: A tuple of values as returned by sys.exc_info().
+    """
+    err = (None, err[1], None)
+    # self.failures.append((test, str(exception)))
+    # self._mirrorOutput = True
+    super(AutofillTestResult, self).addFailure(test, err)
+
+
+class AutofillTestRunner(unittest.TextTestRunner):
+  """An autofill test runner class that displays results in textual form.
+
+  It prints out the names of tests as they are run, errors as they
+  occur, and a summary of the results at the end of the test run.
+  """
+  resultclass = AutofillTestResult
diff --git a/components/test/data/autofill/automated_integration/autofill_test/suite.py b/components/test/data/autofill/automated_integration/autofill_test/suite.py
new file mode 100644
index 0000000..4aad1db3
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/autofill_test/suite.py
@@ -0,0 +1,90 @@
+# Copyright 2016 The Chromium 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 Autofill Test Flow
+
+Execute a set of autofill tasks in a fresh ChromeDriver instance that has been
+pre-loaded with some default profile.
+
+Requires:
+  - Selenium python bindings
+    http://selenium-python.readthedocs.org/
+
+  - ChromeDriver
+    https://sites.google.com/a/chromium.org/chromedriver/downloads
+    The ChromeDriver executable must be available on the search PATH.
+
+  - Chrome
+"""
+
+import importlib
+import unittest
+
+# Local Imports
+from autofill_task.autofill_task import AutofillTask
+from testdata import profile_data
+from .case import AutofillTestCase
+
+
+class AutofillTestSuite(unittest.TestSuite):
+  """Represents an aggregation of individual Autofill test cases.
+
+  Attributes:
+    user_data_dir: Path string for the writable directory in which profiles
+      should be stored.
+    chrome_binary: Path string to the Chrome binary that should be used by
+      ChromeDriver.
+
+      If None then it will use the PATH to find a binary.
+    test_class: Name of the test class that should be run.
+      If this is set, then only the specified class will be executed
+    module: The module to load test cases from. This is relative to the tasks
+      package.
+    profile: Dict of profile data that acts as the master source for
+      validating autofill behaviour. If not specified then default profile data
+      will be used from testdata.profile_data.
+    debug: Whether debug output should be printed (False if not specified).
+  """
+  def __init__(self, user_data_dir, chrome_binary=None, test_class=None,
+               module='sites', profile=None, debug=False):
+    if profile is None:
+      profile = profile_data.DEFAULT
+
+    super(AutofillTestSuite, self).__init__()
+    self._test_class = test_class
+    self._profile = profile
+    self._debug = debug
+
+    module = 'tasks.%s' % module
+
+    try:
+      importlib.import_module(module)
+    except ImportError:
+      print 'Unable to load %s from tasks.' % module
+      raise
+
+    self._generate_tests(user_data_dir, chrome_binary)
+
+  def _generate_tests(self, user_data_dir, chrome_binary=None):
+    task_classes = AutofillTask.__subclasses__()
+    tests = []
+
+    if self._test_class:
+      for task in task_classes:
+        if task.__name__ == self._test_class:
+          test = AutofillTestCase(task, user_data_dir, self._profile,
+                                  chrome_binary=chrome_binary,
+                                  debug=self._debug)
+          self.addTest(test)
+          return
+
+      raise ValueError('Autofill Test \'%s\' could not be found.' %
+                       self._test_class)
+    else:
+      for task in task_classes:
+        tests.append(AutofillTestCase(task, user_data_dir, self._profile,
+                                      chrome_binary=chrome_binary,
+                                      debug=self._debug))
+
+    self.addTests(tests)
diff --git a/components/test/data/autofill/automated_integration/main.py b/components/test/data/autofill/automated_integration/main.py
new file mode 100755
index 0000000..5dd314d
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/main.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Autofill automated integration test runner
+
+Allows you to run integration test(s) for Autofill.
+At this time only a limited set of websites are supported.
+
+Requires:
+  - Selenium python bindings
+    http://selenium-python.readthedocs.org/
+
+  - ChromeDriver
+    https://sites.google.com/a/chromium.org/chromedriver/downloads
+    The ChromeDriver executable must be available on the search PATH.
+
+  - Chrome (>= 53)
+
+  - Write access to '/var/google/autofill/chrome_user_data'
+
+Instructions:
+  - Add tests to tasks/sites.py (or a new module in tasks/)
+  - Run main.py -h to view the available flags.
+    - All tests in tasks/sites.py will be run in the default chrome binary if
+      no flags are specified.
+"""
+
+import argparse
+import types
+import sys
+
+# Local Imports
+from autofill_test.suite import AutofillTestSuite
+from autofill_test.runner import AutofillTestRunner
+
+USER_DATA_DIR = '/var/google/autofill/chrome_user_data'
+
+
+def parse_args():
+  description = 'Allows you to run integration test(s) for Autofill.'
+  epilog = ('All tests in tasks/sites.py will be run in the default chrome '
+            'binary if no flags are specified. At this time only a limited '
+            'set of websites are supported.')
+
+  parser = argparse.ArgumentParser(description=description, epilog=epilog)
+  parser.add_argument('--user-data-dir', dest='user_data_dir', metavar='PATH',
+                      default=USER_DATA_DIR, help='chrome user data directory')
+  parser.add_argument('--chrome-binary', dest='chrome_binary', metavar='PATH',
+                      default=None, help='chrome binary location')
+  parser.add_argument('--module', default='sites', help='task module name')
+  parser.add_argument('--test', dest='test_class',
+                      help='name of a specific test to run')
+  parser.add_argument('-d', '--debug', action='store_true', default=False,
+                      help='print additional information, useful for debugging')
+
+  args = parser.parse_args()
+
+  args.debug = bool(args.debug)
+
+  return args
+
+
+def run(args):
+  if args.debug:
+    print 'Running with arguments: %s' % vars(args)
+
+  try:
+    test_suite = AutofillTestSuite(args.user_data_dir,
+                                   chrome_binary=args.chrome_binary,
+                                   test_class=args.test_class,
+                                   module=args.module, debug=args.debug)
+    verbosity = 2 if args.debug else 1
+    runner = AutofillTestRunner(verbosity=verbosity)
+    runner.run(test_suite)
+  except ImportError as e:
+    print 'Test Execution failed. %s' % str(e)
+  except Exception as e:
+    raise
+
+
+if __name__ == '__main__':
+  args = parse_args()
+  run(args)
diff --git a/components/test/data/autofill/automated_integration/task_flow.py b/components/test/data/autofill/automated_integration/task_flow.py
new file mode 100644
index 0000000..a0e7b31
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/task_flow.py
@@ -0,0 +1,197 @@
+# Copyright 2016 The Chromium 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 Autofill Task Flow
+
+Execute a set of autofill tasks in a fresh ChromeDriver instance that has been
+pre-loaded with some default profile.
+
+Requires:
+  - Selenium python bindings
+    http://selenium-python.readthedocs.org/
+
+  - ChromeDriver
+    https://sites.google.com/a/chromium.org/chromedriver/downloads
+    The ChromeDriver executable must be available on the search PATH.
+
+  - Chrome
+"""
+
+import abc
+from urlparse import urlparse
+import os
+import shutil
+from random import choice
+from string import ascii_lowercase
+
+from selenium import webdriver
+from selenium.common.exceptions import TimeoutException, WebDriverException
+from selenium.webdriver.chrome.options import Options
+
+
+class TaskFlow(object):
+  """Represents an executable set of Autofill Tasks.
+
+  Attributes:
+    profile: Dict of profile data that acts as the master source for
+      validating autofill behaviour.
+    debug: Whether debug output should be printed (False if not specified).
+  """
+  __metaclass__ = abc.ABCMeta
+  def __init__(self, profile, debug=False):
+    self.set_profile(profile)
+    self._debug = debug
+    self._running = False
+
+    self._tasks = self._generate_task_sequence()
+
+  def set_profile(self, profile):
+    """Validates |profile| before assigning it as the source of user data.
+
+    Args:
+      profile: Dict of profile data that acts as the master source for
+        validating autofill behaviour.
+
+    Raises:
+      ValueError: The |profile| dict provided is missing required keys
+    """
+    if not isinstance(profile, dict):
+      raise ValueError('profile must be a a valid dictionary');
+
+    self._profile = profile
+
+  def run(self, user_data_dir, chrome_binary=None):
+    """Generates and executes a sequence of chrome driver tasks.
+
+    Args:
+      user_data_dir: Path string for the writable directory in which profiles
+        should be stored.
+      chrome_binary: Path string to the Chrome binary that should be used by
+        ChromeDriver.
+
+        If None then it will use the PATH to find a binary.
+
+    Raises:
+      RuntimeError: Running the TaskFlow was attempted while it's already
+        running.
+      Exception: Any failure encountered while running the tests
+    """
+    if self._running:
+      raise RuntimeError('Cannot run TaskFlow when already running')
+
+    self._running = True
+
+    self._run_tasks(user_data_dir, chrome_binary=chrome_binary)
+
+    self._running = False
+
+  @abc.abstractmethod
+  def _generate_task_sequence(self):
+    """Generates a set of executable tasks that will be run in ChromeDriver.
+
+    Note: Subclasses must implement this method.
+
+    Raises:
+      NotImplementedError: Subclass did not implement the method
+
+    Returns:
+      A list of AutofillTask instances that are to be run in ChromeDriver.
+
+      These tasks are to be run in order.
+    """
+    raise NotImplementedError()
+
+  def _run_tasks(self, user_data_dir, chrome_binary=None):
+    """Runs the internal set of tasks in a fresh ChromeDriver instance.
+
+    Args:
+      user_data_dir: Path string for the writable directory in which profiles
+        should be stored.
+      chrome_binary: Path string to the Chrome binary that should be used by
+        ChromeDriver.
+
+        If None then it will use the PATH to find a binary.
+
+    Raises:
+      Exception: Any failure encountered while running the tests
+    """
+    driver = self._get_driver(user_data_dir, chrome_binary=chrome_binary)
+    try:
+      for task in self._tasks:
+        task.run(driver)
+    finally:
+      driver.quit()
+      shutil.rmtree(self._profile_dir_dst)
+
+  def _get_driver(self, user_data_dir, profile_name=None, chrome_binary=None,
+                  chromedriver_binary='chromedriver'):
+    """Spin up a ChromeDriver instance that uses a given set of user data.
+
+    Generates a temporary profile data directory using a local set of test data.
+
+    Args:
+      user_data_dir: Path string for the writable directory in which profiles
+        should be stored.
+      profile_name: Name of the profile data directory to be created/used in
+        user_data_dir.
+
+        If None then an eight character name will be generated randomly.
+
+        This directory will be removed after the task flow completes.
+      chrome_binary: Path string to the Chrome binary that should be used by
+        ChromeDriver.
+
+        If None then it will use the PATH to find a binary.
+
+    Returns: The generated Chrome Driver instance.
+    """
+    options = Options()
+
+    if profile_name is None:
+      profile_name = ''.join(choice(ascii_lowercase) for i in range(8))
+
+    options.add_argument('--profile-directory=%s' % profile_name)
+
+    full_path = os.path.realpath(__file__)
+    path, filename = os.path.split(full_path)
+    profile_dir_src = os.path.join(path, 'testdata', 'Default')
+    self._profile_dir_dst = os.path.join(user_data_dir, profile_name)
+    self._copy_tree(profile_dir_src, self._profile_dir_dst)
+
+    if chrome_binary is not None:
+      options.binary_location = chrome_binary
+
+    options.add_argument('--user-data-dir=%s' % user_data_dir)
+    options.add_argument('--show-autofill-type-predictions')
+
+    service_args = []
+
+    driver = webdriver.Chrome(executable_path=chromedriver_binary,
+                              chrome_options=options,
+                              service_args=service_args)
+    driver.set_page_load_timeout(15)  # seconds
+    return driver
+
+  def _copy_tree(self, src, dst):
+    """Recursively copy a directory tree.
+
+    If the destination directory does not exist then it will be created for you.
+    Doesn't overwrite newer existing files.
+
+    Args:
+      src: Path to the target source directory. It must exist.
+      dst: Path to the target destination directory. Permissions to create the
+        the directory (if necessary) and modify it's contents.
+    """
+    if not os.path.exists(dst):
+      os.makedirs(dst)
+    for item in os.listdir(src):
+      src_item = os.path.join(src, item)
+      dst_item = os.path.join(dst, item)
+      if os.path.isdir(src_item):
+        self._copy_tree(src_item, dst_item)
+      elif (not os.path.exists(dst_item) or
+        os.stat(src_item).st_mtime - os.stat(dst_item).st_mtime > 1):
+        # Copy a file if it doesn't already exist, or if existing one is older.
+        shutil.copy2(src_item, dst_item)
diff --git a/components/test/data/autofill/automated_integration/tasks/__init__.py b/components/test/data/autofill/automated_integration/tasks/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/tasks/__init__.py
diff --git a/components/test/data/autofill/automated_integration/tasks/sites.py b/components/test/data/autofill/automated_integration/tasks/sites.py
new file mode 100644
index 0000000..7229bba
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/tasks/sites.py
@@ -0,0 +1,128 @@
+# Copyright 2016 The Chromium 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 autofill_task.autofill_task import AutofillTask
+
+# pylint: disable=g-multiple-import
+# pylint: disable=unused-import
+from autofill_task.actions import (SetContext, Open, Click, Type, Wait, Select,
+                                   ByID, ByClassName, ByCssSelector, Screenshot,
+                                   ByXPath, ValidateFields, TriggerAutofill)
+
+from autofill_task.generator import Generator
+
+
+class TestNeweggComGuestCheckout(AutofillTask):
+  def _create_script(self):
+    self.script = [
+        Open('http://www.newegg.com/Product/Product.aspx?Item=N82E16823126097'),
+        Click(ByXPath('//*[@id="landingpage-cart"]/div/div[2]/button['
+                      'contains(., \'ADD TO CART\')]')),
+        Click(ByXPath('//a[contains(., \'View Shopping Cart\')]'), True),
+        Click(ByXPath('//a[contains(., \'Secure Checkout\')]')),
+        Click(ByXPath('//a[contains(., \'CONTINUE AS A GUEST\')]'), True),
+        TriggerAutofill(ByXPath('//*[@id="SFirstName"]'), 'NAME_FIRST'),
+        ValidateFields([
+            (ByXPath('//*[@id="SFirstName"]'), 'NAME_FIRST'),
+            (ByXPath('//*[@id="SLastName"]'), 'NAME_LAST'),
+            (ByXPath('//*[@id="SAddress1"]'), 'ADDRESS_HOME_LINE1'),
+            (ByXPath('//*[@id="SAddress2"]'), 'ADDRESS_HOME_LINE2'),
+            (ByXPath('//*[@id="SCity"]'), 'ADDRESS_HOME_CITY'),
+            (ByXPath('//*[@id="SState_Option_USA"]'), 'ADDRESS_HOME_STATE',
+             'CA'),
+            (ByXPath('//*[@id="SZip"]'), 'ADDRESS_HOME_ZIP', '94035-____'),
+            (ByXPath('//*[@id="ShippingPhone"]'), 'PHONE_HOME_CITY_AND_NUMBER',
+             '(650) 670-1234 x__________'),
+            (ByXPath('//*[@id="email"]'), 'EMAIL_ADDRESS'),
+        ]),
+    ]
+
+
+class TestGamestopCom(AutofillTask):
+  def _create_script(self):
+    self.script = [
+        Open('http://www.gamestop.com/ps4/consoles/playstation-4-500gb-system-'
+             'white/118544'),
+        # First redirects you to the canadian site if run internationally
+        Open('http://www.gamestop.com/ps4/consoles/playstation-4-500gb-system-'
+             'white/118544'),
+        Click(ByXPath('//*[@id="mainContentPlaceHolder_dynamicContent_ctl00_'
+                      'RepeaterRightColumnLayouts_RightColumnPlaceHolder_0_'
+                      'ctl00_0_ctl00_0_StandardPlaceHolder_2_ctl00_2_'
+                      'rptBuyBoxes_2_lnkAddToCart_0"]')),
+        Click(ByXPath('//*[@id="checkoutButton"]')),
+        Click(ByXPath('//*[@id="cartcheckoutbtn"]')),
+        Click(ByXPath('//*[@id="buyasguest"]')),
+        TriggerAutofill(ByXPath('//*[@id="ShipTo_FirstName"]'), 'NAME_FIRST'),
+        ValidateFields([
+            (ByXPath('//*[@id="ShipTo_CountryCode"]'), 'ADDRESS_HOME_COUNTRY',
+             'US'),
+            (ByXPath('//*[@id="ShipTo_FirstName"]'), 'NAME_FIRST'),
+            (ByXPath('//*[@id="ShipTo_LastName"]'), 'NAME_LAST'),
+            (ByXPath('//*[@id="ShipTo_Line1"]'), 'ADDRESS_HOME_LINE1'),
+            (ByXPath('//*[@id="ShipTo_Line2"]'), 'ADDRESS_HOME_LINE2'),
+            (ByXPath('//*[@id="ShipTo_City"]'), 'ADDRESS_HOME_CITY'),
+            (ByXPath('//*[@id="USStates"]'), 'ADDRESS_HOME_STATE', 'CA'),
+            (ByXPath('//*[@id="ShipTo_PostalCode"]'), 'ADDRESS_HOME_ZIP'),
+            (ByXPath('//*[@id="ShipTo_PhoneNumber"]'),
+             'PHONE_HOME_CITY_AND_NUMBER'),
+            (ByXPath('//*[@id="ShipTo_EmailAddress"]'), 'EMAIL_ADDRESS'),
+        ])
+    ]
+
+
+class TestLowesCom(AutofillTask):
+  def _create_script(self):
+    self.script = [
+        Open('http://www.lowes.com/pd/Weber-Original-Kettle-22-in-Black-'
+             'Porcelain-Enameled-Kettle-Charcoal-Grill/3055249'),
+        Type(ByXPath('//*[@id="zipcode-input"]'),
+             self.profile_data('ADDRESS_HOME_ZIP'), True),
+        Click(ByXPath('//button[contains(., \'Ok\')]'), True),
+        Click(ByXPath('//*[@id="storeList"]/li[1]/div/div[2]/button['
+                      'contains(., \'Shop this store\')]'), True),
+        Wait(3),
+        Click(ByXPath('//button[contains(., \'Add To Cart\')]')),
+        Click(ByXPath('//a[contains(., \'View Cart\')]')),
+        Click(ByXPath('//*[@id="LDshipModeId_1"]')),
+        Click(ByXPath('//*[@id="ShopCartForm"]/div[2]/div[2]/a[contains(.,'
+                      ' \'Start Secure Checkout\')]')),
+        Click(ByXPath('//*[@id="login-container"]/div[2]/div/div/div/a['
+                      'contains(., \'Check Out\')]')),
+        TriggerAutofill(ByXPath('//*[@id="fname"]'), 'NAME_FIRST'),
+        ValidateFields([
+            (ByXPath('//*[@id="fname"]'), 'NAME_FIRST'),
+            (ByXPath('//*[@id="lname"]'), 'NAME_LAST'),
+            (ByXPath('//*[@id="company-name"]'), 'COMPANY_NAME'),
+            (ByXPath('//*[@id="address-1"]'), 'ADDRESS_HOME_LINE1'),
+            (ByXPath('//*[@id="address-2"]'), 'ADDRESS_HOME_LINE2'),
+            (ByXPath('//*[@id="city"]'), 'ADDRESS_HOME_CITY'),
+            (ByXPath('//*[@id="state"]'), 'ADDRESS_HOME_STATE', 'CA'),
+            (ByXPath('//*[@id="zip"]'), 'ADDRESS_HOME_ZIP'),
+        ]),
+        Click(ByXPath('//*[@id="revpay_com_order"]')),
+        Wait(1), # Buttons with the same xPath exists on both pages
+        Click(ByXPath('//*[@id="revpay_com_order"]')),
+        Wait(1), # Buttons with the same xPath exists on both pages
+        TriggerAutofill(ByXPath('//*[@name="cardNumber"]'),
+                        'CREDIT_CARD_NUMBER'),
+        Type(ByXPath('//*[@id="s-code"]'),
+             self.profile_data('CREDIT_CARD_VERIFICATION_CODE')),
+        Type(ByXPath('//*[@id="billing-address-phone1"]'),
+             self.profile_data('PHONE_HOME_CITY_AND_NUMBER')),
+        Type(ByXPath('//*[@id="billingEmailAddress"]'),
+             self.profile_data('EMAIL_ADDRESS')),
+        ValidateFields([
+            (ByXPath('//*[@id="checkout-card-type"]'), 'CREDIT_CARD_TYPE'),
+            (ByXPath('//*[@name="cardNumber"]'), 'CREDIT_CARD_NUMBER'),
+            (ByXPath('//*[@id="s-code"]'), 'CREDIT_CARD_VERIFICATION_CODE'),
+            (ByXPath('//*[@id="expiration-month"]'), 'CREDIT_CARD_EXP_MONTH'),
+            (ByXPath('//*[@id="expiration-year"]'),
+             'CREDIT_CARD_EXP_4_DIGIT_YEAR'),
+            (ByXPath('//*[@id="billing-address-phone1"]'),
+             'PHONE_HOME_CITY_AND_NUMBER', '(650) 670-1234'),
+            (ByXPath('//*[@id="billingEmailAddress"]'), 'EMAIL_ADDRESS'),
+        ]),
+        Click(ByXPath('//*[@id="revpay_com_order"]'))
+    ]
diff --git a/components/test/data/autofill/automated_integration/testdata/Default/Preferences b/components/test/data/autofill/automated_integration/testdata/Default/Preferences
new file mode 100644
index 0000000..9956a29
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/testdata/Default/Preferences
@@ -0,0 +1 @@
+{"autofill":{"profile_use_dates_fixed":true}}
diff --git a/components/test/data/autofill/automated_integration/testdata/Default/Web Data b/components/test/data/autofill/automated_integration/testdata/Default/Web Data
new file mode 100644
index 0000000..c411920
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/testdata/Default/Web Data
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/testdata/README b/components/test/data/autofill/automated_integration/testdata/README
new file mode 100644
index 0000000..069f514
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/testdata/README
@@ -0,0 +1,2 @@
+This data is used to populate the generated user data directory with just enough
+files to add a functioning autofill profile.
diff --git a/components/test/data/autofill/automated_integration/testdata/__init__.py b/components/test/data/autofill/automated_integration/testdata/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/testdata/__init__.py
diff --git a/components/test/data/autofill/automated_integration/testdata/profile_data.py b/components/test/data/autofill/automated_integration/testdata/profile_data.py
new file mode 100644
index 0000000..83cd600
--- /dev/null
+++ b/components/test/data/autofill/automated_integration/testdata/profile_data.py
@@ -0,0 +1,75 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Autofill expected data by field type. This matches the default profile.
+"""
+
+DEFAULT = {
+    # Personal Information categorization types.
+    'NAME_FIRST': 'Donald',
+    'NAME_MIDDLE': 'Craig',
+    'NAME_LAST': 'Figgleburg',
+    'NAME_MIDDLE_INITIAL': 'C',
+    'NAME_FULL': 'Donald Craig Figgleburg',
+    'NAME_SUFFIX': '',
+    'EMAIL_ADDRESS': 'donald@figgleburg.com',
+    'PHONE_HOME_NUMBER': '6701234',
+    'PHONE_HOME_CITY_CODE': '650',
+    'PHONE_HOME_COUNTRY_CODE': '+1',
+    'PHONE_HOME_CITY_AND_NUMBER': '6506701234',
+    'PHONE_HOME_WHOLE_NUMBER': '+16506701234',
+    'ADDRESS_HOME_LINE1': '314 Oceanwalk Rd.',
+    'ADDRESS_HOME_LINE2': 'Apt. 4',
+    'ADDRESS_HOME_APPT_NUM': '4',
+    'ADDRESS_HOME_CITY': 'Mountain View',
+    'ADDRESS_HOME_STATE': 'California',
+    'ADDRESS_HOME_ZIP': '94035',
+    'ADDRESS_HOME_COUNTRY': 'United States',
+    'ADDRESS_BILLING_LINE1': '314 Oceanwalk Rd.',
+    'ADDRESS_BILLING_LINE2': 'Apt. 4',
+    'ADDRESS_BILLING_APPT_NUM': '4',
+    'ADDRESS_BILLING_CITY': 'Mountain View',
+    'ADDRESS_BILLING_STATE': 'California',
+    'ADDRESS_BILLING_ZIP': '94035',
+    'ADDRESS_BILLING_COUNTRY': 'United States',
+    'CREDIT_CARD_NAME': 'Donald Figgleburg',
+    'CREDIT_CARD_NUMBER': '5432123498764567',
+    'CREDIT_CARD_EXP_MONTH': '05',
+    'CREDIT_CARD_EXP_2_DIGIT_YEAR': '21',
+    'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2021',
+    'CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR': '05/21',
+    'CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR': '05/2021',
+    'CREDIT_CARD_TYPE': '',
+    'CREDIT_CARD_VERIFICATION_CODE': '',
+    'COMPANY_NAME': 'Frtizerg Inc.',
+
+    # Generic fieldtype having default value to use, used only by autocheckout
+    # experiment. These field types exist for select merchant pages. Field
+    # mappings for these pages are generated by autocheckout's buildstorage
+    # script.
+    'FIELD_WITH_DEFAULT_VALUE': '',
+    'PHONE_BILLING_NUMBER': '',
+    'PHONE_BILLING_CITY_CODE': '',
+    'PHONE_BILLING_COUNTRY_CODE': '',
+    'PHONE_BILLING_CITY_AND_NUMBER': '',
+    'PHONE_BILLING_WHOLE_NUMBER': '',
+    'NAME_BILLING_FIRST': '',
+    'NAME_BILLING_MIDDLE': '',
+    'NAME_BILLING_LAST': '',
+    'NAME_BILLING_MIDDLE_INITIAL': '',
+    'NAME_BILLING_FULL': '',
+    'NAME_BILLING_SUFFIX': '',
+
+    # Includes of the lines of a street address, including newlines, e.g.
+    #   123 Main Street,
+    #   Apt. #42
+    'ADDRESS_HOME_STREET_ADDRESS': '314 Oceanwalk Rd.\nApt. 4',
+    'ADDRESS_BILLING_STREET_ADDRESS': '314 Oceanwalk Rd.\nApt. 4',
+
+    'ACCOUNT_CREATION_PASSWORD': '',
+
+    # The third line of the street address.
+    'ADDRESS_HOME_LINE3': '',
+    'ADDRESS_BILLING_LINE3': ''
+}
diff --git a/components/test_runner/BUILD.gn b/components/test_runner/BUILD.gn
index 3696199..6b2bad0 100644
--- a/components/test_runner/BUILD.gn
+++ b/components/test_runner/BUILD.gn
@@ -94,11 +94,11 @@
     "web_test_delegate.h",
     "web_test_interfaces.cc",
     "web_test_interfaces.h",
-    "web_test_proxy.cc",
-    "web_test_proxy.h",
     "web_test_runner.h",
     "web_view_test_client.cc",
     "web_view_test_client.h",
+    "web_view_test_proxy.cc",
+    "web_view_test_proxy.h",
     "web_widget_test_client.cc",
     "web_widget_test_client.h",
   ]
diff --git a/components/test_runner/accessibility_controller.cc b/components/test_runner/accessibility_controller.cc
index 005100c..84bf61a 100644
--- a/components/test_runner/accessibility_controller.cc
+++ b/components/test_runner/accessibility_controller.cc
@@ -5,7 +5,7 @@
 #include "components/test_runner/accessibility_controller.h"
 
 #include "base/macros.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "gin/handle.h"
 #include "gin/object_template_builder.h"
 #include "gin/wrappable.h"
@@ -136,9 +136,9 @@
 }
 
 AccessibilityController::AccessibilityController(
-    WebTestProxyBase* web_test_proxy_base)
+    WebViewTestProxyBase* web_view_test_proxy_base)
     : log_accessibility_events_(false),
-      web_test_proxy_base_(web_test_proxy_base),
+      web_view_test_proxy_base_(web_view_test_proxy_base),
       weak_factory_(this) {}
 
 AccessibilityController::~AccessibilityController() {}
@@ -270,7 +270,7 @@
 }
 
 blink::WebView* AccessibilityController::web_view() {
-  return web_test_proxy_base_->web_view();
+  return web_view_test_proxy_base_->web_view();
 }
 
 }  // namespace test_runner
diff --git a/components/test_runner/accessibility_controller.h b/components/test_runner/accessibility_controller.h
index 82618fc2..2864b4d 100644
--- a/components/test_runner/accessibility_controller.h
+++ b/components/test_runner/accessibility_controller.h
@@ -21,11 +21,12 @@
 
 namespace test_runner {
 
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 class AccessibilityController {
  public:
-  explicit AccessibilityController(WebTestProxyBase* web_test_proxy_base);
+  explicit AccessibilityController(
+      WebViewTestProxyBase* web_view_test_proxy_base);
   ~AccessibilityController();
 
   void Reset();
@@ -56,7 +57,7 @@
   v8::Persistent<v8::Function> notification_callback_;
 
   blink::WebView* web_view();
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
 
   base::WeakPtrFactory<AccessibilityController> weak_factory_;
 
diff --git a/components/test_runner/event_sender.cc b/components/test_runner/event_sender.cc
index 3a4b797..be28ef80 100644
--- a/components/test_runner/event_sender.cc
+++ b/components/test_runner/event_sender.cc
@@ -20,7 +20,7 @@
 #include "components/test_runner/test_interfaces.h"
 #include "components/test_runner/web_task.h"
 #include "components/test_runner/web_test_delegate.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "gin/handle.h"
 #include "gin/object_template_builder.h"
 #include "gin/wrappable.h"
@@ -1274,8 +1274,8 @@
       milliseconds(0),
       modifiers(0) {}
 
-EventSender::EventSender(WebTestProxyBase* web_test_proxy_base)
-    : web_test_proxy_base_(web_test_proxy_base),
+EventSender::EventSender(WebViewTestProxyBase* web_view_test_proxy_base)
+    : web_view_test_proxy_base_(web_view_test_proxy_base),
       replaying_saved_events_(false),
       weak_factory_(this) {
   Reset();
@@ -1780,7 +1780,7 @@
 }
 
 void EventSender::ZoomPageIn() {
-  const std::vector<WebTestProxyBase*>& window_list =
+  const std::vector<WebViewTestProxyBase*>& window_list =
       interfaces()->GetWindowList();
 
   for (size_t i = 0; i < window_list.size(); ++i) {
@@ -1790,7 +1790,7 @@
 }
 
 void EventSender::ZoomPageOut() {
-  const std::vector<WebTestProxyBase*>& window_list =
+  const std::vector<WebViewTestProxyBase*>& window_list =
       interfaces()->GetWindowList();
 
   for (size_t i = 0; i < window_list.size(); ++i) {
@@ -1800,7 +1800,7 @@
 }
 
 void EventSender::SetPageZoomFactor(double zoom_factor) {
-  const std::vector<WebTestProxyBase*>& window_list =
+  const std::vector<WebViewTestProxyBase*>& window_list =
       interfaces()->GetWindowList();
 
   for (size_t i = 0; i < window_list.size(); ++i) {
@@ -1923,6 +1923,14 @@
     return;
   }
 
+  float max_start_velocity = std::max(fabs(velocity_x), fabs(velocity_y));
+  if (!max_start_velocity) {
+    v8::Isolate* isolate = blink::mainThreadIsolate();
+    isolate->ThrowException(v8::Exception::TypeError(
+      gin::StringToV8(isolate, "Invalid max start velocity.")));
+    return;
+  }
+
   event.x = x;
   event.y = y;
   event.globalX = event.x;
@@ -2241,7 +2249,7 @@
   uint32_t unique_touch_event_id;
   GetOptionalTouchArgs(args, moved_beyond_slop_region, unique_touch_event_id);
 
-  DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
+  DCHECK_GT(static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap),
             touch_points_.size());
   if (force_layout_on_events_)
     view()->updateAllLifecyclePhases();
@@ -2840,19 +2848,19 @@
 }
 
 TestInterfaces* EventSender::interfaces() {
-  return web_test_proxy_base_->test_interfaces();
+  return web_view_test_proxy_base_->test_interfaces();
 }
 
 WebTestDelegate* EventSender::delegate() {
-  return web_test_proxy_base_->delegate();
+  return web_view_test_proxy_base_->delegate();
 }
 
 const blink::WebView* EventSender::view() const {
-  return web_test_proxy_base_->web_view();
+  return web_view_test_proxy_base_->web_view();
 }
 
 blink::WebView* EventSender::view() {
-  return web_test_proxy_base_->web_view();
+  return web_view_test_proxy_base_->web_view();
 }
 
 std::unique_ptr<WebInputEvent> EventSender::ScaleEvent(
diff --git a/components/test_runner/event_sender.h b/components/test_runner/event_sender.h
index 4f77fcf4..408c5450 100644
--- a/components/test_runner/event_sender.h
+++ b/components/test_runner/event_sender.h
@@ -18,10 +18,10 @@
 #include "build/build_config.h"
 #include "third_party/WebKit/public/platform/WebDragData.h"
 #include "third_party/WebKit/public/platform/WebDragOperation.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEventResult.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebTouchPoint.h"
+#include "third_party/WebKit/public/platform/WebTouchPoint.h"
 
 namespace blink {
 class WebLocalFrame;
@@ -37,7 +37,7 @@
 
 class TestInterfaces;
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 // Key event location code introduced in DOM Level 3.
 // See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
@@ -50,7 +50,7 @@
 
 class EventSender {
  public:
-  explicit EventSender(WebTestProxyBase*);
+  explicit EventSender(WebViewTestProxyBase*);
   virtual ~EventSender();
 
   void Reset();
@@ -257,7 +257,7 @@
   int wm_sys_dead_char_;
 #endif
 
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
   TestInterfaces* interfaces();
   WebTestDelegate* delegate();
   const blink::WebView* view() const;
diff --git a/components/test_runner/pixel_dump.cc b/components/test_runner/pixel_dump.cc
index 2b2abfbf..de2316a 100644
--- a/components/test_runner/pixel_dump.cc
+++ b/components/test_runner/pixel_dump.cc
@@ -150,7 +150,7 @@
                      const LayoutTestRuntimeFlags& layout_test_runtime_flags,
                      float device_scale_factor_for_test,
                      const base::Callback<void(const SkBitmap&)>& callback) {
-  TRACE_EVENT0("shell", "WebTestProxyBase::CapturePixelsAsync");
+  TRACE_EVENT0("shell", "WebViewTestProxyBase::CapturePixelsAsync");
   DCHECK(!callback.is_null());
   DCHECK(!layout_test_runtime_flags.dump_drag_image());
 
diff --git a/components/test_runner/test_interfaces.cc b/components/test_runner/test_interfaces.cc
index 3b2d7c3..d2829325 100644
--- a/components/test_runner/test_interfaces.cc
+++ b/components/test_runner/test_interfaces.cc
@@ -18,7 +18,7 @@
 #include "components/test_runner/gc_controller.h"
 #include "components/test_runner/test_runner.h"
 #include "components/test_runner/text_input_controller.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebCache.h"
 #include "third_party/WebKit/public/web/WebKit.h"
@@ -69,8 +69,8 @@
     gamepad_controller_->Reset();
   blink::WebCache::clear();
 
-  for (WebTestProxyBase* web_test_proxy_base : window_list_)
-    web_test_proxy_base->Reset();
+  for (WebViewTestProxyBase* web_view_test_proxy_base : window_list_)
+    web_view_test_proxy_base->Reset();
 }
 
 void TestInterfaces::ResetAll() {
@@ -121,12 +121,12 @@
   app_banner_client_ = app_banner_client;
 }
 
-void TestInterfaces::WindowOpened(WebTestProxyBase* proxy) {
+void TestInterfaces::WindowOpened(WebViewTestProxyBase* proxy) {
   window_list_.push_back(proxy);
 }
 
-void TestInterfaces::WindowClosed(WebTestProxyBase* proxy) {
-  std::vector<WebTestProxyBase*>::iterator pos =
+void TestInterfaces::WindowClosed(WebViewTestProxyBase* proxy) {
+  std::vector<WebViewTestProxyBase*>::iterator pos =
       std::find(window_list_.begin(), window_list_.end(), proxy);
   if (pos == window_list_.end()) {
     NOTREACHED();
@@ -146,7 +146,7 @@
   return delegate_;
 }
 
-const std::vector<WebTestProxyBase*>& TestInterfaces::GetWindowList() {
+const std::vector<WebViewTestProxyBase*>& TestInterfaces::GetWindowList() {
   return window_list_;
 }
 
diff --git a/components/test_runner/test_interfaces.h b/components/test_runner/test_interfaces.h
index ff7fb48..b12bf869 100644
--- a/components/test_runner/test_interfaces.h
+++ b/components/test_runner/test_interfaces.h
@@ -26,7 +26,7 @@
 class GamepadController;
 class TestRunner;
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 class TestInterfaces {
  public:
@@ -43,12 +43,12 @@
                                bool generate_pixels);
   void SetAppBannerClient(AppBannerClient* app_banner_client);
 
-  void WindowOpened(WebTestProxyBase* proxy);
-  void WindowClosed(WebTestProxyBase* proxy);
+  void WindowOpened(WebViewTestProxyBase* proxy);
+  void WindowClosed(WebViewTestProxyBase* proxy);
 
   TestRunner* GetTestRunner();
   WebTestDelegate* GetDelegate();
-  const std::vector<WebTestProxyBase*>& GetWindowList();
+  const std::vector<WebViewTestProxyBase*>& GetWindowList();
   blink::WebThemeEngine* GetThemeEngine();
   AppBannerClient* GetAppBannerClient();
 
@@ -58,7 +58,7 @@
   WebTestDelegate* delegate_;
   AppBannerClient* app_banner_client_;
 
-  std::vector<WebTestProxyBase*> window_list_;
+  std::vector<WebViewTestProxyBase*> window_list_;
   blink::WebView* main_view_;
 
   std::unique_ptr<MockWebThemeEngine> theme_engine_;
diff --git a/components/test_runner/test_plugin.cc b/components/test_runner/test_plugin.cc
index 64275a5..7fb88ea 100644
--- a/components/test_runner/test_plugin.cc
+++ b/components/test_runner/test_plugin.cc
@@ -22,15 +22,15 @@
 #include "third_party/WebKit/public/platform/Platform.h"
 #include "third_party/WebKit/public/platform/WebCompositorSupport.h"
 #include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h"
+#include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "third_party/WebKit/public/platform/WebTaskRunner.h"
 #include "third_party/WebKit/public/platform/WebThread.h"
+#include "third_party/WebKit/public/platform/WebTouchPoint.h"
 #include "third_party/WebKit/public/platform/WebTraceLocation.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "third_party/WebKit/public/web/WebKit.h"
 #include "third_party/WebKit/public/web/WebPluginParams.h"
-#include "third_party/WebKit/public/web/WebTouchPoint.h"
 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
diff --git a/components/test_runner/test_runner.cc b/components/test_runner/test_runner.cc
index a410ad4..cf41203f 100644
--- a/components/test_runner/test_runner.cc
+++ b/components/test_runner/test_runner.cc
@@ -31,7 +31,7 @@
 #include "components/test_runner/test_runner_for_specific_view.h"
 #include "components/test_runner/web_task.h"
 #include "components/test_runner/web_test_delegate.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "gin/arguments.h"
 #include "gin/array_buffer.h"
 #include "gin/handle.h"
@@ -2228,7 +2228,7 @@
     orientation = WebScreenOrientationLandscapeSecondary;
   }
 
-  for (WebTestProxyBase* window : test_interfaces_->GetWindowList()) {
+  for (WebViewTestProxyBase* window : test_interfaces_->GetWindowList()) {
     WebFrame* main_frame = window->web_view()->mainFrame();
     // TODO(lukasza): Need to make this work for remote frames.
     if (main_frame->isWebLocalFrame()) {
@@ -2341,7 +2341,7 @@
   layout_test_runtime_flags_.set_accept_languages(accept_languages);
   OnLayoutTestRuntimeFlagsChanged();
 
-  for (WebTestProxyBase* window : test_interfaces_->GetWindowList())
+  for (WebViewTestProxyBase* window : test_interfaces_->GetWindowList())
     window->web_view()->acceptLanguagesChanged();
 }
 
diff --git a/components/test_runner/test_runner.gyp b/components/test_runner/test_runner.gyp
index cc3f598..b99001d 100644
--- a/components/test_runner/test_runner.gyp
+++ b/components/test_runner/test_runner.gyp
@@ -123,11 +123,11 @@
         'web_test_delegate.h',
         'web_test_interfaces.cc',
         'web_test_interfaces.h',
-        'web_test_proxy.cc',
-        'web_test_proxy.h',
         'web_test_runner.h',
         'web_view_test_client.cc',
         'web_view_test_client.h',
+        'web_view_test_proxy.cc',
+        'web_view_test_proxy.h',
         'web_widget_test_client.cc',
         'web_widget_test_client.h',
       ],
diff --git a/components/test_runner/test_runner.h b/components/test_runner/test_runner.h
index d9e1a1ca6..69b2ea5f 100644
--- a/components/test_runner/test_runner.h
+++ b/components/test_runner/test_runner.h
@@ -459,7 +459,7 @@
   // results will be the drag image instead of a snapshot of the page.
   void DumpDragImage();
 
-  // Sets a flag that tells the WebTestProxy to dump the default navigation
+  // Sets a flag that tells the WebViewTestProxy to dump the default navigation
   // policy passed to the decidePolicyForNavigation callback.
   void DumpNavigationPolicy();
 
@@ -468,7 +468,7 @@
   void SetDumpConsoleMessages(bool value);
 
   ///////////////////////////////////////////////////////////////////////////
-  // Methods interacting with the WebTestProxy
+  // Methods interacting with the WebViewTestProxy
 
   ///////////////////////////////////////////////////////////////////////////
   // Methods forwarding to the WebTestDelegate
diff --git a/components/test_runner/test_runner_for_specific_view.cc b/components/test_runner/test_runner_for_specific_view.cc
index 84e81db..77957c2 100644
--- a/components/test_runner/test_runner_for_specific_view.cc
+++ b/components/test_runner/test_runner_for_specific_view.cc
@@ -30,7 +30,7 @@
 #include "components/test_runner/test_runner.h"
 #include "components/test_runner/web_task.h"
 #include "components/test_runner/web_test_delegate.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "gin/arguments.h"
 #include "gin/array_buffer.h"
 #include "gin/handle.h"
@@ -78,15 +78,15 @@
 namespace test_runner {
 
 TestRunnerForSpecificView::TestRunnerForSpecificView(
-    WebTestProxyBase* web_test_proxy_base)
-    : web_test_proxy_base_(web_test_proxy_base), weak_factory_(this) {
+    WebViewTestProxyBase* web_view_test_proxy_base)
+    : web_view_test_proxy_base_(web_view_test_proxy_base), weak_factory_(this) {
   Reset();
 }
 
 TestRunnerForSpecificView::~TestRunnerForSpecificView() {}
 
 void TestRunnerForSpecificView::Install(blink::WebLocalFrame* frame) {
-  web_test_proxy_base_->test_interfaces()->GetTestRunner()->Install(
+  web_view_test_proxy_base_->test_interfaces()->GetTestRunner()->Install(
       frame, weak_factory_.GetWeakPtr());
 }
 
@@ -235,10 +235,13 @@
   v8::UniquePersistent<v8::Function> persistent_callback(
       blink::mainThreadIsolate(), callback);
 
-  web_test_proxy_base_->test_interfaces()->GetTestRunner()->DumpPixelsAsync(
-      web_view(), base::Bind(&TestRunnerForSpecificView::CapturePixelsCallback,
-                             weak_factory_.GetWeakPtr(),
-                             base::Passed(std::move(persistent_callback))));
+  web_view_test_proxy_base_->test_interfaces()
+      ->GetTestRunner()
+      ->DumpPixelsAsync(
+          web_view(),
+          base::Bind(&TestRunnerForSpecificView::CapturePixelsCallback,
+                     weak_factory_.GetWeakPtr(),
+                     base::Passed(std::move(persistent_callback))));
 }
 
 void TestRunnerForSpecificView::CapturePixelsCallback(
@@ -527,8 +530,8 @@
 }
 
 void TestRunnerForSpecificView::SetWindowIsKey(bool value) {
-  web_test_proxy_base_->test_interfaces()->GetTestRunner()->SetFocus(web_view(),
-                                                                     value);
+  web_view_test_proxy_base_->test_interfaces()->GetTestRunner()->SetFocus(
+      web_view(), value);
 }
 
 void TestRunnerForSpecificView::DidAcquirePointerLock() {
@@ -690,11 +693,11 @@
 }
 
 blink::WebView* TestRunnerForSpecificView::web_view() {
-  return web_test_proxy_base_->web_view();
+  return web_view_test_proxy_base_->web_view();
 }
 
 WebTestDelegate* TestRunnerForSpecificView::delegate() {
-  return web_test_proxy_base_->delegate();
+  return web_view_test_proxy_base_->delegate();
 }
 
 }  // namespace test_runner
diff --git a/components/test_runner/test_runner_for_specific_view.h b/components/test_runner/test_runner_for_specific_view.h
index e0c6d5e..003d5d9 100644
--- a/components/test_runner/test_runner_for_specific_view.h
+++ b/components/test_runner/test_runner_for_specific_view.h
@@ -31,7 +31,7 @@
 namespace test_runner {
 
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 // TestRunnerForSpecificView implements part of |testRunner| javascript bindings
 // that work with a view where the javascript call originated from.  Examples:
@@ -40,7 +40,8 @@
 // Note that "global" bindings are handled by TestRunner class.
 class TestRunnerForSpecificView {
  public:
-  explicit TestRunnerForSpecificView(WebTestProxyBase* web_test_proxy_base);
+  explicit TestRunnerForSpecificView(
+      WebViewTestProxyBase* web_view_test_proxy_base);
   ~TestRunnerForSpecificView();
 
   // Installs view-specific bindings (handled by |this|) and *also* global
@@ -216,10 +217,10 @@
   std::string SelectionAsMarkup();
   void SetViewSourceForFrame(const std::string& name, bool enabled);
 
-  // Helpers for accessing pointers exposed by |web_test_proxy_base_|.
+  // Helpers for accessing pointers exposed by |web_view_test_proxy_base_|.
   blink::WebView* web_view();
   WebTestDelegate* delegate();
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
 
   base::WeakPtrFactory<TestRunnerForSpecificView> weak_factory_;
 
diff --git a/components/test_runner/text_input_controller.cc b/components/test_runner/text_input_controller.cc
index a10d849..788570b 100644
--- a/components/test_runner/text_input_controller.cc
+++ b/components/test_runner/text_input_controller.cc
@@ -5,7 +5,7 @@
 #include "components/test_runner/text_input_controller.h"
 
 #include "base/macros.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "gin/arguments.h"
 #include "gin/handle.h"
 #include "gin/object_template_builder.h"
@@ -148,8 +148,10 @@
 
 // TextInputController ---------------------------------------------------------
 
-TextInputController::TextInputController(WebTestProxyBase* web_test_proxy_base)
-    : web_test_proxy_base_(web_test_proxy_base), weak_factory_(this) {}
+TextInputController::TextInputController(
+    WebViewTestProxyBase* web_view_test_proxy_base)
+    : web_view_test_proxy_base_(web_view_test_proxy_base),
+      weak_factory_(this) {}
 
 TextInputController::~TextInputController() {}
 
@@ -292,7 +294,7 @@
 }
 
 blink::WebView* TextInputController::view() {
-  return web_test_proxy_base_->web_view();
+  return web_view_test_proxy_base_->web_view();
 }
 
 }  // namespace test_runner
diff --git a/components/test_runner/text_input_controller.h b/components/test_runner/text_input_controller.h
index f7fa367..d7d2958 100644
--- a/components/test_runner/text_input_controller.h
+++ b/components/test_runner/text_input_controller.h
@@ -18,14 +18,14 @@
 
 namespace test_runner {
 
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 // TextInputController is bound to window.textInputController in Javascript
 // when content_shell is running. Layout tests use it to exercise various
 // corners of text input.
 class TextInputController {
  public:
-  explicit TextInputController(WebTestProxyBase* web_test_proxy_base);
+  explicit TextInputController(WebViewTestProxyBase* web_view_test_proxy_base);
   ~TextInputController();
 
   void Install(blink::WebLocalFrame* frame);
@@ -45,7 +45,7 @@
   void SetComposition(const std::string& text);
 
   blink::WebView* view();
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
 
   base::WeakPtrFactory<TextInputController> weak_factory_;
 
diff --git a/components/test_runner/web_frame_test_client.cc b/components/test_runner/web_frame_test_client.cc
index d5eccbf..df4b4b72 100644
--- a/components/test_runner/web_frame_test_client.cc
+++ b/components/test_runner/web_frame_test_client.cc
@@ -21,7 +21,7 @@
 #include "components/test_runner/test_runner.h"
 #include "components/test_runner/web_frame_test_proxy.h"
 #include "components/test_runner/web_test_delegate.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
@@ -186,15 +186,15 @@
 WebFrameTestClient::WebFrameTestClient(
     TestRunner* test_runner,
     WebTestDelegate* delegate,
-    WebTestProxyBase* web_test_proxy_base,
+    WebViewTestProxyBase* web_view_test_proxy_base,
     WebFrameTestProxyBase* web_frame_test_proxy_base)
     : test_runner_(test_runner),
       delegate_(delegate),
-      web_test_proxy_base_(web_test_proxy_base),
+      web_view_test_proxy_base_(web_view_test_proxy_base),
       web_frame_test_proxy_base_(web_frame_test_proxy_base) {
   DCHECK(test_runner);
   DCHECK(delegate_);
-  DCHECK(web_test_proxy_base_);
+  DCHECK(web_view_test_proxy_base_);
 }
 
 WebFrameTestClient::~WebFrameTestClient() {}
@@ -354,7 +354,7 @@
   }
 
   AccessibilityController* accessibility_controller =
-      web_test_proxy_base_->accessibility_controller();
+      web_view_test_proxy_base_->accessibility_controller();
   accessibility_controller->NotificationReceived(obj, event_name);
   if (accessibility_controller->ShouldLogAccessibilityEvents()) {
     std::string message("AccessibilityNotification - ");
@@ -390,7 +390,8 @@
 
 void WebFrameTestClient::showContextMenu(
     const blink::WebContextMenuData& context_menu_data) {
-  web_test_proxy_base_->event_sender()->SetContextMenuData(context_menu_data);
+  web_view_test_proxy_base_->event_sender()->SetContextMenuData(
+      context_menu_data);
 }
 
 blink::WebUserMediaClient* WebFrameTestClient::userMediaClient() {
@@ -748,8 +749,8 @@
 }
 
 void WebFrameTestClient::didClearWindowObject(blink::WebLocalFrame* frame) {
-  web_test_proxy_base_->test_interfaces()->BindTo(frame);
-  web_test_proxy_base_->BindTo(frame);
+  web_view_test_proxy_base_->test_interfaces()->BindTo(frame);
+  web_view_test_proxy_base_->BindTo(frame);
 }
 
 bool WebFrameTestClient::runFileChooser(
diff --git a/components/test_runner/web_frame_test_client.h b/components/test_runner/web_frame_test_client.h
index ed81b72..4bc8e405 100644
--- a/components/test_runner/web_frame_test_client.h
+++ b/components/test_runner/web_frame_test_client.h
@@ -17,7 +17,7 @@
 class TestRunner;
 class WebFrameTestProxyBase;
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 // WebFrameTestClient implements WebFrameClient interface, providing behavior
 // expected by tests.  WebFrameTestClient ends up used by WebFrameTestProxy
@@ -29,7 +29,7 @@
   // forth) live longer than |this|.
   WebFrameTestClient(TestRunner* test_runner,
                      WebTestDelegate* delegate,
-                     WebTestProxyBase* web_test_proxy_base,
+                     WebViewTestProxyBase* web_view_test_proxy_base,
                      WebFrameTestProxyBase* web_frame_test_proxy_base);
 
   ~WebFrameTestClient() override;
@@ -113,7 +113,7 @@
   // Borrowed pointers to other parts of Layout Tests state.
   TestRunner* test_runner_;
   WebTestDelegate* delegate_;
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
   WebFrameTestProxyBase* web_frame_test_proxy_base_;
 
   // Map from request identifier into resource url description.  The map is used
diff --git a/components/test_runner/web_frame_test_proxy.h b/components/test_runner/web_frame_test_proxy.h
index 21bd773..82a193c 100644
--- a/components/test_runner/web_frame_test_proxy.h
+++ b/components/test_runner/web_frame_test_proxy.h
@@ -45,9 +45,9 @@
   DISALLOW_COPY_AND_ASSIGN(WebFrameTestProxyBase);
 };
 
-// WebTestProxy is used during LayoutTests and always instantiated, at time of
-// writing with Base=RenderFrameImpl. It does not directly inherit from it for
-// layering purposes.
+// WebFrameTestProxy is used during LayoutTests and always instantiated, at time
+// of writing with Base=RenderFrameImpl. It does not directly inherit from it
+// for layering purposes.
 template <class Base, typename P>
 class WebFrameTestProxy : public Base, public WebFrameTestProxyBase {
  public:
diff --git a/components/test_runner/web_test_delegate.h b/components/test_runner/web_test_delegate.h
index 82e419b..145a5ef 100644
--- a/components/test_runner/web_test_delegate.h
+++ b/components/test_runner/web_test_delegate.h
@@ -53,7 +53,7 @@
 class DeviceLightData;
 class GamepadController;
 class WebTask;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 struct TestPreferences;
 
 class WebTestDelegate {
diff --git a/components/test_runner/web_test_interfaces.cc b/components/test_runner/web_test_interfaces.cc
index 241e240..fa9b59b 100644
--- a/components/test_runner/web_test_interfaces.cc
+++ b/components/test_runner/web_test_interfaces.cc
@@ -15,8 +15,8 @@
 #include "components/test_runner/test_interfaces.h"
 #include "components/test_runner/test_runner.h"
 #include "components/test_runner/web_frame_test_client.h"
-#include "components/test_runner/web_test_proxy.h"
 #include "components/test_runner/web_view_test_client.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "components/test_runner/web_widget_test_client.h"
 
 using namespace blink;
@@ -90,30 +90,29 @@
 }
 
 std::unique_ptr<WebFrameTestClient> WebTestInterfaces::CreateWebFrameTestClient(
-    WebTestProxyBase* web_test_proxy_base,
+    WebViewTestProxyBase* web_view_test_proxy_base,
     WebFrameTestProxyBase* web_frame_test_proxy_base) {
-  return base::WrapUnique(new WebFrameTestClient(interfaces_->GetTestRunner(),
-                                                 interfaces_->GetDelegate(),
-                                                 web_test_proxy_base,
-                                                 web_frame_test_proxy_base));
+  return base::WrapUnique(new WebFrameTestClient(
+      interfaces_->GetTestRunner(), interfaces_->GetDelegate(),
+      web_view_test_proxy_base, web_frame_test_proxy_base));
 }
 
 std::unique_ptr<WebViewTestClient> WebTestInterfaces::CreateWebViewTestClient(
-    WebTestProxyBase* web_test_proxy_base) {
-  return base::WrapUnique(
-      new WebViewTestClient(interfaces_->GetTestRunner(), web_test_proxy_base));
+    WebViewTestProxyBase* web_view_test_proxy_base) {
+  return base::WrapUnique(new WebViewTestClient(interfaces_->GetTestRunner(),
+                                                web_view_test_proxy_base));
 }
 
 std::unique_ptr<WebWidgetTestClient>
 WebTestInterfaces::CreateWebWidgetTestClient(
-    WebTestProxyBase* web_test_proxy_base) {
+    WebViewTestProxyBase* web_view_test_proxy_base) {
   return base::WrapUnique(new WebWidgetTestClient(interfaces_->GetTestRunner(),
-                                                  web_test_proxy_base));
+                                                  web_view_test_proxy_base));
 }
 
 std::vector<blink::WebView*> WebTestInterfaces::GetWindowList() {
   std::vector<blink::WebView*> result;
-  for (WebTestProxyBase* proxy : interfaces_->GetWindowList())
+  for (WebViewTestProxyBase* proxy : interfaces_->GetWindowList())
     result.push_back(proxy->web_view());
   return result;
 }
diff --git a/components/test_runner/web_test_interfaces.h b/components/test_runner/web_test_interfaces.h
index 4f37c31..2a73e7b 100644
--- a/components/test_runner/web_test_interfaces.h
+++ b/components/test_runner/web_test_interfaces.h
@@ -34,7 +34,7 @@
 class WebFrameTestClient;
 class WebFrameTestProxyBase;
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 class WebTestRunner;
 class WebViewTestClient;
 class WebWidgetTestClient;
@@ -71,24 +71,24 @@
   // Creates a WebFrameClient implementation providing test behavior (i.e.
   // forwarding javascript console output to the test harness).  The caller
   // should guarantee that the returned object won't be used beyond the lifetime
-  // of WebTestInterfaces and/or the lifetime of |web_test_proxy_base|.
+  // of WebTestInterfaces and/or the lifetime of |web_view_test_proxy_base|.
   std::unique_ptr<WebFrameTestClient> CreateWebFrameTestClient(
-      WebTestProxyBase* web_test_proxy_base,
+      WebViewTestProxyBase* web_view_test_proxy_base,
       WebFrameTestProxyBase* web_frame_test_proxy_base);
 
   // Creates a WebViewClient implementation providing test behavior (i.e.
   // providing a mocked speech recognizer).  The caller should guarantee that
   // the returned pointer won't be used beyond the lifetime of WebTestInterfaces
-  // and/or the lifetime of |web_test_proxy_base|.
+  // and/or the lifetime of |web_view_test_proxy_base|.
   std::unique_ptr<WebViewTestClient> CreateWebViewTestClient(
-      WebTestProxyBase* web_test_proxy_base);
+      WebViewTestProxyBase* web_view_test_proxy_base);
 
   // Creates a WebWidgetClient implementation providing test behavior (i.e.
   // providing a mocked screen orientation).  The caller should guarantee that
   // the returned pointer won't be used beyond the lifetime of WebTestInterfaces
-  // and/or the lifetime of |web_test_proxy_base|.
+  // and/or the lifetime of |web_view_test_proxy_base|.
   std::unique_ptr<WebWidgetTestClient> CreateWebWidgetTestClient(
-      WebTestProxyBase* web_test_proxy_base);
+      WebViewTestProxyBase* web_view_test_proxy_base);
 
   // Gets a list of currently opened windows created by the current test.
   std::vector<blink::WebView*> GetWindowList();
diff --git a/components/test_runner/web_test_runner.h b/components/test_runner/web_test_runner.h
index 41b54df..b7efae1 100644
--- a/components/test_runner/web_test_runner.h
+++ b/components/test_runner/web_test_runner.h
@@ -31,7 +31,7 @@
   virtual blink::WebContentSettingsClient* GetWebContentSettings() const = 0;
 
   // After WebTestDelegate::TestFinished was invoked, the following methods
-  // can be used to determine what kind of dump the main WebTestProxy can
+  // can be used to determine what kind of dump the main WebViewTestProxy can
   // provide.
 
   // If true, WebTestDelegate::audioData returns an audio dump and no text
@@ -65,11 +65,11 @@
   // |custom_text_dump| argument.  Otherwise returns |false|.
   virtual bool HasCustomTextDump(std::string* custom_text_dump) const = 0;
 
-  // Returns true if the call to WebTestProxy::captureTree will invoke
+  // Returns true if the call to WebViewTestProxy::captureTree will invoke
   // WebTestDelegate::captureHistoryForWindow.
   virtual bool ShouldDumpBackForwardList() const = 0;
 
-  // Returns true if WebTestProxy::capturePixels should be invoked after
+  // Returns true if WebViewTestProxy::capturePixels should be invoked after
   // capturing text results.
   virtual bool ShouldGeneratePixelResults() = 0;
 
diff --git a/components/test_runner/web_view_test_client.cc b/components/test_runner/web_view_test_client.cc
index b02663fd..ff464ab 100644
--- a/components/test_runner/web_view_test_client.cc
+++ b/components/test_runner/web_view_test_client.cc
@@ -17,7 +17,7 @@
 #include "components/test_runner/test_runner_for_specific_view.h"
 #include "components/test_runner/web_task.h"
 #include "components/test_runner/web_test_delegate.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -28,12 +28,13 @@
 
 namespace test_runner {
 
-WebViewTestClient::WebViewTestClient(TestRunner* test_runner,
-                                     WebTestProxyBase* web_test_proxy_base)
+WebViewTestClient::WebViewTestClient(
+    TestRunner* test_runner,
+    WebViewTestProxyBase* web_view_test_proxy_base)
     : test_runner_(test_runner),
-      web_test_proxy_base_(web_test_proxy_base) {
+      web_view_test_proxy_base_(web_view_test_proxy_base) {
   DCHECK(test_runner);
-  DCHECK(web_test_proxy_base);
+  DCHECK(web_view_test_proxy_base);
 }
 
 WebViewTestClient::~WebViewTestClient() {}
@@ -47,7 +48,7 @@
 
   // When running a test, we need to fake a drag drop operation otherwise
   // Windows waits for real mouse events to know when the drag is over.
-  web_test_proxy_base_->event_sender()->DoDragDrop(data, mask);
+  web_view_test_proxy_base_->event_sender()->DoDragDrop(data, mask);
 }
 
 // The output from these methods in layout test mode should match that
@@ -78,8 +79,8 @@
     delegate()->PrintMessage(std::string("createView(") +
                              URLDescription(request.url()) + ")\n");
 
-  // The return value below is used to communicate to WebTestProxy whether it
-  // should forward the createView request to RenderViewImpl or not.  The
+  // The return value below is used to communicate to WebViewTestProxy whether
+  // it should forward the createView request to RenderViewImpl or not.  The
   // somewhat ugly cast is used to do this while fitting into the existing
   // WebViewClient interface.
   return reinterpret_cast<blink::WebView*>(0xdeadbeef);
@@ -143,11 +144,11 @@
 }
 
 WebTestDelegate* WebViewTestClient::delegate() {
-  return web_test_proxy_base_->delegate();
+  return web_view_test_proxy_base_->delegate();
 }
 
 void WebViewTestClient::didFocus() {
-  test_runner_->SetFocus(web_test_proxy_base_->web_view(), true);
+  test_runner_->SetFocus(web_view_test_proxy_base_->web_view(), true);
 }
 
 }  // namespace test_runner
diff --git a/components/test_runner/web_view_test_client.h b/components/test_runner/web_view_test_client.h
index 03c65cd..21b8c61 100644
--- a/components/test_runner/web_view_test_client.h
+++ b/components/test_runner/web_view_test_client.h
@@ -17,10 +17,10 @@
 class EventSender;
 class TestRunner;
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 // WebViewTestClient implements WebViewClient interface, providing behavior
-// expected by tests.  WebViewTestClient ends up used by WebTestProxy
+// expected by tests.  WebViewTestClient ends up used by WebViewTestProxy
 // which coordinates forwarding WebViewClient calls either to
 // WebViewTestClient or to the product code (i.e. to RenderViewImpl).
 class WebViewTestClient : public blink::WebViewClient {
@@ -28,11 +28,11 @@
   // Caller has to ensure that all arguments (i.e. |test_runner| and |delegate|)
   // live longer than |this|.
   WebViewTestClient(TestRunner* test_runner,
-                    WebTestProxyBase* web_test_proxy_base);
+                    WebViewTestProxyBase* web_view_test_proxy_base);
 
   virtual ~WebViewTestClient();
 
-  // WebViewClient overrides needed by WebTestProxy.
+  // WebViewClient overrides needed by WebViewTestProxy.
   void showValidationMessage(const blink::WebRect& anchor_in_root_view,
                              const blink::WebString& main_message,
                              blink::WebTextDirection main_message_hint,
@@ -61,7 +61,7 @@
 
   // Borrowed pointers to other parts of Layout Tests state.
   TestRunner* test_runner_;
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
 
   DISALLOW_COPY_AND_ASSIGN(WebViewTestClient);
 };
diff --git a/components/test_runner/web_test_proxy.cc b/components/test_runner/web_view_test_proxy.cc
similarity index 82%
rename from components/test_runner/web_test_proxy.cc
rename to components/test_runner/web_view_test_proxy.cc
index 299a45a..1a811930 100644
--- a/components/test_runner/web_test_proxy.cc
+++ b/components/test_runner/web_view_test_proxy.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/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -19,7 +19,7 @@
 
 namespace test_runner {
 
-WebTestProxyBase::WebTestProxyBase()
+WebViewTestProxyBase::WebViewTestProxyBase()
     : test_interfaces_(nullptr),
       delegate_(nullptr),
       web_view_(nullptr),
@@ -29,23 +29,23 @@
       text_input_controller_(new TextInputController(this)),
       view_test_runner_(new TestRunnerForSpecificView(this)) {}
 
-WebTestProxyBase::~WebTestProxyBase() {
+WebViewTestProxyBase::~WebViewTestProxyBase() {
   test_interfaces_->WindowClosed(this);
 }
 
-void WebTestProxyBase::SetInterfaces(WebTestInterfaces* interfaces) {
+void WebViewTestProxyBase::SetInterfaces(WebTestInterfaces* interfaces) {
   test_interfaces_ = interfaces->GetTestInterfaces();
   test_interfaces_->WindowOpened(this);
 }
 
-void WebTestProxyBase::Reset() {
+void WebViewTestProxyBase::Reset() {
   accessibility_controller_->Reset();
   event_sender_->Reset();
   // text_input_controller_ doesn't have any state to reset.
   view_test_runner_->Reset();
 }
 
-void WebTestProxyBase::BindTo(blink::WebLocalFrame* frame) {
+void WebViewTestProxyBase::BindTo(blink::WebLocalFrame* frame) {
   accessibility_controller_->Install(frame);
   event_sender_->Install(frame);
   text_input_controller_->Install(frame);
diff --git a/components/test_runner/web_test_proxy.h b/components/test_runner/web_view_test_proxy.h
similarity index 80%
rename from components/test_runner/web_test_proxy.h
rename to components/test_runner/web_view_test_proxy.h
index 55cadc1a..944731c 100644
--- a/components/test_runner/web_test_proxy.h
+++ b/components/test_runner/web_view_test_proxy.h
@@ -50,12 +50,12 @@
 class WebTestDelegate;
 class WebTestInterfaces;
 
-// WebTestProxyBase is the "brain" of WebTestProxy in the sense that
-// WebTestProxy does the bridge between RenderViewImpl and WebTestProxyBase and
-// when it requires a behavior to be different from the usual, it will call
-// WebTestProxyBase that implements the expected behavior.
-// See WebTestProxy class comments for more information.
-class TEST_RUNNER_EXPORT WebTestProxyBase {
+// WebViewTestProxyBase is the "brain" of WebViewTestProxy in the sense that
+// WebViewTestProxy does the bridge between RenderViewImpl and
+// WebViewTestProxyBase and when it requires a behavior to be different from the
+// usual, it will call WebViewTestProxyBase that implements the expected
+// behavior. See WebViewTestProxy class comments for more information.
+class TEST_RUNNER_EXPORT WebViewTestProxyBase {
  public:
   blink::WebWidget* web_widget() { return web_widget_; }
   void set_web_widget(blink::WebWidget* widget) {
@@ -111,8 +111,8 @@
   void GetScreenOrientationForTesting(blink::WebScreenInfo&);
 
  protected:
-  WebTestProxyBase();
-  ~WebTestProxyBase();
+  WebViewTestProxyBase();
+  ~WebViewTestProxyBase();
 
   blink::WebViewClient* view_test_client() { return view_test_client_.get(); }
   blink::WebWidgetClient* widget_test_client() {
@@ -131,35 +131,36 @@
   std::unique_ptr<TextInputController> text_input_controller_;
   std::unique_ptr<TestRunnerForSpecificView> view_test_runner_;
 
-  DISALLOW_COPY_AND_ASSIGN(WebTestProxyBase);
+  DISALLOW_COPY_AND_ASSIGN(WebViewTestProxyBase);
 };
 
-// WebTestProxy is used during LayoutTests and always instantiated, at time of
-// writing with Base=RenderViewImpl. It does not directly inherit from it for
+// WebViewTestProxy is used during LayoutTests and always instantiated, at time
+// of writing with Base=RenderViewImpl. It does not directly inherit from it for
 // layering purposes.
 // The intent of that class is to wrap RenderViewImpl for tests purposes in
 // order to reduce the amount of test specific code in the production code.
-// WebTestProxy is only doing the glue between RenderViewImpl and
-// WebTestProxyBase, that means that there is no logic living in this class
+// WebViewTestProxy is only doing the glue between RenderViewImpl and
+// WebViewTestProxyBase, that means that there is no logic living in this class
 // except deciding which base class should be called (could be both).
 //
 // Examples of usage:
-//  * when a fooClient has a mock implementation, WebTestProxy can override the
-//    fooClient() call and have WebTestProxyBase return the mock implementation.
-//  * when a value needs to be overridden by LayoutTests, WebTestProxy can
-//    override RenderViewImpl's getter and call a getter from WebTestProxyBase
-//    instead. In addition, WebTestProxyBase will have a public setter that
-//    could be called from the TestRunner.
+//  * when a fooClient has a mock implementation, WebViewTestProxy can override
+//    the fooClient() call and have WebViewTestProxyBase return the mock
+//    implementation.
+//  * when a value needs to be overridden by LayoutTests, WebViewTestProxy can
+//    override RenderViewImpl's getter and call a getter from
+//    WebViewTestProxyBase instead. In addition, WebViewTestProxyBase will have
+//    a public setter that could be called from the TestRunner.
 #if defined(OS_WIN)
-// WebTestProxy is a diamond-shaped hierarchy, with WebWidgetClient at the root.
-// VS warns when we inherit the WebWidgetClient method implementations from
-// RenderWidget. It's safe to ignore that warning.
-#pragma warning(disable: 4250)
+// WebViewTestProxy is a diamond-shaped hierarchy, with WebWidgetClient at the
+// root. VS warns when we inherit the WebWidgetClient method implementations
+// from RenderWidget. It's safe to ignore that warning.
+#pragma warning(disable : 4250)
 #endif
 template <class Base, typename... Args>
-class WebTestProxy : public Base, public WebTestProxyBase {
+class WebViewTestProxy : public Base, public WebViewTestProxyBase {
  public:
-  explicit WebTestProxy(Args... args) : Base(args...) {}
+  explicit WebViewTestProxy(Args... args) : Base(args...) {}
 
   // WebWidgetClient implementation.
   blink::WebScreenInfo screenInfo() override {
@@ -217,8 +218,8 @@
     if (!view_test_client()->createView(creator, request, features, frame_name,
                                         policy, suppress_opener))
       return nullptr;
-    return Base::createView(
-        creator, request, features, frame_name, policy, suppress_opener);
+    return Base::createView(creator, request, features, frame_name, policy,
+                            suppress_opener);
   }
   void setStatusText(const blink::WebString& text) override {
     view_test_client()->setStatusText(text);
@@ -245,9 +246,9 @@
   }
 
  private:
-  virtual ~WebTestProxy() {}
+  virtual ~WebViewTestProxy() {}
 
-  DISALLOW_COPY_AND_ASSIGN(WebTestProxy);
+  DISALLOW_COPY_AND_ASSIGN(WebViewTestProxy);
 };
 
 }  // namespace test_runner
diff --git a/components/test_runner/web_widget_test_client.cc b/components/test_runner/web_widget_test_client.cc
index e40cf26..a3e65061 100644
--- a/components/test_runner/web_widget_test_client.cc
+++ b/components/test_runner/web_widget_test_client.cc
@@ -14,21 +14,22 @@
 #include "components/test_runner/test_runner_for_specific_view.h"
 #include "components/test_runner/web_task.h"
 #include "components/test_runner/web_test_delegate.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
 #include "third_party/WebKit/public/web/WebPagePopup.h"
 #include "third_party/WebKit/public/web/WebWidget.h"
 
 namespace test_runner {
 
-WebWidgetTestClient::WebWidgetTestClient(TestRunner* test_runner,
-                                         WebTestProxyBase* web_test_proxy_base)
+WebWidgetTestClient::WebWidgetTestClient(
+    TestRunner* test_runner,
+    WebViewTestProxyBase* web_view_test_proxy_base)
     : test_runner_(test_runner),
-      web_test_proxy_base_(web_test_proxy_base),
+      web_view_test_proxy_base_(web_view_test_proxy_base),
       animation_scheduled_(false),
       weak_factory_(this) {
   DCHECK(test_runner);
-  DCHECK(web_test_proxy_base);
+  DCHECK(web_view_test_proxy_base);
 }
 
 WebWidgetTestClient::~WebWidgetTestClient() {}
@@ -39,9 +40,9 @@
 
   if (!animation_scheduled_) {
     animation_scheduled_ = true;
-    test_runner_->OnAnimationScheduled(web_test_proxy_base_->web_widget());
+    test_runner_->OnAnimationScheduled(web_view_test_proxy_base_->web_widget());
 
-    web_test_proxy_base_->delegate()->PostDelayedTask(
+    web_view_test_proxy_base_->delegate()->PostDelayedTask(
         new WebCallbackTask(base::Bind(&WebWidgetTestClient::AnimateNow,
                                        weak_factory_.GetWeakPtr())),
         1);
@@ -50,7 +51,7 @@
 
 void WebWidgetTestClient::AnimateNow() {
   if (animation_scheduled_) {
-    blink::WebWidget* web_widget = web_test_proxy_base_->web_widget();
+    blink::WebWidget* web_widget = web_view_test_proxy_base_->web_widget();
     animation_scheduled_ = false;
     test_runner_->OnAnimationBegun(web_widget);
 
@@ -67,11 +68,11 @@
 blink::WebScreenInfo WebWidgetTestClient::screenInfo() {
   blink::WebScreenInfo screen_info;
   MockScreenOrientationClient* mock_client =
-      web_test_proxy_base_->test_interfaces()
+      web_view_test_proxy_base_->test_interfaces()
           ->GetTestRunner()
           ->getMockScreenOrientationClient();
   if (mock_client->IsDisabled()) {
-    // Indicate to WebTestProxy that there is no test/mock info.
+    // Indicate to WebViewTestProxy that there is no test/mock info.
     screen_info.orientationType = blink::WebScreenOrientationUndefined;
   } else {
     // Override screen orientation information with mock data.
@@ -82,15 +83,15 @@
 }
 
 bool WebWidgetTestClient::requestPointerLock() {
-  return web_test_proxy_base_->view_test_runner()->RequestPointerLock();
+  return web_view_test_proxy_base_->view_test_runner()->RequestPointerLock();
 }
 
 void WebWidgetTestClient::requestPointerUnlock() {
-  web_test_proxy_base_->view_test_runner()->RequestPointerUnlock();
+  web_view_test_proxy_base_->view_test_runner()->RequestPointerUnlock();
 }
 
 bool WebWidgetTestClient::isPointerLocked() {
-  return web_test_proxy_base_->view_test_runner()->isPointerLocked();
+  return web_view_test_proxy_base_->view_test_runner()->isPointerLocked();
 }
 
 void WebWidgetTestClient::setToolTipText(const blink::WebString& text,
@@ -101,8 +102,8 @@
 void WebWidgetTestClient::resetInputMethod() {
   // If a composition text exists, then we need to let the browser process
   // to cancel the input method's ongoing composition session.
-  if (web_test_proxy_base_)
-    web_test_proxy_base_->web_widget()->confirmComposition();
+  if (web_view_test_proxy_base_)
+    web_view_test_proxy_base_->web_widget()->confirmComposition();
 }
 
 }  // namespace test_runner
diff --git a/components/test_runner/web_widget_test_client.h b/components/test_runner/web_widget_test_client.h
index 1766746..a5e9d5d1 100644
--- a/components/test_runner/web_widget_test_client.h
+++ b/components/test_runner/web_widget_test_client.h
@@ -17,22 +17,23 @@
 
 class TestRunner;
 class WebTestDelegate;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 
 // WebWidgetTestClient implements WebWidgetClient interface, providing behavior
-// expected by tests.  WebWidgetTestClient ends up used by WebTestProxy which
-// coordinates forwarding WebWidgetClient calls either to WebWidgetTestClient or
-// to the product code (i.e. currently to RenderViewImpl).
+// expected by tests.  WebWidgetTestClient ends up used by WebViewTestProxy
+// which coordinates forwarding WebWidgetClient calls either to
+// WebWidgetTestClient or to the product code (i.e. currently to
+// RenderViewImpl).
 class WebWidgetTestClient : public blink::WebWidgetClient {
  public:
   // Caller has to ensure that all arguments (i.e. |test_runner| and |delegate|)
   // live longer than |this|.
   WebWidgetTestClient(TestRunner* test_runner,
-                      WebTestProxyBase* web_test_proxy_base);
+                      WebViewTestProxyBase* web_view_test_proxy_base);
 
   virtual ~WebWidgetTestClient();
 
-  // WebWidgetClient overrides needed by WebTestProxy.
+  // WebWidgetClient overrides needed by WebViewTestProxy.
   blink::WebScreenInfo screenInfo() override;
   void scheduleAnimation() override;
   bool requestPointerLock() override;
@@ -47,7 +48,7 @@
 
   // Borrowed pointers to other parts of Layout Tests state.
   TestRunner* test_runner_;
-  WebTestProxyBase* web_test_proxy_base_;
+  WebViewTestProxyBase* web_view_test_proxy_base_;
 
   bool animation_scheduled_;
 
diff --git a/components/translate/content/browser/BUILD.gn b/components/translate/content/browser/BUILD.gn
index 1a4b1d8..59bbcc8 100644
--- a/components/translate/content/browser/BUILD.gn
+++ b/components/translate/content/browser/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//build/config/features.gni")
 
-source_set("browser") {
+static_library("browser") {
   sources = [
     "content_translate_driver.cc",
     "content_translate_driver.h",
diff --git a/components/translate/core/browser/BUILD.gn b/components/translate/core/browser/BUILD.gn
index 5efd47f2..bf07001 100644
--- a/components/translate/core/browser/BUILD.gn
+++ b/components/translate/core/browser/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//build/config/ui.gni")
 
-source_set("browser") {
+static_library("browser") {
   sources = [
     "language_state.cc",
     "language_state.h",
diff --git a/components/translate/core/browser/translate_script.cc b/components/translate/core/browser/translate_script.cc
index b95fbd2..511ac6c 100644
--- a/components/translate/core/browser/translate_script.cc
+++ b/components/translate/core/browser/translate_script.cc
@@ -34,7 +34,7 @@
 }  // namespace
 
 const char TranslateScript::kScriptURL[] =
-    "https://translate.google.com/translate_a/element.js";
+    "https://translate.googleapis.com/translate_a/element.js";
 const char TranslateScript::kRequestHeader[] =
     "Google-Translate-Element-Mode: library";
 const char TranslateScript::kAlwaysUseSslQueryName[] = "aus";
diff --git a/components/translate/core/common/BUILD.gn b/components/translate/core/common/BUILD.gn
index f4d461f..237c1ae 100644
--- a/components/translate/core/common/BUILD.gn
+++ b/components/translate/core/common/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("common") {
+static_library("common") {
   sources = [
     "language_detection_details.cc",
     "language_detection_details.h",
diff --git a/components/translate/core/language_detection/BUILD.gn b/components/translate/core/language_detection/BUILD.gn
index 98f4d1f..68eae65 100644
--- a/components/translate/core/language_detection/BUILD.gn
+++ b/components/translate/core/language_detection/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//build/config/features.gni")
 
-source_set("language_detection") {
+static_library("language_detection") {
   sources = [
     "language_detection_util.cc",
     "language_detection_util.h",
diff --git a/components/upload_list/BUILD.gn b/components/upload_list/BUILD.gn
index 5c15ea9..46b8692 100644
--- a/components/upload_list/BUILD.gn
+++ b/components/upload_list/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("upload_list") {
+static_library("upload_list") {
   sources = [
     "crash_upload_list.cc",
     "crash_upload_list.h",
diff --git a/components/url_formatter/BUILD.gn b/components/url_formatter/BUILD.gn
index 0bd6e01..d63a1ed6 100644
--- a/components/url_formatter/BUILD.gn
+++ b/components/url_formatter/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("url_formatter") {
+static_library("url_formatter") {
   sources = [
     "elide_url.cc",
     "elide_url.h",
diff --git a/components/variations/net/BUILD.gn b/components/variations/net/BUILD.gn
index c037d46f..148bf79a 100644
--- a/components/variations/net/BUILD.gn
+++ b/components/variations/net/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("net") {
+static_library("net") {
   sources = [
     "variations_http_headers.cc",
     "variations_http_headers.h",
diff --git a/components/variations/service/BUILD.gn b/components/variations/service/BUILD.gn
index 099be5c2..d2ea94f1 100644
--- a/components/variations/service/BUILD.gn
+++ b/components/variations/service/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("service") {
+static_library("service") {
   sources = [
     "ui_string_overrider.cc",
     "ui_string_overrider.h",
diff --git a/components/version_info/BUILD.gn b/components/version_info/BUILD.gn
index 6c043e53..7e0281a 100644
--- a/components/version_info/BUILD.gn
+++ b/components/version_info/BUILD.gn
@@ -9,7 +9,7 @@
   use_unofficial_version_number = !is_chrome_branded
 }
 
-source_set("version_info") {
+static_library("version_info") {
   sources = [
     "version_info.cc",
     "version_info.h",
diff --git a/components/version_ui/BUILD.gn b/components/version_ui/BUILD.gn
index a6693b6..91b80b27 100644
--- a/components/version_ui/BUILD.gn
+++ b/components/version_ui/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("version_ui") {
+static_library("version_ui") {
   sources = [
     "version_handler_helper.cc",
     "version_handler_helper.h",
diff --git a/components/visitedlink/browser/BUILD.gn b/components/visitedlink/browser/BUILD.gn
index a8ce9ea7..49796fd 100644
--- a/components/visitedlink/browser/BUILD.gn
+++ b/components/visitedlink/browser/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("browser") {
+static_library("browser") {
   sources = [
     "visitedlink_delegate.h",
     "visitedlink_event_listener.cc",
diff --git a/components/visitedlink/common/BUILD.gn b/components/visitedlink/common/BUILD.gn
index 712e8d09..ae0f12d 100644
--- a/components/visitedlink/common/BUILD.gn
+++ b/components/visitedlink/common/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("common") {
+static_library("common") {
   sources = [
     "visitedlink_common.cc",
     "visitedlink_common.h",
diff --git a/components/visitedlink/renderer/BUILD.gn b/components/visitedlink/renderer/BUILD.gn
index 01a11f07..1887406b 100644
--- a/components/visitedlink/renderer/BUILD.gn
+++ b/components/visitedlink/renderer/BUILD.gn
@@ -4,7 +4,7 @@
 
 assert(!is_ios)
 
-source_set("renderer") {
+static_library("renderer") {
   sources = [
     "visitedlink_slave.cc",
     "visitedlink_slave.h",
diff --git a/components/web_cache/browser/BUILD.gn b/components/web_cache/browser/BUILD.gn
index 9b566c5f..00f49a4 100644
--- a/components/web_cache/browser/BUILD.gn
+++ b/components/web_cache/browser/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("browser") {
+static_library("browser") {
   sources = [
     "web_cache_manager.cc",
     "web_cache_manager.h",
diff --git a/components/web_cache/renderer/BUILD.gn b/components/web_cache/renderer/BUILD.gn
index 4f3df24..fdc2b05 100644
--- a/components/web_cache/renderer/BUILD.gn
+++ b/components/web_cache/renderer/BUILD.gn
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("renderer") {
+static_library("renderer") {
   sources = [
     "web_cache_impl.cc",
     "web_cache_impl.h",
diff --git a/components/webcrypto/BUILD.gn b/components/webcrypto/BUILD.gn
index 06d0552e..9c3ca509 100644
--- a/components/webcrypto/BUILD.gn
+++ b/components/webcrypto/BUILD.gn
@@ -5,7 +5,7 @@
 import("//testing/test.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
-source_set("webcrypto") {
+static_library("webcrypto") {
   sources = [
     "algorithm_dispatch.cc",
     "algorithm_dispatch.h",
diff --git a/components/wifi/BUILD.gn b/components/wifi/BUILD.gn
index 7cd31469..878e1f6 100644
--- a/components/wifi/BUILD.gn
+++ b/components/wifi/BUILD.gn
@@ -35,7 +35,7 @@
   }
 }
 
-source_set("test_support") {
+static_library("test_support") {
   sources = [
     "fake_wifi_service.cc",
     "fake_wifi_service.h",
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 604e420..b2dff5c 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -425,10 +425,14 @@
     focus_object = focus_object->GetClosestPlatformObject();
     auto native_focus_object = ToBrowserAccessibilityCocoa(focus_object);
     if (native_focus_object && [native_focus_object instanceActive]) {
-      [user_info setObject:[native_focus_object selectedTextMarkerRange]
-                    forKey:NSAccessibilitySelectedTextMarkerRangeAttribute];
       [user_info setObject:native_focus_object
                     forKey:NSAccessibilityTextChangeElement];
+
+      id selected_text = [native_focus_object selectedTextMarkerRange];
+      if (selected_text) {
+        [user_info setObject:selected_text
+                      forKey:NSAccessibilitySelectedTextMarkerRangeAttribute];
+      }
     }
   }
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 00ba343..8103470d 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -181,6 +181,7 @@
 #endif
 
 #if defined(USE_X11)
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
 #include "ui/base/x/x11_util_internal.h"  // nogncheck
 #include "ui/gfx/x/x11_connection.h"  // nogncheck
 #include "ui/gfx/x/x11_switches.h"  // nogncheck
@@ -682,9 +683,6 @@
     DOMStorageArea::EnableAggressiveCommitDelay();
   }
 
-  GeolocationProvider::SetGeolocationDelegate(
-      GetContentClient()->browser()->CreateGeolocationDelegate());
-
   // Enable memory-infra dump providers.
   InitSkiaEventTracer();
   tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
@@ -762,6 +760,22 @@
   // 2) Must be after parts_->PreCreateThreads to pick up chrome://flags.
   GpuDataManagerImpl::GetInstance()->Initialize();
 
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+  // PreCreateThreads is called before CreateStartupTasks which starts the gpu
+  // process.
+  bool enable_transparent_visuals =
+      !GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
+          gpu::DISABLE_TRANSPARENT_VISUALS);
+  Visual* visual = NULL;
+  int depth = 0;
+  ui::ChooseVisualForWindow(enable_transparent_visuals, &visual, &depth);
+  DCHECK(depth > 0);
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kWindowDepth, base::IntToString(depth));
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kX11VisualID, base::UintToString(visual->visualid));
+#endif
+
 #if !defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID)
   // Single-process is an unsupported and not fully tested mode, so
   // don't enable it for official Chrome builds (except on Android).
@@ -1385,20 +1399,6 @@
     LOG(ERROR) << "Unable to open X display.";
     return false;
   }
-
-#if !defined(OS_CHROMEOS)
-  // InitializeToolkit is called before CreateStartupTasks which one starts the
-  // gpu process.
-  Visual* visual = NULL;
-  int depth = 0;
-  ui::ChooseVisualForWindow(&visual, &depth);
-  DCHECK(depth > 0);
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kWindowDepth, base::IntToString(depth));
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kX11VisualID, base::UintToString(visual->visualid));
-#endif
-
 #endif
 
   // Env creates the compositor. Aura widgets need the compositor to be created
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 632b0b55..274acc3 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -158,7 +158,7 @@
 // static
 void BrowserThreadImpl::FlushThreadPoolHelperForTesting() {
   // We don't want to create a pool if none exists.
-  if (g_globals == NULL)
+  if (g_globals == nullptr)
     return;
   g_globals.Get().blocking_pool->FlushForTesting();
   disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
@@ -286,15 +286,16 @@
   // to prevent a race with accessing the message loop in PostTaskHelper(),
   // remove this thread from the global array now.
   base::AutoLock lock(globals.lock);
-  globals.threads[identifier_] = NULL;
+  globals.threads[identifier_] = nullptr;
 }
 
 void BrowserThreadImpl::Initialize() {
   BrowserThreadGlobals& globals = g_globals.Get();
 
   base::AutoLock lock(globals.lock);
-  DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
-  DCHECK(globals.threads[identifier_] == NULL);
+  DCHECK_GE(identifier_, 0);
+  DCHECK_LT(identifier_, ID_COUNT);
+  DCHECK_EQ(globals.threads[identifier_], nullptr);
   globals.threads[identifier_] = this;
 }
 
@@ -306,7 +307,7 @@
 
   BrowserThreadGlobals& globals = g_globals.Get();
   base::AutoLock lock(globals.lock);
-  globals.threads[identifier_] = NULL;
+  globals.threads[identifier_] = nullptr;
 #ifndef NDEBUG
   // Double check that the threads are ordered correctly in the enumeration.
   for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
@@ -332,7 +333,8 @@
     const base::Closure& task,
     base::TimeDelta delay,
     bool nestable) {
-  DCHECK(identifier >= 0 && identifier < ID_COUNT);
+  DCHECK_GE(identifier, 0);
+  DCHECK_LT(identifier, ID_COUNT);
   // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
   // order of lifetime.  So no need to lock if we know that the target thread
   // outlives current thread.
@@ -350,7 +352,7 @@
 
   base::MessageLoop* message_loop =
       globals.threads[identifier] ? globals.threads[identifier]->message_loop()
-                                  : NULL;
+                                  : nullptr;
   if (message_loop) {
     if (nestable) {
       message_loop->task_runner()->PostDelayedTask(from_here, task, delay);
@@ -407,20 +409,22 @@
 
 // static
 bool BrowserThread::IsThreadInitialized(ID identifier) {
-  if (g_globals == NULL)
+  if (g_globals == nullptr)
     return false;
 
   BrowserThreadGlobals& globals = g_globals.Get();
   base::AutoLock lock(globals.lock);
-  DCHECK(identifier >= 0 && identifier < ID_COUNT);
-  return globals.threads[identifier] != NULL;
+  DCHECK_GE(identifier, 0);
+  DCHECK_LT(identifier, ID_COUNT);
+  return globals.threads[identifier] != nullptr;
 }
 
 // static
 bool BrowserThread::CurrentlyOn(ID identifier) {
   BrowserThreadGlobals& globals = g_globals.Get();
   base::AutoLock lock(globals.lock);
-  DCHECK(identifier >= 0 && identifier < ID_COUNT);
+  DCHECK_GE(identifier, 0);
+  DCHECK_LT(identifier, ID_COUNT);
   return globals.threads[identifier] &&
          globals.threads[identifier]->message_loop() ==
              base::MessageLoop::current();
@@ -442,12 +446,13 @@
 
 // static
 bool BrowserThread::IsMessageLoopValid(ID identifier) {
-  if (g_globals == NULL)
+  if (g_globals == nullptr)
     return false;
 
   BrowserThreadGlobals& globals = g_globals.Get();
   base::AutoLock lock(globals.lock);
-  DCHECK(identifier >= 0 && identifier < ID_COUNT);
+  DCHECK_GE(identifier, 0);
+  DCHECK_LT(identifier, ID_COUNT);
   return globals.threads[identifier] &&
          globals.threads[identifier]->message_loop();
 }
@@ -500,7 +505,7 @@
 
 // static
 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
-  if (g_globals == NULL)
+  if (g_globals == nullptr)
     return false;
 
   base::MessageLoop* cur_message_loop = base::MessageLoop::current();
@@ -529,8 +534,8 @@
 
 // static
 base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
-  if (g_globals == NULL)
-    return NULL;
+  if (g_globals == nullptr)
+    return nullptr;
 
   BrowserThreadGlobals& globals = g_globals.Get();
   base::AutoLock lock(globals.lock);
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index af1f5fe..1827ba8e 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -690,13 +690,8 @@
   return this;
 }
 
-std::unique_ptr<cc::SurfaceIdAllocator>
-GpuProcessTransportFactory::CreateSurfaceIdAllocator() {
-  std::unique_ptr<cc::SurfaceIdAllocator> allocator =
-      base::WrapUnique(new cc::SurfaceIdAllocator(next_surface_client_id_++));
-  if (GetSurfaceManager())
-    allocator->RegisterSurfaceClientId(GetSurfaceManager());
-  return allocator;
+uint32_t GpuProcessTransportFactory::AllocateSurfaceClientId() {
+  return next_surface_client_id_++;
 }
 
 void GpuProcessTransportFactory::ResizeDisplay(ui::Compositor* compositor,
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index 0db60467..797d99e 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -61,7 +61,7 @@
   cc::SharedBitmapManager* GetSharedBitmapManager() override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
-  std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
+  uint32_t AllocateSurfaceClientId() override;
   void ResizeDisplay(ui::Compositor* compositor,
                      const gfx::Size& size) override;
   void SetDisplayColorSpace(ui::Compositor* compositor,
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
index 4cbd80dfa..507c063 100644
--- a/content/browser/compositor/surface_utils.cc
+++ b/content/browser/compositor/surface_utils.cc
@@ -158,12 +158,12 @@
 
 namespace content {
 
-std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() {
+uint32_t AllocateSurfaceClientId() {
 #if defined(OS_ANDROID)
-  return CompositorImpl::CreateSurfaceIdAllocator();
+  return CompositorImpl::AllocateSurfaceClientId();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-  return factory->GetContextFactory()->CreateSurfaceIdAllocator();
+  return factory->GetContextFactory()->AllocateSurfaceClientId();
 #endif
 }
 
diff --git a/content/browser/compositor/surface_utils.h b/content/browser/compositor/surface_utils.h
index 92bfe57..3488e73 100644
--- a/content/browser/compositor/surface_utils.h
+++ b/content/browser/compositor/surface_utils.h
@@ -14,17 +14,14 @@
 
 namespace cc {
 class CopyOutputResult;
-class SurfaceIdAllocator;
 class SurfaceManager;
 }  // namespace cc
 
 namespace content {
 
-CONTENT_EXPORT
-std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator();
+CONTENT_EXPORT uint32_t AllocateSurfaceClientId();
 
-CONTENT_EXPORT
-cc::SurfaceManager* GetSurfaceManager();
+CONTENT_EXPORT cc::SurfaceManager* GetSurfaceManager();
 
 void CopyFromCompositingSurfaceHasResult(
     const gfx::Size& dst_size_in_pixel,
diff --git a/content/browser/download/docs/save-page-as.md b/content/browser/download/docs/save-page-as.md
index 2661289..dba234c 100644
--- a/content/browser/download/docs/save-page-as.md
+++ b/content/browser/download/docs/save-page-as.md
@@ -88,13 +88,16 @@
           API) or by an embedder of `WebContents` (since this is public API of
           //content).
 
-* Step 2: `MHTMLGenerationManager` coordinates generation of the MHTML file
-          by sequentially (one-at-a-time) asking each frame to write its portion
-          of MHTML to a file handle.  Other classes (i.e. `SavePackage` and/or
-          `SaveFileManager`) are not used at this step at all.
+* Step 2: `MHTMLGenerationManager` creates a new instance of
+          `MHTMLGenerationManager::Job` that coordinates generation of
+          the MHTML file by sequentially (one-at-a-time) asking each
+          frame to write its portion of MHTML to a file handle.  Other
+          classes (i.e. `SavePackage` and/or `SaveFileManager`) are not
+          used at this step at all.
 
-* Step 3: When done `MHTMLGenerationManager` calls a completion callback
-          which in case of Save-Page-As will end up in
+* Step 3: When done `MHTMLGenerationManager` destroys
+          `MHTMLGenerationManager::Job` instance and calls a completion
+          callback which in case of Save-Page-As will end up in
           `SavePackage::OnMHTMLGenerated`.
 
 Note: MHTML format is by default disabled in Save-Page-As UI on Windows, MacOS
diff --git a/content/browser/download/download_resource_handler.cc b/content/browser/download/download_resource_handler.cc
index 7798f92..05d22a8e 100644
--- a/content/browser/download/download_resource_handler.cc
+++ b/content/browser/download/download_resource_handler.cc
@@ -149,11 +149,6 @@
   return true;
 }
 
-bool DownloadResourceHandler::OnBeforeNetworkStart(const GURL& url,
-                                                   bool* defer) {
-  return true;
-}
-
 // Create a new buffer, which will be handed to the download thread for file
 // writing and deletion.
 bool DownloadResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
diff --git a/content/browser/download/download_resource_handler.h b/content/browser/download/download_resource_handler.h
index a48aa49..9266358 100644
--- a/content/browser/download/download_resource_handler.h
+++ b/content/browser/download/download_resource_handler.h
@@ -52,9 +52,6 @@
   // Pass-through implementation.
   bool OnWillStart(const GURL& url, bool* defer) override;
 
-  // Pass-through implementation.
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
-
   // Create a new buffer, which will be handed to the download thread for file
   // writing and deletion.
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc
index 0605115..8a8052e 100644
--- a/content/browser/download/mhtml_generation_browsertest.cc
+++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -12,6 +12,9 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/common/frame_messages.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/mhtml_generation_params.h"
 #include "content/public/test/browser_test_utils.h"
@@ -102,7 +105,10 @@
 
   void GenerateMHTML(const MHTMLGenerationParams& params, const GURL& url) {
     NavigateToURL(shell(), url);
+    GenerateMHTMLForCurrentPage(params);
+  }
 
+  void GenerateMHTMLForCurrentPage(const MHTMLGenerationParams& params) {
     base::RunLoop run_loop;
 
     shell()->web_contents()->GenerateMHTML(
@@ -220,6 +226,121 @@
               HasSubstr("Content-Transfer-Encoding: quoted-printable"));
 }
 
+class GenerateMHTMLAndExitRendererMessageFilter : public BrowserMessageFilter {
+ public:
+  GenerateMHTMLAndExitRendererMessageFilter(
+      RenderProcessHostImpl* render_process_host)
+      : BrowserMessageFilter(FrameMsgStart),
+        render_process_host_(render_process_host) {}
+
+ protected:
+  ~GenerateMHTMLAndExitRendererMessageFilter() override {}
+
+ private:
+  bool OnMessageReceived(const IPC::Message& message) override {
+    if (message.type() == FrameHostMsg_SerializeAsMHTMLResponse::ID) {
+      // After |return false| below, this IPC message will be handled by the
+      // product code as illustrated below.  (1), (2), (3) depict points in time
+      // when product code runs on UI and FILE threads.  (X), (Y), (Z) depict
+      // when we want test-injected tasks to run - for the repro, (Z) has to
+      // happen between (1) and (3).  (Y?) and (Z?) depict when test tasks can
+      // theoretically happen and ruin the repro.
+      //
+      //     IO thread       UI thread           FILE thread
+      //     ---------       ---------           -----------
+      //        |                |                     |
+      //    WE ARE HERE          |                     |
+      //        |                |                     |
+      // after |return false|    |                     |
+      //        +--------------->+                     |
+      //        |                |                     |
+      //        |               (X)                    |
+      //        |                |                     |
+      //        |                |                    (Y?)
+      //        |               (Z?)                   |
+      //        |                |                     |
+      // (1)    |      MHTMLGenerationManager          |
+      //        |      ::OnSerializeAsMHTMLResponse    |
+      //        |                +-------------------->+
+      //        |                |                     |
+      //        |                |                    (Y)
+      //        |                |                     |
+      // (2)    |                |          MHTMLGenerationManager::Job
+      //        |                |          ::CloseFileOnFileThread
+      //        |                |                     |
+      //        |               (Z)                    |
+      //        |         test needs to inject         |
+      //        |        fast renderer shutdown        |
+      //        |      HERE - between (1) and (3)      |
+      //        |                |                     |
+      //        |                |                     |
+      //        |                +<--------------------+
+      //        |                |                     |
+      // (3)    |      MHTMLGenerationManager          |
+      //        |      ::OnFileClosed                  |
+      //        |                |                     |
+      //
+      // We hope that (Z) happens between (1) and (3) by doing the following:
+      // - From here post TaskX to UI thread.  (X) is guaranteed to happen
+      //   before timepoint (1) (because posting of (1) happens after
+      //   |return false| / before we post TaskX below).
+      // - From (X) post TaskY to FILE thread.  Because this posting is done
+      //   before (1), we can guarantee that (Y) will happen before (2).
+      // - From (Y) post TaskZ to UI thread.  Because this posting is done
+      //   before (2), we can guarantee that (Z) will happen before (3).
+      // - We cannot really guarantee that (Y) and (Z) happen *after* (1) - i.e.
+      //   execution at (Y?) and (Z?) instead is possible.  In practice,
+      //   bouncing off of UI and FILE thread does mean (Z) happens after (1).
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE, base::Bind(
+              &GenerateMHTMLAndExitRendererMessageFilter::TaskX,
+              base::Unretained(this)));
+    }
+
+    return false;
+  };
+
+  void TaskX() {
+    BrowserThread::PostTask(
+        BrowserThread::FILE, FROM_HERE, base::Bind(
+            &GenerateMHTMLAndExitRendererMessageFilter::TaskY,
+            base::Unretained(this)));
+  }
+
+  void TaskY() {
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE, base::Bind(
+            &GenerateMHTMLAndExitRendererMessageFilter::TaskZ,
+            base::Unretained(this)));
+  }
+
+  void TaskZ() {
+    render_process_host_->FastShutdownIfPossible();
+  }
+
+  RenderProcessHostImpl* render_process_host_;
+
+  DISALLOW_COPY_AND_ASSIGN(GenerateMHTMLAndExitRendererMessageFilter);
+};
+
+// Regression test for the crash/race from https://crbug.com/612098.
+IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLAndExitRenderer) {
+  NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html"));
+
+  RenderProcessHostImpl* render_process_host =
+      static_cast<RenderProcessHostImpl*>(
+          shell()->web_contents()->GetRenderProcessHost());
+  scoped_refptr<BrowserMessageFilter> filter =
+      new GenerateMHTMLAndExitRendererMessageFilter(render_process_host);
+  render_process_host->AddFilter(filter.get());
+
+  base::FilePath path(temp_dir_.path());
+  path = path.Append(FILE_PATH_LITERAL("test.mht"));
+  GenerateMHTMLForCurrentPage(MHTMLGenerationParams(path));
+
+  EXPECT_GT(ReadFileSizeFromDisk(path), 100);  // Verify the actual file size.
+}
+
 IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, InvalidPath) {
   base::FilePath path(FILE_PATH_LITERAL("/invalid/file/path"));
 
diff --git a/content/browser/download/mhtml_generation_manager.cc b/content/browser/download/mhtml_generation_manager.cc
index 60feca0..dc4ef12 100644
--- a/content/browser/download/mhtml_generation_manager.cc
+++ b/content/browser/download/mhtml_generation_manager.cc
@@ -44,11 +44,15 @@
 
   const GenerateMHTMLCallback& callback() const { return callback_; }
 
+  // Indicates whether we expect a message from the |sender| at this time.
+  // We expect only one message per frame - therefore calling this method
+  // will always clear |frame_tree_node_id_of_busy_frame_|.
+  bool IsMessageFromFrameExpected(RenderFrameHostImpl* sender);
+
   // Handler for FrameHostMsg_SerializeAsMHTMLResponse (a notification from the
   // renderer that the MHTML generation for previous frame has finished).
   // Returns |true| upon success; |false| otherwise.
   bool OnSerializeAsMHTMLResponse(
-      RenderFrameHostImpl* sender,
       const std::set<std::string>& digests_of_uris_of_serialized_resources);
 
   // Sends IPC to the renderer, asking for MHTML generation of the next frame.
@@ -75,6 +79,8 @@
                            int exit_code) override;
   void RenderProcessHostDestroyed(RenderProcessHost* host) override;
 
+  void MarkAsFinished();
+
  private:
   static int64_t CloseFileOnFileThread(base::File file);
   void AddFrame(RenderFrameHost* render_frame_host);
@@ -119,6 +125,11 @@
   // The callback to call once generation is complete.
   const GenerateMHTMLCallback callback_;
 
+  // Whether the job is finished (set to true only for the short duration of
+  // time between MHTMLGenerationManager::JobFinished is called and the job is
+  // destroyed by MHTMLGenerationManager::OnFileClosed).
+  bool is_finished_;
+
   // RAII helper for registering this Job as a RenderProcessHost observer.
   ScopedObserver<RenderProcessHost, MHTMLGenerationManager::Job>
       observed_renderer_process_host_;
@@ -136,6 +147,7 @@
       mhtml_boundary_marker_(net::GenerateMimeMultipartBoundary()),
       salt_(base::GenerateGUID()),
       callback_(callback),
+      is_finished_(false),
       observed_renderer_process_host_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   web_contents->ForEachFrame(base::Bind(
@@ -222,6 +234,15 @@
   MHTMLGenerationManager::GetInstance()->RenderProcessExited(this);
 }
 
+void MHTMLGenerationManager::Job::MarkAsFinished() {
+  DCHECK(!is_finished_);
+  is_finished_ = true;
+
+  // Stopping RenderProcessExited notifications is needed to avoid calling
+  // JobFinished twice.  See also https://crbug.com/612098.
+  observed_renderer_process_host_.RemoveAll();
+}
+
 void MHTMLGenerationManager::Job::AddFrame(RenderFrameHost* render_frame_host) {
   auto* rfhi = static_cast<RenderFrameHostImpl*>(render_frame_host);
   int frame_tree_node_id = rfhi->frame_tree_node()->frame_tree_node_id();
@@ -255,18 +276,21 @@
       callback);
 }
 
-bool MHTMLGenerationManager::Job::OnSerializeAsMHTMLResponse(
-    RenderFrameHostImpl* sender,
-    const std::set<std::string>& digests_of_uris_of_serialized_resources) {
-  // Sanitize renderer input / reject unexpected messages.
+bool MHTMLGenerationManager::Job::IsMessageFromFrameExpected(
+    RenderFrameHostImpl* sender) {
   int sender_id = sender->frame_tree_node()->frame_tree_node_id();
-  if (sender_id != frame_tree_node_id_of_busy_frame_) {
-    ReceivedBadMessage(sender->GetProcess(),
-                       bad_message::DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE);
-    return false;  // Report failure.
-  }
+  if (sender_id != frame_tree_node_id_of_busy_frame_)
+    return false;
+
+  // We only expect one message per frame - let's make sure subsequent messages
+  // from the same |sender| will be rejected.
   frame_tree_node_id_of_busy_frame_ = FrameTreeNode::kFrameTreeNodeInvalidId;
 
+  return true;
+}
+
+bool MHTMLGenerationManager::Job::OnSerializeAsMHTMLResponse(
+    const std::set<std::string>& digests_of_uris_of_serialized_resources) {
   // Renderer should be deduping resources with the same uris.
   DCHECK_EQ(0u, base::STLSetIntersection<std::set<std::string>>(
                     digests_of_already_serialized_uris_,
@@ -276,7 +300,7 @@
       digests_of_uris_of_serialized_resources.end());
 
   if (pending_frame_tree_node_ids_.empty())
-    return true;  // Report success.
+    return true;  // Report success - all frames have been processed.
 
   return SendToNextRenderFrame();
 }
@@ -323,7 +347,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   Job* job = FindJob(job_id);
-  if (!job) {
+  if (!job || !job->IsMessageFromFrameExpected(sender)) {
+    NOTREACHED();
     ReceivedBadMessage(sender->GetProcess(),
                        bad_message::DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE);
     return;
@@ -335,7 +360,7 @@
   }
 
   if (!job->OnSerializeAsMHTMLResponse(
-          sender, digests_of_uris_of_serialized_resources)) {
+          digests_of_uris_of_serialized_resources)) {
     JobFinished(job, JobStatus::FAILURE);
     return;
   }
@@ -388,6 +413,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(job);
 
+  job->MarkAsFinished();
   job->CloseFile(
       base::Bind(&MHTMLGenerationManager::OnFileClosed,
                  base::Unretained(this),  // Safe b/c |this| is a singleton.
diff --git a/content/browser/download/mhtml_generation_manager.h b/content/browser/download/mhtml_generation_manager.h
index 39dad54..50d5beb 100644
--- a/content/browser/download/mhtml_generation_manager.h
+++ b/content/browser/download/mhtml_generation_manager.h
@@ -28,6 +28,10 @@
 
 // The class and all of its members live on the UI thread.  Only static methods
 // are executed on other threads.
+//
+// MHTMLGenerationManager is a singleton.  Each call to SaveMHTML method creates
+// a new instance of MHTMLGenerationManager::Job that tracks generation of a
+// single MHTML file.
 class MHTMLGenerationManager {
  public:
   static MHTMLGenerationManager* GetInstance();
diff --git a/content/browser/download/save_file_resource_handler.cc b/content/browser/download/save_file_resource_handler.cc
index 7cba445..969e2db 100644
--- a/content/browser/download/save_file_resource_handler.cc
+++ b/content/browser/download/save_file_resource_handler.cc
@@ -60,11 +60,6 @@
   return true;
 }
 
-bool SaveFileResourceHandler::OnBeforeNetworkStart(const GURL& url,
-                                                   bool* defer) {
-  return true;
-}
-
 bool SaveFileResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                          int* buf_size,
                                          int min_size) {
diff --git a/content/browser/download/save_file_resource_handler.h b/content/browser/download/save_file_resource_handler.h
index e559e44..2ab8b2f7 100644
--- a/content/browser/download/save_file_resource_handler.h
+++ b/content/browser/download/save_file_resource_handler.h
@@ -48,9 +48,6 @@
   // Pass-through implementation.
   bool OnWillStart(const GURL& url, bool* defer) override;
 
-  // Pass-through implementation.
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
-
   // Creates a new buffer, which will be handed to the download thread for file
   // writing and deletion.
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
diff --git a/content/browser/download/save_item.cc b/content/browser/download/save_item.cc
index d19baab..820a27e 100644
--- a/content/browser/download/save_item.cc
+++ b/content/browser/download/save_item.cc
@@ -46,7 +46,7 @@
 
 // Set start state for save item.
 void SaveItem::Start() {
-  DCHECK(state_ == WAIT_START);
+  DCHECK_EQ(state_, WAIT_START);
   state_ = IN_PROGRESS;
 }
 
@@ -93,7 +93,8 @@
 }
 
 void SaveItem::SetTargetPath(const base::FilePath& full_path) {
-  DCHECK(!full_path.empty() && !has_final_name());
+  DCHECK(!full_path.empty());
+  DCHECK(!has_final_name());
   full_path_ = full_path;
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 0ddb1ac..795d4605 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1363,37 +1363,41 @@
   base::TimeTicks before_unload_end_time = renderer_before_unload_end_time;
   if (!renderer_before_unload_start_time.is_null() &&
       !renderer_before_unload_end_time.is_null()) {
-    // When passing TimeTicks across process boundaries, we need to compensate
-    // for any skew between the processes. Here we are converting the
-    // renderer's notion of before_unload_end_time to TimeTicks in the browser
-    // process. See comments in inter_process_time_ticks_converter.h for more.
     base::TimeTicks receive_before_unload_ack_time = base::TimeTicks::Now();
-    InterProcessTimeTicksConverter converter(
-        LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
-        LocalTimeTicks::FromTimeTicks(receive_before_unload_ack_time),
-        RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
-        RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
-    LocalTimeTicks browser_before_unload_end_time =
-        converter.ToLocalTimeTicks(
-            RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
-    before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
 
-    // Collect UMA on the inter-process skew.
-    bool is_skew_additive = false;
-    if (converter.IsSkewAdditiveForMetrics()) {
-      is_skew_additive = true;
-      base::TimeDelta skew = converter.GetSkewForMetrics();
-      if (skew >= base::TimeDelta()) {
-        UMA_HISTOGRAM_TIMES(
-            "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew);
-      } else {
-        UMA_HISTOGRAM_TIMES(
-            "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew);
+    if (!base::TimeTicks::IsConsistentAcrossProcesses()) {
+      // TimeTicks is not consistent across processes and we are passing
+      // TimeTicks across process boundaries so we need to compensate for any
+      // skew between the processes. Here we are converting the renderer's
+      // notion of before_unload_end_time to TimeTicks in the browser process.
+      // See comments in inter_process_time_ticks_converter.h for more.
+      InterProcessTimeTicksConverter converter(
+          LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
+          LocalTimeTicks::FromTimeTicks(receive_before_unload_ack_time),
+          RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
+          RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
+      LocalTimeTicks browser_before_unload_end_time =
+          converter.ToLocalTimeTicks(
+              RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
+      before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
+
+      // Collect UMA on the inter-process skew.
+      bool is_skew_additive = false;
+      if (converter.IsSkewAdditiveForMetrics()) {
+        is_skew_additive = true;
+        base::TimeDelta skew = converter.GetSkewForMetrics();
+        if (skew >= base::TimeDelta()) {
+          UMA_HISTOGRAM_TIMES(
+              "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew);
+        } else {
+          UMA_HISTOGRAM_TIMES(
+              "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew);
+        }
       }
+      UMA_HISTOGRAM_BOOLEAN(
+          "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
+          is_skew_additive);
     }
-    UMA_HISTOGRAM_BOOLEAN(
-        "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
-        is_skew_additive);
 
     base::TimeDelta on_before_unload_overhead_time =
         (receive_before_unload_ack_time - send_before_unload_start_time_) -
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 09f1353..15fbdb9 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -33,6 +33,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/browser_plugin_guest_mode.h"
 #include "gpu/ipc/common/gpu_messages.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/size_f.h"
 
@@ -50,7 +51,8 @@
       observing_begin_frame_source_(false),
       parent_surface_client_id_(0),
       weak_factory_(this) {
-  id_allocator_ = CreateSurfaceIdAllocator();
+  id_allocator_.reset(new cc::SurfaceIdAllocator(AllocateSurfaceClientId()));
+  GetSurfaceManager()->RegisterSurfaceClientId(id_allocator_->client_id());
   RegisterSurfaceNamespaceId();
 
   host_->SetView(this);
@@ -59,6 +61,9 @@
 RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
   if (!surface_id_.is_null())
     surface_factory_->Destroy(surface_id_);
+
+  if (GetSurfaceManager())
+    GetSurfaceManager()->InvalidateSurfaceClientId(id_allocator_->client_id());
 }
 
 void RenderWidgetHostViewChildFrame::SetCrossProcessFrameConnector(
@@ -655,6 +660,31 @@
   }
 }
 
+InputEventAckState RenderWidgetHostViewChildFrame::FilterInputEvent(
+    const blink::WebInputEvent& input_event) {
+  if (input_event.type == blink::WebInputEvent::GestureFlingStart) {
+    const blink::WebGestureEvent& gesture_event =
+        static_cast<const blink::WebGestureEvent&>(input_event);
+    // Zero-velocity touchpad flings are an Aura-specific signal that the
+    // touchpad scroll has ended, and should not be forwarded to the renderer.
+    if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
+        !gesture_event.data.flingStart.velocityX &&
+        !gesture_event.data.flingStart.velocityY) {
+      // Here we indicate that there was no consumer for this event, as
+      // otherwise the fling animation system will try to run an animation
+      // and will also expect a notification when the fling ends. Since
+      // CrOS just uses the GestureFlingStart with zero-velocity as a means
+      // of indicating that touchpad scroll has ended, we don't actually want
+      // a fling animation.
+      // Note: this event handling is modeled on similar code in
+      // TenderWidgetHostViewAura::FilterInputEvent().
+      return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+    }
+  }
+
+  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
 BrowserAccessibilityManager*
 RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
     BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h
index ebffef6..f68c944 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -150,6 +150,8 @@
   void LockCompositingSurface() override;
   void UnlockCompositingSurface() override;
 
+  InputEventAckState FilterInputEvent(
+      const blink::WebInputEvent& input_event) override;
   BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
       BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
 
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index 8263e0f6..f7abcbe 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -137,6 +137,14 @@
      "Native GpuMemoryBuffers have been disabled, either via about:flags"
      " or command line.",
      true},
+    {"vpx_decode", manager->IsFeatureBlacklisted(
+                       gpu::GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE) ||
+                       manager->IsFeatureBlacklisted(
+                           gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE),
+     command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode),
+     "Accelerated VPx video decode has been disabled, either via blacklist,"
+     " about:flags or the command line.",
+     true},
   };
   DCHECK(index < arraysize(kGpuFeatureInfo));
   *eof = (index == arraysize(kGpuFeatureInfo) - 1);
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 892b1b3c..bd57527 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -743,6 +743,14 @@
       command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
     }
   }
+
+#if defined(OS_WIN)
+  if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE) &&
+      gpu_preferences) {
+    gpu_preferences->enable_accelerated_vpx_decode = false;
+  }
+#endif
+
 #if defined(ENABLE_WEBRTC)
   if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
       !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 58fa17f..fdf434b 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -120,6 +120,7 @@
 #endif
 #if defined(OS_WIN)
   switches::kEnableAcceleratedVpxDecode,
+  switches::kEnableMFH264Encoding,
 #endif
   switches::kEnableHeapProfiling,
   switches::kEnableLogging,
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc
index 353fa45..a5bda9f 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -50,6 +50,7 @@
       host_transaction_id_(kNoTransaction),
       ipc_database_id_(kNoDatabase),
       ipc_database_callbacks_id_(kNoDatabaseCallbacks),
+      data_loss_(blink::WebIDBDataLossNone),
       sent_blocked_(false) {}
 
 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
@@ -63,6 +64,7 @@
       host_transaction_id_(kNoTransaction),
       ipc_database_id_(kNoDatabase),
       ipc_database_callbacks_id_(kNoDatabaseCallbacks),
+      data_loss_(blink::WebIDBDataLossNone),
       sent_blocked_(false) {}
 
 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
@@ -79,6 +81,7 @@
       origin_(origin),
       ipc_database_id_(kNoDatabase),
       ipc_database_callbacks_id_(ipc_database_callbacks_id),
+      data_loss_(blink::WebIDBDataLossNone),
       sent_blocked_(false) {}
 
 IndexedDBCallbacks::~IndexedDBCallbacks() {}
@@ -105,7 +108,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   std::vector<base::string16> list;
   for (unsigned i = 0; i < value.size(); ++i)
@@ -140,14 +143,11 @@
   }
 }
 
-void IndexedDBCallbacks::OnDataLoss(const IndexedDBDataLossInfo& info) {
-  data_loss_info_ = info;
-}
-
 void IndexedDBCallbacks::OnUpgradeNeeded(
     int64_t old_version,
     std::unique_ptr<IndexedDBConnection> connection,
-    const IndexedDBDatabaseMetadata& metadata) {
+    const IndexedDBDatabaseMetadata& metadata,
+    const IndexedDBDataLossInfo& data_loss_info) {
   DCHECK(dispatcher_host_.get());
 
   DCHECK_EQ(kNoCursor, ipc_cursor_id_);
@@ -155,6 +155,7 @@
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
 
+  data_loss_ = data_loss_info.status;
   dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_);
   int32_t ipc_database_id =
       dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_);
@@ -168,8 +169,8 @@
   params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
   params.old_version = old_version;
   params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
-  params.data_loss = data_loss_info_.status;
-  params.data_loss_message = data_loss_info_.message;
+  params.data_loss = data_loss_info.status;
+  params.data_loss_message = data_loss_info.message;
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
 
   if (!connection_open_start_time_.is_null()) {
@@ -340,7 +341,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   int32_t ipc_object_id = dispatcher_host_->Add(cursor.get());
   std::unique_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params(
@@ -379,7 +380,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   IndexedDBCursor* idb_cursor =
       dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
@@ -430,7 +431,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   std::vector<IndexedDBKey> msg_keys;
   std::vector<IndexedDBKey> msg_primary_keys;
@@ -488,7 +489,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   std::unique_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params(
       new IndexedDBMsg_CallbacksSuccessValue_Params());
@@ -524,7 +525,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   std::unique_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params(
       new IndexedDBMsg_CallbacksSuccessArray_Params());
@@ -568,7 +569,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
       ipc_thread_id_, ipc_callbacks_id_, value));
@@ -582,7 +583,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
       ipc_thread_id_, ipc_callbacks_id_, value));
@@ -596,7 +597,7 @@
   DCHECK_EQ(kNoTransaction, host_transaction_id_);
   DCHECK_EQ(kNoDatabase, ipc_database_id_);
   DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
-  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status);
+  DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_);
 
   dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
       ipc_thread_id_, ipc_callbacks_id_));
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h
index 683a15e7..edca2193 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -27,15 +27,11 @@
 class IndexedDBCursor;
 class IndexedDBDatabase;
 class IndexedDBDatabaseCallbacks;
+struct IndexedDBDataLossInfo;
 struct IndexedDBDatabaseMetadata;
 struct IndexedDBReturnValue;
 struct IndexedDBValue;
 
-struct IndexedDBDataLossInfo {
-  blink::WebIDBDataLoss status = blink::WebIDBDataLossNone;
-  std::string message;
-};
-
 class CONTENT_EXPORT IndexedDBCallbacks
     : public base::RefCounted<IndexedDBCallbacks> {
  public:
@@ -67,11 +63,11 @@
   virtual void OnBlocked(int64_t existing_version);
 
   // IndexedDBFactory::Open
-  virtual void OnDataLoss(const IndexedDBDataLossInfo& data_loss_info);
   virtual void OnUpgradeNeeded(
       int64_t old_version,
       std::unique_ptr<IndexedDBConnection> connection,
-      const content::IndexedDBDatabaseMetadata& metadata);
+      const content::IndexedDBDatabaseMetadata& metadata,
+      const IndexedDBDataLossInfo& data_loss_info);
   virtual void OnSuccess(std::unique_ptr<IndexedDBConnection> connection,
                          const content::IndexedDBDatabaseMetadata& metadata);
 
@@ -111,10 +107,6 @@
   // IndexedDBCursor::Continue / Advance (when complete)
   virtual void OnSuccess();
 
-  const IndexedDBDataLossInfo& data_loss_info() const {
-    return data_loss_info_;
-  }
-
   void SetConnectionOpenStartTime(const base::TimeTicks& start_time);
 
  protected:
@@ -141,7 +133,7 @@
   int32_t ipc_database_callbacks_id_;
 
   // Used to assert that OnSuccess is only called if there was no data loss.
-  IndexedDBDataLossInfo data_loss_info_;
+  blink::WebIDBDataLoss data_loss_;
 
   // The "blocked" event should be sent at most once per request.
   bool sent_blocked_;
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index d6660df..5f08c3e 100644
--- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "content/browser/indexed_db/indexed_db_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
 #include "content/browser/indexed_db/leveldb/mock_leveldb_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/content/browser/indexed_db/indexed_db_data_loss_info.h b/content/browser/indexed_db/indexed_db_data_loss_info.h
new file mode 100644
index 0000000..ed62eee2
--- /dev/null
+++ b/content/browser/indexed_db/indexed_db_data_loss_info.h
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. 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_INDEXED_DB_INDEXED_DB_DATA_LOSS_INFO_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATA_LOSS_INFO_H_
+
+#include <string>
+
+#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h"
+
+namespace content {
+
+struct IndexedDBDataLossInfo {
+  blink::WebIDBDataLoss status = blink::WebIDBDataLossNone;
+  std::string message;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATA_LOSS_INFO_H_
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index e7a98c05..995ca11 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -117,8 +117,8 @@
     : public IndexedDBDatabase::OpenOrDeleteRequest {
  public:
   OpenRequest(scoped_refptr<IndexedDBDatabase> db,
-              const IndexedDBPendingConnection& pending_connection)
-      : OpenOrDeleteRequest(db), pending_(pending_connection) {}
+              std::unique_ptr<IndexedDBPendingConnection> pending_connection)
+      : OpenOrDeleteRequest(db), pending_(std::move(pending_connection)) {}
 
   void Perform() override {
     if (db_->metadata_.id == kInvalidId) {
@@ -127,15 +127,15 @@
       if (!db_->OpenInternal().ok()) {
         // TODO(jsbell): Consider including sanitized leveldb status message.
         base::string16 message;
-        if (pending_.version == IndexedDBDatabaseMetadata::NO_VERSION) {
+        if (pending_->version == IndexedDBDatabaseMetadata::NO_VERSION) {
           message = ASCIIToUTF16(
               "Internal error opening database with no version specified.");
         } else {
           message =
               ASCIIToUTF16("Internal error opening database with version ") +
-              Int64ToString16(pending_.version);
+              Int64ToString16(pending_->version);
         }
-        pending_.callbacks->OnError(IndexedDBDatabaseError(
+        pending_->callbacks->OnError(IndexedDBDatabaseError(
             blink::WebIDBDatabaseExceptionUnknownError, message));
         db_->RequestComplete(this);
         return;
@@ -145,7 +145,7 @@
     }
 
     const int64_t old_version = db_->metadata_.version;
-    int64_t& new_version = pending_.version;
+    int64_t& new_version = pending_->version;
 
     bool is_new_database = old_version == IndexedDBDatabaseMetadata::NO_VERSION;
 
@@ -153,9 +153,9 @@
       // For unit tests only - skip upgrade steps. (Calling from script with
       // DEFAULT_VERSION throws exception.)
       DCHECK(is_new_database);
-      pending_.callbacks->OnSuccess(
-          db_->CreateConnection(pending_.database_callbacks,
-                                pending_.child_process_id),
+      pending_->callbacks->OnSuccess(
+          db_->CreateConnection(pending_->database_callbacks,
+                                pending_->child_process_id),
           db_->metadata_);
       db_->RequestComplete(this);
       return;
@@ -164,9 +164,9 @@
     if (!is_new_database &&
         (new_version == old_version ||
          new_version == IndexedDBDatabaseMetadata::NO_VERSION)) {
-      pending_.callbacks->OnSuccess(
-          db_->CreateConnection(pending_.database_callbacks,
-                                pending_.child_process_id),
+      pending_->callbacks->OnSuccess(
+          db_->CreateConnection(pending_->database_callbacks,
+                                pending_->child_process_id),
           db_->metadata_);
       db_->RequestComplete(this);
       return;
@@ -180,10 +180,10 @@
     } else if (new_version < old_version) {
       // Requested version is lower than current version - fail the request.
       DCHECK(!is_new_database);
-      pending_.callbacks->OnError(IndexedDBDatabaseError(
+      pending_->callbacks->OnError(IndexedDBDatabaseError(
           blink::WebIDBDatabaseExceptionVersionError,
           ASCIIToUTF16("The requested version (") +
-              Int64ToString16(pending_.version) +
+              Int64ToString16(pending_->version) +
               ASCIIToUTF16(") is less than the existing version (") +
               Int64ToString16(db_->metadata_.version) + ASCIIToUTF16(").")));
       db_->RequestComplete(this);
@@ -203,8 +203,7 @@
     // fired at connections that have close_pending set. A "blocked" event
     // will be fired at the request when one of the connections acks that the
     // "versionchange" event was ignored.
-    DCHECK_NE(pending_.callbacks->data_loss_info().status,
-              blink::WebIDBDataLossTotal);
+    DCHECK_NE(pending_->data_loss_info.status, blink::WebIDBDataLossTotal);
     for (const auto* connection : db_->connections_)
       connection->callbacks()->OnVersionChange(old_version, new_version);
 
@@ -212,13 +211,13 @@
   }
 
   void OnVersionChangeIgnored() const override {
-    pending_.callbacks->OnBlocked(db_->metadata_.version);
+    pending_->callbacks->OnBlocked(db_->metadata_.version);
   }
 
   void OnConnectionClosed(IndexedDBConnection* connection) override {
     // This connection closed prematurely; signal an error and complete.
-    if (connection && connection->callbacks() == pending_.database_callbacks) {
-      pending_.callbacks->OnError(
+    if (connection && connection->callbacks() == pending_->database_callbacks) {
+      pending_->callbacks->OnError(
           IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
                                  "The connection was closed."));
       db_->RequestComplete(this);
@@ -235,26 +234,27 @@
   // IndexedDBDatabase::VersionChangeOperation in order to kick the
   // transaction into the correct state.
   void StartUpgrade() {
-    connection_ = db_->CreateConnection(pending_.database_callbacks,
-                                        pending_.child_process_id);
+    connection_ = db_->CreateConnection(pending_->database_callbacks,
+                                        pending_->child_process_id);
     DCHECK_EQ(db_->connections_.count(connection_.get()), 1UL);
 
     std::vector<int64_t> object_store_ids;
     IndexedDBTransaction* transaction = db_->CreateTransaction(
-        pending_.transaction_id, connection_.get(), object_store_ids,
+        pending_->transaction_id, connection_.get(), object_store_ids,
         blink::WebIDBTransactionModeVersionChange);
 
     DCHECK(db_->transaction_coordinator_.IsRunningVersionChangeTransaction());
     transaction->ScheduleTask(
         base::Bind(&IndexedDBDatabase::VersionChangeOperation, db_,
-                   pending_.version, pending_.callbacks));
+                   pending_->version, pending_->callbacks));
   }
 
   // Called when the upgrade transaction has started executing.
   void UpgradeTransactionStarted(int64_t old_version) override {
     DCHECK(connection_);
-    pending_.callbacks->OnUpgradeNeeded(old_version, std::move(connection_),
-                                        db_->metadata_);
+    pending_->callbacks->OnUpgradeNeeded(old_version, std::move(connection_),
+                                         db_->metadata_,
+                                         pending_->data_loss_info);
   }
 
   void UpgradeTransactionFinished(bool committed) override {
@@ -262,12 +262,12 @@
     DCHECK(!connection_);
 
     if (committed) {
-      DCHECK_EQ(pending_.version, db_->metadata_.version);
-      pending_.callbacks->OnSuccess(std::unique_ptr<IndexedDBConnection>(),
-                                    db_->metadata());
+      DCHECK_EQ(pending_->version, db_->metadata_.version);
+      pending_->callbacks->OnSuccess(std::unique_ptr<IndexedDBConnection>(),
+                                     db_->metadata());
     } else {
-      DCHECK_NE(pending_.version, db_->metadata_.version);
-      pending_.callbacks->OnError(
+      DCHECK_NE(pending_->version, db_->metadata_.version);
+      pending_->callbacks->OnError(
           IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
                                  "Version change transaction was aborted in "
                                  "upgradeneeded event handler."));
@@ -276,7 +276,7 @@
   }
 
  private:
-  IndexedDBPendingConnection pending_;
+  std::unique_ptr<IndexedDBPendingConnection> pending_;
 
   // If an upgrade is needed, holds the pending connection until ownership is
   // transferred to the IndexedDBDispatcherHost via OnUpgradeNeeded.
@@ -303,7 +303,6 @@
     // close_pending set.
     const int64_t old_version = db_->metadata_.version;
     const int64_t new_version = IndexedDBDatabaseMetadata::NO_VERSION;
-    DCHECK_NE(callbacks_->data_loss_info().status, blink::WebIDBDataLossTotal);
     for (const auto* connection : db_->connections_)
       connection->callbacks()->OnVersionChange(old_version, new_version);
   }
@@ -1919,8 +1918,8 @@
 }
 
 void IndexedDBDatabase::OpenConnection(
-    const IndexedDBPendingConnection& connection) {
-  AppendRequest(base::MakeUnique<OpenRequest>(this, connection));
+    std::unique_ptr<IndexedDBPendingConnection> connection) {
+  AppendRequest(base::MakeUnique<OpenRequest>(this, std::move(connection)));
 }
 
 void IndexedDBDatabase::DeleteDatabase(
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h
index 77436fb..587d3ad 100644
--- a/content/browser/indexed_db/indexed_db_database.h
+++ b/content/browser/indexed_db/indexed_db_database.h
@@ -79,7 +79,7 @@
                 int64_t new_max_index_id);
   void RemoveIndex(int64_t object_store_id, int64_t index_id);
 
-  void OpenConnection(const IndexedDBPendingConnection& connection);
+  void OpenConnection(std::unique_ptr<IndexedDBPendingConnection> connection);
   void DeleteDatabase(scoped_refptr<IndexedDBCallbacks> callbacks);
   const IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
 
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc
index 82089c4..1f246b2 100644
--- a/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -76,10 +76,11 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id1 = 1;
-  IndexedDBPendingConnection connection1(
-      request1, callbacks1, kFakeChildProcessId, transaction_id1,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  db->OpenConnection(connection1);
+  std::unique_ptr<IndexedDBPendingConnection> connection1(
+      new IndexedDBPendingConnection(
+          request1, callbacks1, kFakeChildProcessId, transaction_id1,
+          IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  db->OpenConnection(std::move(connection1));
 
   EXPECT_FALSE(backing_store->HasOneRef());  // db, connection count > 0
 
@@ -87,10 +88,11 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id2 = 2;
-  IndexedDBPendingConnection connection2(
-      request2, callbacks2, kFakeChildProcessId, transaction_id2,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  db->OpenConnection(connection2);
+  std::unique_ptr<IndexedDBPendingConnection> connection2(
+      new IndexedDBPendingConnection(
+          request2, callbacks2, kFakeChildProcessId, transaction_id2,
+          IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  db->OpenConnection(std::move(connection2));
 
   EXPECT_FALSE(backing_store->HasOneRef());  // local and connection
 
@@ -128,10 +130,11 @@
       new MockIndexedDBDatabaseCallbacks());
   scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks());
   const int64_t upgrade_transaction_id = 3;
-  IndexedDBPendingConnection connection(
-      request, callbacks, kFakeChildProcessId, upgrade_transaction_id,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  database->OpenConnection(connection);
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(
+          request, callbacks, kFakeChildProcessId, upgrade_transaction_id,
+          IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  database->OpenConnection(std::move(connection));
   EXPECT_EQ(database.get(), request->connection()->database());
 
   const int64_t transaction_id = 123;
@@ -189,10 +192,11 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id1 = 1;
-  IndexedDBPendingConnection connection(
-      request1, callbacks1, kFakeChildProcessId, transaction_id1,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  db->OpenConnection(connection);
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(
+          request1, callbacks1, kFakeChildProcessId, transaction_id1,
+          IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  db->OpenConnection(std::move(connection));
 
   EXPECT_EQ(db->ConnectionCount(), 1UL);
   EXPECT_EQ(db->ActiveOpenDeleteCount(), 0UL);
@@ -246,9 +250,11 @@
     request_ = new MockIndexedDBCallbacks();
     callbacks_ = new MockIndexedDBDatabaseCallbacks();
     const int64_t transaction_id = 1;
-    db_->OpenConnection(IndexedDBPendingConnection(
-        request_, callbacks_, kFakeChildProcessId, transaction_id,
-        IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+    std::unique_ptr<IndexedDBPendingConnection> connection(
+        new IndexedDBPendingConnection(
+            request_, callbacks_, kFakeChildProcessId, transaction_id,
+            IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+    db_->OpenConnection(std::move(connection));
     EXPECT_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version);
 
     connection_ = base::WrapUnique(new IndexedDBConnection(db_, callbacks_));
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index eee1f7e..f6e26b5 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -379,14 +379,14 @@
   scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks =
       new IndexedDBDatabaseCallbacks(
           this, params.ipc_thread_id, params.ipc_database_callbacks_id);
-  IndexedDBPendingConnection connection(callbacks,
-                                        database_callbacks,
-                                        ipc_process_id_,
-                                        host_transaction_id,
-                                        params.version);
+  std::unique_ptr<IndexedDBPendingConnection> connection =
+      base::WrapUnique(new IndexedDBPendingConnection(
+          callbacks, database_callbacks, ipc_process_id_, host_transaction_id,
+          params.version));
   DCHECK(request_context_);
-  context()->GetIDBFactory()->Open(params.name, connection, request_context_,
-                                   params.origin, indexed_db_path);
+  context()->GetIDBFactory()->Open(params.name, std::move(connection),
+                                   request_context_, params.origin,
+                                   indexed_db_path);
 }
 
 void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h
index 3b64fb2..fd60a52 100644
--- a/content/browser/indexed_db/indexed_db_factory.h
+++ b/content/browser/indexed_db/indexed_db_factory.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <utility>
@@ -48,7 +49,7 @@
                                 const base::FilePath& data_directory,
                                 net::URLRequestContext* request_context) = 0;
   virtual void Open(const base::string16& name,
-                    const IndexedDBPendingConnection& connection,
+                    std::unique_ptr<IndexedDBPendingConnection> connection,
                     net::URLRequestContext* request_context,
                     const url::Origin& origin,
                     const base::FilePath& data_directory) = 0;
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index 1ddb6d4..de072a2 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -397,11 +397,12 @@
   return 0;
 }
 
-void IndexedDBFactoryImpl::Open(const base::string16& name,
-                                const IndexedDBPendingConnection& connection,
-                                net::URLRequestContext* request_context,
-                                const Origin& origin,
-                                const base::FilePath& data_directory) {
+void IndexedDBFactoryImpl::Open(
+    const base::string16& name,
+    std::unique_ptr<IndexedDBPendingConnection> connection,
+    net::URLRequestContext* request_context,
+    const Origin& origin,
+    const base::FilePath& data_directory) {
   IDB_TRACE("IndexedDBFactoryImpl::Open");
   scoped_refptr<IndexedDBDatabase> database;
   IndexedDBDatabase::Identifier unique_identifier(origin, name);
@@ -416,18 +417,17 @@
                          &data_loss_info, &disk_full, &s);
     if (!backing_store.get()) {
       if (disk_full) {
-        connection.callbacks->OnError(
-            IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
-                                   ASCIIToUTF16(
-                                       "Encountered full disk while opening "
-                                       "backing store for indexedDB.open.")));
+        connection->callbacks->OnError(IndexedDBDatabaseError(
+            blink::WebIDBDatabaseExceptionQuotaError,
+            ASCIIToUTF16("Encountered full disk while opening "
+                         "backing store for indexedDB.open.")));
         return;
       }
       IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
                                    ASCIIToUTF16(
                                        "Internal error opening backing store"
                                        " for indexedDB.open."));
-      connection.callbacks->OnError(error);
+      connection->callbacks->OnError(error);
       if (s.IsCorruption()) {
         HandleBackingStoreCorruption(origin, error);
       }
@@ -443,7 +443,7 @@
                                        "Internal error creating "
                                        "database backend for "
                                        "indexedDB.open."));
-      connection.callbacks->OnError(error);
+      connection->callbacks->OnError(error);
       if (s.IsCorruption()) {
         backing_store = NULL;  // Closes the LevelDB so that it can be deleted
         HandleBackingStoreCorruption(origin, error);
@@ -454,10 +454,9 @@
     database = it->second;
   }
 
-  if (data_loss_info.status != blink::WebIDBDataLossNone)
-    connection.callbacks->OnDataLoss(data_loss_info);
+  connection->data_loss_info = data_loss_info;
 
-  database->OpenConnection(connection);
+  database->OpenConnection(std::move(connection));
 
   if (!was_open && database->ConnectionCount() > 0) {
     database_map_[unique_identifier] = database.get();
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h
index 345f9282..edab2d8 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -36,7 +36,7 @@
                         const base::FilePath& data_directory,
                         net::URLRequestContext* request_context) override;
   void Open(const base::string16& name,
-            const IndexedDBPendingConnection& connection,
+            std::unique_ptr<IndexedDBPendingConnection> connection,
             net::URLRequestContext* request_context,
             const url::Origin& origin,
             const base::FilePath& data_directory) override;
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 3baab1d..bc57a9d 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -253,12 +253,12 @@
   scoped_refptr<IndexedDBDatabaseCallbacks> dummy_database_callbacks =
       new IndexedDBDatabaseCallbacks(NULL, 0, 0);
   const base::string16 name(ASCIIToUTF16("name"));
-  IndexedDBPendingConnection connection(callbacks,
-                                        dummy_database_callbacks,
-                                        0, /* child_process_id */
-                                        2, /* transaction_id */
-                                        1 /* version */);
-  factory->Open(name, connection, NULL /* request_context */, origin,
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(callbacks, dummy_database_callbacks,
+                                     0, /* child_process_id */
+                                     2, /* transaction_id */
+                                     1 /* version */));
+  factory->Open(name, std::move(connection), NULL /* request_context */, origin,
                 temp_directory.path());
   EXPECT_TRUE(callbacks->error_called());
 }
@@ -273,11 +273,12 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id = 1;
-  IndexedDBPendingConnection connection(
-      callbacks, db_callbacks, 0, /* child_process_id */
-      transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  factory()->Open(ASCIIToUTF16("db"), connection, NULL /* request_context */,
-                  origin, temp_directory.path());
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(
+          callbacks, db_callbacks, 0, /* child_process_id */
+          transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  factory()->Open(ASCIIToUTF16("db"), std::move(connection),
+                  NULL /* request_context */, origin, temp_directory.path());
 
   EXPECT_TRUE(callbacks->connection());
 
@@ -300,11 +301,12 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id = 1;
-  IndexedDBPendingConnection connection(
-      callbacks, db_callbacks, 0, /* child_process_id */
-      transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  factory()->Open(ASCIIToUTF16("db"), connection, NULL /* request_context */,
-                  origin, temp_directory.path());
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(
+          callbacks, db_callbacks, 0, /* child_process_id */
+          transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  factory()->Open(ASCIIToUTF16("db"), std::move(connection),
+                  NULL /* request_context */, origin, temp_directory.path());
 
   EXPECT_TRUE(callbacks->connection());
   IndexedDBBackingStore* store =
@@ -386,11 +388,12 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id = 1;
-  IndexedDBPendingConnection connection(
-      callbacks, db_callbacks, 0, /* child_process_id */
-      transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  factory()->Open(ASCIIToUTF16("db"), connection, NULL /* request_context */,
-                  origin, temp_directory.path());
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(
+          callbacks, db_callbacks, 0, /* child_process_id */
+          transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  factory()->Open(ASCIIToUTF16("db"), std::move(connection),
+                  NULL /* request_context */, origin, temp_directory.path());
 
   EXPECT_TRUE(callbacks->connection());
   EXPECT_TRUE(factory()->IsBackingStoreOpen(origin));
@@ -420,10 +423,10 @@
     EXPECT_FALSE(connection.get());
   }
 
-  void OnUpgradeNeeded(
-      int64_t old_version,
-      std::unique_ptr<IndexedDBConnection> connection,
-      const content::IndexedDBDatabaseMetadata& metadata) override {
+  void OnUpgradeNeeded(int64_t old_version,
+                       std::unique_ptr<IndexedDBConnection> connection,
+                       const content::IndexedDBDatabaseMetadata& metadata,
+                       const IndexedDBDataLossInfo& data_loss_info) override {
     connection_ = std::move(connection);
   }
 
@@ -466,13 +469,12 @@
   {
     scoped_refptr<MockIndexedDBCallbacks> callbacks(
         new UpgradeNeededCallbacks());
-    IndexedDBPendingConnection connection(callbacks,
-                                          db_callbacks,
-                                          0, /* child_process_id */
-                                          transaction_id,
-                                          db_version);
-    factory()->Open(db_name, connection, NULL /* request_context */, origin,
-                    temp_directory.path());
+    std::unique_ptr<IndexedDBPendingConnection> connection(
+        new IndexedDBPendingConnection(callbacks, db_callbacks,
+                                       0, /* child_process_id */
+                                       transaction_id, db_version));
+    factory()->Open(db_name, std::move(connection), NULL /* request_context */,
+                    origin, temp_directory.path());
     EXPECT_TRUE(factory()->IsDatabaseOpen(origin, db_name));
 
     // Pump the message loop so the upgrade transaction can run.
@@ -488,13 +490,12 @@
   // the database object.
   {
     scoped_refptr<ErrorCallbacks> callbacks(new ErrorCallbacks());
-    IndexedDBPendingConnection connection(callbacks,
-                                          db_callbacks,
-                                          0, /* child_process_id */
-                                          transaction_id,
-                                          db_version - 1);
-    factory()->Open(db_name, connection, NULL /* request_context */, origin,
-                    temp_directory.path());
+    std::unique_ptr<IndexedDBPendingConnection> connection(
+        new IndexedDBPendingConnection(callbacks, db_callbacks,
+                                       0, /* child_process_id */
+                                       transaction_id, db_version - 1));
+    factory()->Open(db_name, std::move(connection), NULL /* request_context */,
+                    origin, temp_directory.path());
     EXPECT_TRUE(callbacks->saw_error());
     EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name));
   }
diff --git a/content/browser/indexed_db/indexed_db_pending_connection.h b/content/browser/indexed_db/indexed_db_pending_connection.h
index 10e1b05d..6458a7e 100644
--- a/content/browser/indexed_db/indexed_db_pending_connection.h
+++ b/content/browser/indexed_db/indexed_db_pending_connection.h
@@ -9,6 +9,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "content/browser/indexed_db/indexed_db_callbacks.h"
+#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
 #include "content/common/content_export.h"
 
@@ -31,6 +32,7 @@
   int child_process_id;
   int64_t transaction_id;
   int64_t version;
+  IndexedDBDataLossInfo data_loss_info;
 };
 
 }  // namespace content
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
index b3736a50..88ceb26 100644
--- a/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -193,20 +193,18 @@
 
     test_path = idb_context->GetFilePathForTesting(kTestOrigin);
 
-    IndexedDBPendingConnection open_connection(open_callbacks,
-                                               open_db_callbacks,
-                                               0 /* child_process_id */,
-                                               0 /* host_transaction_id */,
-                                               0 /* version */);
-    factory->Open(base::ASCIIToUTF16("opendb"), open_connection,
+    std::unique_ptr<IndexedDBPendingConnection> open_connection(
+        new IndexedDBPendingConnection(
+            open_callbacks, open_db_callbacks, 0 /* child_process_id */,
+            0 /* host_transaction_id */, 0 /* version */));
+    factory->Open(base::ASCIIToUTF16("opendb"), std::move(open_connection),
                   NULL /* request_context */, Origin(kTestOrigin),
                   idb_context->data_path());
-    IndexedDBPendingConnection closed_connection(closed_callbacks,
-                                                 closed_db_callbacks,
-                                                 0 /* child_process_id */,
-                                                 0 /* host_transaction_id */,
-                                                 0 /* version */);
-    factory->Open(base::ASCIIToUTF16("closeddb"), closed_connection,
+    std::unique_ptr<IndexedDBPendingConnection> closed_connection(
+        new IndexedDBPendingConnection(
+            closed_callbacks, closed_db_callbacks, 0 /* child_process_id */,
+            0 /* host_transaction_id */, 0 /* version */));
+    factory->Open(base::ASCIIToUTF16("closeddb"), std::move(closed_connection),
                   NULL /* request_context */, Origin(kTestOrigin),
                   idb_context->data_path());
 
@@ -274,10 +272,11 @@
   scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
       new MockIndexedDBDatabaseCallbacks());
   const int64_t transaction_id = 1;
-  IndexedDBPendingConnection connection(
-      callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
-      IndexedDBDatabaseMetadata::DEFAULT_VERSION);
-  factory->Open(base::ASCIIToUTF16("db"), connection,
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      new IndexedDBPendingConnection(
+          callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
+          IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  factory->Open(base::ASCIIToUTF16("db"), std::move(connection),
                 NULL /* request_context */, Origin(kTestOrigin),
                 temp_dir.path());
 
diff --git a/content/browser/indexed_db/mock_indexed_db_factory.h b/content/browser/indexed_db/mock_indexed_db_factory.h
index ca073516..c15f12d3 100644
--- a/content/browser/indexed_db/mock_indexed_db_factory.h
+++ b/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -26,12 +26,20 @@
                     const url::Origin& origin,
                     const base::FilePath& data_directory,
                     net::URLRequestContext* request_context));
-  MOCK_METHOD5(Open,
+  MOCK_METHOD5(OpenProxy,
                void(const base::string16& name,
-                    const IndexedDBPendingConnection& connection,
+                    IndexedDBPendingConnection* connection,
                     net::URLRequestContext* request_context,
                     const url::Origin& origin,
                     const base::FilePath& data_directory));
+  // Googlemock can't deal with move-only types, so *Proxy() is a workaround.
+  virtual void Open(const base::string16& name,
+                    std::unique_ptr<IndexedDBPendingConnection> connection,
+                    net::URLRequestContext* request_context,
+                    const url::Origin& origin,
+                    const base::FilePath& data_directory) {
+    OpenProxy(name, connection.get(), request_context, origin, data_directory);
+  }
   MOCK_METHOD5(DeleteDatabase,
                void(const base::string16& name,
                     net::URLRequestContext* request_context,
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index 41e14eb..19e0868 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -411,10 +411,6 @@
   return true;
 }
 
-bool AsyncResourceHandler::OnBeforeNetworkStart(const GURL& url, bool* defer) {
-  return true;
-}
-
 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                       int* buf_size,
                                       int min_size) {
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h
index c087f16..c8c72581 100644
--- a/content/browser/loader/async_resource_handler.h
+++ b/content/browser/loader/async_resource_handler.h
@@ -46,7 +46,6 @@
                            bool* defer) override;
   bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
   bool OnWillStart(const GURL& url, bool* defer) override;
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override;
diff --git a/content/browser/loader/detachable_resource_handler.cc b/content/browser/loader/detachable_resource_handler.cc
index 4e1bb8a..82544549 100644
--- a/content/browser/loader/detachable_resource_handler.cc
+++ b/content/browser/loader/detachable_resource_handler.cc
@@ -128,19 +128,6 @@
   return ret;
 }
 
-bool DetachableResourceHandler::OnBeforeNetworkStart(const GURL& url,
-                                                     bool* defer) {
-  DCHECK(!is_deferred_);
-
-  if (!next_handler_)
-    return true;
-
-  bool ret =
-      next_handler_->OnBeforeNetworkStart(url, &is_deferred_);
-  *defer = is_deferred_;
-  return ret;
-}
-
 bool DetachableResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                            int* buf_size,
                                            int min_size) {
diff --git a/content/browser/loader/detachable_resource_handler.h b/content/browser/loader/detachable_resource_handler.h
index 5db9a1597..6f913520 100644
--- a/content/browser/loader/detachable_resource_handler.h
+++ b/content/browser/loader/detachable_resource_handler.h
@@ -54,7 +54,6 @@
                            bool* defer) override;
   bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
   bool OnWillStart(const GURL& url, bool* defer) override;
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override;
diff --git a/content/browser/loader/layered_resource_handler.cc b/content/browser/loader/layered_resource_handler.cc
index eada59a..0f584bc 100644
--- a/content/browser/loader/layered_resource_handler.cc
+++ b/content/browser/loader/layered_resource_handler.cc
@@ -49,12 +49,6 @@
   return next_handler_->OnWillStart(url, defer);
 }
 
-bool LayeredResourceHandler::OnBeforeNetworkStart(const GURL& url,
-                                                  bool* defer) {
-  DCHECK(next_handler_.get());
-  return next_handler_->OnBeforeNetworkStart(url, defer);
-}
-
 bool LayeredResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                         int* buf_size,
                                         int min_size) {
diff --git a/content/browser/loader/layered_resource_handler.h b/content/browser/loader/layered_resource_handler.h
index a71b40c..7503a9a7 100644
--- a/content/browser/loader/layered_resource_handler.h
+++ b/content/browser/loader/layered_resource_handler.h
@@ -31,7 +31,6 @@
                            bool* defer) override;
   bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
   bool OnWillStart(const GURL& url, bool* defer) override;
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override;
diff --git a/content/browser/loader/mime_type_resource_handler_unittest.cc b/content/browser/loader/mime_type_resource_handler_unittest.cc
index 6bed3a8..8c6f6e3 100644
--- a/content/browser/loader/mime_type_resource_handler_unittest.cc
+++ b/content/browser/loader/mime_type_resource_handler_unittest.cc
@@ -52,11 +52,6 @@
     return false;
   }
 
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
-    NOTREACHED();
-    return false;
-  }
-
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override {
diff --git a/content/browser/loader/navigation_resource_handler.cc b/content/browser/loader/navigation_resource_handler.cc
index 82c5c06..d7d65c4 100644
--- a/content/browser/loader/navigation_resource_handler.cc
+++ b/content/browser/loader/navigation_resource_handler.cc
@@ -121,11 +121,6 @@
   return true;
 }
 
-bool NavigationResourceHandler::OnBeforeNetworkStart(const GURL& url,
-                                                     bool* defer) {
-  return true;
-}
-
 bool NavigationResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                            int* buf_size,
                                            int min_size) {
diff --git a/content/browser/loader/navigation_resource_handler.h b/content/browser/loader/navigation_resource_handler.h
index cf8fc02..48c8625 100644
--- a/content/browser/loader/navigation_resource_handler.h
+++ b/content/browser/loader/navigation_resource_handler.h
@@ -39,7 +39,6 @@
                            bool* defer) override;
   bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
   bool OnWillStart(const GURL& url, bool* defer) override;
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override;
diff --git a/content/browser/loader/resource_handler.h b/content/browser/loader/resource_handler.h
index caf9a7a..ee9b3b6 100644
--- a/content/browser/loader/resource_handler.h
+++ b/content/browser/loader/resource_handler.h
@@ -67,13 +67,6 @@
   // ResourceDispatcherHost::StartDeferredRequest().
   virtual bool OnWillStart(const GURL& url, bool* defer) = 0;
 
-  // Called before the net::URLRequest (whose url is |url|} uses the network for
-  // the first time to load the resource. If the handler returns false, then the
-  // request is cancelled. Otherwise if the return value is true, the
-  // ResourceHandler can delay the request from starting by setting |*defer =
-  // true|. Call controller()->Resume() to continue if deferred.
-  virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) = 0;
-
   // Data will be read for the response.  Upon success, this method places the
   // size and address of the buffer where the data is to be written in its
   // out-params.  This call will be followed by either OnReadCompleted (on
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc
index e5a3419..766177c 100644
--- a/content/browser/loader/resource_loader_unittest.cc
+++ b/content/browser/loader/resource_loader_unittest.cc
@@ -352,10 +352,6 @@
     return true;
   }
 
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
-    return true;
-  }
-
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override {
diff --git a/content/browser/loader/stream_resource_handler.cc b/content/browser/loader/stream_resource_handler.cc
index daf41e5..a910cbf 100644
--- a/content/browser/loader/stream_resource_handler.cc
+++ b/content/browser/loader/stream_resource_handler.cc
@@ -39,10 +39,6 @@
   return true;
 }
 
-bool StreamResourceHandler::OnBeforeNetworkStart(const GURL& url, bool* defer) {
-  return true;
-}
-
 bool StreamResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                        int* buf_size,
                                        int min_size) {
diff --git a/content/browser/loader/stream_resource_handler.h b/content/browser/loader/stream_resource_handler.h
index 42c71e8f..a14c6c3 100644
--- a/content/browser/loader/stream_resource_handler.h
+++ b/content/browser/loader/stream_resource_handler.h
@@ -42,8 +42,6 @@
 
   bool OnWillStart(const GURL& url, bool* defer) override;
 
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
-
   // Create a new buffer to store received data.
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
index c4217b29..9bee602e 100644
--- a/content/browser/loader/sync_resource_handler.cc
+++ b/content/browser/loader/sync_resource_handler.cc
@@ -95,10 +95,6 @@
   return true;
 }
 
-bool SyncResourceHandler::OnBeforeNetworkStart(const GURL& url, bool* defer) {
-  return true;
-}
-
 bool SyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                                      int* buf_size,
                                      int min_size) {
diff --git a/content/browser/loader/sync_resource_handler.h b/content/browser/loader/sync_resource_handler.h
index 49b0d91..dffc511 100644
--- a/content/browser/loader/sync_resource_handler.h
+++ b/content/browser/loader/sync_resource_handler.h
@@ -40,7 +40,6 @@
                            bool* defer) override;
   bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
   bool OnWillStart(const GURL& url, bool* defer) override;
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
   bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                   int* buf_size,
                   int min_size) override;
diff --git a/content/browser/loader/throttling_resource_handler.cc b/content/browser/loader/throttling_resource_handler.cc
index 99d84e6..cf8ad22 100644
--- a/content/browser/loader/throttling_resource_handler.cc
+++ b/content/browser/loader/throttling_resource_handler.cc
@@ -83,30 +83,6 @@
   return next_handler_->OnWillStart(url, defer);
 }
 
-bool ThrottlingResourceHandler::OnBeforeNetworkStart(const GURL& url,
-                                                     bool* defer) {
-  DCHECK(!cancelled_by_resource_throttle_);
-
-  *defer = false;
-  while (next_index_ < throttles_.size()) {
-    int index = next_index_;
-    throttles_[index]->WillStartUsingNetwork(defer);
-    next_index_++;
-    if (cancelled_by_resource_throttle_)
-      return false;
-    if (*defer) {
-      OnRequestDefered(index);
-      deferred_stage_ = DEFERRED_NETWORK_START;
-      deferred_url_ = url;
-      return true;  // Do not cancel.
-    }
-  }
-
-  next_index_ = 0;  // Reset for next time.
-
-  return next_handler_->OnBeforeNetworkStart(url, defer);
-}
-
 bool ThrottlingResourceHandler::OnResponseStarted(ResourceResponse* response,
                                                   bool* defer) {
   DCHECK(!cancelled_by_resource_throttle_);
@@ -159,9 +135,6 @@
     case DEFERRED_START:
       ResumeStart();
       break;
-    case DEFERRED_NETWORK_START:
-      ResumeNetworkStart();
-      break;
     case DEFERRED_REDIRECT:
       ResumeRedirect();
       break;
@@ -185,20 +158,6 @@
   }
 }
 
-void ThrottlingResourceHandler::ResumeNetworkStart() {
-  DCHECK(!cancelled_by_resource_throttle_);
-
-  GURL url = deferred_url_;
-  deferred_url_ = GURL();
-
-  bool defer = false;
-  if (!OnBeforeNetworkStart(url, &defer)) {
-    controller()->Cancel();
-  } else if (!defer) {
-    controller()->Resume();
-  }
-}
-
 void ThrottlingResourceHandler::ResumeRedirect() {
   DCHECK(!cancelled_by_resource_throttle_);
 
diff --git a/content/browser/loader/throttling_resource_handler.h b/content/browser/loader/throttling_resource_handler.h
index 32cc6fa..4341515 100644
--- a/content/browser/loader/throttling_resource_handler.h
+++ b/content/browser/loader/throttling_resource_handler.h
@@ -39,7 +39,6 @@
                            bool* defer) override;
   bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
   bool OnWillStart(const GURL& url, bool* defer) override;
-  bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
 
   // ResourceController implementation:
   void Cancel() override;
@@ -49,7 +48,6 @@
 
  private:
   void ResumeStart();
-  void ResumeNetworkStart();
   void ResumeRedirect();
   void ResumeResponse();
 
@@ -60,7 +58,6 @@
   enum DeferredStage {
     DEFERRED_NONE,
     DEFERRED_START,
-    DEFERRED_NETWORK_START,
     DEFERRED_REDIRECT,
     DEFERRED_RESPONSE
   };
diff --git a/content/browser/media/capture/image_capture_impl.cc b/content/browser/media/capture/image_capture_impl.cc
index 9941b7b..269d90f 100644
--- a/content/browser/media/capture/image_capture_impl.cc
+++ b/content/browser/media/capture/image_capture_impl.cc
@@ -51,19 +51,15 @@
 
 void RunTakePhotoCallbackOnUIThread(
     const ImageCaptureImpl::TakePhotoCallback& callback,
-    const std::string& mime_type,
-    const std::vector<uint8_t>& data) {
-  // TODO(mcasas): Use a mojo typemapping instead of const_cast to avoid copying
-  // |data|, https://crbug.com/630040.
+    media::mojom::BlobPtr blob) {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(callback, mime_type,
-                 base::Passed(const_cast<std::vector<uint8_t>*>(&data))));
+      base::Bind(callback, base::Passed(std::move(blob))));
 }
 
 void RunFailedTakePhotoCallback(const ImageCaptureImpl::TakePhotoCallback& cb) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  cb.Run("", std::vector<uint8_t>());
+  cb.Run(media::mojom::Blob::New());
 }
 
 void GetCapabilitiesOnIOThread(
diff --git a/content/browser/media/webrtc/webrtc_browsertest.cc b/content/browser/media/webrtc/webrtc_browsertest.cc
index 7a9fc3d..14cc4223 100644
--- a/content/browser/media/webrtc/webrtc_browsertest.cc
+++ b/content/browser/media/webrtc/webrtc_browsertest.cc
@@ -45,27 +45,6 @@
   void MakeTypicalPeerConnectionCall(const std::string& javascript) {
     MakeTypicalCall(javascript, "/media/peerconnection-call.html");
   }
-
-  // Convenience method for making calls that detect if audio os playing (which
-  // has some special prerequisites, such that there needs to be an audio output
-  // device on the executing machine).
-  void MakeAudioDetectingPeerConnectionCall(const std::string& javascript) {
-    if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
-      // Bots with no output devices will force the audio code into a state
-      // where it doesn't manage to set either the low or high latency path.
-      // This test will compute useless values in that case, so skip running on
-      // such bots (see crbug.com/326338).
-      LOG(INFO) << "Missing output devices: skipping test...";
-      return;
-    }
-
-    ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kUseFakeDeviceForMediaStream))
-            << "Must run with fake devices since the test will explicitly look "
-            << "for the fake device signal.";
-
-    MakeTypicalPeerConnectionCall(javascript);
-  }
 };
 
 // These tests will make a complete PeerConnection-based call and verify that
@@ -134,21 +113,13 @@
   MakeTypicalPeerConnectionCall(kJavascript);
 }
 
-// Causes asserts in libjingle: http://crbug.com/484826.
 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       DISABLED_CanMakeAudioCallAndThenRenegotiateToVideo) {
+                       CanMakeAudioCallAndThenRenegotiateToVideo) {
   const char* kJavascript =
       "callAndRenegotiateToVideo({audio: true}, {audio: true, video:true});";
   MakeTypicalPeerConnectionCall(kJavascript);
 }
 
-// Causes asserts in libjingle: http://crbug.com/484826.
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       DISABLED_CanMakeVideoCallAndThenRenegotiateToAudio) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndRenegotiateToAudio({audio: true, video:true}, {audio: true});");
-}
-
 // This test makes a call between pc1 and pc2 where a video only stream is sent
 // from pc1 to pc2. The stream sent from pc1 to pc2 is cloned from the stream
 // received on pc2 to test that cloning of remote video and audio tracks works
@@ -219,54 +190,6 @@
   MakeTypicalPeerConnectionCall("addTwoMediaStreamsToOneConnection();");
 }
 
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureAudioIsPlaying({audio:true, video:true});");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureAudioIsPlaying({audio:true});");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EstablishIsac16KCallAndEnsureAudioIsPlaying) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callWithIsac16KAndEnsureAudioIsPlaying({audio:true});");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EstablishAudioVideoCallAndVerifyRemoteMutingWorks) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureRemoteAudioTrackMutingWorks();");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EstablishAudioVideoCallAndVerifyLocalMutingWorks) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureLocalAudioTrackMutingWorks();");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EnsureLocalVideoMuteDoesntMuteAudio) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureLocalVideoMutingDoesntMuteAudio();");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EnsureRemoteVideoMuteDoesntMuteAudio) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureRemoteVideoMutingDoesntMuteAudio();");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
-                       EstablishAudioVideoCallAndVerifyUnmutingWorks) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureAudioTrackUnmutingWorks();");
-}
-
 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, CallAndVerifyVideoMutingWorks) {
   MakeTypicalPeerConnectionCall("callAndEnsureVideoTrackMutingWorks();");
 }
diff --git a/content/browser/media/webrtc/webrtc_browsertest_audio.cc b/content/browser/media/webrtc/webrtc_browsertest_audio.cc
new file mode 100644
index 0000000..a321e451
--- /dev/null
+++ b/content/browser/media/webrtc/webrtc_browsertest_audio.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/webrtc_ip_handling_policy.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/test/webrtc_content_browsertest_base.h"
+#include "media/audio/audio_manager.h"
+#include "media/base/media_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace content {
+
+#if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
+// Renderer crashes under Android ASAN: https://crbug.com/408496.
+#define MAYBE_WebRtcBrowserAudioTest DISABLED_WebRtcBrowserAudioTest
+#else
+#define MAYBE_WebRtcBrowserAudioTest WebRtcBrowserAudioTest
+#endif
+
+// This class tests the scenario when permission to access mic or camera is
+// granted.
+class MAYBE_WebRtcBrowserAudioTest : public WebRtcContentBrowserTest {
+ public:
+  MAYBE_WebRtcBrowserAudioTest() {}
+  ~MAYBE_WebRtcBrowserAudioTest() override {}
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    WebRtcContentBrowserTest::SetUpCommandLine(command_line);
+    // Automatically grant device permission.
+    AppendUseFakeUIForMediaStreamFlag();
+  }
+
+ protected:
+  // Convenience method for making calls that detect if audio os playing (which
+  // has some special prerequisites, such that there needs to be an audio output
+  // device on the executing machine).
+  void MakeAudioDetectingPeerConnectionCall(const std::string& javascript) {
+    if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+      // Bots with no output devices will force the audio code into a state
+      // where it doesn't manage to set either the low or high latency path.
+      // This test will compute useless values in that case, so skip running on
+      // such bots (see crbug.com/326338).
+      LOG(INFO) << "Missing output devices: skipping test...";
+      return;
+    }
+
+    ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kUseFakeDeviceForMediaStream))
+            << "Must run with fake devices since the test will explicitly look "
+            << "for the fake device signal.";
+
+    MakeTypicalCall(javascript, "/media/peerconnection-call-audio.html");
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       CanMakeVideoCallAndThenRenegotiateToAudio) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndRenegotiateToAudio({audio: true, video:true}, {audio: true});");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureAudioIsPlaying({audio:true, video:true});");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureAudioIsPlaying({audio:true});");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EstablishIsac16KCallAndEnsureAudioIsPlaying) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callWithIsac16KAndEnsureAudioIsPlaying({audio:true});");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EstablishAudioVideoCallAndVerifyRemoteMutingWorks) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureRemoteAudioTrackMutingWorks();");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EstablishAudioVideoCallAndVerifyLocalMutingWorks) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureLocalAudioTrackMutingWorks();");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EnsureLocalVideoMuteDoesntMuteAudio) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureLocalVideoMutingDoesntMuteAudio();");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EnsureRemoteVideoMuteDoesntMuteAudio) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureRemoteVideoMutingDoesntMuteAudio();");
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserAudioTest,
+                       EstablishAudioVideoCallAndVerifyUnmutingWorks) {
+  MakeAudioDetectingPeerConnectionCall(
+      "callAndEnsureAudioTrackUnmutingWorks();");
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index d563c6f..c06a342 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -337,14 +337,8 @@
 }
 
 // static
-std::unique_ptr<cc::SurfaceIdAllocator>
-CompositorImpl::CreateSurfaceIdAllocator() {
-  std::unique_ptr<cc::SurfaceIdAllocator> allocator(
-      new cc::SurfaceIdAllocator(++g_surface_client_id));
-  cc::SurfaceManager* manager = GetSurfaceManager();
-  DCHECK(manager);
-  allocator->RegisterSurfaceClientId(manager);
-  return allocator;
+uint32_t CompositorImpl::AllocateSurfaceClientId() {
+  return ++g_surface_client_id;
 }
 
 // static
@@ -363,7 +357,8 @@
 
 CompositorImpl::CompositorImpl(CompositorClient* client,
                                gfx::NativeWindow root_window)
-    : surface_id_allocator_(CreateSurfaceIdAllocator()),
+    : surface_id_allocator_(
+          new cc::SurfaceIdAllocator(AllocateSurfaceClientId())),
       resource_manager_(root_window),
       has_transparent_background_(false),
       device_scale_factor_(1),
@@ -377,6 +372,8 @@
       output_surface_request_pending_(false),
       needs_begin_frames_(false),
       weak_factory_(this) {
+  GetSurfaceManager()->RegisterSurfaceClientId(
+      surface_id_allocator_->client_id());
   DCHECK(client);
   DCHECK(root_window);
   DCHECK(root_window->GetLayer() == nullptr);
@@ -391,6 +388,8 @@
   root_window_->SetLayer(nullptr);
   // Clean-up any surface references.
   SetSurface(NULL);
+  GetSurfaceManager()->InvalidateSurfaceClientId(
+      surface_id_allocator_->client_id());
 }
 
 ui::UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 3bc86da..e77dd91 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -64,7 +64,7 @@
   static bool IsInitialized();
 
   static cc::SurfaceManager* GetSurfaceManager();
-  static std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator();
+  static uint32_t AllocateSurfaceClientId();
 
   static scoped_refptr<cc::VulkanInProcessContextProvider>
   SharedVulkanContextProviderAndroid();
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index f2801e5..626ce81 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -75,7 +75,10 @@
       delegated_frame_evictor_(new DelegatedFrameEvictor(this)) {
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
   factory->GetContextFactory()->AddObserver(this);
-  id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator();
+  id_allocator_.reset(new cc::SurfaceIdAllocator(
+      factory->GetContextFactory()->AllocateSurfaceClientId()));
+  factory->GetSurfaceManager()->RegisterSurfaceClientId(
+      id_allocator_->client_id());
   factory->GetSurfaceManager()->RegisterSurfaceFactoryClient(
       id_allocator_->client_id(), this);
 }
@@ -818,6 +821,8 @@
     surface_factory_->Destroy(surface_id_);
   factory->GetSurfaceManager()->UnregisterSurfaceFactoryClient(
       id_allocator_->client_id());
+  factory->GetSurfaceManager()->InvalidateSurfaceClientId(
+      id_allocator_->client_id());
 
   DCHECK(!vsync_manager_.get());
 }
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index ab6ab3e5..cf7e7cd 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -429,6 +429,12 @@
 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
                                       const ui::LatencyInfo& latency_info,
                                       InputEventDispatchType dispatch_type) {
+  DCHECK(input_event.type != blink::WebInputEvent::GestureFlingStart ||
+         static_cast<const blink::WebGestureEvent&>(input_event)
+                 .data.flingStart.velocityX != 0.0 ||
+         static_cast<const blink::WebGestureEvent&>(input_event)
+                 .data.flingStart.velocityY != 0.0);
+
   // This conversion is temporary. WebInputEvent should be generated
   // directly from ui::Event with the viewport coordinates. See
   // crbug.com/563730.
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.cc b/content/browser/renderer_host/input/synthetic_pointer_action.cc
index f19e8f6a..76eb443 100644
--- a/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -65,7 +65,7 @@
 
 bool SyntheticPointerAction::UserInputCheck(
     const SyntheticPointerActionParams& params) {
-  if (params.index() < 0 || params.index() >= WebTouchEvent::touchesLengthCap)
+  if (params.index() < 0 || params.index() >= WebTouchEvent::kTouchesLengthCap)
     return false;
 
   if (synthetic_pointer_->SourceType() != params.gesture_source_type)
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.h b/content/browser/renderer_host/input/synthetic_pointer_action.h
index 683d1b7..a87ef73 100644
--- a/content/browser/renderer_host/input/synthetic_pointer_action.h
+++ b/content/browser/renderer_host/input/synthetic_pointer_action.h
@@ -19,7 +19,7 @@
 
 class CONTENT_EXPORT SyntheticPointerAction : public SyntheticGesture {
  public:
-  using IndexMap = std::array<int, WebTouchEvent::touchesLengthCap>;
+  using IndexMap = std::array<int, WebTouchEvent::kTouchesLengthCap>;
 
   SyntheticPointerAction(
       std::unique_ptr<std::vector<SyntheticPointerActionParams>> param_list,
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
index 06701fdb..9bee51c6 100644
--- a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -79,10 +79,10 @@
   unsigned touch_length() const { return touch_length_; }
 
  private:
-  gfx::PointF positions_[WebTouchEvent::touchesLengthCap];
+  gfx::PointF positions_[WebTouchEvent::kTouchesLengthCap];
   unsigned touch_length_;
-  int indexes_[WebTouchEvent::touchesLengthCap];
-  WebTouchPoint::State states_[WebTouchEvent::touchesLengthCap];
+  int indexes_[WebTouchEvent::kTouchesLengthCap];
+  WebTouchPoint::State states_[WebTouchEvent::kTouchesLengthCap];
 };
 
 class SyntheticPointerActionTest : public testing::Test {
diff --git a/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/content/browser/renderer_host/input/touch_event_queue_unittest.cc
index 84f7560b..d5dccf4 100644
--- a/content/browser/renderer_host/input/touch_event_queue_unittest.cc
+++ b/content/browser/renderer_host/input/touch_event_queue_unittest.cc
@@ -189,7 +189,7 @@
 
   void ChangeTouchPointRadius(int index, float radius_x, float radius_y) {
     CHECK_GE(index, 0);
-    CHECK_LT(index, touch_event_.touchesLengthCap);
+    CHECK_LT(index, touch_event_.kTouchesLengthCap);
     WebTouchPoint& point = touch_event_.touches[index];
     point.radiusX = radius_x;
     point.radiusY = radius_y;
@@ -203,7 +203,7 @@
 
   void ChangeTouchPointRotationAngle(int index, float rotation_angle) {
     CHECK_GE(index, 0);
-    CHECK_LT(index, touch_event_.touchesLengthCap);
+    CHECK_LT(index, touch_event_.kTouchesLengthCap);
     WebTouchPoint& point = touch_event_.touches[index];
     point.rotationAngle = rotation_angle;
     touch_event_.touches[index].state = WebTouchPoint::StateMoved;
@@ -216,7 +216,7 @@
 
   void ChangeTouchPointForce(int index, float force) {
     CHECK_GE(index, 0);
-    CHECK_LT(index, touch_event_.touchesLengthCap);
+    CHECK_LT(index, touch_event_.kTouchesLengthCap);
     WebTouchPoint& point = touch_event_.touches[index];
     point.force = force;
     touch_event_.touches[index].state = WebTouchPoint::StateMoved;
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
index 5689bff4..a3ed311c 100644
--- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
+++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -21,8 +21,10 @@
 
 OffscreenCanvasSurfaceImpl::OffscreenCanvasSurfaceImpl(
     mojo::InterfaceRequest<blink::mojom::OffscreenCanvasSurface> request)
-    : id_allocator_(CreateSurfaceIdAllocator()),
-      binding_(this, std::move(request)) {}
+    : id_allocator_(new cc::SurfaceIdAllocator(AllocateSurfaceClientId())),
+      binding_(this, std::move(request)) {
+  GetSurfaceManager()->RegisterSurfaceClientId(id_allocator_->client_id());
+}
 
 OffscreenCanvasSurfaceImpl::~OffscreenCanvasSurfaceImpl() {
   if (!GetSurfaceManager()) {
@@ -30,8 +32,8 @@
     // avoid their destruction errors.
     if (surface_factory_)
         surface_factory_->DidDestroySurfaceManager();
-    if (id_allocator_)
-        id_allocator_->DidDestroySurfaceManager();
+  } else {
+    GetSurfaceManager()->InvalidateSurfaceClientId(id_allocator_->client_id());
   }
   surface_factory_->Destroy(surface_id_);
 }
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index ca50c61..9786dad 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -173,10 +173,6 @@
     RenderWidgetHostViewBase* root_view,
     blink::WebGestureEvent* event,
     const ui::LatencyInfo& latency) {
-  DCHECK(event->type != blink::WebInputEvent::GestureFlingStart ||
-         event->data.flingStart.velocityX != 0.0 ||
-         event->data.flingStart.velocityY != 0.0);
-
   switch (event->sourceDevice) {
     case blink::WebGestureDeviceUninitialized:
       NOTREACHED() << "Uninitialized device type is not allowed";
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 69515bc..5245509 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -345,8 +345,10 @@
       locks_on_frame_count_(0),
       observing_root_window_(false),
       weak_ptr_factory_(this) {
-  if (CompositorImpl::GetSurfaceManager())
-    id_allocator_ = CompositorImpl::CreateSurfaceIdAllocator();
+  id_allocator_.reset(
+      new cc::SurfaceIdAllocator(CompositorImpl::AllocateSurfaceClientId()));
+  CompositorImpl::GetSurfaceManager()->RegisterSurfaceClientId(
+      id_allocator_->client_id());
   host_->SetView(this);
   SetContentViewCore(content_view_core);
 }
@@ -795,6 +797,8 @@
     surface_id_ = cc::SurfaceId();
   }
   surface_factory_.reset();
+  CompositorImpl::GetSurfaceManager()->InvalidateSurfaceClientId(
+      id_allocator_->client_id());
 
   // The RenderWidgetHost's destruction led here, so don't call it.
   host_ = NULL;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 62af378..34b8ff6 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1254,12 +1254,16 @@
   if (WebTouchEvent::isTouchEventType(input_event.type))
     return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 
-  // Reporting consumed for a fling suggests that there's now an *active* fling
-  // that requires both animation and a fling-end notification. However, the
-  // OverscrollController consumes a fling to stop its propagation; it doesn't
-  // actually tick a fling animation. Report no consumer to convey this.
-  if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart)
+  if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart) {
+    // Here we indicate that there was no consumer for this event, as
+    // otherwise the fling animation system will try to run an animation
+    // and will also expect a notification when the fling ends. Since
+    // CrOS just uses the GestureFlingStart with zero-velocity as a means
+    // of indicating that touchpad scroll has ended, we don't actually want
+    // a fling animation. Note: Similar code exists in
+    // RenderWidgetHostViewChildFrame::FilterInputEvent()
     return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+  }
 
   return consumed ? INPUT_EVENT_ACK_STATE_CONSUMED
                   : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
diff --git a/content/browser/resources/gpu/info_view.js b/content/browser/resources/gpu/info_view.js
index 8a98725..f2ef843 100644
--- a/content/browser/resources/gpu/info_view.js
+++ b/content/browser/resources/gpu/info_view.js
@@ -95,6 +95,7 @@
         'rasterization': 'Rasterization',
         'multiple_raster_threads': 'Multiple Raster Threads',
         'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
+        'vpx_decode': 'VPx Video Decode',
       };
 
       var statusMap =  {
diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h
index 4a420b0..8e83b1d 100644
--- a/content/browser/service_worker/embedded_worker_registry.h
+++ b/content/browser/service_worker/embedded_worker_registry.h
@@ -111,9 +111,6 @@
   friend class base::RefCounted<EmbeddedWorkerRegistry>;
   friend class EmbeddedWorkerInstance;
   friend class EmbeddedWorkerInstanceTest;
-  // TODO(falken): For temporary debugging. Remove when https://crbug.com/625040
-  // is fixed.
-  friend class ServiceWorkerDispatcherHost;
   FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest,
                            RemoveWorkerInSharedProcess);
 
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 08936fd..10b633b9 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/debug/crash_logging.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -86,52 +85,6 @@
          OriginCanAccessServiceWorkers(given_document_url);
 }
 
-std::string GetIPCMessageTypeAsString(uint32_t type) {
-  switch (type) {
-    case ServiceWorkerHostMsg_InstallEventFinished::ID:
-      return "ServiceWorkerHostMsg_InstallEventFinished";
-    case ServiceWorkerHostMsg_ActivateEventFinished::ID:
-      return "ServiceWorkerHostMsg_ActivateEventFinished";
-    case ServiceWorkerHostMsg_ExtendableMessageEventFinished::ID:
-      return "ServiceWorkerHostMsg_ExtendableMessageEventFinished";
-    case ServiceWorkerHostMsg_FetchEventResponse::ID:
-      return "ServiceWorkerHostMsg_FetchEventResponse";
-    case ServiceWorkerHostMsg_FetchEventFinished::ID:
-      return "ServiceWorkerHostMsg_FetchEventFinished";
-    case ServiceWorkerHostMsg_NotificationClickEventFinished::ID:
-      return "ServiceWorkerHostMsg_NotificationClickEventFinished";
-    case ServiceWorkerHostMsg_NotificationCloseEventFinished::ID:
-      return "ServiceWorkerHostMsg_NotificationCloseEventFinished";
-    case ServiceWorkerHostMsg_PushEventFinished::ID:
-      return "ServiceWorkerHostMsg_PushEventFinished";
-    case ServiceWorkerHostMsg_Pong::ID:
-      return "ServiceWorkerHostMsg_Pong";
-    case ServiceWorkerHostMsg_GetClient::ID:
-      return "ServiceWorkerHostMsg_GetClient";
-    case ServiceWorkerHostMsg_GetClients::ID:
-      return "ServiceWorkerHostMsg_GetClients";
-    case ServiceWorkerHostMsg_PostMessageToClient::ID:
-      return "ServiceWorkerHostMsg_PostMessageToClient";
-    case ServiceWorkerHostMsg_SetCachedMetadata::ID:
-      return "ServiceWorkerHostMsg_SetCachedMetadata";
-    case ServiceWorkerHostMsg_ClearCachedMetadata::ID:
-      return "ServiceWorkerHostMsg_ClearCachedMetadata";
-    case ServiceWorkerHostMsg_OpenWindow::ID:
-      return "ServiceWorkerHostMsg_OpenWindow";
-    case ServiceWorkerHostMsg_FocusClient::ID:
-      return "ServiceWorkerHostMsg_FocusClient";
-    case ServiceWorkerHostMsg_NavigateClient::ID:
-      return "ServiceWorkerHostMsg_NavigateClient";
-    case ServiceWorkerHostMsg_SkipWaiting::ID:
-      return "ServiceWorkerHostMsg_SkipWaiting";
-    case ServiceWorkerHostMsg_ClaimClients::ID:
-      return "ServiceWorkerHostMsg_ClaimClients";
-    case ServiceWorkerHostMsg_RegisterForeignFetchScopes::ID:
-      return "ServiceWorkerHostMsg_RegisterForeignFetchScopes";
-  }
-  return "Unknown";
-}
-
 }  // namespace
 
 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
@@ -254,19 +207,8 @@
   if (!handled && GetContext()) {
     handled = GetContext()->embedded_worker_registry()->OnMessageReceived(
         message, render_process_id_);
-    if (!handled) {
-      // Temporary debugging for https://crbug.com/625040
-      EmbeddedWorkerInstance* worker =
-          GetContext()->embedded_worker_registry()->GetWorkerForMessage(
-              render_process_id_, message.routing_id());
-      base::debug::ScopedCrashKey type_key(
-          "swdh_not_handled_message_type",
-          GetIPCMessageTypeAsString(message.type()));
-      base::debug::ScopedCrashKey status_key(
-          "swdh_not_handled_worker_status",
-          EmbeddedWorkerInstance::StatusToString(worker->status()));
+    if (!handled)
       bad_message::ReceivedBadMessage(this, bad_message::SWDH_NOT_HANDLED);
-    }
   }
 
   return handled;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 1fb9201c..2688776 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/command_line.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/feature_list.h"
 #include "base/lazy_instance.h"
 #include "base/location.h"
@@ -81,6 +82,7 @@
 #include "content/common/input/web_input_event_traits.h"
 #include "content/common/input_messages.h"
 #include "content/common/page_messages.h"
+#include "content/common/page_state_serialization.h"
 #include "content/common/site_isolation_policy.h"
 #include "content/common/ssl_status_serialization.h"
 #include "content/common/view_messages.h"
@@ -4475,6 +4477,25 @@
   if (page_state == frame_entry->page_state())
     return;  // Nothing to update.
 
+  // The document_sequence_number and item_sequence_number recorded in the
+  // FrameNavigationEntry should not differ from the one coming with the update,
+  // since it must come from the same document.
+  ExplodedPageState exploded_state;
+  if (!DecodePageState(page_state.ToEncodedData(), &exploded_state))
+    return;
+
+  if (exploded_state.top.document_sequence_number !=
+          frame_entry->document_sequence_number() ||
+      exploded_state.top.item_sequence_number !=
+          frame_entry->item_sequence_number()) {
+    // Generate a minidump, which can be debugged to understand the root cause
+    // this unexpected update.
+    // TODO(nasko): Remove once https://crbug.com/628677 is understood.
+    base::debug::Alias(&page_state);
+    base::debug::DumpWithoutCrashing();
+    return;
+  }
+
   frame_entry->set_page_state(page_state);
   controller_.NotifyEntryChanged(entry);
 }
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index 2c4b075..346cff15 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -594,7 +594,7 @@
       request_info.loading_web_task_runner) {
     resource_scheduling_filter_->SetRequestIdTaskRunner(
         request_id,
-        base::WrapUnique(request_info.loading_web_task_runner->clone()));
+        request_info.loading_web_task_runner->clone());
   }
 
   message_sender_->Send(new ResourceHostMsg_RequestResource(
@@ -608,7 +608,8 @@
     const ResourceResponseHead& browser_info,
     ResourceResponseInfo* renderer_info) const {
   *renderer_info = browser_info;
-  if (request_info.request_start.is_null() ||
+  if (base::TimeTicks::IsConsistentAcrossProcesses() ||
+      request_info.request_start.is_null() ||
       request_info.response_start.is_null() ||
       browser_info.request_start.is_null() ||
       browser_info.response_start.is_null() ||
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index ec4bdc0f..918f69f 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -550,7 +550,7 @@
       GetRequestContextFrameTypeForWebURLRequest(request);
   request_info.extra_data = request.getExtraData();
   request_info.report_raw_headers = request.reportRawHeaders();
-  request_info.loading_web_task_runner.reset(web_task_runner_->clone());
+  request_info.loading_web_task_runner = web_task_runner_->clone();
   request_info.lofi_state = static_cast<LoFiState>(request.getLoFiState());
 
   scoped_refptr<ResourceRequestBodyImpl> request_body =
@@ -1187,7 +1187,7 @@
     blink::WebTaskRunner* loading_task_runner) {
   // There's no guarantee on the lifetime of |loading_task_runner| so we take a
   // copy.
-  context_->SetWebTaskRunner(base::WrapUnique(loading_task_runner->clone()));
+  context_->SetWebTaskRunner(loading_task_runner->clone());
 }
 
 // This function is implemented here because it uses net functions. it is
diff --git a/content/common/input/event_with_latency_info.cc b/content/common/input/event_with_latency_info.cc
index 5af2757..f04e8ac 100644
--- a/content/common/input/event_with_latency_info.cc
+++ b/content/common/input/event_with_latency_info.cc
@@ -113,13 +113,13 @@
       event.type != WebInputEvent::TouchMove ||
       event.modifiers != event_to_coalesce.modifiers ||
       event.touchesLength != event_to_coalesce.touchesLength ||
-      event.touchesLength > WebTouchEvent::touchesLengthCap)
+      event.touchesLength > WebTouchEvent::kTouchesLengthCap)
     return false;
 
-  static_assert(WebTouchEvent::touchesLengthCap <= sizeof(int32_t) * 8U,
-                "suboptimal touchesLengthCap size");
+  static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U,
+                "suboptimal kTouchesLengthCap size");
   // Ensure that we have a 1-to-1 mapping of pointer ids between touches.
-  std::bitset<WebTouchEvent::touchesLengthCap> unmatched_event_touches(
+  std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches(
       (1 << event.touchesLength) - 1);
   for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) {
     int event_touch_index =
diff --git a/content/common/input/synthetic_web_input_event_builders.cc b/content/common/input/synthetic_web_input_event_builders.cc
index c5962b9..653bccd6 100644
--- a/content/common/input/synthetic_web_input_event_builders.cc
+++ b/content/common/input/synthetic_web_input_event_builders.cc
@@ -189,7 +189,7 @@
 }
 
 int SyntheticWebTouchEvent::PressPoint(float x, float y) {
-  if (touchesLength == touchesLengthCap)
+  if (touchesLength == kTouchesLengthCap)
     return -1;
   WebTouchPoint& point = touches[touchesLength];
   point.id = touchesLength;
@@ -208,7 +208,7 @@
 
 void SyntheticWebTouchEvent::MovePoint(int index, float x, float y) {
   CHECK_GE(index, 0);
-  CHECK_LT(index, touchesLengthCap);
+  CHECK_LT(index, kTouchesLengthCap);
   // Always set this bit to avoid otherwise unexpected touchmove suppression.
   // The caller can opt-out explicitly, if necessary.
   movedBeyondSlopRegion = true;
@@ -222,7 +222,7 @@
 
 void SyntheticWebTouchEvent::ReleasePoint(int index) {
   CHECK_GE(index, 0);
-  CHECK_LT(index, touchesLengthCap);
+  CHECK_LT(index, kTouchesLengthCap);
   touches[index].state = WebTouchPoint::StateReleased;
   WebTouchEventTraits::ResetType(
       WebInputEvent::TouchEnd, timeStampSeconds, this);
@@ -230,7 +230,7 @@
 
 void SyntheticWebTouchEvent::CancelPoint(int index) {
   CHECK_GE(index, 0);
-  CHECK_LT(index, touchesLengthCap);
+  CHECK_LT(index, kTouchesLengthCap);
   touches[index].state = WebTouchPoint::StateCancelled;
   WebTouchEventTraits::ResetType(
       WebInputEvent::TouchCancel, timeStampSeconds, this);
diff --git a/content/common/inter_process_time_ticks_converter.h b/content/common/inter_process_time_ticks_converter.h
index f21ddc8..cc5de55 100644
--- a/content/common/inter_process_time_ticks_converter.h
+++ b/content/common/inter_process_time_ticks_converter.h
@@ -17,8 +17,9 @@
 class RemoteTimeDelta;
 class RemoteTimeTicks;
 
-// On Windows, TimeTicks are not consistent between processes. Often, the values
-// on one process have a static offset relative to another. Occasionally, these
+// On Windows, TimeTicks are not always consistent between processes as
+// indicated by |TimeTicks::IsConsistentAcrossProcesses()|. Often, the values on
+// one process have a static offset relative to another. Occasionally, these
 // offsets shift while running.
 //
 // To combat this, any TimeTicks values sent from the remote process to the
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index f1dbe67..0b8b49a5 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -899,6 +899,7 @@
       'browser/indexed_db/indexed_db_context_impl.h',
       'browser/indexed_db/indexed_db_cursor.cc',
       'browser/indexed_db/indexed_db_cursor.h',
+      'browser/indexed_db/indexed_db_data_loss_info.h',
       'browser/indexed_db/indexed_db_database.cc',
       'browser/indexed_db/indexed_db_database.h',
       'browser/indexed_db/indexed_db_database_callbacks.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 22e4902..9f899f0d 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -313,6 +313,7 @@
     'content_browsertests_webrtc_sources': [
       'browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc',
       'browser/media/webrtc/webrtc_browsertest.cc',
+      'browser/media/webrtc/webrtc_browsertest_audio.cc',
       'browser/media/webrtc/webrtc_browsertest_data.cc',
       'browser/media/webrtc/webrtc_capture_from_element_browsertest.cc',
       'browser/media/webrtc/webrtc_datachannel_browsertest.cc',
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index cc32662..c107799 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -59,6 +59,7 @@
 #include "base/win/scoped_com_initializer.h"
 #include "base/win/windows_version.h"
 #include "media/gpu/dxva_video_decode_accelerator_win.h"
+#include "media/gpu/media_foundation_video_encode_accelerator_win.h"
 #include "sandbox/win/src/sandbox.h"
 #endif
 
@@ -489,6 +490,7 @@
 
 #if defined(OS_WIN)
   media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
+  media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
 #endif
   return true;
 }
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
index 91261af7..7d0aaac 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
@@ -110,13 +110,13 @@
     @Override
     public void onMaxBandwidthChanged(double maxBandwidthMbps) {}
     @Override
-    public void onNetworkConnect(int netId, int connectionType) {}
+    public void onNetworkConnect(long netId, int connectionType) {}
     @Override
-    public void onNetworkSoonToDisconnect(int netId) {}
+    public void onNetworkSoonToDisconnect(long netId) {}
     @Override
-    public void onNetworkDisconnect(int netId) {}
+    public void onNetworkDisconnect(long netId) {}
     @Override
-    public void purgeActiveNetworkList(int[] activeNetIds) {}
+    public void purgeActiveNetworkList(long[] activeNetIds) {}
 
     @NativeClassQualifiedName("BackgroundSyncNetworkObserverAndroid::Observer")
     private native void nativeNotifyConnectionTypeChanged(long nativePtr, int newConnectionType);
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 153ad54..8e1ccf6 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -8,7 +8,6 @@
 #include "base/guid.h"
 #include "build/build_config.h"
 #include "content/public/browser/client_certificate_delegate.h"
-#include "content/public/browser/geolocation_delegate.h"
 #include "content/public/browser/vpn_service_proxy.h"
 #include "content/public/common/sandbox_type.h"
 #include "media/base/cdm_factory.h"
@@ -308,11 +307,6 @@
   return nullptr;
 }
 
-GeolocationDelegate* ContentBrowserClient::CreateGeolocationDelegate() {
-  // We don't need to override anything, the default implementation is good.
-  return nullptr;
-}
-
 bool ContentBrowserClient::IsFastShutdownPossible() {
   return true;
 }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 0d66e5f7..049dcf51 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -107,7 +107,6 @@
 class ClientCertificateDelegate;
 class DevToolsManagerDelegate;
 class ExternalVideoSurfaceContainer;
-class GeolocationDelegate;
 class LocationProvider;
 class MediaObserver;
 class NavigationHandle;
@@ -535,10 +534,6 @@
   // Getters for common objects.
   virtual net::NetLog* GetNetLog();
 
-  // Allows the embedder to provide a Delegate for Geolocation to override some
-  // functionality of the API (e.g. AccessTokenStore, LocationProvider).
-  virtual GeolocationDelegate* CreateGeolocationDelegate();
-
   // Returns true if fast shutdown is possible.
   virtual bool IsFastShutdownPossible();
 
diff --git a/content/public/browser/resource_throttle.h b/content/public/browser/resource_throttle.h
index 010e16c..7a980f2 100644
--- a/content/public/browser/resource_throttle.h
+++ b/content/public/browser/resource_throttle.h
@@ -27,9 +27,6 @@
   // Called before the resource request is started.
   virtual void WillStartRequest(bool* defer) {}
 
-  // Called before the resource request uses the network for the first time.
-  virtual void WillStartUsingNetwork(bool* defer) {}
-
   // Called when the request was redirected.  |redirect_info| contains the
   // redirect responses's HTTP status code and some information about the new
   // request that will be sent if the redirect is followed, including the new
diff --git a/content/public/test/layouttest_support.h b/content/public/test/layouttest_support.h
index ea3460a..a188bb7 100644
--- a/content/public/test/layouttest_support.h
+++ b/content/public/test/layouttest_support.h
@@ -34,7 +34,7 @@
 
 namespace test_runner {
 class WebFrameTestProxyBase;
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 }
 
 namespace content {
@@ -53,22 +53,24 @@
 // Turn a renderer into layout test mode.
 void EnableRendererLayoutTestMode();
 
-// "Casts" |render_view| to |WebTestProxyBase|.  Caller has to ensure that prior
-// to construction of |render_view|, EnableWebTestProxyCreation was called.
-test_runner::WebTestProxyBase* GetWebTestProxyBase(RenderView* render_view);
+// "Casts" |render_view| to |WebViewTestProxyBase|.  Caller has to ensure that
+// prior to construction of |render_view|, EnableWebTestProxyCreation was
+// called.
+test_runner::WebViewTestProxyBase* GetWebViewTestProxyBase(
+    RenderView* render_view);
 
 // "Casts" |render_frame| to |WebFrameTestProxyBase|.  Caller has to ensure
-// that prior to construction of |render_frame|, EnableWebTestProxyCreation was
-// called.
+// that prior to construction of |render_frame|, EnableiewTestProxyCreation
+// was called.
 test_runner::WebFrameTestProxyBase* GetWebFrameTestProxyBase(
     RenderFrame* render_frame);
 
-// Enable injecting of a WebTestProxy between WebViews and RenderViews
+// Enable injecting of a WebViewTestProxy between WebViews and RenderViews
 // and WebFrameTestProxy between WebFrames and RenderFrames.
-// |view_proxy_creation_callback| is invoked after creating WebTestProxy.
+// |view_proxy_creation_callback| is invoked after creating WebViewTestProxy.
 // |frame_proxy_creation_callback| is called after creating WebFrameTestProxy.
 using ViewProxyCreationCallback =
-    base::Callback<void(RenderView*, test_runner::WebTestProxyBase*)>;
+    base::Callback<void(RenderView*, test_runner::WebViewTestProxyBase*)>;
 using FrameProxyCreationCallback =
     base::Callback<void(RenderFrame*, test_runner::WebFrameTestProxyBase*)>;
 void EnableWebTestProxyCreation(
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc
index a186f41..87b543ba 100644
--- a/content/renderer/android/synchronous_compositor_output_surface.cc
+++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -106,10 +106,10 @@
   capabilities_.delegated_rendering = true;
   memory_policy_.priority_cutoff_when_visible =
       gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
-  surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get());
 }
 
-SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {}
+SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() =
+    default;
 
 void SynchronousCompositorOutputSurface::SetSyncClient(
     SynchronousCompositorOutputSurfaceClient* compositor) {
@@ -143,6 +143,7 @@
   registry_->RegisterOutputSurface(routing_id_, this);
   registered_ = true;
 
+  surface_manager_->RegisterSurfaceClientId(surface_id_allocator_->client_id());
   surface_manager_->RegisterSurfaceFactoryClient(
       surface_id_allocator_->client_id(), this);
 
@@ -174,6 +175,8 @@
     surface_factory_->Destroy(delegated_surface_id_);
   surface_manager_->UnregisterSurfaceFactoryClient(
       surface_id_allocator_->client_id());
+  surface_manager_->InvalidateSurfaceClientId(
+      surface_id_allocator_->client_id());
   display_ = nullptr;
   surface_factory_ = nullptr;
   surface_id_allocator_ = nullptr;
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc
index 142de44..f6b4cdc1 100644
--- a/content/renderer/pepper/event_conversion.cc
+++ b/content/renderer/pepper/event_conversion.cc
@@ -290,7 +290,7 @@
                          uint32_t web_touches_length,
                          uint32_t id) {
   // Note: A brute force search to find the (potentially) existing touch point
-  // is cheap given the small bound on |WebTouchEvent::touchesLengthCap|.
+  // is cheap given the small bound on |WebTouchEvent::kTouchesLengthCap|.
   for (uint32_t i = 0; i < web_touches_length; ++i) {
     if (web_touches[i].id == static_cast<int>(id))
       return true;
@@ -305,10 +305,10 @@
   const uint32_t initial_web_touches_length = *web_touches_length;
   const uint32_t touches_length =
       std::min(static_cast<uint32_t>(pp_touches.size()),
-               static_cast<uint32_t>(WebTouchEvent::touchesLengthCap));
+               static_cast<uint32_t>(WebTouchEvent::kTouchesLengthCap));
   for (uint32_t i = 0; i < touches_length; ++i) {
     const uint32_t touch_index = *web_touches_length;
-    if (touch_index >= static_cast<uint32_t>(WebTouchEvent::touchesLengthCap))
+    if (touch_index >= static_cast<uint32_t>(WebTouchEvent::kTouchesLengthCap))
       return;
 
     const PP_TouchPoint& pp_pt = pp_touches[i];
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 28cbbfb6..4c0be2b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2769,6 +2769,9 @@
 }
 
 void RenderFrameImpl::didAccessInitialDocument() {
+  // NOTE: Do not call back into JavaScript here, since this call is made from a
+  // V8 security check.
+
   // If the request hasn't yet committed, notify the browser process that it is
   // no longer safe to show the pending URL of the main frame, since a URL spoof
   // is now possible. (If the request has committed, the browser already knows.)
@@ -4810,6 +4813,9 @@
                "id", routing_id_);
   render_view_->FrameDidStopLoading(frame_);
   Send(new FrameHostMsg_DidStopLoading(routing_id_));
+
+  // Clear any pending NavigationParams if they didn't get used.
+  pending_navigation_params_.reset();
 }
 
 void RenderFrameImpl::didChangeLoadProgress(double load_progress) {
@@ -5649,9 +5655,6 @@
     if (!frame_->isLoading() && !has_history_navigation_in_frame)
       Send(new FrameHostMsg_DidStopLoading(routing_id_));
   }
-
-  // In case LoadRequest failed before didCreateDataSource was called.
-  pending_navigation_params_.reset();
 }
 
 void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 64910a7..376d3a0c 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -315,7 +315,7 @@
   // data URLs to bypass the ResourceDispatcher.
   return new content::WebURLLoaderImpl(
       child_thread ? child_thread->resource_dispatcher() : NULL,
-      base::WrapUnique(currentThread()->getWebTaskRunner()->clone()));
+      currentThread()->getWebTaskRunner()->clone());
 }
 
 blink::WebThread* RendererBlinkPlatformImpl::currentThread() {
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 9cc50e6..bb5eac6 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -15,8 +15,8 @@
   import("//build/config/android/config.gni")
 } else if (is_mac) {
   import("//build/config/mac/rules.gni")
-  import("//build_overrides/v8.gni")
   import("//build/mac/tweak_info_plist.gni")
+  import("//v8/gni/v8.gni")
 } else if (is_win) {
   import("//build/win/syzygy/syzygy.gni")
 }
diff --git a/content/shell/browser/shell_browser_main_parts.cc b/content/shell/browser/shell_browser_main_parts.cc
index 7caf25c..6e541e2 100644
--- a/content/shell/browser/shell_browser_main_parts.cc
+++ b/content/shell/browser/shell_browser_main_parts.cc
@@ -15,11 +15,14 @@
 #include "build/build_config.h"
 #include "components/devtools_http_handler/devtools_http_handler.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/geolocation_provider.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/url_constants.h"
 #include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_access_token_store.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_devtools_manager_delegate.h"
 #include "content/shell/browser/shell_net_log.h"
@@ -55,6 +58,21 @@
 
 namespace {
 
+// A provider of services for Geolocation.
+class ShellGeolocationDelegate : public content::GeolocationDelegate {
+ public:
+  explicit ShellGeolocationDelegate(ShellBrowserContext* context)
+      : context_(context) {}
+
+  scoped_refptr<content::AccessTokenStore> CreateAccessTokenStore() final {
+    return new ShellAccessTokenStore(context_);
+  }
+
+ private:
+  ShellBrowserContext* context_;
+  DISALLOW_COPY_AND_ASSIGN(ShellGeolocationDelegate);
+};
+
 GURL GetStartupURL() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kContentBrowserTest))
@@ -165,6 +183,8 @@
 void ShellBrowserMainParts::PreMainMessageLoopRun() {
   net_log_.reset(new ShellNetLog("content_shell"));
   InitializeBrowserContexts();
+  content::GeolocationProvider::SetGeolocationDelegate(
+      new ShellGeolocationDelegate(browser_context()));
   Shell::Initialize();
   net::NetModule::SetResourceProvider(PlatformResourceProvider);
 
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index 2587b1e..2f522b4 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -17,7 +17,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "content/public/browser/client_certificate_delegate.h"
-#include "content/public/browser/geolocation_delegate.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_dispatcher_host.h"
@@ -27,7 +26,6 @@
 #include "content/public/common/web_preferences.h"
 #include "content/public/test/test_mojo_app.h"
 #include "content/shell/browser/shell.h"
-#include "content/shell/browser/shell_access_token_store.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_browser_main_parts.h"
 #include "content/shell/browser/shell_devtools_manager_delegate.h"
@@ -119,20 +117,6 @@
 }
 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
 
-// A provider of services for Geolocation.
-class ShellGeolocationDelegate : public content::GeolocationDelegate {
- public:
-  ShellGeolocationDelegate() {}
-
-  scoped_refptr<AccessTokenStore> CreateAccessTokenStore() final {
-    return new ShellAccessTokenStore(
-        ShellContentBrowserClient::Get()->browser_context());
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ShellGeolocationDelegate);
-};
-
 }  // namespace
 
 ShellContentBrowserClient* ShellContentBrowserClient::Get() {
@@ -364,8 +348,4 @@
   return shell_browser_main_parts_->off_the_record_browser_context();
 }
 
-GeolocationDelegate* ShellContentBrowserClient::CreateGeolocationDelegate() {
-  return new ShellGeolocationDelegate();
-}
-
 }  // namespace content
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h
index 0a03b35..e378b1f9 100644
--- a/content/shell/browser/shell_content_browser_client.h
+++ b/content/shell/browser/shell_content_browser_client.h
@@ -43,7 +43,6 @@
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
                                       int child_process_id) override;
   void ResourceDispatcherHostCreated() override;
-  GeolocationDelegate* CreateGeolocationDelegate() override;
   std::string GetDefaultDownloadName() override;
   WebContentsViewDelegate* GetWebContentsViewDelegate(
       WebContents* web_contents) override;
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index 9c8e495..81e77cc 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -35,8 +35,8 @@
 #include "components/test_runner/layout_and_paint_async_then.h"
 #include "components/test_runner/pixel_dump.h"
 #include "components/test_runner/web_test_interfaces.h"
-#include "components/test_runner/web_test_proxy.h"
 #include "components/test_runner/web_test_runner.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "content/common/content_switches_internal.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
diff --git a/content/shell/renderer/layout_test/blink_test_runner.h b/content/shell/renderer/layout_test/blink_test_runner.h
index 7d804a9..5756f6bb 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.h
+++ b/content/shell/renderer/layout_test/blink_test_runner.h
@@ -36,7 +36,7 @@
 }
 
 namespace test_runner {
-class WebTestProxyBase;
+class WebViewTestProxyBase;
 }
 
 namespace content {
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
index 065f4218..ff84acfa 100644
--- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
+++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -10,8 +10,8 @@
 #include "components/test_runner/mock_credential_manager_client.h"
 #include "components/test_runner/web_frame_test_proxy.h"
 #include "components/test_runner/web_test_interfaces.h"
-#include "components/test_runner/web_test_proxy.h"
 #include "components/test_runner/web_test_runner.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_switches.h"
@@ -52,8 +52,8 @@
 
 namespace {
 
-void WebTestProxyCreated(RenderView* render_view,
-                         test_runner::WebTestProxyBase* proxy) {
+void WebViewTestProxyCreated(RenderView* render_view,
+                             test_runner::WebViewTestProxyBase* proxy) {
   test_runner::WebTestInterfaces* interfaces =
       LayoutTestRenderThreadObserver::GetInstance()->test_interfaces();
 
@@ -80,18 +80,18 @@
 
 void WebFrameTestProxyCreated(RenderFrame* render_frame,
                               test_runner::WebFrameTestProxyBase* proxy) {
-  test_runner::WebTestProxyBase* web_test_proxy_base =
-      GetWebTestProxyBase(render_frame->GetRenderView());
+  test_runner::WebViewTestProxyBase* web_view_test_proxy_base =
+      GetWebViewTestProxyBase(render_frame->GetRenderView());
   proxy->set_test_client(
       LayoutTestRenderThreadObserver::GetInstance()
           ->test_interfaces()
-          ->CreateWebFrameTestClient(web_test_proxy_base, proxy));
+          ->CreateWebFrameTestClient(web_view_test_proxy_base, proxy));
 }
 
 }  // namespace
 
 LayoutTestContentRendererClient::LayoutTestContentRendererClient() {
-  EnableWebTestProxyCreation(base::Bind(&WebTestProxyCreated),
+  EnableWebTestProxyCreation(base::Bind(&WebViewTestProxyCreated),
                              base::Bind(&WebFrameTestProxyCreated));
 }
 
@@ -115,11 +115,12 @@
     RenderView* render_view) {
   new ShellRenderViewObserver(render_view);
 
-  test_runner::WebTestProxyBase* proxy = GetWebTestProxyBase(render_view);
+  test_runner::WebViewTestProxyBase* proxy =
+      GetWebViewTestProxyBase(render_view);
   proxy->set_web_view(render_view->GetWebView());
   // TODO(lfg): We should fix the TestProxy to track the WebWidgets on every
   // local root in WebFrameTestProxy instead of having only the WebWidget for
-  // the main frame in WebTestProxy.
+  // the main frame in WebViewTestProxy.
   proxy->set_web_widget(render_view->GetWebView()->widget());
   proxy->Reset();
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index af7c977..947faed 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -7,9 +7,9 @@
 import("//build/config/crypto.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
-import("//build_overrides/v8.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//testing/test.gni")
+import("//v8/gni/v8.gni")
 
 content_tests_gypi_values =
     exec_script("//build/gypi_to_gn.py",
diff --git a/content/test/data/media/peerconnection-call-audio.html b/content/test/data/media/peerconnection-call-audio.html
new file mode 100644
index 0000000..3c99688
--- /dev/null
+++ b/content/test/data/media/peerconnection-call-audio.html
@@ -0,0 +1,226 @@
+<html>
+<head>
+  <script type="text/javascript" src="webrtc_test_utilities.js"></script>
+  <script type="text/javascript" src="webrtc_test_common.js"></script>
+  <script type="text/javascript" src="webrtc_test_audio.js"></script>
+  <script type="text/javascript">
+  $ = function(id) {
+    return document.getElementById(id);
+  };
+
+  window.onerror = function(errorMsg, url, lineNumber, column, errorObj) {
+    failTest('Error: ' + errorMsg + '\nScript: ' + url +
+             '\nLine: ' + lineNumber + '\nColumn: ' + column +
+             '\nStackTrace: ' + errorObj);
+  }
+
+  var gFirstConnection = null;
+  var gSecondConnection = null;
+  var gLocalStream = null;
+  var gSentTones = '';
+
+  var gRemoteStreams = {};
+
+  setAllEventsOccuredHandler(reportTestSuccess);
+
+  // The second set of constraints should request audio (e.g. audio:true) since
+  // we expect audio to be playing after the second renegotiation.
+  function callAndRenegotiateToAudio(constraints, renegotiationConstraints) {
+    createConnections(null);
+    navigator.webkitGetUserMedia(constraints,
+        addStreamToBothConnectionsAndNegotiate, printGetUserMediaError);
+
+    waitForConnectionToStabilize(gFirstConnection, function() {
+      gFirstConnection.removeStream(gLocalStream);
+      gSecondConnection.removeStream(gLocalStream);
+
+      navigator.webkitGetUserMedia(renegotiationConstraints,
+          addStreamToTheFirstConnectionAndNegotiate, printGetUserMediaError);
+
+      var onCallEstablished = function() {
+        ensureAudioPlaying(gSecondConnection);
+      };
+
+      waitForConnectionToStabilize(gFirstConnection, onCallEstablished);
+    });
+  }
+
+  function callAndEnsureAudioIsPlaying(constraints) {
+    createConnections(null);
+
+    // Add the local stream to gFirstConnection to play one-way audio.
+    navigator.webkitGetUserMedia(constraints,
+      addStreamToTheFirstConnectionAndNegotiate, printGetUserMediaError);
+
+    var onCallEstablished = function() {
+      ensureAudioPlaying(gSecondConnection);
+    };
+
+    waitForConnectionToStabilize(gFirstConnection, onCallEstablished);
+  }
+
+  function callWithIsac16KAndEnsureAudioIsPlaying(constraints) {
+    setOfferSdpTransform(function(sdp) {
+      sdp = sdp.replace(/m=audio (\d+) RTP\/SAVPF.*\r\n/g,
+                        'm=audio $1 RTP/SAVPF 103 126\r\n');
+      sdp = sdp.replace('a=fmtp:111 minptime=10', 'a=fmtp:103 minptime=10');
+      if (sdp.search('a=rtpmap:103 ISAC/16000') == -1)
+        failTest('Missing iSAC 16K codec on Android; cannot force codec.');
+
+      return sdp;
+    });
+    callAndEnsureAudioIsPlaying(constraints);
+  }
+
+  function enableRemoteVideo(peerConnection, enabled) {
+    remoteStream = peerConnection.getRemoteStreams()[0];
+    remoteStream.getVideoTracks()[0].enabled = enabled;
+  }
+
+  function enableRemoteAudio(peerConnection, enabled) {
+    remoteStream = peerConnection.getRemoteStreams()[0];
+    remoteStream.getAudioTracks()[0].enabled = enabled;
+  }
+
+  function enableLocalVideo(peerConnection, enabled) {
+    localStream = peerConnection.getLocalStreams()[0];
+    localStream.getVideoTracks()[0].enabled = enabled;
+  }
+
+  function enableLocalAudio(peerConnection, enabled) {
+    localStream = peerConnection.getLocalStreams()[0];
+    localStream.getAudioTracks()[0].enabled = enabled;
+  }
+
+  function callAndEnsureRemoteAudioTrackMutingWorks() {
+    callAndEnsureAudioIsPlaying({audio: true, video: true});
+    setAllEventsOccuredHandler(function() {
+      setAllEventsOccuredHandler(reportTestSuccess);
+
+      // Call is up, now mute the remote track and check we stop playing out
+      // audio (after a small delay, we don't expect it to happen instantly).
+      enableRemoteAudio(gSecondConnection, false);
+      ensureSilence(gSecondConnection);
+    });
+  }
+
+  function callAndEnsureLocalAudioTrackMutingWorks() {
+    callAndEnsureAudioIsPlaying({audio: true, video: true});
+    setAllEventsOccuredHandler(function() {
+      setAllEventsOccuredHandler(reportTestSuccess);
+
+      // Call is up, now mute the local track of the sending side and ensure
+      // the receiving side stops receiving audio.
+      enableLocalAudio(gFirstConnection, false);
+      ensureSilence(gSecondConnection);
+    });
+  }
+
+  function callAndEnsureAudioTrackUnmutingWorks() {
+    callAndEnsureAudioIsPlaying({audio: true, video: true});
+    setAllEventsOccuredHandler(function() {
+      setAllEventsOccuredHandler(reportTestSuccess);
+
+      // Mute, wait a while, unmute, verify audio gets back up.
+      // (Also, ensure video muting doesn't affect audio).
+      enableRemoteAudio(gSecondConnection, false);
+      enableRemoteVideo(gSecondConnection, false);
+
+      setTimeout(function() {
+        enableRemoteAudio(gSecondConnection, true);
+      }, 500);
+
+      setTimeout(function() {
+        ensureAudioPlaying(gSecondConnection);
+      }, 1500);
+    });
+  }
+
+  function callAndEnsureLocalVideoMutingDoesntMuteAudio() {
+    callAndEnsureAudioIsPlaying({audio: true, video: true});
+    setAllEventsOccuredHandler(function() {
+      setAllEventsOccuredHandler(reportTestSuccess);
+      enableLocalVideo(gFirstConnection, false);
+      ensureAudioPlaying(gSecondConnection);
+    });
+  }
+
+  function callAndEnsureRemoteVideoMutingDoesntMuteAudio() {
+    callAndEnsureAudioIsPlaying({audio: true, video: true});
+    setAllEventsOccuredHandler(function() {
+      setAllEventsOccuredHandler(reportTestSuccess);
+      enableRemoteVideo(gSecondConnection, false);
+      ensureAudioPlaying(gSecondConnection);
+    });
+  }
+
+  function createConnections(constraints) {
+    gFirstConnection = createConnection(constraints, 'remote-view-1');
+    assertEquals('stable', gFirstConnection.signalingState);
+
+    gSecondConnection = createConnection(constraints, 'remote-view-2');
+    assertEquals('stable', gSecondConnection.signalingState);
+  }
+
+  function createConnection(constraints, remoteView) {
+    var pc = new webkitRTCPeerConnection(null, constraints);
+    pc.onaddstream = function(event) {
+      onRemoteStream(event, remoteView);
+    }
+    return pc;
+  }
+
+  function displayAndRemember(localStream) {
+    var localStreamUrl = URL.createObjectURL(localStream);
+    $('local-view').src = localStreamUrl;
+
+    gLocalStream = localStream;
+  }
+
+  // Called if getUserMedia succeeds and we want to send from both connections.
+  function addStreamToBothConnectionsAndNegotiate(localStream) {
+    displayAndRemember(localStream);
+    gFirstConnection.addStream(localStream);
+    gSecondConnection.addStream(localStream);
+    negotiate();
+  }
+
+  // Called if getUserMedia succeeds when we want to send from one connection.
+  function addStreamToTheFirstConnectionAndNegotiate(localStream) {
+    displayAndRemember(localStream);
+    gFirstConnection.addStream(localStream);
+    negotiate();
+  }
+
+  function negotiate() {
+    negotiateBetween(gFirstConnection, gSecondConnection);
+  }
+
+  function onRemoteStream(e, target) {
+    console.log("Receiving remote stream...");
+    gRemoteStreams[target] = e.stream;
+    var remoteStreamUrl = URL.createObjectURL(e.stream);
+    var remoteVideo = $(target);
+    remoteVideo.src = remoteStreamUrl;
+  }
+
+  </script>
+</head>
+<body>
+  <table border="0">
+    <tr>
+      <td><video width="320" height="240" id="local-view" style="display:none"
+          autoplay muted></video></td>
+      <td><video width="320" height="240" id="remote-view-1"
+          style="display:none" autoplay></video></td>
+      <td><video width="320" height="240" id="remote-view-2"
+          style="display:none" autoplay></video></td>
+      <!-- Canvases are named after their corresponding video elements. -->
+      <td><canvas width="320" height="240" id="remote-view-1-canvas"
+          style="display:none"></canvas></td>
+      <td><canvas width="320" height="240" id="remote-view-2-canvas"
+          style="display:none"></canvas></td>
+    </tr>
+  </table>
+</body>
+</html>
diff --git a/content/test/data/media/peerconnection-call-data.html b/content/test/data/media/peerconnection-call-data.html
index a45356b..6dadbefc 100644
--- a/content/test/data/media/peerconnection-call-data.html
+++ b/content/test/data/media/peerconnection-call-data.html
@@ -3,7 +3,6 @@
 <head>
   <script type="text/javascript" src="webrtc_test_utilities.js"></script>
   <script type="text/javascript" src="webrtc_test_common.js"></script>
-  <script type="text/javascript" src="webrtc_test_audio.js"></script>
   <script type="text/javascript">
   $ = function(id) {
     return document.getElementById(id);
@@ -17,7 +16,6 @@
 
   var gFirstConnection = null;
   var gSecondConnection = null;
-  var gTestWithoutMsid = false;
   var gLocalStream = null;
 
   var gRemoteStreams = {};
@@ -235,10 +233,6 @@
 
   function onRemoteStream(e, target) {
     console.log("Receiving remote stream...");
-    if (gTestWithoutMsid && e.stream.id != "default") {
-      failTest('a default remote stream was expected but instead ' +
-          e.stream.id + ' was received.');
-    }
     gRemoteStreams[target] = e.stream;
     var remoteStreamUrl = URL.createObjectURL(e.stream);
     var remoteVideo = $(target);
diff --git a/content/test/data/media/peerconnection-call.html b/content/test/data/media/peerconnection-call.html
index b0b6758..9782ef9 100644
--- a/content/test/data/media/peerconnection-call.html
+++ b/content/test/data/media/peerconnection-call.html
@@ -2,7 +2,6 @@
 <head>
   <script type="text/javascript" src="webrtc_test_utilities.js"></script>
   <script type="text/javascript" src="webrtc_test_common.js"></script>
-  <script type="text/javascript" src="webrtc_test_audio.js"></script>
   <script type="text/javascript">
   $ = function(id) {
     return document.getElementById(id);
@@ -22,7 +21,6 @@
 
   var gRemoteStreams = {};
 
-
   setAllEventsOccuredHandler(reportTestSuccess);
 
   // Test that we can setup a call with an audio and video track (must request
@@ -99,28 +97,6 @@
     });
   }
 
-  // The second set of constraints should request audio (e.g. audio:true) since
-  // we expect audio to be playing after the second renegotiation.
-  function callAndRenegotiateToAudio(constraints, renegotiationConstraints) {
-    createConnections(null);
-    navigator.webkitGetUserMedia(constraints,
-        addStreamToBothConnectionsAndNegotiate, printGetUserMediaError);
-
-    waitForConnectionToStabilize(gFirstConnection, function() {
-      gFirstConnection.removeStream(gLocalStream);
-      gSecondConnection.removeStream(gLocalStream);
-
-      navigator.webkitGetUserMedia(renegotiationConstraints,
-          addStreamToTheFirstConnectionAndNegotiate, printGetUserMediaError);
-
-      var onCallEstablished = function() {
-        ensureAudioPlaying(gSecondConnection);
-      };
-
-      waitForConnectionToStabilize(gFirstConnection, onCallEstablished);
-    });
-  }
-
   // First makes a call between pc1 and pc2 where a stream is sent from pc1 to
   // pc2. The stream sent from pc1 to pc2 is cloned from the stream received on
   // pc2  to test that cloning of remote video tracks works as intended and is
@@ -270,33 +246,6 @@
         offerOptions);
   }
 
-  function callAndEnsureAudioIsPlaying(constraints) {
-    createConnections(null);
-
-    // Add the local stream to gFirstConnection to play one-way audio.
-    navigator.webkitGetUserMedia(constraints,
-      addStreamToTheFirstConnectionAndNegotiate, printGetUserMediaError);
-
-    var onCallEstablished = function() {
-      ensureAudioPlaying(gSecondConnection);
-    };
-
-    waitForConnectionToStabilize(gFirstConnection, onCallEstablished);
-  }
-
-  function callWithIsac16KAndEnsureAudioIsPlaying(constraints) {
-    setOfferSdpTransform(function(sdp) {
-      sdp = sdp.replace(/m=audio (\d+) RTP\/SAVPF.*\r\n/g,
-                        'm=audio $1 RTP/SAVPF 103 126\r\n');
-      sdp = sdp.replace('a=fmtp:111 minptime=10', 'a=fmtp:103 minptime=10');
-      if (sdp.search('a=rtpmap:103 ISAC/16000') == -1)
-        failTest('Missing iSAC 16K codec on Android; cannot force codec.');
-
-      return sdp;
-    });
-    callAndEnsureAudioIsPlaying(constraints);
-  }
-
   function enableRemoteVideo(peerConnection, enabled) {
     remoteStream = peerConnection.getRemoteStreams()[0];
     remoteStream.getVideoTracks()[0].enabled = enabled;
@@ -307,78 +256,6 @@
     remoteStream.getAudioTracks()[0].enabled = enabled;
   }
 
-  function enableLocalVideo(peerConnection, enabled) {
-    localStream = peerConnection.getLocalStreams()[0];
-    localStream.getVideoTracks()[0].enabled = enabled;
-  }
-
-  function enableLocalAudio(peerConnection, enabled) {
-    localStream = peerConnection.getLocalStreams()[0];
-    localStream.getAudioTracks()[0].enabled = enabled;
-  }
-
-  function callAndEnsureRemoteAudioTrackMutingWorks() {
-    callAndEnsureAudioIsPlaying({audio: true, video: true});
-    setAllEventsOccuredHandler(function() {
-      setAllEventsOccuredHandler(reportTestSuccess);
-
-      // Call is up, now mute the remote track and check we stop playing out
-      // audio (after a small delay, we don't expect it to happen instantly).
-      enableRemoteAudio(gSecondConnection, false);
-      ensureSilence(gSecondConnection);
-    });
-  }
-
-  function callAndEnsureLocalAudioTrackMutingWorks() {
-    callAndEnsureAudioIsPlaying({audio: true, video: true});
-    setAllEventsOccuredHandler(function() {
-      setAllEventsOccuredHandler(reportTestSuccess);
-
-      // Call is up, now mute the local track of the sending side and ensure
-      // the receiving side stops receiving audio.
-      enableLocalAudio(gFirstConnection, false);
-      ensureSilence(gSecondConnection);
-    });
-  }
-
-  function callAndEnsureAudioTrackUnmutingWorks() {
-    callAndEnsureAudioIsPlaying({audio: true, video: true});
-    setAllEventsOccuredHandler(function() {
-      setAllEventsOccuredHandler(reportTestSuccess);
-
-      // Mute, wait a while, unmute, verify audio gets back up.
-      // (Also, ensure video muting doesn't affect audio).
-      enableRemoteAudio(gSecondConnection, false);
-      enableRemoteVideo(gSecondConnection, false);
-
-      setTimeout(function() {
-        enableRemoteAudio(gSecondConnection, true);
-      }, 500);
-
-      setTimeout(function() {
-        ensureAudioPlaying(gSecondConnection);
-      }, 1500);
-    });
-  }
-
-  function callAndEnsureLocalVideoMutingDoesntMuteAudio() {
-    callAndEnsureAudioIsPlaying({audio: true, video: true});
-    setAllEventsOccuredHandler(function() {
-      setAllEventsOccuredHandler(reportTestSuccess);
-      enableLocalVideo(gFirstConnection, false);
-      ensureAudioPlaying(gSecondConnection);
-    });
-  }
-
-  function callAndEnsureRemoteVideoMutingDoesntMuteAudio() {
-    callAndEnsureAudioIsPlaying({audio: true, video: true});
-    setAllEventsOccuredHandler(function() {
-      setAllEventsOccuredHandler(reportTestSuccess);
-      enableRemoteVideo(gSecondConnection, false);
-      ensureAudioPlaying(gSecondConnection);
-    });
-  }
-
   function callAndEnsureVideoTrackMutingWorks() {
     createConnections(null);
     navigator.webkitGetUserMedia({audio: true, video: true},
@@ -710,7 +587,6 @@
     return sdp.replace(/a=group:BUNDLE .*\r\n/g, '');
   }
 
-
   function onRemoteStream(e, target) {
     console.log("Receiving remote stream...");
     if (gTestWithoutMsid && e.stream.id != "default") {
diff --git a/content/test/gpu/gpu_tests/cloud_storage_test_base.py b/content/test/gpu/gpu_tests/cloud_storage_test_base.py
index 73a32479..1ddf9c34 100644
--- a/content/test/gpu/gpu_tests/cloud_storage_test_base.py
+++ b/content/test/gpu/gpu_tests/cloud_storage_test_base.py
@@ -96,6 +96,7 @@
     self.vendor_string = None
     self.device_string = None
     self.msaa = False
+    self.model_name = None
 
   ###
   ### Routines working with the local disk (only used for local
@@ -165,6 +166,7 @@
           system_info.gpu.driver_bug_workarounds) or
         ('disable_multisample_render_to_texture' in
           system_info.gpu.driver_bug_workarounds))
+    self.model_name = system_info.model_name
 
   def _FormatGpuInfo(self, tab):
     self._ComputeGpuInfo(tab)
@@ -173,9 +175,14 @@
       return '%s_%04x_%04x%s' % (
         self.options.os_type, self.vendor_id, self.device_id, msaa_string)
     else:
-      return '%s_%s_%s%s' % (
+      # This is the code path for Android devices. Include the model
+      # name (e.g. "Nexus 9") in the GPU string to disambiguate
+      # multiple devices on the waterfall which might have the same
+      # device string ("NVIDIA Tegra") but different screen
+      # resolutions and device pixel ratios.
+      return '%s_%s_%s_%s%s' % (
         self.options.os_type, self.vendor_string, self.device_string,
-        msaa_string)
+        self.model_name, msaa_string)
 
   def _FormatReferenceImageName(self, img_name, page, tab):
     return '%s_v%s_%s.png' % (
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index 2a054c0..036f354d 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -30,3 +30,7 @@
     # TODO(erikchen) check / generate reference images.
     self.Fail('Pixel.CSSFilterEffects', ['mac'], bug=581526)
     self.Fail('Pixel.CSSFilterEffects.NoOverlays', ['mac'], bug=581526)
+
+    # TODO(kbr): remove once expectations for Android have been
+    # generated using the new naming convention.
+    self.Fail('*', ['android'], bug=624621)
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 746f0aa..3887e7f 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -30,7 +30,6 @@
     # ========================
 
     # 2.0.1 OR LATER
-
     # Too slow (take about one hour to run)
     self.Skip('deqp/functional/gles3/builtinprecision/*.html', bug=619403)
 
@@ -39,14 +38,8 @@
         ['linux'], bug=483282)
 
     # All platforms.
-
     self.Flaky('conformance2/query/occlusion-query.html', bug=603168)
 
-    self.Fail('conformance2/rendering/attrib-type-match.html', bug=627193)
-
-    self.Fail('conformance2/transform_feedback/' +
-        'unwritten-output-defaults-to-zero.html', bug=1441) # ANGLE bug
-
     # Avoid a conflict with a Mac expectation by setting
     self.Fail('conformance2/textures/misc/tex-input-validation.html',
         ['d3d9', 'd3d11', 'opengl'], bug=483282)
@@ -55,16 +48,23 @@
     self.Fail('deqp/functional/gles3/multisample.html',
         ['amd'], bug=617290)
 
-    self.Fail('conformance2/rendering/framebuffer-unsupported.html',
-        bug=628861)
-
-    self.Fail('conformance/glsl/misc/shaders-with-invariance.html',
-        bug=1450) # ANGLE bug
-    # self.Fail('conformance/glsl/misc/shaders-with-invariance.html',
-    #     ['mac'], bug=483282)
-    # self.Fail('conformance/glsl/misc/shaders-with-invariance.html',
-    #     ['linux', 'amd', 'intel'], bug=483282)
-
+    # Windows only.
+    self.Fail('conformance/glsl/bugs/' +
+        'pow-of-small-constant-in-user-defined-function.html',
+        ['win'], bug=485641)
+    self.Fail('conformance/misc/uninitialized-test.html',
+        ['win'], bug=483282)
+    self.Fail('conformance/rendering/point-specific-shader-variables.html',
+        ['win'], bug=616335)
+    self.Fail('conformance/textures/webgl_canvas/' +
+        'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html',
+        ['win'], bug=483282)
+    self.Fail('conformance/textures/webgl_canvas/' +
+        'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html',
+        ['win'], bug=483282)
+    self.Fail('conformance/textures/webgl_canvas/' +
+        'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
+        ['win'], bug=483282)
     self.Fail('conformance/textures/image_bitmap_from_canvas/' +
         'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html',
         ['win'], bug=628954)
@@ -75,55 +75,22 @@
         'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
         ['win'], bug=628954)
 
-    # Windows only.
-    self.Fail('conformance/glsl/bugs/' +
-              'pow-of-small-constant-in-user-defined-function.html',
-        ['win'], bug=485641)
-    self.Fail('conformance/misc/uninitialized-test.html',
-        ['win'], bug=483282)
-    self.Fail('conformance/rendering/point-specific-shader-variables.html',
-        ['win'], bug=616335)
-    self.Fail('conformance/textures/canvas/' +
-              'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html',
-              ['win'], bug=483282)
-    self.Fail('conformance/textures/canvas/' +
-              'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html',
-              ['win'], bug=483282)
-    self.Fail('conformance/textures/canvas/' +
-              'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
-              ['win'], bug=483282)
-    self.Fail('conformance/textures/webgl_canvas/' +
-              'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html',
-              ['win'], bug=483282)
-    self.Fail('conformance/textures/webgl_canvas/' +
-              'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html',
-              ['win'], bug=483282)
-    self.Fail('conformance/textures/webgl_canvas/' +
-              'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
-              ['win'], bug=483282)
     self.Fail('deqp/data/gles2/shaders/functions.html',
         ['win'], bug=478572)
 
-    self.Fail('conformance2/glsl3/array-in-complex-expression.html',
-        ['win'], bug=483282)
-
-    self.Fail('deqp/functional/gles3/fboinvalidate/whole.html',
-        ['win'], bug=624506)
-
     # ANGLE bug id
-    self.Fail('deqp/functional/gles3/fbomultisample*',
-        ['win'], bug=1246)
     self.Fail('deqp/functional/gles3/fboinvalidate/sub.html',
         ['win'], bug=1246)
 
     # Windows 8 only.
-
     self.Flaky('deqp/functional/gles3/buffercopy.html', ['win8'], bug=587601)
 
     # Win / NVidia
     # La la la la la la la la la la ...
 
     # Win / AMD
+    self.Fail('deqp/functional/gles3/fbomultisample.8_samples.html',
+        ['win', ('amd', 0x6779)], bug=483282)
     self.Fail('deqp/functional/gles3/texturespecification/' +
         'texstorage2d_format_depth_stencil.html',
         ['win', ('amd', 0x6779)], bug=614178)
@@ -205,6 +172,8 @@
         ['win', 'intel'], bug=483282)
     self.Fail('deqp/functional/gles3/textureshadow/2d_array_*.html',
         ['win', 'intel'], bug=483282)
+    self.Fail('conformance2/rendering/uniform-block-buffer-size.html',
+        ['win', 'intel'], bug=628863)
 
     # It's unfortunate that these suppressions need to be so broad, but it
     # looks like the D3D11 device can be lost spontaneously on this
@@ -214,10 +183,16 @@
     self.Flaky('deqp/*', ['win', 'intel'], bug=628395)
 
     # Mac only.
+    self.Fail('conformance/glsl/misc/shaders-with-invariance.html',
+        ['mac'], bug=483282)
     self.Flaky('deqp/functional/gles3/shaderindexing/varying.html',
         ['mac'], bug=619264)
     self.Fail('deqp/functional/gles3/shaderloop_do_while.html',
         ['mac'], bug=617820)
+    self.Fail('deqp/functional/gles3/fbocompleteness.html',
+        ['mac'], bug=630800)
+    # self.Fail('deqp/functional/gles3/fbocompleteness.html',
+    #     ['mac', ('nvidia', 0xfe9)], bug=616562)
     self.Fail('deqp/data/gles3/shaders/linkage.html',
         ['mac'], bug=601821)
 
@@ -307,8 +282,6 @@
         ['mac', ('nvidia', 0xfe9)], bug=483282)
     self.Fail('deqp/functional/gles3/negativevertexarrayapi.html',
         ['mac', ('nvidia', 0xfe9)], bug=483282)
-    self.Fail('deqp/functional/gles3/fbocompleteness.html',
-        ['mac', ('nvidia', 0xfe9)], bug=616562)
 
     self.Fail('deqp/functional/gles3/texturespecification/' +
         'basic_copyteximage2d.html',
@@ -528,9 +501,6 @@
                'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
                ['linux'], bug=627525)
 
-    self.Fail('deqp/functional/gles3/fboinvalidate/whole.html',
-        ['linux'], bug=624506)
-
     # Multi-vendor failures.
 
     self.Fail('deqp/data/gles3/shaders/functions.html',
@@ -542,6 +512,10 @@
     self.Flaky('deqp/functional/gles3/texturespecification/' +
         'random_teximage2d_2d.html',
         ['linux', 'amd', 'intel'], bug=618447)
+    self.Fail('conformance/glsl/misc/shaders-with-invariance.html',
+        ['linux', 'amd', 'intel'], bug=483282)
+    self.Fail('deqp/data/gles3/shaders/linkage.html',
+        ['linux', 'amd', 'intel'], bug=483282)
 
     # Linux with ANGLE only
     self.Fail('conformance/misc/uninitialized-test.html',
@@ -851,6 +825,10 @@
 
     self.Fail('conformance2/glsl3/vector-dynamic-indexing.html',
         ['linux', 'amd'], bug=483282)
+    self.Fail('conformance2/reading/read-pixels-pack-parameters.html',
+        ['linux', 'amd', 'no_angle'], bug=483282)
+    self.Fail('conformance2/textures/misc/tex-unpack-params.html',
+        ['linux', 'amd', 'no_angle'], bug=483282)
 
     # Conflicting expectations to test that the
     # "Expectations Have No collisions" unittest works.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 0325776..40fd92e 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -726,6 +726,8 @@
         ['linux', 'debug', ('intel', 0x412)], bug=604140)
 
     # Android failures
+    self.Fail('conformance/glsl/bugs/sequence-operator-evaluation-order.html',
+        ['android'], bug=478572)
     self.Fail('deqp/data/gles2/shaders/constants.html',
         ['android'], bug=478572)
     self.Fail('deqp/data/gles2/shaders/conversions.html',
diff --git a/content/test/gpu/page_sets/gpu_process_tests.py b/content/test/gpu/page_sets/gpu_process_tests.py
index ed93014..f147cba9 100644
--- a/content/test/gpu/page_sets/gpu_process_tests.py
+++ b/content/test/gpu/page_sets/gpu_process_tests.py
@@ -522,6 +522,54 @@
         (browser_list, gpu_list, list(diff)))
 
 
+class HasTransparentVisualsShared(GpuProcessSharedPageState):
+  def __init__(self, test, finder_options, story_set):
+    super(HasTransparentVisualsShared, self).__init__(
+      test, finder_options, story_set)
+    options = finder_options.browser_options
+    if sys.platform.startswith('linux'):
+      # Hit id 173 from kGpuDriverBugListJson.
+      options.AppendExtraBrowserArgs('--gpu-testing-gl-version=3.0 Mesa ' \
+                                     '12.1')
+
+class HasTransparentVisualsGpuProcessPage(DriverBugWorkaroundsTestsPage):
+  def __init__(self, story_set, expectations):
+    super(HasTransparentVisualsGpuProcessPage, self).__init__(
+      name='GpuProcess.has_transparent_visuals_gpu_process',
+      page_set=story_set,
+      shared_page_state_class=HasTransparentVisualsShared,
+      expectations=expectations,
+      expected_workaround=None,
+      unexpected_workaround='disable_transparent_visuals')
+
+  def Validate(self, tab, results):
+    if sys.platform.startswith('linux'):
+      super(HasTransparentVisualsGpuProcessPage, self).Validate(tab, results)
+
+
+class NoTransparentVisualsShared(GpuProcessSharedPageState):
+  def __init__(self, test, finder_options, story_set):
+    super(NoTransparentVisualsShared, self).__init__(
+      test, finder_options, story_set)
+    options = finder_options.browser_options
+    if sys.platform.startswith('linux'):
+      options.AppendExtraBrowserArgs('--disable_transparent_visuals=1')
+
+class NoTransparentVisualsGpuProcessPage(DriverBugWorkaroundsTestsPage):
+  def __init__(self, story_set, expectations):
+    super(NoTransparentVisualsGpuProcessPage, self).__init__(
+      name='GpuProcess.no_transparent_visuals_gpu_process',
+      page_set=story_set,
+      shared_page_state_class=NoTransparentVisualsShared,
+      expectations=expectations,
+      expected_workaround='disable_transparent_visuals',
+      unexpected_workaround=None)
+
+  def Validate(self, tab, results):
+    if sys.platform.startswith('linux'):
+      super(NoTransparentVisualsGpuProcessPage, self).Validate(tab, results)
+
+
 class GpuProcessTestsStorySet(story_set_module.StorySet):
 
   """ Tests that accelerated content triggers the creation of a GPU process """
@@ -546,8 +594,6 @@
     self.AddStory(GpuInfoCompletePage(self, expectations))
     self.AddStory(NoGpuProcessPage(self, expectations))
     self.AddStory(SoftwareGpuProcessPage(self, expectations))
-    if not is_platform_android:
-      self.AddStory(SkipGpuProcessPage(self, expectations))
     self.AddStory(DriverBugWorkaroundsInGpuProcessPage(self, expectations))
     self.AddStory(IdentifyActiveGpuPage1(self, expectations))
     self.AddStory(IdentifyActiveGpuPage2(self, expectations))
@@ -557,6 +603,10 @@
     self.AddStory(DriverBugWorkaroundsUponGLRendererPage(self, expectations))
     self.AddStory(EqualBugWorkaroundsInBrowserAndGpuProcessPage(self,
                                                                 expectations))
+    if not is_platform_android:
+      self.AddStory(SkipGpuProcessPage(self, expectations))
+      self.AddStory(HasTransparentVisualsGpuProcessPage(self, expectations))
+      self.AddStory(NoTransparentVisualsGpuProcessPage(self, expectations))
 
   @property
   def allow_mixed_story_states(self):
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 816a480..904e900 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -17,7 +17,7 @@
 #include "components/scheduler/test/renderer_scheduler_test_support.h"
 #include "components/test_runner/test_common.h"
 #include "components/test_runner/web_frame_test_proxy.h"
-#include "components/test_runner/web_test_proxy.h"
+#include "components/test_runner/web_view_test_proxy.h"
 #include "content/browser/bluetooth/bluetooth_device_chooser_controller.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -70,17 +70,18 @@
 base::LazyInstance<FrameProxyCreationCallback>::Leaky
     g_frame_test_proxy_callback = LAZY_INSTANCE_INITIALIZER;
 
-using WebTestProxyType = test_runner::WebTestProxy<RenderViewImpl,
-                                                   CompositorDependencies*,
-                                                   const ViewMsg_New_Params&>;
+using WebViewTestProxyType =
+    test_runner::WebViewTestProxy<RenderViewImpl,
+                                  CompositorDependencies*,
+                                  const ViewMsg_New_Params&>;
 using WebFrameTestProxyType =
     test_runner::WebFrameTestProxy<RenderFrameImpl,
                                    const RenderFrameImpl::CreateParams&>;
 
-RenderViewImpl* CreateWebTestProxy(CompositorDependencies* compositor_deps,
-                                   const ViewMsg_New_Params& params) {
-  WebTestProxyType* render_view_proxy =
-      new WebTestProxyType(compositor_deps, params);
+RenderViewImpl* CreateWebViewTestProxy(CompositorDependencies* compositor_deps,
+                                       const ViewMsg_New_Params& params) {
+  WebViewTestProxyType* render_view_proxy =
+      new WebViewTestProxyType(compositor_deps, params);
   if (g_view_test_proxy_callback == 0)
     return render_view_proxy;
   g_view_test_proxy_callback.Get().Run(render_view_proxy, render_view_proxy);
@@ -112,10 +113,11 @@
 
 }  // namespace
 
-test_runner::WebTestProxyBase* GetWebTestProxyBase(RenderView* render_view) {
-  WebTestProxyType* render_view_proxy =
-      static_cast<WebTestProxyType*>(render_view);
-  return static_cast<test_runner::WebTestProxyBase*>(render_view_proxy);
+test_runner::WebViewTestProxyBase* GetWebViewTestProxyBase(
+    RenderView* render_view) {
+  WebViewTestProxyType* render_view_proxy =
+      static_cast<WebViewTestProxyType*>(render_view);
+  return static_cast<test_runner::WebViewTestProxyBase*>(render_view_proxy);
 }
 
 test_runner::WebFrameTestProxyBase* GetWebFrameTestProxyBase(
@@ -130,7 +132,7 @@
     const FrameProxyCreationCallback& frame_proxy_creation_callback) {
   g_view_test_proxy_callback.Get() = view_proxy_creation_callback;
   g_frame_test_proxy_callback.Get() = frame_proxy_creation_callback;
-  RenderViewImpl::InstallCreateHook(CreateWebTestProxy);
+  RenderViewImpl::InstallCreateHook(CreateWebViewTestProxy);
   RenderFrameImpl::InstallCreateHook(CreateWebFrameTestProxy);
 }
 
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc
index 019da1c8..b6ed473 100644
--- a/content/test/test_blink_web_unit_test_support.cc
+++ b/content/test/test_blink_web_unit_test_support.cc
@@ -191,7 +191,7 @@
   // This loader should be used only for process-local resources such as
   // data URLs.
   blink::WebURLLoader* default_loader = new WebURLLoaderImpl(
-      nullptr, base::WrapUnique(currentThread->getWebTaskRunner()->clone()));
+      nullptr, currentThread->getWebTaskRunner()->clone());
   return url_loader_factory_->createURLLoader(default_loader);
 }
 
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index e6284f3f..896d87b 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -14,6 +14,7 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/frame_messages.h"
 #include "content/common/frame_owner_properties.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/stream_handle.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/url_constants.h"
@@ -106,6 +107,7 @@
 
   OnDidStartLoading(true);
   OnDidStartProvisionalLoad(url, base::TimeTicks::Now());
+  SimulateWillStartRequest(ui::PAGE_TRANSITION_LINK);
 }
 
 void TestRenderFrameHost::SimulateRedirect(const GURL& new_url) {
@@ -290,6 +292,7 @@
   // so we keep a copy of it to use below.
   GURL url_copy(url);
   OnDidStartProvisionalLoad(url_copy, base::TimeTicks::Now());
+  SimulateWillStartRequest(transition);
 
   FrameHostMsg_DidCommitProvisionalLoad_Params params;
   params.page_id = page_id;
@@ -440,4 +443,13 @@
   return page_id;
 }
 
+void TestRenderFrameHost::SimulateWillStartRequest(
+    ui::PageTransition transition) {
+  if (!navigation_handle())
+    return;
+  navigation_handle()->CallWillStartRequestForTesting(
+      false /* is_post */, Referrer(GURL(), blink::WebReferrerPolicyDefault),
+      true /* user_gesture */, transition, false /* is_external_protocol */);
+}
+
 }  // namespace content
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index 32aa044..7a9b6bfc 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -149,6 +149,8 @@
   // Computes the page ID for a pending navigation in this RenderFrameHost;
   int32_t ComputeNextPageID();
 
+  void SimulateWillStartRequest(ui::PageTransition transition);
+
   TestRenderFrameHostCreationObserver child_creation_observer_;
 
   std::string contents_mime_type_;
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index 29fc6f7..81252ea 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -64,17 +64,28 @@
       is_occluded_(false),
       did_swap_compositor_frame_(false) {
 #if defined(OS_ANDROID)
-    surface_id_allocator_ = CreateSurfaceIdAllocator();
+  surface_id_allocator_.reset(
+      new cc::SurfaceIdAllocator(AllocateSurfaceClientId()));
+  GetSurfaceManager()->RegisterSurfaceClientId(
+      surface_id_allocator_->client_id());
 #else
   // Not all tests initialize or need an image transport factory.
-  if (ImageTransportFactory::GetInstance())
-    surface_id_allocator_ = CreateSurfaceIdAllocator();
+  if (ImageTransportFactory::GetInstance()) {
+    surface_id_allocator_.reset(
+        new cc::SurfaceIdAllocator(AllocateSurfaceClientId()));
+    GetSurfaceManager()->RegisterSurfaceClientId(
+        surface_id_allocator_->client_id());
+  }
 #endif
 
   rwh_->SetView(this);
 }
 
 TestRenderWidgetHostView::~TestRenderWidgetHostView() {
+  if (GetSurfaceManager()) {
+    GetSurfaceManager()->InvalidateSurfaceClientId(
+        surface_id_allocator_->client_id());
+  }
 }
 
 RenderWidgetHost* TestRenderWidgetHostView::GetRenderWidgetHost() const {
diff --git a/extensions/browser/api/app_window/app_window_apitest.cc b/extensions/browser/api/app_window/app_window_apitest.cc
index 63ac734..3d68f862 100644
--- a/extensions/browser/api/app_window/app_window_apitest.cc
+++ b/extensions/browser/api/app_window/app_window_apitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
@@ -23,6 +24,10 @@
 #include "ui/base/win/shell.h"
 #endif
 
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#include "ui/gfx/x/x11_switches.h"
+#endif
+
 namespace extensions {
 
 namespace {
@@ -130,20 +135,30 @@
 
 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
                        WindowsApiAlphaEnabledHasPermissions) {
-  const char* no_alpha_dir =
+  const char kNoAlphaDir[] =
       "platform_apps/windows_api_alpha_enabled/has_permissions_no_alpha";
-  const char* test_dir = no_alpha_dir;
+  const char kHasAlphaDir[] =
+      "platform_apps/windows_api_alpha_enabled/has_permissions_has_alpha";
+  ALLOW_UNUSED_LOCAL(kHasAlphaDir);
+  const char* test_dir = kNoAlphaDir;
 
 #if defined(USE_AURA) && (defined(OS_CHROMEOS) || !defined(OS_LINUX))
-  test_dir =
-      "platform_apps/windows_api_alpha_enabled/has_permissions_has_alpha";
+  test_dir = kHasAlphaDir;
+
 #if defined(OS_WIN)
   if (!ui::win::IsAeroGlassEnabled()) {
-    test_dir = no_alpha_dir;
+    test_dir = kNoAlphaDir;
   }
 #endif  // OS_WIN
 #endif  // USE_AURA && (OS_CHROMEOS || !OS_LINUX)
 
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+  if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kWindowDepth) == "32") {
+    test_dir = kHasAlphaDir;
+  }
+#endif  // USE_X11 && !OS_CHROMEOS
+
   EXPECT_TRUE(RunPlatformAppTest(test_dir)) << message_;
 }
 
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc
index 9da2b991..28c429b 100644
--- a/extensions/common/features/simple_feature.cc
+++ b/extensions/common/features/simple_feature.cc
@@ -667,10 +667,38 @@
   return (extension_id.length() == 32);
 }
 
+void SimpleFeature::set_blacklist(std::vector<std::string>&& blacklist) {
+  blacklist_ = blacklist;
+}
+
+void SimpleFeature::set_command_line_switch(std::string&& command_line_switch) {
+  command_line_switch_ = command_line_switch;
+}
+
+void SimpleFeature::set_contexts(std::vector<Context>&& contexts) {
+  contexts_ = contexts;
+}
+
+void SimpleFeature::set_dependencies(std::vector<std::string>&& dependencies) {
+  dependencies_ = dependencies;
+}
+
+void SimpleFeature::set_extension_types(std::vector<Manifest::Type>&& types) {
+  extension_types_ = types;
+}
+
 void SimpleFeature::set_matches(const std::vector<std::string>& matches) {
   matches_.ClearPatterns();
   for (const std::string& pattern : matches)
     matches_.AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern));
 }
 
+void SimpleFeature::set_platforms(std::vector<Platform>&& platforms) {
+  platforms_ = platforms;
+}
+
+void SimpleFeature::set_whitelist(std::vector<std::string>&& whitelist) {
+  whitelist_ = whitelist;
+}
+
 }  // namespace extensions
diff --git a/extensions/common/features/simple_feature.h b/extensions/common/features/simple_feature.h
index b0bda2d..b427582 100644
--- a/extensions/common/features/simple_feature.h
+++ b/extensions/common/features/simple_feature.h
@@ -99,29 +99,27 @@
   };
 
   // Setters used by generated code to create the feature.
-  void set_blacklist(const std::vector<std::string>& blacklist) {
-    blacklist_ = blacklist;
-  }
+  // NOTE: These setters use rvalue references deliberately. These should only
+  // ever be used by generated code, and we ensure that in each call, the new
+  // value is constructed in-place. This allows us to avoid a copy when we
+  // assign it to the value in this class, and results in noticable improvements
+  // in both speed and binary size.
+  void set_blacklist(std::vector<std::string>&& blacklist);
   void set_channel(version_info::Channel channel) {
     channel_.reset(new version_info::Channel(channel));
   }
-  void set_command_line_switch(const std::string& command_line_switch) {
-    command_line_switch_ = command_line_switch;
-  }
+  void set_command_line_switch(std::string&& command_line_switch);
   void set_component_extensions_auto_granted(bool granted) {
     component_extensions_auto_granted_ = granted;
   }
-  void set_contexts(const std::vector<Context>& contexts) {
-    contexts_ = contexts;
-  }
-  void set_dependencies(const std::vector<std::string>& dependencies) {
-    dependencies_ = dependencies;
-  }
-  void set_extension_types(const std::vector<Manifest::Type> types) {
-    extension_types_ = types;
-  }
+  void set_contexts(std::vector<Context>&& contexts);
+  void set_dependencies(std::vector<std::string>&& dependencies);
+  void set_extension_types(std::vector<Manifest::Type>&& types);
   void set_internal(bool is_internal) { is_internal_ = is_internal; }
   void set_location(Location location) { location_ = location; }
+  // set_matches() is an exception to pass-by-value since we construct an
+  // URLPatternSet from the vector of strings.
+  // TODO(devlin): Pass in an URLPatternSet directly.
   void set_matches(const std::vector<std::string>& matches);
   void set_max_manifest_version(int max_manifest_version) {
     max_manifest_version_ = max_manifest_version;
@@ -129,12 +127,8 @@
   void set_min_manifest_version(int min_manifest_version) {
     min_manifest_version_ = min_manifest_version;
   }
-  void set_platforms(const std::vector<Platform>& platforms) {
-    platforms_ = platforms;
-  }
-  void set_whitelist(const std::vector<std::string>& whitelist) {
-    whitelist_ = whitelist;
-  }
+  void set_platforms(std::vector<Platform>&& platforms);
+  void set_whitelist(std::vector<std::string>&& whitelist);
 
  protected:
   // Accessors used by subclasses in feature verification.
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc
index 587087bd..d20d21d 100644
--- a/extensions/renderer/script_context.cc
+++ b/extensions/renderer/script_context.cc
@@ -108,7 +108,7 @@
       effective_context_type_(effective_context_type),
       safe_builtins_(this),
       isolate_(v8_context->GetIsolate()),
-      url_(web_frame_ ? GetDataSourceURLForFrame(web_frame_) : GURL()),
+      url_(web_frame_ ? GURL(web_frame_->document().url()) : GURL()),
       runner_(new Runner(this)) {
   VLOG(1) << "Created context:\n" << GetDebugString();
   gin::PerContextData* gin_data = gin::PerContextData::From(v8_context);
diff --git a/extensions/renderer/script_context_set.cc b/extensions/renderer/script_context_set.cc
index adefb38..be8035b 100644
--- a/extensions/renderer/script_context_set.cc
+++ b/extensions/renderer/script_context_set.cc
@@ -140,8 +140,21 @@
     // Isolated worlds (content script).
     extension_id = ScriptInjection::GetHostIdForIsolatedWorld(world_id);
   } else {
-    // Extension pages (chrome-extension:// URLs).
-    GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame);
+    // For looking up the extension associated with this frame, we either want
+    // to use the current url or possibly the data source url (which this frame
+    // may be navigating to shortly), depending on the security origin of the
+    // frame. We don't always want to use the data source url because some
+    // frames (eg iframes and windows created via window.open) briefly contain
+    // an about:blank script context that is scriptable by their parent/opener
+    // before they finish navigating.
+    GURL frame_url(frame->document().url());
+    GURL data_src_url = ScriptContext::GetDataSourceURLForFrame(frame);
+    if (frame_url.is_empty() && data_src_url.is_valid() &&
+        frame->getSecurityOrigin().canAccess(
+            blink::WebSecurityOrigin::create(data_src_url))) {
+      frame_url = data_src_url;
+    }
+
     frame_url = ScriptContext::GetEffectiveDocumentURL(frame, frame_url,
                                                        use_effective_url);
     extension_id =
diff --git a/gin/BUILD.gn b/gin/BUILD.gn
index 4da0428..72d0125 100644
--- a/gin/BUILD.gn
+++ b/gin/BUILD.gn
@@ -2,8 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build_overrides/v8.gni")
 import("//testing/test.gni")
+import("//v8/gni/v8.gni")
 
 component("gin") {
   sources = [
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index a53b93f..891458c 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -21,7 +21,6 @@
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/transform_feedback_manager.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_version_info.h"
 #include "ui/gl/trace_util.h"
 
@@ -359,8 +358,9 @@
 
 bool BufferManager::UseShadowBuffer(GLenum target, GLenum usage) {
   const bool is_client_side_array = IsUsageClientSideArray(usage);
+  // feature_info_ can be null in some unit tests.
   const bool support_fixed_attribs =
-      gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2;
+      !feature_info_ || feature_info_->gl_version_info().is_es;
 
   // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002.
   return (
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index 4c907b1..94bf14d 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -434,6 +434,7 @@
                          max_varying_vectors_,
                          max_draw_buffers_,
                          max_dual_source_draw_buffers_,
+                         max_vertex_attribs_,
                          gpu_preferences_,
                          feature_info_.get()));
 
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc
index c19ffa52..ce03cbd 100644
--- a/gpu/command_buffer/service/context_state.cc
+++ b/gpu/command_buffer/service/context_state.cc
@@ -222,6 +222,7 @@
       ignore_cached_state(false),
       fbo_binding_for_scissor_workaround_dirty(false),
       framebuffer_srgb_(false),
+      max_vertex_attribs_(0),
       feature_info_(feature_info),
       error_state_(ErrorState::Create(error_state_client, logger)) {
   Initialize();
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index d026df9a..6e2d293 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -243,6 +243,32 @@
   void SetBoundBuffer(GLenum target, Buffer* buffer);
   void RemoveBoundBuffer(Buffer* buffer);
 
+  void InitGenericAttribBaseType(GLuint max_vertex_attribs) {
+      max_vertex_attribs_ = max_vertex_attribs;
+
+      uint32_t packed_size = max_vertex_attribs_ / 16;
+      packed_size += (max_vertex_attribs_ % 16 == 0) ? 0 : 1;
+      generic_attrib_base_type_mask_.resize(packed_size);
+      for (uint32_t i = 0; i < packed_size; ++i) {
+        // All generic attribs are float type by default.
+        generic_attrib_base_type_mask_[i] = 0x55555555u * SHADER_VARIABLE_FLOAT;
+      }
+  }
+
+  void SetGenericVertexAttribBaseType(GLuint index, GLenum base_type) {
+    DCHECK(index < max_vertex_attribs_);
+    int shift_bits = (index % 16) * 2;
+    generic_attrib_base_type_mask_[index / 16] &= ~(0x3 << shift_bits);
+    generic_attrib_base_type_mask_[index / 16] |= (base_type << shift_bits);
+  }
+
+  // Return 16 attributes' base types, in which the generic attribute
+  // specified by argument 'index' located.
+  uint32_t GetGenericVertexAttribBaseTypeMask(GLuint index) {
+    DCHECK(index < max_vertex_attribs_);
+    return generic_attrib_base_type_mask_[index / 16];
+  }
+
   void UnbindTexture(TextureRef* texture);
   void UnbindSampler(Sampler* sampler);
 
@@ -320,6 +346,12 @@
 
   bool framebuffer_srgb_;
 
+  uint32_t max_vertex_attribs_;
+  // Generic vertex attrib base types: FLOAT, INT, or UINT.
+  // Each base type is encoded into 2 bits, the lowest 2 bits for location 0,
+  // the highest 2 bits for location (max_vertex_attribs_ - 1).
+  std::vector<uint32_t> generic_attrib_base_type_mask_;
+
   FeatureInfo* feature_info_;
   std::unique_ptr<ErrorState> error_state_;
 };
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 46cd137b..4eae5f8 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -1424,6 +1424,21 @@
   return false;
 }
 
+bool FeatureInfo::IsWebGL2OrES3Context() const {
+  // Switch statement to cause a compile-time error if we miss a case.
+  switch (context_type_) {
+    case CONTEXT_TYPE_WEBGL2:
+    case CONTEXT_TYPE_OPENGLES3:
+      return true;
+    case CONTEXT_TYPE_WEBGL1:
+    case CONTEXT_TYPE_OPENGLES2:
+      return false;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
 void FeatureInfo::AddExtensionString(const char* s) {
   std::string str(s);
   size_t pos = extensions_.find(str);
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index 8b7b6acb..0ac0b0b7 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -150,6 +150,7 @@
   bool disable_shader_translator() const { return disable_shader_translator_; }
 
   bool IsWebGLContext() const;
+  bool IsWebGL2OrES3Context() const;
 
   void EnableCHROMIUMColorBufferFloatRGBA();
   void EnableCHROMIUMColorBufferFloatRGB();
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index caa129e9..cce15a22 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -421,24 +421,39 @@
 }
 
 bool Framebuffer::HasUnclearedAttachment(
-    GLenum attachment) const {
-  AttachmentMap::const_iterator it =
-      attachments_.find(attachment);
-  if (it != attachments_.end()) {
-    const Attachment* attachment = it->second.get();
-    return !attachment->cleared();
+    GLenum attachment_type) const {
+  const Attachment* attachment = GetAttachment(attachment_type);
+  switch (attachment_type) {
+    case GL_DEPTH_ATTACHMENT:
+    case GL_STENCIL_ATTACHMENT:
+      attachment = attachment ? attachment :
+          GetAttachment(GL_DEPTH_STENCIL_ATTACHMENT);
+      break;
+   default:
+      break;
   }
-  return false;
+  return attachment && !attachment->cleared();
 }
 
-bool Framebuffer::HasDepthStencilFormatAttachment(
-    GLenum attachment) const {
-  AttachmentMap::const_iterator it = attachments_.find(attachment);
-  if (it != attachments_.end()) {
-    const Attachment* attachment = it->second.get();
-    GLenum internal_format = attachment->internal_format();
-    return TextureManager::ExtractFormatFromStorageFormat(internal_format) ==
-        GL_DEPTH_STENCIL;
+bool Framebuffer::HasDepthStencilFormatAttachment() const {
+  const Attachment* depth_attachment = GetAttachment(GL_DEPTH_ATTACHMENT);
+  const Attachment* stencil_attachment = GetAttachment(GL_STENCIL_ATTACHMENT);
+  const Attachment* depth_stencil_attachment = GetAttachment(
+      GL_DEPTH_STENCIL_ATTACHMENT);
+  if (depth_attachment && stencil_attachment) {
+    GLenum depth_format = depth_attachment->internal_format();
+    depth_format = TextureManager::ExtractFormatFromStorageFormat(depth_format);
+    GLenum stencil_format = stencil_attachment->internal_format();
+    stencil_format = TextureManager::ExtractFormatFromStorageFormat(
+        stencil_format);
+    return depth_format == GL_DEPTH_STENCIL &&
+        stencil_format == GL_DEPTH_STENCIL;
+  }
+  if (depth_stencil_attachment) {
+    GLenum depth_stencil_format = depth_stencil_attachment->internal_format();
+    depth_stencil_format = TextureManager::ExtractFormatFromStorageFormat(
+        depth_stencil_format);
+    return depth_stencil_format == GL_DEPTH_STENCIL;
   }
   return false;
 }
@@ -762,6 +777,16 @@
     }
   }
 
+  // Binding different images to depth and stencil attachment points should
+  // return FRAMEBUFFER_UNSUPPORTED.
+  const Attachment* depth_attachment = GetAttachment(GL_DEPTH_ATTACHMENT);
+  const Attachment* stencil_attachment = GetAttachment(GL_STENCIL_ATTACHMENT);
+  if (depth_attachment && stencil_attachment) {
+    if (!depth_attachment->IsSameAttachment(stencil_attachment)) {
+      return GL_FRAMEBUFFER_UNSUPPORTED;
+    }
+  }
+
   // This does not mean the framebuffer is actually complete. It just means our
   // checks passed.
   return GL_FRAMEBUFFER_COMPLETE;
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 778ceb4..4e96410 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -86,7 +86,7 @@
   bool HasUnclearedColorAttachments() const;
 
   bool HasSRGBAttachments() const;
-  bool HasDepthStencilFormatAttachment(GLenum attachment) const;
+  bool HasDepthStencilFormatAttachment() const;
 
   void ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures(
       GLES2Decoder* decoder,
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index cffebd8..f1602f9 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -39,9 +39,9 @@
 class FramebufferManagerTest : public GpuServiceTest {
  public:
   FramebufferManagerTest()
-      : manager_(1, 1, CONTEXT_TYPE_OPENGLES2, NULL),
+      : manager_(1, 1, CONTEXT_TYPE_OPENGLES2, nullptr),
         feature_info_(new FeatureInfo()) {
-    texture_manager_.reset(new TextureManager(NULL,
+    texture_manager_.reset(new TextureManager(nullptr,
                                               feature_info_.get(),
                                               kMaxTextureSize,
                                               kMaxCubemapSize,
@@ -49,7 +49,7 @@
                                               kMax3DTextureSize,
                                               kMaxArrayTextureLayers,
                                               kUseDefaultTextures));
-    renderbuffer_manager_.reset(new RenderbufferManager(NULL,
+    renderbuffer_manager_.reset(new RenderbufferManager(nullptr,
                                                         kMaxRenderbufferSize,
                                                         kMaxSamples,
                                                         feature_info_.get()));
@@ -75,14 +75,14 @@
   manager_.CreateFramebuffer(kClient1Id, kService1Id);
   // Check framebuffer got created.
   Framebuffer* framebuffer1 = manager_.GetFramebuffer(kClient1Id);
-  ASSERT_TRUE(framebuffer1 != NULL);
+  ASSERT_TRUE(framebuffer1 != nullptr);
   EXPECT_FALSE(framebuffer1->IsDeleted());
   EXPECT_EQ(kService1Id, framebuffer1->service_id());
   GLuint client_id = 0;
   EXPECT_TRUE(manager_.GetClientId(framebuffer1->service_id(), &client_id));
   EXPECT_EQ(kClient1Id, client_id);
   // Check we get nothing for a non-existent framebuffer.
-  EXPECT_TRUE(manager_.GetFramebuffer(kClient2Id) == NULL);
+  EXPECT_TRUE(manager_.GetFramebuffer(kClient2Id) == nullptr);
   // Check trying to a remove non-existent framebuffers does not crash.
   manager_.RemoveFramebuffer(kClient2Id);
   // Check framebuffer gets deleted when last reference is released.
@@ -91,7 +91,7 @@
       .RetiresOnSaturation();
   // Check we can't get the framebuffer after we remove it.
   manager_.RemoveFramebuffer(kClient1Id);
-  EXPECT_TRUE(manager_.GetFramebuffer(kClient1Id) == NULL);
+  EXPECT_TRUE(manager_.GetFramebuffer(kClient1Id) == nullptr);
 }
 
 TEST_F(FramebufferManagerTest, Destroy) {
@@ -101,14 +101,14 @@
   manager_.CreateFramebuffer(kClient1Id, kService1Id);
   // Check framebuffer got created.
   Framebuffer* framebuffer1 = manager_.GetFramebuffer(kClient1Id);
-  ASSERT_TRUE(framebuffer1 != NULL);
+  ASSERT_TRUE(framebuffer1 != nullptr);
   EXPECT_CALL(*gl_, DeleteFramebuffersEXT(1, ::testing::Pointee(kService1Id)))
       .Times(1)
       .RetiresOnSaturation();
   manager_.Destroy(true);
   // Check the resources were released.
   framebuffer1 = manager_.GetFramebuffer(kClient1Id);
-  ASSERT_TRUE(framebuffer1 == NULL);
+  ASSERT_TRUE(framebuffer1 == nullptr);
 }
 
 class FramebufferInfoTestBase : public GpuServiceTest {
@@ -122,7 +122,7 @@
                  context_type,
                  new FramebufferCompletenessCache),
         feature_info_(new FeatureInfo()) {
-    texture_manager_.reset(new TextureManager(NULL,
+    texture_manager_.reset(new TextureManager(nullptr,
                                               feature_info_.get(),
                                               kMaxTextureSize,
                                               kMaxCubemapSize,
@@ -130,7 +130,7 @@
                                               kMax3DTextureSize,
                                               kMaxArrayTextureLayers,
                                               kUseDefaultTextures));
-    renderbuffer_manager_.reset(new RenderbufferManager(NULL,
+    renderbuffer_manager_.reset(new RenderbufferManager(nullptr,
                                                         kMaxRenderbufferSize,
                                                         kMaxSamples,
                                                         feature_info_.get()));
@@ -155,7 +155,7 @@
     manager_.CreateFramebuffer(kClient1Id, kService1Id);
     error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
     framebuffer_ = manager_.GetFramebuffer(kClient1Id);
-    ASSERT_TRUE(framebuffer_ != NULL);
+    ASSERT_TRUE(framebuffer_ != nullptr);
   }
 
   FramebufferManager manager_;
@@ -181,11 +181,11 @@
 TEST_F(FramebufferInfoTest, Basic) {
   EXPECT_EQ(kService1Id, framebuffer_->service_id());
   EXPECT_FALSE(framebuffer_->IsDeleted());
-  EXPECT_TRUE(NULL == framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0));
-  EXPECT_TRUE(NULL == framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT));
-  EXPECT_TRUE(NULL == framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT));
+  EXPECT_TRUE(nullptr == framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0));
+  EXPECT_TRUE(nullptr == framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT));
+  EXPECT_TRUE(nullptr == framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT));
   EXPECT_TRUE(
-      NULL == framebuffer_->GetAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
+      nullptr == framebuffer_->GetAttachment(GL_DEPTH_STENCIL_ATTACHMENT));
   EXPECT_FALSE(framebuffer_->HasDepthAttachment());
   EXPECT_FALSE(framebuffer_->HasStencilAttachment());
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
@@ -205,6 +205,8 @@
   const GLuint kRenderbufferService3Id = 335;
   const GLuint kRenderbufferClient4Id = 36;
   const GLuint kRenderbufferService4Id = 336;
+  const GLuint kRenderbufferClient5Id = 37;
+  const GLuint kRenderbufferService5Id = 337;
   const GLsizei kWidth1 = 16;
   const GLsizei kHeight1 = 32;
   const GLenum kFormat1 = GL_RGBA4;
@@ -220,9 +222,13 @@
   const GLsizei kSamples3 = 0;
   const GLsizei kWidth4 = 16;
   const GLsizei kHeight4 = 32;
-  const GLenum kFormat4 = GL_STENCIL_INDEX8;
+  const GLenum kFormat4 = GL_DEPTH24_STENCIL8;
   const GLsizei kSamples4 = 0;
-  const GLsizei kDifferentSamples4 = 1;
+  const GLsizei kWidth5 = 16;
+  const GLsizei kHeight5 = 32;
+  const GLenum kFormat5 = GL_DEPTH24_STENCIL8;
+  const GLsizei kSamples5 = 0;
+  const GLsizei kDifferentSamples5 = 1;
 
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
@@ -234,9 +240,9 @@
       kRenderbufferClient1Id, kRenderbufferService1Id);
   Renderbuffer* renderbuffer1 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id);
-  ASSERT_TRUE(renderbuffer1 != NULL);
+  ASSERT_TRUE(renderbuffer1 != nullptr);
 
-  // check adding one attachment
+  // Check adding one attachment.
   framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, renderbuffer1);
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
@@ -265,12 +271,12 @@
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
   EXPECT_FALSE(framebuffer_->IsCleared());
 
-  // check adding another
+  // Check adding another.
   renderbuffer_manager_->CreateRenderbuffer(
       kRenderbufferClient2Id, kRenderbufferService2Id);
   Renderbuffer* renderbuffer2 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient2Id);
-  ASSERT_TRUE(renderbuffer2 != NULL);
+  ASSERT_TRUE(renderbuffer2 != nullptr);
   framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer2);
   EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
@@ -295,7 +301,7 @@
   EXPECT_FALSE(framebuffer_->IsCleared());
   EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
 
-  // check marking them as cleared.
+  // Check marking them as cleared.
   manager_.MarkAttachmentsAsCleared(
       framebuffer_, renderbuffer_manager_.get(), texture_manager_.get());
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
@@ -304,12 +310,12 @@
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
   EXPECT_TRUE(framebuffer_->IsCleared());
 
-  // Check adding one that is already cleared.
+  // Add another one to stencil attachment point.
   renderbuffer_manager_->CreateRenderbuffer(
       kRenderbufferClient3Id, kRenderbufferService3Id);
   Renderbuffer* renderbuffer3 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient3Id);
-  ASSERT_TRUE(renderbuffer3 != NULL);
+  ASSERT_TRUE(renderbuffer3 != nullptr);
   renderbuffer_manager_->SetInfo(
       renderbuffer3, kSamples3, kFormat3, kWidth3, kHeight3);
   renderbuffer_manager_->SetCleared(renderbuffer3, true);
@@ -320,11 +326,35 @@
             framebuffer_->GetReadBufferInternalFormat());
   EXPECT_TRUE(framebuffer_->HasDepthAttachment());
   EXPECT_TRUE(framebuffer_->HasStencilAttachment());
+  // Binding different images to depth and stencil attachment points should
+  // return FRAMEBUFFER_UNSUPPORTED.
+  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_UNSUPPORTED),
+            framebuffer_->IsPossiblyComplete(feature_info_.get()));
+
+  // Bind a renderbufer in format DEPTH_STENCIL to depth and stencil
+  // attachment points.
+  renderbuffer_manager_->CreateRenderbuffer(
+      kRenderbufferClient4Id, kRenderbufferService4Id);
+  Renderbuffer* renderbuffer4 =
+      renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient4Id);
+  ASSERT_TRUE(renderbuffer4 != nullptr);
+  renderbuffer_manager_->SetInfo(
+      renderbuffer4, kSamples4, kFormat4, kWidth4, kHeight4);
+  renderbuffer_manager_->SetCleared(renderbuffer4, true);
+
+  EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+  EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+  framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer4);
+  framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer4);
+  EXPECT_EQ(static_cast<GLenum>(kFormat1),
+            framebuffer_->GetReadBufferInternalFormat());
+  EXPECT_TRUE(framebuffer_->HasDepthAttachment());
+  EXPECT_TRUE(framebuffer_->HasStencilAttachment());
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
   EXPECT_TRUE(framebuffer_->IsCleared());
 
-  // Check marking the renderbuffer as unclared.
+  // Check marking the renderbuffer as uncleared.
   renderbuffer_manager_->SetInfo(
       renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1);
   EXPECT_EQ(static_cast<GLenum>(kFormat1),
@@ -337,7 +367,7 @@
 
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
   EXPECT_EQ(kWidth1, attachment->width());
   EXPECT_EQ(kHeight1, attachment->height());
   EXPECT_EQ(kSamples1, attachment->samples());
@@ -352,25 +382,43 @@
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0));
   EXPECT_TRUE(framebuffer_->IsCleared());
 
-  // Check replacing an attachment
+  // Check replacing one attachment when both depth and stencil attachments
+  // are present.
   renderbuffer_manager_->CreateRenderbuffer(
-      kRenderbufferClient4Id, kRenderbufferService4Id);
-  Renderbuffer* renderbuffer4 =
-      renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient4Id);
-  ASSERT_TRUE(renderbuffer4 != NULL);
+      kRenderbufferClient5Id, kRenderbufferService5Id);
+  Renderbuffer* renderbuffer5 =
+      renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient5Id);
+  ASSERT_TRUE(renderbuffer5 != nullptr);
   renderbuffer_manager_->SetInfo(
-      renderbuffer4, kSamples4, kFormat4, kWidth4, kHeight4);
+      renderbuffer5, kSamples5, kFormat5, kWidth5, kHeight5);
 
-  framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer4);
+  framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer5);
   EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
   EXPECT_FALSE(framebuffer_->IsCleared());
 
   attachment = framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT);
-  ASSERT_TRUE(attachment != NULL);
-  EXPECT_EQ(kWidth4, attachment->width());
-  EXPECT_EQ(kHeight4, attachment->height());
-  EXPECT_EQ(kSamples4, attachment->samples());
-  EXPECT_EQ(kFormat4, attachment->internal_format());
+  ASSERT_TRUE(attachment != nullptr);
+  EXPECT_EQ(kWidth5, attachment->width());
+  EXPECT_EQ(kHeight5, attachment->height());
+  EXPECT_EQ(kSamples5, attachment->samples());
+  EXPECT_EQ(kFormat5, attachment->internal_format());
+  EXPECT_FALSE(attachment->cleared());
+  // Binding different images to depth and stencil attachment points should
+  // return FRAMEBUFFER_UNSUPPORTED.
+  EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_UNSUPPORTED),
+            framebuffer_->IsPossiblyComplete(feature_info_.get()));
+
+  // Check replacing both depth and stencil attachments.
+  framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer5);
+  EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+  EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+  EXPECT_FALSE(framebuffer_->IsCleared());
+
+  attachment = framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT);
+  EXPECT_EQ(kWidth5, attachment->width());
+  EXPECT_EQ(kHeight5, attachment->height());
+  EXPECT_EQ(kSamples5, attachment->samples());
+  EXPECT_EQ(kFormat5, attachment->internal_format());
   EXPECT_FALSE(attachment->cleared());
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
@@ -379,49 +427,52 @@
   ASSERT_FALSE(
       feature_info_->feature_flags().chromium_framebuffer_mixed_samples);
   renderbuffer_manager_->SetInfo(
-      renderbuffer4, kDifferentSamples4, kFormat4, kWidth4, kHeight4);
+      renderbuffer5, kDifferentSamples5, kFormat5, kWidth5, kHeight5);
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
   renderbuffer_manager_->SetInfo(
-      renderbuffer4, kSamples4, kFormat4, kWidth4, kHeight4);
+      renderbuffer5, kSamples5, kFormat5, kWidth5, kHeight5);
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
 
   // Check changing an attachment.
   renderbuffer_manager_->SetInfo(
-      renderbuffer4, kSamples4, kFormat4, kWidth4 + 1, kHeight4);
+      renderbuffer5, kSamples5, kFormat5, kWidth5 + 1, kHeight5);
 
   attachment = framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT);
-  ASSERT_TRUE(attachment != NULL);
-  EXPECT_EQ(kWidth4 + 1, attachment->width());
-  EXPECT_EQ(kHeight4, attachment->height());
-  EXPECT_EQ(kSamples4, attachment->samples());
-  EXPECT_EQ(kFormat4, attachment->internal_format());
+  ASSERT_TRUE(attachment != nullptr);
+  EXPECT_EQ(kWidth5 + 1, attachment->width());
+  EXPECT_EQ(kHeight5, attachment->height());
+  EXPECT_EQ(kSamples5, attachment->samples());
+  EXPECT_EQ(kFormat5, attachment->internal_format());
   EXPECT_FALSE(attachment->cleared());
   EXPECT_FALSE(framebuffer_->IsCleared());
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
 
   // Check removing it.
-  framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, NULL);
+  // Restore the width of renderbuffer5 to avoid INCOMPLETE_DIMENSIONS_EXT.
+  renderbuffer_manager_->SetInfo(
+      renderbuffer5, kSamples5, kFormat5, kWidth5, kHeight5);
+
+  framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, nullptr);
   EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
   EXPECT_EQ(static_cast<GLenum>(kFormat1),
             framebuffer_->GetReadBufferInternalFormat());
   EXPECT_TRUE(framebuffer_->HasDepthAttachment());
   EXPECT_FALSE(framebuffer_->HasStencilAttachment());
-
-  EXPECT_TRUE(framebuffer_->IsCleared());
+  EXPECT_FALSE(framebuffer_->IsCleared());
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
 
   // Remove depth, Set color to 0 size.
-  framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, NULL);
+  framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, nullptr);
   renderbuffer_manager_->SetInfo(renderbuffer1, kSamples1, kFormat1, 0, 0);
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
 
   // Remove color.
-  framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, NULL);
+  framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, nullptr);
   EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
 }
@@ -463,7 +514,7 @@
   texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id);
   scoped_refptr<TextureRef> texture1(
       texture_manager_->GetTexture(kTextureClient1Id));
-  ASSERT_TRUE(texture1.get() != NULL);
+  ASSERT_TRUE(texture1.get() != nullptr);
 
   // check adding one attachment
   framebuffer_->AttachTexture(
@@ -501,7 +552,7 @@
 
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
   EXPECT_EQ(kWidth1, attachment->width());
   EXPECT_EQ(kHeight1, attachment->height());
   EXPECT_EQ(kSamples1, attachment->samples());
@@ -512,7 +563,7 @@
   texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
   scoped_refptr<TextureRef> texture2(
       texture_manager_->GetTexture(kTextureClient2Id));
-  ASSERT_TRUE(texture2.get() != NULL);
+  ASSERT_TRUE(texture2.get() != nullptr);
   texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D);
   texture_manager_->SetLevelInfo(texture2.get(), GL_TEXTURE_2D, kLevel2,
                                  kFormat2, kWidth2, kHeight2, kDepth, kBorder,
@@ -527,7 +578,7 @@
   EXPECT_TRUE(framebuffer_->IsCleared());
 
   attachment = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
   EXPECT_EQ(kWidth2, attachment->width());
   EXPECT_EQ(kHeight2, attachment->height());
   EXPECT_EQ(kSamples2, attachment->samples());
@@ -539,7 +590,7 @@
                                  kFormat3, kWidth3, kHeight3, kDepth, kBorder,
                                  kFormat3, kType, gfx::Rect());
   attachment = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
   EXPECT_EQ(kWidth3, attachment->width());
   EXPECT_EQ(kHeight3, attachment->height());
   EXPECT_EQ(kSamples3, attachment->samples());
@@ -559,8 +610,8 @@
             framebuffer_->IsPossiblyComplete(feature_info_.get()));
 
   // Check removing it.
-  framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT0, NULL, 0, 0, 0);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
+  framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT0, nullptr, 0, 0, 0);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == nullptr);
   EXPECT_EQ(static_cast<GLenum>(0),
             framebuffer_->GetReadBufferInternalFormat());
 
@@ -690,13 +741,13 @@
   texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
   scoped_refptr<TextureRef> texture(
       texture_manager_->GetTexture(kTextureClientId));
-  ASSERT_TRUE(texture.get() != NULL);
+  ASSERT_TRUE(texture.get() != nullptr);
   texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D);
   framebuffer_->AttachTexture(
       GL_COLOR_ATTACHMENT0, texture.get(), GL_TEXTURE_2D, 0, 0);
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
 
   // Not cleared at all.
   texture_manager_->SetLevelInfo(texture.get(), GL_TEXTURE_2D, 0, GL_RGBA, 4,
@@ -774,13 +825,13 @@
   texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
   scoped_refptr<TextureRef> texture(
       texture_manager_->GetTexture(kTextureClientId));
-  ASSERT_TRUE(texture.get() != NULL);
+  ASSERT_TRUE(texture.get() != nullptr);
   texture_manager_->SetTarget(texture.get(), GL_TEXTURE_3D);
   framebuffer_->AttachTexture(
       GL_COLOR_ATTACHMENT0, texture.get(), GL_TEXTURE_3D, 0, 0);
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
 
   const int kWidth = 4;
   const int kHeight = 8;
@@ -839,7 +890,7 @@
   texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
   scoped_refptr<TextureRef> texture(
       texture_manager_->GetTexture(kTextureClientId));
-  ASSERT_TRUE(texture.get() != NULL);
+  ASSERT_TRUE(texture.get() != nullptr);
   texture_manager_->SetTarget(texture.get(), GL_TEXTURE_3D);
   // Set base level to 1 but attach level 0.
   TestHelper::SetTexParameteriWithExpectations(gl_.get(),
@@ -853,7 +904,7 @@
       GL_COLOR_ATTACHMENT0, texture.get(), GL_TEXTURE_3D, 0, 0);
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
 
   // Level 0 is not cleared at all.
   texture_manager_->SetLevelInfo(texture.get(), GL_TEXTURE_3D, 0, GL_RGBA, 4,
@@ -888,13 +939,13 @@
   texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
   scoped_refptr<TextureRef> texture(
       texture_manager_->GetTexture(kTextureClientId));
-  ASSERT_TRUE(texture.get() != NULL);
+  ASSERT_TRUE(texture.get() != nullptr);
   texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D);
   framebuffer_->AttachTexture(
       GL_COLOR_ATTACHMENT0, texture.get(), GL_TEXTURE_2D, 0, 0);
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
 
   const int kWidth = 4;
   const int kHeight = 8;
@@ -955,7 +1006,7 @@
   texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
   scoped_refptr<TextureRef> texture(
       texture_manager_->GetTexture(kTextureClientId));
-  ASSERT_TRUE(texture.get() != NULL);
+  ASSERT_TRUE(texture.get() != nullptr);
   texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D);
   // Set base level to 1 but attach level 0.
   TestHelper::SetTexParameteriWithExpectations(gl_.get(),
@@ -969,7 +1020,7 @@
       GL_COLOR_ATTACHMENT0, texture.get(), GL_TEXTURE_2D, 0, 0);
   const Framebuffer::Attachment* attachment =
       framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
-  ASSERT_TRUE(attachment != NULL);
+  ASSERT_TRUE(attachment != nullptr);
 
   // Level 0 is not cleared at all.
   texture_manager_->SetLevelInfo(texture.get(), GL_TEXTURE_2D, 0, GL_RGBA8UI, 4,
@@ -1264,7 +1315,7 @@
   texture_manager_->CreateTexture(kTextureClientId, kTextureServiceId);
   scoped_refptr<TextureRef> texture(
       texture_manager_->GetTexture(kTextureClientId));
-  ASSERT_TRUE(texture.get() != NULL);
+  ASSERT_TRUE(texture.get() != nullptr);
 
   framebuffer_->AttachTexture(
       GL_COLOR_ATTACHMENT0, texture.get(), kTarget, kLevel, kSamples);
@@ -1291,29 +1342,29 @@
       kRenderbufferClient1Id, kRenderbufferService1Id);
   Renderbuffer* renderbuffer1 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id);
-  ASSERT_TRUE(renderbuffer1 != NULL);
+  ASSERT_TRUE(renderbuffer1 != nullptr);
   renderbuffer_manager_->CreateRenderbuffer(
       kRenderbufferClient2Id, kRenderbufferService2Id);
   Renderbuffer* renderbuffer2 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient2Id);
-  ASSERT_TRUE(renderbuffer2 != NULL);
+  ASSERT_TRUE(renderbuffer2 != nullptr);
 
   // Attach to 2 attachment points.
   framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, renderbuffer1);
   framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer1);
   // Check they were attached.
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != nullptr);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != nullptr);
   // Unbind unattached renderbuffer.
   framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer2);
   // Should be no-op.
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != nullptr);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != nullptr);
   // Unbind renderbuffer.
   framebuffer_->UnbindRenderbuffer(GL_RENDERBUFFER, renderbuffer1);
   // Check they were detached
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == NULL);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == nullptr);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == nullptr);
 }
 
 TEST_F(FramebufferInfoTest, UnbindTexture) {
@@ -1328,11 +1379,11 @@
   texture_manager_->CreateTexture(kTextureClient1Id, kTextureService1Id);
   scoped_refptr<TextureRef> texture1(
       texture_manager_->GetTexture(kTextureClient1Id));
-  ASSERT_TRUE(texture1.get() != NULL);
+  ASSERT_TRUE(texture1.get() != nullptr);
   texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
   scoped_refptr<TextureRef> texture2(
       texture_manager_->GetTexture(kTextureClient2Id));
-  ASSERT_TRUE(texture2.get() != NULL);
+  ASSERT_TRUE(texture2.get() != nullptr);
 
   // Attach to 2 attachment points.
   framebuffer_->AttachTexture(
@@ -1340,18 +1391,18 @@
   framebuffer_->AttachTexture(
       GL_DEPTH_ATTACHMENT, texture1.get(), kTarget1, kLevel1, kSamples1);
   // Check they were attached.
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != nullptr);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != nullptr);
   // Unbind unattached texture.
   framebuffer_->UnbindTexture(kTarget1, texture2.get());
   // Should be no-op.
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != NULL);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != NULL);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) != nullptr);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) != nullptr);
   // Unbind texture.
   framebuffer_->UnbindTexture(kTarget1, texture1.get());
   // Check they were detached
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL);
-  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == NULL);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == nullptr);
+  EXPECT_TRUE(framebuffer_->GetAttachment(GL_DEPTH_ATTACHMENT) == nullptr);
 }
 
 TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) {
@@ -1367,11 +1418,11 @@
       kRenderbufferClient1Id, kRenderbufferService1Id);
   Renderbuffer* renderbuffer1 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id);
-  ASSERT_TRUE(renderbuffer1 != NULL);
+  ASSERT_TRUE(renderbuffer1 != nullptr);
   texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
   scoped_refptr<TextureRef> texture2(
       texture_manager_->GetTexture(kTextureClient2Id));
-  ASSERT_TRUE(texture2.get() != NULL);
+  ASSERT_TRUE(texture2.get() != nullptr);
 
   // Check MarkAsComlete marks as complete.
   manager_.MarkAsComplete(framebuffer_);
@@ -1413,11 +1464,11 @@
       kRenderbufferClient1Id, kRenderbufferService1Id);
   Renderbuffer* renderbuffer1 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id);
-  ASSERT_TRUE(renderbuffer1 != NULL);
+  ASSERT_TRUE(renderbuffer1 != nullptr);
   texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id);
   scoped_refptr<TextureRef> texture2(
       texture_manager_->GetTexture(kTextureClient2Id));
-  ASSERT_TRUE(texture2.get() != NULL);
+  ASSERT_TRUE(texture2.get() != nullptr);
   texture_manager_->SetTarget(texture2.get(), GL_TEXTURE_2D);
 
   EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
@@ -1509,7 +1560,7 @@
     manager_.CreateFramebuffer(kClient1Id, kService1Id);
     error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
     framebuffer_ = manager_.GetFramebuffer(kClient1Id);
-    ASSERT_TRUE(framebuffer_ != NULL);
+    ASSERT_TRUE(framebuffer_ != nullptr);
   }
 };
 
@@ -1537,7 +1588,7 @@
       kRenderbufferClient1Id, kRenderbufferService1Id);
   Renderbuffer* renderbuffer1 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id);
-  ASSERT_TRUE(renderbuffer1 != NULL);
+  ASSERT_TRUE(renderbuffer1 != nullptr);
   renderbuffer_manager_->SetInfo(
       renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1);
   framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT0, renderbuffer1);
@@ -1546,7 +1597,7 @@
       kRenderbufferClient2Id, kRenderbufferService2Id);
   Renderbuffer* renderbuffer2 =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient2Id);
-  ASSERT_TRUE(renderbuffer2 != NULL);
+  ASSERT_TRUE(renderbuffer2 != nullptr);
   renderbuffer_manager_->SetInfo(
       renderbuffer2, kSamples2, kFormat2, kWidth2, kHeight2);
   framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer2);
@@ -1604,7 +1655,7 @@
       kRenderbufferClientId, kRenderbufferServiceId);
   Renderbuffer* renderbuffer =
       renderbuffer_manager_->GetRenderbuffer(kRenderbufferClientId);
-  ASSERT_TRUE(renderbuffer != NULL);
+  ASSERT_TRUE(renderbuffer != nullptr);
   framebuffer_->AttachRenderbuffer(GL_COLOR_ATTACHMENT1, renderbuffer);
   EXPECT_TRUE(framebuffer_->GetReadBufferAttachment());
 }
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
index f495923..91ce24e 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -10,7 +10,7 @@
 
 #include "gpu/command_buffer/service/gl_utils.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_version_info.h"
 
 namespace {
 
@@ -94,11 +94,11 @@
     #define TexCoordPrecision\n\
     #endif\n";
 
-std::string GetVertexShaderSource() {
+std::string GetVertexShaderSource(const gl::GLVersionInfo& gl_version_info) {
   std::string source;
 
   // Preamble for core and compatibility mode.
-  if (gl::GetGLImplementation() == gl::kGLImplementationDesktopGLCoreProfile) {
+  if (gl_version_info.is_desktop_core_profile) {
     source += std::string("\
         #version 150\n\
         #define ATTRIBUTE in\n\
@@ -130,13 +130,14 @@
   return source;
 }
 
-std::string GetFragmentShaderSource(bool premultiply_alpha,
+std::string GetFragmentShaderSource(const gl::GLVersionInfo& gl_version_info,
+                                    bool premultiply_alpha,
                                     bool unpremultiply_alpha,
                                     GLenum target) {
   std::string source;
 
   // Preamble for core and compatibility mode.
-  if (gl::GetGLImplementation() == gl::kGLImplementationDesktopGLCoreProfile) {
+  if (gl_version_info.is_desktop_core_profile) {
     source += std::string("\
         #version 150\n\
         out vec4 frag_color;\n\
@@ -574,12 +575,13 @@
     DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
     return;
   }
+  const gl::GLVersionInfo& gl_version_info =
+      decoder->GetFeatureInfo()->gl_version_info();
 
   if (vertex_array_object_id_) {
     glBindVertexArrayOES(vertex_array_object_id_);
   } else {
-    if (gl::GetGLImplementation() !=
-        gl::kGLImplementationDesktopGLCoreProfile) {
+    if (!gl_version_info.is_desktop_core_profile) {
       decoder->ClearAllAttributes();
     }
     glEnableVertexAttribArray(kVertexPositionAttrib);
@@ -598,15 +600,16 @@
     info->program = glCreateProgram();
     if (!vertex_shader_) {
       vertex_shader_ = glCreateShader(GL_VERTEX_SHADER);
-      std::string source = GetVertexShaderSource();
+      std::string source = GetVertexShaderSource(gl_version_info);
       CompileShader(vertex_shader_, source.c_str());
     }
     glAttachShader(info->program, vertex_shader_);
     GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
     if (!*fragment_shader) {
       *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
-      std::string source = GetFragmentShaderSource(
-          premultiply_alpha, unpremultiply_alpha, source_target);
+      std::string source =
+          GetFragmentShaderSource(gl_version_info, premultiply_alpha,
+                                  unpremultiply_alpha, source_target);
       CompileShader(*fragment_shader, source.c_str());
     }
     glAttachShader(info->program, *fragment_shader);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0bcdbd4..542d377 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -110,9 +110,11 @@
   return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
 }
 
-void GetShaderPrecisionFormatImpl(GLenum shader_type,
-                                         GLenum precision_type,
-                                         GLint* range, GLint* precision) {
+void GetShaderPrecisionFormatImpl(const gl::GLVersionInfo& gl_version_info,
+                                  GLenum shader_type,
+                                  GLenum precision_type,
+                                  GLint* range,
+                                  GLint* precision) {
   switch (precision_type) {
     case GL_LOW_INT:
     case GL_MEDIUM_INT:
@@ -135,8 +137,7 @@
       break;
   }
 
-  if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2 &&
-      gl::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
+  if (gl_version_info.is_es) {
     // This function is sometimes defined even though it's really just
     // a stub, so we need to set range and precision as if it weren't
     // defined before calling it.
@@ -598,6 +599,9 @@
   GLES2Util* GetGLES2Util() override { return &util_; }
   gl::GLContext* GetGLContext() override { return context_.get(); }
   ContextGroup* GetContextGroup() override { return group_.get(); }
+  const FeatureInfo* GetFeatureInfo() const override {
+    return feature_info_.get();
+  }
   Capabilities GetCapabilities() override;
   void RestoreState(const ContextState* prev_state) override;
 
@@ -825,6 +829,10 @@
     return group_->memory_tracker();
   }
 
+  const gl::GLVersionInfo& gl_version_info() {
+    return feature_info_->gl_version_info();
+  }
+
   bool EnsureGPUMemoryAvailable(size_t estimated_size) {
     MemoryTracker* tracker = memory_tracker();
     if (tracker) {
@@ -1795,6 +1803,10 @@
   // false if pname is unknown.
   bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
 
+  // Checks if every attribute's type set by vertexAttrib API match
+  // the type of corresponding attribute in vertex shader.
+  bool AttribsTypeMatch();
+
   // Checks if the current program and vertex attributes are valid for drawing.
   bool IsDrawValid(
       const char* function_name, GLuint max_vertex_accessed, bool instanced,
@@ -3036,7 +3048,7 @@
     }
   }
 
-  bool needs_emulation = feature_info_->gl_version_info().IsLowerThanGL(4, 2);
+  bool needs_emulation = gl_version_info().IsLowerThanGL(4, 2);
   transform_feedback_manager_.reset(new TransformFeedbackManager(
       group_->max_transform_feedback_separate_attribs(), needs_emulation));
 
@@ -3066,6 +3078,7 @@
   state_.indexed_uniform_buffer_bindings = new IndexedBufferBindingHost(
       group_->max_uniform_buffer_bindings(), needs_emulation);
 
+  state_.InitGenericAttribBaseType(group_->max_vertex_attribs());
   state_.attrib_values.resize(group_->max_vertex_attribs());
   vertex_array_manager_.reset(new VertexArrayManager());
 
@@ -3092,7 +3105,7 @@
   util_.set_num_compressed_texture_formats(
       validators_->compressed_texture_format.GetValues().size());
 
-  if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
+  if (!gl_version_info().BehavesLikeGLES()) {
     // We have to enable vertex array 0 on GL with compatibility profile or it
     // won't render. Note that ES or GL with core profile does not have this
     // issue.
@@ -3160,9 +3173,8 @@
     }
     offscreen_target_buffer_preserved_ = attrib_helper.buffer_preserved;
 
-    if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) {
-      const bool rgb8_supported =
-          context_->HasExtension("GL_OES_rgb8_rgba8");
+    if (gl_version_info().is_es) {
+      const bool rgb8_supported = context_->HasExtension("GL_OES_rgb8_rgba8");
       // The only available default render buffer formats in GLES2 have very
       // little precision.  Don't enable multisampling unless 8-bit render
       // buffer formats are available--instead fall back to 8-bit textures.
@@ -3309,7 +3321,7 @@
 
       bool default_fb = (GetBackbufferServiceId() == 0);
 
-      if (feature_info_->gl_version_info().is_desktop_core_profile) {
+      if (gl_version_info().is_desktop_core_profile) {
         glGetFramebufferAttachmentParameterivEXT(
             GL_FRAMEBUFFER,
             default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
@@ -3348,10 +3360,10 @@
   // mailing list archives. It also implicitly enables the desktop GL
   // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
   // variable in fragment shaders.
-  if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
+  if (!gl_version_info().BehavesLikeGLES()) {
     glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
     glEnable(GL_POINT_SPRITE);
-  } else if (feature_info_->gl_version_info().is_desktop_core_profile) {
+  } else if (gl_version_info().is_desktop_core_profile) {
     // The desktop core profile changed how program point size mode is
     // enabled.
     glEnable(GL_PROGRAM_POINT_SIZE);
@@ -3363,7 +3375,7 @@
   // Therefore, it seems OK to also always enable it on top of Desktop GL for
   // both ES2 and ES3 contexts.
   if (!feature_info_->workarounds().disable_texture_cube_map_seamless &&
-      feature_info_->gl_version_info().IsAtLeastGL(3, 2)) {
+      gl_version_info().IsAtLeastGL(3, 2)) {
     glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
   }
 
@@ -3454,11 +3466,14 @@
 Capabilities GLES2DecoderImpl::GetCapabilities() {
   DCHECK(initialized());
   Capabilities caps;
-  caps.VisitPrecisions([](GLenum shader, GLenum type,
-                          Capabilities::ShaderPrecision* shader_precision) {
+  const gl::GLVersionInfo& version_info = gl_version_info();
+  caps.VisitPrecisions([&version_info](
+      GLenum shader, GLenum type,
+      Capabilities::ShaderPrecision* shader_precision) {
     GLint range[2] = {0, 0};
     GLint precision = 0;
-    GetShaderPrecisionFormatImpl(shader, type, range, &precision);
+    GetShaderPrecisionFormatImpl(version_info, shader, type, range,
+                                 &precision);
     shader_precision->min_range = range[0];
     shader_precision->max_range = range[1];
     shader_precision->precision = precision;
@@ -3652,8 +3667,8 @@
 
   GLint range[2] = { 0, 0 };
   GLint precision = 0;
-  GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
-                               range, &precision);
+  GetShaderPrecisionFormatImpl(gl_version_info(), GL_FRAGMENT_SHADER,
+                               GL_HIGH_FLOAT, range, &precision);
   resources.FragmentPrecisionHigh =
       PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
 
@@ -3725,8 +3740,6 @@
     driver_bug_workarounds |= SH_INIT_GL_POSITION;
   if (workarounds().unfold_short_circuit_as_ternary_operation)
     driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
-  if (workarounds().init_varyings_without_static_use)
-    driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
   if (workarounds().scalarize_vec_and_mat_constructor_args)
     driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
   if (workarounds().regenerate_struct_names)
@@ -3738,8 +3751,7 @@
       group_->gpu_preferences().emulate_shader_precision;
 
   ShShaderOutput shader_output_language =
-      ShaderTranslator::GetShaderOutputLanguageForContext(
-          feature_info_->gl_version_info());
+      ShaderTranslator::GetShaderOutputLanguageForContext(gl_version_info());
 
   vertex_translator_ = shader_translator_cache()->GetTranslator(
       GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
@@ -5545,8 +5557,8 @@
     glBindTexture(target, texture->service_id());
     if (texture->target() == 0) {
       texture_manager()->SetTarget(texture_ref, target);
-      if (!feature_info_->gl_version_info().BehavesLikeGLES() &&
-          feature_info_->gl_version_info().IsAtLeastGL(3, 2)) {
+      if (!gl_version_info().BehavesLikeGLES() &&
+          gl_version_info().IsAtLeastGL(3, 2)) {
         // In Desktop GL core profile and GL ES, depth textures are always
         // sampled to the RED channel, whereas on Desktop GL compatibility
         // proifle, they are sampled to RED, LUMINANCE, INTENSITY, or ALPHA
@@ -5668,7 +5680,7 @@
 
 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
   if (state_.vertex_attrib_manager->Enable(index, false)) {
-    if (index != 0 || feature_info_->gl_version_info().BehavesLikeGLES()) {
+    if (index != 0 || gl_version_info().BehavesLikeGLES()) {
       glDisableVertexAttribArray(index);
     }
   } else {
@@ -5687,8 +5699,7 @@
   // Because of performance issues, no-op if the format of the attachment is
   // DEPTH_STENCIL and only one part is intended to be invalidated.
   bool has_depth_stencil_format = framebuffer &&
-      framebuffer->HasDepthStencilFormatAttachment(GL_DEPTH_ATTACHMENT) &&
-      framebuffer->HasDepthStencilFormatAttachment(GL_STENCIL_ATTACHMENT);
+      framebuffer->HasDepthStencilFormatAttachment();
   bool invalidate_depth = false;
   bool invalidate_stencil = false;
   std::unique_ptr<GLenum[]> validated_attachments(new GLenum[count]);
@@ -5717,6 +5728,10 @@
           case GL_STENCIL_ATTACHMENT:
             invalidate_stencil = true;
             continue;
+          case GL_DEPTH_STENCIL_ATTACHMENT:
+            invalidate_depth = true;
+            invalidate_stencil = true;
+            continue;
         }
       }
     } else {
@@ -5760,7 +5775,7 @@
   bool dirty = false;
   switch (op) {
     case kFramebufferDiscard:
-      if (feature_info_->gl_version_info().is_es3) {
+      if (gl_version_info().is_es3) {
         glInvalidateFramebuffer(
             target, validated_count, translated_attachments.get());
       } else {
@@ -5770,7 +5785,7 @@
       dirty = true;
       break;
     case kFramebufferInvalidate:
-      if (feature_info_->gl_version_info().IsLowerThanGL(4, 3)) {
+      if (gl_version_info().IsLowerThanGL(4, 3)) {
         // no-op since the function isn't supported.
       } else {
         glInvalidateFramebuffer(
@@ -5792,6 +5807,9 @@
   for (GLsizei i = 0; i < validated_count; ++i) {
     if (framebuffer) {
       if (validated_attachments[i] == GL_DEPTH_STENCIL_ATTACHMENT) {
+        // TODO(qiankun.miao@intel.com): We should only mark DEPTH and STENCIL
+        // attachments as cleared when command buffer handles DEPTH_STENCIL
+        // well. http://crbug.com/630568
         framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
                                              texture_manager(),
                                              GL_DEPTH_ATTACHMENT,
@@ -5800,6 +5818,10 @@
                                              texture_manager(),
                                              GL_STENCIL_ATTACHMENT,
                                              false);
+        framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
+                                             texture_manager(),
+                                             GL_DEPTH_STENCIL_ATTACHMENT,
+                                             false);
       } else {
         framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
                                              texture_manager(),
@@ -6003,7 +6025,7 @@
       break;
   }
 
-  if (gl::GetGLImplementation() != gl::kGLImplementationEGLGLES2) {
+  if (!gl_version_info().is_es) {
     switch (pname) {
       case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
         *num_written = 1;
@@ -6028,7 +6050,7 @@
   if (unsafe_es3_apis_enabled()) {
     switch (pname) {
       case GL_MAX_VARYING_COMPONENTS: {
-        if (feature_info_->gl_version_info().is_es) {
+        if (gl_version_info().is_es) {
           // We can just delegate this query to the driver.
           return false;
         }
@@ -6131,7 +6153,7 @@
         if (framebuffer) {
           if (framebuffer->HasAlphaMRT() &&
               framebuffer->HasSameInternalFormatsMRT()) {
-            if (feature_info_->gl_version_info().is_desktop_core_profile) {
+            if (gl_version_info().is_desktop_core_profile) {
               for (uint32_t i = 0; i < group_->max_draw_buffers(); i++) {
                 if (framebuffer->HasColorAttachment(i)) {
                   glGetFramebufferAttachmentParameterivEXT(
@@ -6154,7 +6176,7 @@
       *num_written = 1;
       if (params) {
         GLint v = 0;
-        if (feature_info_->gl_version_info().is_desktop_core_profile) {
+        if (gl_version_info().is_desktop_core_profile) {
           Framebuffer* framebuffer =
               GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
           if (framebuffer) {
@@ -6178,7 +6200,7 @@
       *num_written = 1;
       if (params) {
         GLint v = 0;
-        if (feature_info_->gl_version_info().is_desktop_core_profile) {
+        if (gl_version_info().is_desktop_core_profile) {
           Framebuffer* framebuffer =
               GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
           if (framebuffer) {
@@ -6217,7 +6239,7 @@
       *num_written = 1;
       if (params) {
         GLint v = 0;
-        if (feature_info_->gl_version_info().is_desktop_core_profile) {
+        if (gl_version_info().is_desktop_core_profile) {
           Framebuffer* framebuffer =
               GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
           if (framebuffer) {
@@ -6468,7 +6490,7 @@
     return GL_MAX_SAMPLES_IMG;
   }
   if (GL_ALIASED_POINT_SIZE_RANGE == pname &&
-      feature_info_->gl_version_info().is_desktop_core_profile) {
+      gl_version_info().is_desktop_core_profile) {
     return GL_POINT_SIZE_RANGE;
   }
   return pname;
@@ -6513,8 +6535,8 @@
   if (unsafe_es3_apis_enabled()) {
     switch (pname) {
       case GL_MAX_ELEMENT_INDEX: {
-        if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
-            feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
+        if (gl_version_info().IsAtLeastGLES(3, 0) ||
+            gl_version_info().IsAtLeastGL(4, 3)) {
           glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
         } else {
           // Assume that desktop GL implementations can generally support
@@ -7594,7 +7616,7 @@
   if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
     glBlitFramebuffer(
         srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-  } else if (feature_info_->gl_version_info().is_angle) {
+  } else if (gl_version_info().is_angle) {
     // This is ES2 only.
     glBlitFramebufferANGLE(
         srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
@@ -8891,7 +8913,7 @@
   DCHECK(simulated);
   *simulated = false;
 
-  if (feature_info_->gl_version_info().BehavesLikeGLES())
+  if (gl_version_info().BehavesLikeGLES())
     return true;
 
   const VertexAttrib* attrib =
@@ -8984,7 +9006,7 @@
   // Never touch vertex attribute 0's state (in particular, never disable it)
   // when running on desktop GL with compatibility profile because it will
   // never be re-enabled.
-  if (attrib_index != 0 || feature_info_->gl_version_info().BehavesLikeGLES()) {
+  if (attrib_index != 0 || gl_version_info().BehavesLikeGLES()) {
     if (attrib->enabled()) {
       glEnableVertexAttribArray(attrib_index);
     } else {
@@ -8998,7 +9020,7 @@
     GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
   DCHECK(simulated);
   *simulated = false;
-  if (feature_info_->gl_version_info().BehavesLikeGLES())
+  if (gl_version_info().BehavesLikeGLES())
     return true;
 
   if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
@@ -9114,6 +9136,28 @@
                                       : 0);
 }
 
+bool GLES2DecoderImpl::AttribsTypeMatch() {
+  for (uint32_t index = 0; index < group_->max_vertex_attribs(); index += 16) {
+    uint32_t shader_attrib_written_mask =
+        state_.current_program->vertex_input_type_written_mask(index);
+    uint32_t vao_attrib_enabled_mask =
+        state_.vertex_attrib_manager->attrib_enabled_mask(index);
+
+    uint32_t vertex_attrib_base_type_mask =
+        (~vao_attrib_enabled_mask &
+         state_.GetGenericVertexAttribBaseTypeMask(index)) |
+        (vao_attrib_enabled_mask &
+         state_.vertex_attrib_manager->attrib_base_type_mask(index));
+
+    if ((state_.current_program->vertex_input_base_type_mask(index)
+         & shader_attrib_written_mask) !=
+         (vertex_attrib_base_type_mask & shader_attrib_written_mask)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 error::Error GLES2DecoderImpl::DoDrawArrays(
     const char* function_name,
     bool instanced,
@@ -9160,6 +9204,12 @@
     return error::kNoError;
   }
 
+  if (feature_info_->IsWebGL2OrES3Context() && !AttribsTypeMatch()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+        "vertexAttrib function must match shader attrib type");
+    return error::kNoError;
+  }
+
   GLuint max_vertex_accessed = first + count - 1;
   if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
     if (!ClearUnclearedTextures()) {
@@ -9286,6 +9336,12 @@
     return error::kNoError;
   }
 
+  if (feature_info_->IsWebGL2OrES3Context() && !AttribsTypeMatch()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+        "vertexAttrib function must match shader attrib type");
+    return error::kNoError;
+  }
+
   GLuint max_vertex_accessed;
   Buffer* element_array_buffer =
       state_.vertex_attrib_manager->element_array_buffer();
@@ -9778,7 +9834,7 @@
       }
       break;
     case GL_TEXTURE_IMMUTABLE_LEVELS:
-      if (feature_info_->gl_version_info().IsLowerThanGL(4, 2)) {
+      if (gl_version_info().IsLowerThanGL(4, 2)) {
         GLint levels = texture->GetImmutableLevels();
         if (fparams) {
           fparams[0] = static_cast<GLfloat>(levels);
@@ -9885,6 +9941,8 @@
 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
   GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
   if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib1f(index, v0);
   }
 }
@@ -9892,6 +9950,8 @@
 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
   GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
   if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib2f(index, v0, v1);
   }
 }
@@ -9900,6 +9960,8 @@
     GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
   GLfloat v[4] = { v0, v1, v2, 1.0f, };
   if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib3f(index, v0, v1, v2);
   }
 }
@@ -9908,6 +9970,8 @@
     GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
   GLfloat v[4] = { v0, v1, v2, v3, };
   if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib4f(index, v0, v1, v2, v3);
   }
 }
@@ -9915,6 +9979,8 @@
 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
   GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
   if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib1fv(index, v);
   }
 }
@@ -9922,6 +9988,8 @@
 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
   GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
   if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib2fv(index, v);
   }
 }
@@ -9929,12 +9997,16 @@
 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
   GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
   if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib3fv(index, v);
   }
 }
 
 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
   if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_FLOAT);
     glVertexAttrib4fv(index, v);
   }
 }
@@ -9943,12 +10015,16 @@
     GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
   GLint v[4] = { v0, v1, v2, v3 };
   if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_INT);
     glVertexAttribI4i(index, v0, v1, v2, v3);
   }
 }
 
 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
   if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_INT);
     glVertexAttribI4iv(index, v);
   }
 }
@@ -9957,12 +10033,16 @@
     GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
   GLuint v[4] = { v0, v1, v2, v3 };
   if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_UINT);
     glVertexAttribI4ui(index, v0, v1, v2, v3);
   }
 }
 
 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
   if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
+    state_.SetGenericVertexAttribBaseType(
+        index, SHADER_VARIABLE_UINT);
     glVertexAttribI4uiv(index, v);
   }
 }
@@ -10041,6 +10121,11 @@
         "glVertexAttribIPointer", "stride not valid for type");
     return error::kNoError;
   }
+
+  GLenum base_type = (type == GL_BYTE || type == GL_SHORT || type == GL_INT) ?
+                      SHADER_VARIABLE_INT : SHADER_VARIABLE_UINT;
+  state_.vertex_attrib_manager->UpdateAttribBaseTypeAndMask(indx, base_type);
+
   GLsizei group_size = GLES2Util::GetGroupSizeForBufferType(size, type);
   state_.vertex_attrib_manager
       ->SetAttribInfo(indx,
@@ -10135,6 +10220,10 @@
         "glVertexAttribPointer", "stride not valid for type");
     return error::kNoError;
   }
+
+  state_.vertex_attrib_manager->UpdateAttribBaseTypeAndMask(
+      indx, SHADER_VARIABLE_FLOAT);
+
   GLsizei group_size = GLES2Util::GetGroupSizeForBufferType(size, type);
   state_.vertex_attrib_manager
       ->SetAttribInfo(indx,
@@ -10147,7 +10236,7 @@
                       offset,
                       GL_FALSE);
   // We support GL_FIXED natively on EGL/GLES2 implementations
-  if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
+  if (type != GL_FIXED || gl_version_info().is_es) {
     glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
   }
   return error::kNoError;
@@ -10523,8 +10612,7 @@
         "format and type incompatible with the current read framebuffer");
     return error::kNoError;
   }
-  if (type == GL_HALF_FLOAT_OES &&
-      !(feature_info_->gl_version_info().is_es2)) {
+  if (type == GL_HALF_FLOAT_OES && !gl_version_info().is_es2) {
     type = GL_HALF_FLOAT;
   }
   if (width == 0 || height == 0) {
@@ -10588,8 +10676,8 @@
       glGenBuffersARB(1, &buffer);
       glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
       // For ANGLE client version 2, GL_STREAM_READ is not available.
-      const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
-          GL_STATIC_DRAW : GL_STREAM_READ;
+      const GLenum usage_hint =
+          gl_version_info().is_angle ? GL_STATIC_DRAW : GL_STREAM_READ;
       glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
       GLenum error = glGetError();
       if (error == GL_NO_ERROR) {
@@ -11649,10 +11737,10 @@
     {12, 10},
     {12, 12}};
 
-bool CheckETCFormatSupport(const FeatureInfo& featureInfo) {
-  const gl::GLVersionInfo& versionInfo = featureInfo.gl_version_info();
-  return versionInfo.IsAtLeastGL(4, 3) || versionInfo.IsAtLeastGLES(3, 0) ||
-         featureInfo.feature_flags().arb_es3_compatibility;
+bool CheckETCFormatSupport(const FeatureInfo& feature_info) {
+  const gl::GLVersionInfo& version_info = feature_info.gl_version_info();
+  return version_info.IsAtLeastGL(4, 3) || version_info.IsAtLeastGLES(3, 0) ||
+         feature_info.feature_flags().arb_es3_compatibility;
 }
 
 using CompressedFormatSupportCheck = bool (*)(const FeatureInfo&);
@@ -13469,7 +13557,8 @@
 
   GLint range[2] = { 0, 0 };
   GLint precision = 0;
-  GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
+  GetShaderPrecisionFormatImpl(gl_version_info(), shader_type, precision_type,
+                               range, &precision);
 
   result->min_range = range[0];
   result->max_range = range[1];
@@ -13906,7 +13995,7 @@
       // Ensure the side effects of the copy are visible to the parent
       // context. There is no need to do this for ANGLE because it uses a
       // single D3D device for all contexts.
-      if (!feature_info_->gl_version_info().is_angle)
+      if (!gl_version_info().is_angle)
         glFlush();
     }
   } else if (supports_async_swap_) {
@@ -16180,7 +16269,7 @@
   typedef cmds::GetInternalformativ::Result Result;
   GLsizei num_values = 0;
   std::vector<GLint> samples;
-  if (feature_info_->gl_version_info().IsLowerThanGL(4, 2)) {
+  if (gl_version_info().IsLowerThanGL(4, 2)) {
     if (!GLES2Util::IsIntegerFormat(format) &&
         !GLES2Util::IsFloatFormat(format)) {
       // No multisampling for integer formats and float formats.
@@ -16229,7 +16318,7 @@
   if (result->size != 0) {
     return error::kInvalidArguments;
   }
-  if (feature_info_->gl_version_info().IsLowerThanGL(4, 2)) {
+  if (gl_version_info().IsLowerThanGL(4, 2)) {
     switch (pname) {
       case GL_NUM_SAMPLE_COUNTS:
         params[0] = static_cast<GLint>(samples.size());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index f4d457e..657cb9e2 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -41,6 +41,7 @@
 
 class ContextGroup;
 class ErrorState;
+class FeatureInfo;
 class GLES2Util;
 class ImageManager;
 class Logger;
@@ -184,6 +185,7 @@
 
   // Gets the associated ContextGroup
   virtual ContextGroup* GetContextGroup() = 0;
+  virtual const FeatureInfo* GetFeatureInfo() const = 0;
 
   virtual Capabilities GetCapabilities() = 0;
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 98c4715..2a04be71 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -65,6 +65,7 @@
   MOCK_METHOD0(GetGLSurface, gl::GLSurface*());
   MOCK_METHOD0(GetGLContext, gl::GLContext*());
   MOCK_METHOD0(GetContextGroup, ContextGroup*());
+  MOCK_CONST_METHOD0(GetFeatureInfo, const FeatureInfo*());
   MOCK_METHOD0(GetContextState, const ContextState*());
   MOCK_METHOD1(GetTranslator,
                scoped_refptr<ShaderTranslatorInterface>(unsigned int type));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 7855403..bfb8de7 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -174,6 +174,10 @@
   return nullptr;
 }
 
+const FeatureInfo* GLES2DecoderPassthroughImpl::GetFeatureInfo() const {
+  return nullptr;
+}
+
 gpu::Capabilities GLES2DecoderPassthroughImpl::GetCapabilities() {
   DCHECK(initialized());
   Capabilities caps;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 927efc6..590ccea 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -73,6 +73,8 @@
   // Gets the associated ContextGroup
   ContextGroup* GetContextGroup() override;
 
+  const FeatureInfo* GetFeatureInfo() const override;
+
   Capabilities GetCapabilities() override;
 
   // Restores all of the decoder GL state.
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 0122d37..2195f602 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -24,7 +24,6 @@
 #include "gpu/command_buffer/service/test_helper.h"
 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_mock.h"
 #include "ui/gl/init/gl_factory.h"
 #include "ui/gl/test/gl_surface_test_support.h"
@@ -394,6 +393,12 @@
         .RetiresOnSaturation();
   }
 
+  if (group_->feature_info()->gl_version_info().is_es) {
+    EXPECT_CALL(
+        *gl_, GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, _, _))
+        .RetiresOnSaturation();
+  }
+
   static GLint max_viewport_dims[] = {
     kMaxViewportWidth,
     kMaxViewportHeight
@@ -1486,8 +1491,7 @@
       .Times(1)
       .RetiresOnSaturation();
 
-  if (attrib != 0 ||
-      gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) {
+  if (attrib != 0 || group_->feature_info()->gl_version_info().is_es) {
     // TODO(bajones): Not sure if I can tell which of these will be called
     EXPECT_CALL(*gl_, EnableVertexAttribArray(attrib))
         .Times(testing::AtMost(1))
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
index dda301a..0040442b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc
@@ -3410,6 +3410,67 @@
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 }
 
+TEST_P(GLES3DecoderTest, InvalidateFramebufferDepthStencilAttachment) {
+  DoBindFramebuffer(
+      GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
+  DoBindRenderbuffer(
+      GL_RENDERBUFFER, client_renderbuffer_id_, kServiceRenderbufferId);
+  DoRenderbufferStorage(
+      GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8,
+      1, 1, GL_NO_ERROR);
+  DoFramebufferRenderbuffer(
+      GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+      client_renderbuffer_id_, kServiceRenderbufferId, GL_NO_ERROR);
+
+  Framebuffer* framebuffer =
+      group().framebuffer_manager()->GetFramebuffer(client_framebuffer_id_);
+  // TODO(qiankun.miao@intel.com): We should only mark DEPTH and STENCIL
+  // attachments as cleared when command buffer handles DEPTH_STENCIL well.
+  // http://crbug.com/630568
+  framebuffer->MarkAttachmentAsCleared(group().renderbuffer_manager(), nullptr,
+                                       GL_DEPTH_ATTACHMENT, true);
+  framebuffer->MarkAttachmentAsCleared(group().renderbuffer_manager(), nullptr,
+                                       GL_STENCIL_ATTACHMENT, true);
+  framebuffer->MarkAttachmentAsCleared(group().renderbuffer_manager(), nullptr,
+                                       GL_DEPTH_STENCIL_ATTACHMENT, true);
+  EXPECT_TRUE(framebuffer->IsCleared());
+
+  const GLenum target = GL_FRAMEBUFFER;
+  const GLsizei count = 1;
+  GLenum attachments[] = {GL_DEPTH_ATTACHMENT};
+  EXPECT_CALL(*gl_, InvalidateFramebuffer(target, 0, _))
+      .Times(1)
+      .RetiresOnSaturation();
+  InvalidateFramebufferImmediate& cmd =
+      *GetImmediateAs<InvalidateFramebufferImmediate>();
+  cmd.Init(target, count, attachments);
+
+  EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(attachments)));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  // Invalidating part of DEPTH_STENCIL attachment doesn't change framebuffer
+  // clearance status.
+  EXPECT_TRUE(framebuffer->IsCleared());
+  EXPECT_FALSE(framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+  EXPECT_FALSE(framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+  EXPECT_FALSE(framebuffer->HasUnclearedAttachment(
+      GL_DEPTH_STENCIL_ATTACHMENT));
+
+  attachments[0] = GL_DEPTH_STENCIL_ATTACHMENT;
+  EXPECT_CALL(*gl_, InvalidateFramebuffer(target, 1, _))
+      .Times(1)
+      .RetiresOnSaturation();
+  cmd.Init(target, count, attachments);
+
+  EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(attachments)));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  // Invalidating DEPTH_STENCIL attachment should make framebuffer uncleared.
+  EXPECT_FALSE(framebuffer->IsCleared());
+  EXPECT_TRUE(framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT));
+  EXPECT_TRUE(framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT));
+  EXPECT_TRUE(framebuffer->HasUnclearedAttachment(
+      GL_DEPTH_STENCIL_ATTACHMENT));
+}
+
 // TODO(gman): PixelStorei
 
 // TODO(gman): SwapBuffers
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
index 4686867c..4bad8496 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -607,8 +607,14 @@
   EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 }
 
-TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatSucceeds) {
-  ScopedGLImplementationSetter gl_impl(::gl::kGLImplementationEGLGLES2);
+TEST_P(GLES2DecoderManualInitTest, GetShaderPrecisionFormatSucceeds) {
+  // Force ES underlying implementation to ensure we check the shader precision
+  // format.
+  InitState init;
+  init.gl_version = "opengl es 2.0";
+  init.bind_generates_resource = true;
+  InitDecoder(init);
+
   GetShaderPrecisionFormat cmd;
   typedef GetShaderPrecisionFormat::Result Result;
   Result* result = static_cast<Result*>(shared_memory_address_);
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 8ce0c847..ca07255 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -117,7 +117,7 @@
          static_cast<const uint8_t*>(start);
 }
 
-ShaderVariableBaseType FragmentOutputTypeToBaseType(GLenum type) {
+ShaderVariableBaseType InputOutputTypeToBaseType(bool is_input, GLenum type) {
   switch (type) {
     case GL_INT:
     case GL_INT_VEC2:
@@ -134,6 +134,17 @@
     case GL_FLOAT_VEC3:
     case GL_FLOAT_VEC4:
       return SHADER_VARIABLE_FLOAT;
+    case GL_FLOAT_MAT2:
+    case GL_FLOAT_MAT3:
+    case GL_FLOAT_MAT4:
+    case GL_FLOAT_MAT2x3:
+    case GL_FLOAT_MAT3x2:
+    case GL_FLOAT_MAT2x4:
+    case GL_FLOAT_MAT4x2:
+    case GL_FLOAT_MAT3x4:
+    case GL_FLOAT_MAT4x3:
+      DCHECK(is_input);
+      return SHADER_VARIABLE_FLOAT;
     default:
       NOTREACHED();
       return SHADER_VARIABLE_UNDEFINED_TYPE;
@@ -316,6 +327,8 @@
   attrib_location_to_index_map_.clear();
   fragment_output_type_mask_ = 0u;
   fragment_output_written_mask_ = 0u;
+  vertex_input_base_type_mask_.clear();
+  vertex_input_type_written_mask_.clear();
 }
 
 void Program::UpdateFragmentOutputBaseTypes() {
@@ -351,11 +364,36 @@
       int shift_bits = ii * 2;
       fragment_output_written_mask_ |= 0x3 << shift_bits;
       fragment_output_type_mask_ |=
-          FragmentOutputTypeToBaseType(output.type) << shift_bits;
+          InputOutputTypeToBaseType(false, output.type) << shift_bits;
     }
   }
 }
 
+void Program::UpdateVertexInputBaseTypes() {
+  max_vertex_attribs_ = manager_->max_vertex_attribs();
+  uint32_t packed_size = max_vertex_attribs_ / 16;
+  packed_size += (max_vertex_attribs_ % 16 == 0) ? 0 : 1;
+  vertex_input_base_type_mask_.resize(packed_size);
+  vertex_input_type_written_mask_.resize(packed_size);
+
+  for (uint32_t ii = 0; ii < packed_size; ++ii) {
+    vertex_input_type_written_mask_[ii] = 0u;
+    vertex_input_base_type_mask_[ii] = 0u;
+  }
+
+  for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
+    DCHECK(ii < max_vertex_attribs_);
+    const VertexAttrib& input = attrib_infos_[ii];
+    if (ProgramManager::HasBuiltInPrefix(input.name)) {
+      continue;
+    }
+    int shift_bits = (input.location % 16) * 2;
+      vertex_input_type_written_mask_[ii / 16] |= 0x3 << shift_bits;
+      vertex_input_base_type_mask_[ii / 16] |=
+          InputOutputTypeToBaseType(true, input.type) << shift_bits;
+  }
+}
+
 void Program::UpdateUniformBlockSizeInfo() {
   switch (feature_info().context_type()) {
     case CONTEXT_TYPE_OPENGLES2:
@@ -623,6 +661,7 @@
   UpdateFragmentInputs();
   UpdateProgramOutputs();
   UpdateFragmentOutputBaseTypes();
+  UpdateVertexInputBaseTypes();
   UpdateUniformBlockSizeInfo();
 
   valid_ = true;
@@ -2376,6 +2415,7 @@
     uint32_t max_varying_vectors,
     uint32_t max_draw_buffers,
     uint32_t max_dual_source_draw_buffers,
+    uint32_t max_vertex_attribs,
     const GpuPreferences& gpu_preferences,
     FeatureInfo* feature_info)
     : program_count_(0),
@@ -2384,6 +2424,7 @@
       max_varying_vectors_(max_varying_vectors),
       max_draw_buffers_(max_draw_buffers),
       max_dual_source_draw_buffers_(max_dual_source_draw_buffers),
+      max_vertex_attribs_(max_vertex_attribs),
       gpu_preferences_(gpu_preferences),
       feature_info_(feature_info) {}
 
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 8b9d62f..a3fd9f2 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -403,6 +403,20 @@
       return fragment_output_written_mask_;
   }
 
+  // The data are only valid after a successful link.
+  // Return 16 attributes' base types, in which the attribute
+  // specified by argument 'loc' located.
+  uint32_t vertex_input_base_type_mask(GLuint loc) const {
+      DCHECK(loc < max_vertex_attribs_);
+      return vertex_input_base_type_mask_[loc / 16];
+  }
+  // Return 16 attributes' type written masks, in which the
+  // attribute specified by argument 'loc' located.
+  uint32_t vertex_input_type_written_mask(GLuint loc) const {
+      DCHECK(loc < max_vertex_attribs_);
+      return vertex_input_type_written_mask_[loc / 16];
+  }
+
   // Update uniform block binding after a successful glUniformBlockBinding().
   void SetUniformBlockBinding(GLuint index, GLuint binding);
 
@@ -447,6 +461,7 @@
   void UpdateFragmentInputs();
   void UpdateProgramOutputs();
   void UpdateFragmentOutputBaseTypes();
+  void UpdateVertexInputBaseTypes();
   void UpdateUniformBlockSizeInfo();
 
   // Process the program log, replacing the hashed names with original names.
@@ -565,6 +580,15 @@
   // Same layout as above, 2 bits per location, 0x03 if a location is occupied
   // by an output variable, 0x00 if not.
   uint32_t fragment_output_written_mask_;
+
+  uint32_t max_vertex_attribs_;
+  // Vertex input attrib base types: FLOAT, INT, or UINT.
+  // Each base type is encoded into 2 bits, the lowest 2 bits for location 0,
+  // the highest 2 bits for location (max_vertex_attribs_ - 1).
+  std::vector<uint32_t> vertex_input_base_type_mask_;
+  // Same layout as above, 2 bits per location, 0x03 if a location is set
+  // by vertexAttrib API, 0x00 if not.
+  std::vector<uint32_t> vertex_input_type_written_mask_;
 };
 
 // Tracks the Programs.
@@ -577,6 +601,7 @@
                  uint32_t max_varying_vectors,
                  uint32_t max_draw_buffers,
                  uint32_t max_dual_source_draw_buffers,
+                 uint32_t max_vertex_attribs,
                  const GpuPreferences& gpu_preferences,
                  FeatureInfo* feature_info);
   ~ProgramManager();
@@ -625,6 +650,8 @@
     return max_dual_source_draw_buffers_;
   }
 
+  uint32_t max_vertex_attribs() const { return max_vertex_attribs_; }
+
  private:
   friend class Program;
 
@@ -653,6 +680,7 @@
   uint32_t max_varying_vectors_;
   uint32_t max_draw_buffers_;
   uint32_t max_dual_source_draw_buffers_;
+  uint32_t max_vertex_attribs_;
 
   const GpuPreferences& gpu_preferences_;
   scoped_refptr<FeatureInfo> feature_info_;
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index 0d4c44b..e9840e97 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -45,6 +45,7 @@
 const uint32_t kMaxVaryingVectors = 8;
 const uint32_t kMaxDrawBuffers = 8;
 const uint32_t kMaxDualSourceDrawBuffers = 8;
+const uint32_t kMaxVertexAttribs = 8;
 
 void ShaderCacheCb(const std::string& key, const std::string& shader) {}
 
@@ -61,6 +62,7 @@
     manager_.reset(new ProgramManager(nullptr, kMaxVaryingVectors,
                                       kMaxDrawBuffers,
                                       kMaxDualSourceDrawBuffers,
+                                      kMaxVertexAttribs,
                                       gpu_preferences_,
                                       feature_info_.get()));
   }
@@ -2072,6 +2074,7 @@
     manager_.reset(new ProgramManager(cache_.get(), kMaxVaryingVectors,
                                       kMaxDrawBuffers,
                                       kMaxDualSourceDrawBuffers,
+                                      kMaxVertexAttribs,
                                       gpu_preferences_,
                                       feature_info_.get()));
   }
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index f148b02..a81a2d0 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -161,8 +161,7 @@
 
 ShaderTranslator::ShaderTranslator()
     : compiler_(NULL),
-      driver_bug_workarounds_(static_cast<ShCompileOptions>(0)),
-      gl_shader_interm_output_(false) {
+      compile_options_(0) {
 }
 
 bool ShaderTranslator::Init(GLenum shader_type,
@@ -186,23 +185,28 @@
     compiler_ = ShConstructCompiler(shader_type, shader_spec,
                                     shader_output_language, resources);
   }
-  driver_bug_workarounds_ = driver_bug_workarounds;
-  gl_shader_interm_output_ = gl_shader_interm_output;
+
+  compile_options_ =
+      SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS |
+      SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH |
+      SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
+  if (gl_shader_interm_output)
+    compile_options_ |= SH_INTERMEDIATE_TREE;
+  compile_options_ |= driver_bug_workarounds;
+  switch (shader_spec) {
+    case SH_WEBGL_SPEC:
+    case SH_WEBGL2_SPEC:
+      compile_options_ |= SH_INIT_OUTPUT_VARIABLES;
+      break;
+    default:
+      break;
+  }
+
   return compiler_ != NULL;
 }
 
 int ShaderTranslator::GetCompileOptions() const {
-  int compile_options =
-      SH_OBJECT_CODE | SH_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS |
-      SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH |
-      SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
-
-  if (gl_shader_interm_output_)
-    compile_options |= SH_INTERMEDIATE_TREE;
-
-  compile_options |= driver_bug_workarounds_;
-
-  return compile_options;
+  return compile_options_;
 }
 
 bool ShaderTranslator::Translate(const std::string& shader_source,
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index d4ea8f5..307a81c 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -126,8 +126,7 @@
   int GetCompileOptions() const;
 
   ShHandle compiler_;
-  ShCompileOptions driver_bug_workarounds_;
-  bool gl_shader_interm_output_;
+  int compile_options_;
   base::ObserverList<DestructionObserver> destruction_observers_;
 };
 
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index 59363f8..b0714d9 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -1184,16 +1184,6 @@
       type, array_size, precision, static_use, name);
 }
 
-ScopedGLImplementationSetter::ScopedGLImplementationSetter(
-    gl::GLImplementation implementation)
-    : old_implementation_(gl::GetGLImplementation()) {
-  gl::SetGLImplementation(implementation);
-}
-
-ScopedGLImplementationSetter::~ScopedGLImplementationSetter() {
-  gl::SetGLImplementation(old_implementation_);
-}
-
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h
index 5a59f9a..6663e92 100644
--- a/gpu/command_buffer/service/test_helper.h
+++ b/gpu/command_buffer/service/test_helper.h
@@ -227,18 +227,6 @@
   static std::vector<std::string> split_extensions_;
 };
 
-// This object temporaritly Sets what gl::GetGLImplementation returns. During
-// testing the GLImplementation is set to kGLImplemenationMockGL but lots of
-// code branches based on what gl::GetGLImplementation returns.
-class ScopedGLImplementationSetter {
- public:
-  explicit ScopedGLImplementationSetter(gl::GLImplementation implementation);
-  ~ScopedGLImplementationSetter();
-
- private:
-  gl::GLImplementation old_implementation_;
-};
-
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/vertex_attrib_manager.cc b/gpu/command_buffer/service/vertex_attrib_manager.cc
index 76883dc..2e18356 100644
--- a/gpu/command_buffer/service/vertex_attrib_manager.cc
+++ b/gpu/command_buffer/service/vertex_attrib_manager.cc
@@ -127,6 +127,16 @@
 void VertexAttribManager::Initialize(uint32_t max_vertex_attribs,
                                      bool init_attribs) {
   vertex_attribs_.resize(max_vertex_attribs);
+  max_vertex_attribs_ = max_vertex_attribs;
+  uint32_t packed_size = max_vertex_attribs_ / 16;
+  packed_size += (max_vertex_attribs_ % 16 == 0) ? 0 : 1;
+  attrib_base_type_mask_.resize(packed_size);
+  attrib_enabled_mask_.resize(packed_size);
+
+  for (uint32_t ii = 0; ii < packed_size; ++ii) {
+    attrib_enabled_mask_[ii] = 0u;
+    attrib_base_type_mask_[ii] = 0u;
+  }
 
   for (uint32_t vv = 0; vv < vertex_attribs_.size(); ++vv) {
     vertex_attribs_[vv].set_index(vv);
@@ -146,6 +156,15 @@
   if (index >= vertex_attribs_.size()) {
     return false;
   }
+
+  DCHECK(index < max_vertex_attribs_);
+  GLuint shift_bits = (index % 16) * 2;
+  if (enable) {
+    attrib_enabled_mask_[index / 16] |= (0x3 << shift_bits);
+  } else {
+    attrib_enabled_mask_[index / 16] &= ~(0x3 << shift_bits);
+  }
+
   VertexAttrib& info = vertex_attribs_[index];
   if (info.enabled() != enable) {
     info.set_enabled(enable);
diff --git a/gpu/command_buffer/service/vertex_attrib_manager.h b/gpu/command_buffer/service/vertex_attrib_manager.h
index f3fae6d..40c6794 100644
--- a/gpu/command_buffer/service/vertex_attrib_manager.h
+++ b/gpu/command_buffer/service/vertex_attrib_manager.h
@@ -200,6 +200,28 @@
     return NULL;
   }
 
+  void UpdateAttribBaseTypeAndMask(GLuint loc, GLenum base_type) {
+    DCHECK(loc < max_vertex_attribs_);
+    int shift_bits = (loc % 16) * 2;
+    attrib_enabled_mask_[loc / 16] |= (0x3 << shift_bits);
+    attrib_base_type_mask_[loc / 16] &= ~(0x3 << shift_bits);
+    attrib_base_type_mask_[loc / 16] |= base_type << shift_bits;
+  }
+
+  // Return 16 attributes' base types, in which the attribute
+  // specified by argument 'loc' located.
+  uint32_t attrib_base_type_mask(GLuint loc) const {
+    DCHECK(loc < max_vertex_attribs_);
+    return attrib_base_type_mask_[loc / 16];
+  }
+
+  // Return 16 attributes' type written masks, in which the
+  // attribute specified by argument 'loc' located.
+  uint32_t attrib_enabled_mask(GLuint loc) const {
+    DCHECK(loc < max_vertex_attribs_);
+    return attrib_enabled_mask_[loc / 16];
+  }
+
   void SetAttribInfo(
       GLuint index,
       Buffer* buffer,
@@ -284,6 +306,16 @@
   // if it is safe to draw.
   std::vector<VertexAttrib> vertex_attribs_;
 
+  uint32_t max_vertex_attribs_;
+  // Vertex attrib base types: FLOAT, INT, or UINT.
+  // Each base type is encoded into 2 bits, the lowest 2 bits for location 0,
+  // the highest 2 bits for location (max_vertex_attribs_ - 1).
+  std::vector<uint32_t> attrib_base_type_mask_;
+  // Same layout as above, 2 bits per location, 0x03 if a location for an
+  // vertex attrib is enabled by enabbleVertexAttribArray, 0x00 if it is
+  // disabled by disableVertexAttribArray. Every location is 0x00 by default.
+  std::vector<uint32_t> attrib_enabled_mask_;
+
   // The currently bound element array buffer. If this is 0 it is illegal
   // to call glDrawElements.
   scoped_refptr<Buffer> element_array_buffer_;
diff --git a/gpu/config/gpu_blacklist.cc b/gpu/config/gpu_blacklist.cc
index a359123..0422fd97 100644
--- a/gpu/config/gpu_blacklist.cc
+++ b/gpu/config/gpu_blacklist.cc
@@ -38,6 +38,8 @@
                             GPU_FEATURE_TYPE_PANEL_FITTING);
   list->AddSupportedFeature("gpu_rasterization",
                             GPU_FEATURE_TYPE_GPU_RASTERIZATION);
+  list->AddSupportedFeature("accelerated_vpx_decode",
+                            GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE);
   list->set_supports_feature_type_all(true);
   return list;
 }
diff --git a/gpu/config/gpu_blacklist_unittest.cc b/gpu/config/gpu_blacklist_unittest.cc
index b5e27e7..8144b76 100644
--- a/gpu/config/gpu_blacklist_unittest.cc
+++ b/gpu/config/gpu_blacklist_unittest.cc
@@ -126,4 +126,8 @@
                            "gpu_rasterization",
                            GPU_FEATURE_TYPE_GPU_RASTERIZATION)
 
+GPU_BLACKLIST_FEATURE_TEST(AcceleratedVpxDecode,
+                           "accelerated_vpx_decode",
+                           GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE)
+
 }  // namespace gpu
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index bfd5349..c2231886 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "8.76",
+  "version": "8.78",
   "entries": [
     {
       "id": 1,
@@ -496,17 +496,6 @@
       ]
     },
     {
-      "id": 57,
-      "cr_bugs": [322760],
-      "description": "Mac drivers handle varyings without static use incorrectly",
-      "os": {
-        "type": "macosx"
-      },
-      "features": [
-        "init_varyings_without_static_use"
-      ]
-    },
-    {
       "id": 59,
       "description": "Multisampling is buggy in Intel IvyBridge",
       "cr_bugs": [116370],
@@ -1857,6 +1846,56 @@
       "features": [
         "disable_framebuffer_cmaa"
       ]
+    },
+    {
+      "id": 173,
+      "description": "Limit transparent visuals to drivers known to work",
+      "cr_bugs": [369209],
+      "os": {
+        "type": "linux"
+      },
+      "exceptions" : [
+        {
+          "driver_vendor": "Mesa"
+        }
+      ],
+      "features": [
+        "disable_transparent_visuals"
+      ]
+    },
+    {
+      "id": 174,
+      "description": "Adreno 4xx support for EXT_multisampled_render_to_texture is buggy on Android 7.0",
+      "cr_bugs": [612474],
+      "os": {
+        "type": "android",
+        "version": {
+          "op": "between",
+          "value": "7.0.0",
+          "value2": "7.0.99"
+          // Only initial version of N.
+        }
+      },
+      "gl_renderer": "Adreno \\(TM\\) 4.*",
+      "disabled_extensions": [
+        "GL_EXT_multisampled_render_to_texture"
+      ]
+    },
+    {
+      "id": 175,
+      "description": "Adreno 5xx support for EXT_multisampled_render_to_texture is buggy on Android < 7.0",
+      "cr_bugs": [612474],
+      "os": {
+        "type": "android",
+        "version": {
+          "op": "<",
+          "value": "7.0"
+        }
+      },
+      "gl_renderer": "Adreno \\(TM\\) 5.*",
+      "disabled_extensions": [
+        "GL_EXT_multisampled_render_to_texture"
+      ]
     }
   ]
 }
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 4b59789..2c1d08d 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -67,6 +67,8 @@
          disable_timestamp_queries)                          \
   GPU_OP(DISABLE_MULTISAMPLING_COLOR_MASK_USAGE,             \
          disable_multisampling_color_mask_usage)             \
+  GPU_OP(DISABLE_TRANSPARENT_VISUALS,                        \
+         disable_transparent_visuals)                        \
   GPU_OP(DISABLE_WEBGL_RGB_MULTISAMPLING_USAGE,              \
          disable_webgl_rgb_multisampling_usage)              \
   GPU_OP(ETC1_POWER_OF_TWO_ONLY,                             \
@@ -89,8 +91,6 @@
          init_gl_position_in_vertex_shader)                  \
   GPU_OP(INIT_TEXTURE_MAX_ANISOTROPY,                        \
          init_texture_max_anisotropy)                        \
-  GPU_OP(INIT_VARYINGS_WITHOUT_STATIC_USE,                   \
-         init_varyings_without_static_use)                   \
   GPU_OP(INIT_VERTEX_ATTRIBUTES,                             \
          init_vertex_attributes)                             \
   GPU_OP(MAX_COPY_TEXTURE_CHROMIUM_SIZE_1048576,             \
diff --git a/gpu/config/gpu_feature_type.h b/gpu/config/gpu_feature_type.h
index 174b2508..f40b26a5 100644
--- a/gpu/config/gpu_feature_type.h
+++ b/gpu/config/gpu_feature_type.h
@@ -21,6 +21,7 @@
   GPU_FEATURE_TYPE_PANEL_FITTING,
   GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE,
   GPU_FEATURE_TYPE_GPU_RASTERIZATION,
+  GPU_FEATURE_TYPE_ACCELERATED_VPX_DECODE,
   NUMBER_OF_GPU_FEATURE_TYPES
 };
 
diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc
index abb2217..286bd1f8 100644
--- a/gpu/perftests/texture_upload_perftest.cc
+++ b/gpu/perftests/texture_upload_perftest.cc
@@ -222,7 +222,7 @@
     // used to draw a quad on the offscreen surface.
     vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader);
 
-    bool is_gles = gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2;
+    bool is_gles = gl_context_->GetVersionInfo()->is_es;
     fragment_shader_ = LoadShader(
         GL_FRAGMENT_SHADER,
         base::StringPrintf("%s%s", is_gles ? kShaderDefaultFloatPrecision : "",
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index e05a862..f270fdff 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -65,10 +65,7 @@
       builders { name: "ios-simulator" }
       builders { name: "ios-simulator-gn" }
       builders { name: "mac_chromium_compile_dbg_ng" }
-      builders {
-        name: "mac_chromium_gyp_rel"
-        experiment_percentage: 75
-      }
+      builders { name: "mac_chromium_gyp_rel" }
       builders { name: "mac_chromium_rel_ng" }
       builders {
         name: "mac_chromium_10.10_rel_ng"
diff --git a/ios/BUILD.gn b/ios/BUILD.gn
index e6150df..487eb91 100644
--- a/ios/BUILD.gn
+++ b/ios/BUILD.gn
@@ -24,6 +24,7 @@
     "//ios/web:ios_web_inttests",
     "//ios/web:ios_web_unittests",
     "//ios/web/shell:ios_web_shell",
+    "//ios/web/shell/test:ios_web_shell_test_host",
   ]
 
   if (!is_component_build) {
diff --git a/ios/chrome/BUILD.gn b/ios/chrome/BUILD.gn
index 26eceb3b..7d95ec4 100644
--- a/ios/chrome/BUILD.gn
+++ b/ios/chrome/BUILD.gn
@@ -77,6 +77,7 @@
     "browser/web_resource/web_resource_util_unittest.cc",
     "browser/webp_transcode/webp_decoder_unittest.mm",
     "common/string_util_unittest.mm",
+    "test/google_toolbox_unittest.mm",
   ]
 
   deps = [
@@ -116,6 +117,7 @@
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
+    "//third_party/google_toolbox_for_mac",
     "//third_party/ocmock",
     "//ui/gfx:test_support",
   ]
diff --git a/ios/chrome/browser/notification_promo.cc b/ios/chrome/browser/notification_promo.cc
index 87adf3a..e5364adad 100644
--- a/ios/chrome/browser/notification_promo.cc
+++ b/ios/chrome/browser/notification_promo.cc
@@ -232,18 +232,17 @@
 
 void NotificationPromo::HandleClosed() {
   if (!closed_) {
-    closed_ = true;
-    WritePrefs();
+    WritePrefs(promo_id_, first_view_time_, views_, true);
   }
 }
 
-bool NotificationPromo::HandleViewed() {
-  ++views_;
-  if (first_view_time_ == 0) {
-    first_view_time_ = base::Time::Now().ToDoubleT();
+void NotificationPromo::HandleViewed() {
+  int views = views_ + 1;
+  double first_view_time = first_view_time_;
+  if (first_view_time == 0) {
+    first_view_time = base::Time::Now().ToDoubleT();
   }
-  WritePrefs();
-  return ExceedsMaxViews() || ExceedsMaxSeconds();
+  WritePrefs(promo_id_, first_view_time, views, closed_);
 }
 
 bool NotificationPromo::ExceedsMaxViews() const {
diff --git a/ios/chrome/browser/notification_promo.h b/ios/chrome/browser/notification_promo.h
index 4431974e1..b790041 100644
--- a/ios/chrome/browser/notification_promo.h
+++ b/ios/chrome/browser/notification_promo.h
@@ -57,9 +57,8 @@
 
   // Mark the promo as closed when the user dismisses it.
   void HandleClosed();
-  // Mark the promo has having been viewed. This returns true if views
-  // exceeds the maximum allowed.
-  bool HandleViewed();
+  // Mark the promo has having been viewed.
+  void HandleViewed();
 
   const std::string& promo_text() const { return promo_text_; }
   PromoType promo_type() const { return promo_type_; }
diff --git a/ios/chrome/browser/notification_promo_unittest.cc b/ios/chrome/browser/notification_promo_unittest.cc
index f2697966..396b63d 100644
--- a/ios/chrome/browser/notification_promo_unittest.cc
+++ b/ios/chrome/browser/notification_promo_unittest.cc
@@ -162,9 +162,7 @@
     NotificationPromo first_promo(&local_state_);
     first_promo.InitFromVariations();
     first_promo.InitFromPrefs(promo_type_);
-
-    first_promo.HandleViewed();
-    EXPECT_EQ(first_promo.max_views_ - 1, first_promo.views_);
+    EXPECT_EQ(first_promo.max_views_ - 2, first_promo.views_);
     EXPECT_TRUE(first_promo.CanShow());
     first_promo.HandleViewed();
 
@@ -173,19 +171,26 @@
     NotificationPromo second_promo(&local_state_);
     second_promo.InitFromVariations();
     second_promo.InitFromPrefs(promo_type_);
-    EXPECT_EQ(second_promo.max_views_, second_promo.views_);
-    EXPECT_FALSE(second_promo.CanShow());
+    EXPECT_EQ(second_promo.max_views_ - 1, second_promo.views_);
+    EXPECT_TRUE(second_promo.CanShow());
+    second_promo.HandleViewed();
+
+    NotificationPromo third_promo(&local_state_);
+    third_promo.InitFromVariations();
+    third_promo.InitFromPrefs(promo_type_);
+    EXPECT_EQ(third_promo.max_views_, third_promo.views_);
+    EXPECT_FALSE(third_promo.CanShow());
 
     // Test out of range views.
     for (int i = max_views_; i < max_views_ * 2; ++i) {
-      second_promo.views_ = i;
-      EXPECT_FALSE(second_promo.CanShow());
+      third_promo.views_ = i;
+      EXPECT_FALSE(third_promo.CanShow());
     }
 
     // Test in range views.
     for (int i = 0; i < max_views_; ++i) {
-      second_promo.views_ = i;
-      EXPECT_TRUE(second_promo.CanShow());
+      third_promo.views_ = i;
+      EXPECT_TRUE(third_promo.CanShow());
     }
 
     // Reset prefs to default.
@@ -200,10 +205,7 @@
     first_promo.InitFromPrefs(promo_type_);
     EXPECT_FALSE(first_promo.closed_);
     EXPECT_TRUE(first_promo.CanShow());
-
     first_promo.HandleClosed();
-    EXPECT_TRUE(first_promo.closed_);
-    EXPECT_FALSE(first_promo.CanShow());
 
     // Initialize another promo to test that the the closing of the promo was
     // recorded correctly in prefs.
@@ -274,14 +276,11 @@
   void TestFirstViewTimeRecorded() {
     EXPECT_EQ(0, notification_promo_.first_view_time_);
     notification_promo_.HandleViewed();
-    EXPECT_NE(0, notification_promo_.first_view_time_);
-    double first_viewed = notification_promo_.first_view_time_;
 
     NotificationPromo temp_promo(&local_state_);
     temp_promo.InitFromVariations();
     temp_promo.InitFromPrefs(promo_type_);
-
-    EXPECT_EQ(first_viewed, temp_promo.first_view_time_);
+    EXPECT_NE(0, temp_promo.first_view_time_);
 
     notification_promo_.views_ = 0;
     notification_promo_.first_view_time_ = 0;
diff --git a/ios/chrome/ios_chrome_tests.gyp b/ios/chrome/ios_chrome_tests.gyp
index 089381e..320b669b 100644
--- a/ios/chrome/ios_chrome_tests.gyp
+++ b/ios/chrome/ios_chrome_tests.gyp
@@ -29,6 +29,7 @@
         '../../skia/skia.gyp:skia',
         '../../testing/gmock.gyp:gmock',
         '../../testing/gtest.gyp:gtest',
+        '../../third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp:google_toolbox_for_mac',
         '../../third_party/ocmock/ocmock.gyp:ocmock',
         '../../ui/gfx/gfx.gyp:gfx',
         '../../ui/gfx/gfx.gyp:gfx_test_support',
@@ -90,6 +91,7 @@
         'browser/web_resource/web_resource_util_unittest.cc',
         'browser/webp_transcode/webp_decoder_unittest.mm',
         'common/string_util_unittest.mm',
+        'test/google_toolbox_unittest.mm',
       ],
       'actions': [
         {
diff --git a/ios/chrome/test/DEPS b/ios/chrome/test/DEPS
index bf91c10..1e957f7 100644
--- a/ios/chrome/test/DEPS
+++ b/ios/chrome/test/DEPS
@@ -6,5 +6,6 @@
   "+ios/public/test",
   "+ios/web/public",
   "+net/url_request",
+  "+third_party/google_toolbox_for_mac",
   "+ui",
 ]
diff --git a/ios/chrome/test/google_toolbox_unittest.mm b/ios/chrome/test/google_toolbox_unittest.mm
new file mode 100644
index 0000000..5f71b80
--- /dev/null
+++ b/ios/chrome/test/google_toolbox_unittest.mm
@@ -0,0 +1,16 @@
+// Copyright (c) 2016 The Chromium 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 <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "testing/gtest_mac.h"
+#import "third_party/google_toolbox_for_mac/src/Foundation/GTMNSDictionary+URLArguments.h"
+
+// [NSDictionary gtm_dictionaryWithHttpArgumentsString] is used downstream.
+// This test ensures that we keep compiling the file.
+TEST(GoogleToolboxForMacTest, dictionaryWithHttpArgumentsString) {
+  NSDictionary* dict = [NSDictionary gtm_dictionaryWithHttpArgumentsString:@""];
+  EXPECT_EQ(0u, [dict count]);
+}
diff --git a/ios/net/cookies/cookie_cache_unittest.cc b/ios/net/cookies/cookie_cache_unittest.cc
index 188d0bc..f1ec53a 100644
--- a/ios/net/cookies/cookie_cache_unittest.cc
+++ b/ios/net/cookies/cookie_cache_unittest.cc
@@ -17,10 +17,10 @@
 CanonicalCookie MakeCookie(const GURL& url,
                            const std::string& name,
                            const std::string& value) {
-  return CanonicalCookie(url, name, value, url.host(), url.path(), base::Time(),
-                         base::Time(), base::Time(), false, false,
-                         net::CookieSameSite::DEFAULT_MODE,
-                         net::COOKIE_PRIORITY_DEFAULT);
+  return *CanonicalCookie::Create(url, name, value, std::string(), url.path(),
+                                  base::Time(), base::Time(), false, false,
+                                  net::CookieSameSite::DEFAULT_MODE, false,
+                                  net::COOKIE_PRIORITY_DEFAULT);
 }
 
 }  // namespace
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm
index d709910..479f926 100644
--- a/ios/net/cookies/cookie_store_ios_unittest.mm
+++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -259,16 +259,17 @@
 
     // Some canonical cookies cannot be converted into System cookies, for
     // example if value is not valid utf8. Such cookies are ignored.
-    net::CanonicalCookie* bad_canonical_cookie = new net::CanonicalCookie(
-        kTestCookieURL, "name", "\x81r\xe4\xbd\xa0\xe5\xa5\xbd", "domain",
-        "path/",
-        base::Time(),  // creation
-        base::Time(),  // expires
-        base::Time(),  // last_access
-        false,         // secure
-        false,         // httponly
-        net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT);
-    cookies.push_back(bad_canonical_cookie);
+    std::unique_ptr<net::CanonicalCookie> bad_canonical_cookie(
+        net::CanonicalCookie::Create(GURL("http://domain/"), "name",
+                                     "\x81r\xe4\xbd\xa0\xe5\xa5\xbd",
+                                     std::string(), "/path/",
+                                     base::Time(),  // creation
+                                     base::Time(),  // expires
+                                     false,         // secure
+                                     false,         // httponly
+                                     net::CookieSameSite::DEFAULT_MODE, false,
+                                     net::COOKIE_PRIORITY_DEFAULT));
+    cookies.push_back(bad_canonical_cookie.release());
     loaded_callback_.Run(cookies);
   }
 
diff --git a/ios/net/cookies/system_cookie_util.mm b/ios/net/cookies/system_cookie_util.mm
index 9c371dca..b0c1388 100644
--- a/ios/net/cookies/system_cookie_util.mm
+++ b/ios/net/cookies/system_cookie_util.mm
@@ -66,8 +66,8 @@
 net::CanonicalCookie CanonicalCookieFromSystemCookie(
     NSHTTPCookie* cookie,
     const base::Time& ceation_time) {
-  return net::CanonicalCookie(
-      GURL(), base::SysNSStringToUTF8([cookie name]),
+  return *net::CanonicalCookie::Create(
+      base::SysNSStringToUTF8([cookie name]),
       base::SysNSStringToUTF8([cookie value]),
       base::SysNSStringToUTF8([cookie domain]),
       base::SysNSStringToUTF8([cookie path]), ceation_time,
diff --git a/ios/net/cookies/system_cookie_util_unittest.mm b/ios/net/cookies/system_cookie_util_unittest.mm
index ddca583..87a573c 100644
--- a/ios/net/cookies/system_cookie_util_unittest.mm
+++ b/ios/net/cookies/system_cookie_util_unittest.mm
@@ -26,8 +26,8 @@
 
 void CheckSystemCookie(const base::Time& expires, bool secure, bool httponly) {
   // Generate a canonical cookie.
-  net::CanonicalCookie canonical_cookie = net::CanonicalCookie(
-      GURL(), kCookieName, kCookieValue, kCookieDomain, kCookiePath,
+  net::CanonicalCookie canonical_cookie = *net::CanonicalCookie::Create(
+      kCookieName, kCookieValue, kCookieDomain, kCookiePath,
       base::Time(),  // creation
       expires,
       base::Time(),  // last_access
@@ -116,8 +116,8 @@
 
 TEST(CookieUtil, SystemCookieFromBadCanonicalCookie) {
   // Generate a bad canonical cookie (value is invalid utf8).
-  net::CanonicalCookie bad_canonical_cookie = net::CanonicalCookie(
-      GURL(), kCookieName, kCookieValueInvalidUtf8, kCookieDomain, kCookiePath,
+  net::CanonicalCookie bad_canonical_cookie = *net::CanonicalCookie::Create(
+      kCookieName, kCookieValueInvalidUtf8, kCookieDomain, kCookiePath,
       base::Time(),  // creation
       base::Time(),  // expires
       base::Time(),  // last_access
diff --git a/ios/testing/earl_grey/BUILD.gn b/ios/testing/earl_grey/BUILD.gn
index 7c7eeb4..a8e6ecf 100644
--- a/ios/testing/earl_grey/BUILD.gn
+++ b/ios/testing/earl_grey/BUILD.gn
@@ -11,6 +11,7 @@
   testonly = true
 
   deps = [
+    "//base/test:test_support",
     "//ios/third_party/earl_grey",
   ]
 
diff --git a/ios/third_party/earl_grey/BUILD.gn b/ios/third_party/earl_grey/BUILD.gn
index f6fa1526..1c515ef6 100644
--- a/ios/third_party/earl_grey/BUILD.gn
+++ b/ios/third_party/earl_grey/BUILD.gn
@@ -7,17 +7,11 @@
 
 config("config") {
   include_dirs = [ "src/EarlGrey" ]
-
-  # EarlGrey and its dependencies need to link to XCTest.framework
-  # that is not under $ios_sdk_path.
-  common_flags = [ "-F$ios_sdk_path/../../Library/Frameworks" ]
-  cflags_objc = common_flags
-  cflags_objcc = common_flags
-  ldflags = common_flags
 }
 
 ios_framework_bundle("earl_grey") {
   output_name = "EarlGrey"
+  info_plist = "Info.plist"
 
   testonly = true
   sources = [
@@ -257,7 +251,11 @@
     "XCTest.framework",
   ]
 
-  public_configs = [ ":config" ]
+  public_configs = [
+    ":config",
+    "//build/config/ios:xctest_config",
+  ]
+
   configs += [ "//build/config/compiler:enable_arc" ]
   configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
   configs += [ "//build/config/gcc:symbol_visibility_default" ]
diff --git a/ios/third_party/earl_grey/Info.plist b/ios/third_party/earl_grey/Info.plist
new file mode 100644
index 0000000..3506f84e
--- /dev/null
+++ b/ios/third_party/earl_grey/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.chromium.test.${EXECUTABLE_NAME:rfc1034identifier}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+</dict>
+</plist>
diff --git a/ios/third_party/earl_grey/ios_eg_test.gni b/ios/third_party/earl_grey/ios_eg_test.gni
new file mode 100644
index 0000000..39d2102
--- /dev/null
+++ b/ios/third_party/earl_grey/ios_eg_test.gni
@@ -0,0 +1,30 @@
+# Copyright 2016 The Chromium 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/ios/rules.gni")
+
+# EarlGrey tests are just XCTests that also depends on EarlGrey.
+template("ios_eg_test") {
+  ios_xctest_test(target_name) {
+    forward_variables_from(invoker, "*")
+    if (!defined(bundle_deps)) {
+      bundle_deps = []
+    }
+    bundle_deps += [
+      "//ios/third_party/earl_grey:earl_grey+bundle",
+      "//ios/third_party/ochamcrest:ochamcrest+bundle",
+    ]
+    if (!defined(deps)) {
+      deps = []
+    }
+    deps += [
+      "//ios/third_party/earl_grey:earl_grey+link",
+      "//ios/third_party/ochamcrest:ochamcrest+link",
+    ]
+  }
+}
+
+set_defaults("ios_eg_test") {
+  configs = default_executable_configs
+}
diff --git a/ios/third_party/ochamcrest/BUILD.gn b/ios/third_party/ochamcrest/BUILD.gn
index 4994658..9c1038b 100644
--- a/ios/third_party/ochamcrest/BUILD.gn
+++ b/ios/third_party/ochamcrest/BUILD.gn
@@ -6,6 +6,7 @@
 
 ios_framework_bundle("ochamcrest") {
   output_name = "OCHamcrest"
+  info_plist = "Info.plist"
 
   testonly = true
   sources = [
diff --git a/ios/third_party/ochamcrest/Info.plist b/ios/third_party/ochamcrest/Info.plist
new file mode 100644
index 0000000..3506f84e
--- /dev/null
+++ b/ios/third_party/ochamcrest/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.chromium.test.${EXECUTABLE_NAME:rfc1034identifier}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+</dict>
+</plist>
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 8a82307..a70b99a07 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -302,6 +302,7 @@
     ":web",
     "//base",
     "//base/test:test_support",
+    "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey",
   ]
 
diff --git a/ios/web/ios_web_shell_tests.gyp b/ios/web/ios_web_shell_tests.gyp
index de75264..1a50a2b 100644
--- a/ios/web/ios_web_shell_tests.gyp
+++ b/ios/web/ios_web_shell_tests.gyp
@@ -8,6 +8,7 @@
   },
   'targets': [
     {
+      # GN version: //ios/web/shell/test:ios_web_shell_test
       'target_name': 'ios_web_shell_test',
       'type': 'loadable_module',
       'mac_xctest_bundle': 1,
@@ -40,6 +41,7 @@
     {
       # Create a test host for earl grey tests, so Xcode 7.3 and above
       # doesn't contaminate the app structure.
+      # GN version: //ios/web/shell/test:ios_web_shell_test_host
       'target_name': 'ios_web_shell_test_host',
       'includes': [
         'ios_web_shell_exe.gypi',
@@ -61,8 +63,9 @@
         '<(DEPTH)/ios/third_party/earl_grey/earl_grey.gyp:EarlGrey',
       ],
       'sources': [
-        'shell/test/web_shell_navigation_egtest.mm',
-        'shell/test/web_shell_page_state_egtest.mm',
+        'shell/test/meta_tags_egtest.mm',
+        'shell/test/navigation_egtest.mm',
+        'shell/test/page_state_egtest.mm',
       ],
       'actions': [{
         'action_name': 'copy_test_data',
@@ -102,6 +105,7 @@
     {
       # TODO(crbug.com/606815): Refactor out code that is common across Chrome
       # and the web shell.
+      # GN version: //ios/web/shell/test:earl_grey_test_support
       'target_name': 'ios_web_shell_earl_grey_test_support',
       'type': 'static_library',
       'dependencies': [
diff --git a/ios/web/shell/BUILD.gn b/ios/web/shell/BUILD.gn
index b941003..71c8d84a 100644
--- a/ios/web/shell/BUILD.gn
+++ b/ios/web/shell/BUILD.gn
@@ -8,10 +8,6 @@
 ios_app_bundle("ios_web_shell") {
   info_plist = "Info.plist"
 
-  sources = [
-    "web_exe_main.mm",
-  ]
-
   deps = [
     ":shell",
 
@@ -56,6 +52,7 @@
     "shell_web_main_parts.mm",
     "view_controller.h",
     "view_controller.mm",
+    "web_exe_main.mm",
   ]
 
   deps = [
diff --git a/ios/web/shell/test/BUILD.gn b/ios/web/shell/test/BUILD.gn
new file mode 100644
index 0000000..301bb888
--- /dev/null
+++ b/ios/web/shell/test/BUILD.gn
@@ -0,0 +1,73 @@
+# Copyright 2016 The Chromium 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("//ios/build/config.gni")
+import("//ios/third_party/earl_grey/ios_eg_test.gni")
+
+ios_eg_test("ios_web_shell_test") {
+  sources = [
+    "meta_tags_egtest.mm",
+    "navigation_egtest.mm",
+    "page_state_egtest.mm",
+  ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//ios/web:test_support",
+    "//ios/web/shell",
+    "//ios/web/shell/test:earl_grey_test_support",
+
+    # All shared libraries must have the sanitizer deps to properly link in
+    # asan mode (this target will be empty in other cases).
+    "//build/config/sanitizers:deps",
+  ]
+
+  bundle_deps = [ ":bundle" ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  assert_no_deps = ios_assert_no_deps
+}
+
+source_set("earl_grey_test_support") {
+  testonly = true
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//ios/testing/earl_grey:earl_grey_support",
+    "//ios/third_party/earl_grey",
+    "//ios/web",
+    "//ios/web:earl_grey_test_support",
+    "//ios/web:test_support",
+    "//ios/web/shell",
+    "//url",
+  ]
+
+  sources = [
+    "app/navigation_test_util.h",
+    "app/navigation_test_util.mm",
+    "app/web_shell_test_util.h",
+    "app/web_shell_test_util.mm",
+    "app/web_view_interaction_test_util.h",
+    "app/web_view_interaction_test_util.mm",
+    "earl_grey/shell_base_test_case.h",
+    "earl_grey/shell_base_test_case.mm",
+    "earl_grey/shell_matchers.h",
+    "earl_grey/shell_matchers.mm",
+  ]
+}
+
+bundle_data("bundle") {
+  visibility = [ ":ios_web_shell_test_host" ]
+  sources = [
+    "http_server_files/basic_navigation_test.html",
+    "http_server_files/tall_page.html",
+  ]
+  outputs = [
+    "{{bundle_resources_dir}}/{{source_root_relative_dir}}/" +
+        "{{source_file_part}}",
+  ]
+}
diff --git a/ios/web/shell/test/meta_tags_egtest.mm b/ios/web/shell/test/meta_tags_egtest.mm
new file mode 100644
index 0000000..b6cf8172
--- /dev/null
+++ b/ios/web/shell/test/meta_tags_egtest.mm
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+
+#include "base/strings/stringprintf.h"
+#include "base/test/ios/wait_util.h"
+#import "ios/web/public/test/http_server.h"
+#include "ios/web/public/test/http_server_util.h"
+#include "ios/web/shell/test/app/navigation_test_util.h"
+#import "ios/web/shell/test/earl_grey/shell_base_test_case.h"
+#import "ios/web/shell/test/earl_grey/shell_matchers.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// A simple test page with generic content.
+const char kDestinationPage[] = "You've arrived!";
+
+// Template for a test page with META refresh tag. Required template arguments
+// are: refresh time in seconds (integer) and destination URL for redirect
+// (string).
+const char kRefreshMetaPageTemplate[] =
+    "<!DOCTYPE html>"
+    "<html>"
+    "  <head><meta HTTP-EQUIV='REFRESH' content='%d;url=%s'></head>"
+    "  <body></body>"
+    "</html>";
+
+}  // namespace
+
+using web::test::HttpServer;
+using web::addressFieldText;
+using web::webViewContainingText;
+
+// META tag test cases for the web shell.
+@interface MetaTagsTest : ShellBaseTestCase
+@end
+
+@implementation MetaTagsTest
+
+// Tests loading of a page with a META tag having a refresh value of 0 seconds.
+- (void)testMetaRefresh0Seconds {
+  [self runMetaRefreshTestWithRefreshInterval:0];
+}
+
+// Tests loading of a page with a META tag having a refresh value of 3 seconds.
+- (void)testMetaRefresh3Seconds {
+  [self runMetaRefreshTestWithRefreshInterval:3];
+}
+
+// Loads a page with a META tag having a refresh value of |refreshInterval|
+// seconds and verifies that redirect happens.
+- (void)runMetaRefreshTestWithRefreshInterval:(int)refreshIntervalInSeconds {
+  // Create map of canned responses and set up the test HTML server.
+  std::map<GURL, std::string> responses;
+  const GURL originURL = HttpServer::MakeUrl("http://origin");
+  const GURL destinationURL = HttpServer::MakeUrl("http://destination");
+  responses[originURL] =
+      base::StringPrintf(kRefreshMetaPageTemplate, refreshIntervalInSeconds,
+                         destinationURL.spec().c_str());
+  responses[destinationURL] = kDestinationPage;
+  web::test::SetUpSimpleHttpServer(responses);
+
+  web::shell_test_util::LoadUrl(originURL);
+
+  // Wait for redirect.
+  base::test::ios::SpinRunLoopWithMaxDelay(
+      base::TimeDelta::FromSecondsD(refreshIntervalInSeconds));
+
+  // Verify that redirect happened.
+  [[EarlGrey selectElementWithMatcher:addressFieldText(destinationURL.spec())]
+      assertWithMatcher:grey_notNil()];
+  [[EarlGrey selectElementWithMatcher:webViewContainingText(kDestinationPage)]
+      assertWithMatcher:grey_notNil()];
+}
+
+@end
diff --git a/ios/web/shell/test/web_shell_navigation_egtest.mm b/ios/web/shell/test/navigation_egtest.mm
similarity index 97%
rename from ios/web/shell/test/web_shell_navigation_egtest.mm
rename to ios/web/shell/test/navigation_egtest.mm
index d51781ff..7c013bf 100644
--- a/ios/web/shell/test/web_shell_navigation_egtest.mm
+++ b/ios/web/shell/test/navigation_egtest.mm
@@ -16,13 +16,16 @@
 #import "ios/web/shell/test/earl_grey/shell_base_test_case.h"
 #import "ios/web/shell/test/earl_grey/shell_matchers.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // Navigation test cases for the web shell. These are Earl Grey integration
 // tests, which are based on XCTest.
-@interface CRWWebShellNavigationTest : ShellBaseTestCase
-
+@interface NavigationTest : ShellBaseTestCase
 @end
 
-@implementation CRWWebShellNavigationTest
+@implementation NavigationTest
 
 // Tests clicking a link to about:blank.
 - (void)testNavigationLinkToAboutBlank {
diff --git a/ios/web/shell/test/web_shell_page_state_egtest.mm b/ios/web/shell/test/page_state_egtest.mm
similarity index 97%
rename from ios/web/shell/test/web_shell_page_state_egtest.mm
rename to ios/web/shell/test/page_state_egtest.mm
index 4e6a096..055bade 100644
--- a/ios/web/shell/test/web_shell_page_state_egtest.mm
+++ b/ios/web/shell/test/page_state_egtest.mm
@@ -52,11 +52,10 @@
 using web::webViewContainingText;
 
 // Page state test cases for the web shell.
-@interface CRWWebShellPageStateTest : ShellBaseTestCase
-
+@interface PageStateTest : ShellBaseTestCase
 @end
 
-@implementation CRWWebShellPageStateTest
+@implementation PageStateTest
 
 // Tests that page scroll position of a page is restored upon returning to the
 // page via the back/forward buttons.
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index 85fcd84c..d9998db 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -165,8 +165,6 @@
   sources = [
     "ipc.mojom",
   ]
-
-  use_new_wrapper_types = false
 }
 
 mojom("test_interfaces") {
@@ -174,8 +172,6 @@
   sources = [
     "ipc_test.mojom",
   ]
-
-  use_new_wrapper_types = false
 }
 
 # This is provided as a separate target so other targets can provide param
diff --git a/ipc/ipc.gyp b/ipc/ipc.gyp
index 556498688..56242d6 100644
--- a/ipc/ipc.gyp
+++ b/ipc/ipc.gyp
@@ -45,7 +45,6 @@
         'mojom_files': [
           'ipc.mojom',
         ],
-        'use_new_wrapper_types': 'false',
       },
       'includes': [ '../mojo/mojom_bindings_generator_explicit.gypi' ],
     },
@@ -68,9 +67,6 @@
         'ipc_test.mojom',
       ],
       'includes': [ '../mojo/mojom_bindings_generator.gypi' ],
-      'variables': {
-        'use_new_wrapper_types': 'false',
-      },
     },
     {
       'target_name': 'ipc_run_all_unittests',
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc
index 9ce2e661b..627efc1d 100644
--- a/ipc/ipc_channel_mojo.cc
+++ b/ipc/ipc_channel_mojo.cc
@@ -179,7 +179,7 @@
 }
 
 MojoResult WrapAttachment(MessageAttachment* attachment,
-                          mojo::Array<mojom::SerializedHandlePtr>* handles) {
+                          std::vector<mojom::SerializedHandlePtr>* handles) {
   mojom::SerializedHandlePtr serialized_handle;
   MojoResult wrap_result = WrapAttachmentImpl(attachment, &serialized_handle);
   if (wrap_result != MOJO_RESULT_OK) {
@@ -409,38 +409,46 @@
 // static
 MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
     Message* message,
-    mojo::Array<mojom::SerializedHandlePtr>* handles) {
-  if (message->HasAttachments()) {
-    MessageAttachmentSet* set = message->attachment_set();
-    for (unsigned i = 0; i < set->num_non_brokerable_attachments(); ++i) {
-      MojoResult result = WrapAttachment(
-              set->GetNonBrokerableAttachmentAt(i).get(), handles);
-      if (result != MOJO_RESULT_OK) {
-        set->CommitAllDescriptors();
-        return result;
-      }
-    }
-    for (unsigned i = 0; i < set->num_brokerable_attachments(); ++i) {
-      MojoResult result =
-          WrapAttachment(set->GetBrokerableAttachmentAt(i).get(), handles);
-      if (result != MOJO_RESULT_OK) {
-        set->CommitAllDescriptors();
-        return result;
-      }
-    }
-    set->CommitAllDescriptors();
+    base::Optional<std::vector<mojom::SerializedHandlePtr>>* handles) {
+  DCHECK(!*handles);
+
+  MojoResult result = MOJO_RESULT_OK;
+  if (!message->HasAttachments())
+    return result;
+
+  std::vector<mojom::SerializedHandlePtr> output_handles;
+  MessageAttachmentSet* set = message->attachment_set();
+
+  for (unsigned i = 0;
+       result == MOJO_RESULT_OK && i < set->num_non_brokerable_attachments();
+       ++i) {
+    result = WrapAttachment(set->GetNonBrokerableAttachmentAt(i).get(),
+                            &output_handles);
   }
-  return MOJO_RESULT_OK;
+  for (unsigned i = 0;
+       result == MOJO_RESULT_OK && i < set->num_brokerable_attachments(); ++i) {
+    result = WrapAttachment(set->GetBrokerableAttachmentAt(i).get(),
+                            &output_handles);
+  }
+
+  set->CommitAllDescriptors();
+
+  if (!output_handles.empty())
+    *handles = std::move(output_handles);
+
+  return result;
 }
 
 // static
 MojoResult ChannelMojo::WriteToMessageAttachmentSet(
-    mojo::Array<mojom::SerializedHandlePtr> handle_buffer,
+    base::Optional<std::vector<mojom::SerializedHandlePtr>> handle_buffer,
     Message* message) {
-  for (size_t i = 0; i < handle_buffer.size(); ++i) {
+  if (!handle_buffer)
+    return MOJO_RESULT_OK;
+  for (size_t i = 0; i < handle_buffer->size(); ++i) {
     scoped_refptr<MessageAttachment> unwrapped_attachment;
-    MojoResult unwrap_result = UnwrapAttachment(std::move(handle_buffer[i]),
-                                                    &unwrapped_attachment);
+    MojoResult unwrap_result =
+        UnwrapAttachment(std::move((*handle_buffer)[i]), &unwrapped_attachment);
     if (unwrap_result != MOJO_RESULT_OK) {
       LOG(WARNING) << "Pipe failed to unwrap handles. Closing: "
                    << unwrap_result;
diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h
index cfadb50..85c84aa 100644
--- a/ipc/ipc_channel_mojo.h
+++ b/ipc/ipc_channel_mojo.h
@@ -83,11 +83,11 @@
   // These access protected API of IPC::Message, which has ChannelMojo
   // as a friend class.
   static MojoResult WriteToMessageAttachmentSet(
-      mojo::Array<mojom::SerializedHandlePtr> handle_buffer,
+      base::Optional<std::vector<mojom::SerializedHandlePtr>> handle_buffer,
       Message* message);
   static MojoResult ReadFromMessageAttachmentSet(
       Message* message,
-      mojo::Array<mojom::SerializedHandlePtr>* handles);
+      base::Optional<std::vector<mojom::SerializedHandlePtr>>* handles);
 
   // MojoBootstrapDelegate implementation
   void OnPipesAvailable(mojom::ChannelAssociatedPtr sender,
diff --git a/ipc/ipc_channel_mojo_unittest.cc b/ipc/ipc_channel_mojo_unittest.cc
index f7652e7..41950d29 100644
--- a/ipc/ipc_channel_mojo_unittest.cc
+++ b/ipc/ipc_channel_mojo_unittest.cc
@@ -265,7 +265,8 @@
   Close();
 }
 
-TEST_F(IPCChannelMojoTest, SendFailWithPendingMessages) {
+// Disabled because flake. http://crbug.com/630831
+TEST_F(IPCChannelMojoTest, DISABLED_SendFailWithPendingMessages) {
   InitWithMojo("IPCChannelMojoErraticTestClient");
 
   // Set up IPC channel and start client.
@@ -628,7 +629,7 @@
 
  private:
   // IPC::mojom::SimpleTestDriver:
-  void ExpectString(const mojo::String& str) override {
+  void ExpectString(const std::string& str) override {
     next_expected_string_ = str;
   }
 
@@ -805,7 +806,7 @@
 
  private:
   // IPC::mojom::SimpleTestDriver:
-  void ExpectString(const mojo::String& str) override {
+  void ExpectString(const std::string& str) override {
     next_expected_string_ = str;
   }
 
diff --git a/ipc/ipc_message_pipe_reader.cc b/ipc/ipc_message_pipe_reader.cc
index 8e1b355..4d8ec8e 100644
--- a/ipc/ipc_message_pipe_reader.cc
+++ b/ipc/ipc_message_pipe_reader.cc
@@ -86,20 +86,20 @@
                          "MessagePipeReader::Send",
                          message->flags(),
                          TRACE_EVENT_FLAG_FLOW_OUT);
-  mojo::Array<mojom::SerializedHandlePtr> handles(nullptr);
+  base::Optional<std::vector<mojom::SerializedHandlePtr>> handles;
   MojoResult result = MOJO_RESULT_OK;
   result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles);
   if (result != MOJO_RESULT_OK)
     return false;
 
-  mojo::Array<uint8_t> data(message->size());
+  std::vector<uint8_t> data(message->size());
   std::copy(reinterpret_cast<const uint8_t*>(message->data()),
             reinterpret_cast<const uint8_t*>(message->data()) + message->size(),
-            &data[0]);
+            data.data());
 
   MessageSerializer serializer;
   mojom::ChannelProxy proxy(&serializer);
-  proxy.Receive(std::move(data), std::move(handles));
+  proxy.Receive(data, std::move(handles));
   mojo::Message* mojo_message = serializer.message();
 
   size_t num_handles = mojo_message->handles()->size();
@@ -127,11 +127,11 @@
 }
 
 void MessagePipeReader::Receive(
-    mojo::Array<uint8_t> data,
-    mojo::Array<mojom::SerializedHandlePtr> handles) {
+    const std::vector<uint8_t>& data,
+    base::Optional<std::vector<mojom::SerializedHandlePtr>> handles) {
   DCHECK_NE(peer_pid_, base::kNullProcessId);
   Message message(
-      data.size() == 0 ? "" : reinterpret_cast<const char*>(&data[0]),
+      data.empty() ? "" : reinterpret_cast<const char*>(data.data()),
       static_cast<uint32_t>(data.size()));
   message.set_sender_pid(peer_pid_);
 
@@ -151,7 +151,7 @@
 }
 
 void MessagePipeReader::GetAssociatedInterface(
-    const mojo::String& name,
+    const std::string& name,
     mojom::GenericInterfaceAssociatedRequest request) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (delegate_)
diff --git a/ipc/ipc_message_pipe_reader.h b/ipc/ipc_message_pipe_reader.h
index e6a2a137..c00cab4 100644
--- a/ipc/ipc_message_pipe_reader.h
+++ b/ipc/ipc_message_pipe_reader.h
@@ -95,10 +95,11 @@
  private:
   // mojom::Channel:
   void SetPeerPid(int32_t peer_pid) override;
-  void Receive(mojo::Array<uint8_t> data,
-               mojo::Array<mojom::SerializedHandlePtr> handles) override;
+  void Receive(
+      const std::vector<uint8_t>& data,
+      base::Optional<std::vector<mojom::SerializedHandlePtr>> handles) override;
   void GetAssociatedInterface(
-      const mojo::String& name,
+      const std::string& name,
       mojom::GenericInterfaceAssociatedRequest request) override;
 
   // |delegate_| is null once the message pipe is closed.
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index c5fe017b..5f710396 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -55,6 +55,9 @@
 // for details.
 const char kEnableExclusiveAudio[] = "enable-exclusive-audio";
 
+// Enables H264 HW encode acceleration using Media Foundation for Windows.
+const char kEnableMFH264Encoding[] = "enable-mf-h264-encoding";
+
 // Force the use of MediaFoundation for video capture. This is only supported in
 // Windows 7 and above. Used, like |kForceDirectShowVideoCapture|, to
 // troubleshoot problems in Windows platforms.
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 322f552..81d562dd 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -37,6 +37,7 @@
 
 #if defined(OS_WIN)
 MEDIA_EXPORT extern const char kEnableExclusiveAudio[];
+MEDIA_EXPORT extern const char kEnableMFH264Encoding[];
 MEDIA_EXPORT extern const char kForceMediaFoundationVideoCapture[];
 MEDIA_EXPORT extern const char kForceWaveAudio[];
 MEDIA_EXPORT extern const char kTrySupportedChannelLayouts[];
diff --git a/media/base/win/BUILD.gn b/media/base/win/BUILD.gn
index a90f7c94..f006c4c1 100644
--- a/media/base/win/BUILD.gn
+++ b/media/base/win/BUILD.gn
@@ -8,6 +8,8 @@
   defines = [ "MF_INITIALIZER_IMPLEMENTATION" ]
   set_sources_assignment_filter([])
   sources = [
+    "mf_helpers.cc",
+    "mf_helpers.h",
     "mf_initializer.cc",
     "mf_initializer.h",
     "mf_initializer_export.h",
diff --git a/media/base/win/mf_helpers.cc b/media/base/win/mf_helpers.cc
new file mode 100644
index 0000000..e5df966
--- /dev/null
+++ b/media/base/win/mf_helpers.cc
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. 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/win/mf_helpers.h"
+
+namespace media {
+
+namespace mf {
+
+void LogDXVAError(int line) {
+  LOG(ERROR) << "Error in dxva_video_decode_accelerator_win.cc on line "
+             << line;
+}
+
+IMFSample* CreateEmptySampleWithBuffer(uint32_t buffer_length, int align) {
+  CHECK_GT(buffer_length, 0U);
+
+  base::win::ScopedComPtr<IMFSample> sample;
+  HRESULT hr = MFCreateSample(sample.Receive());
+  RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL);
+
+  base::win::ScopedComPtr<IMFMediaBuffer> buffer;
+  if (align == 0) {
+    // Note that MFCreateMemoryBuffer is same as MFCreateAlignedMemoryBuffer
+    // with the align argument being 0.
+    hr = MFCreateMemoryBuffer(buffer_length, buffer.Receive());
+  } else {
+    hr =
+        MFCreateAlignedMemoryBuffer(buffer_length, align - 1, buffer.Receive());
+  }
+  RETURN_ON_HR_FAILURE(hr, "Failed to create memory buffer for sample", NULL);
+
+  hr = sample->AddBuffer(buffer.get());
+  RETURN_ON_HR_FAILURE(hr, "Failed to add buffer to sample", NULL);
+
+  buffer->SetCurrentLength(0);
+  return sample.Detach();
+}
+
+MediaBufferScopedPointer::MediaBufferScopedPointer(IMFMediaBuffer* media_buffer)
+    : media_buffer_(media_buffer),
+      buffer_(nullptr),
+      max_length_(0),
+      current_length_(0) {
+  HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, &current_length_);
+  CHECK(SUCCEEDED(hr));
+}
+
+MediaBufferScopedPointer::~MediaBufferScopedPointer() {
+  HRESULT hr = media_buffer_->Unlock();
+  CHECK(SUCCEEDED(hr));
+}
+
+}  // namespace mf
+
+}  // namespace media
\ No newline at end of file
diff --git a/media/base/win/mf_helpers.h b/media/base/win/mf_helpers.h
new file mode 100644
index 0000000..a99eced
--- /dev/null
+++ b/media/base/win/mf_helpers.h
@@ -0,0 +1,77 @@
+// Copyright 2016 The Chromium Authors. 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_WIN_MF_HELPERS_H_
+#define MEDIA_BASE_WIN_MF_HELPERS_H_
+
+#include <mfapi.h>
+#include <stdint.h>
+
+#include "base/win/scoped_comptr.h"
+#include "media/base/win/mf_initializer_export.h"
+
+namespace media {
+
+namespace mf {
+
+#define RETURN_ON_FAILURE(result, log, ret) \
+  do {                                      \
+    if (!(result)) {                        \
+      DLOG(ERROR) << log;                   \
+      mf::LogDXVAError(__LINE__);           \
+      return ret;                           \
+    }                                       \
+  } while (0)
+
+#define RETURN_ON_HR_FAILURE(result, log, ret) \
+  RETURN_ON_FAILURE(SUCCEEDED(result),         \
+                    log << ", HRESULT: 0x" << std::hex << result, ret);
+
+#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
+  do {                                                             \
+    if (!(result)) {                                               \
+      DVLOG(1) << log;                                             \
+      mf::LogDXVAError(__LINE__);                                  \
+      StopOnError(error_code);                                     \
+      return ret;                                                  \
+    }                                                              \
+  } while (0)
+
+#define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret)        \
+  RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result),                            \
+                               log << ", HRESULT: 0x" << std::hex << result, \
+                               error_code, ret);
+
+MF_INITIALIZER_EXPORT void LogDXVAError(int line);
+
+// Creates a Media Foundation sample with one buffer of length |buffer_length|
+// on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0.
+MF_INITIALIZER_EXPORT IMFSample* CreateEmptySampleWithBuffer(
+    uint32_t buffer_length,
+    int align);
+
+// Provides scoped access to the underlying buffer in an IMFMediaBuffer
+// instance.
+class MF_INITIALIZER_EXPORT MediaBufferScopedPointer {
+ public:
+  MediaBufferScopedPointer(IMFMediaBuffer* media_buffer);
+  ~MediaBufferScopedPointer();
+
+  uint8_t* get() { return buffer_; }
+  DWORD current_length() const { return current_length_; }
+
+ private:
+  base::win::ScopedComPtr<IMFMediaBuffer> media_buffer_;
+  uint8_t* buffer_;
+  DWORD max_length_;
+  DWORD current_length_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer);
+};
+
+}  // namespace mf
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_WIN_MF_HELPERS_H_
\ No newline at end of file
diff --git a/media/capture/content/android/screen_capture_machine_android.cc b/media/capture/content/android/screen_capture_machine_android.cc
index 19327a0..204cb55a 100644
--- a/media/capture/content/android/screen_capture_machine_android.cc
+++ b/media/capture/content/android/screen_capture_machine_android.cc
@@ -8,8 +8,6 @@
 #include "base/android/jni_android.h"
 #include "base/android/scoped_java_ref.h"
 #include "jni/ScreenCapture_jni.h"
-#include "media/base/video_capture_types.h"
-#include "media/base/yuv_convert.h"
 #include "media/capture/content/video_capture_oracle.h"
 #include "third_party/libyuv/include/libyuv.h"
 
@@ -60,10 +58,10 @@
   DCHECK(frame->format() == PIXEL_FORMAT_I420 ||
          frame->format() == PIXEL_FORMAT_YV12);
 
-  scoped_refptr<VideoFrame> unscaled_frame = frame;
+  scoped_refptr<VideoFrame> temp_frame = frame;
   if (frame->visible_rect().width() != width ||
       frame->visible_rect().height() != height) {
-    unscaled_frame = VideoFrame::CreateFrame(
+    temp_frame = VideoFrame::CreateFrame(
         PIXEL_FORMAT_I420, gfx::Size(width, height), gfx::Rect(width, height),
         gfx::Size(width, height), base::TimeDelta());
   }
@@ -74,33 +72,31 @@
 
   const int offset = top * row_stride + left * 4;
   // ABGR little endian (rgba in memory) to I420.
-  libyuv::ABGRToI420(src + offset, row_stride,
-                     unscaled_frame->visible_data(VideoFrame::kYPlane),
-                     unscaled_frame->stride(VideoFrame::kYPlane),
-                     unscaled_frame->visible_data(VideoFrame::kUPlane),
-                     unscaled_frame->stride(VideoFrame::kUPlane),
-                     unscaled_frame->visible_data(VideoFrame::kVPlane),
-                     unscaled_frame->stride(VideoFrame::kVPlane),
-                     unscaled_frame->visible_rect().width(),
-                     unscaled_frame->visible_rect().height());
+  libyuv::ABGRToI420(
+      src + offset, row_stride, temp_frame->visible_data(VideoFrame::kYPlane),
+      temp_frame->stride(VideoFrame::kYPlane),
+      temp_frame->visible_data(VideoFrame::kUPlane),
+      temp_frame->stride(VideoFrame::kUPlane),
+      temp_frame->visible_data(VideoFrame::kVPlane),
+      temp_frame->stride(VideoFrame::kVPlane),
+      temp_frame->visible_rect().width(), temp_frame->visible_rect().height());
 
-  if (unscaled_frame != frame) {
-    libyuv::I420Scale(unscaled_frame->visible_data(VideoFrame::kYPlane),
-                      unscaled_frame->stride(VideoFrame::kYPlane),
-                      unscaled_frame->visible_data(VideoFrame::kUPlane),
-                      unscaled_frame->stride(VideoFrame::kUPlane),
-                      unscaled_frame->visible_data(VideoFrame::kVPlane),
-                      unscaled_frame->stride(VideoFrame::kVPlane),
-                      unscaled_frame->visible_rect().width(),
-                      unscaled_frame->visible_rect().height(),
-                      frame->visible_data(VideoFrame::kYPlane),
-                      frame->stride(VideoFrame::kYPlane),
-                      frame->visible_data(VideoFrame::kUPlane),
-                      frame->stride(VideoFrame::kUPlane),
-                      frame->visible_data(VideoFrame::kVPlane),
-                      frame->stride(VideoFrame::kVPlane),
-                      frame->visible_rect().width(),
-                      frame->visible_rect().height(), libyuv::kFilterBilinear);
+  if (temp_frame != frame) {
+    libyuv::I420Scale(
+        temp_frame->visible_data(VideoFrame::kYPlane),
+        temp_frame->stride(VideoFrame::kYPlane),
+        temp_frame->visible_data(VideoFrame::kUPlane),
+        temp_frame->stride(VideoFrame::kUPlane),
+        temp_frame->visible_data(VideoFrame::kVPlane),
+        temp_frame->stride(VideoFrame::kVPlane),
+        temp_frame->visible_rect().width(), temp_frame->visible_rect().height(),
+        frame->visible_data(VideoFrame::kYPlane),
+        frame->stride(VideoFrame::kYPlane),
+        frame->visible_data(VideoFrame::kUPlane),
+        frame->stride(VideoFrame::kUPlane),
+        frame->visible_data(VideoFrame::kVPlane),
+        frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
+        frame->visible_rect().height(), libyuv::kFilterBilinear);
   }
 
   capture_frame_cb.Run(frame, start_time, true);
@@ -137,6 +133,14 @@
   DCHECK(frame->format() == PIXEL_FORMAT_I420 ||
          frame->format() == PIXEL_FORMAT_YV12);
 
+  scoped_refptr<VideoFrame> temp_frame = frame;
+  if (frame->visible_rect().width() != width ||
+      frame->visible_rect().height() != height) {
+    temp_frame = VideoFrame::CreateFrame(
+        PIXEL_FORMAT_I420, gfx::Size(width, height), gfx::Rect(width, height),
+        gfx::Size(width, height), base::TimeDelta());
+  }
+
   uint8_t* const y_src =
       reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer));
   CHECK(y_src);
@@ -147,43 +151,36 @@
       reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer));
   CHECK(v_src);
 
-  // De-interleave the U and V planes into temporary buffers, if needed.
-  int uv_stride = uv_row_stride;
-  std::unique_ptr<uint8_t[]> u_tmp, v_tmp;
-  if (uv_pixel_stride != 1) {
-    // U and V planes are actually interleaved, unpack them here.
-    // TODO(braveyao): According to
-    // https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888,
-    // how U and V planes are interlaced is not guaranteed, so there is no an
-    // existing libyuv function suitable for such a job. Filed a request at
-    // https://bugs.chromium.org/p/libyuv/issues/detail?id=604. Switch to new
-    // function when it's available.
-    const int uv_plane_len = (int)env->GetDirectBufferCapacity(u_buffer);
-    u_tmp.reset(new uint8_t[(uv_plane_len + 1) / uv_pixel_stride]);
-    v_tmp.reset(new uint8_t[(uv_plane_len + 1) / uv_pixel_stride]);
-    for (int index = 0; index * uv_pixel_stride <= uv_plane_len; index++) {
-      u_tmp[index] = u_src[index * uv_pixel_stride];
-      v_tmp[index] = v_src[index * uv_pixel_stride];
-    }
-    u_src = u_tmp.get();
-    v_src = v_tmp.get();
-    uv_stride /= uv_pixel_stride;
-  }
-
   const int y_offset = top * y_stride + left;
-  const int uv_offset = (top / 2) * uv_stride + left / 2;
-  // Note: If source width/height are same as the frame's width/height, the
-  // following will, internally, just perform a copy without scaling.
-  libyuv::I420Scale(y_src + y_offset, y_stride, u_src + uv_offset, uv_stride,
-                    v_src + uv_offset, uv_stride, width, height,
-                    frame->visible_data(VideoFrame::kYPlane),
-                    frame->stride(VideoFrame::kYPlane),
-                    frame->visible_data(VideoFrame::kUPlane),
-                    frame->stride(VideoFrame::kUPlane),
-                    frame->visible_data(VideoFrame::kVPlane),
-                    frame->stride(VideoFrame::kVPlane),
-                    frame->visible_rect().width(),
-                    frame->visible_rect().height(), libyuv::kFilterBilinear);
+  const int uv_offset = (top / 2) * uv_row_stride + left / 2;
+  libyuv::Android420ToI420(
+      y_src + y_offset, y_stride, u_src + uv_offset, uv_row_stride,
+      v_src + uv_offset, uv_row_stride, uv_pixel_stride,
+      temp_frame->visible_data(VideoFrame::kYPlane),
+      temp_frame->stride(VideoFrame::kYPlane),
+      temp_frame->visible_data(VideoFrame::kUPlane),
+      temp_frame->stride(VideoFrame::kUPlane),
+      temp_frame->visible_data(VideoFrame::kVPlane),
+      temp_frame->stride(VideoFrame::kVPlane),
+      temp_frame->visible_rect().width(), temp_frame->visible_rect().height());
+
+  if (temp_frame != frame) {
+    libyuv::I420Scale(
+        temp_frame->visible_data(VideoFrame::kYPlane),
+        temp_frame->stride(VideoFrame::kYPlane),
+        temp_frame->visible_data(VideoFrame::kUPlane),
+        temp_frame->stride(VideoFrame::kUPlane),
+        temp_frame->visible_data(VideoFrame::kVPlane),
+        temp_frame->stride(VideoFrame::kVPlane),
+        temp_frame->visible_rect().width(), temp_frame->visible_rect().height(),
+        frame->visible_data(VideoFrame::kYPlane),
+        frame->stride(VideoFrame::kYPlane),
+        frame->visible_data(VideoFrame::kUPlane),
+        frame->stride(VideoFrame::kUPlane),
+        frame->visible_data(VideoFrame::kVPlane),
+        frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
+        frame->visible_rect().height(), libyuv::kFilterBilinear);
+  }
 
   capture_frame_cb.Run(frame, start_time, true);
 
diff --git a/media/capture/content/android/screen_capture_machine_android.h b/media/capture/content/android/screen_capture_machine_android.h
index 68eb8596..84bf1c71 100644
--- a/media/capture/content/android/screen_capture_machine_android.h
+++ b/media/capture/content/android/screen_capture_machine_android.h
@@ -37,7 +37,7 @@
   void OnI420FrameAvailable(JNIEnv* env,
                             jobject obj,
                             jobject y_buffer,
-                            jint y_Zde,
+                            jint y_stride,
                             jobject u_buffer,
                             jobject v_buffer,
                             jint uv_row_stride,
diff --git a/media/capture/video/android/BUILD.gn b/media/capture/video/android/BUILD.gn
index 92d1f45..a1cb14ba 100644
--- a/media/capture/video/android/BUILD.gn
+++ b/media/capture/video/android/BUILD.gn
@@ -28,6 +28,7 @@
   deps = [
     ":capture_jni_headers",
     "//media/mojo/interfaces:image_capture",
+    "//third_party/libyuv",
   ]
 }
 
diff --git a/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java b/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java
index 20f9c37..3b7fcce 100644
--- a/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java
+++ b/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java
@@ -12,12 +12,32 @@
  **/
 @JNINamespace("media")
 class PhotoCapabilities {
+    public final int maxIso;
+    public final int minIso;
+    public final int currentIso;
+    public final int maxHeight;
+    public final int minHeight;
+    public final int currentHeight;
+    public final int maxWidth;
+    public final int minWidth;
+    public final int currentWidth;
     public final int maxZoom;
     public final int minZoom;
     public final int currentZoom;
     public final boolean autoFocusInUse;
 
-    PhotoCapabilities(int maxZoom, int minZoom, int currentZoom, boolean autoFocusInUse) {
+    PhotoCapabilities(int maxIso, int minIso, int currentIso, int maxHeight, int minHeight,
+            int currentHeight, int maxWidth, int minWidth, int currentWidth, int maxZoom,
+            int minZoom, int currentZoom, boolean autoFocusInUse) {
+        this.maxIso = maxIso;
+        this.minIso = minIso;
+        this.currentIso = currentIso;
+        this.maxHeight = maxHeight;
+        this.minHeight = minHeight;
+        this.currentHeight = currentHeight;
+        this.maxWidth = maxWidth;
+        this.minWidth = minWidth;
+        this.currentWidth = currentWidth;
         this.maxZoom = maxZoom;
         this.minZoom = minZoom;
         this.currentZoom = currentZoom;
@@ -25,6 +45,51 @@
     }
 
     @CalledByNative
+    public int getMinIso() {
+        return minIso;
+    }
+
+    @CalledByNative
+    public int getMaxIso() {
+        return maxIso;
+    }
+
+    @CalledByNative
+    public int getCurrentIso() {
+        return currentIso;
+    }
+
+    @CalledByNative
+    public int getMinHeight() {
+        return minHeight;
+    }
+
+    @CalledByNative
+    public int getMaxHeight() {
+        return maxHeight;
+    }
+
+    @CalledByNative
+    public int getCurrentHeight() {
+        return currentHeight;
+    }
+
+    @CalledByNative
+    public int getMinWidth() {
+        return minWidth;
+    }
+
+    @CalledByNative
+    public int getMaxWidth() {
+        return maxWidth;
+    }
+
+    @CalledByNative
+    public int getCurrentWidth() {
+        return currentWidth;
+    }
+
+    @CalledByNative
     public int getMinZoom() {
         return minZoom;
     }
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java b/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java
index 1801dbae..71a8bb17 100644
--- a/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java
+++ b/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java
@@ -12,6 +12,8 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
+import java.nio.ByteBuffer;
+
 /**
  * Video Capture Device base class, defines a set of methods that native code
  * needs to use to configure, start capture, and to be reached by callbacks and
@@ -55,7 +57,7 @@
     public abstract void setZoom(int zoom);
 
     @CalledByNative
-    public abstract boolean takePhoto(final long callbackId);
+    public abstract boolean takePhoto(final long callbackId, int width, int height);
 
     @CalledByNative
     public abstract void deallocate();
@@ -122,6 +124,10 @@
     public native void nativeOnFrameAvailable(
             long nativeVideoCaptureDeviceAndroid, byte[] data, int length, int rotation);
 
+    public native void nativeOnI420FrameAvailable(long nativeVideoCaptureDeviceAndroid,
+            ByteBuffer yBuffer, int yStride, ByteBuffer uBuffer, ByteBuffer vBuffer,
+            int uvRowStride, int uvPixelStride, int width, int height, int rotation);
+
     // Method for VideoCapture implementations to signal an asynchronous error.
     public native void nativeOnError(long nativeVideoCaptureDeviceAndroid, String message);
 
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java
index 112f876..53607868 100644
--- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java
+++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java
@@ -296,6 +296,27 @@
     @Override
     public PhotoCapabilities getPhotoCapabilities() {
         final android.hardware.Camera.Parameters parameters = getCameraParameters(mCamera);
+        Log.d(TAG, " CAM params: " + parameters.flatten());
+
+        // Before the Camera2 API there was no official way to retrieve the supported, if any, ISO
+        // values from |parameters|; some platforms had "iso-values", others "iso-mode-values" etc.
+        // Ignore them.
+        final int maxIso = 0;
+        final int currentIso = 0;
+        final int minIso = 0;
+
+        List<android.hardware.Camera.Size> supportedSizes = parameters.getSupportedPictureSizes();
+        int minWidth = Integer.MAX_VALUE;
+        int minHeight = Integer.MAX_VALUE;
+        int maxWidth = 0;
+        int maxHeight = 0;
+        for (android.hardware.Camera.Size size : supportedSizes) {
+            if (size.width < minWidth) minWidth = size.width;
+            if (size.height < minHeight) minHeight = size.height;
+            if (size.width > maxWidth) maxWidth = size.width;
+            if (size.height > maxHeight) maxHeight = size.height;
+        }
+        final android.hardware.Camera.Size currentSize = parameters.getPreviewSize();
 
         int maxZoom = 0;
         int currentZoom = 0;
@@ -316,7 +337,9 @@
                 || focusMode.equals(android.hardware.Camera.Parameters.FOCUS_MODE_INFINITY)
                 || focusMode.equals(android.hardware.Camera.Parameters.FOCUS_MODE_EDOF);
 
-        return new PhotoCapabilities(maxZoom, minZoom, currentZoom, !isFocusManual);
+        return new PhotoCapabilities(minIso, maxIso, currentIso, maxHeight, minHeight,
+                currentSize.height, maxWidth, minWidth, currentSize.width, maxZoom, minZoom,
+                currentZoom, !isFocusManual);
     }
 
     @Override
@@ -338,7 +361,7 @@
     }
 
     @Override
-    public boolean takePhoto(final long callbackId) {
+    public boolean takePhoto(final long callbackId, int width, int height) {
         if (mCamera == null || !mIsRunning) {
             Log.e(TAG, "takePhoto: mCamera is null or is not running");
             return false;
@@ -352,13 +375,41 @@
 
         android.hardware.Camera.Parameters parameters = getCameraParameters(mCamera);
         parameters.setRotation(getCameraRotation());
-        mCamera.setParameters(parameters);
+        final android.hardware.Camera.Size original_size = parameters.getPictureSize();
+
+        List<android.hardware.Camera.Size> supportedSizes = parameters.getSupportedPictureSizes();
+        android.hardware.Camera.Size closestSize = null;
+        int minDiff = Integer.MAX_VALUE;
+        for (android.hardware.Camera.Size size : supportedSizes) {
+            final int diff = ((width > 0) ? Math.abs(size.width - width) : 0)
+                    + ((height > 0) ? Math.abs(size.height - height) : 0);
+            if (diff < minDiff) {
+                minDiff = diff;
+                closestSize = size;
+            }
+        }
+        Log.d(TAG, "requested resolution: (%dx%d)", width, height);
+        if (minDiff != Integer.MAX_VALUE) {
+            Log.d(TAG, " matched (%dx%d)", closestSize.width, closestSize.height);
+            parameters.setPictureSize(closestSize.width, closestSize.height);
+        }
+
         try {
+            mCamera.setParameters(parameters);
             mCamera.takePicture(null, null, null, new CrPictureCallback());
         } catch (RuntimeException ex) {
             Log.e(TAG, "takePicture ", ex);
             return false;
         }
+
+        // Restore original parameters.
+        parameters.setPictureSize(original_size.width, original_size.height);
+        try {
+            mCamera.setParameters(parameters);
+        } catch (RuntimeException ex) {
+            Log.e(TAG, "takePicture ", ex);
+            return false;
+        }
         return true;
     }
 
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
index 51a32dc..6103c146 100644
--- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
+++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.util.Range;
 import android.util.Size;
 import android.view.Surface;
 
@@ -127,9 +128,11 @@
                     throw new IllegalStateException();
                 }
 
-                readImageIntoBuffer(image, mCapturedData);
-                nativeOnFrameAvailable(mNativeVideoCaptureDeviceAndroid, mCapturedData,
-                        mCapturedData.length, getCameraRotation());
+                nativeOnI420FrameAvailable(mNativeVideoCaptureDeviceAndroid,
+                        image.getPlanes()[0].getBuffer(), image.getPlanes()[0].getRowStride(),
+                        image.getPlanes()[1].getBuffer(), image.getPlanes()[2].getBuffer(),
+                        image.getPlanes()[1].getRowStride(), image.getPlanes()[1].getPixelStride(),
+                        image.getWidth(), image.getHeight(), getCameraRotation());
             } catch (IllegalStateException ex) {
                 Log.e(TAG, "acquireLatestImage():", ex);
             }
@@ -225,8 +228,6 @@
 
     private final Object mCameraStateLock = new Object();
 
-    private byte[] mCapturedData;
-
     private CameraDevice mCameraDevice;
     private CameraCaptureSession mPreviewSession;
     private CaptureRequest mPreviewRequest;
@@ -312,47 +313,6 @@
         return true;
     }
 
-    private static void readImageIntoBuffer(Image image, byte[] data) {
-        final int imageWidth = image.getWidth();
-        final int imageHeight = image.getHeight();
-        final Image.Plane[] planes = image.getPlanes();
-
-        int offset = 0;
-        for (int plane = 0; plane < planes.length; ++plane) {
-            final ByteBuffer buffer = planes[plane].getBuffer();
-            final int rowStride = planes[plane].getRowStride();
-            // Experimentally, U and V planes have |pixelStride| = 2, which
-            // essentially means they are packed. That's silly, because we are
-            // forced to unpack here.
-            final int pixelStride = planes[plane].getPixelStride();
-            final int planeWidth = (plane == 0) ? imageWidth : imageWidth / 2;
-            final int planeHeight = (plane == 0) ? imageHeight : imageHeight / 2;
-
-            if (pixelStride == 1 && rowStride == planeWidth) {
-                // Copy whole plane from buffer into |data| at once.
-                buffer.get(data, offset, planeWidth * planeHeight);
-                offset += planeWidth * planeHeight;
-            } else {
-                // Copy pixels one by one respecting pixelStride and rowStride.
-                byte[] rowData = new byte[rowStride];
-                for (int row = 0; row < planeHeight - 1; ++row) {
-                    buffer.get(rowData, 0, rowStride);
-                    for (int col = 0; col < planeWidth; ++col) {
-                        data[offset++] = rowData[col * pixelStride];
-                    }
-                }
-
-                // Last row is special in some devices and may not contain the full
-                // |rowStride| bytes of data. See http://crbug.com/458701 and
-                // http://developer.android.com/reference/android/media/Image.Plane.html#getBuffer()
-                buffer.get(rowData, 0, Math.min(rowStride, buffer.remaining()));
-                for (int col = 0; col < planeWidth; ++col) {
-                    data[offset++] = rowData[col * pixelStride];
-                }
-            }
-        }
-    }
-
     private void changeCameraStateAndNotify(CameraState state) {
         synchronized (mCameraStateLock) {
             mCameraState = state;
@@ -360,6 +320,27 @@
         }
     }
 
+    // Finds the closest Size to (|width|x|height|) in |sizes|, and returns it or null.
+    // Ignores |width| or |height| if either is zero (== don't care).
+    private static Size findClosestSizeInArray(Size[] sizes, int width, int height) {
+        if (sizes == null) return null;
+        Size closestSize = null;
+        int minDiff = Integer.MAX_VALUE;
+        for (Size size : sizes) {
+            final int diff = ((width > 0) ? Math.abs(size.getWidth() - width) : 0)
+                    + ((height > 0) ? Math.abs(size.getHeight() - height) : 0);
+            if (diff < minDiff) {
+                minDiff = diff;
+                closestSize = size;
+            }
+        }
+        if (minDiff == Integer.MAX_VALUE) {
+            Log.e(TAG, "Couldn't find resolution close to (%dx%d)", width, height);
+            return null;
+        }
+        return closestSize;
+    }
+
     static boolean isLegacyDevice(Context appContext, int id) {
         final CameraCharacteristics cameraCharacteristics =
                 getCameraCharacteristics(appContext, id);
@@ -476,18 +457,8 @@
 
         // Find closest supported size.
         final Size[] supportedSizes = streamMap.getOutputSizes(ImageFormat.YUV_420_888);
-        if (supportedSizes == null) return false;
-        Size closestSupportedSize = null;
-        int minDiff = Integer.MAX_VALUE;
-        for (Size size : supportedSizes) {
-            final int diff =
-                    Math.abs(size.getWidth() - width) + Math.abs(size.getHeight() - height);
-            if (diff < minDiff) {
-                minDiff = diff;
-                closestSupportedSize = size;
-            }
-        }
-        if (minDiff == Integer.MAX_VALUE) {
+        final Size closestSupportedSize = findClosestSizeInArray(supportedSizes, width, height);
+        if (closestSupportedSize == null) {
             Log.e(TAG, "No supported resolutions.");
             return false;
         }
@@ -497,9 +468,6 @@
         // |mCaptureFormat| is also used to configure the ImageReader.
         mCaptureFormat = new VideoCaptureFormat(closestSupportedSize.getWidth(),
                 closestSupportedSize.getHeight(), frameRate, ImageFormat.YUV_420_888);
-        int expectedFrameSize = mCaptureFormat.mWidth * mCaptureFormat.mHeight
-                * ImageFormat.getBitsPerPixel(mCaptureFormat.mPixelFormat) / 8;
-        mCapturedData = new byte[expectedFrameSize];
         mCameraNativeOrientation =
                 cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
         // TODO(mcasas): The following line is correct for N5 with prerelease Build,
@@ -562,11 +530,36 @@
     public PhotoCapabilities getPhotoCapabilities() {
         final CameraCharacteristics cameraCharacteristics = getCameraCharacteristics(mContext, mId);
 
+        int minIso = 0;
+        int maxIso = 0;
+        final Range<Integer> iso_range =
+                cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
+        if (iso_range != null) {
+            minIso = iso_range.getLower();
+            maxIso = iso_range.getUpper();
+        }
+        final int currentIso = mPreviewRequest.get(CaptureRequest.SENSOR_SENSITIVITY);
+
+        final StreamConfigurationMap streamMap =
+                cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+        final Size[] supportedSizes = streamMap.getOutputSizes(ImageFormat.JPEG);
+        int minWidth = Integer.MAX_VALUE;
+        int minHeight = Integer.MAX_VALUE;
+        int maxWidth = 0;
+        int maxHeight = 0;
+        for (Size size : supportedSizes) {
+            if (size.getWidth() < minWidth) minWidth = size.getWidth();
+            if (size.getHeight() < minHeight) minHeight = size.getHeight();
+            if (size.getWidth() > maxWidth) maxWidth = size.getWidth();
+            if (size.getHeight() > maxHeight) maxHeight = size.getHeight();
+        }
+        final int currentHeight = mCaptureFormat.getHeight();
+        final int currentWidth = mCaptureFormat.getWidth();
+
         // The Min and Max zoom are returned as x100 by the API to avoid using floating point. There
         // is no min-zoom per se, so clamp it to always 100 (TODO(mcasas): make const member).
         final int minZoom = 100;
         final int maxZoom = Math.round(mMaxZoom * 100);
-
         // Width Ratio x100 is used as measure of current zoom.
         final int currentZoom = 100 * mPreviewRequest.get(CaptureRequest.SCALER_CROP_REGION).width()
                 / cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)
@@ -577,7 +570,9 @@
         final boolean isFocusManual = (focusMode == CameraMetadata.CONTROL_AF_MODE_OFF)
                 || (focusMode == CameraMetadata.CONTROL_AF_MODE_EDOF);
 
-        return new PhotoCapabilities(maxZoom, minZoom, currentZoom, !isFocusManual);
+        return new PhotoCapabilities(minIso, maxIso, currentIso, maxHeight, minHeight,
+                currentHeight, maxWidth, minWidth, currentWidth, maxZoom, minZoom, currentZoom,
+                !isFocusManual);
     }
 
     @Override
@@ -606,12 +601,24 @@
     }
 
     @Override
-    public boolean takePhoto(final long callbackId) {
+    public boolean takePhoto(final long callbackId, int width, int height) {
         Log.d(TAG, "takePhoto " + callbackId);
         if (mCameraDevice == null || mCameraState != CameraState.STARTED) return false;
 
-        final ImageReader imageReader = ImageReader.newInstance(mCaptureFormat.getWidth(),
-                mCaptureFormat.getHeight(), ImageFormat.JPEG, 1 /* maxImages */);
+        final CameraCharacteristics cameraCharacteristics = getCameraCharacteristics(mContext, mId);
+        final StreamConfigurationMap streamMap =
+                cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+        final Size[] supportedSizes = streamMap.getOutputSizes(ImageFormat.JPEG);
+        final Size closestSize = findClosestSizeInArray(supportedSizes, width, height);
+
+        Log.d(TAG, "requested resolution: (%dx%d)", width, height);
+        if (closestSize != null) {
+            Log.d(TAG, " matched (%dx%d)", closestSize.getWidth(), closestSize.getHeight());
+        }
+        final ImageReader imageReader = ImageReader.newInstance(
+                (closestSize != null) ? closestSize.getWidth() : mCaptureFormat.getWidth(),
+                (closestSize != null) ? closestSize.getHeight() : mCaptureFormat.getHeight(),
+                ImageFormat.JPEG, 1 /* maxImages */);
 
         HandlerThread thread = new HandlerThread("CameraPicture");
         thread.start();
diff --git a/media/capture/video/android/photo_capabilities.cc b/media/capture/video/android/photo_capabilities.cc
index 69c9440..aa70d07 100644
--- a/media/capture/video/android/photo_capabilities.cc
+++ b/media/capture/video/android/photo_capabilities.cc
@@ -24,6 +24,58 @@
   return RegisterNativesImpl(env);
 }
 
+int PhotoCapabilities::getMinIso() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getMinIso(AttachCurrentThread(), object_.obj());
+}
+
+int PhotoCapabilities::getMaxIso() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getMaxIso(AttachCurrentThread(), object_.obj());
+}
+
+int PhotoCapabilities::getCurrentIso() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getCurrentIso(AttachCurrentThread(),
+                                              object_.obj());
+}
+
+int PhotoCapabilities::getMinHeight() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getMinHeight(AttachCurrentThread(),
+                                             object_.obj());
+}
+
+int PhotoCapabilities::getMaxHeight() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getMaxHeight(AttachCurrentThread(),
+                                             object_.obj());
+}
+
+int PhotoCapabilities::getCurrentHeight() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getCurrentHeight(AttachCurrentThread(),
+                                                 object_.obj());
+}
+
+int PhotoCapabilities::getMinWidth() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getMinWidth(AttachCurrentThread(),
+                                            object_.obj());
+}
+
+int PhotoCapabilities::getMaxWidth() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getMaxWidth(AttachCurrentThread(),
+                                            object_.obj());
+}
+
+int PhotoCapabilities::getCurrentWidth() const {
+  DCHECK(!object_.is_null());
+  return Java_PhotoCapabilities_getCurrentWidth(AttachCurrentThread(),
+                                                object_.obj());
+}
+
 int PhotoCapabilities::getMinZoom() const {
   DCHECK(!object_.is_null());
   return Java_PhotoCapabilities_getMinZoom(AttachCurrentThread(),
diff --git a/media/capture/video/android/photo_capabilities.h b/media/capture/video/android/photo_capabilities.h
index 8f1a0b81..c154b487d 100644
--- a/media/capture/video/android/photo_capabilities.h
+++ b/media/capture/video/android/photo_capabilities.h
@@ -19,6 +19,15 @@
 
   static bool RegisterPhotoCapabilities(JNIEnv* env);
 
+  int getMinIso() const;
+  int getMaxIso() const;
+  int getCurrentIso() const;
+  int getMinHeight() const;
+  int getMaxHeight() const;
+  int getCurrentHeight() const;
+  int getMinWidth() const;
+  int getMaxWidth() const;
+  int getCurrentWidth() const;
   int getMinZoom() const;
   int getMaxZoom() const;
   int getCurrentZoom() const;
diff --git a/media/capture/video/android/video_capture_device_android.cc b/media/capture/video/android/video_capture_device_android.cc
index 35e12ae..715f8f4 100644
--- a/media/capture/video/android/video_capture_device_android.cc
+++ b/media/capture/video/android/video_capture_device_android.cc
@@ -10,10 +10,12 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "jni/VideoCapture_jni.h"
 #include "media/capture/video/android/photo_capabilities.h"
 #include "media/capture/video/android/video_capture_device_factory_android.h"
+#include "third_party/libyuv/include/libyuv.h"
 
 using base::android::AttachCurrentThread;
 using base::android::CheckException;
@@ -150,7 +152,9 @@
   std::unique_ptr<TakePhotoCallback> heap_callback(
       new TakePhotoCallback(std::move(callback)));
   const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get());
-  if (!Java_VideoCapture_takePhoto(env, j_capture_.obj(), callback_id))
+  if (!Java_VideoCapture_takePhoto(env, j_capture_.obj(), callback_id,
+                                   next_photo_resolution_.width(),
+                                   next_photo_resolution_.height()))
     return;
 
   {
@@ -170,6 +174,18 @@
   // PhotoCapabilities to mojom::PhotoCapabilitiesPtr, https://crbug.com/622002.
   mojom::PhotoCapabilitiesPtr photo_capabilities =
       mojom::PhotoCapabilities::New();
+  photo_capabilities->iso = mojom::Range::New();
+  photo_capabilities->iso->current = caps.getCurrentIso();
+  photo_capabilities->iso->max = caps.getMaxIso();
+  photo_capabilities->iso->min = caps.getMinIso();
+  photo_capabilities->height = mojom::Range::New();
+  photo_capabilities->height->current = caps.getCurrentHeight();
+  photo_capabilities->height->max = caps.getMaxHeight();
+  photo_capabilities->height->min = caps.getMinHeight();
+  photo_capabilities->width = mojom::Range::New();
+  photo_capabilities->width->current = caps.getCurrentWidth();
+  photo_capabilities->width->max = caps.getMaxWidth();
+  photo_capabilities->width->min = caps.getMinWidth();
   photo_capabilities->zoom = mojom::Range::New();
   photo_capabilities->zoom->current = caps.getCurrentZoom();
   photo_capabilities->zoom->max = caps.getMaxZoom();
@@ -184,6 +200,18 @@
     mojom::PhotoSettingsPtr settings,
     SetPhotoOptionsCallback callback) {
   JNIEnv* env = AttachCurrentThread();
+  // |width| and/or |height| are kept for the next TakePhoto()s.
+  if (settings->has_width || settings->has_height)
+    next_photo_resolution_.SetSize(0, 0);
+  if (settings->has_width) {
+    next_photo_resolution_.set_width(
+        base::saturated_cast<int>(settings->width));
+  }
+  if (settings->has_height) {
+    next_photo_resolution_.set_height(
+        base::saturated_cast<int>(settings->height));
+  }
+
   if (settings->has_zoom)
     Java_VideoCapture_setZoom(env, j_capture_.obj(), settings->zoom);
   callback.Run(true);
@@ -208,7 +236,7 @@
     return;
   }
 
-  base::TimeTicks current_time = base::TimeTicks::Now();
+  const base::TimeTicks current_time = base::TimeTicks::Now();
   if (!got_first_frame_) {
     // Set aside one frame allowance for fluctuation.
     expected_next_frame_time_ = current_time - frame_interval_;
@@ -230,6 +258,58 @@
   env->ReleaseByteArrayElements(data, buffer, JNI_ABORT);
 }
 
+void VideoCaptureDeviceAndroid::OnI420FrameAvailable(JNIEnv* env,
+                                                     jobject obj,
+                                                     jobject y_buffer,
+                                                     jint y_stride,
+                                                     jobject u_buffer,
+                                                     jobject v_buffer,
+                                                     jint uv_row_stride,
+                                                     jint uv_pixel_stride,
+                                                     jint width,
+                                                     jint height,
+                                                     jint rotation) {
+  const base::TimeTicks current_time = base::TimeTicks::Now();
+  if (!got_first_frame_) {
+    // Set aside one frame allowance for fluctuation.
+    expected_next_frame_time_ = current_time - frame_interval_;
+    first_ref_time_ = current_time;
+    got_first_frame_ = true;
+  }
+
+  uint8_t* const y_src =
+      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer));
+  CHECK(y_src);
+  uint8_t* const u_src =
+      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer));
+  CHECK(u_src);
+  uint8_t* const v_src =
+      reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer));
+  CHECK(v_src);
+
+  const int y_plane_length = width * height;
+  const int uv_plane_length = y_plane_length / 4;
+  const int buffer_length = y_plane_length + uv_plane_length * 2;
+  std::unique_ptr<uint8_t> buffer(new uint8_t[buffer_length]);
+
+  libyuv::Android420ToI420(y_src, y_stride, u_src, uv_row_stride, v_src,
+                           uv_row_stride, uv_pixel_stride, buffer.get(), width,
+                           buffer.get() + y_plane_length, width / 2,
+                           buffer.get() + y_plane_length + uv_plane_length,
+                           width / 2, width, height);
+
+  // Deliver the frame when it doesn't arrive too early.
+  if (expected_next_frame_time_ <= current_time) {
+    expected_next_frame_time_ += frame_interval_;
+
+    // TODO(qiangchen): Investigate how to get raw timestamp for Android,
+    // rather than using reference time to calculate timestamp.
+    client_->OnIncomingCapturedData(buffer.get(), buffer_length,
+                                    capture_format_, rotation, current_time,
+                                    current_time - first_ref_time_);
+  }
+}
+
 void VideoCaptureDeviceAndroid::OnError(JNIEnv* env,
                                         const JavaParamRef<jobject>& obj,
                                         const JavaParamRef<jstring>& message) {
@@ -259,10 +339,10 @@
     return;
   }
 
-  std::vector<uint8_t> native_data;
-  base::android::JavaByteArrayToByteVector(env, data.obj(), &native_data);
-
-  cb->Run(std::string(native_data.empty() ? "" : "image/jpeg"), native_data);
+  mojom::BlobPtr blob = mojom::Blob::New();
+  base::android::JavaByteArrayToByteVector(env, data.obj(), &blob->data);
+  blob->mime_type = blob->data.empty() ? "" : "image/jpeg";
+  cb->Run(std::move(blob));
 
   photo_callbacks_.erase(reference_it);
 }
diff --git a/media/capture/video/android/video_capture_device_android.h b/media/capture/video/android/video_capture_device_android.h
index ce6fd9d..8845c33e 100644
--- a/media/capture/video/android/video_capture_device_android.h
+++ b/media/capture/video/android/video_capture_device_android.h
@@ -68,6 +68,19 @@
                         jint length,
                         jint rotation);
 
+  // Implement org.chromium.media.VideoCapture.nativeOnI420FrameAvailable.
+  void OnI420FrameAvailable(JNIEnv* env,
+                            jobject obj,
+                            jobject y_buffer,
+                            jint y_stride,
+                            jobject u_buffer,
+                            jobject v_buffer,
+                            jint uv_row_stride,
+                            jint uv_pixel_stride,
+                            jint width,
+                            jint height,
+                            jint rotation);
+
   // Implement org.chromium.media.VideoCapture.nativeOnError.
   void OnError(JNIEnv* env,
                const base::android::JavaParamRef<jobject>& obj,
@@ -104,6 +117,8 @@
   base::Lock photo_callbacks_lock_;
   std::list<std::unique_ptr<TakePhotoCallback>> photo_callbacks_;
 
+  gfx::Size next_photo_resolution_;
+
   Name device_name_;
   VideoCaptureFormat capture_format_;
 
diff --git a/media/capture/video/fake_video_capture_device.cc b/media/capture/video/fake_video_capture_device.cc
index d163adf..698588f3 100644
--- a/media/capture/video/fake_video_capture_device.cc
+++ b/media/capture/video/fake_video_capture_device.cc
@@ -101,14 +101,15 @@
   DrawPacman(true /* use_argb */, buffer.get(), elapsed_time, fake_capture_rate,
              capture_format.frame_size, zoom);
 
-  std::vector<uint8_t> encoded_data;
+  mojom::BlobPtr blob = mojom::Blob::New();
   const bool result = gfx::PNGCodec::Encode(
       buffer.get(), gfx::PNGCodec::FORMAT_RGBA, capture_format.frame_size,
       capture_format.frame_size.width() * 4, true /* discard_transparency */,
-      std::vector<gfx::PNGCodec::Comment>(), &encoded_data);
+      std::vector<gfx::PNGCodec::Comment>(), &blob->data);
   DCHECK(result);
 
-  callback.Run("image/png", encoded_data);
+  blob->mime_type = "image/png";
+  callback.Run(std::move(blob));
 }
 
 FakeVideoCaptureDevice::FakeVideoCaptureDevice(BufferOwnership buffer_ownership,
@@ -181,6 +182,19 @@
     GetPhotoCapabilitiesCallback callback) {
   mojom::PhotoCapabilitiesPtr photo_capabilities =
       mojom::PhotoCapabilities::New();
+  photo_capabilities->iso = mojom::Range::New();
+  photo_capabilities->iso->current = 100;
+  photo_capabilities->iso->max = 100;
+  photo_capabilities->iso->min = 100;
+  photo_capabilities->height = mojom::Range::New();
+  photo_capabilities->height->current = capture_format_.frame_size.height();
+  photo_capabilities->height->max = 1080;
+  photo_capabilities->height->min = 240;
+  photo_capabilities->width = mojom::Range::New();
+  photo_capabilities->width->current = capture_format_.frame_size.width();
+  photo_capabilities->width->max = 1920;
+  photo_capabilities->width->min = 320;
+  photo_capabilities->focus_mode = mojom::FocusMode::UNAVAILABLE;
   photo_capabilities->zoom = mojom::Range::New();
   photo_capabilities->zoom->current = current_zoom_;
   photo_capabilities->zoom->max = kMaxZoom;
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc
index d884daf9..931c0f9 100644
--- a/media/capture/video/fake_video_capture_device_unittest.cc
+++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -151,22 +151,20 @@
                void(const base::Callback<void(bool)>&));
 
   // GMock doesn't support move-only arguments, so we use this forward method.
-  void DoOnPhotoTaken(const std::string& mime_type,
-                      const std::vector<uint8_t>& data) {
+  void DoOnPhotoTaken(mojom::BlobPtr blob) {
     // Only PNG images are supported right now.
-    EXPECT_STREQ("image/png", mime_type.c_str());
+    EXPECT_STREQ("image/png", blob->mime_type.c_str());
     // Not worth decoding the incoming data. Just check that the header is PNG.
     // http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
-    ASSERT_GT(data.size(), 4u);
-    EXPECT_EQ('P', data[1]);
-    EXPECT_EQ('N', data[2]);
-    EXPECT_EQ('G', data[3]);
+    ASSERT_GT(blob->data.size(), 4u);
+    EXPECT_EQ('P', blob->data[1]);
+    EXPECT_EQ('N', blob->data[2]);
+    EXPECT_EQ('G', blob->data[3]);
     OnCorrectPhotoTaken();
   }
   MOCK_METHOD0(OnCorrectPhotoTaken, void(void));
   MOCK_METHOD1(OnTakePhotoFailure,
-               void(const base::Callback<void(const std::string&,
-                                              const std::vector<uint8_t>&)>&));
+               void(const base::Callback<void(mojom::BlobPtr)>&));
 
  private:
   friend class base::RefCounted<ImageCaptureClient>;
@@ -320,6 +318,17 @@
 
   auto* capabilities = image_capture_client_->capabilities();
   ASSERT_TRUE(capabilities);
+  EXPECT_EQ(100u, capabilities->iso->min);
+  EXPECT_EQ(100u, capabilities->iso->max);
+  EXPECT_EQ(100u, capabilities->iso->current);
+  EXPECT_EQ(capture_params.requested_format.frame_size.height(),
+            static_cast<int>(capabilities->height->current));
+  EXPECT_EQ(240u, capabilities->height->min);
+  EXPECT_EQ(1080u, capabilities->height->max);
+  EXPECT_EQ(capture_params.requested_format.frame_size.width(),
+            static_cast<int>(capabilities->width->current));
+  EXPECT_EQ(320u, capabilities->width->min);
+  EXPECT_EQ(1920u, capabilities->width->max);
   EXPECT_EQ(100u, capabilities->zoom->min);
   EXPECT_EQ(400u, capabilities->zoom->max);
   EXPECT_GE(capabilities->zoom->current, capabilities->zoom->min);
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm
index 67128563..e11e646d 100644
--- a/media/capture/video/mac/video_capture_device_mac.mm
+++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -444,8 +444,10 @@
     return;
   }
 
-  photo_callback_->Run(
-      mime_type, std::vector<uint8_t>(image_data, image_data + image_length));
+  mojom::BlobPtr blob = mojom::Blob::New();
+  blob->data.assign(image_data, image_data + image_length);
+  blob->mime_type = mime_type;
+  photo_callback_->Run(std::move(blob));
   photo_callback_.reset();
 }
 
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h
index a1707d5..4671df63 100644
--- a/media/capture/video/video_capture_device.h
+++ b/media/capture/video/video_capture_device.h
@@ -325,8 +325,8 @@
   // Asynchronously takes a photo, possibly reconfiguring the capture objects
   // and/or interrupting the capture flow. Runs |callback| on the thread
   // where TakePhoto() is called, if the photo was successfully taken.
-  using TakePhotoCallback = ScopedResultCallback<
-      base::Callback<void(const std::string&, const std::vector<uint8_t>&)>>;
+  using TakePhotoCallback =
+      ScopedResultCallback<base::Callback<void(mojom::BlobPtr blob)>>;
   virtual void TakePhoto(TakePhotoCallback callback);
 
   // Gets the power line frequency, either from the params if specified by the
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index b1b46445..991e9a5f 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -145,22 +145,20 @@
 class MockImageCaptureClient : public base::RefCounted<MockImageCaptureClient> {
  public:
   // GMock doesn't support move-only arguments, so we use this forward method.
-  void DoOnPhotoTaken(const std::string& mime_type,
-                      const std::vector<uint8_t>& data) {
-    EXPECT_STREQ("image/jpeg", mime_type.c_str());
-    ASSERT_GT(data.size(), 4u);
+  void DoOnPhotoTaken(mojom::BlobPtr blob) {
+    EXPECT_STREQ("image/jpeg", blob->mime_type.c_str());
+    ASSERT_GT(blob->data.size(), 4u);
     // Check some bytes that univocally identify |data| as a JPEG File.
     // https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure
-    EXPECT_EQ(0xFF, data[0]);  // First SOI byte
-    EXPECT_EQ(0xD8, data[1]);  // Second SOI byte
-    EXPECT_EQ(0xFF, data[2]);  // First JFIF-APP0 byte
-    EXPECT_EQ(0xE0, data[3]);  // Second JFIF-APP0 byte
+    EXPECT_EQ(0xFF, blob->data[0]);  // First SOI byte
+    EXPECT_EQ(0xD8, blob->data[1]);  // Second SOI byte
+    EXPECT_EQ(0xFF, blob->data[2]);  // First JFIF-APP0 byte
+    EXPECT_EQ(0xE0, blob->data[3]);  // Second JFIF-APP0 byte
     OnCorrectPhotoTaken();
   }
   MOCK_METHOD0(OnCorrectPhotoTaken, void(void));
   MOCK_METHOD1(OnTakePhotoFailure,
-               void(const base::Callback<void(const std::string&,
-                                              const std::vector<uint8_t>&)>&));
+               void(const base::Callback<void(mojom::BlobPtr)>&));
 
  private:
   friend class base::RefCounted<MockImageCaptureClient>;
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 57ec14a..e8c2644 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -337,6 +337,8 @@
       "dxva_picture_buffer_win.h",
       "dxva_video_decode_accelerator_win.cc",
       "dxva_video_decode_accelerator_win.h",
+      "media_foundation_video_encode_accelerator_win.cc",
+      "media_foundation_video_encode_accelerator_win.h",
     ]
     configs += [
       # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
@@ -344,7 +346,10 @@
       "//third_party/khronos:khronos_headers",
     ]
     public_deps += [ "//media/base/win" ]
-    deps += [ "//third_party/angle:includes" ]
+    deps += [
+      "//third_party/angle:includes",
+      "//third_party/libyuv",
+    ]
     libs += [
       "d3d9.lib",
       "d3d11.lib",
@@ -434,7 +439,7 @@
   }
 }
 
-if (is_chromeos || is_mac) {
+if (is_chromeos || is_mac || is_win) {
   test("video_encode_accelerator_unittest") {
     deps = [
       "//base",
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc
index ce43d87..8f3f257 100644
--- a/media/gpu/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/dxva_video_decode_accelerator_win.cc
@@ -39,6 +39,7 @@
 #include "build/build_config.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
+#include "media/base/win/mf_helpers.h"
 #include "media/base/win/mf_initializer.h"
 #include "media/gpu/dxva_picture_buffer_win.h"
 #include "media/video/video_decode_accelerator.h"
@@ -187,42 +188,6 @@
     0x102, 0x106, 0x116, 0x126,
 };
 
-// Provides scoped access to the underlying buffer in an IMFMediaBuffer
-// instance.
-class MediaBufferScopedPointer {
- public:
-  explicit MediaBufferScopedPointer(IMFMediaBuffer* media_buffer)
-      : media_buffer_(media_buffer),
-        buffer_(nullptr),
-        max_length_(0),
-        current_length_(0) {
-    HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, &current_length_);
-    CHECK(SUCCEEDED(hr));
-  }
-
-  ~MediaBufferScopedPointer() {
-    HRESULT hr = media_buffer_->Unlock();
-    CHECK(SUCCEEDED(hr));
-  }
-
-  uint8_t* get() { return buffer_; }
-
-  DWORD current_length() const { return current_length_; }
-
- private:
-  base::win::ScopedComPtr<IMFMediaBuffer> media_buffer_;
-  uint8_t* buffer_;
-  DWORD max_length_;
-  DWORD current_length_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer);
-};
-
-void LogDXVAError(int line) {
-  LOG(ERROR) << "Error in dxva_video_decode_accelerator_win.cc on line "
-             << line;
-}
-
 }  // namespace
 
 namespace media {
@@ -235,34 +200,6 @@
 CreateDXGIDeviceManager
     DXVAVideoDecodeAccelerator::create_dxgi_device_manager_ = NULL;
 
-#define RETURN_ON_FAILURE(result, log, ret) \
-  do {                                      \
-    if (!(result)) {                        \
-      DLOG(ERROR) << log;                   \
-      LogDXVAError(__LINE__);               \
-      return ret;                           \
-    }                                       \
-  } while (0)
-
-#define RETURN_ON_HR_FAILURE(result, log, ret) \
-  RETURN_ON_FAILURE(SUCCEEDED(result),         \
-                    log << ", HRESULT: 0x" << std::hex << result, ret);
-
-#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
-  do {                                                             \
-    if (!(result)) {                                               \
-      DVLOG(1) << log;                                             \
-      LogDXVAError(__LINE__);                                      \
-      StopOnError(error_code);                                     \
-      return ret;                                                  \
-    }                                                              \
-  } while (0)
-
-#define RETURN_AND_NOTIFY_ON_HR_FAILURE(result, log, error_code, ret)        \
-  RETURN_AND_NOTIFY_ON_FAILURE(SUCCEEDED(result),                            \
-                               log << ", HRESULT: 0x" << std::hex << result, \
-                               error_code, ret);
-
 enum {
   // Maximum number of iterations we allow before aborting the attempt to flush
   // the batched queries to the driver and allow torn/corrupt frames to be
@@ -282,41 +219,6 @@
   kAcquireSyncWaitMs = 0,
 };
 
-static IMFSample* CreateEmptySample() {
-  base::win::ScopedComPtr<IMFSample> sample;
-  HRESULT hr = MFCreateSample(sample.Receive());
-  RETURN_ON_HR_FAILURE(hr, "MFCreateSample failed", NULL);
-  return sample.Detach();
-}
-
-// Creates a Media Foundation sample with one buffer of length |buffer_length|
-// on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0.
-static IMFSample* CreateEmptySampleWithBuffer(uint32_t buffer_length,
-                                              int align) {
-  CHECK_GT(buffer_length, 0U);
-
-  base::win::ScopedComPtr<IMFSample> sample;
-  sample.Attach(CreateEmptySample());
-
-  base::win::ScopedComPtr<IMFMediaBuffer> buffer;
-  HRESULT hr = E_FAIL;
-  if (align == 0) {
-    // Note that MFCreateMemoryBuffer is same as MFCreateAlignedMemoryBuffer
-    // with the align argument being 0.
-    hr = MFCreateMemoryBuffer(buffer_length, buffer.Receive());
-  } else {
-    hr =
-        MFCreateAlignedMemoryBuffer(buffer_length, align - 1, buffer.Receive());
-  }
-  RETURN_ON_HR_FAILURE(hr, "Failed to create memory buffer for sample", NULL);
-
-  hr = sample->AddBuffer(buffer.get());
-  RETURN_ON_HR_FAILURE(hr, "Failed to add buffer to sample", NULL);
-
-  buffer->SetCurrentLength(0);
-  return sample.Detach();
-}
-
 // Creates a Media Foundation sample with one buffer containing a copy of the
 // given Annex B stream data.
 // If duration and sample time are not known, provide 0.
@@ -330,7 +232,7 @@
   CHECK_GT(size, 0U);
   base::win::ScopedComPtr<IMFSample> sample;
   sample.Attach(
-      CreateEmptySampleWithBuffer(std::max(min_size, size), alignment));
+      mf::CreateEmptySampleWithBuffer(std::max(min_size, size), alignment));
   RETURN_ON_FAILURE(sample.get(), "Failed to create empty sample", NULL);
 
   base::win::ScopedComPtr<IMFMediaBuffer> buffer;
@@ -2751,7 +2653,7 @@
   HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive());
   RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr);
 
-  MediaBufferScopedPointer scoped_media_buffer(buffer.get());
+  mf::MediaBufferScopedPointer scoped_media_buffer(buffer.get());
 
   if (!config_change_detector_->DetectConfig(
           scoped_media_buffer.get(), scoped_media_buffer.current_length())) {
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
index dc4e515..4c48a9f 100644
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
+++ b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
@@ -35,6 +35,9 @@
 #include "media/gpu/android_video_encode_accelerator.h"
 #elif defined(OS_MACOSX)
 #include "media/gpu/vt_video_encode_accelerator_mac.h"
+#elif defined(OS_WIN)
+#include "media/base/media_switches.h"
+#include "media/gpu/media_foundation_video_encode_accelerator_win.h"
 #endif
 
 namespace media {
@@ -208,6 +211,13 @@
 #if defined(OS_MACOSX)
   create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateVTVEA);
 #endif
+#if defined(OS_WIN)
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableMFH264Encoding)) {
+    create_vea_fps.push_back(
+        &GpuVideoEncodeAccelerator::CreateMediaFoundationVEA);
+  }
+#endif
   return create_vea_fps;
 }
 
@@ -250,6 +260,15 @@
 }
 #endif
 
+#if defined(OS_WIN)
+// static
+std::unique_ptr<media::VideoEncodeAccelerator>
+GpuVideoEncodeAccelerator::CreateMediaFoundationVEA() {
+  return base::WrapUnique<media::VideoEncodeAccelerator>(
+      new MediaFoundationVideoEncodeAccelerator());
+}
+#endif
+
 void GpuVideoEncodeAccelerator::OnEncode(
     const AcceleratedVideoEncoderMsg_Encode_Params& params) {
   DVLOG(3) << "GpuVideoEncodeAccelerator::OnEncode: frame_id = "
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.h b/media/gpu/ipc/service/gpu_video_encode_accelerator.h
index 9b86c08d..c928d6e9 100644
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.h
+++ b/media/gpu/ipc/service/gpu_video_encode_accelerator.h
@@ -92,6 +92,10 @@
 #if defined(OS_MACOSX)
   static std::unique_ptr<VideoEncodeAccelerator> CreateVTVEA();
 #endif
+#if defined(OS_WIN)
+  static std::unique_ptr<media::VideoEncodeAccelerator>
+  CreateMediaFoundationVEA();
+#endif
 
   // IPC handlers, proxying VideoEncodeAccelerator for the renderer
   // process.
diff --git a/media/gpu/media_foundation_video_encode_accelerator_win.cc b/media/gpu/media_foundation_video_encode_accelerator_win.cc
new file mode 100644
index 0000000..bd15bb20
--- /dev/null
+++ b/media/gpu/media_foundation_video_encode_accelerator_win.cc
@@ -0,0 +1,562 @@
+// Copyright 2016 The Chromium Authors. 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/gpu/media_foundation_video_encode_accelerator_win.h"
+
+#pragma warning(push)
+#pragma warning(disable : 4800)  // Disable warning for added padding.
+
+#include <codecapi.h>
+#include <mferror.h>
+#include <mftransform.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/win/scoped_co_mem.h"
+#include "base/win/scoped_variant.h"
+#include "base/win/windows_version.h"
+#include "media/base/win/mf_helpers.h"
+#include "media/base/win/mf_initializer.h"
+#include "third_party/libyuv/include/libyuv.h"
+
+using base::win::ScopedComPtr;
+using media::mf::MediaBufferScopedPointer;
+
+namespace media {
+
+namespace {
+
+const size_t kMaxFrameRateNumerator = 30;
+const size_t kMaxFrameRateDenominator = 1;
+const size_t kMaxResolutionWidth = 4096;
+const size_t kMaxResolutionHeight = 2160;
+const size_t kNumInputBuffers = 3;
+const size_t kOneSecondInMicroseconds = 1000000;
+const size_t kOutputSampleBufferSizeRatio = 4;
+
+constexpr const wchar_t* const kMediaFoundationVideoEncoderDLLs[] = {
+    L"mf.dll", L"mfplat.dll",
+};
+
+}  // namespace
+
+class MediaFoundationVideoEncodeAccelerator::EncodeOutput {
+ public:
+  EncodeOutput(uint32_t size, bool key_frame, base::TimeDelta timestamp)
+      : keyframe(key_frame), capture_timestamp(timestamp), data_(size) {}
+
+  uint8_t* memory() { return data_.data(); }
+
+  int size() const { return static_cast<int>(data_.size()); }
+
+  const bool keyframe;
+  const base::TimeDelta capture_timestamp;
+
+ private:
+  std::vector<uint8_t> data_;
+
+  DISALLOW_COPY_AND_ASSIGN(EncodeOutput);
+};
+
+struct MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef {
+  BitstreamBufferRef(int32_t id,
+                     std::unique_ptr<base::SharedMemory> shm,
+                     size_t size)
+      : id(id), shm(std::move(shm)), size(size) {}
+  const int32_t id;
+  const std::unique_ptr<base::SharedMemory> shm;
+  const size_t size;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef);
+};
+
+MediaFoundationVideoEncodeAccelerator::MediaFoundationVideoEncodeAccelerator()
+    : client_task_runner_(base::SequencedTaskRunnerHandle::Get()),
+      encoder_thread_("MFEncoderThread"),
+      encoder_task_weak_factory_(this) {}
+
+MediaFoundationVideoEncodeAccelerator::
+    ~MediaFoundationVideoEncodeAccelerator() {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  DCHECK(!encoder_thread_.IsRunning());
+  DCHECK(!encoder_task_weak_factory_.HasWeakPtrs());
+}
+
+VideoEncodeAccelerator::SupportedProfiles
+MediaFoundationVideoEncodeAccelerator::GetSupportedProfiles() {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  SupportedProfiles profiles;
+  if (base::win::GetVersion() < base::win::VERSION_WIN8) {
+    DLOG(ERROR) << "Windows versions earlier than 8 are not supported.";
+    return profiles;
+  }
+
+  SupportedProfile profile;
+  // More profiles can be supported here, but they should be available in SW
+  // fallback as well.
+  profile.profile = H264PROFILE_BASELINE;
+  profile.max_framerate_numerator = kMaxFrameRateNumerator;
+  profile.max_framerate_denominator = kMaxFrameRateDenominator;
+  profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight);
+  profiles.push_back(profile);
+  return profiles;
+}
+
+bool MediaFoundationVideoEncodeAccelerator::Initialize(
+    VideoPixelFormat format,
+    const gfx::Size& input_visible_size,
+    VideoCodecProfile output_profile,
+    uint32_t initial_bitrate,
+    Client* client) {
+  DVLOG(3) << __FUNCTION__
+           << ": input_format=" << VideoPixelFormatToString(format)
+           << ", input_visible_size=" << input_visible_size.ToString()
+           << ", output_profile=" << output_profile
+           << ", initial_bitrate=" << initial_bitrate;
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  if (PIXEL_FORMAT_I420 != format) {
+    DLOG(ERROR) << "Input format not supported= "
+                << VideoPixelFormatToString(format);
+    return false;
+  }
+
+  if (H264PROFILE_BASELINE != output_profile) {
+    DLOG(ERROR) << "Output profile not supported= " << output_profile;
+    return false;
+  }
+
+  for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs) {
+    if (!::GetModuleHandle(mfdll)) {
+      DLOG(ERROR) << mfdll << " is required for encoding";
+      return false;
+    }
+  }
+
+  encoder_thread_.init_com_with_mta(false);
+  if (!encoder_thread_.Start()) {
+    DLOG(ERROR) << "Failed spawning encoder thread.";
+    return false;
+  }
+  encoder_thread_task_runner_ = encoder_thread_.task_runner();
+
+  InitializeMediaFoundation();
+
+  uint32_t flags = MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER;
+  MFT_REGISTER_TYPE_INFO input_info;
+  input_info.guidMajorType = MFMediaType_Video;
+  input_info.guidSubtype = MFVideoFormat_NV12;
+  MFT_REGISTER_TYPE_INFO output_info;
+  output_info.guidMajorType = MFMediaType_Video;
+  output_info.guidSubtype = MFVideoFormat_H264;
+
+  base::win::ScopedCoMem<CLSID> CLSIDs;
+  uint32_t count = 0;
+  HRESULT hr = MFTEnum(MFT_CATEGORY_VIDEO_ENCODER, flags, NULL, &output_info,
+                       NULL, &CLSIDs, &count);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't enumerate hardware encoder", false);
+  RETURN_ON_FAILURE((count > 0), "No HW encoder found", false);
+  DVLOG(3) << "HW encoder(s) found: " << count;
+  hr = encoder_.CreateInstance(CLSIDs[0]);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't activate hardware encoder", false);
+
+  client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
+  client_ = client_ptr_factory_->GetWeakPtr();
+  input_visible_size_ = input_visible_size;
+  frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator;
+  target_bitrate_ = initial_bitrate;
+  bitstream_buffer_size_ = input_visible_size.GetArea();
+
+  u_plane_offset_ =
+      VideoFrame::PlaneSize(PIXEL_FORMAT_I420, VideoFrame::kYPlane,
+                            input_visible_size_)
+          .GetArea();
+  v_plane_offset_ =
+      u_plane_offset_ +
+      VideoFrame::PlaneSize(PIXEL_FORMAT_I420, VideoFrame::kUPlane,
+                            input_visible_size_)
+          .GetArea();
+
+  if (!InitializeInputOutputSamples()) {
+    DLOG(ERROR) << "Failed initializing input-output samples.";
+    return false;
+  }
+
+  if (!SetEncoderModes()) {
+    DLOG(ERROR) << "Failed setting encoder parameters.";
+    return false;
+  }
+
+  hr = encoder_->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set ProcessMessage", false);
+
+  client_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers,
+                 input_visible_size_, bitstream_buffer_size_));
+  return SUCCEEDED(hr);
+}
+
+void MediaFoundationVideoEncodeAccelerator::Encode(
+    const scoped_refptr<VideoFrame>& frame,
+    bool force_keyframe) {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  encoder_thread_task_runner_->PostTask(
+      FROM_HERE, base::Bind(&MediaFoundationVideoEncodeAccelerator::EncodeTask,
+                            encoder_task_weak_factory_.GetWeakPtr(), frame,
+                            force_keyframe));
+}
+
+void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBuffer(
+    const BitstreamBuffer& buffer) {
+  DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size();
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  if (buffer.size() < bitstream_buffer_size_) {
+    DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size()
+                << " vs. " << bitstream_buffer_size_;
+    client_->NotifyError(kInvalidArgumentError);
+    return;
+  }
+
+  std::unique_ptr<base::SharedMemory> shm(
+      new base::SharedMemory(buffer.handle(), false));
+  if (!shm->Map(buffer.size())) {
+    DLOG(ERROR) << "Failed mapping shared memory.";
+    client_->NotifyError(kPlatformFailureError);
+    return;
+  }
+
+  std::unique_ptr<BitstreamBufferRef> buffer_ref(
+      new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size()));
+  encoder_thread_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(
+          &MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask,
+          encoder_task_weak_factory_.GetWeakPtr(), base::Passed(&buffer_ref)));
+}
+
+void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange(
+    uint32_t bitrate,
+    uint32_t framerate) {
+  DVLOG(3) << __FUNCTION__ << ": bitrate=" << bitrate
+           << ": framerate=" << framerate;
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  encoder_thread_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&MediaFoundationVideoEncodeAccelerator::
+                     RequestEncodingParametersChangeTask,
+                 encoder_task_weak_factory_.GetWeakPtr(), bitrate, framerate));
+}
+
+void MediaFoundationVideoEncodeAccelerator::Destroy() {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  // Cancel all callbacks.
+  client_ptr_factory_.reset();
+
+  if (encoder_thread_.IsRunning()) {
+    encoder_thread_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&MediaFoundationVideoEncodeAccelerator::DestroyTask,
+                   encoder_task_weak_factory_.GetWeakPtr()));
+    encoder_thread_.Stop();
+  }
+
+  delete this;
+}
+
+// static
+void MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization() {
+  for (const wchar_t* mfdll : kMediaFoundationVideoEncoderDLLs)
+    ::LoadLibrary(mfdll);
+}
+
+bool MediaFoundationVideoEncodeAccelerator::InitializeInputOutputSamples() {
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  HRESULT hr = encoder_->GetStreamLimits(
+      &input_stream_count_min_, &input_stream_count_max_,
+      &output_stream_count_min_, &output_stream_count_max_);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't query stream limits", false);
+  DVLOG(3) << "Stream limits: " << input_stream_count_min_ << ","
+           << input_stream_count_max_ << "," << output_stream_count_min_ << ","
+           << output_stream_count_max_;
+
+  // Initialize output parameters.
+  base::win::ScopedComPtr<IMFMediaType> imf_output_media_type;
+  hr = MFCreateMediaType(imf_output_media_type.Receive());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false);
+  hr = imf_output_media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false);
+  hr = imf_output_media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false);
+  hr = imf_output_media_type->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false);
+  hr = MFSetAttributeRatio(imf_output_media_type.get(), MF_MT_FRAME_RATE,
+                           frame_rate_, kMaxFrameRateDenominator);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false);
+  hr = MFSetAttributeSize(imf_output_media_type.get(), MF_MT_FRAME_SIZE,
+                          input_visible_size_.width(),
+                          input_visible_size_.height());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false);
+  hr = imf_output_media_type->SetUINT32(MF_MT_INTERLACE_MODE,
+                                        MFVideoInterlace_Progressive);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false);
+  hr = imf_output_media_type->SetUINT32(MF_MT_MPEG2_PROFILE,
+                                        eAVEncH264VProfile_Base);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set codec profile", false);
+  hr = encoder_->SetOutputType(0, imf_output_media_type.get(), 0);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set output media type", false);
+
+  // Initialize input parameters.
+  base::win::ScopedComPtr<IMFMediaType> imf_input_media_type;
+  hr = MFCreateMediaType(imf_input_media_type.Receive());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't create media type", false);
+  hr = imf_input_media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set media type", false);
+  hr = imf_input_media_type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YV12);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set video format", false);
+  hr = MFSetAttributeRatio(imf_input_media_type.get(), MF_MT_FRAME_RATE,
+                           frame_rate_, kMaxFrameRateDenominator);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set frame rate", false);
+  hr = MFSetAttributeSize(imf_input_media_type.get(), MF_MT_FRAME_SIZE,
+                          input_visible_size_.width(),
+                          input_visible_size_.height());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set frame size", false);
+  hr = imf_input_media_type->SetUINT32(MF_MT_INTERLACE_MODE,
+                                       MFVideoInterlace_Progressive);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set interlace mode", false);
+  hr = encoder_->SetInputType(0, imf_input_media_type.get(), 0);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set input media type", false);
+
+  input_sample_.Attach(mf::CreateEmptySampleWithBuffer(
+      VideoFrame::AllocationSize(PIXEL_FORMAT_I420, input_visible_size_), 2));
+  output_sample_.Attach(mf::CreateEmptySampleWithBuffer(
+      bitstream_buffer_size_ * kOutputSampleBufferSizeRatio, 2));
+
+  return SUCCEEDED(hr);
+}
+
+bool MediaFoundationVideoEncodeAccelerator::SetEncoderModes() {
+  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+  HRESULT hr = encoder_.QueryInterface(IID_ICodecAPI, codec_api_.ReceiveVoid());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't get ICodecAPI", false);
+  VARIANT var;
+  var.vt = VT_UI4;
+  var.ulVal = eAVEncCommonRateControlMode_CBR;
+  hr = codec_api_->SetValue(&CODECAPI_AVEncCommonRateControlMode, &var);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set CommonRateControlMode", false);
+  var.ulVal = target_bitrate_;
+  hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", false);
+  var.ulVal = eAVEncAdaptiveMode_FrameRate;
+  hr = codec_api_->SetValue(&CODECAPI_AVEncAdaptiveMode, &var);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set FrameRate", false);
+  var.vt = VT_BOOL;
+  var.boolVal = VARIANT_TRUE;
+  hr = codec_api_->SetValue(&CODECAPI_AVLowLatencyMode, &var);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set LowLatencyMode", false);
+  return SUCCEEDED(hr);
+}
+
+void MediaFoundationVideoEncodeAccelerator::NotifyError(
+    VideoEncodeAccelerator::Error error) {
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+  client_task_runner_->PostTask(
+      FROM_HERE, base::Bind(&Client::NotifyError, client_, error));
+}
+
+void MediaFoundationVideoEncodeAccelerator::EncodeTask(
+    const scoped_refptr<VideoFrame>& frame,
+    bool force_keyframe) {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  base::win::ScopedComPtr<IMFMediaBuffer> input_buffer;
+  input_sample_->GetBufferByIndex(0, input_buffer.Receive());
+
+  {
+    MediaBufferScopedPointer scoped_buffer(input_buffer.get());
+    DCHECK(scoped_buffer.get());
+    libyuv::I420Copy(frame->visible_data(VideoFrame::kYPlane),
+                     frame->stride(VideoFrame::kYPlane),
+                     frame->visible_data(VideoFrame::kVPlane),
+                     frame->stride(VideoFrame::kVPlane),
+                     frame->visible_data(VideoFrame::kUPlane),
+                     frame->stride(VideoFrame::kUPlane), scoped_buffer.get(),
+                     frame->stride(VideoFrame::kYPlane),
+                     scoped_buffer.get() + u_plane_offset_,
+                     frame->stride(VideoFrame::kUPlane),
+                     scoped_buffer.get() + v_plane_offset_,
+                     frame->stride(VideoFrame::kVPlane),
+                     input_visible_size_.width(), input_visible_size_.height());
+  }
+
+  input_sample_->SetSampleTime(frame->timestamp().InMicroseconds() * 10);
+  input_sample_->SetSampleDuration(kOneSecondInMicroseconds / frame_rate_);
+  HRESULT hr = encoder_->ProcessInput(0, input_sample_.get(), 0);
+  // According to MSDN, if encoder returns MF_E_NOTACCEPTING, we need to try
+  // processing the output. This error indicates that encoder does not accept
+  // any more input data.
+  if (hr == MF_E_NOTACCEPTING) {
+    DVLOG(3) << "MF_E_NOTACCEPTING";
+    ProcessOutput();
+    hr = encoder_->ProcessInput(0, input_sample_.get(), 0);
+    if (!SUCCEEDED(hr)) {
+      NotifyError(kPlatformFailureError);
+      RETURN_ON_HR_FAILURE(hr, "Couldn't encode", );
+    }
+  } else if (!SUCCEEDED(hr)) {
+    NotifyError(kPlatformFailureError);
+    RETURN_ON_HR_FAILURE(hr, "Couldn't encode", );
+  }
+  DVLOG(3) << "Sent for encode " << hr;
+
+  ProcessOutput();
+}
+
+void MediaFoundationVideoEncodeAccelerator::ProcessOutput() {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0};
+  output_data_buffer.dwStreamID = 0;
+  output_data_buffer.dwStatus = 0;
+  output_data_buffer.pEvents = NULL;
+  output_data_buffer.pSample = output_sample_.get();
+  DWORD status = 0;
+  HRESULT hr = encoder_->ProcessOutput(0, 1, &output_data_buffer, &status);
+  if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
+    DVLOG(3) << "MF_E_TRANSFORM_NEED_MORE_INPUT";
+    return;
+  }
+  RETURN_ON_HR_FAILURE(hr, "Couldn't get encoded data", );
+  DVLOG(3) << "Got encoded data " << hr;
+
+  base::win::ScopedComPtr<IMFMediaBuffer> output_buffer;
+  hr = output_sample_->GetBufferByIndex(0, output_buffer.Receive());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't get buffer by index", );
+  DWORD size = 0;
+  hr = output_buffer->GetCurrentLength(&size);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't get buffer length", );
+
+  const bool keyframe = MFGetAttributeUINT32(
+      output_sample_.get(), MFSampleExtension_CleanPoint, false);
+  DVLOG(3) << "We HAVE encoded data with size:" << size << " keyframe "
+           << keyframe;
+
+  if (bitstream_buffer_queue_.empty()) {
+    DVLOG(3) << "No bitstream buffers.";
+    // We need to copy the output so that encoding can continue.
+    std::unique_ptr<EncodeOutput> encode_output(
+        new EncodeOutput(size, keyframe, base::Time::Now() - base::Time()));
+    {
+      MediaBufferScopedPointer scoped_buffer(output_buffer.get());
+      memcpy(encode_output->memory(), scoped_buffer.get(), size);
+    }
+    encoder_output_queue_.push_back(std::move(encode_output));
+    return;
+  }
+
+  std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef>
+      buffer_ref = std::move(bitstream_buffer_queue_.front());
+  bitstream_buffer_queue_.pop_front();
+
+  {
+    MediaBufferScopedPointer scoped_buffer(output_buffer.get());
+    memcpy(buffer_ref->shm->memory(), scoped_buffer.get(), size);
+  }
+
+  client_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, size,
+                 keyframe, base::Time::Now() - base::Time()));
+
+  // Keep calling ProcessOutput recursively until MF_E_TRANSFORM_NEED_MORE_INPUT
+  // is returned to flush out all the output.
+  ProcessOutput();
+}
+
+void MediaFoundationVideoEncodeAccelerator::UseOutputBitstreamBufferTask(
+    std::unique_ptr<BitstreamBufferRef> buffer_ref) {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  // If there is already EncodeOutput waiting, copy its output first.
+  if (!encoder_output_queue_.empty()) {
+    std::unique_ptr<MediaFoundationVideoEncodeAccelerator::EncodeOutput>
+        encode_output = std::move(encoder_output_queue_.front());
+    encoder_output_queue_.pop_front();
+    ReturnBitstreamBuffer(std::move(encode_output), std::move(buffer_ref));
+    return;
+  }
+
+  bitstream_buffer_queue_.push_back(std::move(buffer_ref));
+}
+
+void MediaFoundationVideoEncodeAccelerator::ReturnBitstreamBuffer(
+    std::unique_ptr<EncodeOutput> encode_output,
+    std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef>
+        buffer_ref) {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  memcpy(buffer_ref->shm->memory(), encode_output->memory(),
+         encode_output->size());
+  client_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id,
+                 encode_output->size(), encode_output->keyframe,
+                 encode_output->capture_timestamp));
+}
+
+void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
+    uint32_t bitrate,
+    uint32_t framerate) {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  frame_rate_ = framerate ? framerate : 1;
+  target_bitrate_ = bitrate ? bitrate : 1;
+
+  VARIANT var;
+  var.vt = VT_UI4;
+  var.ulVal = target_bitrate_;
+  HRESULT hr = codec_api_->SetValue(&CODECAPI_AVEncCommonMeanBitRate, &var);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", );
+
+  base::win::ScopedComPtr<IMFMediaType> imf_output_media_type;
+  hr = MFCreateMediaType(imf_output_media_type.Receive());
+  RETURN_ON_HR_FAILURE(hr, "Couldn't create output media type", );
+  hr = imf_output_media_type->SetUINT32(MF_MT_AVG_BITRATE, target_bitrate_);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set bitrate", );
+  hr = MFSetAttributeRatio(imf_output_media_type.get(), MF_MT_FRAME_RATE,
+                           frame_rate_, kMaxFrameRateDenominator);
+  RETURN_ON_HR_FAILURE(hr, "Couldn't set output type params", );
+}
+
+void MediaFoundationVideoEncodeAccelerator::DestroyTask() {
+  DVLOG(3) << __FUNCTION__;
+  DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+  // Cancel all encoder thread callbacks.
+  encoder_task_weak_factory_.InvalidateWeakPtrs();
+
+  encoder_.Release();
+}
+
+}  // namespace content
diff --git a/media/gpu/media_foundation_video_encode_accelerator_win.h b/media/gpu/media_foundation_video_encode_accelerator_win.h
new file mode 100644
index 0000000..f6b9a0d
--- /dev/null
+++ b/media/gpu/media_foundation_video_encode_accelerator_win.h
@@ -0,0 +1,147 @@
+// Copyright 2016 The Chromium Authors. 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_GPU_MEDIA_FOUNDATION_VIDEO_ENCODE_ACCELERATOR_WIN_H_
+#define MEDIA_GPU_MEDIA_FOUNDATION_VIDEO_ENCODE_ACCELERATOR_WIN_H_
+
+#include <mfapi.h>
+#include <mfidl.h>
+#include <stdint.h>
+#include <strmif.h>
+
+#include <deque>
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
+#include "base/win/scoped_comptr.h"
+#include "media/gpu/media_gpu_export.h"
+#include "media/video/video_encode_accelerator.h"
+
+namespace media {
+
+// Media Foundation implementation of the VideoEncodeAccelerator interface for
+// Windows.
+// This class saves the task runner on which it is constructed and returns
+// encoded data to the client using that same task runner. This class has
+// DCHECKs to makes sure that methods are called in sequence. It starts an
+// internal encoder thread on which VideoEncodeAccelerator implementation tasks
+// are posted.
+class MEDIA_GPU_EXPORT MediaFoundationVideoEncodeAccelerator
+    : public VideoEncodeAccelerator {
+ public:
+  MediaFoundationVideoEncodeAccelerator();
+
+  // VideoEncodeAccelerator implementation.
+  VideoEncodeAccelerator::SupportedProfiles GetSupportedProfiles() override;
+  bool Initialize(VideoPixelFormat input_format,
+                  const gfx::Size& input_visible_size,
+                  VideoCodecProfile output_profile,
+                  uint32_t initial_bitrate,
+                  Client* client) override;
+  void Encode(const scoped_refptr<VideoFrame>& frame,
+              bool force_keyframe) override;
+  void UseOutputBitstreamBuffer(const BitstreamBuffer& buffer) override;
+  void RequestEncodingParametersChange(uint32_t bitrate,
+                                       uint32_t framerate) override;
+  void Destroy() override;
+
+  // Preload dlls required for encoding.
+  static void PreSandboxInitialization();
+
+ protected:
+  ~MediaFoundationVideoEncodeAccelerator() override;
+
+ private:
+  // Holds output buffers coming from the client ready to be filled.
+  struct BitstreamBufferRef;
+
+  // Holds output buffers coming from the encoder.
+  class EncodeOutput;
+
+  // Initializes and allocates memory for input and output samples.
+  bool InitializeInputOutputSamples();
+
+  // Initializes encoder parameters for real-time use.
+  bool SetEncoderModes();
+
+  // Helper function to notify the client of an error on |client_task_runner_|.
+  void NotifyError(VideoEncodeAccelerator::Error error);
+
+  // Encoding tasks to be run on |encoder_thread_|.
+  void EncodeTask(const scoped_refptr<VideoFrame>& frame, bool force_keyframe);
+
+  // Checks for and copies encoded output on |encoder_thread_|.
+  void ProcessOutput();
+
+  // Inserts the output buffers for reuse on |encoder_thread_|.
+  void UseOutputBitstreamBufferTask(
+      std::unique_ptr<BitstreamBufferRef> buffer_ref);
+
+  // Copies EncodeOutput into a BitstreamBuffer and returns it to the |client_|.
+  void ReturnBitstreamBuffer(
+      std::unique_ptr<EncodeOutput> encode_output,
+      std::unique_ptr<MediaFoundationVideoEncodeAccelerator::BitstreamBufferRef>
+          buffer_ref);
+
+  // Changes encode parameters on |encoder_thread_|.
+  void RequestEncodingParametersChangeTask(uint32_t bitrate,
+                                           uint32_t framerate);
+
+  // Destroys encode session on |encoder_thread_|.
+  void DestroyTask();
+
+  // Bitstream buffers ready to be used to return encoded output as a FIFO.
+  std::deque<std::unique_ptr<BitstreamBufferRef>> bitstream_buffer_queue_;
+
+  // EncodeOutput needs to be copied into a BitstreamBufferRef as a FIFO.
+  std::deque<std::unique_ptr<EncodeOutput>> encoder_output_queue_;
+
+  gfx::Size input_visible_size_;
+  size_t bitstream_buffer_size_;
+  int32_t frame_rate_;
+  int32_t target_bitrate_;
+  size_t u_plane_offset_;
+  size_t v_plane_offset_;
+
+  base::win::ScopedComPtr<IMFTransform> encoder_;
+  base::win::ScopedComPtr<ICodecAPI> codec_api_;
+
+  DWORD input_stream_count_min_;
+  DWORD input_stream_count_max_;
+  DWORD output_stream_count_min_;
+  DWORD output_stream_count_max_;
+
+  base::win::ScopedComPtr<IMFSample> input_sample_;
+  base::win::ScopedComPtr<IMFSample> output_sample_;
+
+  // To expose client callbacks from VideoEncodeAccelerator.
+  // NOTE: all calls to this object *MUST* be executed on |client_task_runner_|.
+  base::WeakPtr<Client> client_;
+  std::unique_ptr<base::WeakPtrFactory<Client>> client_ptr_factory_;
+
+  // Our original calling task runner for the child thread.
+  const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
+  // Sequence checker to enforce that the methods of this object are called in
+  // sequence.
+  base::SequenceChecker sequence_checker_;
+
+  // This thread services tasks posted from the VEA API entry points by the
+  // GPU child thread and CompressionCallback() posted from device thread.
+  base::Thread encoder_thread_;
+  scoped_refptr<base::SingleThreadTaskRunner> encoder_thread_task_runner_;
+
+  // Declared last to ensure that all weak pointers are invalidated before
+  // other destructors run.
+  base::WeakPtrFactory<MediaFoundationVideoEncodeAccelerator>
+      encoder_task_weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(MediaFoundationVideoEncodeAccelerator);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_MEDIA_FOUNDATION_VIDEO_ENCODE_ACCELERATOR_WIN_H_
\ No newline at end of file
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc
index eb13008..7ba3fe8d 100644
--- a/media/gpu/video_encode_accelerator_unittest.cc
+++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -27,6 +27,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
@@ -61,6 +62,8 @@
 #endif  // defined(ARCH_CPU_X86_FAMILY)
 #elif defined(OS_MACOSX)
 #include "media/gpu/vt_video_encode_accelerator_mac.h"
+#elif defined(OS_WIN)
+#include "media/gpu/media_foundation_video_encode_accelerator_win.h"
 #else
 #error The VideoEncodeAcceleratorUnittest is not supported on this platform.
 #endif
@@ -110,6 +113,8 @@
 // "in_filename:width:height:profile:out_filename:requested_bitrate
 //  :requested_framerate:requested_subsequent_bitrate
 //  :requested_subsequent_framerate"
+// Instead of ":", "," can be used as a seperator as well. Note that ":" does
+// not work on Windows as it interferes with file paths.
 // - |in_filename| must be an I420 (YUV planar) raw stream
 //   (see http://www.fourcc.org/yuv.php#IYUV).
 // - |width| and |height| are in pixels.
@@ -130,11 +135,14 @@
 //                                    of the stream.
 //   Bitrate is only forced for tests that test bitrate.
 const char* g_default_in_filename = "bear_320x192_40frames.yuv";
-#if !defined(OS_MACOSX)
-const char* g_default_in_parameters = ":320:192:1:out.h264:200000";
-#else
-const char* g_default_in_parameters = ":320:192:0:out.h264:200000";
-#endif
+
+#if defined(OS_CHROMEOS)
+const base::FilePath::CharType* g_default_in_parameters =
+    FILE_PATH_LITERAL(":320:192:1:out.h264:200000");
+#elif defined(OS_MACOSX) || defined(OS_WIN)
+const base::FilePath::CharType* g_default_in_parameters =
+    FILE_PATH_LITERAL(",320,192,0,out.h264,200000");
+#endif  // defined(OS_CHROMEOS)
 
 // Enabled by including a --fake_encoder flag to the command line invoking the
 // test.
@@ -240,6 +248,25 @@
   return profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX;
 }
 
+// Helper functions to do string conversions.
+static base::FilePath::StringType StringToFilePathStringType(
+    const std::string& str) {
+#if defined(OS_WIN)
+  return base::UTF8ToWide(str);
+#else
+  return str;
+#endif  // defined(OS_WIN)
+}
+
+static std::string FilePathStringTypeToString(
+    const base::FilePath::StringType& str) {
+#if defined(OS_WIN)
+  return base::WideToUTF8(str);
+#else
+  return str;
+#endif  // defined(OS_WIN)
+}
+
 // ARM performs CPU cache management with CPU cache line granularity. We thus
 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned).
 // Otherwise newer kernels will refuse to accept them, and on older kernels
@@ -290,7 +317,7 @@
     padding_sizes[i] = padding_rows * coded_bpl[i] + Align64Bytes(size) - size;
   }
 
-  base::FilePath src_file(test_stream->in_filename);
+  base::FilePath src_file(StringToFilePathStringType(test_stream->in_filename));
   int64_t src_file_size = 0;
   LOG_ASSERT(base::GetFileSize(src_file, &src_file_size));
 
@@ -299,7 +326,8 @@
   LOG_ASSERT(src_file_size % visible_buffer_size == 0U)
       << "Stream byte size is not a product of calculated frame byte size";
 
-  test_stream->num_frames = src_file_size / visible_buffer_size;
+  test_stream->num_frames =
+      static_cast<unsigned int>(src_file_size / visible_buffer_size);
 
   LOG_ASSERT(test_stream->aligned_buffer_size > 0UL);
   test_stream->aligned_in_file_data.resize(test_stream->aligned_buffer_size *
@@ -309,7 +337,8 @@
   std::vector<char> src_data(visible_buffer_size);
   off_t src_offset = 0, dest_offset = 0;
   for (size_t frame = 0; frame < test_stream->num_frames; frame++) {
-    LOG_ASSERT(src.Read(src_offset, &src_data[0], visible_buffer_size) ==
+    LOG_ASSERT(src.Read(src_offset, &src_data[0],
+                        static_cast<int>(visible_buffer_size)) ==
                static_cast<int>(visible_buffer_size));
     const char* src_ptr = &src_data[0];
     for (size_t i = 0; i < num_planes; i++) {
@@ -320,19 +349,21 @@
         memcpy(&test_stream->aligned_in_file_data[dest_offset], src_ptr,
                visible_bpl[i]);
         src_ptr += visible_bpl[i];
-        dest_offset += coded_bpl[i];
+        dest_offset += static_cast<off_t>(coded_bpl[i]);
       }
-      dest_offset += padding_sizes[i];
+      dest_offset += static_cast<off_t>(padding_sizes[i]);
     }
-    src_offset += visible_buffer_size;
+    src_offset += static_cast<off_t>(visible_buffer_size);
   }
   src.Close();
 
+#if defined(OS_POSIX)
   // Assert that memory mapped of file starts at 64 byte boundary. So each
   // plane of frames also start at 64 byte boundary.
   ASSERT_EQ(reinterpret_cast<off_t>(&test_stream->aligned_in_file_data[0]) & 63,
             0)
       << "File should be mapped at a 64 byte boundary";
+#endif  // defined(OS_POSIX)
 
   LOG_ASSERT(test_stream->num_frames > 0UL);
 }
@@ -350,13 +381,19 @@
   // Parse each test stream data and read the input file.
   for (size_t index = 0; index < test_streams_data.size(); ++index) {
     std::vector<base::FilePath::StringType> fields = base::SplitString(
-        test_streams_data[index], base::FilePath::StringType(1, ':'),
+        test_streams_data[index], base::FilePath::StringType(1, ','),
         base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+    // Try using ":" as the seperator if "," isn't used.
+    if (fields.size() == 1U) {
+      fields = base::SplitString(test_streams_data[index],
+                                 base::FilePath::StringType(1, ':'),
+                                 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+    }
     LOG_ASSERT(fields.size() >= 4U) << data;
     LOG_ASSERT(fields.size() <= 9U) << data;
     TestStream* test_stream = new TestStream();
 
-    test_stream->in_filename = fields[0];
+    test_stream->in_filename = FilePathStringTypeToString(fields[0]);
     int width, height;
     bool result = base::StringToInt(fields[1], &width);
     LOG_ASSERT(result);
@@ -372,7 +409,7 @@
     test_stream->requested_profile = static_cast<VideoCodecProfile>(profile);
 
     if (fields.size() >= 5 && !fields[4].empty())
-      test_stream->out_filename = fields[4];
+      test_stream->out_filename = FilePathStringTypeToString(fields[4]);
 
     if (fields.size() >= 6 && !fields[5].empty())
       LOG_ASSERT(
@@ -436,7 +473,7 @@
     std::string s = base::StringPrintf("%s: %s\n", key.c_str(), value.c_str());
     LOG(INFO) << s;
     if (log_file_) {
-      log_file_->WriteAtCurrentPos(s.data(), s.length());
+      log_file_->WriteAtCurrentPos(s.data(), static_cast<int>(s.length()));
     }
   }
 
@@ -525,7 +562,7 @@
 };
 
 void H264Validator::ProcessStreamBuffer(const uint8_t* stream, size_t size) {
-  h264_parser_.SetStream(stream, size);
+  h264_parser_.SetStream(stream, static_cast<off_t>(size));
 
   while (1) {
     H264NALU nalu;
@@ -635,7 +672,7 @@
   void VerifyOutputFrame(const scoped_refptr<VideoFrame>& output_frame);
   void Decode();
 
-  enum State { UNINITIALIZED, INITIALIZED, DECODING, ERROR };
+  enum State { UNINITIALIZED, INITIALIZED, DECODING, DECODER_ERROR };
 
   const VideoCodecProfile profile_;
   std::unique_ptr<FFmpegVideoDecoder> decoder_;
@@ -698,11 +735,11 @@
     decoder_state_ = INITIALIZED;
     Decode();
   } else {
-    decoder_state_ = ERROR;
+    decoder_state_ = DECODER_ERROR;
     if (IsH264(profile_))
       LOG(ERROR) << "Chromium does not support H264 decode. Try Chrome.";
-    FAIL() << "Decoder initialization error";
     decode_error_cb_.Run();
+    FAIL() << "Decoder initialization error";
   }
 }
 
@@ -716,9 +753,9 @@
     decoder_state_ = INITIALIZED;
     Decode();
   } else {
-    decoder_state_ = ERROR;
-    FAIL() << "Unexpected decode status = " << status << ". Stop decoding.";
+    decoder_state_ = DECODER_ERROR;
     decode_error_cb_.Run();
+    FAIL() << "Unexpected decode status = " << status << ". Stop decoding.";
   }
 }
 
@@ -727,7 +764,7 @@
 }
 
 void VideoFrameQualityValidator::Flush() {
-  if (decoder_state_ != ERROR) {
+  if (decoder_state_ != DECODER_ERROR) {
     decode_buffers_.push(DecoderBuffer::CreateEOSBuffer());
     Decode();
   }
@@ -735,7 +772,7 @@
 
 void VideoFrameQualityValidator::AddDecodeBuffer(
     const scoped_refptr<DecoderBuffer>& buffer) {
-  if (decoder_state_ != ERROR) {
+  if (decoder_state_ != DECODER_ERROR) {
     decode_buffers_.push(buffer);
     Decode();
   }
@@ -771,15 +808,18 @@
         VideoFrame::Columns(plane, kInputFormat, visible_size.width());
     size_t stride = original_frame->stride(plane);
 
-    for (size_t i = 0; i < rows; i++)
-      for (size_t j = 0; j < columns; j++)
+    for (size_t i = 0; i < rows; i++) {
+      for (size_t j = 0; j < columns; j++) {
         difference += std::abs(original_plane[stride * i + j] -
                                output_plane[stride * i + j]);
+      }
+    }
   }
+
   // Divide the difference by the size of frame.
   difference /= VideoFrame::AllocationSize(kInputFormat, visible_size);
   EXPECT_TRUE(difference <= kDecodeSimilarityThreshold)
-      << "differrence = " << difference << "  > decode similarity threshold";
+      << "difference = " << difference << "  > decode similarity threshold";
 }
 
 class VEAClient : public VideoEncodeAccelerator::Client {
@@ -818,6 +858,7 @@
   std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA();
   std::unique_ptr<VideoEncodeAccelerator> CreateVaapiVEA();
   std::unique_ptr<VideoEncodeAccelerator> CreateVTVEA();
+  std::unique_ptr<VideoEncodeAccelerator> CreateMFVEA();
 
   void SetState(ClientState new_state);
 
@@ -1050,7 +1091,11 @@
 
   if (save_to_file_) {
     LOG_ASSERT(!test_stream_->out_filename.empty());
+#if defined(OS_POSIX)
     base::FilePath out_filename(test_stream_->out_filename);
+#elif defined(OS_WIN)
+    base::FilePath out_filename(base::UTF8ToWide(test_stream_->out_filename));
+#endif
     // This creates or truncates out_filename.
     // Without it, AppendToFile() will not work.
     EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0));
@@ -1102,12 +1147,22 @@
   return encoder;
 }
 
+std::unique_ptr<VideoEncodeAccelerator> VEAClient::CreateMFVEA() {
+  std::unique_ptr<VideoEncodeAccelerator> encoder;
+#if defined(OS_WIN)
+  MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
+  encoder.reset(new MediaFoundationVideoEncodeAccelerator());
+#endif
+  return encoder;
+}
+
 void VEAClient::CreateEncoder() {
   DCHECK(thread_checker_.CalledOnValidThread());
   LOG_ASSERT(!has_encoder());
 
   std::unique_ptr<VideoEncodeAccelerator> encoders[] = {
-      CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA()};
+      CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(),
+      CreateMFVEA()};
 
   DVLOG(1) << "Profile: " << test_stream_->requested_profile
            << ", initial bitrate: " << requested_bitrate_;
@@ -1427,7 +1482,7 @@
   scoped_refptr<VideoFrame> video_frame =
       PrepareInputFrame(pos_in_input_stream_, &input_id);
   frame_timestamps_.push(video_frame->timestamp());
-  pos_in_input_stream_ += test_stream_->aligned_buffer_size;
+  pos_in_input_stream_ += static_cast<off_t>(test_stream_->aligned_buffer_size);
 
   bool force_keyframe = false;
   if (keyframe_period_ && input_id % keyframe_period_ == 0) {
@@ -1557,11 +1612,12 @@
 void VEAClient::VerifyStreamProperties() {
   LOG_ASSERT(num_frames_since_last_check_ > 0UL);
   LOG_ASSERT(encoded_stream_size_since_last_check_ > 0UL);
-  unsigned int bitrate = encoded_stream_size_since_last_check_ * 8 *
-                         current_framerate_ / num_frames_since_last_check_;
+  unsigned int bitrate = static_cast<unsigned int>(
+      encoded_stream_size_since_last_check_ * 8 * current_framerate_ /
+      num_frames_since_last_check_);
   DVLOG(1) << "Current chunk's bitrate: " << bitrate
-           << " (expected: " << current_requested_bitrate_
-           << " @ " << current_framerate_ << " FPS,"
+           << " (expected: " << current_requested_bitrate_ << " @ "
+           << current_framerate_ << " FPS,"
            << " num frames in chunk: " << num_frames_since_last_check_;
 
   num_frames_since_last_check_ = 0;
@@ -1605,7 +1661,7 @@
 void VEAClient::WriteIvfFrameHeader(int frame_index, size_t frame_size) {
   IvfFrameHeader header = {};
 
-  header.frame_size = frame_size;
+  header.frame_size = static_cast<uint32_t>(frame_size);
   header.timestamp = frame_index;
   header.ByteSwap();
   EXPECT_TRUE(base::AppendToFile(
@@ -1697,7 +1753,7 @@
   encoder_thread.Stop();
 }
 
-#if !defined(OS_MACOSX)
+#if defined(OS_CHROMEOS)
 INSTANTIATE_TEST_CASE_P(
     SimpleEncode,
     VideoEncodeAcceleratorTest,
@@ -1755,7 +1811,7 @@
     ::testing::Values(
         std::make_tuple(1, false, 0, false, false, false, false, false, true)));
 
-#else
+#elif defined(OS_MACOSX) || defined(OS_WIN)
 INSTANTIATE_TEST_CASE_P(
     SimpleEncode,
     VideoEncodeAcceleratorTest,
@@ -1780,7 +1836,15 @@
                                                           false,
                                                           false,
                                                           false)));
-#endif
+#if defined(OS_WIN)
+INSTANTIATE_TEST_CASE_P(
+    ForceBitrate,
+    VideoEncodeAcceleratorTest,
+    ::testing::Values(
+        std::make_tuple(1, false, 0, true, false, false, false, false, false)));
+#endif  // defined(OS_WIN)
+
+#endif  // defined(OS_CHROMEOS)
 
 // TODO(posciak): more tests:
 // - async FeedEncoderWithOutput
@@ -1800,8 +1864,8 @@
 
   std::unique_ptr<base::FilePath::StringType> test_stream_data(
       new base::FilePath::StringType(
-          media::GetTestDataFilePath(media::g_default_in_filename).value() +
-          media::g_default_in_parameters));
+          media::GetTestDataFilePath(media::g_default_in_filename).value()));
+  test_stream_data->append(media::g_default_in_parameters);
 
   // Needed to enable DVLOG through --vmodule.
   logging::LoggingSettings settings;
diff --git a/media/media.gyp b/media/media.gyp
index 5ea6e73..463647f8 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -1739,6 +1739,8 @@
           'include_dirs': [ '..', ],
           'defines': [ 'MF_INITIALIZER_IMPLEMENTATION', ],
           'sources': [
+            'base/win/mf_helpers.cc',
+            'base/win/mf_helpers.h',
             'base/win/mf_initializer_export.h',
             'base/win/mf_initializer.cc',
             'base/win/mf_initializer.h',
@@ -2132,7 +2134,7 @@
         }
       ]
     }],
-    ['chromeos==1 or OS=="mac"', {
+    ['chromeos==1 or OS=="mac" or OS=="win"', {
       'targets': [
         {
           'target_name': 'video_encode_accelerator_unittest',
@@ -2164,6 +2166,11 @@
                 '../third_party/webrtc/common_video/common_video.gyp:common_video',
               ],
             }],
+            ['OS=="win"', {
+              'dependencies': [
+                '../media/media.gyp:mf_initializer',
+              ],
+            }],
             ['use_x11==1', {
               'dependencies': [
                 '../ui/gfx/x/gfx_x11.gyp:gfx_x11',
diff --git a/media/media_gpu.gypi b/media/media_gpu.gypi
index d59a94b..e507201 100644
--- a/media/media_gpu.gypi
+++ b/media/media_gpu.gypi
@@ -328,6 +328,7 @@
       'dependencies': [
         '../media/media.gyp:media',
         '../media/media.gyp:mf_initializer',
+        '../third_party/libyuv/libyuv.gyp:libyuv',
         '../ui/gl/gl.gyp:gl',
         '../ui/gl/init/gl_init.gyp:gl_init',
       ],
@@ -358,6 +359,8 @@
         'gpu/dxva_picture_buffer_win.h',
         'gpu/dxva_video_decode_accelerator_win.cc',
         'gpu/dxva_video_decode_accelerator_win.h',
+        'gpu/media_foundation_video_encode_accelerator_win.cc',
+        'gpu/media_foundation_video_encode_accelerator_win.h',
       ],
       'include_dirs': [
         '<(DEPTH)/third_party/khronos',
diff --git a/media/mojo/interfaces/image_capture.mojom b/media/mojo/interfaces/image_capture.mojom
index 3546651c..7c7fed82 100644
--- a/media/mojo/interfaces/image_capture.mojom
+++ b/media/mojo/interfaces/image_capture.mojom
@@ -19,6 +19,9 @@
 // Equivalent to idl PhotoCapabilities,
 // https://w3c.github.io/mediacapture-image/#photocapabilities
 struct PhotoCapabilities {
+  Range iso;
+  Range height;
+  Range width;
   Range zoom;
   FocusMode focus_mode;
 };
@@ -29,6 +32,16 @@
   // uint32 cannot be nullable, i.e. uint32? does not work, use instead a flag.
   bool has_zoom;
   uint32 zoom;
+  bool has_width;
+  uint32 width;
+  bool has_height;
+  uint32 height;
+};
+
+// This is a mojo move-only equivalent of a Blob, i.e. MIME type and Data.
+struct Blob {
+  string mime_type;
+  array<uint8> data;
 };
 
 // |source_id| is the renderer-side UUID identifier of the image capture device.
@@ -44,9 +57,9 @@
     SetOptions(string source_id, PhotoSettings settings)
         => (bool success);
 
-    // Takes a Photo from the given |source_id|, returning it encoded in |data|
-    // with the format specified in |mime_type|.
+    // Takes a Photo from the given |source_id|, returning it encoded in |blob|
+    // with the format specified in its |mime_type|.
     // https://w3c.github.io/mediacapture-image/index.html#widl-ImageCapture-takePhoto-Promise-Blob
     TakePhoto(string source_id)
-        => (string mime_type, array<uint8> data);
+        => (Blob blob);
 };
diff --git a/mojo/edk/system/node_channel.cc b/mojo/edk/system/node_channel.cc
index ce094c16..114e286 100644
--- a/mojo/edk/system/node_channel.cc
+++ b/mojo/edk/system/node_channel.cc
@@ -771,7 +771,6 @@
     pending_writes.swap(pending_write_messages_);
     pending_relays.swap(pending_relay_messages_);
   }
-  DCHECK(pending_writes.empty() && pending_relays.empty());
 
   while (!pending_writes.empty()) {
     Channel::MessagePtr message = std::move(pending_writes.front());
diff --git a/mojo/mojo_edk_tests.gyp b/mojo/mojo_edk_tests.gyp
index e1924621..e18d8747 100644
--- a/mojo/mojo_edk_tests.gyp
+++ b/mojo/mojo_edk_tests.gyp
@@ -56,6 +56,7 @@
         'public/cpp/bindings/tests/constant_unittest.cc',
         'public/cpp/bindings/tests/container_test_util.cc',
         'public/cpp/bindings/tests/container_test_util.h',
+        'public/cpp/bindings/tests/data_view_unittest.cc',
         'public/cpp/bindings/tests/equals_unittest.cc',
         'public/cpp/bindings/tests/handle_passing_unittest.cc',
         'public/cpp/bindings/tests/interface_ptr_unittest.cc',
diff --git a/mojo/mojo_public.gypi b/mojo/mojo_public.gypi
index b5da143..c69da49 100644
--- a/mojo/mojo_public.gypi
+++ b/mojo/mojo_public.gypi
@@ -6,6 +6,7 @@
   'variables': {
     'mojo_cpp_bindings_sources': [
       'public/cpp/bindings/array.h',
+      'public/cpp/bindings/array_data_view.h',
       'public/cpp/bindings/array_traits.h',
       'public/cpp/bindings/array_traits_carray.h',
       'public/cpp/bindings/array_traits_standard.h',
@@ -93,6 +94,7 @@
       'public/cpp/bindings/lib/validation_errors.h',
       'public/cpp/bindings/lib/validation_util.cc',
       'public/cpp/bindings/lib/validation_util.h',
+      'public/cpp/bindings/map_data_view.h',
       'public/cpp/bindings/map_traits.h',
       'public/cpp/bindings/map_traits_standard.h',
       'public/cpp/bindings/map_traits_stl.h',
@@ -101,6 +103,7 @@
       'public/cpp/bindings/message_header_validator.h',
       'public/cpp/bindings/native_enum.h',
       'public/cpp/bindings/native_struct.h',
+      'public/cpp/bindings/native_struct_data_view.h',
       'public/cpp/bindings/no_interface.h',
       'public/cpp/bindings/pipe_control_message_handler.h',
       'public/cpp/bindings/pipe_control_message_handler_delegate.h',
@@ -108,6 +111,7 @@
       'public/cpp/bindings/scoped_interface_endpoint_handle.h',
       'public/cpp/bindings/stl_converters.h',
       'public/cpp/bindings/string.h',
+      'public/cpp/bindings/string_data_view.h',
       'public/cpp/bindings/string_traits.h',
       'public/cpp/bindings/string_traits_standard.h',
       'public/cpp/bindings/string_traits_stl.h',
diff --git a/mojo/mojo_public_tests.gyp b/mojo/mojo_public_tests.gyp
index ebe2b6c..38fd179 100644
--- a/mojo/mojo_public_tests.gyp
+++ b/mojo/mojo_public_tests.gyp
@@ -19,6 +19,7 @@
       'public/interfaces/bindings/tests/scoping.mojom',
       'public/interfaces/bindings/tests/serialization_test_structs.mojom',
       'public/interfaces/bindings/tests/test_constants.mojom',
+      'public/interfaces/bindings/tests/test_data_view.mojom',
       'public/interfaces/bindings/tests/test_native_types.mojom',
       'public/interfaces/bindings/tests/test_sync_methods.mojom',
     ],
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index 3ec98244..320e2d5 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -5,6 +5,7 @@
 static_library("bindings") {
   sources = [
     "array.h",
+    "array_data_view.h",
     "array_traits.h",
     "array_traits_carray.h",
     "array_traits_standard.h",
@@ -94,6 +95,7 @@
     "lib/validation_util.cc",
     "lib/validation_util.h",
     "map.h",
+    "map_data_view.h",
     "map_traits.h",
     "map_traits_standard.h",
     "map_traits_stl.h",
@@ -102,6 +104,7 @@
     "message_header_validator.h",
     "native_enum.h",
     "native_struct.h",
+    "native_struct_data_view.h",
     "no_interface.h",
     "pipe_control_message_handler.h",
     "pipe_control_message_handler_delegate.h",
@@ -109,6 +112,7 @@
     "scoped_interface_endpoint_handle.h",
     "stl_converters.h",
     "string.h",
+    "string_data_view.h",
     "string_traits.h",
     "string_traits_standard.h",
     "string_traits_stl.h",
diff --git a/mojo/public/cpp/bindings/array_data_view.h b/mojo/public/cpp/bindings/array_data_view.h
new file mode 100644
index 0000000..89d1bb4
--- /dev/null
+++ b/mojo/public/cpp/bindings/array_data_view.h
@@ -0,0 +1,231 @@
+// Copyright 2016 The Chromium Authors. 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_ARRAY_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_
+
+#include <type_traits>
+
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T, typename EnableType = void>
+class ArrayDataViewImpl;
+
+template <typename T>
+class ArrayDataViewImpl<
+    T,
+    typename std::enable_if<BelongsTo<typename DataViewTraits<T>::MojomType,
+                                      MojomTypeCategory::POD>::value>::type> {
+ public:
+  static_assert(std::is_same<T, typename DataViewTraits<T>::MojomType>::value,
+                "DataView type mismatch");
+
+  using Data_ = typename MojomTypeTraits<Array<T>>::Data;
+
+  ArrayDataViewImpl(Data_* data, SerializationContext* context)
+      : data_(data), context_(context) {}
+
+  T operator[](size_t index) const { return data_->at(index); }
+
+  const T* data() const { return data_->storage(); }
+
+ protected:
+  Data_* data_;
+  SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<T,
+                        typename std::enable_if<BelongsTo<
+                            typename DataViewTraits<T>::MojomType,
+                            MojomTypeCategory::BOOLEAN>::value>::type> {
+ public:
+  static_assert(std::is_same<T, typename DataViewTraits<T>::MojomType>::value,
+                "DataView type mismatch");
+
+  using Data_ = typename MojomTypeTraits<Array<T>>::Data;
+
+  ArrayDataViewImpl(Data_* data, SerializationContext* context)
+      : data_(data), context_(context) {}
+
+  bool operator[](size_t index) const { return data_->at(index); }
+
+ protected:
+  Data_* data_;
+  SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+    T,
+    typename std::enable_if<BelongsTo<typename DataViewTraits<T>::MojomType,
+                                      MojomTypeCategory::ENUM>::value>::type> {
+ public:
+  static_assert(std::is_same<T, typename DataViewTraits<T>::MojomType>::value,
+                "DataView type mismatch");
+  static_assert(sizeof(T) == sizeof(int32_t), "Unexpected enum size");
+
+  using Data_ = typename MojomTypeTraits<Array<T>>::Data;
+
+  ArrayDataViewImpl(Data_* data, SerializationContext* context)
+      : data_(data), context_(context) {}
+
+  T operator[](size_t index) const { return static_cast<T>(data_->at(index)); }
+
+  const T* data() const { return reinterpret_cast<const T*>(data_->storage()); }
+
+  template <typename U>
+  bool Read(size_t index, U* output) {
+    return Deserialize<T>(data_->at(index), output);
+  }
+
+ protected:
+  Data_* data_;
+  SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+    T,
+    typename std::enable_if<
+        BelongsTo<typename DataViewTraits<T>::MojomType,
+                  MojomTypeCategory::ASSOCIATED_INTERFACE |
+                      MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST |
+                      MojomTypeCategory::HANDLE |
+                      MojomTypeCategory::INTERFACE |
+                      MojomTypeCategory::INTERFACE_REQUEST>::value>::type> {
+ public:
+  static_assert(std::is_same<T, typename DataViewTraits<T>::MojomType>::value,
+                "DataView type mismatch");
+
+  using Data_ = typename MojomTypeTraits<Array<T>>::Data;
+
+  ArrayDataViewImpl(Data_* data, SerializationContext* context)
+      : data_(data), context_(context) {}
+
+  T Take(size_t index) {
+    T result;
+    bool ret = Deserialize<T>(&data_->at(index), &result, context_);
+    DCHECK(ret);
+    return result;
+  }
+
+ protected:
+  Data_* data_;
+  SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<T,
+                        typename std::enable_if<BelongsTo<
+                            typename DataViewTraits<T>::MojomType,
+                            MojomTypeCategory::ARRAY | MojomTypeCategory::MAP |
+                                MojomTypeCategory::STRING |
+                                MojomTypeCategory::STRUCT>::value>::type> {
+ public:
+  using Data_ = typename MojomTypeTraits<
+      Array<typename DataViewTraits<T>::MojomType>>::Data;
+
+  ArrayDataViewImpl(Data_* data, SerializationContext* context)
+      : data_(data), context_(context) {}
+
+  void GetDataView(size_t index, T* output) {
+    *output = T(data_->at(index).Get(), context_);
+  }
+
+  template <typename U>
+  bool Read(size_t index, U* output) {
+    return Deserialize<typename DataViewTraits<T>::MojomType>(
+        data_->at(index).Get(), output, context_);
+  }
+
+ protected:
+  Data_* data_;
+  SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+    T,
+    typename std::enable_if<BelongsTo<typename DataViewTraits<T>::MojomType,
+                                      MojomTypeCategory::UNION>::value>::type> {
+ public:
+  using Data_ = typename MojomTypeTraits<
+      Array<typename DataViewTraits<T>::MojomType>>::Data;
+
+  ArrayDataViewImpl(Data_* data, SerializationContext* context)
+      : data_(data), context_(context) {}
+
+  void GetDataView(size_t index, T* output) {
+    *output = T(&data_->at(index), context_);
+  }
+
+  template <typename U>
+  bool Read(size_t index, U* output) {
+    return Deserialize<typename DataViewTraits<T>::MojomType>(&data_->at(index),
+                                                              output, context_);
+  }
+
+ protected:
+  Data_* data_;
+  SerializationContext* context_;
+};
+
+}  // namespace internal
+
+template <typename K, typename V>
+class MapDataView;
+
+template <typename T>
+class ArrayDataView : public internal::ArrayDataViewImpl<T> {
+ public:
+  using Data_ = typename internal::ArrayDataViewImpl<T>::Data_;
+
+  ArrayDataView() : internal::ArrayDataViewImpl<T>(nullptr, nullptr) {}
+
+  ArrayDataView(Data_* data, internal::SerializationContext* context)
+      : internal::ArrayDataViewImpl<T>(data, context) {}
+
+  bool is_null() const { return !this->data_; }
+
+  size_t size() const { return this->data_->size(); }
+
+  // Methods to access elements are different for different element types. They
+  // are inherited from internal::ArrayDataViewImpl:
+
+  // POD types except boolean and enums:
+  //   T operator[](size_t index) const;
+  //   const T* data() const;
+
+  // Boolean:
+  //   bool operator[](size_t index) const;
+
+  // Enums:
+  //   T operator[](size_t index) const;
+  //   const T* data() const;
+  //   template <typename U>
+  //   bool Read(size_t index, U* output);
+
+  // Handles and interfaces:
+  //   T Take(size_t index);
+
+  // Object types:
+  //   void GetDataView(size_t index, T* output);
+  //   template <typename U>
+  //   bool Read(size_t index, U* output);
+
+ private:
+  template <typename K, typename V>
+  friend class MapDataView;
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_
diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h
index b37d8727..a16ce0e 100644
--- a/mojo/public/cpp/bindings/lib/bindings_internal.h
+++ b/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -20,6 +20,9 @@
 class Array;
 
 template <typename T>
+class ArrayDataView;
+
+template <typename T>
 class AssociatedInterfacePtrInfo;
 
 template <typename T>
@@ -34,14 +37,25 @@
 template <typename K, typename V>
 class Map;
 
+template <typename K, typename V>
+class MapDataView;
+
+class NativeStruct;
+
+class NativeStructDataView;
+
 class String;
 
+class StringDataView;
+
 template <typename T>
 class StructPtr;
 
 template <typename T>
 class InlinedStructPtr;
 
+using NativeStructPtr = StructPtr<NativeStruct>;
+
 namespace internal {
 
 // Please note that this is a different value than |mojo::kInvalidHandleValue|,
@@ -328,6 +342,32 @@
   }
 };
 
+template <typename T>
+struct DataViewTraits {
+  using MojomType = T;
+};
+
+template <typename T>
+struct DataViewTraits<ArrayDataView<T>> {
+  using MojomType = Array<typename DataViewTraits<T>::MojomType>;
+};
+
+template <typename K, typename V>
+struct DataViewTraits<MapDataView<K, V>> {
+  using MojomType = Map<typename DataViewTraits<K>::MojomType,
+                        typename DataViewTraits<V>::MojomType>;
+};
+
+template <>
+struct DataViewTraits<StringDataView> {
+  using MojomType = String;
+};
+
+template <>
+struct DataViewTraits<NativeStructDataView> {
+  using MojomType = NativeStructPtr;
+};
+
 }  // namespace internal
 }  // namespace mojo
 
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h
index 5e65891e..0b62e06 100644
--- a/mojo/public/cpp/bindings/lib/string_serialization.h
+++ b/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -60,7 +60,7 @@
                           SerializationContext* context) {
     if (!input)
       return CallSetToNullIfExists<Traits>(output);
-    return Traits::Read(StringDataView(input), output);
+    return Traits::Read(StringDataView(input, context), output);
   }
 };
 
diff --git a/mojo/public/cpp/bindings/map_data_view.h b/mojo/public/cpp/bindings/map_data_view.h
new file mode 100644
index 0000000..c340407b
--- /dev/null
+++ b/mojo/public/cpp/bindings/map_data_view.h
@@ -0,0 +1,68 @@
+// Copyright 2016 The Chromium Authors. 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_MAP_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_
+
+#include "base/logging.h"
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/array_data_view.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
+#include "mojo/public/cpp/bindings/map.h"
+
+namespace mojo {
+
+template <typename K, typename V>
+class MapDataView {
+ public:
+  using Data_ = typename internal::MojomTypeTraits<
+      Map<typename internal::DataViewTraits<K>::MojomType,
+          typename internal::DataViewTraits<V>::MojomType>>::Data;
+
+  MapDataView() {}
+
+  MapDataView(Data_* data, internal::SerializationContext* context)
+      : keys_(data ? data->keys.Get() : nullptr, context),
+        values_(data ? data->values.Get() : nullptr, context) {}
+
+  bool is_null() const {
+    DCHECK_EQ(keys_.is_null(), values_.is_null());
+    return keys_.is_null();
+  }
+
+  size_t size() const {
+    DCHECK_EQ(keys_.size(), values_.size());
+    return keys_.size();
+  }
+
+  ArrayDataView<K>& keys() { return keys_; }
+  const ArrayDataView<K>& keys() const { return keys_; }
+
+  template <typename U>
+  bool ReadKeys(U* output) {
+    return internal::Deserialize<
+        Array<typename internal::DataViewTraits<K>::MojomType>>(
+        keys_.data_, output, keys_.context_);
+  }
+
+  ArrayDataView<V>& values() { return values_; }
+  const ArrayDataView<V>& values() const { return values_; }
+
+  template <typename U>
+  bool ReadValues(U* output) {
+    return internal::Deserialize<
+        Array<typename internal::DataViewTraits<V>::MojomType>>(
+        values_.data_, output, values_.context_);
+  }
+
+ private:
+  ArrayDataView<K> keys_;
+  ArrayDataView<V> values_;
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_
diff --git a/mojo/public/cpp/bindings/native_struct_data_view.h b/mojo/public/cpp/bindings/native_struct_data_view.h
new file mode 100644
index 0000000..613bd7a
--- /dev/null
+++ b/mojo/public/cpp/bindings/native_struct_data_view.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. 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_NATIVE_STRUCT_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_
+
+#include "mojo/public/cpp/bindings/lib/native_struct_data.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+
+namespace mojo {
+
+class NativeStructDataView {
+ public:
+  using Data_ = internal::NativeStruct_Data;
+
+  NativeStructDataView() {}
+
+  NativeStructDataView(Data_* data, internal::SerializationContext* context)
+      : data_(data) {}
+
+  bool is_null() const { return !data_; }
+
+  size_t size() const { return data_->data.size(); }
+
+  uint8_t operator[](size_t index) const { return data_->data.at(index); }
+
+  const uint8_t* data() const { return data_->data.storage(); }
+
+ private:
+  Data_* data_ = nullptr;
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_
diff --git a/mojo/public/cpp/bindings/string_data_view.h b/mojo/public/cpp/bindings/string_data_view.h
new file mode 100644
index 0000000..2b091b4
--- /dev/null
+++ b/mojo/public/cpp/bindings/string_data_view.h
@@ -0,0 +1,34 @@
+// Copyright 2016 The Chromium Authors. 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_STRING_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+
+namespace mojo {
+
+// Access to the contents of a serialized string.
+class StringDataView {
+ public:
+  StringDataView() {}
+
+  StringDataView(internal::String_Data* data,
+                 internal::SerializationContext* context)
+      : data_(data) {}
+
+  bool is_null() const { return !data_; }
+
+  const char* storage() const { return data_->storage(); }
+
+  size_t size() const { return data_->size(); }
+
+ private:
+  internal::String_Data* data_ = nullptr;
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_
diff --git a/mojo/public/cpp/bindings/string_traits.h b/mojo/public/cpp/bindings/string_traits.h
index a6ade6f..7d3075a5 100644
--- a/mojo/public/cpp/bindings/string_traits.h
+++ b/mojo/public/cpp/bindings/string_traits.h
@@ -5,26 +5,10 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_
 
-#include "base/logging.h"
-#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/string_data_view.h"
 
 namespace mojo {
 
-// Access to the contents of a serialized string.
-class StringDataView {
- public:
-  explicit StringDataView(internal::String_Data* data) : data_(data) {
-    DCHECK(data_);
-  }
-
-  const char* storage() const { return data_->storage(); }
-
-  size_t size() const { return data_->size(); }
-
- private:
-  internal::String_Data* data_;
-};
-
 // This must be specialized for any type |T| to be serialized/deserialized as
 // a mojom string.
 //
@@ -40,6 +24,7 @@
 //     static size_t GetSize(const CustomString& input);
 //     static const char* GetData(const CustomString& input);
 //
+//     // The caller guarantees that |!input.is_null()|.
 //     static bool Read(StringDataView input, CustomString* output);
 //   };
 //
diff --git a/mojo/public/cpp/bindings/struct_traits.h b/mojo/public/cpp/bindings/struct_traits.h
index 0f0bea7..b2a60c7 100644
--- a/mojo/public/cpp/bindings/struct_traits.h
+++ b/mojo/public/cpp/bindings/struct_traits.h
@@ -55,7 +55,8 @@
 //        static bool Read(|MojomType|DataView data, T* output);
 //
 //      The generated |MojomType|DataView type provides a convenient,
-//      inexpensive view of a serialized struct's field data.
+//      inexpensive view of a serialized struct's field data. The caller
+//      guarantees that |!data.is_null()|.
 //
 //      Returning false indicates invalid incoming data and causes the message
 //      pipe receiving it to be disconnected. Therefore, you can do custom
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn
index 3ee0737..b39e603e 100644
--- a/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -17,6 +17,7 @@
     "constant_unittest.cc",
     "container_test_util.cc",
     "container_test_util.h",
+    "data_view_unittest.cc",
     "equals_unittest.cc",
     "handle_passing_unittest.cc",
     "interface_ptr_unittest.cc",
diff --git a/mojo/public/cpp/bindings/tests/data_view_unittest.cc b/mojo/public/cpp/bindings/tests/data_view_unittest.cc
new file mode 100644
index 0000000..7bf58e7
--- /dev/null
+++ b/mojo/public/cpp/bindings/tests/data_view_unittest.cc
@@ -0,0 +1,303 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/message_loop/message_loop.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/serialization.h"
+#include "mojo/public/interfaces/bindings/tests/test_data_view.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace test {
+namespace data_view {
+namespace {
+
+class DataViewTest : public testing::Test {
+ private:
+  base::MessageLoop message_loop_;
+};
+
+struct DataViewHolder {
+  std::unique_ptr<TestStructDataView> data_view;
+  std::unique_ptr<mojo::internal::FixedBufferForTesting> buf;
+  mojo::internal::SerializationContext context;
+};
+
+std::unique_ptr<DataViewHolder> SerializeTestStruct(TestStructPtr input) {
+  std::unique_ptr<DataViewHolder> result(new DataViewHolder);
+
+  size_t size = mojo::internal::PrepareToSerialize<TestStructPtr>(
+      input, &result->context);
+
+  result->buf.reset(new mojo::internal::FixedBufferForTesting(size));
+  internal::TestStruct_Data* data = nullptr;
+  mojo::internal::Serialize<TestStructPtr>(input, result->buf.get(), &data,
+                                           &result->context);
+
+  result->data_view.reset(new TestStructDataView(data, &result->context));
+  return result;
+}
+
+class TestInterfaceImpl : public TestInterface {
+ public:
+  explicit TestInterfaceImpl(TestInterfaceRequest request)
+      : binding_(this, std::move(request)) {}
+  ~TestInterfaceImpl() override {}
+
+  // TestInterface implementation:
+  void Echo(int32_t value, const EchoCallback& callback) override {
+    callback.Run(value);
+  }
+
+ private:
+  Binding<TestInterface> binding_;
+};
+
+}  // namespace
+
+TEST_F(DataViewTest, String) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_string = "hello";
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  StringDataView string_data_view;
+  data_view.GetFStringDataView(&string_data_view);
+
+  ASSERT_FALSE(string_data_view.is_null());
+  EXPECT_EQ(std::string("hello"),
+            std::string(string_data_view.storage(), string_data_view.size()));
+}
+
+TEST_F(DataViewTest, NestedStruct) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_struct = NestedStruct::New();
+  obj->f_struct->f_int32 = 42;
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  NestedStructDataView struct_data_view;
+  data_view.GetFStructDataView(&struct_data_view);
+
+  ASSERT_FALSE(struct_data_view.is_null());
+  EXPECT_EQ(42, struct_data_view.f_int32());
+}
+
+TEST_F(DataViewTest, NativeStruct) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_native_struct = NativeStruct::New();
+  obj->f_native_struct->data = std::vector<uint8_t>({3, 2, 1});
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  NativeStructDataView struct_data_view;
+  data_view.GetFNativeStructDataView(&struct_data_view);
+
+  ASSERT_FALSE(struct_data_view.is_null());
+  ASSERT_EQ(3u, struct_data_view.size());
+  EXPECT_EQ(3, struct_data_view[0]);
+  EXPECT_EQ(2, struct_data_view[1]);
+  EXPECT_EQ(1, struct_data_view[2]);
+  EXPECT_EQ(3, *struct_data_view.data());
+}
+
+TEST_F(DataViewTest, BoolArray) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_bool_array = {true, false};
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<bool> array_data_view;
+  data_view.GetFBoolArrayDataView(&array_data_view);
+
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(2u, array_data_view.size());
+  EXPECT_TRUE(array_data_view[0]);
+  EXPECT_FALSE(array_data_view[1]);
+}
+
+TEST_F(DataViewTest, IntegerArray) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_int32_array = {1024, 128};
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<int32_t> array_data_view;
+  data_view.GetFInt32ArrayDataView(&array_data_view);
+
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(2u, array_data_view.size());
+  EXPECT_EQ(1024, array_data_view[0]);
+  EXPECT_EQ(128, array_data_view[1]);
+  EXPECT_EQ(1024, *array_data_view.data());
+}
+
+TEST_F(DataViewTest, EnumArray) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_enum_array = {TestEnum::VALUE_1, TestEnum::VALUE_0};
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<TestEnum> array_data_view;
+  data_view.GetFEnumArrayDataView(&array_data_view);
+
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(2u, array_data_view.size());
+  EXPECT_EQ(TestEnum::VALUE_1, array_data_view[0]);
+  EXPECT_EQ(TestEnum::VALUE_0, array_data_view[1]);
+  EXPECT_EQ(TestEnum::VALUE_0, *(array_data_view.data() + 1));
+
+  TestEnum output;
+  ASSERT_TRUE(array_data_view.Read(0, &output));
+  EXPECT_EQ(TestEnum::VALUE_1, output);
+}
+
+TEST_F(DataViewTest, InterfaceArray) {
+  TestInterfacePtr ptr;
+  TestInterfaceImpl impl(GetProxy(&ptr));
+
+  TestStructPtr obj(TestStruct::New());
+  obj->f_interface_array.push_back(std::move(ptr));
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<TestInterfacePtr> array_data_view;
+  data_view.GetFInterfaceArrayDataView(&array_data_view);
+
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(1u, array_data_view.size());
+
+  TestInterfacePtr ptr2 = array_data_view.Take(0);
+  ASSERT_TRUE(ptr2);
+  int32_t result = 0;
+  ASSERT_TRUE(ptr2->Echo(42, &result));
+  EXPECT_EQ(42, result);
+}
+
+TEST_F(DataViewTest, NestedArray) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_nested_array = {{3, 4}, {2}};
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<ArrayDataView<int32_t>> array_data_view;
+  data_view.GetFNestedArrayDataView(&array_data_view);
+
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(2u, array_data_view.size());
+
+  ArrayDataView<int32_t> nested_array_data_view;
+  array_data_view.GetDataView(0, &nested_array_data_view);
+  ASSERT_FALSE(nested_array_data_view.is_null());
+  ASSERT_EQ(2u, nested_array_data_view.size());
+  EXPECT_EQ(4, nested_array_data_view[1]);
+
+  std::vector<int32_t> vec;
+  ASSERT_TRUE(array_data_view.Read(1, &vec));
+  ASSERT_EQ(1u, vec.size());
+  EXPECT_EQ(2, vec[0]);
+}
+
+TEST_F(DataViewTest, StructArray) {
+  NestedStructPtr nested_struct(NestedStruct::New());
+  nested_struct->f_int32 = 42;
+
+  TestStructPtr obj(TestStruct::New());
+  obj->f_struct_array.push_back(std::move(nested_struct));
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<NestedStructDataView> array_data_view;
+  data_view.GetFStructArrayDataView(&array_data_view);
+
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(1u, array_data_view.size());
+
+  NestedStructDataView struct_data_view;
+  array_data_view.GetDataView(0, &struct_data_view);
+  ASSERT_FALSE(struct_data_view.is_null());
+  EXPECT_EQ(42, struct_data_view.f_int32());
+
+  NestedStructPtr nested_struct2;
+  ASSERT_TRUE(array_data_view.Read(0, &nested_struct2));
+  ASSERT_TRUE(nested_struct2);
+  EXPECT_EQ(42, nested_struct2->f_int32);
+}
+
+TEST_F(DataViewTest, Map) {
+  TestStructPtr obj(TestStruct::New());
+  obj->f_map["1"] = 1;
+  obj->f_map["2"] = 2;
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  MapDataView<StringDataView, int32_t> map_data_view;
+  data_view.GetFMapDataView(&map_data_view);
+
+  ASSERT_FALSE(map_data_view.is_null());
+  ASSERT_EQ(2u, map_data_view.size());
+
+  ASSERT_FALSE(map_data_view.keys().is_null());
+  ASSERT_EQ(2u, map_data_view.keys().size());
+
+  ASSERT_FALSE(map_data_view.values().is_null());
+  ASSERT_EQ(2u, map_data_view.values().size());
+
+  std::vector<std::string> keys;
+  ASSERT_TRUE(map_data_view.ReadKeys(&keys));
+  std::vector<int32_t> values;
+  ASSERT_TRUE(map_data_view.ReadValues(&values));
+
+  std::unordered_map<std::string, int32_t> map;
+  for (size_t i = 0; i < 2; ++i)
+    map[keys[i]] = values[i];
+
+  EXPECT_EQ(1, map["1"]);
+  EXPECT_EQ(2, map["2"]);
+}
+
+TEST_F(DataViewTest, UnionArray) {
+  TestUnionPtr union_ptr(TestUnion::New());
+  union_ptr->set_f_int32(1024);
+
+  TestStructPtr obj(TestStruct::New());
+  obj->f_union_array.push_back(std::move(union_ptr));
+
+  auto data_view_holder = SerializeTestStruct(std::move(obj));
+  auto& data_view = *data_view_holder->data_view;
+
+  ArrayDataView<TestUnionDataView> array_data_view;
+  data_view.GetFUnionArrayDataView(&array_data_view);
+  ASSERT_FALSE(array_data_view.is_null());
+  ASSERT_EQ(1u, array_data_view.size());
+
+  TestUnionDataView union_data_view;
+  array_data_view.GetDataView(0, &union_data_view);
+  ASSERT_FALSE(union_data_view.is_null());
+
+  TestUnionPtr union_ptr2;
+  ASSERT_TRUE(array_data_view.Read(0, &union_ptr2));
+  ASSERT_TRUE(union_ptr2->is_f_int32());
+  EXPECT_EQ(1024, union_ptr2->get_f_int32());
+}
+
+}  // namespace data_view
+}  // namespace test
+}  // namespace mojo
diff --git a/mojo/public/interfaces/bindings/OWNERS b/mojo/public/interfaces/bindings/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/mojo/public/interfaces/bindings/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index 635b615..a586ec8 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -18,6 +18,7 @@
     "scoping.mojom",
     "serialization_test_structs.mojom",
     "test_constants.mojom",
+    "test_data_view.mojom",
     "test_native_types.mojom",
     "test_structs.mojom",
     "test_sync_methods.mojom",
diff --git a/mojo/public/interfaces/bindings/tests/OWNERS b/mojo/public/interfaces/bindings/tests/OWNERS
index 08850f4..6c1f2fb 100644
--- a/mojo/public/interfaces/bindings/tests/OWNERS
+++ b/mojo/public/interfaces/bindings/tests/OWNERS
@@ -1,2 +1,6 @@
+per-file *.mojom=file://mojo/OWNERS
+
+# These mojom test files don't really require security review, but we need to
+# add these to please PRESUBMIT.
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/mojo/public/interfaces/bindings/tests/test_data_view.mojom b/mojo/public/interfaces/bindings/tests/test_data_view.mojom
new file mode 100644
index 0000000..1fe8c6a
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/test_data_view.mojom
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojo.test.data_view;
+
+enum TestEnum {
+  VALUE_0,
+  VALUE_1
+};
+
+interface TestInterface {
+  [Sync]
+  Echo(int32 value) => (int32 out_value);
+};
+
+struct NestedStruct {
+  int32 f_int32;
+};
+
+[Native]
+struct TestNativeStruct;
+
+union TestUnion {
+  bool f_bool;
+  int32 f_int32;
+};
+
+struct TestStruct {
+  string f_string;
+  NestedStruct? f_struct;
+  TestNativeStruct? f_native_struct;
+  array<bool> f_bool_array;
+  array<int32> f_int32_array;
+  array<TestEnum> f_enum_array;
+  array<TestInterface> f_interface_array;
+  array<array<int32>> f_nested_array;
+  array<NestedStruct> f_struct_array;
+  array<TestUnion> f_union_array;
+  map<string, int32> f_map;
+};
diff --git a/mojo/public/tools/bindings/BUILD.gn b/mojo/public/tools/bindings/BUILD.gn
index eeea5c5b..9d1e0fc 100644
--- a/mojo/public/tools/bindings/BUILD.gn
+++ b/mojo/public/tools/bindings/BUILD.gn
@@ -26,6 +26,7 @@
     "$mojom_generator_root/generators/cpp_templates/struct_macros.tmpl",
     "$mojom_generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl",
     "$mojom_generator_root/generators/cpp_templates/struct_serialization_definition.tmpl",
+    "$mojom_generator_root/generators/cpp_templates/union_data_view_declaration.tmpl",
     "$mojom_generator_root/generators/cpp_templates/union_declaration.tmpl",
     "$mojom_generator_root/generators/cpp_templates/union_definition.tmpl",
     "$mojom_generator_root/generators/cpp_templates/union_serialization_declaration.tmpl",
diff --git a/mojo/public/tools/bindings/bindings.gyp b/mojo/public/tools/bindings/bindings.gyp
index 0f00114..0b6860e 100644
--- a/mojo/public/tools/bindings/bindings.gyp
+++ b/mojo/public/tools/bindings/bindings.gyp
@@ -34,6 +34,7 @@
             'generators/cpp_templates/struct_macros.tmpl',
             'generators/cpp_templates/struct_serialization_declaration.tmpl',
             'generators/cpp_templates/struct_serialization_definition.tmpl',
+            'generators/cpp_templates/union_data_view_declaration.tmpl',
             'generators/cpp_templates/union_declaration.tmpl',
             'generators/cpp_templates/union_definition.tmpl',
             'generators/cpp_templates/union_serialization_declaration.tmpl',
diff --git a/mojo/public/tools/bindings/blink_bindings_configuration.gni b/mojo/public/tools/bindings/blink_bindings_configuration.gni
index ef19cc3c..5083f6b 100644
--- a/mojo/public/tools/bindings/blink_bindings_configuration.gni
+++ b/mojo/public/tools/bindings/blink_bindings_configuration.gni
@@ -9,6 +9,7 @@
 _typemap_imports = [
   "//mojo/public/cpp/bindings/tests/blink_typemaps.gni",
   "//third_party/WebKit/Source/platform/mojo/blink_typemaps.gni",
+  "//third_party/WebKit/public/blink_typemaps.gni",
 ]
 _typemaps = []
 
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index c4f3e07..2daf6e6 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -35,6 +35,17 @@
 {%-   endfor %}
 {%- endmacro %}
 
+{%- macro data_view_traits(kind) %}
+namespace mojo {
+namespace internal {
+template <>
+struct DataViewTraits<{{kind|get_qualified_name_for_kind}}DataView> {
+  using MojomType = {{kind|get_qualified_name_for_kind}}Ptr;
+};
+}  // namespace internal
+}  // namespace mojo
+{%- endmacro %}
+
 #ifndef {{header_guard}}
 #define {{header_guard}}
 
@@ -47,7 +58,7 @@
 
 #include "base/callback.h"
 #include "base/optional.h"
-#include "base/strings/string_piece.h"
+#include "mojo/public/cpp/bindings/array_data_view.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
 #include "mojo/public/cpp/bindings/associated_interface_request.h"
@@ -57,10 +68,13 @@
 #include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
 #include "mojo/public/cpp/bindings/lib/serialization.h"
 #include "mojo/public/cpp/bindings/map.h"
+#include "mojo/public/cpp/bindings/map_data_view.h"
 #include "mojo/public/cpp/bindings/message_filter.h"
 #include "mojo/public/cpp/bindings/native_enum.h"
 #include "mojo/public/cpp/bindings/native_struct.h"
+#include "mojo/public/cpp/bindings/native_struct_data_view.h"
 #include "mojo/public/cpp/bindings/no_interface.h"
+#include "mojo/public/cpp/bindings/string_data_view.h"
 #include "mojo/public/cpp/bindings/struct_ptr.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "{{variant_path}}-internal.h"
@@ -141,6 +155,7 @@
 {%  for struct in structs %}
 {%-   if struct|is_native_only_kind %}
 using {{struct.name}} = mojo::NativeStruct;
+using {{struct.name}}DataView = mojo::NativeStructDataView;
 using {{struct.name}}Ptr = mojo::NativeStructPtr;
 {%-   else %}
 class {{struct.name}};
@@ -156,6 +171,7 @@
 {#--- Union Forward Declarations -#}
 {%  for union in unions %}
 class {{union.name}};
+class {{union.name}}DataView;
 {%    if union|should_inline_union %}
 typedef mojo::InlinedStructPtr<{{union.name}}> {{union.name}}Ptr;
 {%    else %}
@@ -217,6 +233,11 @@
 {%    if struct|should_inline and not struct|is_native_only_kind %}
 {%      include "wrapper_class_declaration.tmpl" %}
 {%      include "struct_data_view_declaration.tmpl" %}
+
+{{namespace_end()}}
+{{data_view_traits(struct)}}
+{{namespace_begin()}}
+
 {%    endif %}
 {%- endfor %}
 
@@ -225,6 +246,12 @@
 {#--- Unions #}
 {%  for union in unions %}
 {%    include "wrapper_union_class_declaration.tmpl" %}
+{%    include "union_data_view_declaration.tmpl" %}
+
+{{namespace_end()}}
+{{data_view_traits(union)}}
+{{namespace_begin()}}
+
 {%- endfor %}
 
 {#--- Non-inlined structs #}
@@ -232,6 +259,11 @@
 {%    if not struct|should_inline and not struct|is_native_only_kind %}
 {%      include "wrapper_class_declaration.tmpl" %}
 {%      include "struct_data_view_declaration.tmpl" %}
+
+{{namespace_end()}}
+{{data_view_traits(struct)}}
+{{namespace_begin()}}
+
 {%    endif %}
 {%- endfor %}
 
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl
index 7c34939..7ba07147 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl
@@ -1,29 +1,40 @@
 class {{struct.name}}DataView {
  public:
+  {{struct.name}}DataView() {}
+
   {{struct.name}}DataView(
       internal::{{struct.name}}_Data* data,
       mojo::internal::SerializationContext* context);
 
+  bool is_null() const { return !data_; }
+
 {%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%-   set kind = pf.field.kind -%}
-{%-   set name = pf.field.name -%}
-{%-   if kind|is_struct_kind or kind|is_array_kind or kind|is_string_kind
-         or kind|is_map_kind %}
+{%-   set kind = pf.field.kind %}
+{%-   set name = pf.field.name %}
+{%-   if kind|is_object_kind %}
+  void Get{{name|under_to_camel}}DataView(
+      {{kind|cpp_data_view_type}}* output);
+
+{%-     if kind|is_union_kind %}
+  bool Read{{name|under_to_camel}}({{kind|cpp_wrapper_type}}* output);
+
+{%-     else %}
   template <typename UserType>
-  bool Read{{name|under_to_camel}}(UserType* value) {
-{%-  if pf.min_version != 0 %}
+  bool Read{{name|under_to_camel}}(UserType* output) {
+{%-       if pf.min_version != 0 %}
     auto pointer = data_->header_.version >= {{pf.min_version}}
                    ? data_->{{name}}.Get() : nullptr;
-{%-  else %}
+{%-       else %}
     auto pointer = data_->{{name}}.Get();
-{%-  endif %}
+{%-       endif %}
     return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
-        pointer, value, context_);
+        pointer, output, context_);
   }
+{%-     endif %}
 
 {%-   elif kind|is_enum_kind %}
   template <typename UserType>
-  bool Read{{name|under_to_camel}}(UserType* value) const {
+  bool Read{{name|under_to_camel}}(UserType* output) const {
 {%-     if pf.min_version != 0 %}
     auto data_value = data_->header_.version >= {{pf.min_version}}
                       ? data_->{{name}} : 0;
@@ -31,14 +42,11 @@
     auto data_value = data_->{{name}};
 {%-     endif %}
     return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
-        data_value, value);
+        data_value, output);
   }
 
   {{kind|get_qualified_name_for_kind}} {{name}}() const;
 
-{%-   elif kind|is_union_kind %}
-  bool Read{{name|under_to_camel}}({{kind|cpp_wrapper_type}}* value);
-
 {%-   elif kind|is_any_handle_or_interface_kind %}
   {{kind|cpp_wrapper_type}} Take{{name|under_to_camel}}();
 
@@ -47,7 +55,7 @@
 {%-   endif %}
 {%- endfor %}
  private:
-  internal::{{struct.name}}_Data* data_;
-  mojo::internal::SerializationContext* context_;
+  internal::{{struct.name}}_Data* data_ = nullptr;
+  mojo::internal::SerializationContext* context_ = nullptr;
 };
 
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl
index 2be92b3..175eb1e 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl
@@ -1,16 +1,49 @@
 {{struct.name}}DataView::{{struct.name}}DataView(
     internal::{{struct.name}}_Data*  data,
     mojo::internal::SerializationContext* context)
-    : data_(data), context_(context) {
-  DCHECK(data_);
-}
+    : data_(data), context_(context) {}
 
 {%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%-   set kind = pf.field.kind -%}
-{%-   set name = pf.field.name -%}
-{%-   if kind|is_struct_kind or kind|is_array_kind or kind|is_string_kind or
-         kind|is_map_kind %}
-{#-     Does nothing. They are already defined in the class declaration. #}
+{%-   set kind = pf.field.kind %}
+{%-   set name = pf.field.name %}
+
+{%-   if kind|is_object_kind %}
+{%-     if kind|is_union_kind %}
+void {{struct.name}}DataView::Get{{name|under_to_camel}}DataView(
+    {{kind|cpp_data_view_type}}* output) {
+{%-       if pf.min_version != 0 %}
+  auto pointer = data_->header_.version >= {{pf.min_version}}
+                 ? &data_->{{name}} : nullptr;
+{%-       else %}
+  auto pointer = &data_->{{name}};
+{%-       endif %}
+  *output = {{kind|cpp_data_view_type}}(pointer, context_);
+}
+
+bool {{struct.name}}DataView::Read{{name|under_to_camel}}(
+    {{kind|cpp_wrapper_type}}* output) {
+{%-       if pf.min_version != 0 %}
+  auto pointer = data_->header_.version >= {{pf.min_version}}
+                 ? &data_->{{name}} : nullptr;
+{%-       else %}
+  auto pointer = &data_->{{name}};
+{%-       endif %}
+  return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+      pointer, output, context_);
+}
+
+{%-     else %}
+void {{struct.name}}DataView::Get{{name|under_to_camel}}DataView(
+    {{kind|cpp_data_view_type}}* output) {
+{%-       if pf.min_version != 0 %}
+  auto pointer = data_->header_.version >= {{pf.min_version}}
+                 ? data_->{{name}}.Get() : nullptr;
+{%-       else %}
+  auto pointer = data_->{{name}}.Get();
+{%-       endif %}
+  *output = {{kind|cpp_data_view_type}}(pointer, context_);
+}
+{%-     endif %}
 
 {%-   elif kind|is_enum_kind %}
 {{kind|get_qualified_name_for_kind}} {{struct.name}}DataView::{{name}}() const {
@@ -21,19 +54,6 @@
   return static_cast<{{kind|get_qualified_name_for_kind}}>(data_->{{name}});
 }
 
-{%-   elif kind|is_union_kind %}
-bool {{struct.name}}DataView::Read{{name|under_to_camel}}(
-    {{kind|cpp_wrapper_type}}* value) {
-{%-     if pf.min_version != 0 %}
-    auto pointer = data_->header_.version >= {{pf.min_version}}
-                   ? &data_->{{name}} : nullptr;
-{%-     else %}
-    auto pointer = &data_->{{name}};
-{%-     endif %}
-  return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
-      pointer, value, context_);
-}
-
 {%-   elif kind|is_any_handle_or_interface_kind %}
 {{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() {
   {{kind|cpp_wrapper_type}} result;
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl
new file mode 100644
index 0000000..d9ab16a
--- /dev/null
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl
@@ -0,0 +1,17 @@
+class {{union.name}}DataView {
+ public:
+  {{union.name}}DataView() {}
+  
+  {{union.name}}DataView(
+      internal::{{union.name}}_Data* data,
+      mojo::internal::SerializationContext* context)
+      : data_(data) {}
+
+  bool is_null() const { return !data_; }
+ 
+  // TODO(yzshen): Union data view is not yet supported.
+
+ private:
+  internal::{{union.name}}_Data* data_ = nullptr;
+};
+
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
index f62bc72..4783d25 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
@@ -1,5 +1,6 @@
 class {{union.name}} {
  public:
+  using DataView = {{union.name}}DataView;
   using Data_ = internal::{{union.name}}_Data;
   using Tag = Data_::{{union.name}}_Tag;
 
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 79b3d3b0..f4daef8 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -242,6 +242,20 @@
   return (cpp_wrapper_type if ShouldPassParamByValue(kind)
                            else "const %s&" % cpp_wrapper_type)
 
+def GetCppDataViewType(kind):
+  if mojom.IsEnumKind(kind):
+    return GetNameForKind(kind)
+  if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
+    return "%sDataView" % GetNameForKind(kind)
+  if mojom.IsArrayKind(kind):
+    return "mojo::ArrayDataView<%s>" % GetCppDataViewType(kind.kind)
+  if mojom.IsMapKind(kind):
+    return ("mojo::MapDataView<%s, %s>" % (GetCppDataViewType(kind.key_kind),
+                                           GetCppDataViewType(kind.value_kind)))
+  if mojom.IsStringKind(kind):
+    return "mojo::StringDataView"
+  return GetCppWrapperType(kind)
+
 def GetCppFieldType(kind):
   if mojom.IsStructKind(kind):
     return ("mojo::internal::Pointer<%s>" %
@@ -412,6 +426,7 @@
   cpp_filters = {
     "constant_value": ConstantValue,
     "cpp_wrapper_param_type": GetCppWrapperParamType,
+    "cpp_data_view_type": GetCppDataViewType,
     "cpp_field_type": GetCppFieldType,
     "cpp_union_field_type": GetCppUnionFieldType,
     "cpp_pod_type": GetCppPodType,
diff --git a/net/BUILD.gn b/net/BUILD.gn
index ef793f70..7dafe36 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -8,13 +8,13 @@
 import("//build/config/crypto.gni")
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
-import("//build_overrides/v8.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
 import("//third_party/icu/config.gni")
 import("//third_party/protobuf/proto_library.gni")
 import("//tools/grit/grit_rule.gni")
 import("//url/features.gni")
+import("//v8/gni/v8.gni")
 
 if (is_android) {
   import("//build/config/android/config.gni")
@@ -629,15 +629,15 @@
     "//url",
   ]
 
-  deps = [
-    ":test_support_bundle_data",
-  ]
+  deps = []
 
   data = [
     "data/",
   ]
 
-  if (!is_ios) {
+  if (is_ios) {
+    deps += [ ":test_support_bundle_data" ]
+  } else {
     public_deps += [ "//third_party/protobuf:py_proto" ]
   }
 
@@ -1339,7 +1339,6 @@
     ":balsa",
     ":extras",
     ":net",
-    ":net_unittests_bundle_data",
     ":simple_quic_tools",
     ":stale_while_revalidate_experiment_domains",
     ":test_support",
@@ -1546,6 +1545,8 @@
       "socket/unix_domain_client_socket_posix_unittest.cc",
       "socket/unix_domain_server_socket_posix_unittest.cc",
     ]
+
+    bundle_deps = [ ":net_unittests_bundle_data" ]
   }
 
   # Unit tests that aren't supported by the current ICU alternatives on Android.
diff --git a/net/OWNERS b/net/OWNERS
index 8282dad..7038b93 100644
--- a/net/OWNERS
+++ b/net/OWNERS
@@ -20,3 +20,6 @@
 per-file *.isolate=maruel@chromium.org
 per-file *.isolate=tandrii@chromium.org
 per-file *.isolate=vadimsh@chromium.org
+
+per-file BUILD.gn=bengr@chromium.org
+per-file net.gyp*=bengr@chromium.org
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
index cc33590..7c38979 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
@@ -93,7 +93,7 @@
      * auto-detection has been enabled, returns NetId.INVALID otherwise.
      */
     @CalledByNative
-    public int getCurrentDefaultNetId() {
+    public long getCurrentDefaultNetId() {
         return mAutoDetector == null ? NetId.INVALID : mAutoDetector.getDefaultNetId();
     }
 
@@ -106,8 +106,8 @@
      * been enabled.
      */
     @CalledByNative
-    public int[] getCurrentNetworksAndTypes() {
-        return mAutoDetector == null ? new int[0] : mAutoDetector.getNetworksAndTypes();
+    public long[] getCurrentNetworksAndTypes() {
+        return mAutoDetector == null ? new long[0] : mAutoDetector.getNetworksAndTypes();
     }
 
     /**
@@ -198,19 +198,19 @@
                                 updateCurrentMaxBandwidth(maxBandwidthMbps);
                             }
                             @Override
-                            public void onNetworkConnect(int netId, int connectionType) {
+                            public void onNetworkConnect(long netId, int connectionType) {
                                 notifyObserversOfNetworkConnect(netId, connectionType);
                             }
                             @Override
-                            public void onNetworkSoonToDisconnect(int netId) {
+                            public void onNetworkSoonToDisconnect(long netId) {
                                 notifyObserversOfNetworkSoonToDisconnect(netId);
                             }
                             @Override
-                            public void onNetworkDisconnect(int netId) {
+                            public void onNetworkDisconnect(long netId) {
                                 notifyObserversOfNetworkDisconnect(netId);
                             }
                             @Override
-                            public void purgeActiveNetworkList(int[] activeNetIds) {
+                            public void purgeActiveNetworkList(long[] activeNetIds) {
                                 notifyObserversToPurgeActiveNetworkList(activeNetIds);
                             }
                         },
@@ -249,35 +249,35 @@
 
     // For testing, pretend a network connected.
     @CalledByNative
-    public static void fakeNetworkConnected(int netId, int connectionType) {
+    public static void fakeNetworkConnected(long netId, int connectionType) {
         setAutoDetectConnectivityState(false);
         getInstance().notifyObserversOfNetworkConnect(netId, connectionType);
     }
 
     // For testing, pretend a network will soon disconnect.
     @CalledByNative
-    public static void fakeNetworkSoonToBeDisconnected(int netId) {
+    public static void fakeNetworkSoonToBeDisconnected(long netId) {
         setAutoDetectConnectivityState(false);
         getInstance().notifyObserversOfNetworkSoonToDisconnect(netId);
     }
 
     // For testing, pretend a network disconnected.
     @CalledByNative
-    public static void fakeNetworkDisconnected(int netId) {
+    public static void fakeNetworkDisconnected(long netId) {
         setAutoDetectConnectivityState(false);
         getInstance().notifyObserversOfNetworkDisconnect(netId);
     }
 
     // For testing, pretend a network lists should be purged.
     @CalledByNative
-    public static void fakePurgeActiveNetworkList(int[] activeNetIds) {
+    public static void fakePurgeActiveNetworkList(long[] activeNetIds) {
         setAutoDetectConnectivityState(false);
         getInstance().notifyObserversToPurgeActiveNetworkList(activeNetIds);
     }
 
     // For testing, pretend a default network changed.
     @CalledByNative
-    public static void fakeDefaultNetwork(int netId, int connectionType) {
+    public static void fakeDefaultNetwork(long netId, int connectionType) {
         setAutoDetectConnectivityState(false);
         getInstance().notifyObserversOfConnectionTypeChange(connectionType, netId);
     }
@@ -311,7 +311,7 @@
         notifyObserversOfConnectionTypeChange(newConnectionType, getCurrentDefaultNetId());
     }
 
-    private void notifyObserversOfConnectionTypeChange(int newConnectionType, int defaultNetId) {
+    private void notifyObserversOfConnectionTypeChange(int newConnectionType, long defaultNetId) {
         for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
             nativeNotifyConnectionTypeChanged(
                     nativeChangeNotifier, newConnectionType, defaultNetId);
@@ -333,7 +333,7 @@
     /**
      * Alerts all observers of a network connect.
      */
-    void notifyObserversOfNetworkConnect(int netId, int connectionType) {
+    void notifyObserversOfNetworkConnect(long netId, int connectionType) {
         for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
             nativeNotifyOfNetworkConnect(nativeChangeNotifier, netId, connectionType);
         }
@@ -342,7 +342,7 @@
     /**
      * Alerts all observers of a network soon to be disconnected.
      */
-    void notifyObserversOfNetworkSoonToDisconnect(int netId) {
+    void notifyObserversOfNetworkSoonToDisconnect(long netId) {
         for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
             nativeNotifyOfNetworkSoonToDisconnect(nativeChangeNotifier, netId);
         }
@@ -351,7 +351,7 @@
     /**
      * Alerts all observers of a network disconnect.
      */
-    void notifyObserversOfNetworkDisconnect(int netId) {
+    void notifyObserversOfNetworkDisconnect(long netId) {
         for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
             nativeNotifyOfNetworkDisconnect(nativeChangeNotifier, netId);
         }
@@ -363,7 +363,7 @@
      * issued if a period elapsed where disconnected notifications may have
      * been missed, and acts to keep cached lists of active networks accurate.
      */
-    void notifyObserversToPurgeActiveNetworkList(int[] activeNetIds) {
+    void notifyObserversToPurgeActiveNetworkList(long[] activeNetIds) {
         for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
             nativeNotifyPurgeActiveNetworkList(nativeChangeNotifier, activeNetIds);
         }
@@ -393,22 +393,23 @@
 
     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
     private native void nativeNotifyConnectionTypeChanged(
-            long nativePtr, int newConnectionType, int defaultNetId);
+            long nativePtr, int newConnectionType, long defaultNetId);
 
     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
     private native void nativeNotifyMaxBandwidthChanged(long nativePtr, double maxBandwidthMbps);
 
     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
-    private native void nativeNotifyOfNetworkConnect(long nativePtr, int netId, int connectionType);
+    private native void nativeNotifyOfNetworkConnect(
+            long nativePtr, long netId, int connectionType);
 
     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
-    private native void nativeNotifyOfNetworkSoonToDisconnect(long nativePtr, int netId);
+    private native void nativeNotifyOfNetworkSoonToDisconnect(long nativePtr, long netId);
 
     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
-    private native void nativeNotifyOfNetworkDisconnect(long nativePtr, int netId);
+    private native void nativeNotifyOfNetworkDisconnect(long nativePtr, long netId);
 
     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
-    private native void nativeNotifyPurgeActiveNetworkList(long nativePtr, int[] activeNetIds);
+    private native void nativeNotifyPurgeActiveNetworkList(long nativePtr, long[] activeNetIds);
 
     private static native double nativeGetMaxBandwidthForConnectionSubtype(int subtype);
 
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
index 352fc8f..8eb6087 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
@@ -201,7 +201,7 @@
          * Only callable on Lollipop and newer releases.
          */
         @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-        int getDefaultNetId() {
+        long getDefaultNetId() {
             // Android Lollipop had no API to get the default network; only an
             // API to return the NetworkInfo for the default network. To
             // determine the default network one can find the network with
@@ -211,7 +211,7 @@
                 return NetId.INVALID;
             }
             final Network[] networks = getAllNetworksFiltered(this, null);
-            int defaultNetId = NetId.INVALID;
+            long defaultNetId = NetId.INVALID;
             for (Network network : networks) {
                 final NetworkInfo networkInfo = getNetworkInfo(network);
                 if (networkInfo != null
@@ -381,7 +381,7 @@
             if (makeVpnDefault) {
                 mVpnInPlace = network;
             }
-            final int netId = networkToNetId(network);
+            final long netId = networkToNetId(network);
             final int connectionType =
                     getCurrentConnectionType(mConnectivityManagerDelegate.getNetworkState(network));
             ThreadUtils.postOnUiThread(new Runnable() {
@@ -392,7 +392,7 @@
                         // Make VPN the default network.
                         mObserver.onConnectionTypeChanged(connectionType);
                         // Purge all other networks as they're inaccessible to Chrome now.
-                        mObserver.purgeActiveNetworkList(new int[] {netId});
+                        mObserver.purgeActiveNetworkList(new long[] {netId});
                     }
                 }
             });
@@ -406,7 +406,7 @@
             }
             // A capabilities change may indicate the ConnectionType has changed,
             // so forward the new ConnectionType along to observer.
-            final int netId = networkToNetId(network);
+            final long netId = networkToNetId(network);
             final int connectionType =
                     getCurrentConnectionType(mConnectivityManagerDelegate.getNetworkState(network));
             ThreadUtils.postOnUiThread(new Runnable() {
@@ -422,7 +422,7 @@
             if (ignoreConnectedNetwork(network, null)) {
                 return;
             }
-            final int netId = networkToNetId(network);
+            final long netId = networkToNetId(network);
             ThreadUtils.postOnUiThread(new Runnable() {
                 @Override
                 public void run() {
@@ -536,7 +536,7 @@
          * connectionType is the type of the network; a member of
          * ConnectionType. Only called on Android L and above.
          */
-        public void onNetworkConnect(int netId, int connectionType);
+        public void onNetworkConnect(long netId, int connectionType);
         /**
          * Called when device determines the connection to the network with
          * NetID netId is no longer preferred, for example when a device
@@ -545,12 +545,12 @@
          * the network in 30s allowing network communications on that network
          * to wrap up. Only called on Android L and above.
          */
-        public void onNetworkSoonToDisconnect(int netId);
+        public void onNetworkSoonToDisconnect(long netId);
         /**
          * Called when device disconnects from network with NetID netId.
          * Only called on Android L and above.
          */
-        public void onNetworkDisconnect(int netId);
+        public void onNetworkDisconnect(long netId);
         /**
          * Called to cause a purge of cached lists of active networks, of any
          * networks not in the accompanying list of active networks. This is
@@ -558,7 +558,7 @@
          * been missed, and acts to keep cached lists of active networks
          * accurate. Only called on Android L and above.
          */
-        public void purgeActiveNetworkList(int[] activeNetIds);
+        public void purgeActiveNetworkList(long[] activeNetIds);
     }
 
     /**
@@ -653,7 +653,7 @@
             // while mNetworkCallback was unregistered.
             final Network[] networks = getAllNetworksFiltered(mConnectivityManagerDelegate, null);
             // Convert Networks to NetIDs.
-            final int[] netIds = new int[networks.length];
+            final long[] netIds = new long[networks.length];
             for (int i = 0; i < networks.length; i++) {
                 netIds[i] = networkToNetId(networks[i]);
             }
@@ -721,12 +721,12 @@
      * Only available on Lollipop and newer releases and when auto-detection has
      * been enabled.
      */
-    public int[] getNetworksAndTypes() {
+    public long[] getNetworksAndTypes() {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            return new int[0];
+            return new long[0];
         }
         final Network networks[] = getAllNetworksFiltered(mConnectivityManagerDelegate, null);
-        final int networksAndTypes[] = new int[networks.length * 2];
+        final long networksAndTypes[] = new long[networks.length * 2];
         int index = 0;
         for (Network network : networks) {
             networksAndTypes[index++] = networkToNetId(network);
@@ -742,7 +742,7 @@
      * Only implemented on Lollipop and newer releases, returns NetId.INVALID
      * when not implemented.
      */
-    public int getDefaultNetId() {
+    public long getDefaultNetId() {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
             return NetId.INVALID;
         }
@@ -915,14 +915,20 @@
     }
 
     /**
-     * Extracts NetID of network. Only available on Lollipop and newer releases.
+     * Extracts NetID of Network on Lollipop and NetworkHandle (which is munged NetID) on
+     * Marshmallow and newer releases. Only available on Lollipop and newer releases.
      */
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     @VisibleForTesting
-    static int networkToNetId(Network network) {
-        // NOTE(pauljensen): This depends on Android framework implementation details.
-        // Fortunately this functionality is unlikely to ever change.
-        // TODO(pauljensen): When we update to Android M SDK, use Network.getNetworkHandle().
-        return Integer.parseInt(network.toString());
+    static long networkToNetId(Network network) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return network.getNetworkHandle();
+        } else {
+            // NOTE(pauljensen): This depends on Android framework implementation details. These
+            // details cannot change because Lollipop is long since released.
+            // NetIDs are only 16-bit so use parseInt. This function returns a long because
+            // getNetworkHandle() returns a long.
+            return Integer.parseInt(network.toString());
+        }
     }
 }
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
index bd89347..a95b6f2 100644
--- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
+++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
@@ -105,6 +105,16 @@
         }
     }
 
+    private static void triggerApplicationStateChange(
+            final RegistrationPolicyApplicationStatus policy, final int applicationState) {
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                policy.onApplicationStateChange(applicationState);
+            }
+        });
+    }
+
     /**
      * Mocks out calls to the ConnectivityManager.
      */
@@ -149,7 +159,7 @@
 
         @Override
         protected NetworkCapabilities getNetworkCapabilities(Network network) {
-            int netId = NetworkChangeNotifierAutoDetect.networkToNetId(network);
+            long netId = NetworkChangeNotifierAutoDetect.networkToNetId(network);
             for (MockNetwork mockNetwork : mMockNetworks) {
                 if (netId == mockNetwork.mNetId) {
                     return mockNetwork.getCapabilities();
@@ -160,7 +170,7 @@
 
         @Override
         protected boolean vpnAccessible(Network network) {
-            int netId = NetworkChangeNotifierAutoDetect.networkToNetId(network);
+            long netId = NetworkChangeNotifierAutoDetect.networkToNetId(network);
             for (MockNetwork mockNetwork : mMockNetworks) {
                 if (netId == mockNetwork.mNetId) {
                     return mockNetwork.mVpnAccessible;
@@ -181,7 +191,7 @@
         // Dummy implementations to avoid NullPointerExceptions in default implementations:
 
         @Override
-        public int getDefaultNetId() {
+        public long getDefaultNetId() {
             return NetId.INVALID;
         }
 
@@ -278,13 +288,13 @@
         // The type of change.
         final ChangeType mChangeType;
         // The network identifier of the network changing.
-        final int mNetId;
+        final long mNetId;
 
         /**
          * @param changeType the type of change.
          * @param netId the network identifier of the network changing.
          */
-        ChangeInfo(ChangeType changeType, int netId) {
+        ChangeInfo(ChangeType changeType, long netId) {
             mChangeType = changeType;
             mNetId = netId;
         }
@@ -303,25 +313,25 @@
         public void onMaxBandwidthChanged(double maxBandwidthMbps) {}
 
         @Override
-        public void onNetworkConnect(int netId, int connectionType) {
+        public void onNetworkConnect(long netId, int connectionType) {
             ThreadUtils.assertOnUiThread();
             mChanges.add(new ChangeInfo(ChangeType.CONNECT, netId));
         }
 
         @Override
-        public void onNetworkSoonToDisconnect(int netId) {
+        public void onNetworkSoonToDisconnect(long netId) {
             ThreadUtils.assertOnUiThread();
             mChanges.add(new ChangeInfo(ChangeType.SOON_TO_DISCONNECT, netId));
         }
 
         @Override
-        public void onNetworkDisconnect(int netId) {
+        public void onNetworkDisconnect(long netId) {
             ThreadUtils.assertOnUiThread();
             mChanges.add(new ChangeInfo(ChangeType.DISCONNECT, netId));
         }
 
         @Override
-        public void purgeActiveNetworkList(int[] activeNetIds) {
+        public void purgeActiveNetworkList(long[] activeNetIds) {
             ThreadUtils.assertOnUiThread();
             if (activeNetIds.length == 1) {
                 mChanges.add(new ChangeInfo(ChangeType.PURGE_LIST, activeNetIds[0]));
@@ -462,13 +472,13 @@
     public void testNetworkChangeNotifierRegistersForIntents() throws InterruptedException {
         RegistrationPolicyApplicationStatus policy =
                 (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy();
-        policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
         assertTrue(mReceiver.isReceiverRegisteredForTesting());
 
-        policy.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES);
         assertFalse(mReceiver.isReceiverRegisteredForTesting());
 
-        policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
         assertTrue(mReceiver.isReceiverRegisteredForTesting());
     }
 
@@ -606,14 +616,14 @@
         // Pretend we got moved to the background.
         final RegistrationPolicyApplicationStatus policy =
                 (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy();
-        policy.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES);
         // Change the state.
         mConnectivityDelegate.setActiveNetworkExists(true);
         mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
         // The NetworkChangeNotifierAutoDetect doesn't receive any notification while we are in the
         // background, but when we get back to the foreground the state changed should be detected
         // and a notification sent.
-        policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
         assertTrue(observer.hasReceivedNotification());
     }
 
@@ -766,7 +776,7 @@
             }
 
             @Override
-            int getDefaultNetId() {
+            long getDefaultNetId() {
                 return Integer.parseInt(mNetworks[1].toString());
             }
 
@@ -840,7 +850,7 @@
 
         RegistrationPolicyApplicationStatus policy =
                 (RegistrationPolicyApplicationStatus) ncn.getRegistrationPolicy();
-        policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
         assertTrue(ncn.isReceiverRegisteredForTesting());
 
         // Find NetworkChangeNotifierAutoDetect's NetworkCallback, which should have been registered
@@ -865,9 +875,9 @@
 
         // Simulate app backgrounding then foregrounding.
         assertTrue(ncn.isReceiverRegisteredForTesting());
-        policy.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES);
         assertFalse(ncn.isReceiverRegisteredForTesting());
-        policy.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
+        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
         assertTrue(ncn.isReceiverRegisteredForTesting());
         // Verify network list purged.
         observer.assertLastChange(ChangeType.PURGE_LIST, NetId.INVALID);
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
index b05e3d8..d3da5ed0 100644
--- a/net/android/network_change_notifier_delegate_android.cc
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -47,16 +47,16 @@
 }  // namespace
 
 // static
-void NetworkChangeNotifierDelegateAndroid::JavaIntArrayToNetworkMap(
+void NetworkChangeNotifierDelegateAndroid::JavaLongArrayToNetworkMap(
     JNIEnv* env,
-    jintArray int_array,
+    jlongArray long_array,
     NetworkMap* network_map) {
-  std::vector<int> int_list;
-  base::android::JavaIntArrayToIntVector(env, int_array, &int_list);
+  std::vector<int64_t> int64_list;
+  base::android::JavaLongArrayToInt64Vector(env, long_array, &int64_list);
   network_map->clear();
-  for (auto i = int_list.begin(); i != int_list.end(); ++i) {
+  for (auto i = int64_list.begin(); i != int64_list.end(); ++i) {
     NetworkChangeNotifier::NetworkHandle network_handle = *i;
-    CHECK(++i != int_list.end());
+    CHECK(++i != int64_list.end());
     (*network_map)[network_handle] = static_cast<ConnectionType>(*i);
   }
 }
@@ -87,10 +87,10 @@
   SetCurrentDefaultNetwork(Java_NetworkChangeNotifier_getCurrentDefaultNetId(
       env, java_network_change_notifier_.obj()));
   NetworkMap network_map;
-  ScopedJavaLocalRef<jintArray> networks_and_types =
+  ScopedJavaLocalRef<jlongArray> networks_and_types =
       Java_NetworkChangeNotifier_getCurrentNetworksAndTypes(
           env, java_network_change_notifier_.obj());
-  JavaIntArrayToNetworkMap(env, networks_and_types.obj(), &network_map);
+  JavaLongArrayToNetworkMap(env, networks_and_types.obj(), &network_map);
   SetCurrentNetworksAndTypes(network_map);
 }
 
@@ -155,7 +155,7 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     jint new_connection_type,
-    jint default_netid) {
+    jlong default_netid) {
   DCHECK(thread_checker_.CalledOnValidThread());
   const ConnectionType actual_connection_type = ConvertConnectionType(
       new_connection_type);
@@ -204,7 +204,7 @@
 void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkConnect(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    jint net_id,
+    jlong net_id,
     jint connection_type) {
   DCHECK(thread_checker_.CalledOnValidThread());
   NetworkHandle network = net_id;
@@ -228,7 +228,7 @@
 void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkSoonToDisconnect(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    jint net_id) {
+    jlong net_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
   NetworkHandle network = net_id;
   {
@@ -242,7 +242,7 @@
 void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    jint net_id) {
+    jlong net_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
   NetworkHandle network = net_id;
   {
@@ -258,11 +258,11 @@
 void NetworkChangeNotifierDelegateAndroid::NotifyPurgeActiveNetworkList(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jintArray>& active_networks) {
+    const JavaParamRef<jlongArray>& active_networks) {
   DCHECK(thread_checker_.CalledOnValidThread());
   NetworkList active_network_list;
-  base::android::JavaIntArrayToIntVector(env, active_networks,
-                                         &active_network_list);
+  base::android::JavaLongArrayToInt64Vector(env, active_networks,
+                                            &active_network_list);
   NetworkList disconnected_networks;
   {
     base::AutoLock auto_lock(connection_lock_);
@@ -355,7 +355,7 @@
     NetworkChangeNotifier::NetworkList networks) {
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_NetworkChangeNotifier_fakePurgeActiveNetworkList(
-      env, base::android::ToJavaIntArray(env, networks).obj());
+      env, base::android::ToJavaLongArray(env, networks).obj());
 }
 
 void NetworkChangeNotifierDelegateAndroid::FakeDefaultNetwork(
diff --git a/net/android/network_change_notifier_delegate_android.h b/net/android/network_change_notifier_delegate_android.h
index 6e710a0c..8b6d0e8 100644
--- a/net/android/network_change_notifier_delegate_android.h
+++ b/net/android/network_change_notifier_delegate_android.h
@@ -54,7 +54,7 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
       jint new_connection_type,
-      jint default_netid);
+      jlong default_netid);
   jint GetConnectionType(JNIEnv* env, jobject obj) const;
 
   // Called from NetworkChangeNotifier.java on the JNI thread whenever
@@ -77,20 +77,20 @@
   // NetworkChangeNotifierAutoDetect.Observer functions of the same names.
   void NotifyOfNetworkConnect(JNIEnv* env,
                               const base::android::JavaParamRef<jobject>& obj,
-                              jint net_id,
+                              jlong net_id,
                               jint connection_type);
   void NotifyOfNetworkSoonToDisconnect(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
-      jint net_id);
+      jlong net_id);
   void NotifyOfNetworkDisconnect(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
-      jint net_id);
+      jlong net_id);
   void NotifyPurgeActiveNetworkList(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
-      const base::android::JavaParamRef<jintArray>& active_networks);
+      const base::android::JavaParamRef<jlongArray>& active_networks);
 
   // These methods can be called on any thread. Note that the provided observer
   // will be notified on the thread AddObserver() is called on.
@@ -119,11 +119,11 @@
   // Map of active connected networks and their connection type.
   typedef std::map<NetworkHandle, ConnectionType> NetworkMap;
 
-  // Converts a Java int[] into a NetworkMap. Expects int[] to contain
+  // Converts a Java long[] into a NetworkMap. Expects long[] to contain
   // repeated instances of: NetworkHandle, ConnectionType
-  static void JavaIntArrayToNetworkMap(JNIEnv* env,
-                                       jintArray int_array,
-                                       NetworkMap* network_map);
+  static void JavaLongArrayToNetworkMap(JNIEnv* env,
+                                        jlongArray long_array,
+                                        NetworkMap* network_map);
 
   // Setters that grab appropriate lock.
   void SetCurrentConnectionType(ConnectionType connection_type);
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index aafee7a2..27a798d 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -211,8 +211,11 @@
   // example an association with a particular WiFi network with a particular
   // SSID or a connection to particular cellular network.
   // The meaning of this handle is target-dependent. On Android NetworkHandles
-  // are equivalent to the framework's concept of NetIDs (e.g. Network.netId).
-  typedef int32_t NetworkHandle;
+  // are equivalent to:
+  //   On Lollipop, the framework's concept of NetIDs (e.g. Network.netId), and
+  //   On Marshmallow and newer releases, network handles
+  //           (e.g. Network.getNetworkHandle()).
+  typedef int64_t NetworkHandle;
 
   // A list of networks.
   typedef std::vector<NetworkHandle> NetworkList;
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index d117d5e..4ac9e88 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -125,34 +125,9 @@
       httponly_(false) {
 }
 
-CanonicalCookie::CanonicalCookie(const GURL& url,
-                                 const std::string& name,
-                                 const std::string& value,
-                                 const std::string& domain,
-                                 const std::string& path,
-                                 const base::Time& creation,
-                                 const base::Time& expiration,
-                                 const base::Time& last_access,
-                                 bool secure,
-                                 bool httponly,
-                                 CookieSameSite same_site,
-                                 CookiePriority priority)
-    : name_(name),
-      value_(value),
-      domain_(domain),
-      path_(path),
-      creation_date_(creation),
-      expiry_date_(expiration),
-      last_access_date_(last_access),
-      secure_(secure),
-      httponly_(httponly),
-      same_site_(same_site),
-      priority_(priority) {}
-
 CanonicalCookie::CanonicalCookie(const CanonicalCookie& other) = default;
 
-CanonicalCookie::~CanonicalCookie() {
-}
+CanonicalCookie::~CanonicalCookie() {}
 
 // static
 std::string CanonicalCookie::CanonPath(const GURL& url,
@@ -480,6 +455,30 @@
   return Priority() < other.Priority();
 }
 
+CanonicalCookie::CanonicalCookie(const GURL& url,
+                                 const std::string& name,
+                                 const std::string& value,
+                                 const std::string& domain,
+                                 const std::string& path,
+                                 const base::Time& creation,
+                                 const base::Time& expiration,
+                                 const base::Time& last_access,
+                                 bool secure,
+                                 bool httponly,
+                                 CookieSameSite same_site,
+                                 CookiePriority priority)
+    : name_(name),
+      value_(value),
+      domain_(domain),
+      path_(path),
+      creation_date_(creation),
+      expiry_date_(expiration),
+      last_access_date_(last_access),
+      secure_(secure),
+      httponly_(httponly),
+      same_site_(same_site),
+      priority_(priority) {}
+
 // static
 CanonicalCookie::CookiePrefix CanonicalCookie::GetCookiePrefix(
     const std::string& name) {
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h
index bdad3bb..53df35e 100644
--- a/net/cookies/canonical_cookie.h
+++ b/net/cookies/canonical_cookie.h
@@ -23,25 +23,7 @@
 
 class NET_EXPORT CanonicalCookie {
  public:
-  // These constructors do no validation or canonicalization of their inputs;
-  // the resulting CanonicalCookies should not be relied on to be canonical
-  // unless the caller has done appropriate validation and canonicalization
-  // themselves.
   CanonicalCookie();
-  // TODO(mmenke): Remove |url|, as it's not used.
-  CanonicalCookie(const GURL& url,
-                  const std::string& name,
-                  const std::string& value,
-                  const std::string& domain,
-                  const std::string& path,
-                  const base::Time& creation,
-                  const base::Time& expiration,
-                  const base::Time& last_access,
-                  bool secure,
-                  bool httponly,
-                  CookieSameSite same_site,
-                  CookiePriority priority);
-
   CanonicalCookie(const CanonicalCookie& other);
 
   ~CanonicalCookie();
@@ -182,6 +164,24 @@
     COOKIE_PREFIX_LAST
   };
 
+  // This constructor does not validate or canonicalize their inputs;
+  // the resulting CanonicalCookies should not be relied on to be canonical
+  // unless the caller has done appropriate validation and canonicalization
+  // themselves.
+  // TODO(mmenke): Remove |url|, as it's not used.
+  CanonicalCookie(const GURL& url,
+                  const std::string& name,
+                  const std::string& value,
+                  const std::string& domain,
+                  const std::string& path,
+                  const base::Time& creation,
+                  const base::Time& expiration,
+                  const base::Time& last_access,
+                  bool secure,
+                  bool httponly,
+                  CookieSameSite same_site,
+                  CookiePriority priority);
+
   // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
   // applies to the given cookie |name|.
   static CookiePrefix GetCookiePrefix(const std::string& name);
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index a523263..b6bff7f 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -18,28 +18,28 @@
   GURL url("http://www.example.com/test");
   base::Time current_time = base::Time::Now();
 
-  CanonicalCookie cookie(url, "A", "2", "www.example.com", "/test",
-                         current_time, base::Time(), current_time, false, false,
-                         CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT);
-  EXPECT_EQ("A", cookie.Name());
-  EXPECT_EQ("2", cookie.Value());
-  EXPECT_EQ("www.example.com", cookie.Domain());
-  EXPECT_EQ("/test", cookie.Path());
-  EXPECT_FALSE(cookie.IsSecure());
-  EXPECT_FALSE(cookie.IsHttpOnly());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie.SameSite());
+  std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
+      url, "A", "2", std::string(), "/test", current_time, base::Time(), false,
+      false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+  EXPECT_EQ("A", cookie->Name());
+  EXPECT_EQ("2", cookie->Value());
+  EXPECT_EQ("www.example.com", cookie->Domain());
+  EXPECT_EQ("/test", cookie->Path());
+  EXPECT_FALSE(cookie->IsSecure());
+  EXPECT_FALSE(cookie->IsHttpOnly());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
 
-  CanonicalCookie cookie2(url, "A", "2", std::string(), std::string(),
-                          current_time, base::Time(), current_time, false,
-                          false, CookieSameSite::DEFAULT_MODE,
-                          COOKIE_PRIORITY_DEFAULT);
-  EXPECT_EQ("A", cookie2.Name());
-  EXPECT_EQ("2", cookie2.Value());
-  EXPECT_EQ("", cookie2.Domain());
-  EXPECT_EQ("", cookie2.Path());
-  EXPECT_FALSE(cookie2.IsSecure());
-  EXPECT_FALSE(cookie2.IsHttpOnly());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2.SameSite());
+  std::unique_ptr<CanonicalCookie> cookie2(CanonicalCookie::Create(
+      url, "A", "2", ".www.example.com", std::string(), current_time,
+      base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false,
+      COOKIE_PRIORITY_DEFAULT));
+  EXPECT_EQ("A", cookie2->Name());
+  EXPECT_EQ("2", cookie2->Value());
+  EXPECT_EQ(".www.example.com", cookie2->Domain());
+  EXPECT_EQ("/", cookie2->Path());
+  EXPECT_FALSE(cookie2->IsSecure());
+  EXPECT_FALSE(cookie2->IsHttpOnly());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2->SameSite());
 }
 
 TEST(CanonicalCookieTest, Create) {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 39784fe..fb2b798 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -510,6 +510,10 @@
 
   quic_connection_error_ = stream_->connection_error();
   ResetStream();
+  if (in_loop_) {
+    // If already in DoLoop(), |callback_| will be handled when DoLoop() exits.
+    return;
+  }
   if (!callback_.is_null()) {
     DoCallback(response_status_);
   }
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 8f76a7f..11ae2cb 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -144,6 +144,26 @@
   DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
 };
 
+// A Callback that deletes the QuicHttpStream.
+class DeleteStreamCallback : public TestCompletionCallbackBase {
+ public:
+  DeleteStreamCallback(std::unique_ptr<QuicHttpStream> stream)
+      : stream_(std::move(stream)),
+        callback_(base::Bind(&DeleteStreamCallback::DeleteStream,
+                             base::Unretained(this))) {}
+
+  const CompletionCallback& callback() const { return callback_; }
+
+ private:
+  void DeleteStream(int result) {
+    stream_.reset();
+    SetResult(result);
+  }
+
+  std::unique_ptr<QuicHttpStream> stream_;
+  CompletionCallback callback_;
+};
+
 }  // namespace
 
 class QuicHttpStreamPeer {
@@ -1312,6 +1332,41 @@
   EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
 }
 
+TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
+  SetRequest("POST", "/", DEFAULT_PRIORITY);
+  size_t spdy_request_headers_frame_length;
+  AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
+                                         &spdy_request_headers_frame_length));
+  AddWrite(
+      ConstructClientDataPacket(2, kIncludeVersion, !kFin, 0, kUploadData));
+  // Second data write will result in a synchronous failure which will close
+  // the session.
+  AddWrite(SYNCHRONOUS, ERR_FAILED);
+  Initialize();
+
+  ChunkedUploadDataStream upload_data_stream(0);
+
+  request_.method = "POST";
+  request_.url = GURL("http://www.example.org/");
+  request_.upload_data_stream = &upload_data_stream;
+  ASSERT_EQ(OK, request_.upload_data_stream->Init(
+                    TestCompletionCallback().callback()));
+
+  size_t chunk_size = strlen(kUploadData);
+  upload_data_stream.AppendData(kUploadData, chunk_size, false);
+  ASSERT_EQ(OK,
+            stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
+                                      net_log_.bound(), callback_.callback()));
+  QuicHttpStream* stream = stream_.get();
+  DeleteStreamCallback delete_stream_callback(std::move(stream_));
+  // SendRequest() completes asynchronously after the final chunk is added.
+  ASSERT_EQ(ERR_IO_PENDING,
+            stream->SendRequest(headers_, &response_, callback_.callback()));
+  upload_data_stream.AppendData(kUploadData, chunk_size, true);
+  int rv = callback_.WaitForResult();
+  EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, rv);
+}
+
 TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   AddWrite(SYNCHRONOUS, ERR_FAILED);
diff --git a/net/tools/testserver/minica.py b/net/tools/testserver/minica.py
index 7d7b06b..d882b19 100644
--- a/net/tools/testserver/minica.py
+++ b/net/tools/testserver/minica.py
@@ -287,20 +287,14 @@
     thisUpdate = now - datetime.timedelta(days=1)
     nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
   elif ocsp_date == OCSP_DATE_OLD:
-    thisUpdate = now - datetime.timedelta(hours=1, weeks=1)
+    thisUpdate = now - datetime.timedelta(days=1, weeks=1)
     nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
   elif ocsp_date == OCSP_DATE_EARLY:
-    thisUpdate = now + datetime.timedelta(hours=1)
+    thisUpdate = now + datetime.timedelta(days=1)
     nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
   elif ocsp_date == OCSP_DATE_LONG:
     thisUpdate = now - datetime.timedelta(days=365)
-    nextUpdate = thisUpdate + datetime.timedelta(hours=1, days=365)
-  elif ocsp_date == OCSP_DATE_BEFORE_CERT:
-    thisUpdate = now - datetime.timedelta(days=1)
-    nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
-  elif ocsp_date == OCSP_DATE_AFTER_CERT:
-    thisUpdate = now - datetime.timedelta(days=1)
-    nextUpdate = thisUpdate + datetime.timedelta(weeks=1)
+    nextUpdate = thisUpdate + datetime.timedelta(days=366)
   else:
     raise ValueError('Bad OCSP date: ' + str(ocsp_date))
 
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index 97f2b057..14c5abc 100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -1941,10 +1941,6 @@
               ocsp_date = minica.OCSP_DATE_EARLY
             elif ocsp_date_arg == 'long':
               ocsp_date = minica.OCSP_DATE_LONG
-            elif ocsp_date_arg == 'before_cert':
-              ocsp_date = minica.OCSP_DATE_AFTER_CERT
-            elif ocsp_date_arg == 'after_cert':
-              ocsp_date = minica.OCSP_DATE_AFTER_CERT
             else:
               raise testserver_base.OptionError('unknown OCSP date: ' +
                   ocsp_date_arg)
diff --git a/net/tools/tld_cleanup/tld_cleanup_util.cc b/net/tools/tld_cleanup/tld_cleanup_util.cc
index f4d93ac..6ed431f 100644
--- a/net/tools/tld_cleanup/tld_cleanup_util.cc
+++ b/net/tools/tld_cleanup/tld_cleanup_util.cc
@@ -165,7 +165,7 @@
       line_end = data.find_first_of("\r\n \t", line_start);
       if (line_end == std::string::npos)
         line_end = data.size();
-      domain.assign(data.data(), line_start, line_end - line_start);
+      domain.assign(data, line_start, line_end - line_start);
 
       Rule rule;
       rule.wildcard = false;
diff --git a/net/udp/udp_socket_posix.cc b/net/udp/udp_socket_posix.cc
index b397262..797e1a0 100644
--- a/net/udp/udp_socket_posix.cc
+++ b/net/udp/udp_socket_posix.cc
@@ -346,27 +346,55 @@
       base::android::SDK_VERSION_LOLLIPOP) {
     return ERR_NOT_IMPLEMENTED;
   }
-  // NOTE(pauljensen): This does rely on Android implementation details, but
-  // these details are unlikely to change.
-  typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd);
-  static SetNetworkForSocket setNetworkForSocket;
-  // This is racy, but all racers should come out with the same answer so it
-  // shouldn't matter.
-  if (!setNetworkForSocket) {
-    // Android's netd client library should always be loaded in our address
-    // space as it shims socket() which was used to create |socket_|.
-    base::FilePath file(base::GetNativeLibraryName("netd_client"));
-    // Use RTLD_NOW to match Android's prior loading of the library:
-    // http://androidxref.com/6.0.0_r5/xref/bionic/libc/bionic/NetdClient.cpp#37
-    // Use RTLD_NOLOAD to assert that the library is already loaded and
-    // avoid doing any disk IO.
-    void* dl = dlopen(file.value().c_str(), RTLD_NOW | RTLD_NOLOAD);
-    setNetworkForSocket =
-        reinterpret_cast<SetNetworkForSocket>(dlsym(dl, "setNetworkForSocket"));
+  int rv;
+  // On Android M and newer releases use supported NDK API. On Android L use
+  // setNetworkForSocket from libnetd_client.so.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+      base::android::SDK_VERSION_MARSHMALLOW) {
+    // See declaration of android_setsocknetwork() here:
+    // http://androidxref.com/6.0.0_r1/xref/development/ndk/platforms/android-M/include/android/multinetwork.h#65
+    // Function cannot be called directly as it will cause app to fail to load
+    // on pre-marshmallow devices.
+    typedef int (*MarshmallowSetNetworkForSocket)(int64_t netId, int socketFd);
+    static MarshmallowSetNetworkForSocket marshmallowSetNetworkForSocket;
+    // This is racy, but all racers should come out with the same answer so it
+    // shouldn't matter.
+    if (!marshmallowSetNetworkForSocket) {
+      base::FilePath file(base::GetNativeLibraryName("android"));
+      void* dl = dlopen(file.value().c_str(), RTLD_NOW);
+      marshmallowSetNetworkForSocket =
+          reinterpret_cast<MarshmallowSetNetworkForSocket>(
+              dlsym(dl, "android_setsocknetwork"));
+    }
+    if (!marshmallowSetNetworkForSocket)
+      return ERR_NOT_IMPLEMENTED;
+    rv = marshmallowSetNetworkForSocket(network, socket_);
+    if (rv)
+      rv = errno;
+  } else {
+    // NOTE(pauljensen): This does rely on Android implementation details, but
+    // they won't change because Lollipop is already released.
+    typedef int (*LollipopSetNetworkForSocket)(unsigned netId, int socketFd);
+    static LollipopSetNetworkForSocket lollipopSetNetworkForSocket;
+    // This is racy, but all racers should come out with the same answer so it
+    // shouldn't matter.
+    if (!lollipopSetNetworkForSocket) {
+      // Android's netd client library should always be loaded in our address
+      // space as it shims socket() which was used to create |socket_|.
+      base::FilePath file(base::GetNativeLibraryName("netd_client"));
+      // Use RTLD_NOW to match Android's prior loading of the library:
+      // http://androidxref.com/6.0.0_r5/xref/bionic/libc/bionic/NetdClient.cpp#37
+      // Use RTLD_NOLOAD to assert that the library is already loaded and
+      // avoid doing any disk IO.
+      void* dl = dlopen(file.value().c_str(), RTLD_NOW | RTLD_NOLOAD);
+      lollipopSetNetworkForSocket =
+          reinterpret_cast<LollipopSetNetworkForSocket>(
+              dlsym(dl, "setNetworkForSocket"));
+    }
+    if (!lollipopSetNetworkForSocket)
+      return ERR_NOT_IMPLEMENTED;
+    rv = -lollipopSetNetworkForSocket(network, socket_);
   }
-  if (!setNetworkForSocket)
-    return ERR_NOT_IMPLEMENTED;
-  int rv = setNetworkForSocket(network, socket_);
   // If |network| has since disconnected, |rv| will be ENONET.  Surface this as
   // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
   // the less descriptive ERR_FAILED.
diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc
index cb4a495c..1f34ff6b 100644
--- a/net/udp/udp_socket_unittest.cc
+++ b/net/udp/udp_socket_unittest.cc
@@ -29,6 +29,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
 #if defined(OS_IOS)
 #include <TargetConditionals.h>
 #endif
@@ -687,6 +691,53 @@
   client.Close();
 }
 
+TEST_F(UDPSocketTest, TestBindToNetwork) {
+  UDPSocket socket(DatagramSocket::RANDOM_BIND, base::Bind(&PrivilegedRand),
+                   NULL, NetLog::Source());
+  ASSERT_EQ(OK, socket.Open(ADDRESS_FAMILY_IPV4));
+  // Test unsuccessful binding, by attempting to bind to a bogus NetworkHandle.
+  int rv = socket.BindToNetwork(65536);
+#if !defined(OS_ANDROID)
+  EXPECT_EQ(ERR_NOT_IMPLEMENTED, rv);
+#else
+  if (base::android::BuildInfo::GetInstance()->sdk_int() <
+      base::android::SDK_VERSION_LOLLIPOP) {
+    EXPECT_EQ(ERR_NOT_IMPLEMENTED, rv);
+  } else if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+             base::android::SDK_VERSION_LOLLIPOP &&
+             base::android::BuildInfo::GetInstance()->sdk_int() <
+             base::android::SDK_VERSION_MARSHMALLOW) {
+    // On Lollipop, we assume if the user has a NetworkHandle that they must
+    // have gotten it from a legitimate source, so if binding to the network
+    // fails it's assumed to be because the network went away so
+    // ERR_NETWORK_CHANGED is returned. In this test the network never existed
+    // anyhow.  ConnectivityService.MAX_NET_ID is 65535, so 65536 won't be used.
+    EXPECT_EQ(ERR_NETWORK_CHANGED, rv);
+  } else if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+             base::android::SDK_VERSION_MARSHMALLOW) {
+    // On Marshmallow and newer releases, the NetworkHandle is munged by
+    // Network.getNetworkHandle() and 65536 isn't munged so it's rejected.
+    EXPECT_EQ(ERR_INVALID_ARGUMENT, rv);
+  }
+
+  if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+      base::android::SDK_VERSION_LOLLIPOP) {
+    EXPECT_EQ(
+        ERR_INVALID_ARGUMENT,
+        socket.BindToNetwork(NetworkChangeNotifier::kInvalidNetworkHandle));
+
+    // Test successful binding, if possible.
+    if (NetworkChangeNotifier::AreNetworkHandlesSupported()) {
+      NetworkChangeNotifier::NetworkHandle network_handle =
+          NetworkChangeNotifier::GetDefaultNetwork();
+      if (network_handle != NetworkChangeNotifier::kInvalidNetworkHandle) {
+        EXPECT_EQ(OK, socket.BindToNetwork(network_handle));
+      }
+    }
+  }
+#endif
+}
+
 }  // namespace
 
 #if defined(OS_WIN)
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 6aabd6e7..7a5805bc 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -9463,8 +9463,6 @@
 
 };
 
-// Flaky on Android Tests (dbg) bot, crbug.com/630286.
-#if !defined(OS_ANDROID)
 class HTTPSOCSPVerifyTest
     : public HTTPSOCSPTest,
       public testing::WithParamInterface<OCSPVerifyTestData> {};
@@ -9499,7 +9497,6 @@
 INSTANTIATE_TEST_CASE_P(OCSPVerify,
                         HTTPSOCSPVerifyTest,
                         testing::ValuesIn(kOCSPVerifyData));
-#endif
 
 class HTTPSHardFailTest : public HTTPSOCSPTest {
  protected:
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index 2df2e9af..ebe053e 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -33,6 +33,7 @@
   deps = [
     "//third_party/pdfium/testing/libfuzzer:pdf_jpx_fuzzer",
   ]
+  seed_corpus = "corpora/pdf_jpx"
 }
 
 if (pdf_enable_xfa) {
@@ -41,6 +42,7 @@
     deps = [
       "//third_party/pdfium/testing/libfuzzer:pdf_codec_bmp_fuzzer",
     ]
+    seed_corpus = "corpora/pdf_codec_bmp"
   }
 
   fuzzer_test("pdf_codec_gif_fuzzer") {
@@ -48,6 +50,8 @@
     deps = [
       "//third_party/pdfium/testing/libfuzzer:pdf_codec_gif_fuzzer",
     ]
+    dict = "dicts/pdf_codec_gif.dict"
+    seed_corpus = "corpora/pdf_codec_gif"
   }
 
   fuzzer_test("pdf_codec_jpeg_fuzzer") {
@@ -55,6 +59,8 @@
     deps = [
       "//third_party/pdfium/testing/libfuzzer:pdf_codec_jpeg_fuzzer",
     ]
+    dict = "dicts/pdf_codec_jpeg.dict"
+    seed_corpus = "corpora/pdf_codec_jpeg"
   }
 
   fuzzer_test("pdf_codec_png_fuzzer") {
@@ -62,6 +68,8 @@
     deps = [
       "//third_party/pdfium/testing/libfuzzer:pdf_codec_png_fuzzer",
     ]
+    dict = "dicts/pdf_codec_png.dict"
+    seed_corpus = "corpora/pdf_codec_png"
   }
 
   fuzzer_test("pdf_codec_tiff_fuzzer") {
@@ -69,6 +77,8 @@
     deps = [
       "//third_party/pdfium/testing/libfuzzer:pdf_codec_tiff_fuzzer",
     ]
+    dict = "dicts/pdf_codec_tiff.dict"
+    seed_corpus = "corpora/pdf_codec_tiff"
   }
 
   fuzzer_test("pdf_css_fuzzer") {
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_gif/not_kitty.gif b/pdf/pdfium/fuzzers/corpora/pdf_codec_gif/not_kitty.gif
new file mode 100644
index 0000000..244fcc6
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_gif/not_kitty.gif
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_jpeg/not_kitty.jpg b/pdf/pdfium/fuzzers/corpora/pdf_codec_jpeg/not_kitty.jpg
new file mode 100644
index 0000000..0497be4
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_jpeg/not_kitty.jpg
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty.png b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty.png
new file mode 100644
index 0000000..eff7c170
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty.png
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_alpha.png b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_alpha.png
new file mode 100644
index 0000000..2fb8da2
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_alpha.png
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_gamma.png b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_gamma.png
new file mode 100644
index 0000000..939d9d2
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_gamma.png
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_icc.png b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_icc.png
new file mode 100644
index 0000000..f0c7804d
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_png/not_kitty_icc.png
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_codec_tiff/not_kitty.tiff b/pdf/pdfium/fuzzers/corpora/pdf_codec_tiff/not_kitty.tiff
new file mode 100644
index 0000000..506ca1a
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_codec_tiff/not_kitty.tiff
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/pdf_jpx/not_kitty.jp2 b/pdf/pdfium/fuzzers/corpora/pdf_jpx/not_kitty.jp2
new file mode 100644
index 0000000..14bca292
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/pdf_jpx/not_kitty.jp2
Binary files differ
diff --git a/pdf/pdfium/fuzzers/dicts/pdf_codec_gif.dict b/pdf/pdfium/fuzzers/dicts/pdf_codec_gif.dict
new file mode 100644
index 0000000..7114893
--- /dev/null
+++ b/pdf/pdfium/fuzzers/dicts/pdf_codec_gif.dict
@@ -0,0 +1,18 @@
+#
+# AFL dictionary for GIF images
+# -----------------------------
+#
+# Created by Michal Zalewski <lcamtuf@google.com>
+#
+
+header_87a="87a"
+header_89a="89a"
+header_gif="GIF"
+
+marker_2c=","
+marker_3b=";"
+
+section_2101="!\x01\x12"
+section_21f9="!\xf9\x04"
+section_21fe="!\xfe"
+section_21ff="!\xff\x11"
diff --git a/pdf/pdfium/fuzzers/dicts/pdf_codec_jpeg.dict b/pdf/pdfium/fuzzers/dicts/pdf_codec_jpeg.dict
new file mode 100644
index 0000000..15efede
--- /dev/null
+++ b/pdf/pdfium/fuzzers/dicts/pdf_codec_jpeg.dict
@@ -0,0 +1,22 @@
+#
+# AFL dictionary for JPEG images
+# ------------------------------
+#
+# Created by Michal Zalewski <lcamtuf@google.com>
+#
+
+header_jfif="JFIF\x00"
+header_jfxx="JFXX\x00"
+
+section_ffc0="\xff\xc0"
+section_ffc2="\xff\xc2"
+section_ffc4="\xff\xc4"
+section_ffd0="\xff\xd0"
+section_ffd8="\xff\xd8"
+section_ffd9="\xff\xd9"
+section_ffda="\xff\xda"
+section_ffdb="\xff\xdb"
+section_ffdd="\xff\xdd"
+section_ffe0="\xff\xe0"
+section_ffe1="\xff\xe1"
+section_fffe="\xff\xfe"
diff --git a/pdf/pdfium/fuzzers/dicts/pdf_codec_png.dict b/pdf/pdfium/fuzzers/dicts/pdf_codec_png.dict
new file mode 100644
index 0000000..ea12d19
--- /dev/null
+++ b/pdf/pdfium/fuzzers/dicts/pdf_codec_png.dict
@@ -0,0 +1,38 @@
+#
+# AFL dictionary for PNG images
+# -----------------------------
+#
+# Just the basic, standard-originating sections; does not include vendor
+# extensions.
+#
+# Created by Michal Zalewski <lcamtuf@google.com>
+#
+
+header_png="\x89PNG\x0d\x0a\x1a\x0a"
+
+section_IDAT="IDAT"
+section_IEND="IEND"
+section_IHDR="IHDR"
+section_PLTE="PLTE"
+section_bKGD="bKGD"
+section_cHRM="cHRM"
+section_fRAc="fRAc"
+section_gAMA="gAMA"
+section_gIFg="gIFg"
+section_gIFt="gIFt"
+section_gIFx="gIFx"
+section_hIST="hIST"
+section_iCCP="iCCP"
+section_iTXt="iTXt"
+section_oFFs="oFFs"
+section_pCAL="pCAL"
+section_pHYs="pHYs"
+section_sBIT="sBIT"
+section_sCAL="sCAL"
+section_sPLT="sPLT"
+section_sRGB="sRGB"
+section_sTER="sTER"
+section_tEXt="tEXt"
+section_tIME="tIME"
+section_tRNS="tRNS"
+section_zTXt="zTXt"
diff --git a/pdf/pdfium/fuzzers/dicts/pdf_codec_tiff.dict b/pdf/pdfium/fuzzers/dicts/pdf_codec_tiff.dict
new file mode 100644
index 0000000..8f04b5af
--- /dev/null
+++ b/pdf/pdfium/fuzzers/dicts/pdf_codec_tiff.dict
@@ -0,0 +1,51 @@
+#
+# AFL dictionary for TIFF images
+# ------------------------------
+#
+# Just the basic, standard-originating sections; does not include vendor
+# extensions.
+#
+# Created by Michal Zalewski <lcamtuf@google.com>
+#
+
+header_ii="II*\x00"
+header_mm="MM\x00*"
+
+section_100="\x00\x01"
+section_101="\x01\x01"
+section_102="\x02\x01"
+section_103="\x03\x01"
+section_106="\x06\x01"
+section_107="\x07\x01"
+section_10D="\x0d\x01"
+section_10E="\x0e\x01"
+section_10F="\x0f\x01"
+section_110="\x10\x01"
+section_111="\x11\x01"
+section_112="\x12\x01"
+section_115="\x15\x01"
+section_116="\x16\x01"
+section_117="\x17\x01"
+section_11A="\x1a\x01"
+section_11B="\x1b\x01"
+section_11C="\x1c\x01"
+section_11D="\x1d\x01"
+section_11E="\x1e\x01"
+section_11F="\x1f\x01"
+section_122="\"\x01"
+section_123="#\x01"
+section_124="$\x01"
+section_125="%\x01"
+section_128="(\x01"
+section_129=")\x01"
+section_12D="-\x01"
+section_131="1\x01"
+section_132="2\x01"
+section_13B=";\x01"
+section_13C="<\x01"
+section_13D="=\x01"
+section_13E=">\x01"
+section_13F="?\x01"
+section_140="@\x01"
+section_FE="\xfe\x00"
+section_FF="\xff\x00"
diff --git a/printing/printing.gyp b/printing/printing.gyp
index 695870c..3c43ce9 100644
--- a/printing/printing.gyp
+++ b/printing/printing.gyp
@@ -173,14 +173,13 @@
             # of the print backend and enables a custom implementation instead.
             'PRINT_BACKEND_AVAILABLE',
           ],
-
           'conditions': [
             ['chromeos==1', {
               'sources': [
                 'backend/cups_connection.cc',
                 'backend/cups_connection.h',
-                'backend/cups_deleter.cc',
-                'backend/cups_deleter.h',
+                'backend/cups_deleters.cc',
+                'backend/cups_deleters.h',
                 'backend/cups_ipp_util.cc',
                 'backend/cups_ipp_util.h',
                 'backend/cups_printer.cc',
diff --git a/remoting/base/constants.cc b/remoting/base/constants.cc
index 88affff..c61ec01 100644
--- a/remoting/base/constants.cc
+++ b/remoting/base/constants.cc
@@ -12,6 +12,7 @@
 const char kControlChannelName[] = "control";
 const char kEventChannelName[] = "event";
 const char kVideoChannelName[] = "video";
+const char kVideoStatsChannelNamePrefix[] = "video_stats:";
 
 const char kMimeTypeTextUtf8[] = "text/plain; charset=UTF-8";
 
diff --git a/remoting/base/constants.h b/remoting/base/constants.h
index 8048ae23..c056e78 100644
--- a/remoting/base/constants.h
+++ b/remoting/base/constants.h
@@ -15,6 +15,7 @@
 extern const char kControlChannelName[];
 extern const char kEventChannelName[];
 extern const char kVideoChannelName[];
+extern const char kVideoStatsChannelNamePrefix[];
 
 // MIME types for the clipboard.
 extern const char kMimeTypeTextUtf8[];
diff --git a/remoting/client/BUILD.gn b/remoting/client/BUILD.gn
index 0712393..5bae90e 100644
--- a/remoting/client/BUILD.gn
+++ b/remoting/client/BUILD.gn
@@ -85,6 +85,7 @@
     "chromoting_client_runtime_unittest.cc",
     "client_status_logger_unittest.cc",
     "client_telemetry_logger_unittest.cc",
+    "dual_buffer_frame_consumer_unittest.cc",
     "empty_cursor_filter_unittest.cc",
     "key_event_mapper_unittest.cc",
     "normalizing_input_filter_cros_unittest.cc",
diff --git a/remoting/client/dual_buffer_frame_consumer.cc b/remoting/client/dual_buffer_frame_consumer.cc
new file mode 100644
index 0000000..709f1be
--- /dev/null
+++ b/remoting/client/dual_buffer_frame_consumer.cc
@@ -0,0 +1,112 @@
+// Copyright 2016 The Chromium Authors. 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/client/dual_buffer_frame_consumer.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/shared_desktop_frame.h"
+
+namespace remoting {
+
+DualBufferFrameConsumer::DualBufferFrameConsumer(
+    const RenderCallback& callback,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    protocol::FrameConsumer::PixelFormat format)
+    : callback_(callback),
+      task_runner_(task_runner),
+      pixel_format_(format),
+      weak_factory_(this) {
+  weak_ptr_ = weak_factory_.GetWeakPtr();
+  thread_checker_.DetachFromThread();
+}
+
+DualBufferFrameConsumer::~DualBufferFrameConsumer() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void DualBufferFrameConsumer::RequestFullDesktopFrame() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!buffers_[0]) {
+    return;
+  }
+  DCHECK(buffers_[0]->size().equals(buffers_[1]->size()));
+  // This creates a copy of buffers_[0] and merges area defined in
+  // |buffer_1_mask_| from buffers_[1] into the copy.
+  std::unique_ptr<webrtc::DesktopFrame> full_frame(
+      webrtc::BasicDesktopFrame::CopyOf(*buffers_[0]));
+  webrtc::DesktopRect desktop_rect =
+        webrtc::DesktopRect::MakeSize(buffers_[0]->size());
+  for (webrtc::DesktopRegion::Iterator i(buffer_1_mask_); !i.IsAtEnd();
+       i.Advance()) {
+    full_frame->CopyPixelsFrom(*buffers_[1], i.rect().top_left(),
+                               i.rect());
+  }
+  full_frame->mutable_updated_region()->SetRect(desktop_rect);
+
+  RunRenderCallback(std::move(full_frame), base::Bind(&base::DoNothing));
+}
+
+std::unique_ptr<webrtc::DesktopFrame> DualBufferFrameConsumer::AllocateFrame(
+    const webrtc::DesktopSize& size) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  // Both buffers are reallocated whenever screen size changes.
+  if (!buffers_[0] || !buffers_[0]->size().equals(size)) {
+    buffers_[0] = webrtc::SharedDesktopFrame::Wrap(
+        base::WrapUnique(new webrtc::BasicDesktopFrame(size)));
+    buffers_[1] = webrtc::SharedDesktopFrame::Wrap(
+        base::WrapUnique(new webrtc::BasicDesktopFrame(size)));
+    buffer_1_mask_.Clear();
+    current_buffer_ = 0;
+  } else {
+    current_buffer_ = (current_buffer_ + 1) % 2;
+  }
+  return buffers_[current_buffer_]->Share();
+}
+
+void DualBufferFrameConsumer::DrawFrame(
+    std::unique_ptr<webrtc::DesktopFrame> frame,
+    const base::Closure& done) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  webrtc::SharedDesktopFrame* shared_frame =
+      reinterpret_cast<webrtc::SharedDesktopFrame*> (frame.get());
+  if (shared_frame->GetUnderlyingFrame() == buffers_[1]->GetUnderlyingFrame()) {
+    buffer_1_mask_.AddRegion(frame->updated_region());
+  } else if (shared_frame->GetUnderlyingFrame() ==
+      buffers_[0]->GetUnderlyingFrame()) {
+    buffer_1_mask_.Subtract(frame->updated_region());
+  }
+  RunRenderCallback(std::move(frame), done);
+}
+
+protocol::FrameConsumer::PixelFormat
+DualBufferFrameConsumer::GetPixelFormat() {
+  return pixel_format_;
+}
+
+base::WeakPtr<DualBufferFrameConsumer> DualBufferFrameConsumer::GetWeakPtr() {
+  return weak_ptr_;
+}
+
+void DualBufferFrameConsumer::RunRenderCallback(
+    std::unique_ptr<webrtc::DesktopFrame> frame,
+    const base::Closure& done) {
+  if (!task_runner_) {
+    callback_.Run(std::move(frame), done);
+    return;
+  }
+
+  task_runner_->PostTask(
+      FROM_HERE, base::Bind(callback_, base::Passed(&frame), base::Bind(
+          base::IgnoreResult(&base::TaskRunner::PostTask),
+          base::ThreadTaskRunnerHandle::Get(), FROM_HERE, done)));
+}
+
+}  // namespace remoting
diff --git a/remoting/client/dual_buffer_frame_consumer.h b/remoting/client/dual_buffer_frame_consumer.h
new file mode 100644
index 0000000..a1f609f
--- /dev/null
+++ b/remoting/client/dual_buffer_frame_consumer.h
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium Authors. 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_CLIENT_DUAL_BUFFER_FRAME_CONSUMER_H_
+#define REMOTING_CLIENT_DUAL_BUFFER_FRAME_CONSUMER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
+#include "remoting/protocol/frame_consumer.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
+
+namespace webrtc {
+class SharedDesktopFrame;
+}  // namespace webrtc
+
+namespace remoting {
+
+// This class continuously uses two BasicDesktopFrame as buffer for decoding
+// updated regions until the resolution is changed.
+// This class should be used and destroyed on the same thread. If |task_runner|
+// is null |callback| will be run directly upon the stack of DrawFrame,
+// otherwise a task will be posted to feed the callback on the thread of
+// |task_runner|.
+// Only areas bound by updated_region() on the buffer are considered valid to
+// |callback|. Please use RequestFullDesktopFrame() if you want to get a full
+// desktop frame.
+class DualBufferFrameConsumer : public protocol::FrameConsumer {
+ public:
+  // RenderCallback(decoded_frame, done)
+  // |done| should be run after it is rendered. Can be called on any thread.
+  using RenderCallback =
+      base::Callback<void(std::unique_ptr<webrtc::DesktopFrame>,
+                          const base::Closure&)>;
+  DualBufferFrameConsumer(
+      const RenderCallback& callback,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      PixelFormat format);
+  ~DualBufferFrameConsumer() override;
+
+  // Feeds the callback on the right thread with a BasicDesktopFrame that merges
+  // updates from buffer_[0] and buffer_[1]. Do nothing if no updates have
+  // received yet.
+  void RequestFullDesktopFrame();
+
+  // FrameConsumer interface.
+  std::unique_ptr<webrtc::DesktopFrame> AllocateFrame(
+      const webrtc::DesktopSize& size) override;
+  void DrawFrame(std::unique_ptr<webrtc::DesktopFrame> frame,
+                 const base::Closure& done) override;
+  PixelFormat GetPixelFormat() override;
+
+  base::WeakPtr<DualBufferFrameConsumer> GetWeakPtr();
+
+ private:
+  void RunRenderCallback(std::unique_ptr<webrtc::DesktopFrame> frame,
+                 const base::Closure& done);
+
+  std::unique_ptr<webrtc::SharedDesktopFrame> buffers_[2];
+
+  // Represents dirty regions that are currently in buffers_[1]. Will be used
+  // when calling RequestFullDesktopFrame() to construct the full desktop frame.
+  webrtc::DesktopRegion buffer_1_mask_;
+
+  int current_buffer_ = 0;
+
+  RenderCallback callback_;
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  PixelFormat pixel_format_;
+  base::ThreadChecker thread_checker_;
+  base::WeakPtr<DualBufferFrameConsumer> weak_ptr_;
+  base::WeakPtrFactory<DualBufferFrameConsumer> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DualBufferFrameConsumer);
+};
+
+}  // namespace remoting
+#endif  // REMOTING_CLIENT_DUAL_BUFFER_FRAME_CONSUMER_H_
diff --git a/remoting/client/dual_buffer_frame_consumer_unittest.cc b/remoting/client/dual_buffer_frame_consumer_unittest.cc
new file mode 100644
index 0000000..be3a05ba
--- /dev/null
+++ b/remoting/client/dual_buffer_frame_consumer_unittest.cc
@@ -0,0 +1,205 @@
+// Copyright 2016 The Chromium Authors. 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/client/dual_buffer_frame_consumer.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/shared_desktop_frame.h"
+
+namespace remoting {
+
+namespace {
+
+webrtc::DesktopFrame* GetUnderlyingFrame(
+    const std::unique_ptr<webrtc::DesktopFrame>& frame) {
+  return reinterpret_cast<webrtc::SharedDesktopFrame*>(frame.get())->
+      GetUnderlyingFrame();
+}
+
+void FillRGBARect(uint8_t r,
+                  uint8_t g,
+                  uint8_t b,
+                  uint8_t a,
+                  const webrtc::DesktopRect& rect,
+                  webrtc::DesktopFrame* frame) {
+  for (int x = 0; x < rect.width(); x++) {
+    for (int y = 0; y < rect.height(); y++) {
+      uint8_t* data = frame->GetFrameDataAtPos(
+          rect.top_left().add(webrtc::DesktopVector(x, y)));
+      data[0] = r;
+      data[1] = g;
+      data[2] = b;
+      data[3] = a;
+    }
+  }
+  frame->mutable_updated_region()->SetRect(rect);
+}
+
+void CheckFrameColor(uint8_t r,
+                     uint8_t g,
+                     uint8_t b,
+                     uint8_t a,
+                     const webrtc::DesktopVector& pos,
+                     const webrtc::DesktopFrame& frame) {
+  uint8_t* data = frame.GetFrameDataAtPos(pos);
+  EXPECT_EQ(r, data[0]);
+  EXPECT_EQ(g, data[1]);
+  EXPECT_EQ(b, data[2]);
+  EXPECT_EQ(a, data[3]);
+}
+
+}  // namespace
+
+class DualBufferFrameConsumerTest : public testing::Test {
+ public:
+  void SetUp() override;
+ protected:
+  std::unique_ptr<DualBufferFrameConsumer> consumer_;
+  std::unique_ptr<webrtc::DesktopFrame> received_frame_;
+  base::Closure done_closure_;
+ private:
+  void OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame,
+                       const base::Closure& done);
+};
+
+void DualBufferFrameConsumerTest::SetUp() {
+  consumer_.reset(new DualBufferFrameConsumer(
+      base::Bind(&DualBufferFrameConsumerTest::OnFrameReceived,
+                 base::Unretained(this)), nullptr,
+                 protocol::FrameConsumer::FORMAT_RGBA));
+}
+
+void DualBufferFrameConsumerTest::OnFrameReceived(
+    std::unique_ptr<webrtc::DesktopFrame> frame,
+    const base::Closure& done) {
+  received_frame_ = std::move(frame);
+  done_closure_ = done;
+}
+
+TEST_F(DualBufferFrameConsumerTest, AllocateOneFrame) {
+  std::unique_ptr<webrtc::DesktopFrame> frame =
+      consumer_->AllocateFrame(webrtc::DesktopSize(16, 16));
+  ASSERT_TRUE(frame->size().equals(webrtc::DesktopSize(16, 16)));
+  webrtc::DesktopFrame* raw_frame = frame.get();
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+  EXPECT_EQ(raw_frame, received_frame_.get());
+}
+
+TEST_F(DualBufferFrameConsumerTest, BufferRotation) {
+  webrtc::DesktopSize size16x16(16, 16);
+
+  std::unique_ptr<webrtc::DesktopFrame> frame =
+      consumer_->AllocateFrame(size16x16);
+  webrtc::DesktopFrame* underlying_frame_1 = GetUnderlyingFrame(frame);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  frame = consumer_->AllocateFrame(size16x16);
+  webrtc::DesktopFrame* underlying_frame_2 = GetUnderlyingFrame(frame);
+  EXPECT_NE(underlying_frame_1, underlying_frame_2);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  frame = consumer_->AllocateFrame(size16x16);
+  webrtc::DesktopFrame* underlying_frame_3 = GetUnderlyingFrame(frame);
+  EXPECT_EQ(underlying_frame_1, underlying_frame_3);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  frame = consumer_->AllocateFrame(size16x16);
+  webrtc::DesktopFrame* underlying_frame_4 = GetUnderlyingFrame(frame);
+  EXPECT_EQ(underlying_frame_2, underlying_frame_4);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+}
+
+TEST_F(DualBufferFrameConsumerTest, DrawAndMergeFrames) {
+  webrtc::DesktopSize size2x2(2, 2);
+
+  // X means uninitialized color.
+
+  // Frame 1:
+  // RR
+  // RR
+  std::unique_ptr<webrtc::DesktopFrame> frame =
+      consumer_->AllocateFrame(size2x2);
+  FillRGBARect(0xff, 0, 0, 0xff, webrtc::DesktopRect::MakeXYWH(0, 0, 2, 2),
+               frame.get());
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  // Frame 2:
+  // GG
+  // XX
+  frame = consumer_->AllocateFrame(size2x2);
+  FillRGBARect(0, 0xff, 0, 0xff, webrtc::DesktopRect::MakeXYWH(0, 0, 2, 1),
+               frame.get());
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  // Merged Frame:
+  // GG
+  // RR
+  consumer_->RequestFullDesktopFrame();
+  ASSERT_TRUE(received_frame_->size().equals(size2x2));
+
+  CheckFrameColor(0, 0xff, 0, 0xff, webrtc::DesktopVector(0, 0),
+                  *received_frame_);
+  CheckFrameColor(0xff, 0, 0, 0xff, webrtc::DesktopVector(0, 1),
+                  *received_frame_);
+  CheckFrameColor(0, 0xff, 0, 0xff, webrtc::DesktopVector(1, 0),
+                  *received_frame_);
+  CheckFrameColor(0xff, 0, 0, 0xff, webrtc::DesktopVector(1, 1),
+                  *received_frame_);
+
+  // Frame 3:
+  // BX
+  // BX
+  frame = consumer_->AllocateFrame(size2x2);
+  FillRGBARect(0, 0, 0xff, 0xff, webrtc::DesktopRect::MakeXYWH(0, 0, 1, 2),
+               frame.get());
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  // Merged Frame:
+  // BG
+  // BR
+  consumer_->RequestFullDesktopFrame();
+  ASSERT_TRUE(received_frame_->size().equals(size2x2));
+
+  CheckFrameColor(0, 0, 0xff, 0xff, webrtc::DesktopVector(0, 0),
+                  *received_frame_);
+  CheckFrameColor(0, 0, 0xff, 0xff, webrtc::DesktopVector(0, 1),
+                  *received_frame_);
+  CheckFrameColor(0, 0xff, 0, 0xff, webrtc::DesktopVector(1, 0),
+                  *received_frame_);
+  CheckFrameColor(0xff, 0, 0, 0xff, webrtc::DesktopVector(1, 1),
+                  *received_frame_);
+}
+
+TEST_F(DualBufferFrameConsumerTest, ChangeScreenSizeAndReallocateBuffers) {
+  webrtc::DesktopSize size16x16(16, 16);
+
+  std::unique_ptr<webrtc::DesktopFrame> frame =
+      consumer_->AllocateFrame(size16x16);
+  webrtc::DesktopFrame* underlying_frame_1 = GetUnderlyingFrame(frame);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  frame = consumer_->AllocateFrame(size16x16);
+  webrtc::DesktopFrame* underlying_frame_2 = GetUnderlyingFrame(frame);
+  EXPECT_NE(underlying_frame_1, underlying_frame_2);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  webrtc::DesktopSize size32x32(32, 32);
+
+  frame = consumer_->AllocateFrame(size32x32);
+  webrtc::DesktopFrame* underlying_frame_3 = GetUnderlyingFrame(frame);
+  EXPECT_NE(underlying_frame_1, underlying_frame_3);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+
+  frame = consumer_->AllocateFrame(size32x32);
+  webrtc::DesktopFrame* underlying_frame_4 = GetUnderlyingFrame(frame);
+  EXPECT_NE(underlying_frame_2, underlying_frame_4);
+  consumer_->DrawFrame(std::move(frame), base::Closure());
+}
+
+}  // namespace remoting
diff --git a/remoting/client/gl_desktop.cc b/remoting/client/gl_desktop.cc
index 4ac5d784..656e3bb6 100644
--- a/remoting/client/gl_desktop.cc
+++ b/remoting/client/gl_desktop.cc
@@ -27,33 +27,31 @@
     return;
   }
   layer_.reset(new GlRenderLayer(kTextureId, canvas));
-  if (last_frame_) {
-    layer_->SetTexture(last_frame_->data(), last_frame_->size().width(),
-                       last_frame_->size().height());
-  }
+  last_desktop_size_.set(0, 0);
 }
 
 void GlDesktop::SetVideoFrame(std::unique_ptr<webrtc::DesktopFrame> frame) {
-  if (layer_) {
-    if (!last_frame_ || !frame->size().equals(last_frame_->size())) {
-      layer_->SetTexture(frame->data(), frame->size().width(),
-                         frame->size().height());
-    } else {
-      for (webrtc::DesktopRegion::Iterator i(frame->updated_region());
-          !i.IsAtEnd(); i.Advance()) {
-        const uint8_t* rect_start =
-            frame->GetFrameDataAtPos(i.rect().top_left());
-        layer_->UpdateTexture(
-            rect_start, i.rect().left(), i.rect().top(), i.rect().width(),
-            i.rect().height(), frame->stride());
-      }
+  if (!layer_) {
+    return;
+  }
+  if (!frame->size().equals(last_desktop_size_)) {
+    layer_->SetTexture(frame->data(), frame->size().width(),
+                       frame->size().height());
+    last_desktop_size_.set(frame->size().width(), frame->size().height());
+  } else {
+    for (webrtc::DesktopRegion::Iterator i(frame->updated_region());
+        !i.IsAtEnd(); i.Advance()) {
+      const uint8_t* rect_start =
+          frame->GetFrameDataAtPos(i.rect().top_left());
+      layer_->UpdateTexture(
+          rect_start, i.rect().left(), i.rect().top(), i.rect().width(),
+          i.rect().height(), frame->stride());
     }
   }
-  last_frame_ = std::move(frame);
 }
 
 void GlDesktop::Draw() {
-  if (layer_ && last_frame_) {
+  if (layer_ && !last_desktop_size_.is_empty()) {
     layer_->Draw(1.f);
   }
 }
diff --git a/remoting/client/gl_desktop.h b/remoting/client/gl_desktop.h
index afdf0eb..ca7a5ee 100644
--- a/remoting/client/gl_desktop.h
+++ b/remoting/client/gl_desktop.h
@@ -8,10 +8,10 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 
 namespace webrtc {
 class DesktopFrame;
-class DesktopRegion;
 }  // namespace webrtc
 
 namespace remoting {
@@ -25,10 +25,11 @@
   GlDesktop();
   virtual ~GlDesktop();
 
+  // |frame| can be either a full frame or updated regions only frame.
   void SetVideoFrame(std::unique_ptr<webrtc::DesktopFrame> frame);
 
-  // Sets the canvas on which the desktop will be drawn. Resumes the current
-  // state of the desktop to the context of the new canvas.
+  // Sets the canvas on which the desktop will be drawn. Caller must feed a
+  // full desktop frame after calling this function.
   // If |canvas| is nullptr, nothing will happen when calling Draw().
   void SetCanvas(GlCanvas* canvas);
 
@@ -37,7 +38,7 @@
 
  private:
   std::unique_ptr<GlRenderLayer> layer_;
-  std::unique_ptr<webrtc::DesktopFrame> last_frame_;
+  webrtc::DesktopSize last_desktop_size_;
 
   DISALLOW_COPY_AND_ASSIGN(GlDesktop);
 };
diff --git a/remoting/client/software_video_renderer.cc b/remoting/client/software_video_renderer.cc
index 930087dc..52ff346 100644
--- a/remoting/client/software_video_renderer.cc
+++ b/remoting/client/software_video_renderer.cc
@@ -51,13 +51,10 @@
 }
 
 SoftwareVideoRenderer::SoftwareVideoRenderer(
-    scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner,
-    protocol::FrameConsumer* consumer,
-    protocol::FrameStatsConsumer* stats_consumer)
-    : decode_task_runner_(decode_task_runner),
-      consumer_(consumer),
-      stats_consumer_(stats_consumer),
-      weak_factory_(this) {}
+    std::unique_ptr<protocol::FrameConsumer> consumer)
+    : SoftwareVideoRenderer(consumer.get()) {
+  owned_consumer_ = std::move(consumer);
+}
 
 SoftwareVideoRenderer::~SoftwareVideoRenderer() {
   if (decoder_)
diff --git a/remoting/client/software_video_renderer.h b/remoting/client/software_video_renderer.h
index 2172500..84aafd75 100644
--- a/remoting/client/software_video_renderer.h
+++ b/remoting/client/software_video_renderer.h
@@ -44,17 +44,10 @@
   // be called on the same thread.
   explicit SoftwareVideoRenderer(protocol::FrameConsumer* consumer);
 
-  // Deprecated constructor. TODO(yuweih): remove.
-  // Constructs the renderer and initializes it immediately. Caller should not
-  // call Initialize() after using this constructor.
-  // All methods must be called on the same thread the renderer is created. The
-  // |decode_task_runner_| is used to decode the video packets. |consumer| and
-  // |stats_consumer| must outlive the renderer. |stats_consumer| may be
-  // nullptr, performance tracking is disabled in that case.
-  SoftwareVideoRenderer(
-      scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner,
-      protocol::FrameConsumer* consumer,
-      protocol::FrameStatsConsumer* stats_consumer);
+  // Same as above, but take ownership of the |consumer|.
+  explicit SoftwareVideoRenderer(
+      std::unique_ptr<protocol::FrameConsumer> consumer);
+
   ~SoftwareVideoRenderer() override;
 
   // VideoRenderer interface.
@@ -77,7 +70,12 @@
                        const base::Closure& done);
 
   scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_;
+
+  // |owned_consumer_| and |consumer_| should refer to the same object if
+  // |owned_consumer_| is not null.
+  std::unique_ptr<protocol::FrameConsumer> owned_consumer_;
   protocol::FrameConsumer* const consumer_;
+
   protocol::FrameStatsConsumer* stats_consumer_ = nullptr;
 
   std::unique_ptr<VideoDecoder> decoder_;
diff --git a/remoting/client/software_video_renderer_unittest.cc b/remoting/client/software_video_renderer_unittest.cc
index dbac7d8dd..b4b5a055 100644
--- a/remoting/client/software_video_renderer_unittest.cc
+++ b/remoting/client/software_video_renderer_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
+#include "remoting/client/client_context.h"
 #include "remoting/codec/video_encoder_verbatim.h"
 #include "remoting/proto/video.pb.h"
 #include "remoting/protocol/frame_consumer.h"
@@ -134,17 +135,17 @@
 
 class SoftwareVideoRendererTest : public ::testing::Test {
  public:
-  SoftwareVideoRendererTest() : decode_thread_("TestDecodeThread") {
-    decode_thread_.Start();
-    renderer_.reset(new SoftwareVideoRenderer(decode_thread_.task_runner(),
-                                              &frame_consumer_, nullptr));
+  SoftwareVideoRendererTest() : context_(nullptr) {
+    context_.Start();
+    renderer_.reset(new SoftwareVideoRenderer(&frame_consumer_));
+    renderer_->Initialize(context_, nullptr);
     renderer_->OnSessionConfig(
         *protocol::SessionConfig::ForTestWithVerbatimVideo());
   }
 
  protected:
   base::MessageLoop message_loop_;
-  base::Thread decode_thread_;
+  ClientContext context_;
 
   TestFrameConsumer frame_consumer_;
   std::unique_ptr<SoftwareVideoRenderer> renderer_;
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index 720e4594..0df1ea9e 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -995,6 +995,12 @@
       if (is_mac) {
         extra_configs = [ "//remoting:version" ]
         info_plist = "remoting_me2me_host-Info.plist"
+        extra_substitutions = [
+          "BUNDLE_ID=$host_bundle_id",
+          "VERSION_FULL=$remoting_version_full",
+          "VERSION_SHORT=$remoting_version_short",
+          "MACOSX_DEPLOYMENT_TARGET=10.7",
+        ]
       } else {
         configs += [ "//remoting:version" ]
       }
@@ -1081,6 +1087,12 @@
       if (is_mac) {
         info_plist = "setup/native_messaging_host-Info.plist"
         extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
+        extra_substitutions = [
+          "BUNDLE_ID=$native_messaging_host_bundle_id",
+          "VERSION_FULL=$remoting_version_full",
+          "VERSION_SHORT=$remoting_version_short",
+          "MACOSX_DEPLOYMENT_TARGET=10.7",
+        ]
       } else {
         configs += [ "//build/config/compiler:wexit_time_destructors" ]
       }
@@ -1416,6 +1428,12 @@
 
     mac_app_bundle("remoting_host_uninstaller") {
       info_plist = _uninstaller_plist
+      extra_substitutions = [
+        "BUNDLE_ID=$uninstaller_bundle_id",
+        "VERSION_FULL=$remoting_version_full",
+        "VERSION_SHORT=$remoting_version_short",
+        "MACOSX_DEPLOYMENT_TARGET=10.7",
+      ]
 
       defines = [
         "HOST_BUNDLE_NAME=\"" + host_bundle_name + "\"",
@@ -1472,7 +1490,7 @@
       deps = [
         ":remoting_host_prefpane",
         ":remoting_host_prefpane_bundle_data",
-        ":remoting_host_prefpane_plist",
+        ":remoting_host_prefpane_plist_bundle_data",
         ":remoting_host_prefpane_resources",
         ":remoting_host_prefpane_xibs",
         ":remoting_infoplist_strings",
@@ -1537,13 +1555,25 @@
       }
     }
 
-    bundle_data("remoting_host_prefpane_plist") {
-      sources = [
-        "mac/me2me_preference_pane-Info.plist",
+    mac_info_plist("remoting_host_prefpane_plist") {
+      info_plist = "mac/me2me_preference_pane-Info.plist"
+      extra_substitutions = [
+        "BUNDLE_ID=$prefpane_bundle_id",
+        "VERSION_FULL=$remoting_version_full",
+        "VERSION_SHORT=$remoting_version_short",
+        "MACOSX_DEPLOYMENT_TARGET=10.7",
       ]
+      executable_name = "remoting_host_prefpane"
+    }
+
+    bundle_data("remoting_host_prefpane_plist_bundle_data") {
+      sources = get_target_outputs(":remoting_host_prefpane_plist")
       outputs = [
         "{{bundle_root_dir}}/Info.plist",
       ]
+      public_deps = [
+        ":remoting_host_prefpane_plist",
+      ]
     }
 
     foreach(locale, remoting_locales_with_underscores) {
diff --git a/remoting/host/installer/mac/uninstaller/remoting_uninstaller-Info.plist b/remoting/host/installer/mac/uninstaller/remoting_uninstaller-Info.plist
index 87a4e822..ab760e2 100644
--- a/remoting/host/installer/mac/uninstaller/remoting_uninstaller-Info.plist
+++ b/remoting/host/installer/mac/uninstaller/remoting_uninstaller-Info.plist
@@ -9,17 +9,17 @@
 	<key>CFBundleIconFile</key>
 	<string>remoting_uninstaller</string>
 	<key>CFBundleIdentifier</key>
-	<string>BUNDLE_ID</string>
+	<string>${BUNDLE_ID}</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>VERSION_SHORT</string>
+	<string>${VERSION_SHORT}</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>VERSION_FULL</string>
+	<string>${VERSION_FULL}</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
 	<key>NSMainNibFile</key>
diff --git a/remoting/host/it2me/BUILD.gn b/remoting/host/it2me/BUILD.gn
index dac44d3d..e97e871e 100644
--- a/remoting/host/it2me/BUILD.gn
+++ b/remoting/host/it2me/BUILD.gn
@@ -6,6 +6,7 @@
 import("//remoting/remoting_enable.gni")
 import("//remoting/remoting_srcs.gni")
 import("//remoting/remoting_locales.gni")
+import("//remoting/remoting_version.gni")
 
 if (is_win) {
   import("//remoting/host/predefines_win.gni")
@@ -119,6 +120,12 @@
     target(app_target_type, "remote_assistance_host") {
       if (is_mac) {
         info_plist = "remote_assistance_host-Info.plist"
+        extra_substitutions = [
+          "BUNDLE_ID=$remote_assistance_host_bundle_id",
+          "VERSION_FULL=$remoting_version_full",
+          "VERSION_SHORT=$remoting_version_short",
+          "MACOSX_DEPLOYMENT_TARGET=10.7",
+        ]
         extra_configs = [
           "//build/config/compiler:wexit_time_destructors",
           "//remoting:version",
diff --git a/remoting/host/it2me/remote_assistance_host-Info.plist b/remoting/host/it2me/remote_assistance_host-Info.plist
index f7149131..9e3a62c 100644
--- a/remoting/host/it2me/remote_assistance_host-Info.plist
+++ b/remoting/host/it2me/remote_assistance_host-Info.plist
@@ -9,7 +9,7 @@
   <key>CFBundleIconFile</key>
   <string>remote_assistance_host</string>
   <key>CFBundleIdentifier</key>
-  <string>BUNDLE_ID</string>
+  <string>${BUNDLE_ID}</string>
   <key>CFBundleInfoDictionaryVersion</key>
   <string>6.0</string>
   <key>CFBundleName</key>
@@ -19,9 +19,9 @@
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>
-  <string>VERSION_FULL</string>
+  <string>${VERSION_FULL}</string>
   <key>CFBundleShortVersionString</key>
-  <string>VERSION_SHORT</string>
+  <string>${VERSION_SHORT}</string>
   <key>LSMinimumSystemVersion</key>
   <string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
   <key>NSPrincipalClass</key>
@@ -31,6 +31,6 @@
   <key>BreakpadProduct</key>
   <string>Chromoting_Mac</string>
   <key>BreakpadVersion</key>
-  <string>VERSION_FULL</string>
+  <string>${VERSION_FULL}</string>
 </dict>
 </plist>
diff --git a/remoting/host/mac/me2me_preference_pane-Info.plist b/remoting/host/mac/me2me_preference_pane-Info.plist
index 001968e..d856360 100644
--- a/remoting/host/mac/me2me_preference_pane-Info.plist
+++ b/remoting/host/mac/me2me_preference_pane-Info.plist
@@ -9,17 +9,17 @@
 	<key>CFBundleIconFile</key>
 	<string></string>
 	<key>CFBundleIdentifier</key>
-	<string>BUNDLE_ID</string>
+	<string>${BUNDLE_ID}</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundlePackageType</key>
 	<string>BNDL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>VERSION_SHORT</string>
+	<string>${VERSION_SHORT}</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>VERSION_FULL</string>
+	<string>${VERSION_FULL}</string>
 	<key>NSMainNibFile</key>
 	<string>me2me_preference_pane</string>
 	<key>NSPrefPaneIconFile</key>
diff --git a/remoting/host/remoting_me2me_host-Info.plist b/remoting/host/remoting_me2me_host-Info.plist
index 1f2b9dfb..ea0375d2 100644
--- a/remoting/host/remoting_me2me_host-Info.plist
+++ b/remoting/host/remoting_me2me_host-Info.plist
@@ -9,7 +9,7 @@
   <key>CFBundleIconFile</key>
   <string>remoting_me2me_host</string>
   <key>CFBundleIdentifier</key>
-  <string>BUNDLE_ID</string>
+  <string>${BUNDLE_ID}</string>
   <key>CFBundleInfoDictionaryVersion</key>
   <string>6.0</string>
   <key>CFBundleName</key>
@@ -19,9 +19,9 @@
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>
-  <string>VERSION_FULL</string>
+  <string>${VERSION_FULL}</string>
   <key>CFBundleShortVersionString</key>
-  <string>VERSION_SHORT</string>
+  <string>${VERSION_SHORT}</string>
   <key>LSMinimumSystemVersion</key>
   <string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
   <key>NSPrincipalClass</key>
@@ -31,6 +31,6 @@
   <key>BreakpadProduct</key>
   <string>Chromoting_Mac</string>
   <key>BreakpadVersion</key>
-  <string>VERSION_FULL</string>
+  <string>${VERSION_FULL}</string>
 </dict>
 </plist>
diff --git a/remoting/host/setup/native_messaging_host-Info.plist b/remoting/host/setup/native_messaging_host-Info.plist
index fe01256..3a36510 100644
--- a/remoting/host/setup/native_messaging_host-Info.plist
+++ b/remoting/host/setup/native_messaging_host-Info.plist
@@ -9,7 +9,7 @@
   <key>CFBundleIconFile</key>
   <string>native_messaging_host</string>
   <key>CFBundleIdentifier</key>
-  <string>BUNDLE_ID</string>
+  <string>${BUNDLE_ID}</string>
   <key>CFBundleInfoDictionaryVersion</key>
   <string>6.0</string>
   <key>CFBundleName</key>
@@ -19,9 +19,9 @@
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>
-  <string>VERSION_FULL</string>
+  <string>${VERSION_FULL}</string>
   <key>CFBundleShortVersionString</key>
-  <string>VERSION_SHORT</string>
+  <string>${VERSION_SHORT}</string>
   <key>LSMinimumSystemVersion</key>
   <string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
   <key>NSPrincipalClass</key>
@@ -31,6 +31,6 @@
   <key>BreakpadProduct</key>
   <string>Chromoting_Mac</string>
   <key>BreakpadVersion</key>
-  <string>VERSION_FULL</string>
+  <string>${VERSION_FULL}</string>
 </dict>
 </plist>
diff --git a/remoting/proto/BUILD.gn b/remoting/proto/BUILD.gn
index 268b623..83c5bca 100644
--- a/remoting/proto/BUILD.gn
+++ b/remoting/proto/BUILD.gn
@@ -12,5 +12,6 @@
     "internal.proto",
     "mux.proto",
     "video.proto",
+    "video_stats.proto",
   ]
 }
diff --git a/remoting/proto/chromotocol.gyp b/remoting/proto/chromotocol.gyp
index 3f6778d..ef81c9b 100644
--- a/remoting/proto/chromotocol.gyp
+++ b/remoting/proto/chromotocol.gyp
@@ -18,6 +18,7 @@
         'internal.proto',
         'mux.proto',
         'video.proto',
+        'video_stats.proto',
       ],
       'variables': {
         'proto_out_dir': 'remoting/proto',
diff --git a/remoting/proto/video_stats.proto b/remoting/proto/video_stats.proto
new file mode 100644
index 0000000..7d73e3d
--- /dev/null
+++ b/remoting/proto/video_stats.proto
@@ -0,0 +1,42 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Internal message types that should not be seen outside the protocol
+// directory.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package remoting;
+
+message FrameStatsMessage {
+  // Frame ID.
+  optional int32 frame_id = 1;
+
+  // Frame size.
+  optional int32 frame_size = 2;
+
+  // Id of the last event that was injected before this frame was captured.
+  optional int64 latest_event_timestamp = 3;
+
+  // Time from when the last event was injected until capturing has started.
+  optional int32 capture_pending_time_ms = 4;
+
+  // Time in milliseconds spent in capturing this video frame.
+  optional int32 capture_time_ms = 5;
+
+  // Total overhead time for IPC and threading when capturing frames.
+  optional int32 capture_overhead_time_ms = 6;
+
+  // Time between when the frame was captured and when encoding started.
+  optional int32 encode_pending_time_ms = 7;
+
+  // Time in milliseconds spent in encoding this video frame.
+  optional int32 encode_time_ms = 8;
+
+  // Time for which the frame is blocked until it's sent to the client.
+  optional int64 send_pending_time_ms = 9;
+}
+
diff --git a/remoting/protocol/channel_dispatcher_base.cc b/remoting/protocol/channel_dispatcher_base.cc
index 399c2f3..fd8f21e8 100644
--- a/remoting/protocol/channel_dispatcher_base.cc
+++ b/remoting/protocol/channel_dispatcher_base.cc
@@ -14,7 +14,7 @@
 namespace remoting {
 namespace protocol {
 
-ChannelDispatcherBase::ChannelDispatcherBase(const char* channel_name)
+ChannelDispatcherBase::ChannelDispatcherBase(const std::string& channel_name)
     : channel_name_(channel_name) {}
 
 ChannelDispatcherBase::~ChannelDispatcherBase() {
@@ -57,6 +57,7 @@
 
 void ChannelDispatcherBase::OnMessagePipeClosed() {
   is_connected_ = false;
+  message_pipe_.reset();
   event_handler_->OnChannelClosed(this);
 }
 
diff --git a/remoting/protocol/channel_dispatcher_base.h b/remoting/protocol/channel_dispatcher_base.h
index 216ffad7..52e3e5d 100644
--- a/remoting/protocol/channel_dispatcher_base.h
+++ b/remoting/protocol/channel_dispatcher_base.h
@@ -40,10 +40,6 @@
     virtual void OnChannelClosed(ChannelDispatcherBase* channel_dispatcher) = 0;
   };
 
-  // The callback is called when initialization is finished. The
-  // parameter is set to true on success.
-  typedef base::Callback<void(bool)> InitializedCallback;
-
   ~ChannelDispatcherBase() override;
 
   // Creates and connects the channel using |channel_factory|.
@@ -60,7 +56,7 @@
   bool is_connected() { return is_connected_; }
 
  protected:
-  explicit ChannelDispatcherBase(const char* channel_name);
+  explicit ChannelDispatcherBase(const std::string& channel_name);
 
   MessagePipe* message_pipe() { return message_pipe_.get(); }
 
diff --git a/remoting/protocol/client_video_stats_dispatcher.cc b/remoting/protocol/client_video_stats_dispatcher.cc
new file mode 100644
index 0000000..19b49ba
--- /dev/null
+++ b/remoting/protocol/client_video_stats_dispatcher.cc
@@ -0,0 +1,47 @@
+// Copyright 2016 The Chromium Authors. 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/protocol/client_video_stats_dispatcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "net/socket/stream_socket.h"
+#include "remoting/base/compound_buffer.h"
+#include "remoting/proto/video_stats.pb.h"
+#include "remoting/protocol/frame_stats.h"
+#include "remoting/protocol/message_pipe.h"
+#include "remoting/protocol/message_serialization.h"
+#include "remoting/protocol/video_stats_stub.h"
+
+namespace remoting {
+namespace protocol {
+
+ClientVideoStatsDispatcher::ClientVideoStatsDispatcher(
+    const std::string& stream_name,
+    VideoStatsStub* video_stats_stub)
+    : ChannelDispatcherBase(kVideoStatsChannelNamePrefix + stream_name),
+      video_stats_stub_(video_stats_stub) {}
+
+ClientVideoStatsDispatcher::~ClientVideoStatsDispatcher() {}
+
+void ClientVideoStatsDispatcher::OnIncomingMessage(
+    std::unique_ptr<CompoundBuffer> message) {
+  std::unique_ptr<FrameStatsMessage> stats_proto =
+      ParseMessage<FrameStatsMessage>(message.get());
+  if (!stats_proto)
+    return;
+
+  if (!stats_proto->has_frame_id()) {
+    LOG(ERROR) << "Received invalid FrameStatsMessage.";
+    return;
+  }
+  video_stats_stub_->OnVideoFrameStats(
+      stats_proto->frame_id(),
+      HostFrameStats::FromFrameStatsMessage(*stats_proto));
+}
+
+}  // namespace protocol
+}  // namespace remoting
diff --git a/remoting/protocol/client_video_stats_dispatcher.h b/remoting/protocol/client_video_stats_dispatcher.h
new file mode 100644
index 0000000..a430b03
--- /dev/null
+++ b/remoting/protocol/client_video_stats_dispatcher.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. 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_PROTOCOL_CLIENT_VIDEO_STATE_DISPATCHER_H_
+#define REMOTING_PROTOCOL_CLIENT_VIDEO_STATE_DISPATCHER_H_
+
+#include <list>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "remoting/base/constants.h"
+#include "remoting/protocol/channel_dispatcher_base.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+
+namespace remoting {
+namespace protocol {
+
+class ClientStub;
+class VideoStatsStub;
+
+class ClientVideoStatsDispatcher : public ChannelDispatcherBase {
+ public:
+  ClientVideoStatsDispatcher(const std::string& stream_name,
+                             VideoStatsStub* video_stats_stub);
+  ~ClientVideoStatsDispatcher() override;
+
+ private:
+  void OnIncomingMessage(std::unique_ptr<CompoundBuffer> message) override;
+
+  VideoStatsStub* video_stats_stub_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClientVideoStatsDispatcher);
+};
+
+}  // namespace protocol
+}  // namespace remoting
+
+#endif  // REMOTING_PROTOCOL_CLIENT_VIDEO_STATE_DISPATCHER_H_
diff --git a/remoting/protocol/frame_consumer.h b/remoting/protocol/frame_consumer.h
index be9c881..6581168 100644
--- a/remoting/protocol/frame_consumer.h
+++ b/remoting/protocol/frame_consumer.h
@@ -20,6 +20,8 @@
 
 class FrameConsumer {
  public:
+  virtual ~FrameConsumer() {}
+
   // List of supported pixel formats needed by various platforms.
   enum PixelFormat {
     FORMAT_BGRA,  // Used by the Pepper plugin.
@@ -37,7 +39,6 @@
 
  protected:
   FrameConsumer() {}
-  virtual ~FrameConsumer() {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FrameConsumer);
diff --git a/remoting/protocol/frame_stats.cc b/remoting/protocol/frame_stats.cc
index 37ec56e..80bf7c29 100644
--- a/remoting/protocol/frame_stats.cc
+++ b/remoting/protocol/frame_stats.cc
@@ -5,6 +5,7 @@
 #include "remoting/protocol/frame_stats.h"
 
 #include "remoting/proto/video.pb.h"
+#include "remoting/proto/video_stats.pb.h"
 
 namespace remoting {
 namespace protocol {
@@ -54,6 +55,75 @@
   return result;
 }
 
+// static
+HostFrameStats HostFrameStats::FromFrameStatsMessage(
+    const FrameStatsMessage& message) {
+  HostFrameStats result;
+  result.frame_size = message.frame_size();
+  if (message.has_latest_event_timestamp()) {
+    result.latest_event_timestamp =
+        base::TimeTicks::FromInternalValue(message.latest_event_timestamp());
+  }
+  if (message.has_capture_time_ms()) {
+    result.capture_delay =
+        base::TimeDelta::FromMilliseconds(message.capture_time_ms());
+  }
+  if (message.has_encode_time_ms()) {
+    result.encode_delay =
+        base::TimeDelta::FromMilliseconds(message.encode_time_ms());
+  }
+  if (message.has_capture_pending_time_ms()) {
+    result.capture_pending_delay =
+        base::TimeDelta::FromMilliseconds(message.capture_pending_time_ms());
+  }
+  if (message.has_capture_overhead_time_ms()) {
+    result.capture_overhead_delay =
+        base::TimeDelta::FromMilliseconds(message.capture_overhead_time_ms());
+  }
+  if (message.has_encode_pending_time_ms()) {
+    result.encode_pending_delay =
+        base::TimeDelta::FromMilliseconds(message.encode_pending_time_ms());
+  }
+
+  if (message.has_send_pending_time_ms()) {
+    result.send_pending_delay =
+        base::TimeDelta::FromMilliseconds(message.send_pending_time_ms());
+  }
+
+  return result;
+}
+
+void HostFrameStats::ToFrameStatsMessage(FrameStatsMessage* message_out) const {
+  message_out->set_frame_size(frame_size);
+
+  if (!latest_event_timestamp.is_null()) {
+    message_out->set_latest_event_timestamp(
+        latest_event_timestamp.ToInternalValue());
+  }
+  if (capture_delay != base::TimeDelta::Max()) {
+    message_out->set_capture_time_ms(capture_delay.InMilliseconds());
+  }
+  if (encode_delay != base::TimeDelta::Max()) {
+    message_out->set_encode_time_ms(encode_delay.InMilliseconds());
+  }
+  if (capture_pending_delay != base::TimeDelta::Max()) {
+    message_out->set_capture_pending_time_ms(
+        capture_pending_delay.InMilliseconds());
+  }
+  if (capture_overhead_delay != base::TimeDelta::Max()) {
+    message_out->set_capture_overhead_time_ms(
+        capture_overhead_delay.InMilliseconds());
+  }
+  if (encode_pending_delay != base::TimeDelta::Max()) {
+    message_out->set_encode_pending_time_ms(
+        encode_pending_delay.InMilliseconds());
+  }
+  if (send_pending_delay != base::TimeDelta::Max()) {
+    message_out->set_send_pending_time_ms(send_pending_delay.InMilliseconds());
+  }
+
+}
+
 FrameStats::FrameStats() = default;
 FrameStats::FrameStats(const FrameStats&) = default;
 FrameStats::~FrameStats() = default;
diff --git a/remoting/protocol/frame_stats.h b/remoting/protocol/frame_stats.h
index c2c5ad9..7727b712 100644
--- a/remoting/protocol/frame_stats.h
+++ b/remoting/protocol/frame_stats.h
@@ -22,6 +22,10 @@
   // Extracts timing fields from the |packet|.
   static HostFrameStats GetForVideoPacket(const VideoPacket& packet);
 
+  // Converts FrameStatsMessage protobuf message to HostFrameStats.
+  static HostFrameStats FromFrameStatsMessage(const FrameStatsMessage& message);
+  void ToFrameStatsMessage(FrameStatsMessage* message_out) const;
+
   // Frame Size.
   int frame_size {};
 
diff --git a/remoting/protocol/host_video_stats_dispatcher.cc b/remoting/protocol/host_video_stats_dispatcher.cc
new file mode 100644
index 0000000..2185fb3
--- /dev/null
+++ b/remoting/protocol/host_video_stats_dispatcher.cc
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. 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/protocol/host_video_stats_dispatcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "net/socket/stream_socket.h"
+#include "remoting/base/compound_buffer.h"
+#include "remoting/base/constants.h"
+#include "remoting/proto/video_stats.pb.h"
+#include "remoting/protocol/frame_stats.h"
+#include "remoting/protocol/message_pipe.h"
+#include "remoting/protocol/message_serialization.h"
+#include "remoting/protocol/video_stats_stub.h"
+
+namespace remoting {
+namespace protocol {
+
+HostVideoStatsDispatcher::HostVideoStatsDispatcher(
+    const std::string& stream_name)
+    : ChannelDispatcherBase(kVideoStatsChannelNamePrefix + stream_name) {}
+
+HostVideoStatsDispatcher::~HostVideoStatsDispatcher() {}
+
+void HostVideoStatsDispatcher::OnVideoFrameStats(uint32_t frame_id,
+                                                 const HostFrameStats& stats) {
+  FrameStatsMessage message;
+  message.set_frame_id(frame_id);
+  stats.ToFrameStatsMessage(&message);
+  message_pipe()->Send(&message, base::Closure());
+}
+
+void HostVideoStatsDispatcher::OnIncomingMessage(
+    std::unique_ptr<CompoundBuffer> message) {}
+
+}  // namespace protocol
+}  // namespace remoting
diff --git a/remoting/protocol/host_video_stats_dispatcher.h b/remoting/protocol/host_video_stats_dispatcher.h
new file mode 100644
index 0000000..2824905
--- /dev/null
+++ b/remoting/protocol/host_video_stats_dispatcher.h
@@ -0,0 +1,35 @@
+// Copyright 2016 The Chromium Authors. 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_PROTOCOL_HOST_VIDEO_STATE_DISPATCHER_H_
+#define REMOTING_PROTOCOL_HOST_VIDEO_STATE_DISPATCHER_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "remoting/protocol/channel_dispatcher_base.h"
+#include "remoting/protocol/video_stats_stub.h"
+
+namespace remoting {
+namespace protocol {
+
+class HostVideoStatsDispatcher : public ChannelDispatcherBase,
+                                 public VideoStatsStub {
+ public:
+  explicit HostVideoStatsDispatcher(const std::string& stream_name);
+  ~HostVideoStatsDispatcher() override;
+
+  // VideoStatsStub interface.
+  void OnVideoFrameStats(uint32_t frame_id,
+                         const HostFrameStats& frame_stats) override;
+
+ private:
+  void OnIncomingMessage(std::unique_ptr<CompoundBuffer> message) override;
+
+  DISALLOW_COPY_AND_ASSIGN(HostVideoStatsDispatcher);
+};
+
+}  // namespace protocol
+}  // namespace remoting
+
+#endif  // REMOTING_PROTOCOL_HOST_VIDEO_STATE_DISPATCHER_H_
diff --git a/remoting/protocol/video_stats_stub.h b/remoting/protocol/video_stats_stub.h
new file mode 100644
index 0000000..28ddbba1
--- /dev/null
+++ b/remoting/protocol/video_stats_stub.h
@@ -0,0 +1,34 @@
+// 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 REMOTING_PROTOCOL_VIDEO_STATE_STUB_H_
+#define REMOTING_PROTOCOL_VIDEO_STATE_STUB_H_
+
+#include <cstdint>
+
+#include "base/macros.h"
+
+namespace remoting {
+namespace protocol {
+
+struct HostFrameStats;
+
+// Interface used to send video frame stats from host to client.
+class VideoStatsStub {
+ public:
+  virtual void OnVideoFrameStats(uint32_t frame_id,
+                                 const HostFrameStats& frame_stats) = 0;
+
+ protected:
+  VideoStatsStub() {}
+  virtual ~VideoStatsStub() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VideoStatsStub);
+};
+
+}  // namespace protocol
+}  // namespace remoting
+
+#endif  // REMOTING_PROTOCOL_VIDEO_SSTATE_TUB_H_
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi
index 57b3e93..8b670e6 100644
--- a/remoting/remoting_host.gypi
+++ b/remoting/remoting_host.gypi
@@ -474,8 +474,9 @@
               },
               'xcode_settings': {
                 'INFOPLIST_FILE': 'host/remoting_me2me_host-Info.plist',
-                'INFOPLIST_PREPROCESS': 'YES',
-                'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(host_bundle_id)"',
+                'VERSION_FULL': '<(version_full)',
+                'VERSION_SHORT': '<(version_short)',
+                'BUNDLE_ID': '<(host_bundle_id)',
               },
               'mac_bundle_resources': [
                 '<(PRODUCT_DIR)/icudtl.dat',
@@ -559,8 +560,9 @@
               },
               'xcode_settings': {
                 'INFOPLIST_FILE': 'host/setup/native_messaging_host-Info.plist',
-                'INFOPLIST_PREPROCESS': 'YES',
-                'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(host_bundle_id)"',
+                'VERSION_FULL': '<(version_full)',
+                'VERSION_SHORT': '<(version_short)',
+                'BUNDLE_ID': '<(host_bundle_id)',
               },
               'mac_bundle_resources': [
                 'host/setup/native_messaging_host-Info.plist',
@@ -672,8 +674,9 @@
                   },
                   'xcode_settings': {
                     'INFOPLIST_FILE': 'host/it2me/remote_assistance_host-Info.plist',
-                    'INFOPLIST_PREPROCESS': 'YES',
-                    'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(host_bundle_id)"',
+                    'VERSION_FULL': '<(version_full)',
+                    'VERSION_SHORT': '<(version_short)',
+                    'BUNDLE_ID': '<(host_bundle_id)',
                   },
                   'mac_bundle_resources': [
                     '<(PRODUCT_DIR)/icudtl.dat',
diff --git a/remoting/remoting_host_mac.gypi b/remoting/remoting_host_mac.gypi
index fb03e282..db9bea8f 100644
--- a/remoting/remoting_host_mac.gypi
+++ b/remoting/remoting_host_mac.gypi
@@ -52,8 +52,9 @@
       ],
       'xcode_settings': {
         'INFOPLIST_FILE': 'host/installer/mac/uninstaller/remoting_uninstaller-Info.plist',
-        'INFOPLIST_PREPROCESS': 'YES',
-        'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(bundle_id)"',
+        'VERSION_FULL': '<(version_full)',
+        'VERSION_SHORT': '<(version_short)',
+        'BUNDLE_ID': '<(bundle_id)',
       },
       'mac_bundle_resources': [
         'host/installer/mac/uninstaller/remoting_uninstaller.icns',
@@ -212,8 +213,9 @@
       'xcode_settings': {
         'GCC_ENABLE_OBJC_GC': 'supported',
         'INFOPLIST_FILE': 'host/mac/me2me_preference_pane-Info.plist',
-        'INFOPLIST_PREPROCESS': 'YES',
-        'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(bundle_id)"',
+        'VERSION_FULL': '<(version_full)',
+        'VERSION_SHORT': '<(version_short)',
+        'BUNDLE_ID': '<(bundle_id)',
       },
       'mac_bundle_resources': [
         'host/mac/me2me_preference_pane.xib',
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi
index 3268bb89..6e1c3d8 100644
--- a/remoting/remoting_srcs.gypi
+++ b/remoting/remoting_srcs.gypi
@@ -100,6 +100,8 @@
       'protocol/client_stub.h',
       'protocol/client_video_dispatcher.cc',
       'protocol/client_video_dispatcher.h',
+      'protocol/client_video_stats_dispatcher.cc',
+      'protocol/client_video_stats_dispatcher.h',
       'protocol/clipboard_echo_filter.cc',
       'protocol/clipboard_echo_filter.h',
       'protocol/clipboard_filter.cc',
@@ -125,6 +127,8 @@
       'protocol/host_stub.h',
       'protocol/host_video_dispatcher.cc',
       'protocol/host_video_dispatcher.h',
+      'protocol/host_video_stats_dispatcher.cc',
+      'protocol/host_video_stats_dispatcher.h',
       'protocol/http_ice_config_request.cc',
       'protocol/http_ice_config_request.h',
       'protocol/ice_config.cc',
@@ -224,6 +228,7 @@
       'protocol/v2_authenticator.cc',
       'protocol/v2_authenticator.h',
       'protocol/video_renderer.h',
+      'protocol/video_stats_stub.h',
       'protocol/video_stub.h',
     ],
 
@@ -292,6 +297,8 @@
       'client/client_telemetry_logger.cc',
       'client/client_telemetry_logger.h',
       'client/client_user_interface.h',
+      'client/dual_buffer_frame_consumer.cc',
+      'client/dual_buffer_frame_consumer.h',
       'client/empty_cursor_filter.cc',
       'client/empty_cursor_filter.h',
       'client/key_event_mapper.cc',
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi
index d42839b..d4e0c73 100644
--- a/remoting/remoting_test.gypi
+++ b/remoting/remoting_test.gypi
@@ -223,9 +223,6 @@
       'defines': [
         'VERSION=<(version_full)',
       ],
-      'include_dirs': [
-        '../testing/gmock/include',
-      ],
       'sources': [
         # Note: sources list duplicated in GN build.
         'base/auto_thread_task_runner_unittest.cc',
@@ -246,6 +243,7 @@
         'client/chromoting_client_runtime_unittest.cc',
         'client/client_status_logger_unittest.cc',
         'client/client_telemetry_logger_unittest.cc',
+        'client/dual_buffer_frame_consumer_unittest.cc',
         'client/empty_cursor_filter_unittest.cc',
         'client/key_event_mapper_unittest.cc',
         'client/normalizing_input_filter_cros_unittest.cc',
@@ -574,9 +572,6 @@
           'defines': [
             'VERSION=<(version_full)',
           ],
-          'include_dirs': [
-            '../testing/gmock/include',
-          ],
           'sources': [
             'base/run_all_unittests.cc',
             'test/codec_perftest.cc',
diff --git a/remoting/remoting_version.gni b/remoting/remoting_version.gni
index 13e5162b..565011b1 100644
--- a/remoting/remoting_version.gni
+++ b/remoting/remoting_version.gni
@@ -3,9 +3,11 @@
 # found in the LICENSE file.
 
 import("//build/config/chrome_build.gni")
+import("//build/util/version.gni")
+
+remoting_version_file = "//remoting/VERSION"
 
 _version_py_abspath = "//build/util/version.py"
-_remoting_version_abspath = "//remoting/VERSION"
 if (is_chrome_branded) {
   _remoting_branding_abspath = "//remoting/branding_Chrome"
 } else {
@@ -15,22 +17,42 @@
 # Set these files as being input dependencies to the scripts, so the build will
 # be re-run if the files change.
 remoting_version_files = [
-  _remoting_version_abspath,
+  remoting_version_file,
   _remoting_branding_abspath,
 ]
 
-_remoting_version_path = rebase_path(_remoting_version_abspath, root_build_dir)
+_remoting_version_path = rebase_path(remoting_version_file, root_build_dir)
 _remoting_branding_path =
     rebase_path(_remoting_branding_abspath, root_build_dir)
 
-_branding_dictionary_template = "mac_host_bundle = \"@MAC_HOST_BUNDLE_NAME@\" " + "mac_native_messaging_bundle = \"@MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME@\" " + "mac_remote_assistance_bundle = \"@MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME@\" " + "prefpane_bundle_name = \"@MAC_PREFPANE_BUNDLE_NAME@\" " + "host_bundle_name = \"@MAC_HOST_BUNDLE_NAME@\" " + "host_name= \"@MAC_HOST_PACKAGE_NAME@\" " + "host_service_name = \"@DAEMON_FILE_NAME@\" " + "bundle_prefix = \"@MAC_UNINSTALLER_BUNDLE_PREFIX@\" " + "host_uninstaller_name = \"@MAC_UNINSTALLER_NAME@\""
+_template = "mac_host_bundle = \"@MAC_HOST_BUNDLE_NAME@\" "
+_template +=
+    "mac_native_messaging_bundle = \"@MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME@\" "
+_template += "mac_remote_assistance_bundle = \"@MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME@\" "
+_template += "prefpane_bundle_name = \"@MAC_PREFPANE_BUNDLE_NAME@\" "
+_template += "host_bundle_name = \"@MAC_HOST_BUNDLE_NAME@\" "
+_template += "host_name= \"@MAC_HOST_PACKAGE_NAME@\" "
+_template += "host_service_name = \"@DAEMON_FILE_NAME@\" "
+_template += "bundle_prefix = \"@MAC_UNINSTALLER_BUNDLE_PREFIX@\" "
+_template += "host_uninstaller_name = \"@MAC_UNINSTALLER_NAME@\" "
+_template += "version_patch = \"@REMOTING_PATCH@\" "
+
+if (is_mac) {
+  _template += "host_bundle_id = \"@MAC_HOST_BUNDLE_ID@\" "
+  _template += "native_messaging_host_bundle_id = \"@MAC_NATIVE_MESSAGING_HOST_BUNDLE_ID@\""
+  _template += "prefpane_bundle_id = \"@MAC_PREFPANE_BUNDLE_ID@\" "
+  _template += "remote_assistance_host_bundle_id = \"@MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID@\" "
+  _template += "uninstaller_bundle_id = \"@MAC_UNINSTALLER_BUNDLE_ID@\""
+}
 
 _result = exec_script(_version_py_abspath,
                       [
                         "-f",
                         _remoting_branding_path,
+                        "-f",
+                        _remoting_version_path,
                         "-t",
-                        _branding_dictionary_template,
+                        _template,
                       ],
                       "scope",
                       remoting_version_files)
@@ -44,3 +66,15 @@
 me2me_host_bundle_name = _result.mac_host_bundle
 native_messaging_host_bundle_name = _result.mac_native_messaging_bundle
 remote_assistance_host_bundle_name = _result.mac_remote_assistance_bundle
+remoting_version_patch = _result.version_patch
+remoting_version_short =
+    "$chrome_version_major.$remoting_version_patch.$chrome_version_build"
+remoting_version_full = "$remoting_version_short.$chrome_version_patch"
+
+if (is_mac) {
+  host_bundle_id = _result.host_bundle_id
+  native_messaging_host_bundle_id = _result.native_messaging_host_bundle_id
+  prefpane_bundle_id = _result.prefpane_bundle_id
+  remote_assistance_host_bundle_id = _result.remote_assistance_host_bundle_id
+  uninstaller_bundle_id = _result.uninstaller_bundle_id
+}
diff --git a/remoting/webapp/js_proto/chrome_mocks.js b/remoting/webapp/js_proto/chrome_mocks.js
index d3dfd95..9590c7c 100644
--- a/remoting/webapp/js_proto/chrome_mocks.js
+++ b/remoting/webapp/js_proto/chrome_mocks.js
@@ -113,7 +113,7 @@
   return port;
 };
 
-/** @const {Object<!chromeMocks.runtime.Port>} */
+/** @type {Object<!chromeMocks.runtime.Port>} */
 var nativePorts = null;
 
 /** @type {string} */
diff --git a/services/ui/service.cc b/services/ui/service.cc
index b11c4cf..d4eca9cc 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -75,7 +75,6 @@
 };
 
 struct Service::UserState {
-  std::unique_ptr<clipboard::ClipboardImpl> clipboard;
   std::unique_ptr<ws::AccessibilityManager> accessibility;
   std::unique_ptr<ws::WindowTreeHostFactory> window_tree_host_factory;
 };
@@ -296,10 +295,8 @@
 
 void Service::Create(shell::Connection* connection,
                      mojom::ClipboardRequest request) {
-  UserState* user_state = GetUserState(connection);
-  if (!user_state->clipboard)
-    user_state->clipboard.reset(new clipboard::ClipboardImpl);
-  user_state->clipboard->AddBinding(std::move(request));
+  const ws::UserId& user_id = connection->GetRemoteIdentity().user_id();
+  window_server_->GetClipboardForUser(user_id)->AddBinding(std::move(request));
 }
 
 void Service::Create(shell::Connection* connection,
diff --git a/services/ui/surfaces/display_compositor.cc b/services/ui/surfaces/display_compositor.cc
index b1a3024..c6679dfe 100644
--- a/services/ui/surfaces/display_compositor.cc
+++ b/services/ui/surfaces/display_compositor.cc
@@ -31,7 +31,7 @@
       surfaces_state_(surfaces_state),
       factory_(surfaces_state->manager(), this),
       allocator_(surfaces_state->next_client_id()) {
-  allocator_.RegisterSurfaceClientId(surfaces_state_->manager());
+  surfaces_state_->manager()->RegisterSurfaceClientId(allocator_.client_id());
   surfaces_state_->manager()->RegisterSurfaceFactoryClient(
       allocator_.client_id(), this);
 
@@ -78,6 +78,7 @@
 DisplayCompositor::~DisplayCompositor() {
   surfaces_state_->manager()->UnregisterSurfaceFactoryClient(
       allocator_.client_id());
+  surfaces_state_->manager()->InvalidateSurfaceClientId(allocator_.client_id());
 }
 
 void DisplayCompositor::SubmitCompositorFrame(
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn
index 2291568..5160f60 100644
--- a/services/ui/ws/BUILD.gn
+++ b/services/ui/ws/BUILD.gn
@@ -112,6 +112,7 @@
     "//services/shell/public/cpp",
     "//services/shell/public/interfaces",
     "//services/tracing/public/cpp",
+    "//services/ui/clipboard:lib",
     "//services/ui/common:mus_common",
     "//services/ui/display",
     "//services/ui/gles2",
diff --git a/services/ui/ws/server_window_surface.cc b/services/ui/ws/server_window_surface.cc
index 6f8f525..fd7be5e 100644
--- a/services/ui/ws/server_window_surface.cc
+++ b/services/ui/ws/server_window_surface.cc
@@ -27,7 +27,7 @@
       client_(std::move(client)),
       binding_(this, std::move(request)) {
   cc::SurfaceManager* surface_manager = manager_->GetSurfaceManager();
-  surface_id_allocator_.RegisterSurfaceClientId(surface_manager);
+  surface_manager->RegisterSurfaceClientId(surface_id_allocator_.client_id());
   surface_manager->RegisterSurfaceFactoryClient(
       surface_id_allocator_.client_id(), this);
 }
@@ -40,6 +40,7 @@
   cc::SurfaceManager* surface_manager = manager_->GetSurfaceManager();
   surface_manager->UnregisterSurfaceFactoryClient(
       surface_id_allocator_.client_id());
+  surface_manager->InvalidateSurfaceClientId(surface_id_allocator_.client_id());
 }
 
 void ServerWindowSurface::SubmitCompositorFrame(
diff --git a/services/ui/ws/window_manager_state.cc b/services/ui/ws/window_manager_state.cc
index 4f4d2eee..cbec88f 100644
--- a/services/ui/ws/window_manager_state.cc
+++ b/services/ui/ws/window_manager_state.cc
@@ -496,12 +496,14 @@
       tree = window_server()->GetTreeWithId(window->id().client_id);
   }
 
-  const ServerWindow* embed_root =
-      tree->HasRoot(window) ? window : GetEmbedRoot(window);
-  while (tree && tree->embedder_intercepts_events()) {
-    DCHECK(tree->HasRoot(embed_root));
-    tree = window_server()->GetTreeWithId(embed_root->id().client_id);
-    embed_root = GetEmbedRoot(embed_root);
+  if (tree) {
+    const ServerWindow* embed_root =
+        tree->HasRoot(window) ? window : GetEmbedRoot(window);
+    while (tree && tree->embedder_intercepts_events()) {
+      DCHECK(tree->HasRoot(embed_root));
+      tree = window_server()->GetTreeWithId(embed_root->id().client_id);
+      embed_root = GetEmbedRoot(embed_root);
+    }
   }
 
   if (!tree) {
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc
index 92aa4ae..8403378 100644
--- a/services/ui/ws/window_server.cc
+++ b/services/ui/ws/window_server.cc
@@ -242,6 +242,12 @@
   delegate_->CreateDefaultDisplays();
 }
 
+ui::clipboard::ClipboardImpl* WindowServer::GetClipboardForUser(
+    const UserId& user_id) {
+  DCHECK_GT(clipboard_map_.count(user_id), 0u);
+  return clipboard_map_[user_id].get();
+}
+
 UserActivityMonitor* WindowServer::GetUserActivityMonitorForUser(
     const UserId& user_id) {
   DCHECK_GT(activity_monitor_map_.count(user_id), 0u);
@@ -769,10 +775,12 @@
 
 void WindowServer::OnUserIdAdded(const UserId& id) {
   activity_monitor_map_[id] = base::MakeUnique<UserActivityMonitor>(nullptr);
+  clipboard_map_[id] = base::MakeUnique<clipboard::ClipboardImpl>();
 }
 
 void WindowServer::OnUserIdRemoved(const UserId& id) {
   activity_monitor_map_.erase(id);
+  clipboard_map_.erase(id);
 }
 
 }  // namespace ws
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h
index 8978098..1ff4e3b 100644
--- a/services/ui/ws/window_server.h
+++ b/services/ui/ws/window_server.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/array.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/ui/clipboard/clipboard_impl.h"
 #include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "services/ui/public/interfaces/window_tree_host.mojom.h"
@@ -131,6 +132,8 @@
 
   void OnFirstWindowManagerWindowTreeFactoryReady();
 
+  clipboard::ClipboardImpl* GetClipboardForUser(const UserId& user_id);
+
   UserActivityMonitor* GetUserActivityMonitorForUser(const UserId& user_id);
 
   WindowManagerWindowTreeFactorySet* window_manager_window_tree_factory_set() {
@@ -218,6 +221,8 @@
       std::map<ClientSpecificId, std::unique_ptr<WindowTree>>;
   using UserActivityMonitorMap =
       std::map<UserId, std::unique_ptr<UserActivityMonitor>>;
+  using UserClipboardMap =
+      std::map<UserId, std::unique_ptr<ui::clipboard::ClipboardImpl>>;
 
   struct InFlightWindowManagerChange {
     // Identifies the client that initiated the change.
@@ -350,6 +355,7 @@
   base::Callback<void(ServerWindow*)> window_paint_callback_;
 
   UserActivityMonitorMap activity_monitor_map_;
+  UserClipboardMap clipboard_map_;
 
   WindowManagerWindowTreeFactorySet window_manager_window_tree_factory_set_;
 
diff --git a/skia/ext/SkMemory_new_handler.cpp b/skia/ext/SkMemory_new_handler.cpp
index b45ad1c..c90a8921 100644
--- a/skia/ext/SkMemory_new_handler.cpp
+++ b/skia/ext/SkMemory_new_handler.cpp
@@ -34,13 +34,8 @@
 
 void sk_out_of_memory(void) {
     SkASSERT(!"sk_out_of_memory");
-#if defined(OS_WIN)
-    // Kill the process. This is important for security since most of code
-    // does not check the result of memory allocation.
-    // https://msdn.microsoft.com/en-us/library/het71c37.aspx
-    ::RaiseException(base::win::kOomExceptionCode, EXCEPTION_NONCONTINUABLE, 0,
-                     nullptr);
-#endif
+    base::TerminateBecauseOutOfMemory(0);
+    // Extra safety abort().
     abort();
 }
 
diff --git a/testing/gmock.gyp b/testing/gmock.gyp
index d6bf3a1..6ef2566 100644
--- a/testing/gmock.gyp
+++ b/testing/gmock.gyp
@@ -36,11 +36,12 @@
         'gmock/src/gmock-all.cc',  # Not needed by our build.
       ],
       'include_dirs': [
-        'gmock',
+        'gmock_custom',
         'gmock/include',
       ],
       'all_dependent_settings': {
         'include_dirs': [
+          'gmock_custom',
           'gmock/include',  # So that gmock headers can find themselves.
         ],
       },
diff --git a/testing/gmock_custom/gmock/internal/custom/gmock-port.h b/testing/gmock_custom/gmock/internal/custom/gmock-port.h
new file mode 100644
index 0000000..f8eb6cd4
--- /dev/null
+++ b/testing/gmock_custom/gmock/internal/custom/gmock-port.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_GMOCK_CUSTOM_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+#define TESTING_GMOCK_CUSTOM_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+
+#include <type_traits>
+
+namespace std {
+
+// Provide alternative implementation of std::is_default_constructible for
+// old, pre-4.7 of libstdc++, where is_default_constructible is missing.
+// <20120322 below implies pre-4.7.0. In addition we blacklist several version
+// that released after 4.7.0 from pre-4.7.0 branch. 20120702 implies 4.5.4, and
+// 20121127 implies 4.6.4.
+#if defined(__GLIBCXX__) &&   \
+  (__GLIBCXX__ < 20120322 ||  \
+   __GLIBCXX__ == 20120702 || \
+   __GLIBCXX__ == 20121127)
+template <typename T>
+using is_default_constructible = std::is_constructible<T>;
+#endif
+
+}
+
+#endif  // TESTING_GMOCK_CUSTOM_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
diff --git a/testing/gtest.gyp b/testing/gtest.gyp
index ec8be2a..f551d1df 100644
--- a/testing/gtest.gyp
+++ b/testing/gtest.gyp
@@ -25,8 +25,6 @@
         # In order to allow regex matches in gtest to be shared between Windows
         # and other systems, we tell gtest to always use it's internal engine.
         'GTEST_HAS_POSIX_RE=0',
-        # Chrome doesn't support / require C++11, yet.
-        'GTEST_LANG_CXX11=0',
       ],
       'all_dependent_settings': {
         'include_dirs': [
@@ -34,7 +32,6 @@
         ],
         'defines': [
           'GTEST_HAS_POSIX_RE=0',
-          'GTEST_LANG_CXX11=0',
         ],
       },
       'conditions': [
diff --git a/testing/gtest_nacl.gyp b/testing/gtest_nacl.gyp
index d1c0ce0..910c9e3 100644
--- a/testing/gtest_nacl.gyp
+++ b/testing/gtest_nacl.gyp
@@ -36,20 +36,10 @@
             # Windows and other systems, we tell gtest to always use it's
             # internal engine.
             'GTEST_HAS_POSIX_RE=0',
-            'GTEST_LANG_CXX11=0',
-            # gtest isn't able to figure out when RTTI is disabled for gcc
-            # versions older than 4.3.2, and assumes it's enabled.  Our Mac
-            # and Linux builds disable RTTI, and cannot guarantee that the
-            # compiler will be 4.3.2. or newer.  The Mac, for example, uses
-            # 4.2.1 as that is the latest available on that platform.  gtest
-            # must be instructed that RTTI is disabled here, and for any
-            # direct dependents that might include gtest headers.
-            'GTEST_HAS_RTTI=0',
           ],
           'all_dependent_settings': {
             'defines': [
               'GTEST_HAS_POSIX_RE=0',
-              'GTEST_LANG_CXX11=0',
             ],
             'link_flags': [
               '-lgtest_nacl',
@@ -58,7 +48,6 @@
           'direct_dependent_settings': {
             'defines': [
               'UNIT_TEST',
-              'GTEST_HAS_RTTI=0',
             ],
             'include_dirs': [
               'gtest/include',  # So that gtest headers can find themselves.
diff --git a/testing/test.gni b/testing/test.gni
index 0f06c6b4..18f4f94 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -281,7 +281,7 @@
     _resources_bundle_data = target_name + "_resources_bundle_data"
 
     bundle_data(_resources_bundle_data) {
-      visibility = [ ":*" ]
+      visibility = [ ":$_test_target" ]
       sources = [
         "//testing/gtest_ios/Default.png",
       ]
@@ -320,12 +320,14 @@
         deps = []
       }
       deps += [
-        ":$_resources_bundle_data",
-
         # All shared libraries must have the sanitizer deps to properly link in
         # asan mode (this target will be empty in other cases).
         "//build/config/sanitizers:deps",
       ]
+      if (!defined(bundle_deps)) {
+        bundle_deps = []
+      }
+      bundle_deps += [ ":$_resources_bundle_data" ]
     }
   } else {
     executable(target_name) {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index cb16792..616337c0 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -143,8 +143,6 @@
 crbug.com/567965 [ Debug ] imported/wpt/user-timing/test_user_timing_mark.html [ Skip ]
 crbug.com/518993 imported/wpt/user-timing/test_user_timing_measure_navigation_timing.html [ Skip ]
 
-crbug.com/526594 [ Win ] plugins/webview-plugin-lifecycle.html [ Failure ]
-
 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/410949 http/tests/security/local-image-from-remote-whitelisted.html [ Failure Pass ]
@@ -756,7 +754,6 @@
 crbug.com/564403 http/tests/inspector/service-workers/service-worker-manager.html [ Failure Pass ]
 
 crbug.com/613728 fast/table/border-collapsing/cached-cell-append.html [ Failure ]
-crbug.com/613728 fast/table/border-collapsing/cached-cell-remove.html [ Failure ]
 crbug.com/613728 fast/table/border-collapsing/cached-69296.html [ Failure ]
 crbug.com/613728 fast/table/border-collapsing/cached-change-table-border-width.html [ Failure ]
 
@@ -876,7 +873,6 @@
 crbug.com/498021 [ Linux ] fast/text/international/danda-space.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/international/hindi-whitespace.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/selection-multiple-runs.html [ Failure ]
-crbug.com/498021 [ Linux ] editing/pasteboard/4944770-2.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/encoding/invalid-UTF-8.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/emoticons.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/international/hindi-spacing.html [ Failure ]
@@ -1103,8 +1099,6 @@
 crbug.com/619103 virtual/rootlayerscrolls/fast/scrolling/background-paint-scrolled.html [ Crash Timeout ]
 crbug.com/619103 [ Debug ] fast/layers/remove-layer-with-nested-stacking.html [ Crash Timeout ]
 
-crbug.com/443596 media/sources-fallback-codecs.html [ Pass Failure ]
-
 crbug.com/464736 http/tests/xmlhttprequest/ontimeout-event-override-after-failure.html [ Pass Failure ]
 
 crbug.com/595483 [ Android ] editing/caret/caret-color.html [ Failure Crash ]
@@ -1214,8 +1208,6 @@
 crbug.com/572723 [ Linux Mac10.9 ] inspector/sources/debugger/debugger-disable-enable.html [ Pass Failure Timeout ]
 crbug.com/572723 inspector/sources/debugger/debugger-uncaught-promise-on-pause.html [ Timeout Pass ]
 
-crbug.com/572726 inspector/tracing/timeline-misc/timeline-node-reference.html [ Timeout Pass Crash ]
-
 crbug.com/155836 fast/text/emphasis-ellipsis-complextext.html [ Failure Pass ]
 
 crbug.com/577380 [ Linux Debug ] http/tests/serviceworker/chromium/registration-stress.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base-expected.html b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base-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-local-url-with-base.html b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base.html
new file mode 100644
index 0000000..c928cbe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<style>
+#target {
+  width: 100px;
+  height: 100px;
+  background-color: red;
+  filter: url(#filter);
+}
+</style>
+<div id="target"></div>
+<svg>
+  <filter id="filter" x="0" y="0" width="1" height="1" color-interpolation-filters="sRGB">
+    <feFlood flood-color="green"/>
+  </filter>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base-expected.html b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base-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/masking/clip-path-reference-local-url-with-base.html b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html
new file mode 100644
index 0000000..3403359a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<style>
+#target {
+  width: 100px;
+  height: 100px;
+  border-right: 100px solid red;
+  background-color: green;
+  -webkit-clip-path: url(#clip);
+  clip-path: url(#clip);
+}
+</style>
+<div id="target"></div>
+<svg>
+  <clipPath id="clip">
+    <rect width="100" height="100"/>
+  </filter>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-nonexisting-existing-local-expected.html b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-nonexisting-existing-local-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-nonexisting-existing-local-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/masking/clip-path-reference-nonexisting-existing-local.html b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-nonexisting-existing-local.html
new file mode 100644
index 0000000..8be423b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-nonexisting-existing-local.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<style>
+#target {
+  width: 100px;
+  height: 100px;
+  background-color: green;
+  -webkit-clip-path: url(notexisting.svg#c);
+  clip-path: url(notexisting.svg#c);
+}
+</style>
+<div style="background-color: red; width: 100px">
+  <div id="target"></div>
+</div>
+<svg>
+  <clipPath id="c" clipPathUnits="objectBoundingBox">
+    <circle cx="0.5" cy="0.5" r="0.5"/>
+  </clipPath>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/custom-elements/spec/callback.html b/third_party/WebKit/LayoutTests/custom-elements/spec/callback.html
index 4c304f764..86d327e 100644
--- a/third_party/WebKit/LayoutTests/custom-elements/spec/callback.html
+++ b/third_party/WebKit/LayoutTests/custom-elements/spec/callback.html
@@ -91,6 +91,78 @@
   test_with_window(w => {
     let document = w.document;
     let element = document.createElement('a-a');
+    document.body.appendChild(element);
+    let logs = define_logger(w, ['style']);
+
+    logs.length = 0;
+    element.style.color = 'red';
+    assert_equals(logs.length, 1);
+    assert_log_is_type(logs, 0, attributeChanged, element, ['style', null, 'color: red;', '']);
+
+    element.style.color = 'green';
+    assert_equals(logs.length, 2);
+    assert_log_is_type(logs, 1, attributeChanged, element, ['style', 'color: red;', 'color: green;', '']);
+
+    element.style.color = '';
+    assert_equals(logs.length, 3);
+    assert_log_is_type(logs, 2, attributeChanged, element, ['style', 'color: green;', null, '']);
+  }, 'style.color should enqueue attributeChangedCallback for style attribute');
+
+  test_with_window(w => {
+    let document = w.document;
+    let element = document.createElement('a-a');
+    document.body.appendChild(element);
+    let logs = define_logger(w, ['style']);
+
+    logs.length = 0;
+    element.style.cssText = 'color: red';
+    assert_equals(logs.length, 1);
+    assert_log_is_type(logs, 0, attributeChanged, element, ['style', null, 'color: red;', '']);
+  }, 'style.cssText should enqueue attributeChangedCallback for style attribute');
+
+  test_with_window(w => {
+    let document = w.document;
+    let element = document.createElement('a-a');
+    document.body.appendChild(element);
+    let logs = define_logger(w, ['style']);
+
+    logs.length = 0;
+    element.style.setProperty('color', 'red');
+    assert_equals(logs.length, 1);
+    assert_log_is_type(logs, 0, attributeChanged, element, ['style', null, 'color: red;', '']);
+
+    element.style.removeProperty('color', 'red');
+    assert_equals(logs.length, 2);
+    assert_log_is_type(logs, 1, attributeChanged, element, ['style', 'color: red;', null, '']);
+  }, 'style.setProperty/removeProperty should enqueue attributeChangedCallback for style attribute');
+
+  test_with_window(w => {
+    let document = w.document;
+    let element = document.createElement('a-a');
+    document.body.appendChild(element);
+    let logs = define_logger(w, ['style']);
+
+    logs.length = 0;
+    element.style.cssFloat = 'left';
+    assert_equals(logs.length, 1);
+    assert_log_is_type(logs, 0, attributeChanged, element, ['style', null, 'float: left;', '']);
+  }, 'style.cssFloat should enqueue attributeChangedCallback for style attribute');
+
+  test_with_window(w => {
+    let document = w.document;
+    let element = document.createElement('a-a');
+    document.body.appendChild(element);
+    let logs = define_logger(w, ['lang']);
+
+    logs.length = 0;
+    element.lang = 'ja-jp';
+    assert_equals(logs.length, 1);
+    assert_log_is_type(logs, 0, attributeChanged, element, ['lang', null, 'ja-jp', '']);
+  }, 'lang property setter should enqueue attributeChangedCallback for lang attribute');
+
+  test_with_window(w => {
+    let document = w.document;
+    let element = document.createElement('a-a');
     element.setAttribute('x', '1');
     document.body.appendChild(element);
     let logs = define_logger(w, ['x']);
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt
index 6621896..04901236 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set-expected.txt
@@ -22,6 +22,10 @@
 PASS window.getComputedStyle(gridAutoFixedFixedWithFixedFixedWithChildren, '').getPropertyValue('grid-auto-columns') is "40px"
 PASS window.getComputedStyle(gridAutoFixedFixedWithFixedFixedWithChildren, '').getPropertyValue('grid-template-columns') is "20px 40px 40px"
 PASS window.getComputedStyle(gridAutoFixedFixedWithFixedFixedWithChildren, '').getPropertyValue('grid-template-rows') is "15px 30px 30px"
+PASS window.getComputedStyle(gridAutoMultipleTracks, '').getPropertyValue('grid-template-columns') is "25px 50px 100px 25px"
+PASS window.getComputedStyle(gridAutoMultipleTracks, '').getPropertyValue('grid-template-rows') is "10px 20px 30px 10px"
+PASS window.getComputedStyle(gridAutoMultipleTracksNegativeIndexes, '').getPropertyValue('grid-template-columns') is "100px 25px 50px 100px"
+PASS window.getComputedStyle(gridAutoMultipleTracksNegativeIndexes, '').getPropertyValue('grid-template-rows') is "30px 10px 20px 30px"
 
 Test that grid-template-* definitions are not affected by grid-auto-* definitions
 PASS window.getComputedStyle(gridAutoFixedFixed, '').getPropertyValue('grid-template-columns') is "none"
@@ -36,22 +40,28 @@
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'auto'
 
 Test getting and setting grid-auto-columns and grid-auto-rows through JS
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is '180px'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is '660px'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is 'minmax(min-content, 48px)'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'minmax(80px, min-content)'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is 'minmax(min-content, max-content)'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'minmax(max-content, min-content)'
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "180px"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "660px"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "minmax(min-content, 48px)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "minmax(80px, min-content)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "minmax(min-content, max-content)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "minmax(max-content, min-content)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "minmax(min-content, 10px) 48px 5%"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto 30px minmax(10%, 60%)"
 
 Test setting grid-auto-columns and grid-auto-rows to bad minmax value through JS
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is 'auto'
-PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is 'auto'
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is "auto"
+PASS getComputedStyle(element, '').getPropertyValue('grid-auto-rows') is "auto"
 
 Test setting grid-auto-columns and grid-auto-rows to 'inherit' through JS
 PASS getComputedStyle(element, '').getPropertyValue('grid-auto-columns') is '50px'
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set.html
index 29edd22..6491c20 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set.html
@@ -30,6 +30,13 @@
     grid-auto-columns: minmax(10vw, auto);
 }
 
+.gridAutoMultipleTracks {
+    width: 100px;
+    height: 50px;
+    grid-auto-rows: 10px 20px 30px;
+    grid-auto-columns: 25px 50px 100px;
+}
+
 </style>
 <script src="../../resources/js-test.js"></script>
 <script src="resources/grid-definitions-parsing-utils.js"></script>
@@ -46,6 +53,19 @@
     <div class="sizedToGridArea thirdRowAutoColumn"></div>
     <div class="sizedToGridArea autoRowThirdColumn"></div>
 </div>
+<div class="grid gridAutoMultipleTracks" id="gridAutoMultipleTracks">
+    <div style="grid-column: 1; grid-row: 1"></div>
+    <div style="grid-column: 2; grid-row: 2"></div>
+    <div style="grid-column: 3; grid-row: 3"></div>
+    <div style="grid-column: 4; grid-row: 4"></div>
+</div>
+<div class="grid gridAutoMultipleTracks" id="gridAutoMultipleTracksNegativeIndexes">
+    <div style="grid-column: -2; grid-row: -2"></div>
+    <div style="grid-column: -3; grid-row: -3"></div>
+    <div style="grid-column: -4; grid-row: -4"></div>
+    <div style="grid-column: -5; grid-row: -5"></div>
+</div>
+
 <script>
 description('Test that setting and getting grid-auto-columns and grid-auto-rows works as expected');
 
@@ -61,6 +81,8 @@
 testGridDefinitionsValues(document.getElementById("gridAutoFixedFixedWithChildren"), "50px", "30px");
 testGridAutoDefinitionsValues(document.getElementById("gridAutoFixedFixedWithFixedFixedWithChildren"), "30px", "40px");
 testGridDefinitionsValues(document.getElementById("gridAutoFixedFixedWithFixedFixedWithChildren"), "20px 40px 40px", "15px 30px 30px");
+testGridDefinitionsValues(document.getElementById("gridAutoMultipleTracks"), "25px 50px 100px 25px", "10px 20px 30px 10px");
+testGridDefinitionsValues(document.getElementById("gridAutoMultipleTracksNegativeIndexes"), "100px 25px 50px 100px", "30px 10px 20px 30px");
 
 debug("");
 debug("Test that grid-template-* definitions are not affected by grid-auto-* definitions");
@@ -75,64 +97,31 @@
 shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'auto'");
 shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'auto'");
 
+function testAutoValues(autoCols, autoRows, computedAutoCols, computedAutoRows) {
+     element = document.createElement("div");
+     document.body.appendChild(element);
+     element.style.fontSize = "10px";
+     element.style.gridAutoColumns = autoCols;
+     element.style.gridAutoRows = autoRows;
+     shouldBeEqualToString("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", computedAutoCols || autoCols);
+     shouldBeEqualToString("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", computedAutoRows || autoRows);
+}
+
 debug("");
 debug("Test getting and setting grid-auto-columns and grid-auto-rows through JS");
-element.style.font = "10px Ahem";
-element.style.gridAutoColumns = "18em";
-element.style.gridAutoRows = "66em";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'180px'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'660px'");
-
-element = document.createElement("div");
-document.body.appendChild(element);
-element.style.gridAutoColumns = "minmax(min-content, 8vh)";
-element.style.gridAutoRows = "minmax(10vw, min-content)";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'minmax(min-content, 48px)'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'minmax(80px, min-content)'");
-
-element = document.createElement("div");
-document.body.appendChild(element);
-element.style.gridAutoColumns = "minmax(min-content, max-content)";
-element.style.gridAutoRows = "minmax(max-content, min-content)";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'minmax(min-content, max-content)'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'minmax(max-content, min-content)'");
+testAutoValues("18em", "66em", "180px", "660px");
+testAutoValues("minmax(min-content, 8vh)", "minmax(10vw, min-content)", "minmax(min-content, 48px)", "minmax(80px, min-content)");
+testAutoValues("minmax(min-content, max-content)", "minmax(max-content, min-content)");
+testAutoValues("minmax(min-content, 10px) 48px 5%", "auto 30px minmax(10%, 60%)");
 
 debug("");
 debug("Test setting grid-auto-columns and grid-auto-rows to bad minmax value through JS");
-element = document.createElement("div");
-document.body.appendChild(element);
-// No comma.
-element.style.gridAutoColumns = "minmax(10px 20px)";
-// Only 1 argument provided.
-element.style.gridAutoRows = "minmax(10px)";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'auto'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'auto'");
-
-element = document.createElement("div");
-document.body.appendChild(element);
-// Nested minmax.
-element.style.gridAutoColumns = "minmax(minmax(10px, 20px), 20px)";
-// Only 2 arguments are allowed.
-element.style.gridAutoRows = "minmax(10px, 20px, 30px)";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'auto'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'auto'");
-
-element = document.createElement("div");
-document.body.appendChild(element);
-// No breadth value.
-element.style.gridAutoColumns = "minmax()";
-// No comma.
-element.style.gridAutoRows = "minmax(30px 30% 30em)";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'auto'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'auto'");
-
-element = document.createElement("div");
-document.body.appendChild(element);
-// None is not allowed for grid-auto-{rows|columns}.
-element.style.gridAutoColumns = "none";
-element.style.gridAutoRows = "none";
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-columns')", "'auto'");
-shouldBe("getComputedStyle(element, '').getPropertyValue('grid-auto-rows')", "'auto'");
+testAutoValues("minmax(10px 20px)", "minmax(10px)", "auto", "auto");
+testAutoValues("minmax(minmax(10px, 20px), 20px)", "minmax(10px, 20px, 30px)", "auto", "auto");
+testAutoValues("minmax()", "minmax(30px 30% 30em)", "auto", "auto");
+testAutoValues("none", "none", "auto", "auto");
+testAutoValues("10px [a] 20px", "[z] auto [y] min-content", "auto", "auto");
+testAutoValues("repeat(2, 10px [a] 20px)", "[z] repeat(auto-fit, 100px)", "auto", "auto");
 
 function testInherit()
 {
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set-expected.txt
index 3ad2a930..5e22378 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set-expected.txt
@@ -58,6 +58,12 @@
 PASS window.getComputedStyle(gridWithAutoFlowAndRowsAndColumns, '').getPropertyValue('grid-auto-flow') is "column"
 PASS window.getComputedStyle(gridWithAutoFlowAndRowsAndColumns, '').getPropertyValue('grid-auto-columns') is "20px"
 PASS window.getComputedStyle(gridWithAutoFlowAndRowsAndColumns, '').getPropertyValue('grid-auto-rows') is "10px"
+PASS window.getComputedStyle(gridWithAutoFlowAndMultipleAutoTracks, '').getPropertyValue('grid-template-columns') is "none"
+PASS window.getComputedStyle(gridWithAutoFlowAndMultipleAutoTracks, '').getPropertyValue('grid-template-rows') is "none"
+PASS window.getComputedStyle(gridWithAutoFlowAndMultipleAutoTracks, '').getPropertyValue('grid-template-areas') is "none"
+PASS window.getComputedStyle(gridWithAutoFlowAndMultipleAutoTracks, '').getPropertyValue('grid-auto-flow') is "row"
+PASS window.getComputedStyle(gridWithAutoFlowAndMultipleAutoTracks, '').getPropertyValue('grid-auto-columns') is "100px 10%"
+PASS window.getComputedStyle(gridWithAutoFlowAndMultipleAutoTracks, '').getPropertyValue('grid-auto-rows') is "20px 10px"
 
 Test getting wrong values for 'grid' shorthand through CSS (they should resolve to the default: 'none')
 PASS window.getComputedStyle(gridWithExplicitAndImplicit, '').getPropertyValue('grid-template-columns') is "none"
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set.html
index e90c290..73cdf6ec 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-shorthand-get-set.html
@@ -27,6 +27,9 @@
 #gridWithAutoFlowAndRowsAndColumns {
     grid: column 10px / 20px;
 }
+#gridWithAutoFlowAndMultipleAutoTracks {
+    grid: row 20px 10px / 100px 10%;
+}
 
 /* Bad values. */
 
@@ -59,6 +62,7 @@
 <div class="grid" id="gridWithAutoFlowColumnDense"></div>
 <div class="grid" id="gridWithAutoFlowDenseRow"></div>
 <div class="grid" id="gridWithAutoFlowAndRowsAndColumns"></div>
+<div class="grid" id="gridWithAutoFlowAndMultipleAutoTracks"></div>
 <div class="grid" id="gridWithExplicitAndImplicit"></div>
 <div class="grid" id="gridWithMisplacedNone1"></div>
 <div class="grid" id="gridWithMisplacedNone2"></div>
@@ -77,6 +81,7 @@
     testGridDefinitionsValues(document.getElementById("gridWithAutoFlowColumnDense"), "none", "none", "none", "column dense", "10px", "10px");
     testGridDefinitionsValues(document.getElementById("gridWithAutoFlowDenseRow"), "none", "none", "none", "row dense", "10px", "10px");
     testGridDefinitionsValues(document.getElementById("gridWithAutoFlowAndRowsAndColumns"), "none", "none", "none", "column", "20px", "10px");
+    testGridDefinitionsValues(document.getElementById("gridWithAutoFlowAndMultipleAutoTracks"), "none", "none", "none", "row", "100px 10%", "20px 10px");
 
     debug("");
     debug("Test getting wrong values for 'grid' shorthand through CSS (they should resolve to the default: 'none')");
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope-expected.txt
index 484ad6c..7d03691 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope-expected.txt
@@ -1,4 +1,5 @@
-Test verifies that a timeout callback is run in the proper execution context. 2 timeouts are set on a child iframe's window. 'Closure' callback should execute in the main page, 'string' callback should execute in the iframe. Test passes if you see 2 lines 'PASS' below.
+Test verifies that a timeout callback is run in the proper execution context. 3 timeouts are set on a child iframe's window. Test passes if you see 3 lines 'PASS' below. See also: https://html.spec.whatwg.org/multipage/webappapis.html#timer-initialisation-steps
 
-PASS
-PASS
+PASS -- function argument: if the argument is a function, then the callback function must run in the relevant realm for that function object.
+PASS -- string argument: if the argument is a string, then it must be compiled in the relevant realm for the context object, hence must run in the relevant realm for the context object.
+PASS -- callback this value: the callback this value must be the context object.
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope.html b/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope.html
index c33aba8a..be0da77 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/timeout-callback-scope.html
@@ -1,6 +1,5 @@
 <html>
 <script>
-
 // When both timeouts finish, the counter will be 2.
 window.completionCounter = 0;
 function test()
@@ -9,34 +8,49 @@
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
     }
+
     // Get the iframe's window.
+    var mainWindow = window;
     var iframeWindow = window.frames["testIframe"];
+
     // setTimeout with a callback specified as a JS closure.
     // This one should run in the context of the main page.
     iframeWindow.setTimeout(
-        function() { 
-            document.getElementById("closureResult").innerText = (window == parent ? "PASS" : "FAIL");
+        function() {
+            document.getElementById("closureResult").innerText = (window == mainWindow ? "PASS" : "FAIL");
             completionCounter++;
-        }, 1);
+        }, 0);
+
     // setTimeout with a JS string containing similar code.
     // This one should run 'inside' iframe.
-    iframeWindow.setTimeout(
+    mainWindow.setTimeout.call(
+        iframeWindow,
         "parent.document.getElementById('stringResult').innerText = (window != parent ? 'PASS' : 'FAIL');" +
-        "parent.completionCounter++;"
-        , 1);
+        "parent.completionCounter++;",
+        0);
+
+    // The callback this value must be the context object.
+    iframeWindow.setTimeout.call(window, function() {
+        document.getElementById("contextResult").innerText = (this == mainWindow ? "PASS" : "FAIL");
+        completionCounter++;
+    }, 0);
+
     window.setInterval(checkResult, 10);
 }
 function checkResult() {
-    if (completionCounter < 2)
+    if (completionCounter < 3)
         return;
     if (window.testRunner)
         testRunner.notifyDone();
 }
 </script>
 <body onload="test()">
-<p>Test verifies that a timeout callback is run in the proper execution context. 2 timeouts are set on a child iframe's window. 'Closure' callback should execute in the main page, 'string' callback should execute in the iframe. Test passes if you see 2 lines 'PASS' below.</p>
-<div id=closureResult>FAIL</div>
-<div id=stringResult>FAIL</div>
-<iframe style="display:none" src="about:blank" name=testIframe></iframe>
+<p>Test verifies that a timeout callback is run in the proper execution context. 3 timeouts are set on a child iframe's window.  Test passes if you see 3 lines 'PASS' below.  See also:
+<a href="https://html.spec.whatwg.org/multipage/webappapis.html#timer-initialisation-steps">https://html.spec.whatwg.org/multipage/webappapis.html#timer-initialisation-steps</a></p>
+
+<div><span id="closureResult">FAIL: Test didn't run.</span> -- function argument: if the argument is a function, then the callback function must run in the relevant realm for that function object.</div>
+<div><span id="stringResult">FAIL: Test didn't run.</span> -- string argument: if the argument is a string, then it must be compiled in the relevant realm for the context object, hence must run in the relevant realm for the context object.</div>
+<div><span id="contextResult">FAIL: Test didn't run.</span> -- callback this value: the callback this value must be the context object.</div>
+<iframe style="display:none" src="about:blank" name="testIframe"></iframe>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-fling.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-fling.html
index b865246..026a0c2 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-fling.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-fling.html
@@ -59,7 +59,7 @@
     var touchHeight = 25;
 
     eventSender.gestureTapDown(scrollbarX, scrollbarY, touchWidth, touchHeight);
-    eventSender.gestureFlingStart(0, 0, 0, 0, "touchscreen");
+    eventSender.gestureFlingStart(0, 0, 1, 0, "touchscreen");
 }
 
 function exitIfNecessary()
diff --git a/third_party/WebKit/LayoutTests/fast/forms/percent-height-auto-width-form-controls.html b/third_party/WebKit/LayoutTests/fast/forms/percent-height-auto-width-form-controls.html
index 60e579f..34daeea 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/percent-height-auto-width-form-controls.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/percent-height-auto-width-form-controls.html
@@ -39,13 +39,13 @@
 
 <div style="width: 100px; background: pink">
     <table><tbody><tr><td>
-        <select id="select-a" style="height: 100%"><option>aaaaaaaaaaaaaaaaaaaaaaaaa
+        <select id="select-a" style="-webkit-appearance:menulist-button; height: 100%"><option>aaaaaaaaaaaaaaaaaaaaaaaaa
     </td></tr></tbody></table>
 </div>
 
 <div style="width: 100px; background: pink">
     <table><tbody><tr><td>
-        <select id="select-b"><option>aaaaaaaaaaaaaaaaaaaaaaaaa
+        <select id="select-b" style="-webkit-appearance:menulist-button;"><option>aaaaaaaaaaaaaaaaaaaaaaaaa
     </td></tr></tbody></table>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-border-box-expected.html b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-border-box-expected.html
new file mode 100644
index 0000000..464ce9e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-border-box-expected.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<style>
+    td {
+        width: 50px;
+        height: 50px;
+        padding: 0px;
+        background: lime;
+    }
+    td div {
+      display: inline-block;
+      width: 22px;
+      height: 5px;
+      background: orange;
+    }
+</style>
+<p>Removing the left cell with a big border should give the remaining cells enough space to put the orange inline-blocks on the same line.</p>
+<table style="border-collapse:collapse">
+  <tr>
+    <td><div></div> <div></div></td>
+    <td><div></div> <div></div></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-border-box.html b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-border-box.html
new file mode 100644
index 0000000..191cdf1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-border-box.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<style>
+    td {
+        width: 50px;
+        height: 50px;
+        padding: 0px;
+        background: lime;
+        box-sizing: border-box;
+    }
+    td div {
+      display: inline-block;
+      width: 22px;
+      height: 5px;
+      background: orange;
+    }
+</style>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script type="text/javascript">
+    runAfterLayoutAndPaint(() => theRow.removeChild(cellToRemove), true);
+</script>
+<p>Removing the left cell with a big border should give the remaining cells enough space to put the orange inline-blocks on the same line.</p>
+<table style="border-collapse:collapse">
+  <tr id="theRow">
+    <td><div></div> <div></div></td>
+    <td style="border:18px solid red" id="cellToRemove"></td>
+    <td><div></div> <div></div></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-large-border-width-expected.txt b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-large-border-width-expected.txt
new file mode 100644
index 0000000..a1b8d3c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-large-border-width-expected.txt
@@ -0,0 +1,3 @@
+After removing the middle cell with the red border the 2 remaining cells' widths should depend on sharing the black border, and not have stale widths from sharing the red border.
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-large-border-width.html b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-large-border-width.html
new file mode 100644
index 0000000..d2cf7a7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/remove-cell-with-large-border-width.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<style>
+    td {
+        width: 50px;
+        height: 50px;
+        padding: 0px;
+        background: lime;
+    }
+</style>
+<script src="../../resources/check-layout.js"></script>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script type="text/javascript">
+    function removeMiddleCell() {
+        theRow.removeChild(cellToRemove);
+        checkLayout("table");
+    }
+    runAfterLayoutAndPaint(removeMiddleCell, true);
+</script>
+<p>After removing the middle cell with the red border the 2 remaining cells' widths should depend on sharing the black border, and not have stale widths from sharing the red border.</p>
+<table style="border-collapse:collapse" data-expected-width=108>
+  <tr id="theRow">
+    <td style="border:4px solid black" data-expected-width=54></td>
+    <td style="border:18px solid red" id="cellToRemove"></td>
+    <td data-expected-width=52></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view-expected.txt
index 5378aea..df7d72d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view-expected.txt
@@ -24,7 +24,7 @@
 Running: testXMLWithUnknownMime
 Creating a NetworkRequest with mimeType: text/foobar
 Content: <bar><foo/></bar>
-Its previewer type: SearchableView > widget vbox
+Its previewer type: SearchableView > widget vbox view
 
 Running: testXMLWithError500
 Creating a NetworkRequest with mimeType: text/xml
@@ -34,12 +34,12 @@
 Running: testUnknownMimeTextWithError500
 Creating a NetworkRequest with mimeType: text/foobar
 Content: Foo Bar
-Its previewer type: SearchableView > widget vbox
+Its previewer type: SearchableView > widget vbox view
 
 Running: testBinaryImageFile
 Creating a NetworkRequest with mimeType: image/png
 Content: Bin**NULL**ary File**NULL****NULL**
-Its previewer type: SearchableView > widget vbox
+Its previewer type: SearchableView > widget vbox view
 
 Running: testBinaryBlankImageFile
 Creating a NetworkRequest with mimeType: image/png
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2-expected.txt b/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2-expected.txt
deleted file mode 100644
index 15c9511..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Slow loading WebVTT file interrupted in the middle of a timestamp line.
-
-EXPECTED (track.track.cues.length === '2') OK
-EXPECTED (track.track.cues[0].text === 'Lorem ipsum') OK
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2.html b/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2.html
index d2802d8b..28045df0 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-2.html
@@ -1,34 +1,23 @@
-<!doctype html>
-<title>Slow loading WebVTT file interrupted in the middle of a timestamp line</title>
-<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
-     (Please avoid writing new tests using video-test.js) -->
-<script src=/media-resources/video-test.js></script>
+<!DOCTYPE html>
+<title>Slow loading WebVTT file interrupted in the middle of a timestamp line.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-function loadAndStall()
-{
-    return "http://127.0.0.1:8000/resources/load-and-stall.php";
-}
-
-function vttTrack()
-{
-    return "?name=../../../media/track/captions-webvtt/captions-multiline-lf.vtt&mimeType=text%2Fvtt";
-}
-
-window.onload = function()
-{
-    video = document.createElement('video');
-    track = document.createElement('track');
+async_test(function(t) {
+    var video = document.createElement("video");
+    var track = document.createElement("track");
     video.appendChild(track);
-    track.onload = function() {
-        testExpected("track.track.cues.length", 2, "===");
-        testExpected("track.track.cues[0].text", 'Lorem\u000aipsum', "===");
-        endTest();
-    };
-    track.onerror = function() {
-        failTest();
-    };
-    track.src = loadAndStall() + vttTrack() + "&stallAt=32&stallFor=1";
+
+    track.onload = t.step_func_done(function() {
+        assert_equals(track.track.cues.length, 2);
+        assert_equals(track.track.cues[0].text, "Lorem\u000aipsum");
+    });
+
+    track.onerror = t.unreached_func();
+
+    var loadAndStallUrl = "http://127.0.0.1:8000/resources/load-and-stall.php";
+    var vttTrackUrl = "?name=../../../media/track/captions-webvtt/captions-multiline-lf.vtt&mimeType=text%2Fvtt";
+    track.src = loadAndStallUrl + vttTrackUrl + "&stallAt=32&stallFor=1";
     track.track.mode = "hidden";
-}
-</script>
-<p>Slow loading WebVTT file interrupted in the middle of a timestamp line.</p>
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-expected.txt b/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-expected.txt
deleted file mode 100644
index 3add4a1..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Slow loading WebVTT file interrupted just after a cue text linebreak.
-
-EXPECTED (track.track.cues.length === '2') OK
-EXPECTED (track.track.cues[0].text === 'Lorem ipsum') OK
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading.html b/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading.html
index 949f19b..e12cc1b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/track/track-webvtt-slow-loading.html
@@ -1,34 +1,23 @@
-<!doctype html>
-<title>Slow loading WebVTT file interrupted just after a cue text linebreak</title>
-<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
-     (Please avoid writing new tests using video-test.js) -->
-<script src=/media-resources/video-test.js></script>
+<!DOCTYPE html>
+<title>Slow loading WebVTT file interrupted just after a cue text linebreak.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
-function loadAndStall()
-{
-    return "http://127.0.0.1:8000/resources/load-and-stall.php";
-}
-
-function vttTrack()
-{
-    return "?name=../../../media/track/captions-webvtt/captions-multiline-lf.vtt&mimeType=text%2Fvtt";
-}
-
-window.onload = function()
-{
-    video = document.createElement('video');
-    track = document.createElement('track');
+async_test(function(t) {
+    var video = document.createElement("video");
+    var track = document.createElement("track");
     video.appendChild(track);
-    track.onload = function() {
-        testExpected("track.track.cues.length", 2, "===");
-        testExpected("track.track.cues[0].text", 'Lorem\u000aipsum', "===");
-        endTest();
-    };
-    track.onerror = function() {
-        failTest();
-    };
-    track.src = loadAndStall() + vttTrack() + "&stallAt=49&stallFor=1";
+
+    track.onload = t.step_func_done(function() {
+        assert_equals(track.track.cues.length, 2);
+        assert_equals(track.track.cues[0].text, "Lorem\u000aipsum");
+    });
+
+    track.onerror = t.unreached_func();
+
+    var loadAndStallUrl = "http://127.0.0.1:8000/resources/load-and-stall.php";
+    var vttTrackUrl = "?name=../../../media/track/captions-webvtt/captions-multiline-lf.vtt&mimeType=text%2Fvtt";
+    track.src = loadAndStallUrl + vttTrackUrl + "&stallAt=49&stallFor=1";
     track.track.mode = "hidden";
-}
-</script>
-<p>Slow loading WebVTT file interrupted just after a cue text linebreak.</p>
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-cookie-expected.txt b/third_party/WebKit/LayoutTests/http/tests/media/video-cookie-expected.txt
deleted file mode 100644
index a7876924..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-cookie-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-EVENT(canplay)
-Tests that the media player will send the relevant cookies when requesting the media file.
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-cookie.html b/third_party/WebKit/LayoutTests/http/tests/media/video-cookie.html
index 7a73dba..7478c13 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-cookie.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/video-cookie.html
@@ -1,40 +1,23 @@
-<html>
-<head>
-</head>
-<body onload="loadCookie()">
-<video id="video"></video>
-<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
-     (Please avoid writing new tests using video-test.js) -->
-<script src=../../media-resources/video-test.js></script>
-<script src=../../media-resources/media-file.js></script>
+<!DOCTYPE html>
+<title>Tests that the media player will send the relevant cookies when requesting the media file.</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../../media-resources/media-file.js"></script>
+<body>
+<video></video>
 <script>
-    if (window.testRunner) {
-        testRunner.dumpAsText();
-        testRunner.setBlockThirdPartyCookies(false);
-        testRunner.waitUntilDone();
-    }
+async_test(function(t) {
+    var movie = findMediaFile("video", "resources/test");
+    var frame = document.createElement("iframe");
+    document.body.appendChild(frame);
 
-    function loadCookie () {
-        var movie = findMediaFile("video", "resources/test");
-        var frame = document.createElement("iframe");
-        document.body.appendChild(frame);
+    frame.onload = t.step_func(function() {
+        var video = document.querySelector("video");
+        video.src="http://127.0.0.1:8000/media/resources/video-cookie-check-cookie.php";
+        video.oncanplay = t.step_func_done();
+        video.play();
+    });
 
-        frame.addEventListener('load', function () {
-                video = document.getElementById('video');
-                video.src="http://127.0.0.1:8000/media/resources/video-cookie-check-cookie.php";
-                video.play();
-        });
-
-        frame.width = 0;
-        frame.height = 0;
-        frame.src = "http://127.0.0.1:8000/media/resources/setCookie.cgi?name=" + movie;
-    }
-
-    waitForEvent("canplay", function () {
-        if (window.testRunner)
-            window.testRunner.notifyDone();
-    } );
-</script>
-Tests that the media player will send the relevant cookies when requesting the media file.<br/>
-</body>
-</html>
+    frame.src = "http://127.0.0.1:8000/media/resources/setCookie.cgi?name=" + movie;
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort-expected.txt b/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort-expected.txt
deleted file mode 100644
index 9d7b331..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Test before movie is open
-EXPECTED (video.error == 'null') OK
-
-'loadstart' event
-EXPECTED (video.error == 'null') OK
-RUN(video.load())
-
-'abort' event
-EXPECTED (video.error == 'null') OK
-EXPECTED (event.lengthComputable == 'undefined') OK
-
-'loadstart' event
-EXPECTED (video.error == 'null') OK
-
-'canplaythrough' event
-EXPECTED (video.error == 'null') OK
-
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort.html b/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort.html
index 687437e..e1284898 100644
--- a/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort.html
+++ b/third_party/WebKit/LayoutTests/http/tests/media/video-error-abort.html
@@ -1,67 +1,32 @@
-<!DOCTYPE HTML>
-<html>
-    <head>
-        <title>'abort' event test</title>
-        <script src=../../media-resources/media-file.js></script>
-        <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
-             (Please avoid writing new tests using video-test.js) -->
-        <script src=../../media-resources/video-test.js></script>
-        <script>
-            var didLoad = false;
+<!DOCTYPE html>
+<title>Test "abort" event.</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../../media-resources/media-file.js"></script>
+<video></video>
+<script>
+async_test(function(t) {
+    var video = document.querySelector("video");
+    // Test before movie is open.
+    assert_equals(video.error, null);
+    video.onerror = t.unreached_func();
 
-            function loadstart()
-            {
-                consoleWrite("<br><b><em>'loadstart'</em> event</b>");
-                testExpected("video.error", null);
+    var watcher = new EventWatcher(t, video, ["loadstart", "abort", "canplaythrough"]);
+    watcher.wait_for("loadstart").then(t.step_func(function() {
+        assert_equals(video.error, null);
+        video.load();
+        return watcher.wait_for("abort");
+    })).then(t.step_func(function() {
+        assert_equals(video.error, null);
+        return watcher.wait_for("loadstart");
+    })).then(t.step_func(function() {
+        assert_equals(video.error, null);
+        return watcher.wait_for("canplaythrough");
+    })).then(t.step_func_done(function() {
+        assert_equals(video.error, null);
+    }));
 
-                if (didLoad)
-                    return;
-                didLoad = true;
-
-                // Force the element to reload, while the current movie is still loading,
-                // this should generate an 'abort' event
-                run("video.load()");
-            }
-
-            function abort()
-            {
-                consoleWrite("<br><b><em>'abort'</em> event</b>");
-                testExpected("video.error", null);
-
-                // Progress events have a 'lengthComputable' field, check to make sure this event
-                // doesn't have one.
-                testExpected("event.lengthComputable", undefined);
-            }
-
-            function canplaythrough()
-            {
-                consoleWrite("<br><b><em>'canplaythrough'</em> event</b>");
-                testExpected("video.error", null);
-
-                consoleWrite("");
-                endTest();
-            }
-
-            function start()
-            {
-                findMediaElement();
-
-                waitForEvent("error");
-
-                consoleWrite("<br><b>Test before movie is open</b>");
-                testExpected("video.error", null);
-
-                var movie = findMediaFile("video", "../resources/test");
-                video.src = "http://127.0.0.1:8000/media/video-throttled-load.cgi?name=" + movie + "&throttle=256";
-            }
-        </script>
-    </head>
-
-    <body onload="start()">
-        <video controls
-            onloadstart="loadstart()"
-            onabort="abort()"
-            oncanplaythrough="canplaythrough()"
-            ></video>
-    </body>
-</html>
+    var movie = findMediaFile("video", "../resources/test");
+    video.src = "http://127.0.0.1:8000/media/video-throttled-load.cgi?name=" + movie + "&throttle=256";
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/link_header_preload_on_commit.php b/third_party/WebKit/LayoutTests/http/tests/preload/link_header_preload_on_commit.php
new file mode 100644
index 0000000..b9895d3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/preload/link_header_preload_on_commit.php
@@ -0,0 +1,40 @@
+<?php
+    header("Link: </resources/dummy.css>;rel=preload", false);
+    header("Link: </resources/square.png>;rel=preload;as=image;media=(min-width: 1px)", false);
+?>
+<!DOCTYPE html>
+<html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="preload" href="/resources/dummy.js" as="script">
+<script>
+    var t = async_test('Makes sure that Link headers preload resources');
+</script>
+<script src="/resources/slow-script.pl?delay=200"></script>
+<script>
+    window.addEventListener("load", t.step_func(function() {
+      var nonMediaHeader = performance.getEntriesByName(
+        "http://127.0.0.1:8000/resources/dummy.css")[0];
+      var mediaHeader = performance.getEntriesByName(
+        "http://127.0.0.1:8000/resources/square.png")[0];
+      var markup = performance.getEntriesByName(
+        "http://127.0.0.1:8000/resources/dummy.js")[0];
+      var normalResource = performance.getEntriesByName(
+        "http://127.0.0.1:8000/resources/testharness.js")[0];
+      // The non-media header can be processed at commit time.
+      // The media header needs to tokenize the first chunk of html, and the
+      // markup still needs to be tokenized.
+      // Note: the link preloads can be preloaded before the normal resource
+      // because they don't need to wait for the document element to be
+      // available (ApplicationCache initialization time).
+      assert_greater_than(markup.startTime, nonMediaHeader.startTime);
+      assert_greater_than(mediaHeader.startTime, nonMediaHeader.startTime);
+      assert_greater_than(normalResource.startTime, mediaHeader.startTime);
+      assert_greater_than(normalResource.startTime, markup.startTime);
+      t.done();
+    }));
+</script>
+</body>
+</html>
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource-expected.html b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource-expected.html
new file mode 100644
index 0000000..5fc78bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 200px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource.html b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource.html
new file mode 100644
index 0000000..14cbba5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<base href="http://127.0.0.1:8000/svg/resources/red100x100.svg">
+<svg>
+  <rect id="rect" width="100" height="100" fill="green"/>
+  <use xlink:href="#rect" x="100"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/http/tests/svg/resources/red100x100.svg b/third_party/WebKit/LayoutTests/http/tests/svg/resources/red100x100.svg
new file mode 100644
index 0000000..263b3af
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/svg/resources/red100x100.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect id="rect" width="100" height="100" fill="red"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/imagecapture/getphotocapabilities.html b/third_party/WebKit/LayoutTests/imagecapture/getphotocapabilities.html
index 686892f8..ec03fa2 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/getphotocapabilities.html
+++ b/third_party/WebKit/LayoutTests/imagecapture/getphotocapabilities.html
@@ -33,13 +33,37 @@
     })
     .then(capabilities => {
       assert_true(capabilities instanceof PhotoCapabilities);
-      assert_true(capabilities.zoom instanceof MediaSettingsRange);
 
+      assert_true(capabilities.iso instanceof MediaSettingsRange);
+      assert_equals(capabilities.iso.max, mock_capabilities.iso.max);
+      assert_equals(capabilities.iso.min, mock_capabilities.iso.min);
+      assert_equals(capabilities.iso.current,
+                    mock_capabilities.iso.current);
+
+      assert_true(capabilities.imageHeight instanceof MediaSettingsRange);
+      assert_equals(capabilities.imageHeight.max,
+                    mock_capabilities.height.max);
+      assert_equals(capabilities.imageHeight.min,
+                    mock_capabilities.height.min);
+      assert_equals(capabilities.imageHeight.current,
+                    mock_capabilities.height.current);
+
+      assert_true(capabilities.imageWidth instanceof MediaSettingsRange);
+      assert_equals(capabilities.imageWidth.max,
+                    mock_capabilities.width.max);
+      assert_equals(capabilities.imageWidth.min,
+                    mock_capabilities.width.min);
+      assert_equals(capabilities.imageWidth.current,
+                    mock_capabilities.width.current);
+
+      assert_true(capabilities.zoom instanceof MediaSettingsRange);
       assert_equals(capabilities.zoom.max, mock_capabilities.zoom.max);
       assert_equals(capabilities.zoom.min, mock_capabilities.zoom.min);
       assert_equals(capabilities.zoom.current,
                     mock_capabilities.zoom.current);
 
+      assert_equals(capabilities.focusMode, mock_capabilities.focusMode);
+
       t.done();
     })
     .catch(error => {
diff --git a/third_party/WebKit/LayoutTests/imagecapture/resources/mock-imagecapture.js b/third_party/WebKit/LayoutTests/imagecapture/resources/mock-imagecapture.js
index 050a9206b..367e313 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/resources/mock-imagecapture.js
+++ b/third_party/WebKit/LayoutTests/imagecapture/resources/mock-imagecapture.js
@@ -14,7 +14,14 @@
           imageCapture.ImageCapture.name,
           pipe => this.bindToPipe(pipe));
 
-      this.capabilities_ = { capabilities: { zoom : { min : 0, max : 10, current : 5 } } };
+      this.capabilities_ = { capabilities : {
+          iso : { min : 100, max : 12000, current : 400 },
+          height : { min : 240, max : 2448, current : 240 },
+          width : { min : 320, max : 3264, current : 320 },
+          width : { min : 320, max : 3264, current : 320 },
+          zoom : { min : 0, max : 10, current : 5 },
+          focusMode : "unavailable",
+      }};
       this.settings_ = null;
     }
 
@@ -33,8 +40,8 @@
     }
 
     takePhoto(source_id) {
-      return Promise.resolve({ mime_type : 'image/cat',
-                               data : "(,,,)=(^.^)=(,,,)" });
+      return Promise.resolve({ blob : { mime_type : 'image/cat',
+                                        data : new Array(2) } });
     }
 
     capabilities() {
diff --git a/third_party/WebKit/LayoutTests/imagecapture/setoptions.html b/third_party/WebKit/LayoutTests/imagecapture/setoptions.html
index 6decd34..f6d32a0 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/setoptions.html
+++ b/third_party/WebKit/LayoutTests/imagecapture/setoptions.html
@@ -19,7 +19,7 @@
   var stream = canvas.captureStream();
 
   var theMock = null;
-  const optionsDict = { zoom : 7 };
+  const optionsDict = { zoom : 7, imageWidth : 1080, imageHeight : 100 };
   mockImageCaptureReady
     .then(mock => {
       theMock = mock;
@@ -32,8 +32,12 @@
       return capturer.setOptions(optionsDict);
     })
     .then(function() {
-      assert_equals(1, theMock.options().has_zoom, 'has_zoom must be true');
+      assert_true(theMock.options().has_zoom, 'has_zoom must be true');
       assert_equals(optionsDict.zoom, theMock.options().zoom, 'zoom value');
+      assert_equals(true, theMock.options().has_width, 'has_width must be true');
+      assert_equals(optionsDict.imageWidth, theMock.options().width, 'width value');
+      assert_equals(true, theMock.options().has_height, 'has_height must be true');
+      assert_equals(optionsDict.imageHeight, theMock.options().height, 'height value');
       t.done();
     })
     .catch(error => {
diff --git a/third_party/WebKit/LayoutTests/imagecapture/takephoto.html b/third_party/WebKit/LayoutTests/imagecapture/takephoto.html
index fce8337..bbac020 100644
--- a/third_party/WebKit/LayoutTests/imagecapture/takephoto.html
+++ b/third_party/WebKit/LayoutTests/imagecapture/takephoto.html
@@ -29,7 +29,9 @@
       return capturer.takePhoto();
     })
     .then(blob => {
-      assert_true(blob.size > 0);
+      // JS Blob is almost-opaque, can only check |type| and |size|.
+      assert_equals(blob.type, 'image/cat');
+      assert_equals(blob.size, 2);
       t.done();
     })
     .catch(error => {
diff --git a/third_party/WebKit/LayoutTests/inspector/components/minimum-size.html b/third_party/WebKit/LayoutTests/inspector/components/minimum-size.html
index 44466f8..a74bec9 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/minimum-size.html
+++ b/third_party/WebKit/LayoutTests/inspector/components/minimum-size.html
@@ -81,7 +81,7 @@
     dumpBoundingBoxes(widgets);
 
     InspectorTest.addResult("Detaching sidebar");
-    secondSidebarWidget.detach();
+    childsplitWidget.setSidebarWidget(null);
     delete widgets["secondSidebarWidget"];
     dumpBoundingBoxes(widgets);
 
diff --git a/third_party/WebKit/LayoutTests/inspector/components/widget-events-expected.txt b/third_party/WebKit/LayoutTests/inspector/components/widget-events-expected.txt
index 814aa5bd..f1e9cb3 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/widget-events-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/components/widget-events-expected.txt
@@ -238,3 +238,9 @@
   Child.willHide()
   Parent.willHide()
 
+Running: testAlienParent
+Parent()
+Parent()
+Child()
+Error: Attempt to show under node belonging to alien widget
+
diff --git a/third_party/WebKit/LayoutTests/inspector/components/widget-events.html b/third_party/WebKit/LayoutTests/inspector/components/widget-events.html
index 4174cf0..e4cbc78c 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/widget-events.html
+++ b/third_party/WebKit/LayoutTests/inspector/components/widget-events.html
@@ -151,13 +151,13 @@
             var parentWidget = new TestWidget("Parent");
             parentWidget.markAsRoot();
             var childWidget = new TestWidget("Child");
-            parentWidget.show(WebInspector.inspectorView.element);
+            parentWidget.show(document.body);
 
             parentWidget.doResize();
             childWidget.show(parentWidget.element);
             parentWidget.doResize();
             parentWidget.detach();
-            parentWidget.show(WebInspector.inspectorView.element);
+            parentWidget.show(document.body);
             childWidget.detach();
             parentWidget.detach();
             next();
@@ -341,6 +341,20 @@
             parentWidget.show(WebInspector.inspectorView.element);
             parentWidget.detach();
             next();
+        },
+
+        function testAlienParent(next)
+        {
+            var parentWidget1 = new TestWidget("Parent");
+            var parentWidget2 = new TestWidget("Parent");
+            var childWidget = new TestWidget("Child");
+            childWidget.attach(parentWidget1);
+            try {
+                childWidget.showWidget(parentWidget2.element);
+            } catch (e) {
+                InspectorTest.addResult(e);
+            }
+            next();
         }
     ]);
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/editor/editor-test.js b/third_party/WebKit/LayoutTests/inspector/editor/editor-test.js
index a7ac98b..7422b14c 100644
--- a/third_party/WebKit/LayoutTests/inspector/editor/editor-test.js
+++ b/third_party/WebKit/LayoutTests/inspector/editor/editor-test.js
@@ -95,7 +95,7 @@
     ArrowDown: 40
 };
 
-function createCodeMirrorFakeEvent(eventType, code, charCode, modifiers)
+function createCodeMirrorFakeEvent(editor, eventType, code, charCode, modifiers)
 {
     function eventPreventDefault()
     {
@@ -108,6 +108,7 @@
         charCode: charCode,
         preventDefault: eventPreventDefault,
         stopPropagation: function(){},
+        target: editor._codeMirror.display.input.textarea
     };
     if (modifiers) {
         for (var i = 0; i < modifiers.length; ++i)
@@ -118,7 +119,7 @@
 
 function fakeCodeMirrorKeyEvent(editor, eventType, code, charCode, modifiers)
 {
-    var event = createCodeMirrorFakeEvent(eventType, code, charCode, modifiers);
+    var event = createCodeMirrorFakeEvent(editor, eventType, code, charCode, modifiers);
     switch(eventType) {
     case "keydown":
         editor._codeMirror.triggerOnKeyDown(event);
@@ -138,7 +139,7 @@
 function fakeCodeMirrorInputEvent(editor, character)
 {
     if (typeof character === "string")
-        editor._codeMirror.display.input.value += character;
+        editor._codeMirror.display.input.textarea.value += character;
 }
 
 InspectorTest.fakeKeyEvent = function(editor, originalCode, modifiers, callback)
diff --git a/third_party/WebKit/LayoutTests/media/sources-fallback-codecs-expected.txt b/third_party/WebKit/LayoutTests/media/sources-fallback-codecs-expected.txt
deleted file mode 100644
index 7216bec..0000000
--- a/third_party/WebKit/LayoutTests/media/sources-fallback-codecs-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Test that fallback among codecs is done correctly regardless of their order.     
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/media/sources-fallback-codecs.html b/third_party/WebKit/LayoutTests/media/sources-fallback-codecs.html
index 03bc677..6ffa741 100644
--- a/third_party/WebKit/LayoutTests/media/sources-fallback-codecs.html
+++ b/third_party/WebKit/LayoutTests/media/sources-fallback-codecs.html
@@ -1,263 +1,45 @@
 <!DOCTYPE html>
-<html>
-    <head>
-        <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
-             (Please avoid writing new tests using video-test.js) -->
-        <script src=video-test.js></script>
-        <script>
-            var canPlayThroughCount = 0;
-            function onCanPlayThrough() {
-                if (++canPlayThroughCount == document.getElementsByTagName('video').length + document.getElementsByTagName('audio').length) {
-                    endTest();
-                    return;
-                }
-            }
-            function onError(e) {
-                var type = e.target.type;
-                if (!type) {
-                    var src = e.target.src;
-                    var semicolon;
-                    if ((src.substr(0,5) == "data:") && ((semicolon = src.substr(5).indexOf(';')) > 0))
-                        type = src.substr(5).substr(0, semicolon);
-                    if (!type) {
-                        failTest("Couldn't find type");
-                        return;
-                    }
-                }
+<title>Test that fallback among codecs is done correctly regardless of their order.</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+// This could be made far more general, testing all permutations of
+// (audio|video)Codecs and so on, but in reality we only have these 4
+// test files, so simply enumerating them manually and testing they
+// all hit canplaythrough is good enough. Someday when many more
+// files are present, consider generalizing this.
 
-                if (e.target.tagName == 'SOURCE' && !e.target.parentNode.canPlayType(type)) {
-                    // Expected error; ignore.
-                    return;
-                }
-                var id = (e.target.tagName == 'SOURCE' ? e.target.parentNode.id : e.target.id);
-                failTest("tag: " + e.target.tagName + ", id: " + id + ", src: " + e.target.src);
-            }
-            </script>
-    </head>
-    <body>
-        Test that fallback among codecs is done correctly regardless of their order.
-        <!-- This could be made far more general, testing all permutations of
-             (audio|video)Codecs and so on, but in reality we only have these 4
-             test files, so simply enumerating them manually and testing they
-             all hit canplaythrough is good enough.  Someday when many more
-             files are present, consider generalizing this.
-        -->
+// The base64'd data below was generated from the corresponding content/test.{mp4,ogv}files with:
+// rm -f test-frame.ogv test-frame.mp4 and
+// ~/tmp/ffmpeg/ffmpeg -i test.mp4 -an -vframes 1 test-frame.png and
+// pngtopnm test-frame.png > test-frame.pnm && pnmscale 0.25 test-frame.pnm|pnmtopng > test-frame.png and
+// ~/tmp/ffmpeg/ffmpeg -i test-frame.png -an -vframes 1 -s 80x60 test-frame.mp4 and
+// ffmpeg2theora test-frame.mp4 -o test-frame.ogv && rm test-frame.png test-frame.pnm
+// Followed by [base64 -w 120 test-frame.ogv] and [base64 -w 120 test-frame.mp4].
+var mp4DataSrc = "data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAHuG1kYXQAAAGzABAHAAABthBgdgpU4Bg8SyD1tWXqqBr13UzOZBxmb/64MV3Y2OWRzRBZvxztjdtC0aswA4S201VqgQ/Np60Xf8OUmDifBg+95svvk+lsTg4EMuv6x9WzQbpfFfpARTAuyg4uzeDkGWlUS9HIed50tZ6pNjlvoEfjd6hclYB4KApmDwRrAZTg4Zawfliu78GzrSRSn2346BT23GdS+aoN6cTJARID4MA79lWcA4kA03AYcp4mBVsNlk9hYqEJW20JJePwNxJqthUyX/HNYEHS8P79hhLN0z88EBKyOd+B1NqZkSmM3f98PYrSpxGVM3yYDZa0O1fh/5O2X+YZUK2WVYfe/n3HgYtxtM0pHQkA8H/zsj2RQX80S0+Kh2rBCgMv2gdVpR+r98t6k36bRyJE2B8AxqxLxhod7g6EhYQ8T3vi/jReXfANEtMOmQZcHg/+cG6IybfRqtMAigG43g6Z1uA+D/0/aXh2JCpWr94eCSlZrbKZU1oKZujuwvCGCnA1qcvxZJ/BJmgxb9VRA6Boch+DAJF7KUeYOvCXiYEVpOCmEDGmmByrBhy3GFUgf6x6DnR3VI5/6SMt3auZC58DgjfA2pLsBxfufZsv8t3N/+XLmysB62z/RALC37Kv/1Ost0zGiEOtD/qbAYriTG1CnwPBwC96PlF9crWpNK1WtFmtbJuWXJXfMuPghiUJbPmPD5vitVGYrbYTRq62XKh3U1AzrIfgiBDjegrA+o5V5Fe/LTAuD5igwiNL96HmL9LeoEIgs9Njn4EdPlGBGHSZmK1SRppvFUSZfLTGMxr0zPB1A8VKvXZimtKlXrb5hqGI+2HzFBhEaX70PMX6W9QIRBZ6bHPwI6ftWqYrDIKxq9abBkGb1TjfVhAZUqRBb7BAb6Ofh58t3DNZ/zcU+3P4HOWbBi6Fa7DMRgY+tzvSqoCxnpQIDfQIfGz/fwAAlGlBJKl2GEIGPL970qiEtZ6UiC30CPxu+GqXYYQgY8v3vSqIS1npSILfQI/G738bbfztogcuLou9sK/swqEtInsxr+92bvi1hlgtmXmlgg+8WqKN1HVBCDrB4D8vBkoQ2wPlwMmSfSphCwdYPU/vVRBDZZZV+l0cbQ/LlWJgMZvIH9Z3/rfNVx8eDofsfLv61+AaBTjmfS437cZn7PJml418ciBRz33Mz+LgLCKDD8GA4OgD+AHpWtCEJYHE/x+Oh+qbTKPqtxVlEgv8IrTbebfcAtv7xTG22hb9hwB4CB7BtA6DKgYegGRN9P4uEMSx4PB2OqWiAP0g9V4mLQ+q2stFo5SNyKZ/FCks3+GQLGOWko+rLFHLStNd9VFK83ywea03Vw4qr9QDjQSBiDAHA8BBL4Ac20EEDol+BSl46Vsj8A694m8lZaLPt7palrcm+z7WqYoZ6zVQ5a8ZVLlX1QQGkzfpn2h8IF9KH4deURcPtLbZJ0GKvr2yNfRP9wAAqGbBWAoQZkHApGBCoKoG6Cra+uCKOFAfYmQqB6WlogoxB1EHbfQtG4PA/woPDQFoPFf8oPnQDI2Bi8HgIHkfAxe0B7S5KkAMBVeV1vUwhNKwVYKfC7l/vh6wBYPt5aylUiDQMiKLRgmB4CCjA0pB4L/JUqeA8JAT8RdB4b/hpOXMaA0nbHIMv4cB8mUUGK1O8bAyNmhxhWVjdE4tN5htX7ydkERVqktTllbHHMtwDGFeqd5iyLp9qEoM0DNg8D/kg3QeCgFwVQKYDQPCf+Yflofh+DAqGFCgQCXvUHDolGiQHgIG8DSkHgv9tSp4DwkA3xF0Hhv+uk42LgUQKYtBxeWlqgGAoo4o6DBvSc8v37AKsERoFWIAGgUxXFQN0t4H4dgw2A0uHYF+AIGFet+EMERhgPxGB4X/fLZ4GERSDgVVAyBcFYjBUkVLZYHAhAGA8LAUhCB4mAbLgfNgCWDgQgDAeFgKQhA8TANlwPmwBKF0tsHAhAGA8LAUhCB4mAbLgfNgCWDgQgDAeFgKQhA8TANlwPmwBP1u1a7DMRgY+tzvSqoCxnpQIDfQIfGz2DgQgDAeFgKQhA8TANlwPmwBNsghAHDhsHgoCkQg60HhIB0uoiVACIz0GBGbBXaNn+8AALxqgSSpdhhCBjy/e9KohLWelIgt9Aj8bvgYjwR1baofW40BlgfWgXoMjwA5Svre7QeD/52eXbtW8ptKwtT8JLOjjuNB6H3VtBkIOA90RQeG/52eFHjWhb9Lb8JLOjjuNB6H3VtBkIOA90RQeG/52eFHjWha/CSzo47jQeh91bQZCDgPdEUHhv+dnhR41oW/S2/CSzo47jQeh91bQZCDgPdEUHhv+dnhR41oWvwks6OO40HofdW0GQg4D3RFB4b/nZ4UeNaFv3X9jXt/veey7VGb/eZO1R703/6az2Xdq2SvVaL2m/41k/3U0Sr5zmW8UaabiHCB+ElnRx3Gg9D7q2gyEHAe6IoPDf87PCjxrQtfhJZ0cdxoPQ+6toMhBwHuiKDw3/Ozwo8a0LfrQtWuwzEYGPrc70qqAsZ6UCA30CHxs9+ElnRx3Gg9D7q2gyEHAe6IoPDf87PCjxrQtoGUts5ntjXGcYzSroMN4B6at+7lB4P/nZ5NzYt5TNikBfsAAAMbbW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAAACgAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAkZ0cmFrAAAAXHRraGQAAAAPAAAAAAAAAAAAAAABAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAFAAAAA8AAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAAoAAAAAAABAAAAAAG+bWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAAAGQAAAAFVxAAAAAAALWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABWaWRlb0hhbmRsZXIAAAABaW1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAASlzdGJsAAAAxXN0c2QAAAAAAAAAAQAAALVtcDR2AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAFAAPABIAAAASAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGP//AAAAX2VzZHMAAAAAA4CAgE4AAQAEgICAQCARAAAAAAYBgAAGAYAFgICALgAAAbABAAABtYkTAAABAAAAASAAxI2IAM0ChAeUQwAAAbJMYXZjNTQuMS4xMDAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAQAAAAEAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAHsAAAAAEAAAAUc3RjbwAAAAAAAAABAAAALAAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAAAQAAAABMYXZmNTQuMC4xMDA=";
 
-        <video id='v1' controls oncanplaythrough='onCanPlayThrough()' onerror='onError(event)'>
-            <source onerror='onError(event)' type="video/mp4" src="content/test.mp4"/>
-            <source onerror='onError(event)' type="video/ogg" src="content/test.ogv"/>
-        </video>
+var ogvDataSrc = "data:video/ogg;base64,T2dnUwACAAAAAAAAAABDt3UdAAAAAG1FPOwBQGZpc2hlYWQAAwAAAAAAAAAAAAAA6AMAAAAAAAAAAAAAAAAAAOgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPZ2dTAAIAAAAAAAAAAKK34ysAAAAAwlsClQEqgHRoZW9yYQMCAQAFAAQAAFAAADwABAAAABkAAAABAAABAAABAgAAAIDAT2dnUwAAAAAAAAAAAABDt3UdAQAAAFp3fKUBUGZpc2JvbmUALAAAAKK34ysDAAAAGQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABDb250ZW50LVR5cGU6IHZpZGVvL3RoZW9yYQ0KT2dnUwAAAAAAAAAAAACit+MrAQAAAHoeC5AOWP///////////////5CBdGhlb3JhKwAAAFhpcGguT3JnIGxpYnRoZW9yYSAxLjEgMjAwOTA4MjIgKFRodXNuZWxkYSkBAAAAGgAAAEVOQ09ERVI9ZmZtcGVnMnRoZW9yYS0wLjI0gnRoZW9yYb7NKPe5zWsYtalJShBznOYxjFKUpCEIMYxiEIQhCEAAAAAAAAAAAAARba5TZ5LI/FYS/Hg5W2zmKvVoq1QoEykkWhD+eTmbjWZTCXiyVSmTiSSCGQh8PB2OBqNBgLxWKhQJBGIhCHw8HAyGAsFAiDgVFtrlNnksj8VhL8eDlbbOYq9WirVCgTKSRaEP55OZuNZlMJeLJVKZOJJIIZCHw8HY4Go0GAvFYqFAkEYiEIfDwcDIYCwUCIOBQLDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8MDA8SFBQVDQ0OERIVFRQODg8SFBUVFQ4QERMUFRUVEBEUFRUVFRUSExQVFRUVFRQVFRUVFRUVFRUVFRUVFRUQDAsQFBkbHA0NDhIVHBwbDg0QFBkcHBwOEBMWGx0dHBETGRwcHh4dFBgbHB0eHh0bHB0dHh4eHh0dHR0eHh4dEAsKEBgoMz0MDA4TGjo8Nw4NEBgoOUU4DhEWHTNXUD4SFiU6RG1nTRgjN0BRaHFcMUBOV2d5eGVIXF9icGRnYxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSEhUZGhoaGhIUFhoaGhoaFRYZGhoaGhoZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaERIWHyQkJCQSFBgiJCQkJBYYISQkJCQkHyIkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJBESGC9jY2NjEhUaQmNjY2MYGjhjY2NjYy9CY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2MVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVEhISFRcYGRsSEhUXGBkbHBIVFxgZGxwdFRcYGRscHR0XGBkbHB0dHRgZGxwdHR0eGRscHR0dHh4bHB0dHR4eHhERERQXGhwgEREUFxocICIRFBcaHCAiJRQXGhwgIiUlFxocICIlJSUaHCAiJSUlKRwgIiUlJSkqICIlJSUpKioQEBAUGBwgKBAQFBgcICgwEBQYHCAoMEAUGBwgKDBAQBgcICgwQEBAHCAoMEBAQGAgKDBAQEBggCgwQEBAYICAB8Xlx0fV7c7D8vrrAaZid8hRvB1RN7csxFuo43wH7lEkS9wbGS+tVSNMyuxdiECcjB7R1Ml85htasNjKpSvPt3D8k7iGmZXYuxBC+RR4arUGxkvH5y7mJXR7R5Jwn3VUhBiuap91VIrsaCM5TSg9o867khwMrWY2+cP4rwvBLzt/wnHaYe0edSRMYC6tZmU1BrvhktIUf2gXoU8bHMuyNA7lB7R51ym213sFcFKowIviT/i0Wscg+4RDubX+4haRsMxZWgN05K5FD3bzqS9VSVCPM4TpWs2C43ihFdgaSByeKHu3Xf/2TG8tgpB7PAtOs7jixWYw+Ayo5GjUTSybX/1KW52RxYfB8nBNLJtHgt4DPq6BZWBFpjyZX/1KW5Ca0evOwG1EX/A9j5fQm5hOz6W2CtcCaWTXTFAeZO71VIgCTX69y9TiaXag3Os2ES1DcLKw0/xR5HfnCqkpQF0Z1kxKNfhZWLycml2keduHMQh3HubB/pbUUoCK5wxetZRZWPJF/bdyE21H2YjMOhP/pkthqKUCOEWVm68+1J5n7ahES5sOhaZPdOC5j4kc91FVIsrF8ofe+A2on/16Z4RiKQZcMU3NouO9N4YAvrWaiA6h4bfLqhTitbnnJ2iPSVRNJH+aZGE+YXzq7Ah/OncW2K59AKamlocOUYTSvaJPNcjDfMGrmG9pOV2MbgI9v3B3ECZ7RLJ51UpzMn0C1huA87Ngom9lkiaw3t5yvFZmDl1HpkuP+PiqlawgD69jAT5Nxr2i6cwiytcwHhK2KJvZI9C1m/4VUil8RvO/ydxmgsFdzdgGpMbUeyyRNOi1k5hMb6hVSMuTrOE/xuDhGExQ219l07sV2kG5fOEnkWHwgqUkbvC0P2KTytY4nHLqJDc3DMGlDbX2aXK/4UuJxizaIkZITS7a3HN5374PrVlYKIcP9xl1BUKqQ7aAml2k1o5uGcN8A+tPz1HF1YVnmE7cyx4FIiUA2ml1k0hX9HB7l4tMO+R9YrMWcf5Anub1BZXUp3Ce4jBM21l0kyhcF/vg6FGeHa345MYv4BVSciTJhj5AbuD2K0dfIXc4jKAbazaS53rv1lYqpIVr2fcgcPox4u/WVnRfJ25GGING2s2cqjKIVUtwGbRtrljLd9CQOHhewUTfiKxWk7Olr2dHyIKlLgejEbasmmdGF/dhuhVrU9xGi6Hksgm/+5Bw813T3mJyRNqIYGdYspVZFzQ6dhNLJ7H+fYWh8Q+cMbzLc/O0evM4srXGjpECaXaT2jApqM4LRavgPnH7ecDRQSErabX3zC4EcXfOVZZUpYs3UIfMsKVR+6hgFzHhvWWWl4EqZtrJpHnyeO0T2icPrqVRyyDRKmbayexv7wdolGfh1hwtsK4G5jDOIHz/lTULUM47PaBmNJm2ssmTq+ssXeHBjgij3G5P+u5QVFIGQ21TNM5aGOHbqKssQ/HiM9kvcWjdCtF6gZNMzbXFhNP2gV2FNQi+OpOR+S+3RvOBVSOr+E5hjyPrQho7/QDNEG2qRNLpHl6WVl3m4p3POFvwEWUN0ByvCQTSttdM48H7tjQWVk73qoUvhiSDbVK0mzyohbuHXofmEaK/xXYJ+Vq7tBUN6lMAdrouC3p96IS8kMzbVK0myY4f+HKdRGsrG9SlDwEfQkXsGLIbapmmcv/sA5TrqC36t4sRdjylU4JC9KwG2plM0zxuT2iFFzAPXyj9ZWRu+tx5UpFv0jn0gQrKyMF5MyaZsDbXG7/qIdp0tHG4jOQumLzBliaZttaLfZFUBSOu7FaUn/+IXETfwUj2E0o6gJ2HB/l8N7jFnzWWBESErabWPvy9bUKqS4y78CME0rbXSTNFRf8H7r1wwxQbltish5nFVIRkhKaTNtc6L3LHAh8+B2yi/tHvXG4nusVwAKMb/0/MCmoWrvASDM0mbay5YRI+7CtC96OPtxudDEyTGmbbWVRgkvR8qaiA8+rLCft7cW8H8UI3E8nzmJVSQIT3+0srHfUbgKA21ZNM8WEy+W7wbj9OuBpm21MKGWN80kaA5PZfoSqkRPLa1h31wIEjiUhcnX/e5VSWVkQnPhtqoYXrjLFpn7M8tjB17xSqfWgoA21StJpM48eSG+5A/dsGUQn8sV7impA4dQjxPyrsBfHd8tUGBIJWkxtrnljE3eu/xTUO/nVsA9I4uVlZ5uQvy9IwYjbWUmaZ5XE9HAWVkXUKmoI3y4vDKZpnKNtccJHK2iA83ej+fvgI3KR9P6qpG/kBCUdxHFisLkq8aZttTCZlj/b0G8XoLX/3fHhZWCVcMsWmZtqmYXz0cpOiBHCqpKUZu76iICRxYVuSULpmF/421MsWmfyhbP4ew1FVKAjFlY437JXImUTm2r/4ZYtMy61hf16RPJIRA8tU1BDc5/JzAkEzTM21lyx7sK9wojRX/OHXoOv05IDbUymaZyscL7qlMA8c/CiK3csceqzuOEU1EPpbz4QEahIShpm21MJmWN924f98WKyf51EEYBli0zNtUzC+6X9P9ysrU1CHyA3RJFFr1w67HpyULT+YMsWmZtquYXz97oKil44sI1bpL8hRSDeMkhiIBwOgxwZ5Fs6+5M+NdH+3Kjv0sreSqqRvGSQxEA4HQY4M8i2dfcmfGuj/blR36WVvJVVI3jJIYiAcDoMcGeRbOvuTPjXR/tyo79LK3kqqkVUnCfqAES8EzTM21lykY4Q+LKxby+9F3ZHR/uC2OGpS9cv6BZXAebhckMGIymaZm2st8/B38i6A/n58pVLKwfURet4UBwSF6UaZttSZljhd2jW9BZWcrX0/hG4Sdt/SBCdH6UMJmWK80zba3URKaik8iB9PR2459CuyOAbi0/GWLTMmYXm2t0vUkNQhRPVldKpAN5HgHyZfdOtGuj/YxwZ5S8u3CjqMgQoyQJRdawvJlE530/+sVg21c8GWLTPf3yJVSVUoCMWVjjfslciZRObav/hli0zLrWF/XpE8khT2dnUwAEAAAAAAAAAABDt3UdAgAAAAzIIuQBAE9nZ1MABEAAAAAAAAAAorfjKwIAAABgTJAeBf////+/IK2oPwLwetDyEoOnddpgLM7J5tdTLMgoKCgs2quQe7o7SkFBQfQK1d3nTvIG8WYJg+kQTYyKcCBTI2uld4Ck3ITAiUxzwCDzbvEz4RL4jH2GES+Ix2gjjoZkfroYD2Rxe50JehL0UdqOhDasSshteOirUpDV6cdCD6ZJksRwtMAehrVhPC2k8aZU2c9cac+Z9PmWWWX4+Pj4BEssvCb4TfCZNG9wSOUm6QGyfTX2kmypyN8xrVMPuq146O3o6OjorWtdevXrGK1qWvX08a6Rq0xLLxJJJTaDmSCHcNKfdSi8+/01vmG83m83ns7OzsErzebyPYtBJ0iEFRa8Nk7BZXXvaD9HsioatlKUtt6FxDflKUpxFWLa06Gy9Fa73KyurjJRShhHP3rKPc1/8e9M4svw7z9/y5hmd6tC/+c2BGWkiRIkSMOWLESxaepEN5HCA8fbnt2c+oiWh3nDTVDj5GpecOZ6Pej2HglzRu77Ha7NevXrw9mr17Ge0nSP3nJ+/u8QhEvP/jNd8EFWSIRATu7oooou7uijwzeQQSuISlxl4fNRTj4fl3hrIGCibpjzMyqyFWQqyFWQBMyJVkKPwSJe+CRxuoEF/gEU2CHC4E9tYgQEIgLbW21ttbbW21ttbbW3VRNfeEUjw5p+43Jszx9/+J9Xq/cPHkNoGheXKleIvTLu7iOchCVRx4+8YZD/8eO7wQfAz3YR//ArgZPYDA4O/j0JZ8SBCyNGQJAoyBIGM3Nszg65/dg9KU0ZAssfyut/18FfOYHejZoiN64XH3AV8+A+MZAbifeO46k45f/YwcgIrj/v0lKe/O7777/urfwDuRL4vnLC2W8VNKmlTXI85zhb9Tzg5Pq3b4MHGJysA0vsJbIsiyLIsEXpf8Fvh9ve5rMuDmsFkgjCv6z0V/RCArnWZw2pL3cs2uKgHydecWhDe3OxQXkRfRz3haf8V7+0/u7FiQDyfSCDxnf/uIhzK8RYGDCXYRMYqVpiJEi6iqzlnq91PbMvN7rqyqfI2QlKUpAgQIcDeBvA3afsV8/MqBxcDH6z8DKVq+fDeHyLb9bk1SlLLSZV5sj6vR9c+ZoSzmUe7nFIY77Io1uY7TGlp67W1xSRjyffmuz+ZZnIo6iK81o5jPqjLad2pJVNlxcrFNTU1NxMGZmYZLw9FOO1MMyzMZOXW2i5f+SZOTWvXrxbvWtF9F/qpM8k7VWZ1srpVdmc/rNt5671q/4oaPLioDn63vKe+3TsR1QdT3cbbX29dJhFWxGfPji8uow/RvEdxN26QXd3d3dmltxmvn9xX41q7lJ+EyZMmTJk5d7e2lt4T80idGzp5p4ZOwcwt9MfSg2px6rrOjC7dunTLPnPm37py9tZjaU10a2lujlPd5ZYZbWZmZmYa7t76epZjI6IyFSpUiRI6tO81MJ+FSshXxUNo2qCYteb6DTfQ7eWHcYqrx8q3N+WmphpSJJJJM/j1au8t2/m25K9evXr169fcx23mLqG6yrVvctNSdG9PTPz32j10DtUeJJJCiPs2L3slpLcg3LLLJJJQaTfR9IalPOLMvdptttts9C1Q35jwWm306Lp06dOnTp0aWtuFpwSSSSHPcIguQA=";
 
-        <video id='v2' controls oncanplaythrough='onCanPlayThrough()' onerror='onError(event)'>
-            <source onerror='onError(event)' type="video/ogg" src="content/test.ogv"/>
-            <source onerror='onError(event)' type="video/mp4" src="content/test.mp4"/>
-        </video>
+var testInfo = [
+    { element: "video", typeArray: ["video/mp4", "video/ogg"], srcArray: ["content/test.mp4", "content/test.ogv"], description: "Test video with ['video/mp4', 'video/ogg']" },
+    { element: "video", typeArray: ["video/ogg", "video/mp4"], srcArray: ["content/test.ogv", "content/test.mp4"], description: "Test video with ['video/ogg', 'video/mp4']" },
+    { element: "audio", typeArray: ["audio/wav", "audio/ogg"], srcArray: ["content/test.wav", "content/test.oga"], description: "Test audio with ['audio/wav', 'audio/ogg']" },
+    { element: "audio", typeArray: ["audio/ogg", "audio/wav"], srcArray: ["content/test.oga", "content/test.wav"], description: "Test audio with ['audio/ogg', 'audio/wav']" },
+    { element: "video", srcArray: [mp4DataSrc, ogvDataSrc], description: "Test video with ['data:video/mp4;base64', 'data:video/ogg;base64']" },
+    { element: "video", srcArray: [ogvDataSrc, mp4DataSrc], description: "Test video with ['data:video/ogg;base64', 'data:video/mp4;base64']" }
+];
 
-        <audio id='a1' controls oncanplaythrough='onCanPlayThrough()' onerror='onError(event)'>
-            <source onerror='onError(event)' type="audio/wav" src="content/test.wav"/>
-            <source onerror='onError(event)' type="audio/ogg" src="content/test.oga"/>
-        </audio>
-
-        <audio id='a2' controls oncanplaythrough='onCanPlayThrough()' onerror='onError(event)'>
-            <source onerror='onError(event)' type="audio/ogg" src="content/test.oga"/>
-            <source onerror='onError(event)' type="audio/wav" src="content/test.wav"/>
-        </audio>
-
-        <!-- The base64'd data below was generated from the corresponding content/test.{mp4,ogv} files with:
-             rm -f test-frame.ogv test-frame.mp4 && \
-               ~/tmp/ffmpeg/ffmpeg -i test.mp4 -an -vframes 1 test-frame.png && \
-               pngtopnm test-frame.png > test-frame.pnm && pnmscale 0.25 test-frame.pnm|pnmtopng > test-frame.png && \
-               ~/tmp/ffmpeg/ffmpeg -i test-frame.png -an -vframes 1 -s 80x60 test-frame.mp4 && \
-               ffmpeg2theora test-frame.mp4 -o test-frame.ogv && rm test-frame.png test-frame.pnm
-             Followed by [base64 -w 120 test-frame.ogv] and [base64 -w 120 test-frame.mp4].
-        -->
-        <video id="v3" controls oncanplaythrough='onCanPlayThrough()' onerror='onError(event)'>
-            <source onerror='onError(event)'
-                    src="data:video/mp4;base64,
-AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAHuG1kYXQAAAGzABAHAAABthBgdgpU4Bg8SyD1tWXqqBr13UzOZBxmb/64MV3Y2OWRzRBZ
-vxztjdtC0aswA4S201VqgQ/Np60Xf8OUmDifBg+95svvk+lsTg4EMuv6x9WzQbpfFfpARTAuyg4uzeDkGWlUS9HIed50tZ6pNjlvoEfjd6hclYB4KApmDwRr
-AZTg4Zawfliu78GzrSRSn2346BT23GdS+aoN6cTJARID4MA79lWcA4kA03AYcp4mBVsNlk9hYqEJW20JJePwNxJqthUyX/HNYEHS8P79hhLN0z88EBKyOd+B
-1NqZkSmM3f98PYrSpxGVM3yYDZa0O1fh/5O2X+YZUK2WVYfe/n3HgYtxtM0pHQkA8H/zsj2RQX80S0+Kh2rBCgMv2gdVpR+r98t6k36bRyJE2B8AxqxLxhod
-7g6EhYQ8T3vi/jReXfANEtMOmQZcHg/+cG6IybfRqtMAigG43g6Z1uA+D/0/aXh2JCpWr94eCSlZrbKZU1oKZujuwvCGCnA1qcvxZJ/BJmgxb9VRA6Boch+D
-AJF7KUeYOvCXiYEVpOCmEDGmmByrBhy3GFUgf6x6DnR3VI5/6SMt3auZC58DgjfA2pLsBxfufZsv8t3N/+XLmysB62z/RALC37Kv/1Ost0zGiEOtD/qbAYri
-TG1CnwPBwC96PlF9crWpNK1WtFmtbJuWXJXfMuPghiUJbPmPD5vitVGYrbYTRq62XKh3U1AzrIfgiBDjegrA+o5V5Fe/LTAuD5igwiNL96HmL9LeoEIgs9Nj
-n4EdPlGBGHSZmK1SRppvFUSZfLTGMxr0zPB1A8VKvXZimtKlXrb5hqGI+2HzFBhEaX70PMX6W9QIRBZ6bHPwI6ftWqYrDIKxq9abBkGb1TjfVhAZUqRBb7BA
-b6Ofh58t3DNZ/zcU+3P4HOWbBi6Fa7DMRgY+tzvSqoCxnpQIDfQIfGz/fwAAlGlBJKl2GEIGPL970qiEtZ6UiC30CPxu+GqXYYQgY8v3vSqIS1npSILfQI/G
-738bbfztogcuLou9sK/swqEtInsxr+92bvi1hlgtmXmlgg+8WqKN1HVBCDrB4D8vBkoQ2wPlwMmSfSphCwdYPU/vVRBDZZZV+l0cbQ/LlWJgMZvIH9Z3/rfN
-Vx8eDofsfLv61+AaBTjmfS437cZn7PJml418ciBRz33Mz+LgLCKDD8GA4OgD+AHpWtCEJYHE/x+Oh+qbTKPqtxVlEgv8IrTbebfcAtv7xTG22hb9hwB4CB7B
-tA6DKgYegGRN9P4uEMSx4PB2OqWiAP0g9V4mLQ+q2stFo5SNyKZ/FCks3+GQLGOWko+rLFHLStNd9VFK83ywea03Vw4qr9QDjQSBiDAHA8BBL4Ac20EEDol+
-BSl46Vsj8A694m8lZaLPt7palrcm+z7WqYoZ6zVQ5a8ZVLlX1QQGkzfpn2h8IF9KH4deURcPtLbZJ0GKvr2yNfRP9wAAqGbBWAoQZkHApGBCoKoG6Cra+uCK
-OFAfYmQqB6WlogoxB1EHbfQtG4PA/woPDQFoPFf8oPnQDI2Bi8HgIHkfAxe0B7S5KkAMBVeV1vUwhNKwVYKfC7l/vh6wBYPt5aylUiDQMiKLRgmB4CCjA0pB
-4L/JUqeA8JAT8RdB4b/hpOXMaA0nbHIMv4cB8mUUGK1O8bAyNmhxhWVjdE4tN5htX7ydkERVqktTllbHHMtwDGFeqd5iyLp9qEoM0DNg8D/kg3QeCgFwVQKY
-DQPCf+Yflofh+DAqGFCgQCXvUHDolGiQHgIG8DSkHgv9tSp4DwkA3xF0Hhv+uk42LgUQKYtBxeWlqgGAoo4o6DBvSc8v37AKsERoFWIAGgUxXFQN0t4H4dgw
-2A0uHYF+AIGFet+EMERhgPxGB4X/fLZ4GERSDgVVAyBcFYjBUkVLZYHAhAGA8LAUhCB4mAbLgfNgCWDgQgDAeFgKQhA8TANlwPmwBKF0tsHAhAGA8LAUhCB4
-mAbLgfNgCWDgQgDAeFgKQhA8TANlwPmwBP1u1a7DMRgY+tzvSqoCxnpQIDfQIfGz2DgQgDAeFgKQhA8TANlwPmwBNsghAHDhsHgoCkQg60HhIB0uoiVACIz0
-GBGbBXaNn+8AALxqgSSpdhhCBjy/e9KohLWelIgt9Aj8bvgYjwR1baofW40BlgfWgXoMjwA5Svre7QeD/52eXbtW8ptKwtT8JLOjjuNB6H3VtBkIOA90RQeG
-/52eFHjWhb9Lb8JLOjjuNB6H3VtBkIOA90RQeG/52eFHjWha/CSzo47jQeh91bQZCDgPdEUHhv+dnhR41oW/S2/CSzo47jQeh91bQZCDgPdEUHhv+dnhR41o
-Wvwks6OO40HofdW0GQg4D3RFB4b/nZ4UeNaFv3X9jXt/veey7VGb/eZO1R703/6az2Xdq2SvVaL2m/41k/3U0Sr5zmW8UaabiHCB+ElnRx3Gg9D7q2gyEHAe
-6IoPDf87PCjxrQtfhJZ0cdxoPQ+6toMhBwHuiKDw3/Ozwo8a0LfrQtWuwzEYGPrc70qqAsZ6UCA30CHxs9+ElnRx3Gg9D7q2gyEHAe6IoPDf87PCjxrQtoGU
-ts5ntjXGcYzSroMN4B6at+7lB4P/nZ5NzYt5TNikBfsAAAMbbW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAAACgAAQAAAQAAAAAAAAAAAAAAAAEAAAAA
-AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAkZ0cmFrAAAAXHRraGQAAAAPAAAAAAAAAAAAAAAB
-AAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAFAAAAA8AAAAAAAkZWR0cwAAABxlbHN0AAAAAAAA
-AAEAAAAoAAAAAAABAAAAAAG+bWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAAAGQAAAAFVxAAAAAAALWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABWaWRl
-b0hhbmRsZXIAAAABaW1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAASlzdGJsAAAAxXN0c2QA
-AAAAAAAAAQAAALVtcDR2AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAFAAPABIAAAASAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-GP//AAAAX2VzZHMAAAAAA4CAgE4AAQAEgICAQCARAAAAAAYBgAAGAYAFgICALgAAAbABAAABtYkTAAABAAAAASAAxI2IAM0ChAeUQwAAAbJMYXZjNTQuMS4x
-MDAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAQAAAAEAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAHsAAAAAEAAAAUc3RjbwAA
-AAAAAAABAAAALAAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAA
-AQAAAABMYXZmNTQuMC4xMDA="/>
-            <source onerror='onError(event)'
-                    src="data:video/ogg;base64,
-T2dnUwACAAAAAAAAAABDt3UdAAAAAG1FPOwBQGZpc2hlYWQAAwAAAAAAAAAAAAAA6AMAAAAAAAAAAAAAAAAAAOgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AABPZ2dTAAIAAAAAAAAAAKK34ysAAAAAwlsClQEqgHRoZW9yYQMCAQAFAAQAAFAAADwABAAAABkAAAABAAABAAABAgAAAIDAT2dnUwAAAAAAAAAAAABDt3Ud
-AQAAAFp3fKUBUGZpc2JvbmUALAAAAKK34ysDAAAAGQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABDb250ZW50LVR5cGU6IHZpZGVvL3RoZW9yYQ0K
-T2dnUwAAAAAAAAAAAACit+MrAQAAAHoeC5AOWP///////////////5CBdGhlb3JhKwAAAFhpcGguT3JnIGxpYnRoZW9yYSAxLjEgMjAwOTA4MjIgKFRodXNu
-ZWxkYSkBAAAAGgAAAEVOQ09ERVI9ZmZtcGVnMnRoZW9yYS0wLjI0gnRoZW9yYb7NKPe5zWsYtalJShBznOYxjFKUpCEIMYxiEIQhCEAAAAAAAAAAAAARba5T
-Z5LI/FYS/Hg5W2zmKvVoq1QoEykkWhD+eTmbjWZTCXiyVSmTiSSCGQh8PB2OBqNBgLxWKhQJBGIhCHw8HAyGAsFAiDgVFtrlNnksj8VhL8eDlbbOYq9WirVC
-gTKSRaEP55OZuNZlMJeLJVKZOJJIIZCHw8HY4Go0GAvFYqFAkEYiEIfDwcDIYCwUCIOBQLDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw
-8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8MDA8SFBQVDQ0OERIVFRQODg8SFBUVFQ4QERMUFRUVEBEUFRUVFRUSExQVFRUVFRQVFRUVFRUVFRUVFRUVFR
-UQDAsQFBkbHA0NDhIVHBwbDg0QFBkcHBwOEBMWGx0dHBETGRwcHh4dFBgbHB0eHh0bHB0dHh4eHh0dHR0eHh4dEAsKEBgoMz0MDA4TGjo8Nw4NEBgoOUU4Dh
-EWHTNXUD4SFiU6RG1nTRgjN0BRaHFcMUBOV2d5eGVIXF9icGRnYxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx
-MTExMTExMTExMTExMSEhUZGhoaGhIUFhoaGhoaFRYZGhoaGhoZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaERIWHyQkJCQSFBgiJC
-QkJBYYISQkJCQkHyIkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJBESGC9jY2NjEhUaQmNjY2MYGjhjY2NjYy9CY2NjY2NjY2NjY2NjY2
-NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2MVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVEh
-ISFRcYGRsSEhUXGBkbHBIVFxgZGxwdFRcYGRscHR0XGBkbHB0dHRgZGxwdHR0eGRscHR0dHh4bHB0dHR4eHhERERQXGhwgEREUFxocICIRFBcaHCAiJRQXGh
-wgIiUlFxocICIlJSUaHCAiJSUlKRwgIiUlJSkqICIlJSUpKioQEBAUGBwgKBAQFBgcICgwEBQYHCAoMEAUGBwgKDBAQBgcICgwQEBAHCAoMEBAQGAgKDBAQE
-BggCgwQEBAYICAB8Xlx0fV7c7D8vrrAaZid8hRvB1RN7csxFuo43wH7lEkS9wbGS+tVSNMyuxdiECcjB7R1Ml85htasNjKpSvPt3D8k7iGmZXYuxBC+RR4ar
-UGxkvH5y7mJXR7R5Jwn3VUhBiuap91VIrsaCM5TSg9o867khwMrWY2+cP4rwvBLzt/wnHaYe0edSRMYC6tZmU1BrvhktIUf2gXoU8bHMuyNA7lB7R51ym213
-sFcFKowIviT/i0Wscg+4RDubX+4haRsMxZWgN05K5FD3bzqS9VSVCPM4TpWs2C43ihFdgaSByeKHu3Xf/2TG8tgpB7PAtOs7jixWYw+Ayo5GjUTSybX/1KW5
-2RxYfB8nBNLJtHgt4DPq6BZWBFpjyZX/1KW5Ca0evOwG1EX/A9j5fQm5hOz6W2CtcCaWTXTFAeZO71VIgCTX69y9TiaXag3Os2ES1DcLKw0/xR5HfnCqkpQF
-0Z1kxKNfhZWLycml2keduHMQh3HubB/pbUUoCK5wxetZRZWPJF/bdyE21H2YjMOhP/pkthqKUCOEWVm68+1J5n7ahES5sOhaZPdOC5j4kc91FVIsrF8ofe+A
-2on/16Z4RiKQZcMU3NouO9N4YAvrWaiA6h4bfLqhTitbnnJ2iPSVRNJH+aZGE+YXzq7Ah/OncW2K59AKamlocOUYTSvaJPNcjDfMGrmG9pOV2MbgI9v3B3EC
-Z7RLJ51UpzMn0C1huA87Ngom9lkiaw3t5yvFZmDl1HpkuP+PiqlawgD69jAT5Nxr2i6cwiytcwHhK2KJvZI9C1m/4VUil8RvO/ydxmgsFdzdgGpMbUeyyRNO
-i1k5hMb6hVSMuTrOE/xuDhGExQ219l07sV2kG5fOEnkWHwgqUkbvC0P2KTytY4nHLqJDc3DMGlDbX2aXK/4UuJxizaIkZITS7a3HN5374PrVlYKIcP9xl1BU
-KqQ7aAml2k1o5uGcN8A+tPz1HF1YVnmE7cyx4FIiUA2ml1k0hX9HB7l4tMO+R9YrMWcf5Anub1BZXUp3Ce4jBM21l0kyhcF/vg6FGeHa345MYv4BVSciTJhj
-5AbuD2K0dfIXc4jKAbazaS53rv1lYqpIVr2fcgcPox4u/WVnRfJ25GGING2s2cqjKIVUtwGbRtrljLd9CQOHhewUTfiKxWk7Olr2dHyIKlLgejEbasmmdGF/
-dhuhVrU9xGi6Hksgm/+5Bw813T3mJyRNqIYGdYspVZFzQ6dhNLJ7H+fYWh8Q+cMbzLc/O0evM4srXGjpECaXaT2jApqM4LRavgPnH7ecDRQSErabX3zC4EcX
-fOVZZUpYs3UIfMsKVR+6hgFzHhvWWWl4EqZtrJpHnyeO0T2icPrqVRyyDRKmbayexv7wdolGfh1hwtsK4G5jDOIHz/lTULUM47PaBmNJm2ssmTq+ssXeHBjg
-ij3G5P+u5QVFIGQ21TNM5aGOHbqKssQ/HiM9kvcWjdCtF6gZNMzbXFhNP2gV2FNQi+OpOR+S+3RvOBVSOr+E5hjyPrQho7/QDNEG2qRNLpHl6WVl3m4p3POF
-vwEWUN0ByvCQTSttdM48H7tjQWVk73qoUvhiSDbVK0mzyohbuHXofmEaK/xXYJ+Vq7tBUN6lMAdrouC3p96IS8kMzbVK0myY4f+HKdRGsrG9SlDwEfQkXsGL
-Ibapmmcv/sA5TrqC36t4sRdjylU4JC9KwG2plM0zxuT2iFFzAPXyj9ZWRu+tx5UpFv0jn0gQrKyMF5MyaZsDbXG7/qIdp0tHG4jOQumLzBliaZttaLfZFUBS
-Ou7FaUn/+IXETfwUj2E0o6gJ2HB/l8N7jFnzWWBESErabWPvy9bUKqS4y78CME0rbXSTNFRf8H7r1wwxQbltish5nFVIRkhKaTNtc6L3LHAh8+B2yi/tHvXG
-4nusVwAKMb/0/MCmoWrvASDM0mbay5YRI+7CtC96OPtxudDEyTGmbbWVRgkvR8qaiA8+rLCft7cW8H8UI3E8nzmJVSQIT3+0srHfUbgKA21ZNM8WEy+W7wbj
-9OuBpm21MKGWN80kaA5PZfoSqkRPLa1h31wIEjiUhcnX/e5VSWVkQnPhtqoYXrjLFpn7M8tjB17xSqfWgoA21StJpM48eSG+5A/dsGUQn8sV7impA4dQjxPy
-rsBfHd8tUGBIJWkxtrnljE3eu/xTUO/nVsA9I4uVlZ5uQvy9IwYjbWUmaZ5XE9HAWVkXUKmoI3y4vDKZpnKNtccJHK2iA83ej+fvgI3KR9P6qpG/kBCUdxHF
-isLkq8aZttTCZlj/b0G8XoLX/3fHhZWCVcMsWmZtqmYXz0cpOiBHCqpKUZu76iICRxYVuSULpmF/421MsWmfyhbP4ew1FVKAjFlY437JXImUTm2r/4ZYtMy6
-1hf16RPJIRA8tU1BDc5/JzAkEzTM21lyx7sK9wojRX/OHXoOv05IDbUymaZyscL7qlMA8c/CiK3csceqzuOEU1EPpbz4QEahIShpm21MJmWN924f98WKyf51
-EEYBli0zNtUzC+6X9P9ysrU1CHyA3RJFFr1w67HpyULT+YMsWmZtquYXz97oKil44sI1bpL8hRSDeMkhiIBwOgxwZ5Fs6+5M+NdH+3Kjv0sreSqqRvGSQxEA
-4HQY4M8i2dfcmfGuj/blR36WVvJVVI3jJIYiAcDoMcGeRbOvuTPjXR/tyo79LK3kqqkVUnCfqAES8EzTM21lykY4Q+LKxby+9F3ZHR/uC2OGpS9cv6BZXAeb
-hckMGIymaZm2st8/B38i6A/n58pVLKwfURet4UBwSF6UaZttSZljhd2jW9BZWcrX0/hG4Sdt/SBCdH6UMJmWK80zba3URKaik8iB9PR2459CuyOAbi0/GWLT
-MmYXm2t0vUkNQhRPVldKpAN5HgHyZfdOtGuj/YxwZ5S8u3CjqMgQoyQJRdawvJlE530/+sVg21c8GWLTPf3yJVSVUoCMWVjjfslciZRObav/hli0zLrWF/Xp
-E8khT2dnUwAEAAAAAAAAAABDt3UdAgAAAAzIIuQBAE9nZ1MABEAAAAAAAAAAorfjKwIAAABgTJAeBf////+/IK2oPwLwetDyEoOnddpgLM7J5tdTLMgoKCgs
-2quQe7o7SkFBQfQK1d3nTvIG8WYJg+kQTYyKcCBTI2uld4Ck3ITAiUxzwCDzbvEz4RL4jH2GES+Ix2gjjoZkfroYD2Rxe50JehL0UdqOhDasSshteOirUpDV
-6cdCD6ZJksRwtMAehrVhPC2k8aZU2c9cac+Z9PmWWWX4+Pj4BEssvCb4TfCZNG9wSOUm6QGyfTX2kmypyN8xrVMPuq146O3o6OjorWtdevXrGK1qWvX08a6R
-q0xLLxJJJTaDmSCHcNKfdSi8+/01vmG83m83ns7OzsErzebyPYtBJ0iEFRa8Nk7BZXXvaD9HsioatlKUtt6FxDflKUpxFWLa06Gy9Fa73KyurjJRShhHP3rK
-Pc1/8e9M4svw7z9/y5hmd6tC/+c2BGWkiRIkSMOWLESxaepEN5HCA8fbnt2c+oiWh3nDTVDj5GpecOZ6Pej2HglzRu77Ha7NevXrw9mr17Ge0nSP3nJ+/u8Q
-hEvP/jNd8EFWSIRATu7oooou7uijwzeQQSuISlxl4fNRTj4fl3hrIGCibpjzMyqyFWQqyFWQBMyJVkKPwSJe+CRxuoEF/gEU2CHC4E9tYgQEIgLbW21ttbbW
-21ttbbW3VRNfeEUjw5p+43Jszx9/+J9Xq/cPHkNoGheXKleIvTLu7iOchCVRx4+8YZD/8eO7wQfAz3YR//ArgZPYDA4O/j0JZ8SBCyNGQJAoyBIGM3Nszg65
-/dg9KU0ZAssfyut/18FfOYHejZoiN64XH3AV8+A+MZAbifeO46k45f/YwcgIrj/v0lKe/O7777/urfwDuRL4vnLC2W8VNKmlTXI85zhb9Tzg5Pq3b4MHGJys
-A0vsJbIsiyLIsEXpf8Fvh9ve5rMuDmsFkgjCv6z0V/RCArnWZw2pL3cs2uKgHydecWhDe3OxQXkRfRz3haf8V7+0/u7FiQDyfSCDxnf/uIhzK8RYGDCXYRMY
-qVpiJEi6iqzlnq91PbMvN7rqyqfI2QlKUpAgQIcDeBvA3afsV8/MqBxcDH6z8DKVq+fDeHyLb9bk1SlLLSZV5sj6vR9c+ZoSzmUe7nFIY77Io1uY7TGlp67W
-1xSRjyffmuz+ZZnIo6iK81o5jPqjLad2pJVNlxcrFNTU1NxMGZmYZLw9FOO1MMyzMZOXW2i5f+SZOTWvXrxbvWtF9F/qpM8k7VWZ1srpVdmc/rNt5671q/4o
-aPLioDn63vKe+3TsR1QdT3cbbX29dJhFWxGfPji8uow/RvEdxN26QXd3d3dmltxmvn9xX41q7lJ+EyZMmTJk5d7e2lt4T80idGzp5p4ZOwcwt9MfSg2px6rr
-OjC7dunTLPnPm37py9tZjaU10a2lujlPd5ZYZbWZmZmYa7t76epZjI6IyFSpUiRI6tO81MJ+FSshXxUNo2qCYteb6DTfQ7eWHcYqrx8q3N+WmphpSJJJJM/j
-1au8t2/m25K9evXr169fcx23mLqG6yrVvctNSdG9PTPz32j10DtUeJJJCiPs2L3slpLcg3LLLJJJQaTfR9IalPOLMvdptttts9C1Q35jwWm306Lp06dOnTp0
-aWtuFpwSSSSHPcIguQA="/>
-        </video>
-
-        <video id="v4" controls oncanplaythrough='onCanPlayThrough()' onerror='onError(event)'>
-            <source onerror='onError(event)'
-                    src="data:video/ogg;base64,
-T2dnUwACAAAAAAAAAABDt3UdAAAAAG1FPOwBQGZpc2hlYWQAAwAAAAAAAAAAAAAA6AMAAAAAAAAAAAAAAAAAAOgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AABPZ2dTAAIAAAAAAAAAAKK34ysAAAAAwlsClQEqgHRoZW9yYQMCAQAFAAQAAFAAADwABAAAABkAAAABAAABAAABAgAAAIDAT2dnUwAAAAAAAAAAAABDt3Ud
-AQAAAFp3fKUBUGZpc2JvbmUALAAAAKK34ysDAAAAGQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABDb250ZW50LVR5cGU6IHZpZGVvL3RoZW9yYQ0K
-T2dnUwAAAAAAAAAAAACit+MrAQAAAHoeC5AOWP///////////////5CBdGhlb3JhKwAAAFhpcGguT3JnIGxpYnRoZW9yYSAxLjEgMjAwOTA4MjIgKFRodXNu
-ZWxkYSkBAAAAGgAAAEVOQ09ERVI9ZmZtcGVnMnRoZW9yYS0wLjI0gnRoZW9yYb7NKPe5zWsYtalJShBznOYxjFKUpCEIMYxiEIQhCEAAAAAAAAAAAAARba5T
-Z5LI/FYS/Hg5W2zmKvVoq1QoEykkWhD+eTmbjWZTCXiyVSmTiSSCGQh8PB2OBqNBgLxWKhQJBGIhCHw8HAyGAsFAiDgVFtrlNnksj8VhL8eDlbbOYq9WirVC
-gTKSRaEP55OZuNZlMJeLJVKZOJJIIZCHw8HY4Go0GAvFYqFAkEYiEIfDwcDIYCwUCIOBQLDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw
-8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8MDA8SFBQVDQ0OERIVFRQODg8SFBUVFQ4QERMUFRUVEBEUFRUVFRUSExQVFRUVFRQVFRUVFRUVFRUVFRUVFR
-UQDAsQFBkbHA0NDhIVHBwbDg0QFBkcHBwOEBMWGx0dHBETGRwcHh4dFBgbHB0eHh0bHB0dHh4eHh0dHR0eHh4dEAsKEBgoMz0MDA4TGjo8Nw4NEBgoOUU4Dh
-EWHTNXUD4SFiU6RG1nTRgjN0BRaHFcMUBOV2d5eGVIXF9icGRnYxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEx
-MTExMTExMTExMTExMSEhUZGhoaGhIUFhoaGhoaFRYZGhoaGhoZGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaERIWHyQkJCQSFBgiJC
-QkJBYYISQkJCQkHyIkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJBESGC9jY2NjEhUaQmNjY2MYGjhjY2NjYy9CY2NjY2NjY2NjY2NjY2
-NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2MVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVEh
-ISFRcYGRsSEhUXGBkbHBIVFxgZGxwdFRcYGRscHR0XGBkbHB0dHRgZGxwdHR0eGRscHR0dHh4bHB0dHR4eHhERERQXGhwgEREUFxocICIRFBcaHCAiJRQXGh
-wgIiUlFxocICIlJSUaHCAiJSUlKRwgIiUlJSkqICIlJSUpKioQEBAUGBwgKBAQFBgcICgwEBQYHCAoMEAUGBwgKDBAQBgcICgwQEBAHCAoMEBAQGAgKDBAQE
-BggCgwQEBAYICAB8Xlx0fV7c7D8vrrAaZid8hRvB1RN7csxFuo43wH7lEkS9wbGS+tVSNMyuxdiECcjB7R1Ml85htasNjKpSvPt3D8k7iGmZXYuxBC+RR4ar
-UGxkvH5y7mJXR7R5Jwn3VUhBiuap91VIrsaCM5TSg9o867khwMrWY2+cP4rwvBLzt/wnHaYe0edSRMYC6tZmU1BrvhktIUf2gXoU8bHMuyNA7lB7R51ym213
-sFcFKowIviT/i0Wscg+4RDubX+4haRsMxZWgN05K5FD3bzqS9VSVCPM4TpWs2C43ihFdgaSByeKHu3Xf/2TG8tgpB7PAtOs7jixWYw+Ayo5GjUTSybX/1KW5
-2RxYfB8nBNLJtHgt4DPq6BZWBFpjyZX/1KW5Ca0evOwG1EX/A9j5fQm5hOz6W2CtcCaWTXTFAeZO71VIgCTX69y9TiaXag3Os2ES1DcLKw0/xR5HfnCqkpQF
-0Z1kxKNfhZWLycml2keduHMQh3HubB/pbUUoCK5wxetZRZWPJF/bdyE21H2YjMOhP/pkthqKUCOEWVm68+1J5n7ahES5sOhaZPdOC5j4kc91FVIsrF8ofe+A
-2on/16Z4RiKQZcMU3NouO9N4YAvrWaiA6h4bfLqhTitbnnJ2iPSVRNJH+aZGE+YXzq7Ah/OncW2K59AKamlocOUYTSvaJPNcjDfMGrmG9pOV2MbgI9v3B3EC
-Z7RLJ51UpzMn0C1huA87Ngom9lkiaw3t5yvFZmDl1HpkuP+PiqlawgD69jAT5Nxr2i6cwiytcwHhK2KJvZI9C1m/4VUil8RvO/ydxmgsFdzdgGpMbUeyyRNO
-i1k5hMb6hVSMuTrOE/xuDhGExQ219l07sV2kG5fOEnkWHwgqUkbvC0P2KTytY4nHLqJDc3DMGlDbX2aXK/4UuJxizaIkZITS7a3HN5374PrVlYKIcP9xl1BU
-KqQ7aAml2k1o5uGcN8A+tPz1HF1YVnmE7cyx4FIiUA2ml1k0hX9HB7l4tMO+R9YrMWcf5Anub1BZXUp3Ce4jBM21l0kyhcF/vg6FGeHa345MYv4BVSciTJhj
-5AbuD2K0dfIXc4jKAbazaS53rv1lYqpIVr2fcgcPox4u/WVnRfJ25GGING2s2cqjKIVUtwGbRtrljLd9CQOHhewUTfiKxWk7Olr2dHyIKlLgejEbasmmdGF/
-dhuhVrU9xGi6Hksgm/+5Bw813T3mJyRNqIYGdYspVZFzQ6dhNLJ7H+fYWh8Q+cMbzLc/O0evM4srXGjpECaXaT2jApqM4LRavgPnH7ecDRQSErabX3zC4EcX
-fOVZZUpYs3UIfMsKVR+6hgFzHhvWWWl4EqZtrJpHnyeO0T2icPrqVRyyDRKmbayexv7wdolGfh1hwtsK4G5jDOIHz/lTULUM47PaBmNJm2ssmTq+ssXeHBjg
-ij3G5P+u5QVFIGQ21TNM5aGOHbqKssQ/HiM9kvcWjdCtF6gZNMzbXFhNP2gV2FNQi+OpOR+S+3RvOBVSOr+E5hjyPrQho7/QDNEG2qRNLpHl6WVl3m4p3POF
-vwEWUN0ByvCQTSttdM48H7tjQWVk73qoUvhiSDbVK0mzyohbuHXofmEaK/xXYJ+Vq7tBUN6lMAdrouC3p96IS8kMzbVK0myY4f+HKdRGsrG9SlDwEfQkXsGL
-Ibapmmcv/sA5TrqC36t4sRdjylU4JC9KwG2plM0zxuT2iFFzAPXyj9ZWRu+tx5UpFv0jn0gQrKyMF5MyaZsDbXG7/qIdp0tHG4jOQumLzBliaZttaLfZFUBS
-Ou7FaUn/+IXETfwUj2E0o6gJ2HB/l8N7jFnzWWBESErabWPvy9bUKqS4y78CME0rbXSTNFRf8H7r1wwxQbltish5nFVIRkhKaTNtc6L3LHAh8+B2yi/tHvXG
-4nusVwAKMb/0/MCmoWrvASDM0mbay5YRI+7CtC96OPtxudDEyTGmbbWVRgkvR8qaiA8+rLCft7cW8H8UI3E8nzmJVSQIT3+0srHfUbgKA21ZNM8WEy+W7wbj
-9OuBpm21MKGWN80kaA5PZfoSqkRPLa1h31wIEjiUhcnX/e5VSWVkQnPhtqoYXrjLFpn7M8tjB17xSqfWgoA21StJpM48eSG+5A/dsGUQn8sV7impA4dQjxPy
-rsBfHd8tUGBIJWkxtrnljE3eu/xTUO/nVsA9I4uVlZ5uQvy9IwYjbWUmaZ5XE9HAWVkXUKmoI3y4vDKZpnKNtccJHK2iA83ej+fvgI3KR9P6qpG/kBCUdxHF
-isLkq8aZttTCZlj/b0G8XoLX/3fHhZWCVcMsWmZtqmYXz0cpOiBHCqpKUZu76iICRxYVuSULpmF/421MsWmfyhbP4ew1FVKAjFlY437JXImUTm2r/4ZYtMy6
-1hf16RPJIRA8tU1BDc5/JzAkEzTM21lyx7sK9wojRX/OHXoOv05IDbUymaZyscL7qlMA8c/CiK3csceqzuOEU1EPpbz4QEahIShpm21MJmWN924f98WKyf51
-EEYBli0zNtUzC+6X9P9ysrU1CHyA3RJFFr1w67HpyULT+YMsWmZtquYXz97oKil44sI1bpL8hRSDeMkhiIBwOgxwZ5Fs6+5M+NdH+3Kjv0sreSqqRvGSQxEA
-4HQY4M8i2dfcmfGuj/blR36WVvJVVI3jJIYiAcDoMcGeRbOvuTPjXR/tyo79LK3kqqkVUnCfqAES8EzTM21lykY4Q+LKxby+9F3ZHR/uC2OGpS9cv6BZXAeb
-hckMGIymaZm2st8/B38i6A/n58pVLKwfURet4UBwSF6UaZttSZljhd2jW9BZWcrX0/hG4Sdt/SBCdH6UMJmWK80zba3URKaik8iB9PR2459CuyOAbi0/GWLT
-MmYXm2t0vUkNQhRPVldKpAN5HgHyZfdOtGuj/YxwZ5S8u3CjqMgQoyQJRdawvJlE530/+sVg21c8GWLTPf3yJVSVUoCMWVjjfslciZRObav/hli0zLrWF/Xp
-E8khT2dnUwAEAAAAAAAAAABDt3UdAgAAAAzIIuQBAE9nZ1MABEAAAAAAAAAAorfjKwIAAABgTJAeBf////+/IK2oPwLwetDyEoOnddpgLM7J5tdTLMgoKCgs
-2quQe7o7SkFBQfQK1d3nTvIG8WYJg+kQTYyKcCBTI2uld4Ck3ITAiUxzwCDzbvEz4RL4jH2GES+Ix2gjjoZkfroYD2Rxe50JehL0UdqOhDasSshteOirUpDV
-6cdCD6ZJksRwtMAehrVhPC2k8aZU2c9cac+Z9PmWWWX4+Pj4BEssvCb4TfCZNG9wSOUm6QGyfTX2kmypyN8xrVMPuq146O3o6OjorWtdevXrGK1qWvX08a6R
-q0xLLxJJJTaDmSCHcNKfdSi8+/01vmG83m83ns7OzsErzebyPYtBJ0iEFRa8Nk7BZXXvaD9HsioatlKUtt6FxDflKUpxFWLa06Gy9Fa73KyurjJRShhHP3rK
-Pc1/8e9M4svw7z9/y5hmd6tC/+c2BGWkiRIkSMOWLESxaepEN5HCA8fbnt2c+oiWh3nDTVDj5GpecOZ6Pej2HglzRu77Ha7NevXrw9mr17Ge0nSP3nJ+/u8Q
-hEvP/jNd8EFWSIRATu7oooou7uijwzeQQSuISlxl4fNRTj4fl3hrIGCibpjzMyqyFWQqyFWQBMyJVkKPwSJe+CRxuoEF/gEU2CHC4E9tYgQEIgLbW21ttbbW
-21ttbbW3VRNfeEUjw5p+43Jszx9/+J9Xq/cPHkNoGheXKleIvTLu7iOchCVRx4+8YZD/8eO7wQfAz3YR//ArgZPYDA4O/j0JZ8SBCyNGQJAoyBIGM3Nszg65
-/dg9KU0ZAssfyut/18FfOYHejZoiN64XH3AV8+A+MZAbifeO46k45f/YwcgIrj/v0lKe/O7777/urfwDuRL4vnLC2W8VNKmlTXI85zhb9Tzg5Pq3b4MHGJys
-A0vsJbIsiyLIsEXpf8Fvh9ve5rMuDmsFkgjCv6z0V/RCArnWZw2pL3cs2uKgHydecWhDe3OxQXkRfRz3haf8V7+0/u7FiQDyfSCDxnf/uIhzK8RYGDCXYRMY
-qVpiJEi6iqzlnq91PbMvN7rqyqfI2QlKUpAgQIcDeBvA3afsV8/MqBxcDH6z8DKVq+fDeHyLb9bk1SlLLSZV5sj6vR9c+ZoSzmUe7nFIY77Io1uY7TGlp67W
-1xSRjyffmuz+ZZnIo6iK81o5jPqjLad2pJVNlxcrFNTU1NxMGZmYZLw9FOO1MMyzMZOXW2i5f+SZOTWvXrxbvWtF9F/qpM8k7VWZ1srpVdmc/rNt5671q/4o
-aPLioDn63vKe+3TsR1QdT3cbbX29dJhFWxGfPji8uow/RvEdxN26QXd3d3dmltxmvn9xX41q7lJ+EyZMmTJk5d7e2lt4T80idGzp5p4ZOwcwt9MfSg2px6rr
-OjC7dunTLPnPm37py9tZjaU10a2lujlPd5ZYZbWZmZmYa7t76epZjI6IyFSpUiRI6tO81MJ+FSshXxUNo2qCYteb6DTfQ7eWHcYqrx8q3N+WmphpSJJJJM/j
-1au8t2/m25K9evXr169fcx23mLqG6yrVvctNSdG9PTPz32j10DtUeJJJCiPs2L3slpLcg3LLLJJJQaTfR9IalPOLMvdptttts9C1Q35jwWm306Lp06dOnTp0
-aWtuFpwSSSSHPcIguQA="/>
-            <source onerror='onError(event)'
-                    src="data:video/mp4;base64,
-AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAHuG1kYXQAAAGzABAHAAABthBgdgpU4Bg8SyD1tWXqqBr13UzOZBxmb/64MV3Y2OWRzRBZ
-vxztjdtC0aswA4S201VqgQ/Np60Xf8OUmDifBg+95svvk+lsTg4EMuv6x9WzQbpfFfpARTAuyg4uzeDkGWlUS9HIed50tZ6pNjlvoEfjd6hclYB4KApmDwRr
-AZTg4Zawfliu78GzrSRSn2346BT23GdS+aoN6cTJARID4MA79lWcA4kA03AYcp4mBVsNlk9hYqEJW20JJePwNxJqthUyX/HNYEHS8P79hhLN0z88EBKyOd+B
-1NqZkSmM3f98PYrSpxGVM3yYDZa0O1fh/5O2X+YZUK2WVYfe/n3HgYtxtM0pHQkA8H/zsj2RQX80S0+Kh2rBCgMv2gdVpR+r98t6k36bRyJE2B8AxqxLxhod
-7g6EhYQ8T3vi/jReXfANEtMOmQZcHg/+cG6IybfRqtMAigG43g6Z1uA+D/0/aXh2JCpWr94eCSlZrbKZU1oKZujuwvCGCnA1qcvxZJ/BJmgxb9VRA6Boch+D
-AJF7KUeYOvCXiYEVpOCmEDGmmByrBhy3GFUgf6x6DnR3VI5/6SMt3auZC58DgjfA2pLsBxfufZsv8t3N/+XLmysB62z/RALC37Kv/1Ost0zGiEOtD/qbAYri
-TG1CnwPBwC96PlF9crWpNK1WtFmtbJuWXJXfMuPghiUJbPmPD5vitVGYrbYTRq62XKh3U1AzrIfgiBDjegrA+o5V5Fe/LTAuD5igwiNL96HmL9LeoEIgs9Nj
-n4EdPlGBGHSZmK1SRppvFUSZfLTGMxr0zPB1A8VKvXZimtKlXrb5hqGI+2HzFBhEaX70PMX6W9QIRBZ6bHPwI6ftWqYrDIKxq9abBkGb1TjfVhAZUqRBb7BA
-b6Ofh58t3DNZ/zcU+3P4HOWbBi6Fa7DMRgY+tzvSqoCxnpQIDfQIfGz/fwAAlGlBJKl2GEIGPL970qiEtZ6UiC30CPxu+GqXYYQgY8v3vSqIS1npSILfQI/G
-738bbfztogcuLou9sK/swqEtInsxr+92bvi1hlgtmXmlgg+8WqKN1HVBCDrB4D8vBkoQ2wPlwMmSfSphCwdYPU/vVRBDZZZV+l0cbQ/LlWJgMZvIH9Z3/rfN
-Vx8eDofsfLv61+AaBTjmfS437cZn7PJml418ciBRz33Mz+LgLCKDD8GA4OgD+AHpWtCEJYHE/x+Oh+qbTKPqtxVlEgv8IrTbebfcAtv7xTG22hb9hwB4CB7B
-tA6DKgYegGRN9P4uEMSx4PB2OqWiAP0g9V4mLQ+q2stFo5SNyKZ/FCks3+GQLGOWko+rLFHLStNd9VFK83ywea03Vw4qr9QDjQSBiDAHA8BBL4Ac20EEDol+
-BSl46Vsj8A694m8lZaLPt7palrcm+z7WqYoZ6zVQ5a8ZVLlX1QQGkzfpn2h8IF9KH4deURcPtLbZJ0GKvr2yNfRP9wAAqGbBWAoQZkHApGBCoKoG6Cra+uCK
-OFAfYmQqB6WlogoxB1EHbfQtG4PA/woPDQFoPFf8oPnQDI2Bi8HgIHkfAxe0B7S5KkAMBVeV1vUwhNKwVYKfC7l/vh6wBYPt5aylUiDQMiKLRgmB4CCjA0pB
-4L/JUqeA8JAT8RdB4b/hpOXMaA0nbHIMv4cB8mUUGK1O8bAyNmhxhWVjdE4tN5htX7ydkERVqktTllbHHMtwDGFeqd5iyLp9qEoM0DNg8D/kg3QeCgFwVQKY
-DQPCf+Yflofh+DAqGFCgQCXvUHDolGiQHgIG8DSkHgv9tSp4DwkA3xF0Hhv+uk42LgUQKYtBxeWlqgGAoo4o6DBvSc8v37AKsERoFWIAGgUxXFQN0t4H4dgw
-2A0uHYF+AIGFet+EMERhgPxGB4X/fLZ4GERSDgVVAyBcFYjBUkVLZYHAhAGA8LAUhCB4mAbLgfNgCWDgQgDAeFgKQhA8TANlwPmwBKF0tsHAhAGA8LAUhCB4
-mAbLgfNgCWDgQgDAeFgKQhA8TANlwPmwBP1u1a7DMRgY+tzvSqoCxnpQIDfQIfGz2DgQgDAeFgKQhA8TANlwPmwBNsghAHDhsHgoCkQg60HhIB0uoiVACIz0
-GBGbBXaNn+8AALxqgSSpdhhCBjy/e9KohLWelIgt9Aj8bvgYjwR1baofW40BlgfWgXoMjwA5Svre7QeD/52eXbtW8ptKwtT8JLOjjuNB6H3VtBkIOA90RQeG
-/52eFHjWhb9Lb8JLOjjuNB6H3VtBkIOA90RQeG/52eFHjWha/CSzo47jQeh91bQZCDgPdEUHhv+dnhR41oW/S2/CSzo47jQeh91bQZCDgPdEUHhv+dnhR41o
-Wvwks6OO40HofdW0GQg4D3RFB4b/nZ4UeNaFv3X9jXt/veey7VGb/eZO1R703/6az2Xdq2SvVaL2m/41k/3U0Sr5zmW8UaabiHCB+ElnRx3Gg9D7q2gyEHAe
-6IoPDf87PCjxrQtfhJZ0cdxoPQ+6toMhBwHuiKDw3/Ozwo8a0LfrQtWuwzEYGPrc70qqAsZ6UCA30CHxs9+ElnRx3Gg9D7q2gyEHAe6IoPDf87PCjxrQtoGU
-ts5ntjXGcYzSroMN4B6at+7lB4P/nZ5NzYt5TNikBfsAAAMbbW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAAACgAAQAAAQAAAAAAAAAAAAAAAAEAAAAA
-AAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAkZ0cmFrAAAAXHRraGQAAAAPAAAAAAAAAAAAAAAB
-AAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAFAAAAA8AAAAAAAkZWR0cwAAABxlbHN0AAAAAAAA
-AAEAAAAoAAAAAAABAAAAAAG+bWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAAAGQAAAAFVxAAAAAAALWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABWaWRl
-b0hhbmRsZXIAAAABaW1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAASlzdGJsAAAAxXN0c2QA
-AAAAAAAAAQAAALVtcDR2AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAFAAPABIAAAASAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-GP//AAAAX2VzZHMAAAAAA4CAgE4AAQAEgICAQCARAAAAAAYBgAAGAYAFgICALgAAAbABAAABtYkTAAABAAAAASAAxI2IAM0ChAeUQwAAAbJMYXZjNTQuMS4x
-MDAGgICAAQIAAAAYc3R0cwAAAAAAAAABAAAAAQAAAAEAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAHsAAAAAEAAAAUc3RjbwAA
-AAAAAAABAAAALAAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAA
-AQAAAABMYXZmNTQuMC4xMDA="/>
-        </video>
-
-    </body>
-</html>
+testInfo.forEach(function(test) {
+    async_test(function(t) {
+        var media = document.createElement(test.element);
+        for (var i = 0; i < test.srcArray.length; i++) {
+            var source = document.createElement("source");
+            if (test.typeArray)
+                source.type = test.typeArray[i];
+            source.src = test.srcArray[i];
+            media.appendChild(source);
+        }
+        media.oncanplaythrough = t.step_func_done();
+    }, test.description);
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-playbackrate-expected.txt b/third_party/WebKit/LayoutTests/media/video-playbackrate-expected.txt
deleted file mode 100644
index 403068a..0000000
--- a/third_party/WebKit/LayoutTests/media/video-playbackrate-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-'playbackRate' should not change when play() is called.
-'playbackRate' and 'defaultPlaybackRate' should always return the last value set.
-*** setting src
-EVENT(canplaythrough)
-
-*** checking defaults
-EXPECTED (video.playbackRate == '1') OK
-EXPECTED (video.defaultPlaybackRate == '1') OK
-
-*** setting defaultPlaybackRate
-RUN(video.defaultPlaybackRate = 2)
-EXPECTED (video.playbackRate == '1') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-
-EVENT(ratechange)
-*** checking rates after event
-EXPECTED (video.playbackRate == '1') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-
-*** setting playbackRate
-RUN(video.playbackRate = 2)
-EXPECTED (video.playbackRate == '2') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-
-EVENT(ratechange)
-*** checking rates after event
-EXPECTED (video.playbackRate == '2') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-
-*** beginning playback
-RUN(video.playbackRate = 1)
-EXPECTED (video.playbackRate == '1') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-RUN(video.play())
-
-EVENT(ratechange)
-*** checking rates after event
-EXPECTED (video.playbackRate == '1') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-
-EVENT(ended)
-EXPECTED (video.playbackRate == '1') OK
-EXPECTED (video.defaultPlaybackRate == '2') OK
-
-Test extreme playback rates
-RUN(video.defaultPlaybackRate = Number.MIN_VALUE)
-EXPECTED (video.defaultPlaybackRate == '5e-324') OK
-
-RUN(video.defaultPlaybackRate = Number.MAX_VALUE)
-EXPECTED (video.defaultPlaybackRate == '1.7976931348623157e+308') OK
-
-RUN(video.playbackRate = Number.MIN_VALUE)
-EXPECTED (video.playbackRate == '5e-324') OK
-
-RUN(video.playbackRate = Number.MAX_VALUE)
-EXPECTED (video.playbackRate == '1.7976931348623157e+308') OK
-
-Test non-finite playback rates
-TEST(video.defaultPlaybackRate = -Infinity) THROWS("TypeError: Failed to set the 'defaultPlaybackRate' property on 'HTMLMediaElement': The provided double value is non-finite.") OK
-TEST(video.defaultPlaybackRate = Infinity) THROWS("TypeError: Failed to set the 'defaultPlaybackRate' property on 'HTMLMediaElement': The provided double value is non-finite.") OK
-TEST(video.defaultPlaybackRate = NaN) THROWS("TypeError: Failed to set the 'defaultPlaybackRate' property on 'HTMLMediaElement': The provided double value is non-finite.") OK
-
-TEST(video.playbackRate = -Infinity) THROWS("TypeError: Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided double value is non-finite.") OK
-TEST(video.playbackRate = Infinity) THROWS("TypeError: Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided double value is non-finite.") OK
-TEST(video.playbackRate = NaN) THROWS("TypeError: Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided double value is non-finite.") OK
-
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/media/video-playbackrate.html b/third_party/WebKit/LayoutTests/media/video-playbackrate.html
index abe071a..47cff03 100644
--- a/third_party/WebKit/LayoutTests/media/video-playbackrate.html
+++ b/third_party/WebKit/LayoutTests/media/video-playbackrate.html
@@ -1,121 +1,85 @@
 <!DOCTYPE html>
-<html>
-    <head>
-        <title>test playbackRate and defaultPlaybackRate</title>
-        <script src=media-file.js></script>
-        <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956
-             (Please avoid writing new tests using video-test.js) -->
-        <script src=video-test.js></script>
-        <script>
-            var rateChangeCount = 0;
+<title>Test playbackRate and defaultPlaybackRate.</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="media-file.js"></script>
+<video></video>
+<script>
+// "playbackRate" should not change when play() is called.
+// "playbackRate" and "defaultPlaybackRate" should always return the last value set.
+async_test(function(t) {
+    var video = document.querySelector("video");
 
-            function ratechange()
-            {
-                consoleWrite("*** checking rates after event");
-                switch (++rateChangeCount)
-                {
-                    case 1:
-                        testExpected("video.playbackRate", 1);
-                        testExpected("video.defaultPlaybackRate", 2);
+    video.oncanplaythrough = t.step_func(function() {
+        video.oncanplaythrough = null;
+        // checking defaults.
+        assert_equals(video.playbackRate, 1);
+        assert_equals(video.defaultPlaybackRate, 1);
 
-                        consoleWrite("<br>*** setting playbackRate");
-                        run("video.playbackRate = 2");
-                        testExpected("video.playbackRate", 2);
-                        testExpected("video.defaultPlaybackRate", 2);
-                        consoleWrite("");
-                        break;
-                    case 2:
-                        testExpected("video.playbackRate", 2);
-                        testExpected("video.defaultPlaybackRate", 2);
+        // setting defaultPlaybackRate.
+        video.defaultPlaybackRate = 2;
+        assert_equals(video.playbackRate, 1);
+        assert_equals(video.defaultPlaybackRate, 2);
+    });
 
-                        consoleWrite("<br>*** beginning playback");
-                        video.currentTime = video.duration - 0.2;
-                        run("video.playbackRate = 1");
-                        testExpected("video.playbackRate", 1);
-                        testExpected("video.defaultPlaybackRate", 2);
-                        run("video.play()");
-                        consoleWrite("");
-                        break;
-                    case 3:
-                        testExpected("video.playbackRate", 1);
-                        testExpected("video.defaultPlaybackRate", 2);
-                        consoleWrite("");
-                        break;
-                    default:
-                        break;
-                }
-            }
+    video.onended = t.step_func_done(function() {
+        assert_equals(video.playbackRate, 1);
+        assert_equals(video.defaultPlaybackRate, 2);
 
-            function canplaythrough()
-            {
-                consoleWrite("<br>*** checking defaults");
-                testExpected("video.playbackRate", 1);
-                testExpected("video.defaultPlaybackRate", 1);
+        // Test extreme playback rates.
+        video.defaultPlaybackRate = Number.MIN_VALUE;
+        assert_equals(video.defaultPlaybackRate, Number.MIN_VALUE);
 
-                consoleWrite("<br>*** setting defaultPlaybackRate");
-                run("video.defaultPlaybackRate = 2");
-                testExpected("video.playbackRate", 1);
-                testExpected("video.defaultPlaybackRate", 2);
-                consoleWrite("");
-            }
+        video.defaultPlaybackRate = Number.MAX_VALUE;
+        assert_equals(video.defaultPlaybackRate, Number.MAX_VALUE);
 
-            function ended()
-            {
-                testExpected("video.playbackRate", 1);
-                testExpected("video.defaultPlaybackRate", 2);
-                consoleWrite("");
+        video.playbackRate = Number.MIN_VALUE;
+        assert_equals(video.playbackRate, Number.MIN_VALUE);
 
-                consoleWrite("Test extreme playback rates");
-                run("video.defaultPlaybackRate = Number.MIN_VALUE");
-                testExpected("video.defaultPlaybackRate", Number.MIN_VALUE);
-                consoleWrite("");
+        video.playbackRate = Number.MAX_VALUE;
+        assert_equals(video.playbackRate, Number.MAX_VALUE);
 
-                run("video.defaultPlaybackRate = Number.MAX_VALUE");
-                testExpected("video.defaultPlaybackRate", Number.MAX_VALUE);
-                consoleWrite("");
+        // Test non-finite playback rates.
+        assert_throws(new TypeError, function() { video.defaultPlaybackRate = -Infinity; });
+        assert_throws(new TypeError, function() { video.defaultPlaybackRate = Infinity; });
+        assert_throws(new TypeError, function() { video.defaultPlaybackRate = NaN; });
 
-                run("video.playbackRate = Number.MIN_VALUE");
-                testExpected("video.playbackRate", Number.MIN_VALUE);
-                consoleWrite("");
+        assert_throws(new TypeError, function() { video.playbackRate = -Infinity; });
+        assert_throws(new TypeError, function() { video.playbackRate = Infinity; });
+        assert_throws(new TypeError, function() { video.playbackRate = NaN; });
+    });
 
-                run("video.playbackRate = Number.MAX_VALUE");
-                testExpected("video.playbackRate", Number.MAX_VALUE);
-                consoleWrite("");
+    var rateChangeCount = 0;
+    video.onratechange = t.step_func(function() {
+        // checking rate after event.
+        switch (++rateChangeCount) {
+        case 1:
+            assert_equals(video.playbackRate, 1);
+            assert_equals(video.defaultPlaybackRate, 2);
 
-                consoleWrite("Test non-finite playback rates");
-                testException("video.defaultPlaybackRate = -Infinity", '"TypeError: Failed to set the \'defaultPlaybackRate\' property on \'HTMLMediaElement\': The provided double value is non-finite."');
-                testException("video.defaultPlaybackRate = Infinity", '"TypeError: Failed to set the \'defaultPlaybackRate\' property on \'HTMLMediaElement\': The provided double value is non-finite."');
-                testException("video.defaultPlaybackRate = NaN", '"TypeError: Failed to set the \'defaultPlaybackRate\' property on \'HTMLMediaElement\': The provided double value is non-finite."');
-                consoleWrite("");
+            // setting playbackRate.
+            video.playbackRate = 2;
+            assert_equals(video.playbackRate, 2);
+            assert_equals(video.defaultPlaybackRate, 2);
+            break;
+        case 2:
+            assert_equals(video.playbackRate, 2);
+            assert_equals(video.defaultPlaybackRate, 2);
 
-                testException("video.playbackRate = -Infinity", '"TypeError: Failed to set the \'playbackRate\' property on \'HTMLMediaElement\': The provided double value is non-finite."');
-                testException("video.playbackRate = Infinity", '"TypeError: Failed to set the \'playbackRate\' property on \'HTMLMediaElement\': The provided double value is non-finite."');
-                testException("video.playbackRate = NaN", '"TypeError: Failed to set the \'playbackRate\' property on \'HTMLMediaElement\': The provided double value is non-finite."');
-                consoleWrite("");
+            // beginning playback.
+            video.currentTime = video.duration - 0.2;
+            video.playbackRate = 1;
+            assert_equals(video.playbackRate, 1);
+            assert_equals(video.defaultPlaybackRate, 2);
+            video.play();
+            break;
+        case 3:
+            assert_equals(video.playbackRate, 1);
+            assert_equals(video.defaultPlaybackRate, 2);
+            break;
+        }
+    });
 
-                endTest();
-            }
-
-            function start()
-            {
-                findMediaElement();
-                waitForEventOnce('canplaythrough', canplaythrough);
-                waitForEvent('ended', ended);
-                waitForEvent('ratechange', ratechange);
-
-                consoleWrite("*** setting src");
-                setSrcByTagName("video", findMediaFile("video", "content/test"));
-            }
-
-        </script>
-    </head>
-
-    <body onload="start()">
-
-        <video controls > </video>
-        <ol>
-            <li>'playbackRate' should not change when play() is called.</li>
-            <li>'playbackRate' and 'defaultPlaybackRate' should always return the last value set.</li>
-        </ol>
-    </body>
-</html>
+    video.src = findMediaFile("video", "content/test");
+});
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index 5f49f784..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/table-collapsed-border-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/table-collapsed-border-expected.txt
index ecb5b157..8e1845e5 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/table-collapsed-border-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/repaint/table-collapsed-border-expected.txt
@@ -112,6 +112,26 @@
           "object": "LayoutTable TABLE",
           "rect": [78, 286, 25, 82],
           "reason": "incremental"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 224, 14, 22],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 132, 14, 22],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [17, 225, 4, 19],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [17, 133, 4, 19],
+          "reason": "forced by layout"
         }
       ]
     }
@@ -198,6 +218,22 @@
       "reason": "forced by layout"
     },
     {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "forced by layout"
+    },
+    {
       "object": "InlineTextBox 'sit amet'",
       "reason": "forced by layout"
     },
@@ -210,6 +246,22 @@
       "reason": "forced by layout"
     },
     {
+      "object": "LayoutTableCell TD",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "forced by layout"
+    },
+    {
       "object": "LayoutTable TABLE",
       "reason": "incremental"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/sources-fallback-codecs-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/media/sources-fallback-codecs-expected.txt
deleted file mode 100644
index 0cf988d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/media/sources-fallback-codecs-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Test that fallback among codecs is done correctly regardless of their order.    
-END OF TEST
-
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index 29a87826..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.txt
deleted file mode 100644
index 229e5d25..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 604
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 785x600
-  LayoutBlockFlow {html} at (0,0) size 785x600
-    LayoutInline {base} at (0,0) size 0x0
-    LayoutText {#text} at (0,0) size 0x0
-    LayoutText {#text} at (0,0) size 0x0
-    LayoutSVGRoot {svg} at (0,0) size 100x100
-      LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGResourceLinearGradient {linearGradient} [id="orange_red"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
-          LayoutSVGGradientStop {stop} [offset=0.00] [color=#FF0000]
-          LayoutSVGGradientStop {stop} [offset=1.00] [color=#FF0000]
-      LayoutSVGRect {rect} at (0,0) size 100x100 [x=0.00] [y=0.00] [width=100.00] [height=100.00]
-    LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-appearance-expected.png
index 2525a13..d93b8cd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
index b26cff9d..17bb7255 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
index 6a3784c..ea55a9f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
index 523d414..9f89bff 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.png
index acaf578..c3871ea 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.txt
index f220b99..b8e3fb4 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/basic-selects-expected.txt
@@ -1,9 +1,9 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x446
-  LayoutBlockFlow {HTML} at (0,0) size 800x446
-    LayoutBlockFlow {BODY} at (8,8) size 784x430
-      LayoutBlockFlow {DIV} at (0,0) size 784x430 [border: (1px solid #FF0000)]
+layer at (0,0) size 800x456
+  LayoutBlockFlow {HTML} at (0,0) size 800x456
+    LayoutBlockFlow {BODY} at (8,8) size 784x440
+      LayoutBlockFlow {DIV} at (0,0) size 784x440 [border: (1px solid #FF0000)]
         LayoutText {#text} at (1,0) size 169x18
           text run at (1,0) width 169: "Whitespace in option text:"
         LayoutMenuList {SELECT} at (169.39,1) size 54x18 [bgcolor=#F8F8F8]
@@ -100,75 +100,75 @@
           text run at (217,187) width 9: "b"
         LayoutBR {BR} at (225,187) size 1x18
         LayoutBR {BR} at (1,208) size 0x18
-        LayoutText {#text} at (1,224) size 491x18
-          text run at (1,224) width 491: "Height larger than font-size, button should grow, text baseline should center:"
-        LayoutMenuList {SELECT} at (491.11,225) size 48x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 48x18
-            LayoutText (anonymous) at (8,2) size 17x13
-              text run at (8,2) width 17: "foo"
-        LayoutText {#text} at (539,224) size 8x18
-          text run at (539,224) width 8: "a"
-        LayoutMenuList {SELECT} at (546.20,225) size 48x18 [color=#808080] [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 48x18
-            LayoutText (anonymous) at (8,2) size 4x13
-              text run at (8,2) width 4: " "
-        LayoutText {#text} at (594,224) size 9x18
-          text run at (594,224) width 9: "b"
-        LayoutBR {BR} at (602,224) size 1x18
-        LayoutBR {BR} at (1,242) size 0x18
-        LayoutText {#text} at (1,258) size 498x18
-          text run at (1,258) width 498: "Height smaller than font-size, whole select shrinks but baseline is unchanged:"
-        LayoutMenuList {SELECT} at (498.20,259) size 48x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 48x18
-            LayoutText (anonymous) at (8,2) size 17x13
-              text run at (8,2) width 17: "foo"
-        LayoutText {#text} at (546,258) size 8x18
-          text run at (546,258) width 8: "a"
-        LayoutMenuList {SELECT} at (553.30,259) size 48x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 48x18
-            LayoutText (anonymous) at (8,2) size 17x13
-              text run at (8,2) width 17: "bar"
-        LayoutText {#text} at (601,258) size 9x18
-          text run at (601,258) width 9: "b"
-        LayoutBR {BR} at (609,258) size 1x18
-        LayoutBR {BR} at (1,276) size 0x18
-        LayoutText {#text} at (1,292) size 173x18
-          text run at (1,292) width 173: "select control with size=0: "
-        LayoutBR {BR} at (173,292) size 1x18
-        LayoutMenuList {SELECT} at (1,309) size 187x18 [bgcolor=#F8F8F8]
+        LayoutText {#text} at (1,230) size 491x18
+          text run at (1,230) width 491: "Height larger than font-size, button should grow, text baseline should center:"
+        LayoutMenuList {SELECT} at (491.11,225) size 40x30 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,7) size 38x16
+            LayoutText (anonymous) at (8,1) size 17x13
+              text run at (8,1) width 17: "foo"
+        LayoutText {#text} at (531,230) size 8x18
+          text run at (531,230) width 8: "a"
+        LayoutMenuList {SELECT} at (538.20,225) size 40x30 [color=#7F7F7F] [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,7) size 38x16
+            LayoutText (anonymous) at (8,1) size 4x13
+              text run at (8,1) width 4: " "
+        LayoutText {#text} at (578,230) size 9x18
+          text run at (578,230) width 9: "b"
+        LayoutBR {BR} at (586,230) size 1x18
+        LayoutBR {BR} at (1,254) size 0x18
+        LayoutText {#text} at (1,270) size 498x18
+          text run at (1,270) width 498: "Height smaller than font-size, whole select shrinks but baseline is unchanged:"
+        LayoutMenuList {SELECT} at (498.20,271) size 40x15 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 38x16
+            LayoutText (anonymous) at (8,1) size 17x13
+              text run at (8,1) width 17: "foo"
+        LayoutText {#text} at (538,270) size 8x18
+          text run at (538,270) width 8: "a"
+        LayoutMenuList {SELECT} at (545.30,271) size 40x15 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 38x16
+            LayoutText (anonymous) at (8,1) size 17x13
+              text run at (8,1) width 17: "bar"
+        LayoutText {#text} at (585,270) size 9x18
+          text run at (585,270) width 9: "b"
+        LayoutBR {BR} at (593,270) size 1x18
+        LayoutBR {BR} at (1,286) size 0x18
+        LayoutText {#text} at (1,302) size 173x18
+          text run at (1,302) width 173: "select control with size=0: "
+        LayoutBR {BR} at (173,302) size 1x18
+        LayoutMenuList {SELECT} at (1,319) size 187x18 [bgcolor=#F8F8F8]
           LayoutBlockFlow (anonymous) at (0,0) size 187x18
             LayoutText (anonymous) at (8,2) size 67x13
               text run at (8,2) width 67: "Future Series"
-        LayoutText {#text} at (188,308) size 4x18
-          text run at (188,308) width 4: " "
+        LayoutText {#text} at (188,318) size 4x18
+          text run at (188,318) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,326) size 173x18
-          text run at (1,326) width 173: "select control with size=1: "
-        LayoutBR {BR} at (173,326) size 1x18
-        LayoutMenuList {SELECT} at (1,343) size 187x18 [bgcolor=#F8F8F8]
+        LayoutText {#text} at (1,336) size 173x18
+          text run at (1,336) width 173: "select control with size=1: "
+        LayoutBR {BR} at (173,336) size 1x18
+        LayoutMenuList {SELECT} at (1,353) size 187x18 [bgcolor=#F8F8F8]
           LayoutBlockFlow (anonymous) at (0,0) size 187x18
             LayoutText (anonymous) at (8,2) size 67x13
               text run at (8,2) width 67: "Future Series"
-        LayoutText {#text} at (188,342) size 4x18
-          text run at (188,342) width 4: " "
+        LayoutText {#text} at (188,352) size 4x18
+          text run at (188,352) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,360) size 170x18
-          text run at (1,360) width 170: "Non-styled select control: "
-        LayoutBR {BR} at (170,360) size 1x18
-        LayoutMenuList {SELECT} at (1,377) size 179x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutText {#text} at (1,370) size 170x18
+          text run at (1,370) width 170: "Non-styled select control: "
+        LayoutBR {BR} at (170,370) size 1x18
+        LayoutMenuList {SELECT} at (1,387) size 179x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
           LayoutBlockFlow (anonymous) at (1,1) size 177x16
             LayoutText (anonymous) at (8,1) size 67x13
               text run at (8,1) width 67: "Future Series"
-        LayoutText {#text} at (180,376) size 4x18
-          text run at (180,376) width 4: " "
+        LayoutText {#text} at (180,386) size 4x18
+          text run at (180,386) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,394) size 298x18
-          text run at (1,394) width 298: "Styled select control with large border-radius: "
-        LayoutBR {BR} at (298,394) size 1x18
-        LayoutMenuList {SELECT} at (1,411) size 179x18 [bgcolor=#33CCFF] [border: (1px solid #A6A6A6)]
+        LayoutText {#text} at (1,404) size 298x18
+          text run at (1,404) width 298: "Styled select control with large border-radius: "
+        LayoutBR {BR} at (298,404) size 1x18
+        LayoutMenuList {SELECT} at (1,421) size 179x18 [bgcolor=#33CCFF] [border: (1px solid #A6A6A6)]
           LayoutBlockFlow (anonymous) at (1,1) size 177x16
             LayoutText (anonymous) at (8,1) size 67x13
               text run at (8,1) width 67: "Future Series"
-        LayoutText {#text} at (180,410) size 4x18
-          text run at (180,410) width 4: " "
+        LayoutText {#text} at (180,420) size 4x18
+          text run at (180,420) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png
index 046d213..7461214a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt
index 4ae9499..8a8f726d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt
@@ -1,8 +1,8 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x476
-  LayoutBlockFlow {HTML} at (0,0) size 800x476
-    LayoutBlockFlow {BODY} at (8,8) size 784x460
+layer at (0,0) size 800x488
+  LayoutBlockFlow {HTML} at (0,0) size 800x488
+    LayoutBlockFlow {BODY} at (8,8) size 784x472
       LayoutMenuList {SELECT} at (4,4) size 48x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 48x18
           LayoutText (anonymous) at (8,2) size 17x13
@@ -69,87 +69,87 @@
       LayoutText {#text} at (48,125) size 4x18
         text run at (48,125) width 4: " "
       LayoutBR {BR} at (52,125) size 0x18
-      LayoutMenuList {SELECT} at (4,152) size 51x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 51x21
-          LayoutText (anonymous) at (8,2) size 20x16
-            text run at (8,2) width 20: "foo"
-      LayoutText {#text} at (59,153) size 4x18
-        text run at (59,153) width 4: " "
-      LayoutMenuList {SELECT} at (67,152) size 51x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 51x21
-          LayoutText (anonymous) at (8,2) size 20x16
-            text run at (8,2) width 20: "foo"
-      LayoutText {#text} at (122,153) size 4x18
-        text run at (122,153) width 4: " "
-      LayoutMenuList {SELECT} at (130,152) size 51x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 51x21
-          LayoutText (anonymous) at (8,2) size 20x16
-            text run at (8,2) width 20: "foo"
-      LayoutText {#text} at (185,153) size 4x18
-        text run at (185,153) width 4: " "
-      LayoutBR {BR} at (189,153) size 0x18
-      LayoutMenuList {SELECT} at (6,192) size 59x25 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutMenuList {SELECT} at (4,160) size 50x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 48x21
+          LayoutText (anonymous) at (8,1) size 24x18
+            text run at (8,1) width 24: "foo"
+      LayoutText {#text} at (58,163) size 4x18
+        text run at (58,163) width 4: " "
+      LayoutMenuList {SELECT} at (66,156) size 58x28 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 56x26
+          LayoutText (anonymous) at (8,1) size 30x23
+            text run at (8,1) width 30: "foo"
+      LayoutText {#text} at (128,163) size 4x18
+        text run at (128,163) width 4: " "
+      LayoutMenuList {SELECT} at (136,152) size 65x33 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 63x31
+          LayoutText (anonymous) at (8,1) size 36x28
+            text run at (8,1) width 36: "foo"
+      LayoutText {#text} at (205,163) size 4x18
+        text run at (205,163) width 4: " "
+      LayoutBR {BR} at (209,163) size 0x18
+      LayoutMenuList {SELECT} at (6,204) size 59x25 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 57x23
           LayoutText (anonymous) at (12,1) size 25x19
             text run at (12,1) width 25: "foo"
-      LayoutText {#text} at (71,196) size 4x18
-        text run at (71,196) width 4: " "
-      LayoutMenuList {SELECT} at (83,185) size 79x36 [bgcolor=#F8F8F8] [border: (2px solid #A6A6A6)]
+      LayoutText {#text} at (71,208) size 4x18
+        text run at (71,208) width 4: " "
+      LayoutMenuList {SELECT} at (83,197) size 79x36 [bgcolor=#F8F8F8] [border: (2px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (2,2) size 75x32
           LayoutText (anonymous) at (16,2) size 33x26
             text run at (16,2) width 33: "foo"
-      LayoutText {#text} at (170,196) size 4x18
-        text run at (170,196) width 4: " "
-      LayoutBR {BR} at (174,196) size 0x18
-      LayoutText {#text} at (208,244) size 4x18
-        text run at (208,244) width 4: " "
-      LayoutBR {BR} at (212,244) size 0x18
-      LayoutText {#text} at (208,277) size 4x18
-        text run at (208,277) width 4: " "
-      LayoutBR {BR} at (212,277) size 0x18
-      LayoutText {#text} at (208,310) size 4x18
-        text run at (208,310) width 4: " "
-      LayoutBR {BR} at (212,310) size 0x18
-      LayoutText {#text} at (208,343) size 4x18
-        text run at (208,343) width 4: " "
-      LayoutBR {BR} at (212,343) size 0x18
-      LayoutText {#text} at (208,376) size 4x18
-        text run at (208,376) width 4: " "
-      LayoutBR {BR} at (212,376) size 0x18
-      LayoutMenuList {SELECT} at (4,398) size 60x18 [bgcolor=#F8F8F8]
+      LayoutText {#text} at (170,208) size 4x18
+        text run at (170,208) width 4: " "
+      LayoutBR {BR} at (174,208) size 0x18
+      LayoutText {#text} at (208,256) size 4x18
+        text run at (208,256) width 4: " "
+      LayoutBR {BR} at (212,256) size 0x18
+      LayoutText {#text} at (208,289) size 4x18
+        text run at (208,289) width 4: " "
+      LayoutBR {BR} at (212,289) size 0x18
+      LayoutText {#text} at (208,322) size 4x18
+        text run at (208,322) width 4: " "
+      LayoutBR {BR} at (212,322) size 0x18
+      LayoutText {#text} at (208,355) size 4x18
+        text run at (208,355) width 4: " "
+      LayoutBR {BR} at (212,355) size 0x18
+      LayoutText {#text} at (208,388) size 4x18
+        text run at (208,388) width 4: " "
+      LayoutBR {BR} at (212,388) size 0x18
+      LayoutMenuList {SELECT} at (4,410) size 60x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 60x18
           LayoutText (anonymous) at (8,2) size 33x13
             text run at (8,2) width 33: "Month"
-      LayoutText {#text} at (68,397) size 4x18
-        text run at (68,397) width 4: " "
-      LayoutBR {BR} at (72,397) size 0x18
-      LayoutMenuList {SELECT} at (4,431) size 48x18 [bgcolor=#F8F8F8]
+      LayoutText {#text} at (68,409) size 4x18
+        text run at (68,409) width 4: " "
+      LayoutBR {BR} at (72,409) size 0x18
+      LayoutMenuList {SELECT} at (4,443) size 48x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 48x18
           LayoutText (anonymous) at (8,2) size 17x13
             text run at (8,2) width 17: "foo"
-      LayoutText {#text} at (56,430) size 4x18
-        text run at (56,430) width 4: " "
-      LayoutMenuList {SELECT} at (64,429) size 44x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
+      LayoutText {#text} at (56,442) size 4x18
+        text run at (56,442) width 4: " "
+      LayoutMenuList {SELECT} at (64,441) size 44x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (3,3) size 38x16
           LayoutText (anonymous) at (8,1) size 17x13
             text run at (8,1) width 17: "foo"
-      LayoutText {#text} at (112,430) size 4x18
-        text run at (112,430) width 4: " "
-      LayoutMenuList {SELECT} at (120,424) size 54x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
+      LayoutText {#text} at (112,442) size 4x18
+        text run at (112,442) width 4: " "
+      LayoutMenuList {SELECT} at (120,436) size 54x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (8,8) size 38x16
           LayoutText (anonymous) at (8,1) size 17x13
             text run at (8,1) width 17: "foo"
-      LayoutText {#text} at (178,430) size 4x18
-        text run at (178,430) width 4: " "
-      LayoutMenuList {SELECT} at (186,431) size 40x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutText {#text} at (178,442) size 4x18
+        text run at (178,442) width 4: " "
+      LayoutMenuList {SELECT} at (186,443) size 40x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 38x16
           LayoutText (anonymous) at (8,1) size 17x13
             text run at (8,1) width 17: "foo"
-      LayoutText {#text} at (230,430) size 4x18
-        text run at (230,430) width 4: " "
-      LayoutBR {BR} at (234,430) size 0x18
-layer at (12,241) size 200x25 clip at (13,242) size 187x23 scrollHeight 43
-  LayoutListBox {SELECT} at (4,233) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+      LayoutText {#text} at (230,442) size 4x18
+        text run at (230,442) width 4: " "
+      LayoutBR {BR} at (234,442) size 0x18
+layer at (12,253) size 200x25 clip at (13,254) size 187x23 scrollHeight 43
+  LayoutListBox {SELECT} at (4,245) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 1"
@@ -159,8 +159,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 3"
-layer at (12,274) size 200x25 clip at (13,275) size 187x23 scrollY 5.00 scrollHeight 43
-  LayoutListBox {SELECT} at (4,266) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,286) size 200x25 clip at (13,287) size 187x23 scrollY 5.00 scrollHeight 43
+  LayoutListBox {SELECT} at (4,278) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 1"
@@ -170,8 +170,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 3"
-layer at (12,307) size 200x25 clip at (13,308) size 187x23 scrollY 5.00 scrollHeight 43
-  LayoutListBox {SELECT} at (4,299) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,319) size 200x25 clip at (13,320) size 187x23 scrollY 5.00 scrollHeight 43
+  LayoutListBox {SELECT} at (4,311) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 1"
@@ -181,8 +181,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 3"
-layer at (12,340) size 200x25 clip at (13,341) size 187x23 scrollHeight 312
-  LayoutListBox {SELECT} at (4,332) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,352) size 200x25 clip at (13,353) size 187x23 scrollHeight 312
+  LayoutListBox {SELECT} at (4,344) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 41x13
         text run at (2,0) width 41: "Item 0.1"
@@ -299,8 +299,8 @@
     LayoutBlockFlow {OPTION} at (1,298.94) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 41x13
         text run at (2,0) width 41: "Item 0.2"
-layer at (12,373) size 200x25 clip at (13,374) size 187x23 scrollHeight 17507
-  LayoutListBox {SELECT} at (4,365) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,385) size 200x25 clip at (13,386) size 187x23 scrollHeight 17507
+  LayoutListBox {SELECT} at (4,377) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 32x13
         text run at (2,0) width 32: "Item 1"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.png
index ca4a79f6..69cb1bf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.txt
index e935468..b2e900e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-no-overflow-expected.txt
@@ -3,8 +3,8 @@
 layer at (0,0) size 800x600
   LayoutBlockFlow {HTML} at (0,0) size 800x600
     LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutMenuList {SELECT} at (0,0) size 233x15 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 233x16
-          LayoutText (anonymous) at (10,2) size 201x11
-            text run at (10,2) width 201: "No overflow should be allowed on popup menus!"
+      LayoutMenuList {SELECT} at (0,0) size 237x16 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 235x14
+          LayoutText (anonymous) at (8,1) size 214x11
+            text run at (8,1) width 214: "No overflow should be allowed on popup menus!"
       LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
index eee9036a..dc8cf4bd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
index a5c77f9..2b2073d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
@@ -1,99 +1,99 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x514
-  LayoutBlockFlow {HTML} at (0,0) size 800x514
-    LayoutBlockFlow {BODY} at (8,16) size 784x490
+layer at (0,0) size 800x530
+  LayoutBlockFlow {HTML} at (0,0) size 800x530
+    LayoutBlockFlow {BODY} at (8,16) size 784x506
       LayoutBlockFlow {P} at (0,0) size 784x18
         LayoutText {#text} at (0,0) size 709x18
           text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
           text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 153x16
-              text run at (8,2) width 30: "First "
-              text run at (37,2) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (84,2) width 16: "03"
-              text run at (99,2) width 36 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (134,2) width 27: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
+      LayoutBlockFlow {DIV} at (0,34) size 784x236
+        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 188x18
+              text run at (8,1) width 37: "First "
+              text run at (44,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+              text run at (102,1) width 19: "03"
+              text run at (120,1) width 44 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (163,1) width 33: " fifth"
+        LayoutBlockFlow {DIV} at (0,23) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 32: "First "
             text run at (41,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
             text run at (89,10) width 17: "03"
             text run at (105,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (141,10) width 32: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 153x16
-              text run at (8,2) width 23: "fifth"
-              text run at (30,2) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (81,2) width 15: "03"
-              text run at (95,2) width 40 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (134,2) width 27: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
+        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 188x18
+              text run at (8,1) width 28: "fifth"
+              text run at (35,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+              text run at (98,1) width 19: "03"
+              text run at (116,1) width 48 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (163,1) width 33: "First"
+        LayoutBlockFlow {DIV} at (0,82) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 27: "fifth"
             text run at (36,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
             text run at (87,10) width 17: "03"
             text run at (103,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (144,10) width 29: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 153x16
-              text run at (8,2) width 153 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
+        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 188x18
+              text run at (8,1) width 188 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,141) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 153x16
-              text run at (8,2) width 153 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
+        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 188x18
+              text run at (8,1) width 188 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,200) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,262) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (324,2) size 153x16
-              text run at (324,2) width 30: "First "
-              text run at (354,2) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (401,2) width 15: "03"
-              text run at (415,2) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (451,2) width 26: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
+      LayoutBlockFlow {DIV} at (0,270) size 784x236
+        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (294,1) size 188x18
+              text run at (294,1) width 37: "First "
+              text run at (330,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+              text run at (388,1) width 19: "03"
+              text run at (406,1) width 45 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (450,1) width 32: " fifth"
+        LayoutBlockFlow {DIV} at (0,23) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 33: "First "
             text run at (329,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
             text run at (376,10) width 18: "03"
             text run at (393,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (429,10) width 31: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (324,2) size 153x16
-              text run at (324,2) width 23: "fifth"
-              text run at (346,2) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (397,2) width 16: "03"
-              text run at (412,2) width 40 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (451,2) width 26: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
+        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (294,1) size 188x18
+              text run at (294,1) width 28: "fifth"
+              text run at (321,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+              text run at (384,1) width 19: "03"
+              text run at (402,1) width 49 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (450,1) width 32: "First"
+        LayoutBlockFlow {DIV} at (0,82) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 28: "fifth"
             text run at (324,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
             text run at (375,10) width 17: "03"
             text run at (391,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (432,10) width 28: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (324,2) size 153x16
-              text run at (324,2) width 153 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
+        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (294,1) size 188x18
+              text run at (294,1) width 188 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,141) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (324,2) size 153x16
-              text run at (324,2) width 153 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
+        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (294,1) size 188x18
+              text run at (294,1) width 188 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,200) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-appearance-expected.png
index 26b9a3f..47b9a2a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
index e323c0b..ec05e2a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
index 5c07d61f..3b048602 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
index c9a769ca..e8c2cb238 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png
index 8d17b40a..9a62e8d7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.png
index c1368ff..05a1795 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.txt
index cc2d550..8a5d415 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/basic-selects-expected.txt
@@ -1,9 +1,9 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x446
-  LayoutBlockFlow {HTML} at (0,0) size 800x446
-    LayoutBlockFlow {BODY} at (8,8) size 784x430
-      LayoutBlockFlow {DIV} at (0,0) size 784x430 [border: (1px solid #FF0000)]
+layer at (0,0) size 800x456
+  LayoutBlockFlow {HTML} at (0,0) size 800x456
+    LayoutBlockFlow {BODY} at (8,8) size 784x440
+      LayoutBlockFlow {DIV} at (0,0) size 784x440 [border: (1px solid #FF0000)]
         LayoutText {#text} at (1,0) size 169x18
           text run at (1,0) width 169: "Whitespace in option text:"
         LayoutMenuList {SELECT} at (169.39,1) size 56x18 [bgcolor=#F8F8F8]
@@ -100,75 +100,75 @@
           text run at (219,187) width 9: "b"
         LayoutBR {BR} at (227,187) size 1x18
         LayoutBR {BR} at (1,208) size 0x18
-        LayoutText {#text} at (1,224) size 491x18
-          text run at (1,224) width 491: "Height larger than font-size, button should grow, text baseline should center:"
-        LayoutMenuList {SELECT} at (491.11,225) size 49x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 49x18
-            LayoutText (anonymous) at (8,2) size 18x13
-              text run at (8,2) width 18: "foo"
-        LayoutText {#text} at (540,224) size 8x18
-          text run at (540,224) width 8: "a"
-        LayoutMenuList {SELECT} at (547.20,225) size 49x18 [color=#808080] [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 49x18
-            LayoutText (anonymous) at (8,2) size 4x13
-              text run at (8,2) width 4: " "
-        LayoutText {#text} at (596,224) size 9x18
-          text run at (596,224) width 9: "b"
-        LayoutBR {BR} at (604,224) size 1x18
-        LayoutBR {BR} at (1,242) size 0x18
-        LayoutText {#text} at (1,258) size 498x18
-          text run at (1,258) width 498: "Height smaller than font-size, whole select shrinks but baseline is unchanged:"
-        LayoutMenuList {SELECT} at (498.20,259) size 49x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 49x18
-            LayoutText (anonymous) at (8,2) size 18x13
-              text run at (8,2) width 18: "foo"
-        LayoutText {#text} at (547,258) size 8x18
-          text run at (547,258) width 8: "a"
-        LayoutMenuList {SELECT} at (554.30,259) size 49x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 49x18
-            LayoutText (anonymous) at (8,2) size 18x13
-              text run at (8,2) width 18: "bar"
-        LayoutText {#text} at (603,258) size 9x18
-          text run at (603,258) width 9: "b"
-        LayoutBR {BR} at (611,258) size 1x18
-        LayoutBR {BR} at (1,276) size 0x18
-        LayoutText {#text} at (1,292) size 173x18
-          text run at (1,292) width 173: "select control with size=0: "
-        LayoutBR {BR} at (173,292) size 1x18
-        LayoutMenuList {SELECT} at (1,309) size 198x18 [bgcolor=#F8F8F8]
+        LayoutText {#text} at (1,230) size 491x18
+          text run at (1,230) width 491: "Height larger than font-size, button should grow, text baseline should center:"
+        LayoutMenuList {SELECT} at (491.11,225) size 41x30 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,7) size 39x16
+            LayoutText (anonymous) at (8,1) size 18x13
+              text run at (8,1) width 18: "foo"
+        LayoutText {#text} at (532,230) size 8x18
+          text run at (532,230) width 8: "a"
+        LayoutMenuList {SELECT} at (539.20,225) size 41x30 [color=#7F7F7F] [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,7) size 39x16
+            LayoutText (anonymous) at (8,1) size 4x13
+              text run at (8,1) width 4: " "
+        LayoutText {#text} at (580,230) size 9x18
+          text run at (580,230) width 9: "b"
+        LayoutBR {BR} at (588,230) size 1x18
+        LayoutBR {BR} at (1,254) size 0x18
+        LayoutText {#text} at (1,270) size 498x18
+          text run at (1,270) width 498: "Height smaller than font-size, whole select shrinks but baseline is unchanged:"
+        LayoutMenuList {SELECT} at (498.20,271) size 41x15 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 39x16
+            LayoutText (anonymous) at (8,1) size 18x13
+              text run at (8,1) width 18: "foo"
+        LayoutText {#text} at (539,270) size 8x18
+          text run at (539,270) width 8: "a"
+        LayoutMenuList {SELECT} at (546.30,271) size 41x15 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 39x16
+            LayoutText (anonymous) at (8,1) size 18x13
+              text run at (8,1) width 18: "bar"
+        LayoutText {#text} at (587,270) size 9x18
+          text run at (587,270) width 9: "b"
+        LayoutBR {BR} at (595,270) size 1x18
+        LayoutBR {BR} at (1,286) size 0x18
+        LayoutText {#text} at (1,302) size 173x18
+          text run at (1,302) width 173: "select control with size=0: "
+        LayoutBR {BR} at (173,302) size 1x18
+        LayoutMenuList {SELECT} at (1,319) size 198x18 [bgcolor=#F8F8F8]
           LayoutBlockFlow (anonymous) at (0,0) size 198x18
             LayoutText (anonymous) at (8,2) size 70x13
               text run at (8,2) width 70: "Future Series"
-        LayoutText {#text} at (199,308) size 4x18
-          text run at (199,308) width 4: " "
+        LayoutText {#text} at (199,318) size 4x18
+          text run at (199,318) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,326) size 173x18
-          text run at (1,326) width 173: "select control with size=1: "
-        LayoutBR {BR} at (173,326) size 1x18
-        LayoutMenuList {SELECT} at (1,343) size 198x18 [bgcolor=#F8F8F8]
+        LayoutText {#text} at (1,336) size 173x18
+          text run at (1,336) width 173: "select control with size=1: "
+        LayoutBR {BR} at (173,336) size 1x18
+        LayoutMenuList {SELECT} at (1,353) size 198x18 [bgcolor=#F8F8F8]
           LayoutBlockFlow (anonymous) at (0,0) size 198x18
             LayoutText (anonymous) at (8,2) size 70x13
               text run at (8,2) width 70: "Future Series"
-        LayoutText {#text} at (199,342) size 4x18
-          text run at (199,342) width 4: " "
+        LayoutText {#text} at (199,352) size 4x18
+          text run at (199,352) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,360) size 170x18
-          text run at (1,360) width 170: "Non-styled select control: "
-        LayoutBR {BR} at (170,360) size 1x18
-        LayoutMenuList {SELECT} at (1,377) size 190x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutText {#text} at (1,370) size 170x18
+          text run at (1,370) width 170: "Non-styled select control: "
+        LayoutBR {BR} at (170,370) size 1x18
+        LayoutMenuList {SELECT} at (1,387) size 190x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
           LayoutBlockFlow (anonymous) at (1,1) size 188x16
             LayoutText (anonymous) at (8,1) size 70x13
               text run at (8,1) width 70: "Future Series"
-        LayoutText {#text} at (191,376) size 4x18
-          text run at (191,376) width 4: " "
+        LayoutText {#text} at (191,386) size 4x18
+          text run at (191,386) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,394) size 298x18
-          text run at (1,394) width 298: "Styled select control with large border-radius: "
-        LayoutBR {BR} at (298,394) size 1x18
-        LayoutMenuList {SELECT} at (1,411) size 190x18 [bgcolor=#33CCFF] [border: (1px solid #A6A6A6)]
+        LayoutText {#text} at (1,404) size 298x18
+          text run at (1,404) width 298: "Styled select control with large border-radius: "
+        LayoutBR {BR} at (298,404) size 1x18
+        LayoutMenuList {SELECT} at (1,421) size 190x18 [bgcolor=#33CCFF] [border: (1px solid #A6A6A6)]
           LayoutBlockFlow (anonymous) at (1,1) size 188x16
             LayoutText (anonymous) at (8,1) size 70x13
               text run at (8,1) width 70: "Future Series"
-        LayoutText {#text} at (191,410) size 4x18
-          text run at (191,410) width 4: " "
+        LayoutText {#text} at (191,420) size 4x18
+          text run at (191,420) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png
index 40acbe93e..e099a09 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt
index 28abc8f7..2e1cd2c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt
@@ -1,8 +1,8 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x476
-  LayoutBlockFlow {HTML} at (0,0) size 800x476
-    LayoutBlockFlow {BODY} at (8,8) size 784x460
+layer at (0,0) size 800x488
+  LayoutBlockFlow {HTML} at (0,0) size 800x488
+    LayoutBlockFlow {BODY} at (8,8) size 784x472
       LayoutMenuList {SELECT} at (4,4) size 49x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 49x18
           LayoutText (anonymous) at (8,2) size 18x13
@@ -69,87 +69,87 @@
       LayoutText {#text} at (49,125) size 4x18
         text run at (49,125) width 4: " "
       LayoutBR {BR} at (53,125) size 0x18
-      LayoutMenuList {SELECT} at (4,152) size 52x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 52x21
-          LayoutText (anonymous) at (8,2) size 21x16
-            text run at (8,2) width 21: "foo"
-      LayoutText {#text} at (60,153) size 4x18
-        text run at (60,153) width 4: " "
-      LayoutMenuList {SELECT} at (68,152) size 52x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 52x21
-          LayoutText (anonymous) at (8,2) size 21x16
-            text run at (8,2) width 21: "foo"
-      LayoutText {#text} at (124,153) size 4x18
-        text run at (124,153) width 4: " "
-      LayoutMenuList {SELECT} at (132,152) size 52x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 52x21
-          LayoutText (anonymous) at (8,2) size 21x16
-            text run at (8,2) width 21: "foo"
-      LayoutText {#text} at (188,153) size 4x18
-        text run at (188,153) width 4: " "
-      LayoutBR {BR} at (192,153) size 0x18
-      LayoutMenuList {SELECT} at (6,192) size 61x25 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutMenuList {SELECT} at (4,160) size 52x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 50x21
+          LayoutText (anonymous) at (8,1) size 26x18
+            text run at (8,1) width 26: "foo"
+      LayoutText {#text} at (60,163) size 4x18
+        text run at (60,163) width 4: " "
+      LayoutMenuList {SELECT} at (68,156) size 60x28 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 58x26
+          LayoutText (anonymous) at (8,1) size 32x23
+            text run at (8,1) width 32: "foo"
+      LayoutText {#text} at (132,163) size 4x18
+        text run at (132,163) width 4: " "
+      LayoutMenuList {SELECT} at (140,152) size 68x33 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 66x31
+          LayoutText (anonymous) at (8,1) size 39x28
+            text run at (8,1) width 39: "foo"
+      LayoutText {#text} at (212,163) size 4x18
+        text run at (212,163) width 4: " "
+      LayoutBR {BR} at (216,163) size 0x18
+      LayoutMenuList {SELECT} at (6,204) size 61x25 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 59x23
           LayoutText (anonymous) at (12,1) size 27x19
             text run at (12,1) width 27: "foo"
-      LayoutText {#text} at (73,196) size 4x18
-        text run at (73,196) width 4: " "
-      LayoutMenuList {SELECT} at (85,185) size 82x36 [bgcolor=#F8F8F8] [border: (2px solid #A6A6A6)]
+      LayoutText {#text} at (73,208) size 4x18
+        text run at (73,208) width 4: " "
+      LayoutMenuList {SELECT} at (85,197) size 82x36 [bgcolor=#F8F8F8] [border: (2px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (2,2) size 78x32
           LayoutText (anonymous) at (16,2) size 36x26
             text run at (16,2) width 36: "foo"
-      LayoutText {#text} at (175,196) size 4x18
-        text run at (175,196) width 4: " "
-      LayoutBR {BR} at (179,196) size 0x18
-      LayoutText {#text} at (208,244) size 4x18
-        text run at (208,244) width 4: " "
-      LayoutBR {BR} at (212,244) size 0x18
-      LayoutText {#text} at (208,277) size 4x18
-        text run at (208,277) width 4: " "
-      LayoutBR {BR} at (212,277) size 0x18
-      LayoutText {#text} at (208,310) size 4x18
-        text run at (208,310) width 4: " "
-      LayoutBR {BR} at (212,310) size 0x18
-      LayoutText {#text} at (208,343) size 4x18
-        text run at (208,343) width 4: " "
-      LayoutBR {BR} at (212,343) size 0x18
-      LayoutText {#text} at (208,376) size 4x18
-        text run at (208,376) width 4: " "
-      LayoutBR {BR} at (212,376) size 0x18
-      LayoutMenuList {SELECT} at (4,398) size 60x18 [bgcolor=#F8F8F8]
+      LayoutText {#text} at (175,208) size 4x18
+        text run at (175,208) width 4: " "
+      LayoutBR {BR} at (179,208) size 0x18
+      LayoutText {#text} at (208,256) size 4x18
+        text run at (208,256) width 4: " "
+      LayoutBR {BR} at (212,256) size 0x18
+      LayoutText {#text} at (208,289) size 4x18
+        text run at (208,289) width 4: " "
+      LayoutBR {BR} at (212,289) size 0x18
+      LayoutText {#text} at (208,322) size 4x18
+        text run at (208,322) width 4: " "
+      LayoutBR {BR} at (212,322) size 0x18
+      LayoutText {#text} at (208,355) size 4x18
+        text run at (208,355) width 4: " "
+      LayoutBR {BR} at (212,355) size 0x18
+      LayoutText {#text} at (208,388) size 4x18
+        text run at (208,388) width 4: " "
+      LayoutBR {BR} at (212,388) size 0x18
+      LayoutMenuList {SELECT} at (4,410) size 60x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 60x18
           LayoutText (anonymous) at (8,2) size 34x13
             text run at (8,2) width 34: "Month"
-      LayoutText {#text} at (68,397) size 4x18
-        text run at (68,397) width 4: " "
-      LayoutBR {BR} at (72,397) size 0x18
-      LayoutMenuList {SELECT} at (4,431) size 49x18 [bgcolor=#F8F8F8]
+      LayoutText {#text} at (68,409) size 4x18
+        text run at (68,409) width 4: " "
+      LayoutBR {BR} at (72,409) size 0x18
+      LayoutMenuList {SELECT} at (4,443) size 49x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 49x18
           LayoutText (anonymous) at (8,2) size 18x13
             text run at (8,2) width 18: "foo"
-      LayoutText {#text} at (57,430) size 4x18
-        text run at (57,430) width 4: " "
-      LayoutMenuList {SELECT} at (65,429) size 45x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
+      LayoutText {#text} at (57,442) size 4x18
+        text run at (57,442) width 4: " "
+      LayoutMenuList {SELECT} at (65,441) size 45x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (3,3) size 39x16
           LayoutText (anonymous) at (8,1) size 18x13
             text run at (8,1) width 18: "foo"
-      LayoutText {#text} at (114,430) size 4x18
-        text run at (114,430) width 4: " "
-      LayoutMenuList {SELECT} at (122,424) size 55x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
+      LayoutText {#text} at (114,442) size 4x18
+        text run at (114,442) width 4: " "
+      LayoutMenuList {SELECT} at (122,436) size 55x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (8,8) size 39x16
           LayoutText (anonymous) at (8,1) size 18x13
             text run at (8,1) width 18: "foo"
-      LayoutText {#text} at (181,430) size 4x18
-        text run at (181,430) width 4: " "
-      LayoutMenuList {SELECT} at (189,431) size 41x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutText {#text} at (181,442) size 4x18
+        text run at (181,442) width 4: " "
+      LayoutMenuList {SELECT} at (189,443) size 41x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 39x16
           LayoutText (anonymous) at (8,1) size 18x13
             text run at (8,1) width 18: "foo"
-      LayoutText {#text} at (234,430) size 4x18
-        text run at (234,430) width 4: " "
-      LayoutBR {BR} at (238,430) size 0x18
-layer at (12,241) size 200x25 clip at (13,242) size 187x23 scrollHeight 43
-  LayoutListBox {SELECT} at (4,233) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+      LayoutText {#text} at (234,442) size 4x18
+        text run at (234,442) width 4: " "
+      LayoutBR {BR} at (238,442) size 0x18
+layer at (12,253) size 200x25 clip at (13,254) size 187x23 scrollHeight 43
+  LayoutListBox {SELECT} at (4,245) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 1"
@@ -159,8 +159,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 3"
-layer at (12,274) size 200x25 clip at (13,275) size 187x23 scrollY 5.00 scrollHeight 43
-  LayoutListBox {SELECT} at (4,266) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,286) size 200x25 clip at (13,287) size 187x23 scrollY 5.00 scrollHeight 43
+  LayoutListBox {SELECT} at (4,278) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 1"
@@ -170,8 +170,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 3"
-layer at (12,307) size 200x25 clip at (13,308) size 187x23 scrollY 5.00 scrollHeight 43
-  LayoutListBox {SELECT} at (4,299) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,319) size 200x25 clip at (13,320) size 187x23 scrollY 5.00 scrollHeight 43
+  LayoutListBox {SELECT} at (4,311) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 1"
@@ -181,8 +181,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 3"
-layer at (12,340) size 200x25 clip at (13,341) size 187x23 scrollHeight 312
-  LayoutListBox {SELECT} at (4,332) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,352) size 200x25 clip at (13,353) size 187x23 scrollHeight 312
+  LayoutListBox {SELECT} at (4,344) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 45x13
         text run at (2,0) width 45: "Item 0.1"
@@ -299,8 +299,8 @@
     LayoutBlockFlow {OPTION} at (1,298.94) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 45x13
         text run at (2,0) width 45: "Item 0.2"
-layer at (12,373) size 200x25 clip at (13,374) size 187x23 scrollHeight 17507
-  LayoutListBox {SELECT} at (4,365) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,385) size 200x25 clip at (13,386) size 187x23 scrollHeight 17507
+  LayoutListBox {SELECT} at (4,377) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 35x13
         text run at (2,0) width 35: "Item 1"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.png
index 726d2c53..169d4c8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.txt
index 38b5f94..0a92933 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-no-overflow-expected.txt
@@ -3,8 +3,8 @@
 layer at (0,0) size 800x600
   LayoutBlockFlow {HTML} at (0,0) size 800x600
     LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutMenuList {SELECT} at (0,0) size 247x15 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 247x16
-          LayoutText (anonymous) at (10,2) size 215x11
-            text run at (10,2) width 215: "No overflow should be allowed on popup menus!"
+      LayoutMenuList {SELECT} at (0,0) size 252x16 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 250x14
+          LayoutText (anonymous) at (8,1) size 229x11
+            text run at (8,1) width 229: "No overflow should be allowed on popup menus!"
       LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
index 6563f93..4e2f75f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
index 28a3fd5..d7f9069 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
@@ -1,99 +1,99 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x514
-  LayoutBlockFlow {HTML} at (0,0) size 800x514
-    LayoutBlockFlow {BODY} at (8,16) size 784x490
+layer at (0,0) size 800x530
+  LayoutBlockFlow {HTML} at (0,0) size 800x530
+    LayoutBlockFlow {BODY} at (8,16) size 784x506
       LayoutBlockFlow {P} at (0,0) size 784x18
         LayoutText {#text} at (0,0) size 709x18
           text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
           text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 163x16
-              text run at (8,2) width 32: "First "
-              text run at (39,2) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (87,2) width 17: "03"
-              text run at (103,2) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (139,2) width 32: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
+      LayoutBlockFlow {DIV} at (0,34) size 784x236
+        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 200x18
+              text run at (8,1) width 39: "First "
+              text run at (46,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+              text run at (105,1) width 21: "03"
+              text run at (125,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (170,1) width 38: " fifth"
+        LayoutBlockFlow {DIV} at (0,23) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 32: "First "
             text run at (41,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
             text run at (89,10) width 17: "03"
             text run at (105,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (141,10) width 32: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 163x16
-              text run at (8,2) width 27: "fifth"
-              text run at (34,2) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (85,2) width 17: "03"
-              text run at (101,2) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (142,2) width 29: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
+        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 200x18
+              text run at (8,1) width 33: "fifth"
+              text run at (40,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+              text run at (103,1) width 21: "03"
+              text run at (123,1) width 51 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (173,1) width 35: "First"
+        LayoutBlockFlow {DIV} at (0,82) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 27: "fifth"
             text run at (36,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
             text run at (87,10) width 17: "03"
             text run at (103,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (144,10) width 29: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 163x16
-              text run at (8,2) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
+        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 200x18
+              text run at (8,1) width 200 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,141) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 163x16
-              text run at (8,2) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
+        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 200x18
+              text run at (8,1) width 200 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,200) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,262) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (314,2) size 163x16
-              text run at (314,2) width 33: "First "
-              text run at (346,2) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (393,2) width 18: "03"
-              text run at (410,2) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (446,2) width 31: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
+      LayoutBlockFlow {DIV} at (0,270) size 784x236
+        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (282,1) size 200x18
+              text run at (282,1) width 40: "First "
+              text run at (321,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+              text run at (379,1) width 22: "03"
+              text run at (400,1) width 45 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (444,1) width 38: " fifth"
+        LayoutBlockFlow {DIV} at (0,23) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 33: "First "
             text run at (329,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
             text run at (376,10) width 18: "03"
             text run at (393,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (429,10) width 31: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (314,2) size 163x16
-              text run at (314,2) width 28: "fifth"
-              text run at (341,2) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (392,2) width 17: "03"
-              text run at (408,2) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (449,2) width 28: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
+        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (282,1) size 200x18
+              text run at (282,1) width 33: "fifth"
+              text run at (314,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+              text run at (378,1) width 21: "03"
+              text run at (398,1) width 51 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (448,1) width 34: "First"
+        LayoutBlockFlow {DIV} at (0,82) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 28: "fifth"
             text run at (324,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
             text run at (375,10) width 17: "03"
             text run at (391,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (432,10) width 28: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (314,2) size 163x16
-              text run at (314,2) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
+        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (282,1) size 200x18
+              text run at (282,1) width 200 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,141) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (314,2) size 163x16
-              text run at (314,2) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
+        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (282,1) size 200x18
+              text run at (282,1) width 200 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,200) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index 8cc3425a..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-appearance-expected.png
index bb5e037..b03e25bc7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
index c16a9434..ff75054 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-one-row-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
index 8e60952..9aa03f2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-two-row-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
index 7e13eff7..ee13a239 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/color-suggestion-picker-with-scrollbar-appearance-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
index 52c2d39..6786dd0 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
index f126a02..253e2498 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
@@ -13,9 +13,9 @@
         LayoutBlockFlow {INPUT} at (0,18) size 44x23 [bgcolor=#C0C0C0] [border: none (1px solid #A9A9A9) none (1px solid #A9A9A9)]
           LayoutFlexibleBox {DIV} at (3,1) size 38x21
             LayoutBlockFlow {DIV} at (2,4) size 34x13 [bgcolor=#000000] [border: (1px solid #777777)]
-        LayoutBlockFlow {INPUT} at (44,22) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#000000] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (44,18) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#000000] [border: (1px solid #000000)]
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {H3} at (0,100.44) size 784x22
         LayoutText {#text} at (0,0) size 159x22
@@ -39,19 +39,19 @@
             LayoutBlockFlow {DIV} at (2,4) size 34x13 [bgcolor=#00FF00] [border: (1px solid #777777)]
         LayoutText {#text} at (140,21) size 4x18
           text run at (140,21) width 4: " "
-        LayoutBlockFlow {INPUT} at (144,19) size 88x21 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x21
-            LayoutBlockFlow {DIV} at (8,4) size 56x13 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (144,18) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#00FF00] [border: (1px solid #000000)]
         LayoutText {#text} at (232,21) size 4x18
           text run at (232,21) width 4: " "
-        LayoutBlockFlow {INPUT} at (236,22) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (236,18) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#00FF00] [border: (1px solid #000000)]
         LayoutText {#text} at (324,21) size 4x18
           text run at (324,21) width 4: " "
-        LayoutBlockFlow {INPUT} at (328,25) size 88x15 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x15
-            LayoutBlockFlow {DIV} at (8,4) size 56x7 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (328,18) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#00FF00] [border: (1px solid #000000)]
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {H3} at (0,200.88) size 784x22
         LayoutText {#text} at (0,0) size 120x22
@@ -82,29 +82,29 @@
             LayoutBlockFlow {DIV} at (2,4) size 34x13 [bgcolor=#40E0D0] [border: (1px solid #777777)]
         LayoutText {#text} at (236,3) size 4x18
           text run at (236,3) width 4: " "
-        LayoutBlockFlow {INPUT} at (240,4) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (240,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#FF0000] [border: (1px solid #000000)]
         LayoutText {#text} at (328,3) size 4x18
           text run at (328,3) width 4: " "
-        LayoutBlockFlow {INPUT} at (332,4) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (332,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#00FF00] [border: (1px solid #000000)]
         LayoutText {#text} at (420,3) size 4x18
           text run at (420,3) width 4: " "
-        LayoutBlockFlow {INPUT} at (424,4) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#0000FF] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (424,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#0000FF] [border: (1px solid #000000)]
         LayoutText {#text} at (512,3) size 4x18
           text run at (512,3) width 4: " "
-        LayoutBlockFlow {INPUT} at (516,4) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#EC008C] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (516,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#EC008C] [border: (1px solid #000000)]
         LayoutText {#text} at (604,3) size 4x18
           text run at (604,3) width 4: " "
-        LayoutBlockFlow {INPUT} at (608,4) size 88x18 [bgcolor=#F8F8F8]
-          LayoutFlexibleBox {DIV} at (0,0) size 88x18
-            LayoutBlockFlow {DIV} at (8,4) size 56x10 [bgcolor=#40E0D0] [border: (1px solid #000000)]
+        LayoutBlockFlow {INPUT} at (608,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#40E0D0] [border: (1px solid #000000)]
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {H3} at (0,283.31) size 784x22
         LayoutText {#text} at (0,0) size 116x22
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.png
index f7f1956f..21f3368 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.txt
index 56293fa..77ec2dac 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/basic-selects-expected.txt
@@ -1,9 +1,9 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x446
-  LayoutBlockFlow {HTML} at (0,0) size 800x446
-    LayoutBlockFlow {BODY} at (8,8) size 784x430
-      LayoutBlockFlow {DIV} at (0,0) size 784x430 [border: (1px solid #FF0000)]
+layer at (0,0) size 800x456
+  LayoutBlockFlow {HTML} at (0,0) size 800x456
+    LayoutBlockFlow {BODY} at (8,8) size 784x440
+      LayoutBlockFlow {DIV} at (0,0) size 784x440 [border: (1px solid #FF0000)]
         LayoutText {#text} at (1,0) size 169x18
           text run at (1,0) width 169: "Whitespace in option text:"
         LayoutMenuList {SELECT} at (169.39,1) size 55x18 [bgcolor=#F8F8F8]
@@ -100,75 +100,75 @@
           text run at (217,187) width 9: "b"
         LayoutBR {BR} at (225,187) size 1x18
         LayoutBR {BR} at (1,208) size 0x18
-        LayoutText {#text} at (1,224) size 491x18
-          text run at (1,224) width 491: "Height larger than font-size, button should grow, text baseline should center:"
-        LayoutMenuList {SELECT} at (491.11,225) size 48x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 48x18
-            LayoutText (anonymous) at (8,2) size 17x13
-              text run at (8,2) width 17: "foo"
-        LayoutText {#text} at (539,224) size 8x18
-          text run at (539,224) width 8: "a"
-        LayoutMenuList {SELECT} at (546.20,225) size 48x18 [color=#808080] [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 48x18
-            LayoutText (anonymous) at (8,2) size 4x13
-              text run at (8,2) width 4: " "
-        LayoutText {#text} at (594,224) size 9x18
-          text run at (594,224) width 9: "b"
-        LayoutBR {BR} at (602,224) size 1x18
-        LayoutBR {BR} at (1,242) size 0x18
-        LayoutText {#text} at (1,258) size 498x18
-          text run at (1,258) width 498: "Height smaller than font-size, whole select shrinks but baseline is unchanged:"
-        LayoutMenuList {SELECT} at (498.20,259) size 49x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 49x18
-            LayoutText (anonymous) at (8,2) size 17x13
-              text run at (8,2) width 17: "foo"
-        LayoutText {#text} at (547,258) size 8x18
-          text run at (547,258) width 8: "a"
-        LayoutMenuList {SELECT} at (554.30,259) size 49x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 49x18
-            LayoutText (anonymous) at (8,2) size 18x13
-              text run at (8,2) width 18: "bar"
-        LayoutText {#text} at (603,258) size 9x18
-          text run at (603,258) width 9: "b"
-        LayoutBR {BR} at (611,258) size 1x18
-        LayoutBR {BR} at (1,276) size 0x18
-        LayoutText {#text} at (1,292) size 173x18
-          text run at (1,292) width 173: "select control with size=0: "
-        LayoutBR {BR} at (173,292) size 1x18
-        LayoutMenuList {SELECT} at (1,309) size 193x18 [bgcolor=#F8F8F8]
+        LayoutText {#text} at (1,230) size 491x18
+          text run at (1,230) width 491: "Height larger than font-size, button should grow, text baseline should center:"
+        LayoutMenuList {SELECT} at (491.11,225) size 40x30 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,7) size 38x16
+            LayoutText (anonymous) at (8,1) size 17x13
+              text run at (8,1) width 17: "foo"
+        LayoutText {#text} at (531,230) size 8x18
+          text run at (531,230) width 8: "a"
+        LayoutMenuList {SELECT} at (538.20,225) size 40x30 [color=#7F7F7F] [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,7) size 38x16
+            LayoutText (anonymous) at (8,1) size 4x13
+              text run at (8,1) width 4: " "
+        LayoutText {#text} at (578,230) size 9x18
+          text run at (578,230) width 9: "b"
+        LayoutBR {BR} at (586,230) size 1x18
+        LayoutBR {BR} at (1,254) size 0x18
+        LayoutText {#text} at (1,270) size 498x18
+          text run at (1,270) width 498: "Height smaller than font-size, whole select shrinks but baseline is unchanged:"
+        LayoutMenuList {SELECT} at (498.20,271) size 41x15 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 39x16
+            LayoutText (anonymous) at (8,1) size 17x13
+              text run at (8,1) width 17: "foo"
+        LayoutText {#text} at (539,270) size 8x18
+          text run at (539,270) width 8: "a"
+        LayoutMenuList {SELECT} at (546.30,271) size 41x15 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 39x16
+            LayoutText (anonymous) at (8,1) size 18x13
+              text run at (8,1) width 18: "bar"
+        LayoutText {#text} at (587,270) size 9x18
+          text run at (587,270) width 9: "b"
+        LayoutBR {BR} at (595,270) size 1x18
+        LayoutBR {BR} at (1,286) size 0x18
+        LayoutText {#text} at (1,302) size 173x18
+          text run at (1,302) width 173: "select control with size=0: "
+        LayoutBR {BR} at (173,302) size 1x18
+        LayoutMenuList {SELECT} at (1,319) size 193x18 [bgcolor=#F8F8F8]
           LayoutBlockFlow (anonymous) at (0,0) size 193x18
             LayoutText (anonymous) at (8,2) size 69x13
               text run at (8,2) width 69: "Future Series"
-        LayoutText {#text} at (194,308) size 4x18
-          text run at (194,308) width 4: " "
+        LayoutText {#text} at (194,318) size 4x18
+          text run at (194,318) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,326) size 173x18
-          text run at (1,326) width 173: "select control with size=1: "
-        LayoutBR {BR} at (173,326) size 1x18
-        LayoutMenuList {SELECT} at (1,343) size 193x18 [bgcolor=#F8F8F8]
+        LayoutText {#text} at (1,336) size 173x18
+          text run at (1,336) width 173: "select control with size=1: "
+        LayoutBR {BR} at (173,336) size 1x18
+        LayoutMenuList {SELECT} at (1,353) size 193x18 [bgcolor=#F8F8F8]
           LayoutBlockFlow (anonymous) at (0,0) size 193x18
             LayoutText (anonymous) at (8,2) size 69x13
               text run at (8,2) width 69: "Future Series"
-        LayoutText {#text} at (194,342) size 4x18
-          text run at (194,342) width 4: " "
+        LayoutText {#text} at (194,352) size 4x18
+          text run at (194,352) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,360) size 170x18
-          text run at (1,360) width 170: "Non-styled select control: "
-        LayoutBR {BR} at (170,360) size 1x18
-        LayoutMenuList {SELECT} at (1,377) size 185x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutText {#text} at (1,370) size 170x18
+          text run at (1,370) width 170: "Non-styled select control: "
+        LayoutBR {BR} at (170,370) size 1x18
+        LayoutMenuList {SELECT} at (1,387) size 185x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
           LayoutBlockFlow (anonymous) at (1,1) size 183x16
             LayoutText (anonymous) at (8,1) size 69x13
               text run at (8,1) width 69: "Future Series"
-        LayoutText {#text} at (186,376) size 4x18
-          text run at (186,376) width 4: " "
+        LayoutText {#text} at (186,386) size 4x18
+          text run at (186,386) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
-        LayoutText {#text} at (1,394) size 298x18
-          text run at (1,394) width 298: "Styled select control with large border-radius: "
-        LayoutBR {BR} at (298,394) size 1x18
-        LayoutMenuList {SELECT} at (1,411) size 185x18 [bgcolor=#33CCFF] [border: (1px solid #A6A6A6)]
+        LayoutText {#text} at (1,404) size 298x18
+          text run at (1,404) width 298: "Styled select control with large border-radius: "
+        LayoutBR {BR} at (298,404) size 1x18
+        LayoutMenuList {SELECT} at (1,421) size 185x18 [bgcolor=#33CCFF] [border: (1px solid #A6A6A6)]
           LayoutBlockFlow (anonymous) at (1,1) size 183x16
             LayoutText (anonymous) at (8,1) size 69x13
               text run at (8,1) width 69: "Future Series"
-        LayoutText {#text} at (186,410) size 4x18
-          text run at (186,410) width 4: " "
+        LayoutText {#text} at (186,420) size 4x18
+          text run at (186,420) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png
index 8b76c421..7aadfa1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt
index 21c1bf3..bc2f9adf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt
@@ -1,8 +1,8 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x476
-  LayoutBlockFlow {HTML} at (0,0) size 800x476
-    LayoutBlockFlow {BODY} at (8,8) size 784x460
+layer at (0,0) size 800x488
+  LayoutBlockFlow {HTML} at (0,0) size 800x488
+    LayoutBlockFlow {BODY} at (8,8) size 784x472
       LayoutMenuList {SELECT} at (4,4) size 48x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 48x18
           LayoutText (anonymous) at (8,2) size 17x13
@@ -69,87 +69,87 @@
       LayoutText {#text} at (48,125) size 4x18
         text run at (48,125) width 4: " "
       LayoutBR {BR} at (52,125) size 0x18
-      LayoutMenuList {SELECT} at (4,152) size 51x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 51x21
-          LayoutText (anonymous) at (8,2) size 20x16
-            text run at (8,2) width 20: "foo"
-      LayoutText {#text} at (59,153) size 4x18
-        text run at (59,153) width 4: " "
-      LayoutMenuList {SELECT} at (67,152) size 51x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 51x21
-          LayoutText (anonymous) at (8,2) size 20x16
-            text run at (8,2) width 20: "foo"
-      LayoutText {#text} at (122,153) size 4x18
-        text run at (122,153) width 4: " "
-      LayoutMenuList {SELECT} at (130,152) size 51x21 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 51x21
-          LayoutText (anonymous) at (8,2) size 20x16
-            text run at (8,2) width 20: "foo"
-      LayoutText {#text} at (185,153) size 4x18
-        text run at (185,153) width 4: " "
-      LayoutBR {BR} at (189,153) size 0x18
-      LayoutMenuList {SELECT} at (6,192) size 60x25 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutMenuList {SELECT} at (4,160) size 51x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 49x21
+          LayoutText (anonymous) at (8,1) size 25x18
+            text run at (8,1) width 25: "foo"
+      LayoutText {#text} at (59,163) size 4x18
+        text run at (59,163) width 4: " "
+      LayoutMenuList {SELECT} at (67,156) size 56x28 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 54x26
+          LayoutText (anonymous) at (8,1) size 28x23
+            text run at (8,1) width 28: "foo"
+      LayoutText {#text} at (127,163) size 4x18
+        text run at (127,163) width 4: " "
+      LayoutMenuList {SELECT} at (135,152) size 63x33 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 61x31
+          LayoutText (anonymous) at (8,1) size 34x28
+            text run at (8,1) width 34: "foo"
+      LayoutText {#text} at (202,163) size 4x18
+        text run at (202,163) width 4: " "
+      LayoutBR {BR} at (206,163) size 0x18
+      LayoutMenuList {SELECT} at (6,204) size 60x25 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 58x23
           LayoutText (anonymous) at (12,1) size 26x19
             text run at (12,1) width 26: "foo"
-      LayoutText {#text} at (72,196) size 4x18
-        text run at (72,196) width 4: " "
-      LayoutMenuList {SELECT} at (84,185) size 77x36 [bgcolor=#F8F8F8] [border: (2px solid #A6A6A6)]
+      LayoutText {#text} at (72,208) size 4x18
+        text run at (72,208) width 4: " "
+      LayoutMenuList {SELECT} at (84,197) size 77x36 [bgcolor=#F8F8F8] [border: (2px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (2,2) size 73x32
           LayoutText (anonymous) at (16,2) size 31x26
             text run at (16,2) width 31: "foo"
-      LayoutText {#text} at (169,196) size 4x18
-        text run at (169,196) width 4: " "
-      LayoutBR {BR} at (173,196) size 0x18
-      LayoutText {#text} at (208,244) size 4x18
-        text run at (208,244) width 4: " "
-      LayoutBR {BR} at (212,244) size 0x18
-      LayoutText {#text} at (208,277) size 4x18
-        text run at (208,277) width 4: " "
-      LayoutBR {BR} at (212,277) size 0x18
-      LayoutText {#text} at (208,310) size 4x18
-        text run at (208,310) width 4: " "
-      LayoutBR {BR} at (212,310) size 0x18
-      LayoutText {#text} at (208,343) size 4x18
-        text run at (208,343) width 4: " "
-      LayoutBR {BR} at (212,343) size 0x18
-      LayoutText {#text} at (208,376) size 4x18
-        text run at (208,376) width 4: " "
-      LayoutBR {BR} at (212,376) size 0x18
-      LayoutMenuList {SELECT} at (4,398) size 60x18 [bgcolor=#F8F8F8]
+      LayoutText {#text} at (169,208) size 4x18
+        text run at (169,208) width 4: " "
+      LayoutBR {BR} at (173,208) size 0x18
+      LayoutText {#text} at (208,256) size 4x18
+        text run at (208,256) width 4: " "
+      LayoutBR {BR} at (212,256) size 0x18
+      LayoutText {#text} at (208,289) size 4x18
+        text run at (208,289) width 4: " "
+      LayoutBR {BR} at (212,289) size 0x18
+      LayoutText {#text} at (208,322) size 4x18
+        text run at (208,322) width 4: " "
+      LayoutBR {BR} at (212,322) size 0x18
+      LayoutText {#text} at (208,355) size 4x18
+        text run at (208,355) width 4: " "
+      LayoutBR {BR} at (212,355) size 0x18
+      LayoutText {#text} at (208,388) size 4x18
+        text run at (208,388) width 4: " "
+      LayoutBR {BR} at (212,388) size 0x18
+      LayoutMenuList {SELECT} at (4,410) size 60x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 60x18
           LayoutText (anonymous) at (8,2) size 34x13
             text run at (8,2) width 34: "Month"
-      LayoutText {#text} at (68,397) size 4x18
-        text run at (68,397) width 4: " "
-      LayoutBR {BR} at (72,397) size 0x18
-      LayoutMenuList {SELECT} at (4,431) size 48x18 [bgcolor=#F8F8F8]
+      LayoutText {#text} at (68,409) size 4x18
+        text run at (68,409) width 4: " "
+      LayoutBR {BR} at (72,409) size 0x18
+      LayoutMenuList {SELECT} at (4,443) size 48x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 48x18
           LayoutText (anonymous) at (8,2) size 17x13
             text run at (8,2) width 17: "foo"
-      LayoutText {#text} at (56,430) size 4x18
-        text run at (56,430) width 4: " "
-      LayoutMenuList {SELECT} at (64,429) size 44x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
+      LayoutText {#text} at (56,442) size 4x18
+        text run at (56,442) width 4: " "
+      LayoutMenuList {SELECT} at (64,441) size 44x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (3,3) size 38x16
           LayoutText (anonymous) at (8,1) size 17x13
             text run at (8,1) width 17: "foo"
-      LayoutText {#text} at (112,430) size 4x18
-        text run at (112,430) width 4: " "
-      LayoutMenuList {SELECT} at (120,424) size 54x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
+      LayoutText {#text} at (112,442) size 4x18
+        text run at (112,442) width 4: " "
+      LayoutMenuList {SELECT} at (120,436) size 54x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (8,8) size 38x16
           LayoutText (anonymous) at (8,1) size 17x13
             text run at (8,1) width 17: "foo"
-      LayoutText {#text} at (178,430) size 4x18
-        text run at (178,430) width 4: " "
-      LayoutMenuList {SELECT} at (186,431) size 40x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutText {#text} at (178,442) size 4x18
+        text run at (178,442) width 4: " "
+      LayoutMenuList {SELECT} at (186,443) size 40x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 38x16
           LayoutText (anonymous) at (8,1) size 17x13
             text run at (8,1) width 17: "foo"
-      LayoutText {#text} at (230,430) size 4x18
-        text run at (230,430) width 4: " "
-      LayoutBR {BR} at (234,430) size 0x18
-layer at (12,241) size 200x25 clip at (13,242) size 187x23 scrollHeight 43
-  LayoutListBox {SELECT} at (4,233) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+      LayoutText {#text} at (230,442) size 4x18
+        text run at (230,442) width 4: " "
+      LayoutBR {BR} at (234,442) size 0x18
+layer at (12,253) size 200x25 clip at (13,254) size 187x23 scrollHeight 43
+  LayoutListBox {SELECT} at (4,245) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 31x13
         text run at (2,0) width 31: "Item 1"
@@ -159,8 +159,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19
       LayoutText {#text} at (2,0) size 33x13
         text run at (2,0) width 33: "Item 3"
-layer at (12,274) size 200x25 clip at (13,275) size 187x23 scrollY 5.00 scrollHeight 43
-  LayoutListBox {SELECT} at (4,266) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,286) size 200x25 clip at (13,287) size 187x23 scrollY 5.00 scrollHeight 43
+  LayoutListBox {SELECT} at (4,278) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 31x13
         text run at (2,0) width 31: "Item 1"
@@ -170,8 +170,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19
       LayoutText {#text} at (2,0) size 33x13
         text run at (2,0) width 33: "Item 3"
-layer at (12,307) size 200x25 clip at (13,308) size 187x23 scrollY 5.00 scrollHeight 43
-  LayoutListBox {SELECT} at (4,299) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,319) size 200x25 clip at (13,320) size 187x23 scrollY 5.00 scrollHeight 43
+  LayoutListBox {SELECT} at (4,311) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
       LayoutText {#text} at (2,0) size 31x13
         text run at (2,0) width 31: "Item 1"
@@ -181,8 +181,8 @@
     LayoutBlockFlow {OPTION} at (1,29.38) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 33x13
         text run at (2,0) width 33: "Item 3"
-layer at (12,340) size 200x25 clip at (13,341) size 187x23 scrollHeight 312
-  LayoutListBox {SELECT} at (4,332) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,352) size 200x25 clip at (13,353) size 187x23 scrollHeight 312
+  LayoutListBox {SELECT} at (4,344) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 41x13
         text run at (2,0) width 41: "Item 0.1"
@@ -299,8 +299,8 @@
     LayoutBlockFlow {OPTION} at (1,298.94) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 42x13
         text run at (2,0) width 42: "Item 0.2"
-layer at (12,373) size 200x25 clip at (13,374) size 187x23 scrollHeight 17507
-  LayoutListBox {SELECT} at (4,365) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
+layer at (12,385) size 200x25 clip at (13,386) size 187x23 scrollHeight 17507
+  LayoutListBox {SELECT} at (4,377) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19 [bgcolor=#D4D4D4]
       LayoutText {#text} at (2,0) size 31x13
         text run at (2,0) width 31: "Item 1"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.png
index dddcd2c..32f742f9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.txt
index 422d76e3..e764273 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-no-overflow-expected.txt
@@ -3,8 +3,8 @@
 layer at (0,0) size 800x600
   LayoutBlockFlow {HTML} at (0,0) size 800x600
     LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutMenuList {SELECT} at (0,0) size 238x15 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 238x16
-          LayoutText (anonymous) at (10,2) size 206x11
-            text run at (10,2) width 206: "No overflow should be allowed on popup menus!"
+      LayoutMenuList {SELECT} at (0,0) size 243x16 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 241x14
+          LayoutText (anonymous) at (8,1) size 220x11
+            text run at (8,1) width 220: "No overflow should be allowed on popup menus!"
       LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-popup-item-style-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-popup-item-style-expected.txt
index 0484543..dfed10c2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-popup-item-style-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-popup-item-style-expected.txt
@@ -7,7 +7,7 @@
 PASS internals.selectPopupItemStyleIsRtl(popup, 2) is true
 PASS internals.isSelectPopupVisible(popup) is false
 PASS internals.isSelectPopupVisible(popup) is true
-FAIL internals.selectPopupItemStyleFontHeight(popup, 2) should be > 50. Was 16 (of type number).
+PASS internals.selectPopupItemStyleFontHeight(popup, 2) is > 50
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/repaint/table-collapsed-border-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/repaint/table-collapsed-border-expected.txt
index 7e95534..0ef5b8c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/repaint/table-collapsed-border-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/repaint/table-collapsed-border-expected.txt
@@ -112,6 +112,26 @@
           "object": "LayoutTable TABLE",
           "rect": [83, 268, 26, 76],
           "reason": "incremental"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 210, 14, 20],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 124, 14, 20],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [17, 211, 4, 18],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [17, 125, 4, 18],
+          "reason": "forced by layout"
         }
       ]
     }
@@ -198,6 +218,22 @@
       "reason": "forced by layout"
     },
     {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "forced by layout"
+    },
+    {
       "object": "InlineTextBox 'sit amet'",
       "reason": "forced by layout"
     },
@@ -210,6 +246,22 @@
       "reason": "forced by layout"
     },
     {
+      "object": "LayoutTableCell TD",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "forced by layout"
+    },
+    {
       "object": "LayoutTable TABLE",
       "reason": "incremental"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/table-percent-height-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/table-percent-height-expected.txt
index f34caaf..6646d864 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/table-percent-height-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/replaced/table-percent-height-expected.txt
@@ -80,7 +80,7 @@
 PASS getHeight('input-submit-75') is getHeight('input-submit-100')
 PASS getWidth('select-75') is getWidth('select-100')
 PASS getHeight('select-75') != '0px' is true
-PASS getHeight('select-75') is getHeight('select-100')
+FAIL getHeight('select-75') should be 16px. Was 15px.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
index 7be0350..ee5e71bb 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
index f4ce3c0..d015cef0 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
@@ -1,99 +1,99 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x514
-  LayoutBlockFlow {HTML} at (0,0) size 800x514
-    LayoutBlockFlow {BODY} at (8,16) size 784x490
+layer at (0,0) size 800x530
+  LayoutBlockFlow {HTML} at (0,0) size 800x530
+    LayoutBlockFlow {BODY} at (8,16) size 784x506
       LayoutBlockFlow {P} at (0,0) size 784x18
         LayoutText {#text} at (0,0) size 709x18
           text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
           text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 161x16
-              text run at (8,2) width 31: "First "
-              text run at (38,2) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (87,2) width 17: "03"
-              text run at (103,2) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (139,2) width 30: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
+      LayoutBlockFlow {DIV} at (0,34) size 784x236
+        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 198x18
+              text run at (8,1) width 38: "First "
+              text run at (45,1) width 61 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+              text run at (105,1) width 21: "03"
+              text run at (125,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (170,1) width 36: " fifth"
+        LayoutBlockFlow {DIV} at (0,23) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 32: "First "
             text run at (41,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
             text run at (89,10) width 17: "03"
             text run at (105,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (141,10) width 32: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 161x16
-              text run at (8,2) width 26: "fifth"
-              text run at (33,2) width 53 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (85,2) width 17: "03"
-              text run at (101,2) width 41 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (141,2) width 28: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
+        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 198x18
+              text run at (8,1) width 31: "fifth"
+              text run at (38,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+              text run at (103,1) width 21: "03"
+              text run at (123,1) width 50 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (172,1) width 34: "First"
+        LayoutBlockFlow {DIV} at (0,82) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 27: "fifth"
             text run at (36,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
             text run at (87,10) width 17: "03"
             text run at (103,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (144,10) width 29: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 161x16
-              text run at (8,2) width 161 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
+        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 198x18
+              text run at (8,1) width 198 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,141) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (8,2) size 161x16
-              text run at (8,2) width 161 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
+        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (8,1) size 198x18
+              text run at (8,1) width 198 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,200) size 470x36
           LayoutText {#text} at (10,10) size 163x16
             text run at (10,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,262) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (316,2) size 161x16
-              text run at (316,2) width 32: "First "
-              text run at (347,2) width 49 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (395,2) width 17: "03"
-              text run at (411,2) width 38 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (448,2) width 29: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
+      LayoutBlockFlow {DIV} at (0,270) size 784x236
+        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (284,1) size 198x18
+              text run at (284,1) width 39: "First "
+              text run at (322,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+              text run at (381,1) width 21: "03"
+              text run at (401,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (446,1) width 36: " fifth"
+        LayoutBlockFlow {DIV} at (0,23) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 33: "First "
             text run at (329,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
             text run at (376,10) width 18: "03"
             text run at (393,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (429,10) width 31: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (316,2) size 161x16
-              text run at (316,2) width 26: "fifth"
-              text run at (341,2) width 53 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (393,2) width 18: "03"
-              text run at (410,2) width 41 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (450,2) width 27: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
+        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (284,1) size 198x18
+              text run at (284,1) width 32: "fifth"
+              text run at (315,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+              text run at (379,1) width 21: "03"
+              text run at (399,1) width 50 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+              text run at (448,1) width 34: "First"
+        LayoutBlockFlow {DIV} at (0,82) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 28: "fifth"
             text run at (324,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
             text run at (375,10) width 17: "03"
             text run at (391,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (432,10) width 28: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (316,2) size 161x16
-              text run at (316,2) width 161 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
+        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (284,1) size 198x18
+              text run at (284,1) width 198 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,141) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 500x21
-            LayoutText (anonymous) at (316,2) size 161x16
-              text run at (316,2) width 161 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
+        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutBlockFlow (anonymous) at (1,1) size 498x21
+            LayoutText (anonymous) at (284,1) size 198x18
+              text run at (284,1) width 198 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+        LayoutBlockFlow {DIV} at (0,200) size 470x36
           LayoutText {#text} at (297,10) size 163x16
             text run at (297,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index b76d4971..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.txt
deleted file mode 100644
index 229e5d25..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 604
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 785x600
-  LayoutBlockFlow {html} at (0,0) size 785x600
-    LayoutInline {base} at (0,0) size 0x0
-    LayoutText {#text} at (0,0) size 0x0
-    LayoutText {#text} at (0,0) size 0x0
-    LayoutSVGRoot {svg} at (0,0) size 100x100
-      LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGResourceLinearGradient {linearGradient} [id="orange_red"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
-          LayoutSVGGradientStop {stop} [offset=0.00] [color=#FF0000]
-          LayoutSVGGradientStop {stop} [offset=1.00] [color=#FF0000]
-      LayoutSVGRect {rect} at (0,0) size 100x100 [x=0.00] [y=0.00] [width=100.00] [height=100.00]
-    LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/repaint/table-collapsed-border-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/repaint/table-collapsed-border-expected.txt
index 24c92056..4e2a921c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/repaint/table-collapsed-border-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/repaint/table-collapsed-border-expected.txt
@@ -112,6 +112,26 @@
           "object": "LayoutTable TABLE",
           "rect": [83, 268, 26, 76],
           "reason": "incremental"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 210, 14, 20],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutTableCell TD",
+          "rect": [8, 124, 14, 20],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [17, 211, 4, 17],
+          "reason": "forced by layout"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [17, 125, 4, 17],
+          "reason": "forced by layout"
         }
       ]
     }
@@ -198,6 +218,22 @@
       "reason": "forced by layout"
     },
     {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutTableCell TD",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "forced by layout"
+    },
+    {
       "object": "InlineTextBox 'sit amet'",
       "reason": "forced by layout"
     },
@@ -210,6 +246,22 @@
       "reason": "forced by layout"
     },
     {
+      "object": "LayoutTableCell TD",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "forced by layout"
+    },
+    {
+      "object": "InlineTextBox '\u00A0'",
+      "reason": "forced by layout"
+    },
+    {
       "object": "LayoutTable TABLE",
       "reason": "incremental"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/win/plugins/webview-plugin-lifecycle-expected.png b/third_party/WebKit/LayoutTests/platform/win/plugins/webview-plugin-lifecycle-expected.png
index ca6fcea..d0c783b1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/plugins/webview-plugin-lifecycle-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/plugins/webview-plugin-lifecycle-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index b4e81fd..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.txt
deleted file mode 100644
index 3629126..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 603
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 785x600
-  LayoutBlockFlow {html} at (0,0) size 785x600
-    LayoutInline {base} at (0,0) size 0x0
-    LayoutText {#text} at (0,0) size 0x0
-    LayoutText {#text} at (0,0) size 0x0
-    LayoutSVGRoot {svg} at (0,0) size 100x100
-      LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGResourceLinearGradient {linearGradient} [id="orange_red"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
-          LayoutSVGGradientStop {stop} [offset=0.00] [color=#FF0000]
-          LayoutSVGGradientStop {stop} [offset=1.00] [color=#FF0000]
-      LayoutSVGRect {rect} at (0,0) size 100x100 [x=0.00] [y=0.00] [width=100.00] [height=100.00]
-    LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/crashes/slot-dir-attribute-crash.html b/third_party/WebKit/LayoutTests/shadow-dom/crashes/slot-dir-attribute-crash.html
new file mode 100644
index 0000000..a3c3f2c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/shadow-dom/crashes/slot-dir-attribute-crash.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src='../../resources/testharness.js'></script>
+<script src='../../resources/testharnessreport.js'></script>
+<script>
+test(() => {
+  let slot = document.createElement("slot");
+  // This could cause crash. See crbug.com/627385
+  slot.setAttribute("dir", "auto");
+  assert_true(true, 'This test must run without crash.');
+}, "HTMLSlotElement's dir attribute should not be used until Blink supports slots in a flat tree.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference-expected.html b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference-expected.html
new file mode 100644
index 0000000..5fc78bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 200px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference.html b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference.html
new file mode 100644
index 0000000..48985759
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<svg>
+  <script>
+    var svgRoot = document.querySelector('svg');
+    svgRoot.pauseAnimations();
+    svgRoot.setCurrentTime(1);
+  </script>
+  <defs>
+    <path id="path" d="M100,0z"/>
+  </defs>
+  <rect width="100" height="100" fill="green">
+    <animateMotion dur="0.01" fill="freeze">
+      <mpath xlink:href="#path"/>
+    </animateMotion>
+  </rect>
+  <rect id="rect" width="100" height="100" fill="red"/>
+  <set attributeName="fill" xlink:href="#rect" to="green" dur="indefinite"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html b/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html
index 75768a0..bc3a3d93 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html
+++ b/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <svg>
-   <rect id="rect" width="100" height="100" fill="green"/>
+   <rect width="100" height="100" fill="green"/>
+   <rect x="150" width="100" height="100" fill="green"/>
 </svg>
 
diff --git a/third_party/WebKit/LayoutTests/svg/custom/getBBox-path-expected.txt b/third_party/WebKit/LayoutTests/svg/custom/getBBox-path-expected.txt
index 33975cc8..86db678a 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/getBBox-path-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/custom/getBBox-path-expected.txt
@@ -1 +1 @@
-100 50 FAIL
+100 37.5 PASS
diff --git a/third_party/WebKit/LayoutTests/svg/custom/linking-base-external-reference.xhtml b/third_party/WebKit/LayoutTests/svg/custom/linking-base-external-reference.xhtml
deleted file mode 100644
index 16cf05cc..0000000
--- a/third_party/WebKit/LayoutTests/svg/custom/linking-base-external-reference.xhtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%">
-  <base href="http://www.example.com"/>
-  <!-- There should be no red -->
-  <svg width="100%" height="100%" version="1.1"
-       xmlns="http://www.w3.org/2000/svg">
-
-    <defs>
-      <linearGradient id="orange_red" x1="0%" y1="0%" x2="100%" y2="0%">
-        <stop offset="0%" style="stop-color:red;"/>
-        <stop offset="100%" style="stop-color:red;"/>
-      </linearGradient>
-
-    </defs>
-
-    <rect x="0" y="0" width="100" height="100" style="fill: url(#orange_red)"/>
-  </svg>
-</html>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc-expected.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc-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/svg/custom/local-url-reference-srcdoc.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc.html
new file mode 100644
index 0000000..201ba10
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<iframe srcdoc="
+  <!DOCTYPE html>
+  <style>body { margin: 0; }</style>
+  <svg xmlns='http://www.w3.org/2000/svg'>
+    <linearGradient id='gradient'>
+      <stop stop-color='green'/>
+    </linearGradient>
+    <rect width='100' height='100' fill='url(#gradient) red'/>
+  </svg>"
+  style="margin: 0; border: none" scrolling="no">
+</iframe>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-references-expected.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-references-expected.html
new file mode 100644
index 0000000..2a4e1f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-references-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 400px; height: 300px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-references.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-references.html
new file mode 100644
index 0000000..b8049870
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-references.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<svg width="400" height="300">
+  <linearGradient id="paint">
+    <stop stop-color="green"/>
+  </linearGradient>
+  <linearGradient id="inheritedPaint" xlink:href="#paint"/>
+  <rect id="rect" width="100" height="100" fill="url(#paint) red"/>
+  <rect x="125" y="25" width="50" height="50" stroke="url(#paint) red" stroke-width="50"/>
+  <use x="200" xlink:href="#rect"/>
+  <rect x="300" width="100" height="100" fill="url(#inheritedPaint) red"/>
+
+  <filter id="filter" x="0" y="0" width="1" height="1" color-interpolation-filters="sRGB">
+    <feImage xlink:href="#rect"/>
+  </filter>
+  <rect y="100" width="100" height="100" fill="red" filter="url(#filter)"/>
+
+  <clipPath id="clip">
+    <rect y="50" width="100" height="50"/>
+  </clipPath>
+  <rect x="100" y="100" width="100" height="50" fill="green"/>
+  <g clip-path="url(#clip)" transform="translate(100, 100)">
+    <rect width="100" height="50" fill="red"/>
+    <rect y="50" width="100" height="50" fill="green"/>
+  </g>
+
+  <mask id="mask">
+    <rect y="50" width="100" height="50" fill="white"/>
+  </mask>
+  <rect y="100" x="200" width="100" height="50" fill="green"/>
+  <g mask="url(#mask)" transform="translate(200, 100)">
+    <rect width="100" height="50" fill="red"/>
+    <rect y="50" width="100" height="50" fill="green"/>
+  </g>
+
+  <pattern id="pattern" width="100" height="100" patternUnits="userSpaceOnUse">
+    <rect width="100" height="100" fill="green"/>
+  </pattern>
+  <pattern id="inheritedPattern" xlink:href="#pattern"/>
+  <rect x="300" y="100" width="100" height="100" fill="url(#inheritedPattern) red"/>
+
+  <marker id="marker" refY="0.5">
+    <rect width="1" height="1" fill="green"/>
+  </marker>
+  <polyline points="0,250 100,250 200,250" stroke="red" stroke-width="100"
+            marker-start="url(#marker)" marker-mid="url(#marker)" marker-end="url(#marker)"/>
+
+  <radialGradient id="radial">
+    <stop stop-color="green"/>
+  </radialGradient>
+  <radialGradient id="inheritedRadial" xlink:href="#radial"/>
+  <rect x="300" y="200" width="100" height="100" fill="url(#inheritedRadial) red"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/use-external-base-change-assert-expected.txt b/third_party/WebKit/LayoutTests/svg/custom/use-external-base-change-assert-expected.txt
new file mode 100644
index 0000000..094733c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/use-external-base-change-assert-expected.txt
@@ -0,0 +1 @@
+PASS if no assert in debug
diff --git a/third_party/WebKit/LayoutTests/svg/custom/use-external-base-change-assert.html b/third_party/WebKit/LayoutTests/svg/custom/use-external-base-change-assert.html
new file mode 100644
index 0000000..272c0a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/use-external-base-change-assert.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<svg>
+  <use href="resources/linkingCircle-f.svg#circle-1"/>
+  <script>
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    var baseElement = document.createElement("base");
+    baseElement.setAttribute("href", "http://www.example.com/");
+    document.head.appendChild(baseElement);
+  </script>
+</svg>
+<p>PASS if no assert in debug</p>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/use-external-dynamic-base-change-expected.html b/third_party/WebKit/LayoutTests/svg/custom/use-external-dynamic-base-change-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/use-external-dynamic-base-change-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/svg/custom/use-external-dynamic-base-change.html b/third_party/WebKit/LayoutTests/svg/custom/use-external-dynamic-base-change.html
new file mode 100644
index 0000000..8a54ec37
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/use-external-dynamic-base-change.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<svg>
+  <rect id="rect" width="0" height="100"/>
+  <use xlink:href="#rect" fill="green"/>
+</svg>
+<script>
+runAfterLayoutAndPaint(function() {
+  var baseElement = document.createElement("base");
+  baseElement.setAttribute("href", "http://www.example.com/");
+  document.head.appendChild(baseElement);
+  document.querySelector('#rect').setAttribute("width", "100");
+}, true);
+</script>
diff --git a/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference-expected.html b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference-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/svg/text/textpath-local-url-reference.html b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference.html
new file mode 100644
index 0000000..0051ba87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<script src="../../resources/ahem.js"></script>
+<svg>
+  <path id="path" d="M0,80h100"/>
+  <text font-size="100" font-family="Ahem" fill="green"><textPath xlink:href="#path">X</textPath></textPath>
+</svg>
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 985b78d..48ea60d4 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4444,6 +4444,9 @@
 interface PhotoCapabilities
     attribute @@toStringTag
     getter focusMode
+    getter imageHeight
+    getter imageWidth
+    getter iso
     getter zoom
     method constructor
 interface Plugin
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolverTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolverTest.cpp
index e1f7e55..052d415 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolverTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseResolverTest.cpp
@@ -18,8 +18,6 @@
 
 namespace {
 
-void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { }
-
 class Function : public ScriptFunction {
 public:
     static v8::Local<v8::Function> createFunction(ScriptState* scriptState, String* value)
@@ -54,11 +52,6 @@
 
     ~ScriptPromiseResolverTest() override
     {
-        ScriptState::Scope scope(getScriptState());
-        // FIXME: We put this statement here to clear an exception from the
-        // isolate.
-        createClosure(callback, v8::Undefined(isolate()), isolate());
-
         // Execute all pending microtasks
         v8::MicrotasksScope::PerformCheckpoint(isolate());
     }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseTest.cpp
index 7146ae52..21e908eb 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptPromiseTest.cpp
@@ -46,8 +46,6 @@
 
 typedef ScriptPromise::InternalResolver Resolver;
 
-void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { }
-
 class Function : public ScriptFunction {
 public:
     static v8::Local<v8::Function> createFunction(ScriptState* scriptState, ScriptValue* output)
@@ -83,9 +81,6 @@
 
     ~TryCatchScope()
     {
-        // FIXME: We put this statement here to clear an exception from the isolate.
-        createClosure(callback, v8::Undefined(m_isolate), m_isolate);
-
         // Execute all pending microtasks
         v8::MicrotasksScope::PerformCheckpoint(m_isolate);
     }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptState.h b/third_party/WebKit/Source/bindings/core/v8/ScriptState.h
index 3ef79f0b..96dc103 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptState.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptState.h
@@ -57,6 +57,16 @@
         return from(isolate->GetCurrentContext());
     }
 
+    static ScriptState* forHolderObject(const v8::FunctionCallbackInfo<v8::Value>& info)
+    {
+        return from(info.Holder()->CreationContext());
+    }
+
+    static ScriptState* forHolderObject(const v8::PropertyCallbackInfo<v8::Value>& info)
+    {
+        return from(info.Holder()->CreationContext());
+    }
+
     // Debugger context doesn't have associated ScriptState and when current
     // context is debugger it should be treated as if context stack was empty.
     static bool hasCurrentScriptState(v8::Isolate* isolate)
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
index 998bcec4..512fa57 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -181,7 +181,7 @@
         , m_queueTailPosition(0)
         , m_bookmarkPosition(0)
         , m_lengthOfBOM(0)
-        , m_loadingTaskRunner(wrapUnique(loadingTaskRunner->clone()))
+        , m_loadingTaskRunner(loadingTaskRunner->clone())
     {
     }
 
@@ -590,7 +590,7 @@
     , m_scriptURLString(m_resource->url().copy().getString())
     , m_scriptResourceIdentifier(m_resource->identifier())
     , m_encoding(v8::ScriptCompiler::StreamedSource::TWO_BYTE) // Unfortunately there's no dummy encoding value in the enum; let's use one we don't stream.
-    , m_loadingTaskRunner(wrapUnique(loadingTaskRunner->clone()))
+    , m_loadingTaskRunner(loadingTaskRunner->clone())
 {
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp b/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp
index 285f873..41a0d7940f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingForTesting.cpp
@@ -82,6 +82,11 @@
 
 V8TestingScope::~V8TestingScope()
 {
+    // TODO(yukishiino): We put this statement here to clear an exception from
+    // the isolate.  Otherwise, the leak detector complains.  Really mysterious
+    // hack.
+    v8::Function::New(context(), nullptr);
+
     if (m_holder->document().frame())
         getScriptState()->disposePerContextData();
 }
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
index 9d3e972..2117ab53a 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -38,6 +38,7 @@
 #include "core/css/CSSStyleDeclaration.h"
 #include "core/css/CSSValue.h"
 #include "core/css/parser/CSSParser.h"
+#include "core/dom/custom/CEReactionsScope.h"
 #include "core/events/EventTarget.h"
 #include "wtf/ASCIICType.h"
 #include "wtf/PassRefPtr.h"
@@ -212,6 +213,8 @@
     if (!unresolvedProperty)
         return;
 
+    CEReactionsScope ceReactionsScope;
+
     TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, propertyValue, value);
     ExceptionState exceptionState(ExceptionState::SetterContext, getPropertyName(resolveCSSPropertyID(unresolvedProperty)), "CSSStyleDeclaration", info.Holder(), info.GetIsolate());
     // TODO(leviw): This API doesn't support custom properties.
diff --git a/third_party/WebKit/Source/bindings/templates/attributes.cpp b/third_party/WebKit/Source/bindings/templates/attributes.cpp
index ccd09228..be5b5ea 100644
--- a/third_party/WebKit/Source/bindings/templates/attributes.cpp
+++ b/third_party/WebKit/Source/bindings/templates/attributes.cpp
@@ -62,7 +62,7 @@
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     {% endif %}
     {% if attribute.is_call_with_script_state %}
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     {% endif %}
     {% if (attribute.is_check_security_for_receiver and
            not attribute.is_data_type_property) or
@@ -193,7 +193,7 @@
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as('AttributeGetter')}});
     {% endif %}
     {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     {% if attribute.activity_logging_world_check %}
     if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger())
@@ -342,7 +342,7 @@
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     {% endif %}
     {% if attribute.is_call_with_script_state %}
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     {% endif %}
     {# Set #}
     {% if attribute.cpp_setter %}
@@ -378,7 +378,7 @@
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as('AttributeSetter')}});
     {% endif %}
     {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     {% if attribute.activity_logging_world_check %}
     if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) {
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp b/third_party/WebKit/Source/bindings/templates/methods.cpp
index 6edab40..0ebe28a 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp
@@ -233,7 +233,7 @@
 {% if method.is_call_with_script_state or method.is_call_with_this_value %}
 {# [ConstructorCallWith=ScriptState] #}
 {# [CallWith=ScriptState] #}
-ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+ScriptState* scriptState = ScriptState::forHolderObject(info);
 {% endif %}
 {% if method.is_call_with_execution_context %}
 {# [ConstructorCallWith=ExecutionContext] #}
@@ -502,7 +502,7 @@
     {% endif %}
     {% endif %}{# not method.overloads #}
     {% if world_suffix in method.activity_logging_world_list %}
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     {% if method.activity_logging_world_check %}
     if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger())
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index 4fee8f1..0b480a7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -1786,7 +1786,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "toJSON", "TestInterface", info.Holder(), info.GetIsolate());
     TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ScriptValue result = impl->toJSONForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -1815,7 +1815,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestInterface", info.Holder(), info.GetIsolate());
     TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterator(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
index d4f5979..b7a9637 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -238,7 +238,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "keys", "TestInterface2", info.Holder(), info.GetIsolate());
     TestInterface2* impl = V8TestInterface2::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->keysForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -256,7 +256,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "values", "TestInterface2", info.Holder(), info.GetIsolate());
     TestInterface2* impl = V8TestInterface2::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->valuesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -274,7 +274,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "entries", "TestInterface2", info.Holder(), info.GetIsolate());
     TestInterface2* impl = V8TestInterface2::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->entriesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -308,7 +308,7 @@
         callback = ScriptValue(ScriptState::current(info.GetIsolate()), info[0]);
         thisArg = ScriptValue(ScriptState::current(info.GetIsolate()), info[1]);
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->forEachForBinding(scriptState, ScriptValue(scriptState, info.Holder()), callback, thisArg, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -339,7 +339,7 @@
             return;
         }
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     bool result = impl->hasForBinding(scriptState, value, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -368,7 +368,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestInterface2", info.Holder(), info.GetIsolate());
     TestInterface2* impl = V8TestInterface2::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterator(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
index f0d15387..139f7c88 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -78,7 +78,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "keys", "TestInterface3", info.Holder(), info.GetIsolate());
     TestInterface3* impl = V8TestInterface3::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterableKeys(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -96,7 +96,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "values", "TestInterface3", info.Holder(), info.GetIsolate());
     TestInterface3* impl = V8TestInterface3::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->valuesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -114,7 +114,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "entries", "TestInterface3", info.Holder(), info.GetIsolate());
     TestInterface3* impl = V8TestInterface3::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->entriesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -148,7 +148,7 @@
         callback = ScriptValue(ScriptState::current(info.GetIsolate()), info[0]);
         thisArg = ScriptValue(ScriptState::current(info.GetIsolate()), info[1]);
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->forEachForBinding(scriptState, ScriptValue(scriptState, info.Holder()), callback, thisArg, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -176,7 +176,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestInterface3", info.Holder(), info.GetIsolate());
     TestInterface3* impl = V8TestInterface3::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterator(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
index 70af33f..132f6ca1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -42,7 +42,7 @@
 static void constructor1(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     ExceptionState exceptionState(ExceptionState::ConstructionContext, "TestInterfaceConstructor", info.Holder(), info.GetIsolate());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
     TestInterfaceConstructor* impl = TestInterfaceConstructor::create(scriptState, executionContext, document, exceptionState);
@@ -112,7 +112,7 @@
             return;
         }
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
     TestInterfaceConstructor* impl = TestInterfaceConstructor::create(scriptState, executionContext, document, doubleArg, stringArg, testInterfaceEmptyArg, dictionaryArg, sequenceStringArg, sequenceDictionaryArg, sequenceLongOrTestDictionaryArg, optionalDictionaryArg, optionalTestInterfaceEmptyArg, exceptionState);
@@ -141,7 +141,7 @@
         if (!arg.prepare())
             return;
         if (UNLIKELY(numArgsPassed <= 1)) {
-            ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+            ScriptState* scriptState = ScriptState::forHolderObject(info);
             ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
             Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
             TestInterfaceConstructor* impl = TestInterfaceConstructor::create(scriptState, executionContext, document, arg, exceptionState);
@@ -158,7 +158,7 @@
         if (!optArg.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
     TestInterfaceConstructor* impl = TestInterfaceConstructor::create(scriptState, executionContext, document, arg, optArg, exceptionState);
@@ -188,7 +188,7 @@
         if (!arg3.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
     TestInterfaceConstructor* impl = TestInterfaceConstructor::create(scriptState, executionContext, document, arg, arg2, arg3, exceptionState);
@@ -304,7 +304,7 @@
         if (!arg.prepare())
             return;
         if (UNLIKELY(numArgsPassed <= 1)) {
-            ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+            ScriptState* scriptState = ScriptState::forHolderObject(info);
             ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
             Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
             TestInterfaceConstructor* impl = TestInterfaceConstructor::createForJSConstructor(scriptState, executionContext, document, arg, exceptionState);
@@ -321,7 +321,7 @@
         if (!optArg.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
     TestInterfaceConstructor* impl = TestInterfaceConstructor::createForJSConstructor(scriptState, executionContext, document, arg, optArg, exceptionState);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
index 4361804..47cc440c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
@@ -97,7 +97,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "keys", "TestInterfaceGarbageCollected", info.Holder(), info.GetIsolate());
     TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->keysForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -115,7 +115,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "values", "TestInterfaceGarbageCollected", info.Holder(), info.GetIsolate());
     TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->valuesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -133,7 +133,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "entries", "TestInterfaceGarbageCollected", info.Holder(), info.GetIsolate());
     TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->entriesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -167,7 +167,7 @@
         callback = ScriptValue(ScriptState::current(info.GetIsolate()), info[0]);
         thisArg = ScriptValue(ScriptState::current(info.GetIsolate()), info[1]);
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->forEachForBinding(scriptState, ScriptValue(scriptState, info.Holder()), callback, thisArg, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -195,7 +195,7 @@
         if (!value.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     bool result = impl->hasForBinding(scriptState, value, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -224,7 +224,7 @@
         if (!value.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     TestInterfaceGarbageCollected* result = impl->addForBinding(scriptState, value, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -242,7 +242,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "clear", "TestInterfaceGarbageCollected", info.Holder(), info.GetIsolate());
     TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->clearForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -270,7 +270,7 @@
         if (!value.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     bool result = impl->deleteForBinding(scriptState, value, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -288,7 +288,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestInterfaceGarbageCollected", info.Holder(), info.GetIsolate());
     TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterator(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index 665564c..cf7eb77 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -2029,7 +2029,7 @@
 
 static void activityLoggingAccessForAllWorldsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingAccessForAllWorldsLongAttribute");
@@ -2050,7 +2050,7 @@
 static void activityLoggingAccessForAllWorldsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     v8::Local<v8::Value> v8Value = info[0];
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         contextData->activityLogger()->logSetter("TestObject.activityLoggingAccessForAllWorldsLongAttribute", v8Value);
@@ -2067,7 +2067,7 @@
 
 static void activityLoggingGetterForAllWorldsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingGetterForAllWorldsLongAttribute");
@@ -2117,7 +2117,7 @@
 static void activityLoggingSetterForAllWorldsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     v8::Local<v8::Value> v8Value = info[0];
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         contextData->activityLogger()->logSetter("TestObject.activityLoggingSetterForAllWorldsLongAttribute", v8Value);
@@ -2276,7 +2276,7 @@
 {
     v8::Local<v8::Object> holder = info.Holder();
     TestObject* impl = V8TestObject::toImpl(holder);
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     v8SetReturnValue(info, impl->callWithScriptStateAnyAttribute(scriptState).v8Value());
 }
 
@@ -2290,7 +2290,7 @@
     v8::Local<v8::Object> holder = info.Holder();
     TestObject* impl = V8TestObject::toImpl(holder);
     ScriptValue cppValue = ScriptValue(ScriptState::current(info.GetIsolate()), v8Value);
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->setCallWithScriptStateAnyAttribute(scriptState, cppValue);
 }
 
@@ -2305,7 +2305,7 @@
     v8::Local<v8::Object> holder = info.Holder();
     TestObject* impl = V8TestObject::toImpl(holder);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     v8SetReturnValue(info, impl->callWithExecutionContextAndScriptStateAnyAttribute(scriptState, executionContext).v8Value());
 }
 
@@ -2320,7 +2320,7 @@
     TestObject* impl = V8TestObject::toImpl(holder);
     ScriptValue cppValue = ScriptValue(ScriptState::current(info.GetIsolate()), v8Value);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->setCallWithExecutionContextAndScriptStateAnyAttribute(scriptState, executionContext, cppValue);
 }
 
@@ -2704,7 +2704,7 @@
 
 static void activityLoggingAccessPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute");
@@ -2725,7 +2725,7 @@
 static void activityLoggingAccessPerWorldBindingsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     v8::Local<v8::Value> v8Value = info[0];
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         contextData->activityLogger()->logSetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute", v8Value);
@@ -2742,7 +2742,7 @@
 
 static void activityLoggingAccessPerWorldBindingsLongAttributeAttributeGetterCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute");
@@ -2763,7 +2763,7 @@
 static void activityLoggingAccessPerWorldBindingsLongAttributeAttributeSetterCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     v8::Local<v8::Value> v8Value = info[0];
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         contextData->activityLogger()->logSetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute", v8Value);
@@ -2780,7 +2780,7 @@
 
 static void activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttribute");
@@ -2801,7 +2801,7 @@
 static void activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     v8::Local<v8::Value> v8Value = info[0];
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         contextData->activityLogger()->logSetter("TestObject.activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttribute", v8Value);
@@ -2847,7 +2847,7 @@
 
 static void activityLoggingGetterPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingGetterPerWorldBindingsLongAttribute");
@@ -2880,7 +2880,7 @@
 
 static void activityLoggingGetterPerWorldBindingsLongAttributeAttributeGetterCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingGetterPerWorldBindingsLongAttribute");
@@ -2913,7 +2913,7 @@
 
 static void activityLoggingGetterForIsolatedWorldsPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger())
         contextData->activityLogger()->logGetter("TestObject.activityLoggingGetterForIsolatedWorldsPerWorldBindingsLongAttribute");
@@ -8929,7 +8929,7 @@
         if (exceptionState.throwIfNeeded())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ScriptValue result = impl->item(scriptState, index);
     v8SetReturnValue(info, result.v8Value());
 }
@@ -8958,7 +8958,7 @@
         if (!value.prepare())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     String result = impl->setItem(scriptState, index, value);
     v8SetReturnValueString(info, result, info.GetIsolate());
 }
@@ -9162,7 +9162,7 @@
 
 static void activityLoggingAccessForAllWorldsMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         ExceptionState exceptionState(ExceptionState::ExecutionContext, "activityLoggingAccessForAllWorldsMethod", "TestObject", info.Holder(), info.GetIsolate());
@@ -9187,7 +9187,7 @@
 static void callWithScriptStateVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->callWithScriptStateVoidMethod(scriptState);
 }
 
@@ -9199,7 +9199,7 @@
 static void callWithScriptStateLongMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     int result = impl->callWithScriptStateLongMethod(scriptState);
     v8SetReturnValueInt(info, result);
 }
@@ -9212,7 +9212,7 @@
 static void callWithScriptStateExecutionContextVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
     impl->callWithScriptStateExecutionContextVoidMethod(scriptState, executionContext);
 }
@@ -9225,7 +9225,7 @@
 static void callWithScriptStateScriptArgumentsVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ScriptArguments* scriptArguments(ScriptArguments::create(scriptState, info, 0));
     impl->callWithScriptStateScriptArgumentsVoidMethod(scriptState, scriptArguments);
 }
@@ -9248,7 +9248,7 @@
             --numArgsPassed;
         }
         if (UNLIKELY(numArgsPassed <= 0)) {
-            ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+            ScriptState* scriptState = ScriptState::forHolderObject(info);
             ScriptArguments* scriptArguments(ScriptArguments::create(scriptState, info, 1));
             impl->callWithScriptStateScriptArgumentsVoidMethodOptionalBooleanArg(scriptState, scriptArguments);
             return;
@@ -9257,7 +9257,7 @@
         if (exceptionState.throwIfNeeded())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ScriptArguments* scriptArguments(ScriptArguments::create(scriptState, info, 1));
     impl->callWithScriptStateScriptArgumentsVoidMethodOptionalBooleanArg(scriptState, scriptArguments, optionalBooleanArg);
 }
@@ -9292,7 +9292,7 @@
 static void callWithThisValueMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->callWithThisValue(ScriptValue(scriptState, info.Holder()));
 }
 
@@ -9958,7 +9958,7 @@
 
 static void activityLoggingForAllWorldsPerWorldBindingsVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         ExceptionState exceptionState(ExceptionState::ExecutionContext, "activityLoggingForAllWorldsPerWorldBindingsVoidMethod", "TestObject", info.Holder(), info.GetIsolate());
@@ -9976,7 +9976,7 @@
 
 static void activityLoggingForAllWorldsPerWorldBindingsVoidMethodMethodCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         ExceptionState exceptionState(ExceptionState::ExecutionContext, "activityLoggingForAllWorldsPerWorldBindingsVoidMethod", "TestObject", info.Holder(), info.GetIsolate());
@@ -9994,7 +9994,7 @@
 
 static void activityLoggingForIsolatedWorldsPerWorldBindingsVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     V8PerContextData* contextData = scriptState->perContextData();
     if (contextData && contextData->activityLogger()) {
         ExceptionState exceptionState(ExceptionState::ExecutionContext, "activityLoggingForIsolatedWorldsPerWorldBindingsVoidMethod", "TestObject", info.Holder(), info.GetIsolate());
@@ -10837,7 +10837,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "keys", "TestObject", info.Holder(), info.GetIsolate());
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->keysForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -10855,7 +10855,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "values", "TestObject", info.Holder(), info.GetIsolate());
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->valuesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -10873,7 +10873,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "entries", "TestObject", info.Holder(), info.GetIsolate());
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->entriesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -10907,7 +10907,7 @@
         callback = ScriptValue(ScriptState::current(info.GetIsolate()), info[0]);
         thisArg = ScriptValue(ScriptState::current(info.GetIsolate()), info[1]);
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->forEachForBinding(scriptState, ScriptValue(scriptState, info.Holder()), callback, thisArg, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -10935,7 +10935,7 @@
         if (exceptionState.throwIfNeeded())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     bool result = impl->hasForBinding(scriptState, key, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -10964,7 +10964,7 @@
         if (exceptionState.throwIfNeeded())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     ScriptValue result = impl->getForBinding(scriptState, key, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -10982,7 +10982,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "clear", "TestObject", info.Holder(), info.GetIsolate());
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->clearForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -11010,7 +11010,7 @@
         if (exceptionState.throwIfNeeded())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     bool result = impl->deleteForBinding(scriptState, key, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -11043,7 +11043,7 @@
         if (exceptionState.throwIfNeeded())
             return;
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     TestObject* result = impl->setForBinding(scriptState, key, value, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -11083,7 +11083,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestObject", info.Holder(), info.GetIsolate());
     TestObject* impl = V8TestObject::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterator(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
index 0373cf1..f4f4028 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
@@ -523,7 +523,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "keys", "TestInterface5", info.Holder(), info.GetIsolate());
     TestInterface5Implementation* impl = V8TestInterface5::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->keysForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -541,7 +541,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "values", "TestInterface5", info.Holder(), info.GetIsolate());
     TestInterface5Implementation* impl = V8TestInterface5::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->valuesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -559,7 +559,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "entries", "TestInterface5", info.Holder(), info.GetIsolate());
     TestInterface5Implementation* impl = V8TestInterface5::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->entriesForBinding(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -593,7 +593,7 @@
         callback = ScriptValue(ScriptState::current(info.GetIsolate()), info[0]);
         thisArg = ScriptValue(ScriptState::current(info.GetIsolate()), info[1]);
     }
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     impl->forEachForBinding(scriptState, ScriptValue(scriptState, info.Holder()), callback, thisArg, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
@@ -621,7 +621,7 @@
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "iterator", "TestInterface5", info.Holder(), info.GetIsolate());
     TestInterface5Implementation* impl = V8TestInterface5::toImpl(info.Holder());
-    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
+    ScriptState* scriptState = ScriptState::forHolderObject(info);
     Iterator* result = impl->iterator(scriptState, exceptionState);
     if (exceptionState.hadException()) {
         exceptionState.throwIfNeeded();
diff --git a/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp
index b12ffaf..7c1fbd9 100644
--- a/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/FilterInterpolationFunctions.cpp
@@ -91,8 +91,11 @@
 
 InterpolationValue FilterInterpolationFunctions::maybeConvertCSSFilter(const CSSValue& value)
 {
+    if (value.isURIValue())
+        return nullptr;
+
     const CSSFunctionValue& filter = toCSSFunctionValue(value);
-    ASSERT(filter.length() <= 1);
+    DCHECK_LE(filter.length(), 1u);
     FilterOperation::OperationType type = FilterOperationResolver::filterOperationForType(filter.functionType());
     InterpolationValue result = nullptr;
 
@@ -136,9 +139,6 @@
         break;
     }
 
-    case FilterOperation::REFERENCE:
-        return nullptr;
-
     default:
         NOTREACHED();
         return nullptr;
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index 494fc4e..51a45f3f 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -1215,8 +1215,6 @@
             'css/CSSRule.h',
             'css/CSSRuleList.cpp',
             'css/CSSRuleList.h',
-            'css/CSSSVGDocumentValue.cpp',
-            'css/CSSSVGDocumentValue.h',
             'css/CSSSegmentedFontFace.cpp',
             'css/CSSSegmentedFontFace.h',
             'css/CSSSelector.cpp',
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in
index 39071e06..6dc3b0d7 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.in
+++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -207,9 +207,9 @@
 float type_name=EFloat, name_for_methods=Floating
 flood-color interpolable, svg, converter=convertColor
 flood-opacity interpolable, svg, converter=convertNumberOrPercentage
-grid-auto-columns runtime_flag=CSSGridLayout, converter=convertGridTrackSize
+grid-auto-columns runtime_flag=CSSGridLayout, converter=convertGridTrackSizeList
 grid-auto-flow runtime_flag=CSSGridLayout, converter=convertGridAutoFlow, type_name=GridAutoFlow
-grid-auto-rows runtime_flag=CSSGridLayout, converter=convertGridTrackSize
+grid-auto-rows runtime_flag=CSSGridLayout, converter=convertGridTrackSizeList
 grid-column-end runtime_flag=CSSGridLayout, converter=convertGridPosition
 grid-column-gap runtime_flag=CSSGridLayout, converter=convertLength
 grid-column-start runtime_flag=CSSGridLayout, converter=convertGridPosition
diff --git a/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp b/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp
deleted file mode 100644
index 158620a1..0000000
--- a/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * 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 "core/css/CSSSVGDocumentValue.h"
-
-#include "core/css/CSSMarkup.h"
-#include "core/dom/Document.h"
-#include "core/fetch/FetchInitiatorTypeNames.h"
-#include "core/fetch/FetchRequest.h"
-#include "core/fetch/ResourceFetcher.h"
-
-namespace blink {
-
-CSSSVGDocumentValue::CSSSVGDocumentValue(const String& url)
-    : CSSValue(CSSSVGDocumentClass)
-    , m_url(url)
-    , m_loadRequested(false)
-{
-}
-
-CSSSVGDocumentValue::~CSSSVGDocumentValue()
-{
-}
-
-DocumentResource* CSSSVGDocumentValue::load(Document* document) const
-{
-    ASSERT(document);
-
-    if (!m_loadRequested) {
-        m_loadRequested = true;
-
-        FetchRequest request(ResourceRequest(document->completeURL(m_url)), FetchInitiatorTypeNames::css);
-        m_document = DocumentResource::fetchSVGDocument(request, document->fetcher());
-    }
-
-    return m_document.get();
-}
-
-String CSSSVGDocumentValue::customCSSText() const
-{
-    return serializeString(m_url);
-}
-
-bool CSSSVGDocumentValue::equals(const CSSSVGDocumentValue& other) const
-{
-    return m_url == other.m_url;
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h b/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h
deleted file mode 100644
index da2185e..0000000
--- a/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CSSSVGDocumentValue_h
-#define CSSSVGDocumentValue_h
-
-#include "core/css/CSSValue.h"
-#include "core/fetch/DocumentResource.h"
-
-namespace blink {
-
-class Document;
-
-class CSSSVGDocumentValue : public CSSValue {
-public:
-    static CSSSVGDocumentValue* create(const String& url)
-    {
-        return new CSSSVGDocumentValue(url);
-    }
-    ~CSSSVGDocumentValue();
-
-    DocumentResource* cachedSVGDocument() const { return m_document.get(); }
-    DocumentResource* load(Document*) const;
-
-    String customCSSText() const;
-    const String& url() const { return m_url; }
-    bool loadRequested() const { return m_loadRequested; }
-    bool equals(const CSSSVGDocumentValue&) const;
-
-    DEFINE_INLINE_TRACE_AFTER_DISPATCH()
-    {
-        visitor->trace(m_document);
-        CSSValue::traceAfterDispatch(visitor);
-    }
-
-private:
-    CSSSVGDocumentValue(const String& url);
-
-    String m_url;
-
-    // Document cache.
-    mutable Member<DocumentResource> m_document;
-    mutable bool m_loadRequested;
-};
-
-DEFINE_CSS_VALUE_TYPE_CASTS(CSSSVGDocumentValue, isSVGDocumentValue());
-
-} // namespace blink
-
-#endif // CSSSVGDocumentValue_h
diff --git a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
index 9386183..bf4e728 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
+++ b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
@@ -24,19 +24,19 @@
     DependentLifetime,
     SetWrapperReferenceTo(CSSRule parentRule),
 ] interface CSSStyleDeclaration {
-    [RaisesException=Setter] attribute DOMString cssText;
+    [CEReactions, RaisesException=Setter] attribute DOMString cssText;
     readonly attribute unsigned long length;
     getter DOMString item(unsigned long index);
     DOMString getPropertyValue(DOMString property);
     DOMString getPropertyPriority(DOMString property);
     // TODO(foolip): The value and priority arguments should have
     // [TreatNullAs=EmptyString] and should not be nullable.
-    [RaisesException] void setProperty(DOMString property, DOMString? value, optional DOMString? priority = null);
+    [CEReactions, RaisesException] void setProperty(DOMString property, DOMString? value, optional DOMString? priority = null);
     // void setPropertyValue(DOMString property, [TreatNullAs=EmptyString] DOMString value);
     // void setPropertyPriority(DOMString property, [TreatNullAs=EmptyString] DOMString priority);
-    [RaisesException] DOMString removeProperty(DOMString property);
+    [CEReactions, RaisesException] DOMString removeProperty(DOMString property);
     readonly attribute CSSRule? parentRule;
-    [RaisesException=Setter, TreatNullAs=EmptyString] attribute DOMString cssFloat;
+    [CEReactions, RaisesException=Setter, TreatNullAs=EmptyString] attribute DOMString cssFloat;
 
     // The camel-cased and dashed attribute getters have custom bindings.
     // http://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-camel-cased-attribute
diff --git a/third_party/WebKit/Source/core/css/CSSURIValue.cpp b/third_party/WebKit/Source/core/css/CSSURIValue.cpp
index b9a388f..c885a02 100644
--- a/third_party/WebKit/Source/core/css/CSSURIValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSURIValue.cpp
@@ -5,21 +5,49 @@
 #include "core/css/CSSURIValue.h"
 
 #include "core/css/CSSMarkup.h"
+#include "core/dom/Document.h"
+#include "core/fetch/FetchInitiatorTypeNames.h"
+#include "core/fetch/FetchRequest.h"
+#include "core/fetch/ResourceFetcher.h"
 #include "wtf/text/WTFString.h"
 
 namespace blink {
 
-CSSURIValue::CSSURIValue(const String& str)
+CSSURIValue::CSSURIValue(const String& urlString)
     : CSSValue(URIClass)
-    , m_string(str) { }
+    , m_url(urlString)
+    , m_loadRequested(false)
+{
+}
+
+CSSURIValue::~CSSURIValue()
+{
+}
+
+DocumentResource* CSSURIValue::load(Document& document) const
+{
+    if (!m_loadRequested) {
+        m_loadRequested = true;
+
+        FetchRequest request(ResourceRequest(document.completeURL(m_url)), FetchInitiatorTypeNames::css);
+        m_document = DocumentResource::fetchSVGDocument(request, document.fetcher());
+    }
+    return m_document;
+}
 
 String CSSURIValue::customCSSText() const
 {
-    return serializeURI(m_string);
+    return serializeURI(m_url);
+}
+
+bool CSSURIValue::equals(const CSSURIValue& other) const
+{
+    return m_url == other.m_url;
 }
 
 DEFINE_TRACE_AFTER_DISPATCH(CSSURIValue)
 {
+    visitor->trace(m_document);
     CSSValue::traceAfterDispatch(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSURIValue.h b/third_party/WebKit/Source/core/css/CSSURIValue.h
index c647160..acd783d 100644
--- a/third_party/WebKit/Source/core/css/CSSURIValue.h
+++ b/third_party/WebKit/Source/core/css/CSSURIValue.h
@@ -6,31 +6,41 @@
 #define CSSURIValue_h
 
 #include "core/css/CSSValue.h"
+#include "core/fetch/DocumentResource.h"
 
 namespace blink {
 
+class Document;
+
 class CSSURIValue : public CSSValue {
 public:
     static CSSURIValue* create(const String& str)
     {
         return new CSSURIValue(str);
     }
+    ~CSSURIValue();
 
-    String value() const { return m_string; }
+    DocumentResource* cachedDocument() const { return m_document; }
+    DocumentResource* load(Document&) const;
+
+    const String& value() const { return m_url; }
+    const String& url() const { return m_url; }
 
     String customCSSText() const;
 
-    bool equals(const CSSURIValue& other) const
-    {
-        return m_string == other.m_string;
-    }
+    bool loadRequested() const { return m_loadRequested; }
+    bool equals(const CSSURIValue&) const;
 
     DECLARE_TRACE_AFTER_DISPATCH();
 
 private:
     CSSURIValue(const String&);
 
-    String m_string;
+    String m_url;
+
+    // Document cache.
+    mutable Member<DocumentResource> m_document;
+    mutable bool m_loadRequested;
 };
 
 DEFINE_CSS_VALUE_TYPE_CASTS(CSSURIValue, isURIValue());
diff --git a/third_party/WebKit/Source/core/css/CSSValue.cpp b/third_party/WebKit/Source/core/css/CSSValue.cpp
index d2c1e07..d0a7b501 100644
--- a/third_party/WebKit/Source/core/css/CSSValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSValue.cpp
@@ -53,7 +53,6 @@
 #include "core/css/CSSPrimitiveValue.h"
 #include "core/css/CSSQuadValue.h"
 #include "core/css/CSSReflectValue.h"
-#include "core/css/CSSSVGDocumentValue.h"
 #include "core/css/CSSShadowValue.h"
 #include "core/css/CSSStringValue.h"
 #include "core/css/CSSTimingFunctionValue.h"
@@ -177,8 +176,6 @@
             return compareCSSValues<CSSValuePair>(*this, other);
         case ImageSetClass:
             return compareCSSValues<CSSImageSetValue>(*this, other);
-        case CSSSVGDocumentClass:
-            return compareCSSValues<CSSSVGDocumentValue>(*this, other);
         case CSSContentDistributionClass:
             return compareCSSValues<CSSContentDistributionValue>(*this, other);
         case CustomPropertyDeclarationClass:
@@ -271,8 +268,6 @@
         return toCSSValueList(this)->customCSSText();
     case ImageSetClass:
         return toCSSImageSetValue(this)->customCSSText();
-    case CSSSVGDocumentClass:
-        return toCSSSVGDocumentValue(this)->customCSSText();
     case CSSContentDistributionClass:
         return toCSSContentDistributionValue(this)->customCSSText();
     case VariableReferenceClass:
@@ -400,9 +395,6 @@
     case ImageSetClass:
         delete toCSSImageSetValue(this);
         return;
-    case CSSSVGDocumentClass:
-        delete toCSSSVGDocumentValue(this);
-        return;
     case CSSContentDistributionClass:
         delete toCSSContentDistributionValue(this);
         return;
@@ -533,9 +525,6 @@
     case ImageSetClass:
         toCSSImageSetValue(this)->~CSSImageSetValue();
         return;
-    case CSSSVGDocumentClass:
-        toCSSSVGDocumentValue(this)->~CSSSVGDocumentValue();
-        return;
     case CSSContentDistributionClass:
         toCSSContentDistributionValue(this)->~CSSContentDistributionValue();
         return;
@@ -666,9 +655,6 @@
     case ImageSetClass:
         toCSSImageSetValue(this)->traceAfterDispatch(visitor);
         return;
-    case CSSSVGDocumentClass:
-        toCSSSVGDocumentValue(this)->traceAfterDispatch(visitor);
-        return;
     case CSSContentDistributionClass:
         toCSSContentDistributionValue(this)->traceAfterDispatch(visitor);
         return;
diff --git a/third_party/WebKit/Source/core/css/CSSValue.h b/third_party/WebKit/Source/core/css/CSSValue.h
index 25b465e..b529e27 100644
--- a/third_party/WebKit/Source/core/css/CSSValue.h
+++ b/third_party/WebKit/Source/core/css/CSSValue.h
@@ -91,7 +91,6 @@
     bool isCubicBezierTimingFunctionValue() const { return m_classType == CubicBezierTimingFunctionClass; }
     bool isStepsTimingFunctionValue() const { return m_classType == StepsTimingFunctionClass; }
     bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; }
-    bool isSVGDocumentValue() const { return m_classType == CSSSVGDocumentClass; }
     bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; }
     bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
     bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; }
@@ -166,9 +165,6 @@
         CustomPropertyDeclarationClass,
         PendingSubstitutionValueClass,
 
-        // SVG classes.
-        CSSSVGDocumentClass,
-
         CSSContentDistributionClass,
 
         // List class types must appear after ValueListClass.
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index d6d2f3e..735bca6 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -823,6 +823,16 @@
         list.append(*lineNames);
 }
 
+static CSSValue* valueForGridTrackSizeList(GridTrackSizingDirection direction, const ComputedStyle& style)
+{
+    const Vector<GridTrackSize>& autoTrackSizes = direction == ForColumns ? style.gridAutoColumns() : style.gridAutoRows();
+
+    CSSValueList* list = CSSValueList::createSpaceSeparated();
+    for (auto& trackSize : autoTrackSizes)
+        list->append(*specifiedValueForGridTrackSize(trackSize, style));
+    return list;
+}
+
 static CSSValue* valueForGridTrackList(GridTrackSizingDirection direction, const LayoutObject* layoutObject, const ComputedStyle& style)
 {
     bool isRowAxis = direction == ForColumns;
@@ -1972,14 +1982,14 @@
         return list;
     }
     // Specs mention that getComputedStyle() should return the used value of the property instead of the computed
-    // one for grid-definition-{rows|columns} but not for the grid-auto-{rows|columns} as things like
+    // one for grid-template-{rows|columns} but not for the grid-auto-{rows|columns} as things like
     // grid-auto-columns: 2fr; cannot be resolved to a value in pixels as the '2fr' means very different things
     // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See
     // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html
     case CSSPropertyGridAutoColumns:
-        return specifiedValueForGridTrackSize(style.gridAutoColumns(), style);
+        return valueForGridTrackSizeList(ForColumns, style);
     case CSSPropertyGridAutoRows:
-        return specifiedValueForGridTrackSize(style.gridAutoRows(), style);
+        return valueForGridTrackSizeList(ForRows, style);
 
     case CSSPropertyGridTemplateColumns:
         return valueForGridTrackList(ForColumns, layoutObject, style);
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
index a2ce7517..fa07350 100644
--- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
+++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -34,6 +34,8 @@
 #include "core/dom/MutationRecord.h"
 #include "core/dom/StyleChangeReason.h"
 #include "core/dom/StyleEngine.h"
+#include "core/dom/custom/CustomElement.h"
+#include "core/dom/custom/CustomElementDefinition.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
@@ -41,6 +43,13 @@
 
 namespace {
 
+static CustomElementDefinition* definitionIfStyleChangedCallback(Element* element)
+{
+    CustomElementDefinition* definition = CustomElement::definitionForElement(element);
+    return definition && definition->hasStyleAttributeChangedCallback()
+        ? definition : nullptr;
+}
+
 class StyleAttributeMutationScope {
     WTF_MAKE_NONCOPYABLE(StyleAttributeMutationScope);
     STACK_ALLOCATED();
@@ -60,18 +69,16 @@
         if (!s_currentDecl->parentElement())
             return;
 
-        bool shouldReadOldValue = false;
-
         m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(*s_currentDecl->parentElement(), HTMLNames::styleAttr);
-        if (m_mutationRecipients && m_mutationRecipients->isOldValueRequested())
-            shouldReadOldValue = true;
+        bool shouldReadOldValue =
+            (m_mutationRecipients && m_mutationRecipients->isOldValueRequested())
+            || definitionIfStyleChangedCallback(s_currentDecl->parentElement());
 
-        AtomicString oldValue;
         if (shouldReadOldValue)
-            oldValue = s_currentDecl->parentElement()->getAttribute(HTMLNames::styleAttr);
+            m_oldValue = s_currentDecl->parentElement()->getAttribute(HTMLNames::styleAttr);
 
         if (m_mutationRecipients) {
-            AtomicString requestedOldValue = m_mutationRecipients->isOldValueRequested() ? oldValue : nullAtom;
+            AtomicString requestedOldValue = m_mutationRecipients->isOldValueRequested() ? m_oldValue : nullAtom;
             m_mutation = MutationRecord::createAttributes(s_currentDecl->parentElement(), HTMLNames::styleAttr, requestedOldValue);
         }
     }
@@ -82,10 +89,19 @@
         if (s_scopeCount)
             return;
 
-        if (m_mutation && s_shouldDeliver)
-            m_mutationRecipients->enqueueMutationRecord(m_mutation);
+        if (s_shouldDeliver) {
+            if (m_mutation)
+                m_mutationRecipients->enqueueMutationRecord(m_mutation);
 
-        s_shouldDeliver = false;
+            Element* element = s_currentDecl->parentElement();
+            if (CustomElementDefinition* definition = definitionIfStyleChangedCallback(element)) {
+                definition->enqueueAttributeChangedCallback(element,
+                    HTMLNames::styleAttr, m_oldValue,
+                    element->getAttribute(HTMLNames::styleAttr));
+            }
+
+            s_shouldDeliver = false;
+        }
 
         // We have to clear internal state before calling Inspector's code.
         AbstractPropertySetCSSStyleDeclaration* localCopyStyleDecl = s_currentDecl;
@@ -117,6 +133,7 @@
 
     Member<MutationObserverInterestGroup> m_mutationRecipients;
     Member<MutationRecord> m_mutation;
+    AtomicString m_oldValue;
 };
 
 unsigned StyleAttributeMutationScope::s_scopeCount = 0;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 6a5ef8dd..79d287d 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -29,7 +29,6 @@
 #include "core/css/CSSPrimitiveValueMappings.h"
 #include "core/css/CSSQuadValue.h"
 #include "core/css/CSSReflectValue.h"
-#include "core/css/CSSSVGDocumentValue.h"
 #include "core/css/CSSShadowValue.h"
 #include "core/css/CSSStringValue.h"
 #include "core/css/CSSTimingFunctionValue.h"
@@ -1458,10 +1457,9 @@
     CSSValueList* list = CSSValueList::createSpaceSeparated();
     do {
         String url = consumeUrl(range);
-        CSSFunctionValue* filterValue = nullptr;
+        CSSValue* filterValue = nullptr;
         if (!url.isNull()) {
-            filterValue = CSSFunctionValue::create(CSSValueUrl);
-            filterValue->append(*CSSSVGDocumentValue::create(url));
+            filterValue = CSSURIValue::create(url);
         } else {
             filterValue = consumeFilterFunction(range, context);
             if (!filterValue)
@@ -3476,13 +3474,20 @@
     return true;
 }
 
-static CSSValue* consumeGridTrackList(CSSParserTokenRange& range, CSSParserMode cssParserMode, bool allowRepeat = true)
+enum TrackListType { GridTemplate, GridTemplateNoRepeat, GridAuto };
+
+static CSSValue* consumeGridTrackList(CSSParserTokenRange& range, CSSParserMode cssParserMode, TrackListType trackListType)
 {
+    bool allowGridLineNames = trackListType != GridAuto;
     CSSValueList* values = CSSValueList::createSpaceSeparated();
     CSSGridLineNamesValue* lineNames = consumeGridLineNames(range);
-    if (lineNames)
+    if (lineNames) {
+        if (!allowGridLineNames)
+            return nullptr;
         values->append(*lineNames);
+    }
 
+    bool allowRepeat = trackListType == GridTemplate;
     bool seenAutoRepeat = false;
     bool allTracksAreFixedSized = true;
     do {
@@ -3505,8 +3510,11 @@
         if (seenAutoRepeat && !allTracksAreFixedSized)
             return nullptr;
         lineNames = consumeGridLineNames(range);
-        if (lineNames)
+        if (lineNames) {
+            if (!allowGridLineNames)
+                return nullptr;
             values->append(*lineNames);
+        }
     } while (!range.atEnd() && range.peek().type() != DelimiterToken);
     return values;
 }
@@ -3515,7 +3523,7 @@
 {
     if (range.peek().id() == CSSValueNone)
         return consumeIdent(range);
-    return consumeGridTrackList(range, cssParserMode);
+    return consumeGridTrackList(range, cssParserMode, GridTemplate);
 }
 
 static CSSValue* consumeGridTemplateAreas(CSSParserTokenRange& range)
@@ -3952,7 +3960,7 @@
     case CSSPropertyGridAutoColumns:
     case CSSPropertyGridAutoRows:
         ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
-        return consumeGridTrackSize(m_range, m_context.mode());
+        return consumeGridTrackList(m_range, m_context.mode(), GridAuto);
     case CSSPropertyGridTemplateColumns:
     case CSSPropertyGridTemplateRows:
         ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
@@ -4879,7 +4887,7 @@
     if (!m_range.atEnd()) {
         if (!consumeSlashIncludingWhitespace(m_range))
             return false;
-        columnsValue = consumeGridTrackList(m_range, m_context.mode(), false);
+        columnsValue = consumeGridTrackList(m_range, m_context.mode(), GridTemplateNoRepeat);
         if (!columnsValue || !m_range.atEnd())
             return false;
     } else {
@@ -4909,7 +4917,7 @@
 
     // 2- <grid-template-rows> / <grid-template-columns>
     if (!rowsValue)
-        rowsValue = consumeGridTrackList(m_range, m_context.mode());
+        rowsValue = consumeGridTrackList(m_range, m_context.mode(), GridTemplate);
 
     if (rowsValue) {
         if (!consumeSlashIncludingWhitespace(m_range))
@@ -4959,11 +4967,11 @@
     CSSValue* autoRowsValue = nullptr;
 
     if (!m_range.atEnd()) {
-        autoRowsValue = consumeGridTrackSize(m_range, m_context.mode());
+        autoRowsValue = consumeGridTrackList(m_range, m_context.mode(), GridAuto);
         if (!autoRowsValue)
             return false;
         if (consumeSlashIncludingWhitespace(m_range)) {
-            autoColumnsValue = consumeGridTrackSize(m_range, m_context.mode());
+            autoColumnsValue = consumeGridTrackList(m_range, m_context.mode(), GridAuto);
             if (!autoColumnsValue)
                 return false;
         }
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
index 99c5fe68..7b9538b 100644
--- a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
@@ -26,7 +26,7 @@
 #include "core/css/CSSCursorImageValue.h"
 #include "core/css/CSSGradientValue.h"
 #include "core/css/CSSImageValue.h"
-#include "core/css/CSSSVGDocumentValue.h"
+#include "core/css/CSSURIValue.h"
 #include "core/dom/Document.h"
 #include "core/fetch/ResourceFetcher.h"
 #include "core/layout/svg/ReferenceFilterBuilder.h"
@@ -104,9 +104,9 @@
     return value.cachedImage(m_deviceScaleFactor);
 }
 
-void ElementStyleResources::addPendingSVGDocument(FilterOperation* filterOperation, const CSSSVGDocumentValue* cssSVGDocumentValue)
+void ElementStyleResources::addPendingSVGDocument(FilterOperation* filterOperation, const CSSURIValue* cssUriValue)
 {
-    m_pendingSVGDocuments.set(filterOperation, cssSVGDocumentValue);
+    m_pendingSVGDocuments.set(filterOperation, cssUriValue);
 }
 
 void ElementStyleResources::loadPendingSVGDocuments(ComputedStyle* computedStyle)
@@ -120,10 +120,10 @@
         if (filterOperation->type() == FilterOperation::REFERENCE) {
             ReferenceFilterOperation* referenceFilter = toReferenceFilterOperation(filterOperation);
 
-            const CSSSVGDocumentValue* value = m_pendingSVGDocuments.get(referenceFilter);
+            const CSSURIValue* value = m_pendingSVGDocuments.get(referenceFilter);
             if (!value)
                 continue;
-            DocumentResource* resource = value->load(m_document);
+            DocumentResource* resource = value->load(*m_document);
             if (!resource)
                 continue;
 
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
index 355e8aa..876d4bb 100644
--- a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
+++ b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
@@ -37,7 +37,7 @@
 class CSSImageGeneratorValue;
 class CSSImageSetValue;
 class CSSImageValue;
-class CSSSVGDocumentValue;
+class CSSURIValue;
 class CSSValue;
 class ComputedStyle;
 class Document;
@@ -59,7 +59,7 @@
 
     void loadPendingResources(ComputedStyle*);
 
-    void addPendingSVGDocument(FilterOperation*, const CSSSVGDocumentValue*);
+    void addPendingSVGDocument(FilterOperation*, const CSSURIValue*);
 
 private:
     StyleImage* cursorOrPendingFromValue(CSSPropertyID, const CSSCursorImageValue&);
@@ -72,7 +72,7 @@
 
     Member<Document> m_document;
     HashSet<CSSPropertyID> m_pendingImageProperties;
-    HeapHashMap<Member<FilterOperation>, Member<const CSSSVGDocumentValue>> m_pendingSVGDocuments;
+    HeapHashMap<Member<FilterOperation>, Member<const CSSURIValue>> m_pendingSVGDocuments;
     float m_deviceScaleFactor;
 };
 
diff --git a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
index d41a8cf..ade3260 100644
--- a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
@@ -31,17 +31,17 @@
 #include "core/css/CSSFunctionValue.h"
 #include "core/css/CSSPrimitiveValueMappings.h"
 #include "core/css/CSSShadowValue.h"
+#include "core/css/CSSURIValue.h"
 #include "core/css/resolver/StyleResolverState.h"
 #include "core/frame/UseCounter.h"
 #include "core/layout/svg/ReferenceFilterBuilder.h"
+#include "core/svg/SVGURIReference.h"
 
 namespace blink {
 
 FilterOperation::OperationType FilterOperationResolver::filterOperationForType(CSSValueID type)
 {
     switch (type) {
-    case CSSValueUrl:
-        return FilterOperation::REFERENCE;
     case CSSValueGrayscale:
         return FilterOperation::GRAYSCALE;
     case CSSValueSepia:
@@ -127,26 +127,27 @@
 
     const CSSToLengthConversionData& conversionData = state.cssToLengthConversionData();
     for (auto& currValue : toCSSValueList(inValue)) {
-        const CSSFunctionValue* filterValue = toCSSFunctionValue(currValue.get());
-        FilterOperation::OperationType operationType = filterOperationForType(filterValue->functionType());
-        countFilterUse(operationType, state.document());
-        ASSERT(filterValue->length() <= 1);
+        if (currValue->isURIValue()) {
+            countFilterUse(FilterOperation::REFERENCE, state.document());
 
-        if (operationType == FilterOperation::REFERENCE) {
-            const CSSSVGDocumentValue& svgDocumentValue = toCSSSVGDocumentValue(filterValue->item(0));
-            KURL url = state.document().completeURL(svgDocumentValue.url());
-
-            ReferenceFilterOperation* operation = ReferenceFilterOperation::create(svgDocumentValue.url(), AtomicString(url.fragmentIdentifier()));
-            if (!equalIgnoringFragmentIdentifier(url, state.document().url())) {
-                if (!svgDocumentValue.loadRequested())
-                    state.elementStyleResources().addPendingSVGDocument(operation, &svgDocumentValue);
-                else if (svgDocumentValue.cachedSVGDocument())
-                    ReferenceFilterBuilder::setDocumentResourceReference(operation, new DocumentResourceReference(svgDocumentValue.cachedSVGDocument()));
+            const CSSURIValue& urlValue = toCSSURIValue(*currValue);
+            SVGURLReferenceResolver resolver(urlValue.value(), state.document());
+            ReferenceFilterOperation* operation = ReferenceFilterOperation::create(urlValue.value(), resolver.fragmentIdentifier());
+            if (!resolver.isLocal()) {
+                if (!urlValue.loadRequested())
+                    state.elementStyleResources().addPendingSVGDocument(operation, &urlValue);
+                else if (urlValue.cachedDocument())
+                    ReferenceFilterBuilder::setDocumentResourceReference(operation, new DocumentResourceReference(urlValue.cachedDocument()));
             }
             operations.operations().append(operation);
             continue;
         }
 
+        const CSSFunctionValue* filterValue = toCSSFunctionValue(currValue.get());
+        FilterOperation::OperationType operationType = filterOperationForType(filterValue->functionType());
+        countFilterUse(operationType, state.document());
+        DCHECK_LE(filterValue->length(), 1u);
+
         const CSSPrimitiveValue* firstValue = filterValue->length() && filterValue->item(0).isPrimitiveValue() ? &toCSSPrimitiveValue(filterValue->item(0)) : nullptr;
         switch (filterValue->functionType()) {
         case CSSValueGrayscale:
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index bd5c532c..f5fd517e 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -123,10 +123,14 @@
     if (value.isBasicShapeValue())
         return ShapeClipPathOperation::create(basicShapeForValue(state, value));
     if (value.isURIValue()) {
-        String cssURLValue = toCSSURIValue(value).value();
-        KURL url = state.document().completeURL(cssURLValue);
+        SVGURLReferenceResolver resolver(toCSSURIValue(value).value(), state.document());
+        // If the reference is non-local, then the fragment will remain as a
+        // null string, which makes the element lookup fail.
+        AtomicString fragmentIdentifier;
+        if (resolver.isLocal())
+            fragmentIdentifier = resolver.fragmentIdentifier();
         // TODO(fs): Doesn't work with forward or external SVG references (crbug.com/391604, crbug.com/109212, ...)
-        return ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier()));
+        return ReferenceClipPathOperation::create(toCSSURIValue(value).value(), fragmentIdentifier);
     }
     DCHECK(value.isPrimitiveValue() && toCSSPrimitiveValue(value).getValueID() == CSSValueNone);
     return nullptr;
@@ -555,6 +559,18 @@
     }
 }
 
+Vector<GridTrackSize> StyleBuilderConverter::convertGridTrackSizeList(StyleResolverState& state, const CSSValue& value)
+{
+    DCHECK(value.isValueList());
+    Vector<GridTrackSize> trackSizes;
+    for (auto& currValue : toCSSValueList(value)) {
+        DCHECK(!currValue->isGridLineNamesValue());
+        DCHECK(!currValue->isGridAutoRepeatValue());
+        trackSizes.append(convertGridTrackSize(state, *currValue));
+    }
+    return trackSizes;
+}
+
 void StyleBuilderConverter::convertGridTrackList(const CSSValue& value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, OrderedNamedGridLines& orderedNamedGridLines, Vector<GridTrackSize>& autoRepeatTrackSizes, NamedGridLinesMap& autoRepeatNamedGridLines, OrderedNamedGridLines& autoRepeatOrderedNamedGridLines, size_t& autoRepeatInsertionPoint, AutoRepeatType &autoRepeatType, StyleResolverState& state)
 {
     if (value.isPrimitiveValue()) {
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
index d10c16c..2258951 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
@@ -77,6 +77,7 @@
     static GridAutoFlow convertGridAutoFlow(StyleResolverState&, const CSSValue&);
     static GridPosition convertGridPosition(StyleResolverState&, const CSSValue&);
     static GridTrackSize convertGridTrackSize(StyleResolverState&, const CSSValue&);
+    static Vector<GridTrackSize> convertGridTrackSizeList(StyleResolverState&, const CSSValue&);
     template <typename T> static T convertLineWidth(StyleResolverState&, const CSSValue&);
     static Length convertLength(const StyleResolverState&, const CSSValue&);
     static UnzoomedLength convertUnzoomedLength(const StyleResolverState&, const CSSValue&);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
index 53ac115..9120985 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
@@ -26,7 +26,6 @@
 #include "core/CoreExport.h"
 #include "core/animation/css/CSSAnimationUpdate.h"
 #include "core/css/CSSPendingSubstitutionValue.h"
-#include "core/css/CSSSVGDocumentValue.h"
 #include "core/css/CSSToLengthConversionData.h"
 #include "core/css/resolver/CSSToStyleMap.h"
 #include "core/css/resolver/ElementResolveContext.h"
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 97f556b..01d8cf82 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -447,7 +447,7 @@
     , m_compositorPendingAnimations(new CompositorPendingAnimations())
     , m_templateDocumentHost(nullptr)
     , m_didAssociateFormControlsTimer(this, &Document::didAssociateFormControlsTimerFired)
-    , m_timers(TaskRunnerHelper::getTimerTaskRunner(this)->adoptClone())
+    , m_timers(TaskRunnerHelper::getTimerTaskRunner(this)->clone())
     , m_hasViewportUnits(false)
     , m_parserSyncPolicy(AllowAsynchronousParsing)
     , m_nodeCount(0)
@@ -2232,7 +2232,7 @@
     }
 
     m_timers.setTimerTaskRunner(
-        Platform::current()->currentThread()->scheduler()->timerTaskRunner()->adoptClone());
+        Platform::current()->currentThread()->scheduler()->timerTaskRunner()->clone());
 
     // This is required, as our LocalFrame might delete itself as soon as it detaches
     // us. However, this violates Node::detach() semantics, as it's never
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index fec04be5..955634a4 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -539,16 +539,18 @@
 static bool hasEditableStyle(const Node&, EditableLevel);
 static bool isEditableToAccessibility(const Node&, EditableLevel);
 
-bool Node::isContentEditable() const
+// TODO(yoichio): Move to core/editing
+bool isContentEditable(const Node& node)
 {
-    document().updateStyleAndLayoutTree();
-    return blink::hasEditableStyle(*this, Editable);
+    node.document().updateStyleAndLayoutTree();
+    return blink::hasEditableStyle(node, Editable);
 }
 
-bool Node::isContentRichlyEditable() const
+// TODO(yoichio): Move to core/editing
+bool isContentRichlyEditable(const Node& node)
 {
-    document().updateStyleAndLayoutTree();
-    return blink::hasEditableStyle(*this, RichlyEditable);
+    node.document().updateStyleAndLayoutTree();
+    return blink::hasEditableStyle(node, RichlyEditable);
 }
 
 // TODO(yoichio): Move to core/editing
@@ -2237,7 +2239,7 @@
 {
     if (isDisabledFormControl(this))
         return false;
-    return isContentEditable() || hasEventListeners(EventTypeNames::mouseup) || hasEventListeners(EventTypeNames::mousedown) || hasEventListeners(EventTypeNames::click) || hasEventListeners(EventTypeNames::DOMActivate);
+    return isContentEditable(*this) || hasEventListeners(EventTypeNames::mouseup) || hasEventListeners(EventTypeNames::mousedown) || hasEventListeners(EventTypeNames::click) || hasEventListeners(EventTypeNames::DOMActivate);
 }
 
 bool Node::willRespondToTouchEvents()
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index addb538..b63afa0 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -416,9 +416,6 @@
     // must be recognized as inert to prevent text selection.
     bool isInert() const;
 
-    bool isContentEditable() const;
-    bool isContentRichlyEditable() const;
-
     virtual LayoutRect boundingBox() const;
     IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); }
 
@@ -863,6 +860,8 @@
 CORE_EXPORT Element* rootEditableElement(const Node&, EditableType);
 CORE_EXPORT bool hasEditableStyle(const Node&, EditableType = ContentIsEditable);
 CORE_EXPORT bool layoutObjectIsRichlyEditable(const Node&, EditableType = ContentIsEditable);
+CORE_EXPORT bool isContentEditable(const Node&);
+CORE_EXPORT bool isContentRichlyEditable(const Node&);
 
 // Allow equality comparisons of Nodes by reference or pointer, interchangeably.
 DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES_REFCOUNTED(Node)
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
index 1e36ebb..f601b79e1 100644
--- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -192,7 +192,6 @@
         return;
 
     TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document;
-    DCHECK(isStyleElement(*node) || treeScope == m_document);
     DCHECK(!isXSLStyleSheet(*node));
     TreeScopeStyleSheetCollection* collection = ensureStyleSheetCollectionFor(treeScope);
     DCHECK(collection);
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
index 16d712fb..1156806d 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
@@ -32,13 +32,21 @@
     return nullptr;
 }
 
-CustomElementDefinition* CustomElement::definitionForElement(const Element& element)
+static CustomElementDefinition* definitionForElementWithoutCheck(const Element& element)
 {
+    DCHECK_EQ(element.getCustomElementState(), CustomElementState::Custom);
     if (CustomElementsRegistry* registry = CustomElement::registry(element))
         return registry->definitionForName(element.localName());
     return nullptr;
 }
 
+CustomElementDefinition* CustomElement::definitionForElement(const Element* element)
+{
+    if (!element || element->getCustomElementState() != CustomElementState::Custom)
+        return nullptr;
+    return definitionForElementWithoutCheck(*element);
+}
+
 bool CustomElement::isValidName(const AtomicString& name)
 {
     if (!name.length() || name[0] < 'a' || name[0] > 'z')
@@ -180,16 +188,14 @@
 
 void CustomElement::enqueueConnectedCallback(Element* element)
 {
-    DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom);
-    CustomElementDefinition* definition = definitionForElement(*element);
+    CustomElementDefinition* definition = definitionForElementWithoutCheck(*element);
     if (definition->hasConnectedCallback())
         definition->enqueueConnectedCallback(element);
 }
 
 void CustomElement::enqueueDisconnectedCallback(Element* element)
 {
-    DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom);
-    CustomElementDefinition* definition = definitionForElement(*element);
+    CustomElementDefinition* definition = definitionForElementWithoutCheck(*element);
     if (definition->hasDisconnectedCallback())
         definition->enqueueDisconnectedCallback(element);
 }
@@ -199,8 +205,7 @@
     const QualifiedName& name,
     const AtomicString& oldValue, const AtomicString& newValue)
 {
-    DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom);
-    CustomElementDefinition* definition = definitionForElement(*element);
+    CustomElementDefinition* definition = definitionForElementWithoutCheck(*element);
     if (definition->hasAttributeChangedCallback(name))
         definition->enqueueAttributeChangedCallback(element, name, oldValue, newValue);
 }
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElement.h b/third_party/WebKit/Source/core/dom/custom/CustomElement.h
index 8ab8feb..6465570 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElement.h
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElement.h
@@ -30,7 +30,7 @@
     static CustomElementsRegistry* registry(const Element&);
     static CustomElementsRegistry* registry(const Document&);
 
-    static CustomElementDefinition* definitionForElement(const Element&);
+    static CustomElementDefinition* definitionForElement(const Element*);
 
     static bool isValidName(const AtomicString& name);
 
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.cpp
index e0567a9..b5666d5 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.cpp
@@ -24,8 +24,10 @@
 CustomElementDefinition::CustomElementDefinition(
     const CustomElementDescriptor& descriptor,
     const HashSet<AtomicString>& observedAttributes)
-    : m_observedAttributes(observedAttributes)
-    , m_descriptor(descriptor)
+    : m_descriptor(descriptor)
+    , m_observedAttributes(observedAttributes)
+    , m_hasStyleAttributeChangedCallback(
+        observedAttributes.contains(HTMLNames::styleAttr.localName()))
 {
 }
 
@@ -127,11 +129,16 @@
 }
 
 bool CustomElementDefinition::hasAttributeChangedCallback(
-    const QualifiedName& name)
+    const QualifiedName& name) const
 {
     return m_observedAttributes.contains(name.localName());
 }
 
+bool CustomElementDefinition::hasStyleAttributeChangedCallback() const
+{
+    return m_hasStyleAttributeChangedCallback;
+}
+
 void CustomElementDefinition::enqueueUpgradeReaction(Element* element)
 {
     CustomElement::enqueue(element,
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.h b/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.h
index a1db45a..eead3c5 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.h
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementDefinition.h
@@ -56,7 +56,8 @@
 
     virtual bool hasConnectedCallback() const = 0;
     virtual bool hasDisconnectedCallback() const = 0;
-    bool hasAttributeChangedCallback(const QualifiedName&);
+    bool hasAttributeChangedCallback(const QualifiedName&) const;
+    bool hasStyleAttributeChangedCallback() const;
 
     virtual void runConnectedCallback(Element*) = 0;
     virtual void runDisconnectedCallback(Element*) = 0;
@@ -74,11 +75,11 @@
 
     static void checkConstructorResult(Element*, Document&, const QualifiedName&, ExceptionState&);
 
-    HashSet<AtomicString> m_observedAttributes;
-
 private:
     const CustomElementDescriptor m_descriptor;
     ConstructionStack m_constructionStack;
+    HashSet<AtomicString> m_observedAttributes;
+    bool m_hasStyleAttributeChangedCallback;
 
     void enqueueAttributeChangedCallbackForAllAttributes(Element*);
 };
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistryTest.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistryTest.cpp
index 17467d0b..0f50fdf 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistryTest.cpp
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistryTest.cpp
@@ -231,6 +231,12 @@
     {
     }
 
+    TestCustomElementDefinition(const CustomElementDescriptor& descriptor,
+        const HashSet<AtomicString>& observedAttributes)
+        : CustomElementDefinition(descriptor, observedAttributes)
+    {
+    }
+
     ~TestCustomElementDefinition() override = default;
 
     ScriptValue getConstructorForScript() override
@@ -265,11 +271,12 @@
     WTF_MAKE_NONCOPYABLE(LogUpgradeDefinition);
 public:
     LogUpgradeDefinition(const CustomElementDescriptor& descriptor)
-        : TestCustomElementDefinition(descriptor)
+        : TestCustomElementDefinition(descriptor, {
+            "attr1",
+            "attr2",
+            HTMLNames::contenteditableAttr.localName(),
+        })
     {
-        m_observedAttributes.add("attr1");
-        m_observedAttributes.add("attr2");
-        m_observedAttributes.add(HTMLNames::contenteditableAttr.localName());
     }
 
     DEFINE_INLINE_VIRTUAL_TRACE()
diff --git a/third_party/WebKit/Source/core/editing/CaretBase.cpp b/third_party/WebKit/Source/core/editing/CaretBase.cpp
index 5759cdb..e8f3697 100644
--- a/third_party/WebKit/Source/core/editing/CaretBase.cpp
+++ b/third_party/WebKit/Source/core/editing/CaretBase.cpp
@@ -166,7 +166,7 @@
     // If PositionAnchorType::BeforeAnchor or PositionAnchorType::AfterAnchor,
     // carets need to be repainted not only when the node is contentEditable but
     // also when its parentNode() is contentEditable.
-    return node.isContentEditable() || (node.parentNode() && node.parentNode()->isContentEditable());
+    return isContentEditable(node) || (node.parentNode() && isContentEditable(*node.parentNode()));
 }
 
 bool CaretBase::shouldRepaintCaret(const LayoutViewItem view) const
@@ -185,7 +185,7 @@
         return;
 
     if (LayoutViewItem view = node->document().layoutViewItem()) {
-        if (node->isContentEditable() || shouldRepaintCaret(view))
+        if (isContentEditable(*node) || shouldRepaintCaret(view))
             invalidateLocalCaretRect(node, localCaretRectWithoutUpdate());
     }
 }
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index c1e68547..c6dff69a 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -583,7 +583,7 @@
         return false;
 
     Node* innerNode = hitTestResult.innerNode();
-    bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->canStartSelection());
+    bool innerNodeIsSelectable = innerNode && (isContentEditable(*innerNode) || innerNode->canStartSelection());
     if (!innerNodeIsSelectable)
         return false;
 
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index 017aa6fc..411ce6c 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1476,80 +1476,84 @@
 }
 
 template <typename Strategy>
-VisiblePositionTemplate<Strategy> startOfParagraphAlgorithm(const VisiblePositionTemplate<Strategy>& c, EditingBoundaryCrossingRule boundaryCrossingRule)
+PositionTemplate<Strategy> startOfParagraphAlgorithm(const PositionTemplate<Strategy>& position, EditingBoundaryCrossingRule boundaryCrossingRule)
 {
-    const PositionTemplate<Strategy> p = c.deepEquivalent();
-    Node* startNode = p.anchorNode();
+    Node* const startNode = position.anchorNode();
 
     if (!startNode)
-        return VisiblePositionTemplate<Strategy>();
+        return PositionTemplate<Strategy>();
 
     if (isRenderedAsNonInlineTableImageOrHR(startNode))
-        return createVisiblePosition(PositionTemplate<Strategy>::beforeNode(startNode));
+        return PositionTemplate<Strategy>::beforeNode(startNode);
 
-    Element* startBlock = enclosingBlock(PositionTemplate<Strategy>::firstPositionInOrBeforeNode(startNode), CannotCrossEditingBoundary);
+    Element* const startBlock = enclosingBlock(PositionTemplate<Strategy>::firstPositionInOrBeforeNode(startNode), CannotCrossEditingBoundary);
+    ContainerNode* const highestRoot = highestEditableRoot(position);
+    const bool startNodeIsEditable = hasEditableStyle(*startNode);
 
-    Node* node = startNode;
-    ContainerNode* highestRoot = highestEditableRoot(p);
-    int offset = p.computeEditingOffset();
-    PositionAnchorType type = p.anchorType();
+    Node* candidateNode = startNode;
+    PositionAnchorType candidateType = position.anchorType();
+    int candidateOffset = position.computeEditingOffset();
 
-    Node* n = startNode;
-    bool startNodeIsEditable = hasEditableStyle(*startNode);
-    while (n) {
-        if (boundaryCrossingRule == CannotCrossEditingBoundary && !nodeIsUserSelectAll(n) && hasEditableStyle(*n) != startNodeIsEditable)
+    Node* prevousNodeIterator = startNode;
+    while (prevousNodeIterator) {
+        if (boundaryCrossingRule == CannotCrossEditingBoundary && !nodeIsUserSelectAll(prevousNodeIterator) && hasEditableStyle(*prevousNodeIterator) != startNodeIsEditable)
             break;
         if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
-            while (n && hasEditableStyle(*n) != startNodeIsEditable)
-                n = Strategy::previousPostOrder(*n, startBlock);
-            if (!n || !n->isDescendantOf(highestRoot))
+            while (prevousNodeIterator && hasEditableStyle(*prevousNodeIterator) != startNodeIsEditable)
+                prevousNodeIterator = Strategy::previousPostOrder(*prevousNodeIterator, startBlock);
+            if (!prevousNodeIterator || !prevousNodeIterator->isDescendantOf(highestRoot))
                 break;
         }
-        LayoutObject* r = n->layoutObject();
-        LayoutItem ri = LayoutItem(r);
-        if (ri.isNull()) {
-            n = Strategy::previousPostOrder(*n, startBlock);
+
+        const LayoutItem layoutItem = LayoutItem(prevousNodeIterator->layoutObject());
+        if (layoutItem.isNull()) {
+            prevousNodeIterator = Strategy::previousPostOrder(*prevousNodeIterator, startBlock);
             continue;
         }
-        const ComputedStyle& style = ri.styleRef();
+        const ComputedStyle& style = layoutItem.styleRef();
         if (style.visibility() != VISIBLE) {
-            n = Strategy::previousPostOrder(*n, startBlock);
+            prevousNodeIterator = Strategy::previousPostOrder(*prevousNodeIterator, startBlock);
             continue;
         }
 
-        if (ri.isBR() || isEnclosingBlock(n))
+        if (layoutItem.isBR() || isEnclosingBlock(prevousNodeIterator))
             break;
 
-        if (ri.isText() && toLayoutText(r)->resolvedTextLength()) {
-            ASSERT_WITH_SECURITY_IMPLICATION(n->isTextNode());
-            type = PositionAnchorType::OffsetInAnchor;
+        if (layoutItem.isText() && toLayoutText(prevousNodeIterator->layoutObject())->resolvedTextLength()) {
+            SECURITY_DCHECK(prevousNodeIterator->isTextNode());
             if (style.preserveNewline()) {
-                LayoutText* text = toLayoutText(r);
-                int i = text->textLength();
-                int o = offset;
-                if (n == startNode && o < i)
-                    i = max(0, o);
-                while (--i >= 0) {
-                    if ((*text)[i] == '\n')
-                        return createVisiblePosition(PositionTemplate<Strategy>(toText(n), i + 1));
+                LayoutText* text = toLayoutText(prevousNodeIterator->layoutObject());
+                int index = text->textLength();
+                if (prevousNodeIterator == startNode && candidateOffset < index)
+                    index = max(0, candidateOffset);
+                while (--index >= 0) {
+                    if ((*text)[index] == '\n')
+                        return PositionTemplate<Strategy>(toText(prevousNodeIterator), index + 1);
                 }
             }
-            node = n;
-            offset = 0;
-            n = Strategy::previousPostOrder(*n, startBlock);
-        } else if (editingIgnoresContent(n) || isDisplayInsideTable(n)) {
-            node = n;
-            type = PositionAnchorType::BeforeAnchor;
-            n = n->previousSibling() ? n->previousSibling() : Strategy::previousPostOrder(*n, startBlock);
+            candidateNode = prevousNodeIterator;
+            candidateType = PositionAnchorType::OffsetInAnchor;
+            candidateOffset = 0;
+            prevousNodeIterator = Strategy::previousPostOrder(*prevousNodeIterator, startBlock);
+        } else if (editingIgnoresContent(prevousNodeIterator) || isDisplayInsideTable(prevousNodeIterator)) {
+            candidateNode = prevousNodeIterator;
+            candidateType = PositionAnchorType::BeforeAnchor;
+            prevousNodeIterator = prevousNodeIterator->previousSibling() ? prevousNodeIterator->previousSibling() : Strategy::previousPostOrder(*prevousNodeIterator, startBlock);
         } else {
-            n = Strategy::previousPostOrder(*n, startBlock);
+            prevousNodeIterator = Strategy::previousPostOrder(*prevousNodeIterator, startBlock);
         }
     }
 
-    if (type == PositionAnchorType::OffsetInAnchor)
-        return createVisiblePosition(PositionTemplate<Strategy>(node, offset));
+    if (candidateType == PositionAnchorType::OffsetInAnchor)
+        return PositionTemplate<Strategy>(candidateNode, candidateOffset);
 
-    return createVisiblePosition(PositionTemplate<Strategy>(node, type));
+    return PositionTemplate<Strategy>(candidateNode, candidateType);
+}
+
+template <typename Strategy>
+VisiblePositionTemplate<Strategy> startOfParagraphAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule boundaryCrossingRule)
+{
+    return createVisiblePosition(startOfParagraphAlgorithm(visiblePosition.deepEquivalent(), boundaryCrossingRule));
 }
 
 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index 51527d4..5ee9e54 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -994,7 +994,7 @@
 {
     DCHECK(element);
 
-    if (!element->parentNode() || !element->parentNode()->isContentEditable())
+    if (!element->parentNode() || !isContentEditable(*element->parentNode()))
         return false;
 
     if (isStyledInlineElementToRemove(element)) {
@@ -1486,7 +1486,7 @@
 
     while (node) {
         Node* next = node->nextSibling();
-        if (node->isContentEditable()) {
+        if (isContentEditable(*node)) {
             removeNode(node, editingState);
             if (editingState->isAborted())
                 return;
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteFromTextNodeCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteFromTextNodeCommand.cpp
index bbfed41..ca03d58e 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteFromTextNodeCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteFromTextNodeCommand.cpp
@@ -46,7 +46,7 @@
 {
     DCHECK(m_node);
 
-    if (!m_node->isContentEditable())
+    if (!isContentEditable(*m_node))
         return;
 
     TrackExceptionState exceptionState;
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index 4de8fdf..fb62e50 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -566,6 +566,10 @@
 
 static bool executeFindString(LocalFrame& frame, Event*, EditorCommandSource, const String& value)
 {
+    DCHECK(frame.document());
+    // Up-to-date, clean tree is required for finding text in page, since it relies
+    // on TextIterator to look over the text.
+    frame.document()->updateStyleAndLayoutIgnorePendingStylesheets();
     return frame.editor().findString(value, CaseInsensitive | WrapAround);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertNodeBeforeCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertNodeBeforeCommand.cpp
index fe10ce67..7032c65 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertNodeBeforeCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertNodeBeforeCommand.cpp
@@ -47,16 +47,16 @@
 void InsertNodeBeforeCommand::doApply(EditingState*)
 {
     ContainerNode* parent = m_refChild->parentNode();
-    if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable && !parent->isContentEditable()))
+    if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable && !isContentEditable(*parent)))
         return;
-    DCHECK(parent->isContentEditable()) << parent;
+    DCHECK(isContentEditable(*parent)) << parent;
 
     parent->insertBefore(m_insertChild.get(), m_refChild.get(), IGNORE_EXCEPTION);
 }
 
 void InsertNodeBeforeCommand::doUnapply()
 {
-    if (!m_insertChild->isContentEditable())
+    if (!isContentEditable(*m_insertChild))
         return;
 
     m_insertChild->remove(IGNORE_EXCEPTION);
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp
index 34cf6be..4898758 100644
--- a/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/RemoveNodeCommand.cpp
@@ -45,9 +45,9 @@
 {
     ContainerNode* parent = m_node->parentNode();
     if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable
-        && !parent->isContentEditable() && parent->inActiveDocument()))
+        && !isContentEditable(*parent) && parent->inActiveDocument()))
         return;
-    DCHECK(parent->isContentEditable() || !parent->inActiveDocument()) << parent;
+    DCHECK(isContentEditable(*parent) || !parent->inActiveDocument()) << parent;
 
     m_parent = parent;
     m_refChild = m_node->nextSibling();
diff --git a/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp b/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp
index 87ea248..6aa714e 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp
@@ -434,18 +434,12 @@
         TextIteratorBehaviorFlags behavior = iteratorFlagsForFindPlainText;
         if (options & FindAPICall)
             behavior |= TextIteratorForWindowFind;
-        // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
-        // see http://crbug.com/590369 for more details.
-        inputRange.startPosition().document()->updateStyleAndLayoutIgnorePendingStylesheets();
         CharacterIteratorAlgorithm<Strategy> findIterator(inputRange, behavior);
         matchLength = findPlainTextInternal(findIterator, target, options, matchStart);
         if (!matchLength)
             return EphemeralRangeTemplate<Strategy>(options & Backwards ? inputRange.startPosition() : inputRange.endPosition());
     }
 
-    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
-    // see http://crbug.com/590369 for more details.
-    inputRange.startPosition().document()->updateStyleAndLayoutIgnorePendingStylesheets();
     CharacterIteratorAlgorithm<Strategy> computeRangeIterator(inputRange, iteratorFlagsForFindPlainText);
     return computeRangeIterator.calculateCharacterSubrange(matchStart, matchLength);
 }
diff --git a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
index 7f53198..09937a62 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
@@ -156,7 +156,7 @@
     void postTask(const WebTraceLocation&, Task*) override { }
     void postDelayedTask(const WebTraceLocation&, Task*, double) override { }
     bool runsTasksOnCurrentThread() override { return true; }
-    WebTaskRunner* clone() override { return nullptr; }
+    std::unique_ptr<WebTaskRunner> clone() override { return nullptr; }
     double virtualTimeSeconds() const override { return 0.0; }
     double monotonicallyIncreasingVirtualTimeSeconds() const override { return 0.0; }
 };
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
index 7843494..e74ea5b 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp
@@ -66,7 +66,7 @@
     void postTask(const WebTraceLocation&, Task*) override { }
     void postDelayedTask(const WebTraceLocation&, Task*, double) override { }
     bool runsTasksOnCurrentThread() override { return true; }
-    WebTaskRunner* clone() override { return nullptr; }
+    std::unique_ptr<WebTaskRunner> clone() override { return nullptr; }
     double virtualTimeSeconds() const override { return 0.0; }
     double monotonicallyIncreasingVirtualTimeSeconds() const override { return 0.0; }
 };
diff --git a/third_party/WebKit/Source/core/fileapi/FileReader.idl b/third_party/WebKit/Source/core/fileapi/FileReader.idl
index d44da50..bed069a 100644
--- a/third_party/WebKit/Source/core/fileapi/FileReader.idl
+++ b/third_party/WebKit/Source/core/fileapi/FileReader.idl
@@ -40,9 +40,7 @@
 ] interface FileReader : EventTarget {
     // async read methods
     [RaisesException] void readAsArrayBuffer(Blob blob);
-    // TODO(foolip): readAsBinaryString() was removed from the spec in 2012:
-    // https://github.com/w3c/FileAPI/commit/8cce54559dc27bf8b8244f3f0ca9fb3e4d96efdb
-    [RaisesException, Measure] void readAsBinaryString(Blob blob);
+    [RaisesException] void readAsBinaryString(Blob blob);
     [RaisesException] void readAsText(Blob blob, optional DOMString label);
     [RaisesException] void readAsDataURL(Blob blob);
 
diff --git a/third_party/WebKit/Source/core/fileapi/FileReaderSync.idl b/third_party/WebKit/Source/core/fileapi/FileReaderSync.idl
index 8e9037e..8166be3 100644
--- a/third_party/WebKit/Source/core/fileapi/FileReaderSync.idl
+++ b/third_party/WebKit/Source/core/fileapi/FileReaderSync.idl
@@ -35,9 +35,7 @@
     Constructor,
 ] interface FileReaderSync {
     [CallWith=ExecutionContext, RaisesException] ArrayBuffer readAsArrayBuffer(Blob blob);
-    // TODO(foolip): readAsBinaryString() was removed from the spec in 2012:
-    // https://github.com/w3c/FileAPI/commit/8cce54559dc27bf8b8244f3f0ca9fb3e4d96efdb
-    [CallWith=ExecutionContext, RaisesException, Measure] DOMString readAsBinaryString(Blob blob);
+    [CallWith=ExecutionContext, RaisesException] DOMString readAsBinaryString(Blob blob);
     [CallWith=ExecutionContext, RaisesException] DOMString readAsText(Blob blob, optional DOMString label);
     [CallWith=ExecutionContext, RaisesException] DOMString readAsDataURL(Blob blob);
 };
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index ba05486..47b0b70b 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -828,6 +828,14 @@
         m_scrollAnchor.save();
 }
 
+bool FrameView::shouldPerformScrollAnchoring() const
+{
+    return RuntimeEnabledFeatures::scrollAnchoringEnabled()
+        && m_frame->settings() && !m_frame->settings()->rootLayerScrolls()
+        && m_scrollAnchor.hasScroller()
+        && layoutBox()->style()->overflowAnchor() != AnchorNone;
+}
+
 static inline void layoutFromRootObject(LayoutObject& root)
 {
     LayoutState layoutState(root);
@@ -3644,7 +3652,7 @@
     // Restore before clamping because clamping clears the scroll anchor.
     // TODO(ymalik): This same logic exists in PaintLayerScrollableArea.
     // Remove when root-layer-scrolls is enabled.
-    if (clamped != scrollPositionDouble() && shouldPerformScrollAnchoring() && m_scrollAnchor.hasScroller()) {
+    if (clamped != scrollPositionDouble() && shouldPerformScrollAnchoring()) {
         m_scrollAnchor.restore();
         clamped = clampScrollPosition(scrollPositionDouble());
     }
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h
index 7e5be60..bca05f80 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.h
+++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -617,6 +617,7 @@
 
     ScrollAnchor& scrollAnchor() { return m_scrollAnchor; }
     void clearScrollAnchor();
+    bool shouldPerformScrollAnchoring() const override;
 
     // For PaintInvalidator temporarily. TODO(wangxianzhu): Move into PaintInvalidator.
     void invalidatePaintIfNeeded(const PaintInvalidationState&);
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index f7a1145..22291aa 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -857,6 +857,10 @@
     if (!isCurrentlyDisplayedInFrame())
         return false;
 
+    // Up-to-date, clean tree is required for finding text in page, since it relies
+    // on TextIterator to look over the text.
+    frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();
+
     // FIXME (13016): Support searchInFrames and showDialog
     FindOptions options = (backwards ? Backwards : 0) | (caseSensitive ? 0 : CaseInsensitive) | (wrap ? WrapAround : 0) | (wholeWord ? WholeWord | AtWordStarts : 0);
     return frame()->editor().findString(string, options);
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 8a16dce..fef16f2 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -639,8 +639,6 @@
         V8HTMLLinkElement_Disabled_AttributeSetter = 811,
         V8HTMLStyleElement_Disabled_AttributeGetter = 812,
         V8HTMLStyleElement_Disabled_AttributeSetter = 813,
-        V8FileReader_ReadAsBinaryString_Method = 814,
-        V8FileReaderSync_ReadAsBinaryString_Method = 815,
         V8DOMError_Constructor = 816,
         V8DOMError_Name_AttributeGetter = 817,
         V8DOMError_Message_AttributeGetter = 818,
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp
index 1dc0d5833..c308e99e4 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -586,6 +586,11 @@
         exceptionState.throwDOMException(SyntaxError, "The value provided ('" + enabled + "') is not one of 'true', 'false', 'plaintext-only', or 'inherit'.");
 }
 
+bool HTMLElement::isContentEditable() const
+{
+    return blink::isContentEditable(*this);
+}
+
 bool HTMLElement::draggable() const
 {
     return equalIgnoringCase(getAttribute(draggableAttr), "true");
@@ -777,6 +782,8 @@
 {
     // If an ancestor has dir=auto, and this node has the first character,
     // changes to dir attribute may affect the ancestor.
+    if (!canParticipateInFlatTree())
+        return;
     updateDistribution();
     Element* parent = FlatTreeTraversal::parentElement(*this);
     if (parent && parent->isHTMLElement() && toHTMLElement(parent)->selfOrAncestorHasDirAutoAttribute())
@@ -1038,7 +1045,7 @@
     // if the element is a text form control (like <input type=text> or <textarea>)
     // or has contentEditable attribute on, we should enter a space or newline
     // even in spatial navigation mode instead of handling it as a "click" action.
-    if (isTextFormControl() || isContentEditable())
+    if (isTextFormControl() || blink::isContentEditable(*this))
         return;
     int charCode = event->charCode();
     if (charCode == '\r' || charCode == ' ') {
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.h b/third_party/WebKit/Source/core/html/HTMLElement.h
index 820c43d2..1b9af5d1 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLElement.h
@@ -56,6 +56,7 @@
 
     String contentEditable() const;
     void setContentEditable(const String&, ExceptionState&);
+    bool isContentEditable() const;
 
     virtual bool draggable() const;
     void setDraggable(bool);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index 22a7b2c..459bd6d 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -112,7 +112,7 @@
     , m_options(&document)
     , m_token(syncPolicy == ForceSynchronousParsing ? wrapUnique(new HTMLToken) : nullptr)
     , m_tokenizer(syncPolicy == ForceSynchronousParsing ? HTMLTokenizer::create(m_options) : nullptr)
-    , m_loadingTaskRunner(wrapUnique(TaskRunnerHelper::getLoadingTaskRunner(&document)->clone()))
+    , m_loadingTaskRunner(TaskRunnerHelper::getLoadingTaskRunner(&document)->clone())
     , m_parserScheduler(syncPolicy == AllowAsynchronousParsing ? HTMLParserScheduler::create(this, m_loadingTaskRunner.get()) : nullptr)
     , m_xssAuditorDelegate(&document)
     , m_weakFactory(this)
@@ -298,17 +298,32 @@
 
     // ApplicationCache needs to be initialized before issuing preloads.
     // We suspend preload until HTMLHTMLElement is inserted and
-    // ApplicationCache is initialized.
+    // ApplicationCache is initialized. Note: link rel preloads don't follow
+    // this policy per the spec. These directives should initiate a fetch as
+    // fast as possible.
+    if (!m_triedLoadingLinkHeaders && document()->loader() && !pendingChunks.isEmpty()) {
+        // Note that on commit, the loader dispatched preloads for all the
+        // non-media links.
+        document()->loader()->dispatchLinkHeaderPreloads(&pendingChunks.first()->viewport, LinkLoader::OnlyLoadMedia);
+        m_triedLoadingLinkHeaders = true;
+    }
+
     if (!document()->documentElement()) {
+        PreloadRequestStream linkRelPreloads;
         for (auto& chunk : pendingChunks) {
-            for (auto& request : chunk->preloads)
-                m_queuedPreloads.append(std::move(request));
+            for (auto& request : chunk->preloads) {
+                if (request->isLinkRelPreload())
+                    linkRelPreloads.append(std::move(request));
+                else
+                    m_queuedPreloads.append(std::move(request));
+            }
             for (auto& index : chunk->likelyDocumentWriteScriptIndices) {
                 const CompactHTMLToken& token = chunk->tokens->at(index);
                 ASSERT(token.type() == HTMLToken::TokenType::Character);
                 m_queuedDocumentWriteScripts.append(token.data());
             }
         }
+        m_preloader->takeAndPreload(linkRelPreloads);
     } else {
         // We can safely assume that there are no queued preloads request after
         // the document element is available, as we empty the queue immediately
@@ -468,16 +483,6 @@
         if (isStopped())
             break;
 
-        if (!m_triedLoadingLinkHeaders && document()->loader()) {
-            String linkHeader = document()->loader()->response().httpHeaderField(HTTPNames::Link);
-            if (!linkHeader.isEmpty()) {
-                ASSERT(chunk);
-                LinkLoader::loadLinksFromHeader(linkHeader, document()->loader()->response().url(),
-                    document(), NetworkHintsInterfaceImpl(), LinkLoader::OnlyLoadResources, &(chunk->viewport));
-                m_triedLoadingLinkHeaders = true;
-            }
-        }
-
         if (isWaitingForScripts()) {
             ASSERT(it + 1 == tokens->end()); // The </script> is assumed to be the last token of this bunch.
             runScriptsForPausedTreeBuilder();
@@ -747,7 +752,7 @@
         document()->url(),
         passed(CachedDocumentParameters::create(document())),
         MediaValuesCached::MediaValuesCachedData(*document()),
-        passed(wrapUnique(m_loadingTaskRunner->clone())));
+        passed(m_loadingTaskRunner->clone()));
 }
 
 void HTMLDocumentParser::stopBackgroundParser()
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp
index 0d757cbc5..64890b5 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserScheduler.cpp
@@ -68,7 +68,7 @@
 
 HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser* parser, WebTaskRunner* loadingTaskRunner)
     : m_parser(parser)
-    , m_loadingTaskRunner(wrapUnique(loadingTaskRunner->clone()))
+    , m_loadingTaskRunner(loadingTaskRunner->clone())
     , m_cancellableContinueParse(CancellableTaskFactory::create(this, &HTMLParserScheduler::continueParsing))
     , m_isSuspendedWithActiveTimer(false)
 {
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
index c4ac3a38..827bbc8 100644
--- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
+++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
@@ -56,6 +56,7 @@
     float resourceWidth() const { return m_resourceWidth.isSet ? m_resourceWidth.width : 0; }
     const KURL& baseURL() const { return m_baseURL; }
     bool isPreconnect() const { return m_requestType == RequestTypePreconnect; }
+    bool isLinkRelPreload() const { return m_requestType == RequestTypeLinkRelPreload; }
     const ClientHintsPreferences& preferences() const { return m_clientHintsPreferences; }
     ReferrerPolicy getReferrerPolicy() const { return m_referrerPolicy; }
     void setIntegrityMetadata(const IntegrityMetadataSet& metadataSet)
diff --git a/third_party/WebKit/Source/core/layout/ImageQualityControllerTest.cpp b/third_party/WebKit/Source/core/layout/ImageQualityControllerTest.cpp
index 15b8e27..4ad63e8 100644
--- a/third_party/WebKit/Source/core/layout/ImageQualityControllerTest.cpp
+++ b/third_party/WebKit/Source/core/layout/ImageQualityControllerTest.cpp
@@ -133,7 +133,7 @@
 
     }
     bool runsTasksOnCurrentThread() override { return true; }
-    WebTaskRunner* clone() override { return nullptr; }
+    std::unique_ptr<WebTaskRunner> clone() override { return nullptr; }
     double virtualTimeSeconds() const override { return 0.0; }
     double monotonicallyIncreasingVirtualTimeSeconds() const override { return m_time; }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 72f0687..644462c0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -63,10 +63,12 @@
 };
 
 struct LayoutFlexibleBox::FlexItem {
-    FlexItem(LayoutBox* box, LayoutUnit flexBaseContentSize, LayoutUnit hypotheticalMainContentSize)
+    FlexItem(LayoutBox* box, LayoutUnit flexBaseContentSize, LayoutUnit hypotheticalMainContentSize, LayoutUnit mainAxisBorderAndPadding, LayoutUnit mainAxisMargin)
         : box(box)
         , flexBaseContentSize(flexBaseContentSize)
         , hypotheticalMainContentSize(hypotheticalMainContentSize)
+        , mainAxisBorderAndPadding(mainAxisBorderAndPadding)
+        , mainAxisMargin(mainAxisMargin)
         , frozen(false)
     {
     }
@@ -76,12 +78,26 @@
         : box(box)
         , flexBaseContentSize()
         , hypotheticalMainContentSize()
+        , mainAxisBorderAndPadding()
         , frozen(true)
     {
     }
+
+    LayoutUnit hypotheticalMainAxisMarginBoxSize() const
+    {
+        return hypotheticalMainContentSize + mainAxisBorderAndPadding + mainAxisMargin;
+    }
+
+    LayoutUnit flexBaseMarginBoxSize() const
+    {
+        return flexBaseContentSize + mainAxisBorderAndPadding + mainAxisMargin;
+    }
+
     LayoutBox* box;
     const LayoutUnit flexBaseContentSize;
     const LayoutUnit hypotheticalMainContentSize;
+    const LayoutUnit mainAxisBorderAndPadding;
+    const LayoutUnit mainAxisMargin;
     LayoutUnit flexedContentSize;
     bool frozen;
 };
@@ -769,11 +785,6 @@
         child.setLocationAndUpdateOverflowControlsIfNeeded(location.transposedPoint());
 }
 
-LayoutUnit LayoutFlexibleBox::mainAxisBorderAndPaddingExtentForChild(const LayoutBox& child) const
-{
-    return isHorizontalFlow() ? child.borderAndPaddingWidth() : child.borderAndPaddingHeight();
-}
-
 bool LayoutFlexibleBox::mainAxisLengthIsDefinite(const LayoutBox& child, const Length& flexBasis) const
 {
     if (flexBasis.isAuto())
@@ -837,7 +848,7 @@
     m_intrinsicSizeAlongMainAxis.remove(&child);
 }
 
-LayoutUnit LayoutFlexibleBox::computeInnerFlexBaseSizeForChild(LayoutBox& child, ChildLayoutType childLayoutType)
+LayoutUnit LayoutFlexibleBox::computeInnerFlexBaseSizeForChild(LayoutBox& child, LayoutUnit mainAxisBorderAndPadding, ChildLayoutType childLayoutType)
 {
     child.clearOverrideSize();
 
@@ -865,8 +876,8 @@
         // of this if.
         mainAxisExtent = child.maxPreferredLogicalWidth();
     }
-    ASSERT(mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child) >= 0);
-    return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
+    DCHECK_GE(mainAxisExtent - mainAxisBorderAndPadding, LayoutUnit()) << mainAxisExtent << " - " << mainAxisBorderAndPadding;
+    return mainAxisExtent - mainAxisBorderAndPadding;
 }
 
 void LayoutFlexibleBox::layoutFlexItems(bool relayoutChildren, SubtreeLayoutScope& layoutScope)
@@ -901,11 +912,11 @@
         // use remainingFreeSpace here.
         remainingFreeSpace = containerMainInnerSize;
         for (size_t i = 0; i < orderedChildren.size(); ++i) {
+            FlexItem& flexItem = orderedChildren[i];
             LayoutBox* child = orderedChildren[i].box;
             if (child->isOutOfFlowPositioned())
                 continue;
-            remainingFreeSpace -= (orderedChildren[i].flexedContentSize + mainAxisBorderAndPaddingExtentForChild(*child)
-                + (isHorizontalFlow() ? child->marginWidth() : child->marginHeight()));
+            remainingFreeSpace -= orderedChildren[i].flexedContentSize + flexItem.mainAxisBorderAndPadding + flexItem.mainAxisMargin;
         }
         layoutAndPlaceChildren(crossAxisOffset, orderedChildren, remainingFreeSpace, relayoutChildren, layoutScope, lineContexts);
     }
@@ -1200,6 +1211,15 @@
     return childSize;
 }
 
+LayoutFlexibleBox::FlexItem LayoutFlexibleBox::constructFlexItem(LayoutBox& child, ChildLayoutType layoutType)
+{
+    LayoutUnit borderAndPadding = isHorizontalFlow() ? child.borderAndPaddingWidth() : child.borderAndPaddingHeight();
+    LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild(child, borderAndPadding, layoutType);
+    LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childInnerFlexBaseSize);
+    LayoutUnit margin = isHorizontalFlow() ? child.marginWidth() : child.marginHeight();
+    return FlexItem(&child, childInnerFlexBaseSize, childMinMaxAppliedMainAxisExtent, borderAndPadding, margin);
+}
+
 bool LayoutFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren)
 {
     orderedChildren.clear();
@@ -1232,23 +1252,16 @@
             layoutType = LayoutIfNeeded;
         }
 
-        LayoutUnit childInnerFlexBaseSize = computeInnerFlexBaseSizeForChild(*child, layoutType);
-        LayoutUnit childMainAxisMarginBorderPadding = mainAxisBorderAndPaddingExtentForChild(*child)
-            + (isHorizontalFlow() ? child->marginWidth() : child->marginHeight());
-        LayoutUnit childOuterFlexBaseSize = childInnerFlexBaseSize + childMainAxisMarginBorderPadding;
-
-        LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(*child, childInnerFlexBaseSize);
-        LayoutUnit childHypotheticalMainSize = childMinMaxAppliedMainAxisExtent + childMainAxisMarginBorderPadding;
-
-        if (isMultiline() && sumHypotheticalMainSize + childHypotheticalMainSize > lineBreakLength && lineHasInFlowItem)
+        FlexItem flexItem = constructFlexItem(*child, layoutType);
+        if (isMultiline() && sumHypotheticalMainSize + flexItem.hypotheticalMainAxisMarginBoxSize() > lineBreakLength && lineHasInFlowItem)
             break;
-        orderedChildren.append(FlexItem(child, childInnerFlexBaseSize, childMinMaxAppliedMainAxisExtent));
+        orderedChildren.append(flexItem);
         lineHasInFlowItem  = true;
-        sumFlexBaseSize += childOuterFlexBaseSize;
+        sumFlexBaseSize += flexItem.flexBaseMarginBoxSize();
         totalFlexGrow += child->style()->flexGrow();
         totalFlexShrink += child->style()->flexShrink();
-        totalWeightedFlexShrink += child->style()->flexShrink() * childInnerFlexBaseSize;
-        sumHypotheticalMainSize += childHypotheticalMainSize;
+        totalWeightedFlexShrink += child->style()->flexShrink() * flexItem.flexBaseContentSize;
+        sumHypotheticalMainSize += flexItem.hypotheticalMainAxisMarginBoxSize();
     }
     return true;
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
index d907bb77..d736ddf 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -147,8 +147,7 @@
     void setFlowAwareLocationForChild(LayoutBox& child, const LayoutPoint&);
     void adjustAlignmentForChild(LayoutBox& child, LayoutUnit);
     ItemPosition alignmentForChild(const LayoutBox& child) const;
-    LayoutUnit mainAxisBorderAndPaddingExtentForChild(const LayoutBox& child) const;
-    LayoutUnit computeInnerFlexBaseSizeForChild(LayoutBox& child, ChildLayoutType = LayoutIfNeeded);
+    LayoutUnit computeInnerFlexBaseSizeForChild(LayoutBox& child, LayoutUnit mainAxisBorderAndPadding, ChildLayoutType = LayoutIfNeeded);
     bool mainAxisLengthIsDefinite(const LayoutBox& child, const Length& flexBasis) const;
     bool crossAxisLengthIsDefinite(const LayoutBox& child, const Length& flexBasis) const;
     bool childFlexBaseSizeRequiresLayout(const LayoutBox& child) const;
@@ -174,6 +173,7 @@
     void prepareOrderIteratorAndMargins();
     LayoutUnit adjustChildSizeForMinAndMax(const LayoutBox& child, LayoutUnit childSize);
     LayoutUnit adjustChildSizeForAspectRatioCrossAxisMinAndMax(const LayoutBox& child, LayoutUnit childSize);
+    FlexItem constructFlexItem(LayoutBox& child, ChildLayoutType);
     // The hypothetical main size of an item is the flex base size clamped according to its min and max main size properties
     bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& sumFlexBaseSize, double& totalFlexGrow, double& totalFlexShrink, double& totalWeightedFlexShrink, LayoutUnit& sumHypotheticalMainSize, bool relayoutChildren);
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
index e9d0096..0e9ff3f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -848,7 +848,7 @@
     bool isRowAxis = direction == ForColumns;
     const Vector<GridTrackSize>& trackStyles = isRowAxis ? styleRef().gridTemplateColumns() : styleRef().gridTemplateRows();
     const Vector<GridTrackSize>& autoRepeatTrackStyles = isRowAxis ? styleRef().gridAutoRepeatColumns() : styleRef().gridAutoRepeatRows();
-    const GridTrackSize& autoTrackSize = isRowAxis ? styleRef().gridAutoColumns() : styleRef().gridAutoRows();
+    const Vector<GridTrackSize>& autoTrackStyles = isRowAxis ? styleRef().gridAutoColumns() : styleRef().gridAutoRows();
     size_t insertionPoint = isRowAxis ? styleRef().gridAutoRepeatColumnsInsertionPoint() : styleRef().gridAutoRepeatRowsInsertionPoint();
     size_t autoRepeatTracksCount = autoRepeatCountForDirection(direction);
 
@@ -858,12 +858,17 @@
     size_t explicitTracksCount = trackStyles.size() + autoRepeatTracksCount;
 
     int untranslatedIndexAsInt = translatedIndex + (isRowAxis ? m_smallestColumnStart : m_smallestRowStart);
-    if (untranslatedIndexAsInt < 0)
-        return autoTrackSize;
+    size_t autoTrackStylesSize = autoTrackStyles.size();
+    if (untranslatedIndexAsInt < 0) {
+        int index = untranslatedIndexAsInt % static_cast<int>(autoTrackStylesSize);
+        // We need to traspose the index because the first negative implicit line will get the last defined auto track and so on.
+        index += index ? autoTrackStylesSize : 0;
+        return autoTrackStyles[index];
+    }
 
     size_t untranslatedIndex = static_cast<size_t>(untranslatedIndexAsInt);
     if (untranslatedIndex >= explicitTracksCount)
-        return autoTrackSize;
+        return autoTrackStyles[(untranslatedIndex - explicitTracksCount) % autoTrackStylesSize];
 
     if (LIKELY(!autoRepeatTracksCount) || untranslatedIndex < insertionPoint)
         return trackStyles[untranslatedIndex];
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index 24e6c041..8dae489 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -179,7 +179,7 @@
 //
 // LayoutObjects are created during the DOM attachment. This phase computes
 // the style and create the LayoutObject associated with the Node (see
-// Node::attach). LayoutObjects are destructed during detachment (see
+// Node::attachLayoutTree). LayoutObjects are destructed during detachment (see
 // Node::detach), which can happen when the DOM node is removed from the
 // DOM tree, during page tear down or when the style is changed to contain
 // 'display: none'.
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
index 3469d4a..eb1a826 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
@@ -66,6 +66,26 @@
     LayoutBlockFlow::willBeRemovedFromTree();
 
     section()->setNeedsCellRecalc();
+
+    // When borders collapse, removing a cell can affect the the width of neighboring cells.
+    if (!parent())
+        return;
+    LayoutTable* enclosingTable = table();
+    DCHECK(enclosingTable);
+    if (!enclosingTable->collapseBorders())
+        return;
+    if (previousCell()) {
+        // TODO(dgrogan): Should this be setChildNeedsLayout or setNeedsLayout?
+        // remove-cell-with-border-box.html only passes with setNeedsLayout but other places
+        // use setChildNeedsLayout.
+        previousCell()->setNeedsLayout(LayoutInvalidationReason::TableChanged);
+        previousCell()->setPreferredLogicalWidthsDirty();
+    }
+    if (nextCell()) {
+        // TODO(dgrogan): Same as above re: setChildNeedsLayout vs setNeedsLayout.
+        nextCell()->setNeedsLayout(LayoutInvalidationReason::TableChanged);
+        nextCell()->setPreferredLogicalWidthsDirty();
+    }
 }
 
 unsigned LayoutTableCell::parseColSpanFromDOM() const
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm b/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
index ad3fd3f..7c85b6e9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
@@ -111,6 +111,22 @@
 
 namespace blink {
 
+namespace {
+
+bool fontSizeMatchesToControlSize(const ComputedStyle& style)
+{
+    int fontSize = style.fontSize();
+    if (fontSize == [NSFont systemFontSizeForControlSize:NSRegularControlSize])
+        return true;
+    if (fontSize == [NSFont systemFontSizeForControlSize:NSSmallControlSize])
+        return true;
+    if (fontSize == [NSFont systemFontSizeForControlSize:NSMiniControlSize])
+        return true;
+    return false;
+}
+
+} // namespace
+
 using namespace HTMLNames;
 
 LayoutThemeMac::LayoutThemeMac()
@@ -445,14 +461,22 @@
     if (style.appearance() == TextFieldPart || style.appearance() == TextAreaPart)
         return style.hasAuthorBorder() || style.boxShadow();
 
-    // FIXME: This is horrible, but there is not much else that can be done.
-    // Menu lists cannot draw properly when scaled. They can't really draw
-    // properly when transformed either. We can't detect the transform case at
-    // style adjustment time so that will just have to stay broken.  We can
-    // however detect that we're zooming. If zooming is in effect we treat it
-    // like the control is styled.
-    if (style.appearance() == MenulistPart && style.effectiveZoom() != 1.0f)
-        return true;
+    if (style.appearance() == MenulistPart) {
+        // FIXME: This is horrible, but there is not much else that can be done.
+        // Menu lists cannot draw properly when scaled. They can't really draw
+        // properly when transformed either. We can't detect the transform case
+        // at style adjustment time so that will just have to stay broken.  We
+        // can however detect that we're zooming. If zooming is in effect we
+        // treat it like the control is styled.
+        if (style.effectiveZoom() != 1.0f)
+            return true;
+        if (!fontSizeMatchesToControlSize(style))
+            return true;
+        if (style.getFontDescription().family().family() != "BlinkMacSystemFont")
+            return true;
+        if (!style.height().isIntrinsicOrAuto())
+            return true;
+    }
     // Some other cells don't work well when scaled.
     if (style.effectiveZoom() != 1) {
         switch (style.appearance()) {
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index ba24f4d..9e23b1a9 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -208,6 +208,11 @@
     return resource;
 }
 
+void DocumentLoader::dispatchLinkHeaderPreloads(ViewportDescriptionWrapper* viewport, LinkLoader::MediaPreloadPolicy mediaPolicy)
+{
+    LinkLoader::loadLinksFromHeader(response().httpHeaderField(HTTPNames::Link), response().url(), m_frame->document(), NetworkHintsInterfaceImpl(), LinkLoader::OnlyLoadResources, mediaPolicy, viewport);
+}
+
 void DocumentLoader::didChangePerformanceTiming()
 {
     if (frame() && frame()->isMainFrame() && m_state >= Committed) {
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h
index a8b4216..2551df87 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.h
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -41,6 +41,7 @@
 #include "core/loader/DocumentLoadTiming.h"
 #include "core/loader/DocumentWriter.h"
 #include "core/loader/FrameLoaderTypes.h"
+#include "core/loader/LinkLoader.h"
 #include "core/loader/NavigationPolicy.h"
 #include "platform/SharedBuffer.h"
 #include "platform/network/ResourceError.h"
@@ -60,6 +61,7 @@
 class FrameLoader;
 class ResourceLoader;
 class WebDocumentSubresourceFilter;
+struct ViewportDescriptionWrapper;
 
 class CORE_EXPORT DocumentLoader : public GarbageCollectedFinalized<DocumentLoader>, private RawResourceClient {
 public:
@@ -146,6 +148,8 @@
     void setWasBlockedAfterXFrameOptionsOrCSP() { m_wasBlockedAfterXFrameOptionsOrCSP = true; }
     bool wasBlockedAfterXFrameOptionsOrCSP() { return m_wasBlockedAfterXFrameOptionsOrCSP; }
 
+    void dispatchLinkHeaderPreloads(ViewportDescriptionWrapper*, LinkLoader::MediaPreloadPolicy);
+
     Resource* startPreload(Resource::Type, FetchRequest&);
 
     DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index c8d3ea4..f873f582 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -797,7 +797,7 @@
         // When response is received with a provisional docloader, the resource haven't committed yet, and we cannot load resources, only preconnect.
         resourceLoadingPolicy = LinkLoader::DoNotLoadResources;
     }
-    LinkLoader::loadLinksFromHeader(response.httpHeaderField(HTTPNames::Link), response.url(), frame()->document(), NetworkHintsInterfaceImpl(), resourceLoadingPolicy, nullptr);
+    LinkLoader::loadLinksFromHeader(response.httpHeaderField(HTTPNames::Link), response.url(), frame()->document(), NetworkHintsInterfaceImpl(), resourceLoadingPolicy, LinkLoader::LoadAll, nullptr);
 
     if (response.hasMajorCertificateErrors())
         MixedContentChecker::handleCertificateError(frame(), response, frameType, requestContext);
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 3137c89..2a181112 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -170,7 +170,6 @@
     , m_inStopAllLoaders(false)
     , m_checkTimer(this, &FrameLoader::checkTimerFired)
     , m_didAccessInitialDocument(false)
-    , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired)
     , m_forcedSandboxFlags(SandboxNone)
     , m_dispatchingDidClearWindowObjectInMainWorld(false)
     , m_protectProvisionalLoader(false)
@@ -445,6 +444,11 @@
     if (client()->isControlledByServiceWorker(*m_documentLoader))
         client()->didObserveLoadingBehavior(WebLoadingBehaviorServiceWorkerControlled);
 
+    // Links with media values need more information (like viewport
+    // information). This happens after the first chunk is parsed in
+    // HTMLDocumentParser.
+    m_documentLoader->dispatchLinkHeaderPreloads(nullptr, LinkLoader::OnlyLoadNonMedia);
+
     TRACE_EVENT1("devtools.timeline", "CommitLoad", "data", InspectorCommitLoadEvent::data(m_frame));
     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
     m_frame->page()->didCommitLoad(m_frame);
@@ -1061,22 +1065,12 @@
     // We only need to notify the client once, and only for the main frame.
     if (isLoadingMainFrame() && !m_didAccessInitialDocument) {
         m_didAccessInitialDocument = true;
-        // Notify asynchronously, since this is called within a JavaScript security check.
-        m_didAccessInitialDocumentTimer.startOneShot(0, BLINK_FROM_HERE);
-    }
-}
 
-void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*)
-{
-    if (client())
-        client()->didAccessInitialDocument();
-}
-
-void FrameLoader::notifyIfInitialDocumentAccessed()
-{
-    if (m_didAccessInitialDocumentTimer.isActive()) {
-        m_didAccessInitialDocumentTimer.stop();
-        didAccessInitialDocumentTimerFired(0);
+        // Forbid script execution to prevent re-entering V8, since this is
+        // called from a binding security check.
+        ScriptForbiddenScope forbidScripts;
+        if (client())
+            client()->didAccessInitialDocument();
     }
 }
 
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h
index 759083d..d137ce5 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.h
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -100,16 +100,12 @@
 
     void replaceDocumentWhileExecutingJavaScriptURL(const String& source, Document* ownerDocument);
 
-    // Sets a timer to notify the client that the initial empty document has
-    // been accessed, and thus it is no longer safe to show a provisional URL
-    // above the document without risking a URL spoof.
+    // Notifies the client that the initial empty document has been accessed,
+    // and thus it is no longer safe to show a provisional URL above the
+    // document without risking a URL spoof. The client must not call back into
+    // JavaScript.
     void didAccessInitialDocument();
 
-    // If the initial empty document is showing and has been accessed, this
-    // cancels the timer and immediately notifies the client in cases that
-    // waiting to notify would allow a URL spoof.
-    void notifyIfInitialDocumentAccessed();
-
     DocumentLoader* documentLoader() const { return m_documentLoader.get(); }
     DocumentLoader* provisionalDocumentLoader() const { return m_provisionalDocumentLoader.get(); }
 
@@ -281,7 +277,6 @@
     Timer<FrameLoader> m_checkTimer;
 
     bool m_didAccessInitialDocument;
-    Timer<FrameLoader> m_didAccessInitialDocumentTimer;
 
     SandboxFlags m_forcedSandboxFlags;
 
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
index eb58c35c..d777e1c 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -302,7 +302,7 @@
 }
 
 void LinkLoader::loadLinksFromHeader(const String& headerValue, const KURL& baseURL, Document* document, const NetworkHintsInterface& networkHintsInterface,
-    CanLoadResources canLoadResources, ViewportDescriptionWrapper* viewportDescriptionWrapper)
+    CanLoadResources canLoadResources, MediaPreloadPolicy mediaPolicy, ViewportDescriptionWrapper* viewportDescriptionWrapper)
 {
     if (!document || headerValue.isEmpty())
         return;
@@ -311,6 +311,11 @@
         if (!header.valid() || header.url().isEmpty() || header.rel().isEmpty())
             continue;
 
+        if (mediaPolicy == OnlyLoadMedia && header.media().isEmpty())
+            continue;
+        if (mediaPolicy == OnlyLoadNonMedia && !header.media().isEmpty())
+            continue;
+
         LinkRelAttribute relAttribute(header.rel());
         KURL url(baseURL, header.url());
         // Sanity check to avoid re-entrancy here.
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.h b/third_party/WebKit/Source/core/loader/LinkLoader.h
index a9f0b1dd..ac40af66 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.h
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.h
@@ -75,7 +75,10 @@
     void released();
     bool loadLink(const LinkRelAttribute&, CrossOriginAttributeValue, const String& type, const String& as, const String& media, const KURL&, Document&, const NetworkHintsInterface&);
     enum CanLoadResources { OnlyLoadResources, DoNotLoadResources, LoadResourcesAndPreconnect };
-    static void loadLinksFromHeader(const String& headerValue, const KURL& baseURL, Document*, const NetworkHintsInterface&, CanLoadResources, ViewportDescriptionWrapper*);
+    // Media links cannot be preloaded until the first chunk is parsed. The rest
+    // can be preloaded at commit time.
+    enum MediaPreloadPolicy { LoadAll, OnlyLoadNonMedia, OnlyLoadMedia };
+    static void loadLinksFromHeader(const String& headerValue, const KURL& baseURL, Document*, const NetworkHintsInterface&, CanLoadResources, MediaPreloadPolicy, ViewportDescriptionWrapper*);
     static bool getResourceTypeFromAsAttribute(const String& as, Resource::Type&);
 
     DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index 97d8446a..0d6d6a0 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -718,7 +718,7 @@
 
 static void prepareDataTransferForImageDrag(LocalFrame* source, DataTransfer* dataTransfer, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label)
 {
-    if (node->isContentRichlyEditable()) {
+    if (isContentRichlyEditable(*node)) {
         Range* range = source->document()->createRange();
         range->selectNode(node, ASSERT_NO_EXCEPTION);
         source->selection().setSelection(VisibleSelection(EphemeralRange(range)));
diff --git a/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp b/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp
index 8a41b18..c247c99 100644
--- a/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp
+++ b/third_party/WebKit/Source/core/page/ScopedPageLoadDeferrer.cpp
@@ -36,11 +36,6 @@
         if (page == exclusion || page->defersLoading())
             continue;
         m_deferredPages.append(page);
-
-        // Ensure that we notify the client if the initial empty document is accessed before
-        // showing anything modal, to prevent spoofs while the modal window or sheet is visible.
-        if (page->mainFrame()->isLocalFrame())
-            page->deprecatedLocalMainFrame()->loader().notifyIfInitialDocumentAccessed();
     }
 
     setDefersLoading(true);
diff --git a/third_party/WebKit/Source/core/page/TouchAdjustment.cpp b/third_party/WebKit/Source/core/page/TouchAdjustment.cpp
index 57c1e3c..f2d31df8 100644
--- a/third_party/WebKit/Source/core/page/TouchAdjustment.cpp
+++ b/third_party/WebKit/Source/core/page/TouchAdjustment.cpp
@@ -116,7 +116,7 @@
     ASSERT(node->layoutObject() || node->isShadowRoot());
     if (!node->layoutObject())
         return false;
-    if (node->isContentEditable())
+    if (isContentEditable(*node))
         return true;
     if (node->isLink())
         return true;
@@ -298,10 +298,10 @@
         // Consolidate bounds for editable content.
         if (editableAncestors.contains(candidate))
             continue;
-        if (candidate->isContentEditable()) {
+        if (isContentEditable(*candidate)) {
             Node* replacement = candidate;
             Node* parent = candidate->parentOrShadowHostNode();
-            while (parent && parent->isContentEditable()) {
+            while (parent && isContentEditable(*parent)) {
                 replacement = parent;
                 if (editableAncestors.contains(replacement)) {
                     replacement = nullptr;
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
index 44cfc084..919d296 100644
--- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
+++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
@@ -418,7 +418,6 @@
     m_destRect.intersect(paintRect);
 
     // Snap as-yet unsnapped values.
-    DCHECK(m_phase == LayoutPoint(roundedIntPoint(m_phase)));
     setDestRect(LayoutRect(pixelSnappedIntRect(m_destRect)));
 }
 
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
index db6e7070..2d72971 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -92,12 +92,12 @@
     void setPerspective(PassRefPtr<TransformPaintPropertyNode> perspective) { m_perspective = perspective; }
     void setSvgLocalToBorderBoxTransform(PassRefPtr<TransformPaintPropertyNode> transform)
     {
-        DCHECK(!scrollTranslation()) << "SVG elements cannot scroll so there should never be both a scroll translation and an SVG local to border box transform.";
+        DCHECK(!scrollTranslation() || !transform) << "SVG elements cannot scroll so there should never be both a scroll translation and an SVG local to border box transform.";
         m_svgLocalToBorderBoxTransform = transform;
     }
     void setScrollTranslation(PassRefPtr<TransformPaintPropertyNode> translation)
     {
-        DCHECK(!svgLocalToBorderBoxTransform()) << "SVG elements cannot scroll so there should never be both a scroll translation and an SVG local to border box transform.";
+        DCHECK(!svgLocalToBorderBoxTransform() || !translation) << "SVG elements cannot scroll so there should never be both a scroll translation and an SVG local to border box transform.";
         m_scrollTranslation = translation;
     }
     void setScrollbarPaintOffset(PassRefPtr<TransformPaintPropertyNode> paintOffset) { m_scrollbarPaintOffset = paintOffset; }
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
index 47b0cae..e552529 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
@@ -135,10 +135,4 @@
     layoutBox()->setMayNeedPaintInvalidation();
 }
 
-bool PaintInvalidationCapableScrollableArea::shouldPerformScrollAnchoring() const
-{
-    return RuntimeEnabledFeatures::scrollAnchoringEnabled()
-        && layoutBox()->style()->overflowAnchor() != AnchorNone;
-}
-
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
index 6d59980..4ef4a25 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
@@ -36,8 +36,6 @@
 
     LayoutRect visualRectForScrollbarParts() const override;
 
-    bool shouldPerformScrollAnchoring() const override;
-
 private:
     virtual LayoutScrollbarPart* scrollCorner() const = 0;
     virtual LayoutScrollbarPart* resizer() const = 0;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index ef02d56e..cb5500a 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -754,7 +754,7 @@
 
     DoublePoint clamped = clampScrollPosition(scrollPositionDouble());
     // Restore before clamping because clamping clears the scroll anchor.
-    if (clamped != scrollPositionDouble() && shouldPerformScrollAnchoring() && m_scrollAnchor.hasScroller()) {
+    if (clamped != scrollPositionDouble() && shouldPerformScrollAnchoring()) {
         m_scrollAnchor.restore();
         clamped = clampScrollPosition(scrollPositionDouble());
     }
@@ -766,6 +766,13 @@
     m_scrollbarManager.destroyDetachedScrollbars();
 }
 
+bool PaintLayerScrollableArea::shouldPerformScrollAnchoring() const
+{
+    return RuntimeEnabledFeatures::scrollAnchoringEnabled()
+        && m_scrollAnchor.hasScroller()
+        && layoutBox()->style()->overflowAnchor() != AnchorNone;
+}
+
 ScrollBehavior PaintLayerScrollableArea::scrollBehaviorStyle() const
 {
     return box().style()->getScrollBehavior();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
index dd957916..6bb62e9 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -405,6 +405,7 @@
     IntRect rectForVerticalScrollbar(const IntRect& borderBoxRect) const;
 
     Widget* getWidget() override;
+    bool shouldPerformScrollAnchoring() const override;
     ScrollAnchor& scrollAnchor() { return m_scrollAnchor; }
     bool isPaintLayerScrollableArea() const override { return true; }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 1d394cb..1540c0f 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -21,17 +21,18 @@
 
 void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPropertyTreeBuilderContext& context)
 {
-    RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr);
-    context.current.transform = context.absolutePosition.transform = context.fixedPosition.transform = transformRoot.get();
-    rootFrame.setRootTransform(std::move(transformRoot));
+    if (!rootFrame.rootTransform() || rootFrame.rootTransform()->parent()) {
+        rootFrame.setRootTransform(TransformPaintPropertyNode::create(nullptr, TransformationMatrix(), FloatPoint3D()));
+        rootFrame.setRootClip(ClipPaintPropertyNode::create(nullptr, rootFrame.rootTransform(), FloatRoundedRect(LayoutRect::infiniteIntRect())));
+        rootFrame.setRootEffect(EffectPaintPropertyNode::create(nullptr, 1.0));
+    } else {
+        DCHECK(rootFrame.rootClip() && !rootFrame.rootClip()->parent());
+        DCHECK(rootFrame.rootEffect() && !rootFrame.rootEffect()->parent());
+    }
 
-    RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(transformRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr);
-    context.current.clip = context.absolutePosition.clip = context.fixedPosition.clip = clipRoot.get();
-    rootFrame.setRootClip(std::move(clipRoot));
-
-    RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create(1.0, nullptr);
-    context.currentEffect = effectRoot.get();
-    rootFrame.setRootEffect(std::move(effectRoot));
+    context.current.transform = context.absolutePosition.transform = context.fixedPosition.transform = rootFrame.rootTransform();
+    context.current.clip = context.absolutePosition.clip = context.fixedPosition.clip = rootFrame.rootClip();
+    context.currentEffect = rootFrame.rootEffect();
 }
 
 void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropertyTreeBuilderContext& context)
@@ -42,58 +43,84 @@
 
     TransformationMatrix frameTranslate;
     frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), frameView.y() + context.current.paintOffset.y());
-    RefPtr<TransformPaintPropertyNode> newTransformNodeForPreTranslation = TransformPaintPropertyNode::create(frameTranslate, FloatPoint3D(), context.current.transform);
+    if (TransformPaintPropertyNode* existingPreTranslation = frameView.preTranslation())
+        existingPreTranslation->update(context.current.transform, frameTranslate, FloatPoint3D());
+    else
+        frameView.setPreTranslation(TransformPaintPropertyNode::create(context.current.transform, frameTranslate, FloatPoint3D()));
 
     FloatRoundedRect contentClip(IntRect(IntPoint(), frameView.visibleContentSize()));
-    RefPtr<ClipPaintPropertyNode> newClipNodeForContentClip = ClipPaintPropertyNode::create(newTransformNodeForPreTranslation.get(), contentClip, context.current.clip);
+    if (ClipPaintPropertyNode* existingContentClip = frameView.contentClip())
+        existingContentClip->update(context.current.clip, frameView.preTranslation(), contentClip);
+    else
+        frameView.setContentClip(ClipPaintPropertyNode::create(context.current.clip, frameView.preTranslation(), contentClip));
 
     DoubleSize scrollOffset = frameView.scrollOffsetDouble();
     TransformationMatrix frameScroll;
     frameScroll.translate(-scrollOffset.width(), -scrollOffset.height());
-    RefPtr<TransformPaintPropertyNode> newTransformNodeForScrollTranslation = TransformPaintPropertyNode::create(frameScroll, FloatPoint3D(), newTransformNodeForPreTranslation);
+    if (TransformPaintPropertyNode* existingScrollTranslation = frameView.scrollTranslation())
+        existingScrollTranslation->update(frameView.preTranslation(), frameScroll, FloatPoint3D());
+    else
+        frameView.setScrollTranslation(TransformPaintPropertyNode::create(frameView.preTranslation(), frameScroll, FloatPoint3D()));
 
     // Initialize the context for current, absolute and fixed position cases.
     // They are the same, except that scroll translation does not apply to
     // fixed position descendants.
-    context.current.transform = newTransformNodeForScrollTranslation.get();
+    context.current.transform = frameView.scrollTranslation();
     context.current.paintOffset = LayoutPoint();
-    context.current.clip = newClipNodeForContentClip.get();
+    context.current.clip = frameView.contentClip();
     context.absolutePosition = context.current;
     context.containerForAbsolutePosition = nullptr;
     context.fixedPosition = context.current;
-    context.fixedPosition.transform = newTransformNodeForPreTranslation.get();
+    context.fixedPosition.transform = frameView.preTranslation();
+}
 
-    frameView.setPreTranslation(newTransformNodeForPreTranslation.release());
-    frameView.setScrollTranslation(newTransformNodeForScrollTranslation.release());
-    frameView.setContentClip(newClipNodeForContentClip.release());
+template <typename PropertyNode, void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>)>
+void PaintPropertyTreeBuilder::clearPaintProperty(const LayoutObject& object)
+{
+    if (ObjectPaintProperties* existingProperties = object.objectPaintProperties())
+        (existingProperties->*Setter)(nullptr);
+}
+
+template <
+    typename PropertyNode,
+    PropertyNode* (ObjectPaintProperties::*Getter)() const,
+    void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>),
+    typename... Args>
+void PaintPropertyTreeBuilder::updateOrCreatePaintProperty(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context, PropertyNode*& contextProperty, const Args&... args)
+{
+    ObjectPaintProperties* existingProperties = object.objectPaintProperties();
+    PropertyNode* existingPropertyNode = existingProperties ? (existingProperties->*Getter)() : nullptr;
+    if (existingPropertyNode) {
+        existingPropertyNode->update(contextProperty, args...);
+        contextProperty = existingPropertyNode;
+    } else {
+        RefPtr<PropertyNode> newPropertyNode = PropertyNode::create(contextProperty, args...);
+        contextProperty = newPropertyNode.get();
+        (object.getMutableForPainting().ensureObjectPaintProperties().*Setter)(newPropertyNode.release());
+    }
 }
 
 void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
 {
-    if (object.isBoxModelObject()) {
+    if (object.isBoxModelObject() && context.current.paintOffset != LayoutPoint()) {
         // TODO(trchen): Eliminate PaintLayer dependency.
         PaintLayer* layer = toLayoutBoxModelObject(object).layer();
-        if (!layer || !layer->paintsWithTransform(GlobalPaintNormalPhase))
+        if (layer && layer->paintsWithTransform(GlobalPaintNormalPhase)) {
+            // We should use the same subpixel paint offset values for snapping regardless of whether a
+            // transform is present. If there is a transform we round the paint offset but keep around
+            // the residual fractional component for the transformed content to paint with.
+            // In spv1 this was called "subpixel accumulation". For more information, see
+            // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentByApplyingTransform.
+            IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
+            LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset);
+
+            updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::paintOffsetTranslation, &ObjectPaintProperties::setPaintOffsetTranslation>(
+                object, context, context.current.transform, TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y()), FloatPoint3D());
+            context.current.paintOffset = fractionalPaintOffset;
             return;
+        }
     }
-
-    if (context.current.paintOffset == LayoutPoint())
-        return;
-
-    // We should use the same subpixel paint offset values for snapping regardless of whether a
-    // transform is present. If there is a transform we round the paint offset but keep around
-    // the residual fractional component for the transformed content to paint with.
-    // In spv1 this was called "subpixel accumulation". For more information, see
-    // PaintLayer::subpixelAccumulation() and PaintLayerPainter::paintFragmentByApplyingTransform.
-    IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
-    LayoutPoint fractionalPaintOffset = LayoutPoint(context.current.paintOffset - roundedPaintOffset);
-
-    RefPtr<TransformPaintPropertyNode> paintOffsetTranslation = TransformPaintPropertyNode::create(
-        TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y()),
-        FloatPoint3D(), context.current.transform);
-    context.current.transform = paintOffsetTranslation.get();
-    context.current.paintOffset = fractionalPaintOffset;
-    object.getMutableForPainting().ensureObjectPaintProperties().setPaintOffsetTranslation(paintOffsetTranslation.release());
+    clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setPaintOffsetTranslation>(object);
 }
 
 static FloatPoint3D transformOrigin(const LayoutBox& box)
@@ -117,56 +144,52 @@
         // the animation passes through the identity matrix.
         // FIXME(pdr): Refactor this so all non-root SVG objects use the same transform function.
         const AffineTransform& transform = object.isSVGForeignObject() ? object.localSVGTransform() : object.localToSVGParentTransform();
-        if (transform.isIdentity())
+        if (!transform.isIdentity()) {
+            // The origin is included in the local transform, so leave origin empty.
+            updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::transform, &ObjectPaintProperties::setTransform>(
+                object, context, context.current.transform, TransformationMatrix(transform), FloatPoint3D());
             return;
-
-        // The origin is included in the local transform, so use an empty origin.
-        RefPtr<TransformPaintPropertyNode> svgTransform = TransformPaintPropertyNode::create(
-            transform, FloatPoint3D(0, 0, 0), context.current.transform);
-        context.current.transform = svgTransform.get();
-        object.getMutableForPainting().ensureObjectPaintProperties().setTransform(svgTransform.release());
-        return;
+        }
+    } else {
+        const ComputedStyle& style = object.styleRef();
+        if (object.isBox() && style.hasTransform()) {
+            TransformationMatrix matrix;
+            style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::ExcludeTransformOrigin,
+                ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties);
+            FloatPoint3D origin = transformOrigin(toLayoutBox(object));
+            updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::transform, &ObjectPaintProperties::setTransform>(
+                object, context, context.current.transform, matrix, origin);
+            return;
+        }
     }
-
-    const ComputedStyle& style = object.styleRef();
-    if (!object.isBox() || !style.hasTransform())
-        return;
-
-    TransformationMatrix matrix;
-    style.applyTransform(matrix, toLayoutBox(object).size(), ComputedStyle::ExcludeTransformOrigin,
-        ComputedStyle::IncludeMotionPath, ComputedStyle::IncludeIndependentTransformProperties);
-    RefPtr<TransformPaintPropertyNode> transformNode = TransformPaintPropertyNode::create(
-        matrix, transformOrigin(toLayoutBox(object)), context.current.transform);
-    context.current.transform = transformNode.get();
-    object.getMutableForPainting().ensureObjectPaintProperties().setTransform(transformNode.release());
+    clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setTransform>(object);
 }
 
 void PaintPropertyTreeBuilder::updateEffect(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
 {
-    if (!object.styleRef().hasOpacity())
+    if (!object.styleRef().hasOpacity()) {
+        clearPaintProperty<EffectPaintPropertyNode, &ObjectPaintProperties::setEffect>(object);
         return;
-    RefPtr<EffectPaintPropertyNode> effectNode = EffectPaintPropertyNode::create(object.styleRef().opacity(), context.currentEffect);
-    context.currentEffect = effectNode.get();
-    object.getMutableForPainting().ensureObjectPaintProperties().setEffect(effectNode.release());
+    }
+
+    updateOrCreatePaintProperty<EffectPaintPropertyNode, &ObjectPaintProperties::effect, &ObjectPaintProperties::setEffect>(
+        object, context, context.currentEffect, object.styleRef().opacity());
 }
 
 void PaintPropertyTreeBuilder::updateCssClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
 {
-    if (!object.hasClip())
+    if (object.hasClip()) {
+        // Create clip node for descendants that are not fixed position.
+        // We don't have to setup context.absolutePosition.clip here because this object must be
+        // a container for absolute position descendants, and will copy from in-flow context later
+        // at updateOutOfFlowContext() step.
+        DCHECK(object.canContainAbsolutePositionObjects());
+        LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffset);
+        updateOrCreatePaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::cssClip, &ObjectPaintProperties::setCssClip>(
+            object, context, context.current.clip, context.current.transform, FloatRoundedRect(FloatRect(clipRect)));
         return;
-    ASSERT(object.canContainAbsolutePositionObjects());
-
-    // Create clip node for descendants that are not fixed position.
-    // We don't have to setup context.absolutePosition.clip here because this object must be
-    // a container for absolute position descendants, and will copy from in-flow context later
-    // at updateOutOfFlowContext() step.
-    LayoutRect clipRect = toLayoutBox(object).clipRect(context.current.paintOffset);
-    RefPtr<ClipPaintPropertyNode> clipNode = ClipPaintPropertyNode::create(
-        context.current.transform,
-        FloatRoundedRect(FloatRect(clipRect)),
-        context.current.clip);
-    context.current.clip = clipNode.get();
-    object.getMutableForPainting().ensureObjectPaintProperties().setCssClip(clipNode.release());
+    }
+    clearPaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::setCssClip>(object);
 }
 
 void PaintPropertyTreeBuilder::updateLocalBorderBoxContext(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
@@ -186,20 +209,20 @@
 void PaintPropertyTreeBuilder::updateScrollbarPaintOffset(const LayoutObject& object, const PaintPropertyTreeBuilderContext& context)
 {
     IntPoint roundedPaintOffset = roundedIntPoint(context.current.paintOffset);
-    if (roundedPaintOffset == IntPoint())
-        return;
-
-    if (!object.isBoxModelObject())
-        return;
-    PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).getScrollableArea();
-    if (!scrollableArea)
-        return;
-    if (!scrollableArea->horizontalScrollbar() && !scrollableArea->verticalScrollbar())
-        return;
-
-    auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y());
-    object.getMutableForPainting().ensureObjectPaintProperties().setScrollbarPaintOffset(
-        TransformPaintPropertyNode::create(paintOffset, FloatPoint3D(), context.current.transform));
+    if (roundedPaintOffset != IntPoint() && object.isBoxModelObject()) {
+        if (PaintLayerScrollableArea* scrollableArea = toLayoutBoxModelObject(object).getScrollableArea()) {
+            if (scrollableArea->horizontalScrollbar() || scrollableArea->verticalScrollbar()) {
+                auto paintOffset = TransformationMatrix().translate(roundedPaintOffset.x(), roundedPaintOffset.y());
+                // Make a copy of context.current.transform because we don't want to set the scrollbarPaintOffset node
+                // as the current transform.
+                TransformPaintPropertyNode* parentTransform = context.current.transform;
+                updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::scrollbarPaintOffset, &ObjectPaintProperties::setScrollbarPaintOffset>(
+                    object, context, parentTransform, paintOffset, FloatPoint3D());
+                return;
+            }
+        }
+    }
+    clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setScrollbarPaintOffset>(object);
 }
 
 void PaintPropertyTreeBuilder::updateOverflowClip(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
@@ -213,27 +236,26 @@
     // We should clip the overflow from those children. This is called control clip and we
     // technically treat them like overflow clip.
     LayoutRect clipRect;
-    if (box.hasControlClip())
+    if (box.hasControlClip()) {
         clipRect = box.controlClipRect(context.current.paintOffset);
-    else if (box.hasOverflowClip())
+    } else if (box.hasOverflowClip()) {
         clipRect = box.overflowClipRect(context.current.paintOffset);
-    else
+    } else {
+        clearPaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::setOverflowClip>(object);
         return;
+    }
 
+    // This need to be in top-level block to hold the reference until we finish creating the normal clip node.
     RefPtr<ClipPaintPropertyNode> borderRadiusClip;
     if (box.styleRef().hasBorderRadius()) {
         auto innerBorder = box.styleRef().getRoundedInnerBorderFor(
             LayoutRect(context.current.paintOffset, box.size()));
-        borderRadiusClip = ClipPaintPropertyNode::create(
-            context.current.transform, innerBorder, context.current.clip);
+        borderRadiusClip = ClipPaintPropertyNode::create(context.current.clip, context.current.transform, innerBorder);
+        context.current.clip = borderRadiusClip.get();
     }
 
-    RefPtr<ClipPaintPropertyNode> overflowClip = ClipPaintPropertyNode::create(
-        context.current.transform,
-        FloatRoundedRect(FloatRect(clipRect)),
-        borderRadiusClip ? borderRadiusClip.release() : context.current.clip);
-    context.current.clip = overflowClip.get();
-    object.getMutableForPainting().ensureObjectPaintProperties().setOverflowClip(overflowClip.release());
+    updateOrCreatePaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::overflowClip, &ObjectPaintProperties::setOverflowClip>(
+        object, context, context.current.clip, context.current.transform, FloatRoundedRect(FloatRect(clipRect)));
 }
 
 static FloatPoint perspectiveOrigin(const LayoutBox& box)
@@ -248,15 +270,14 @@
 void PaintPropertyTreeBuilder::updatePerspective(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
 {
     const ComputedStyle& style = object.styleRef();
-    if (!object.isBox() || !style.hasPerspective())
+    if (!object.isBox() || !style.hasPerspective()) {
+        clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setPerspective>(object);
         return;
+    }
 
-    RefPtr<TransformPaintPropertyNode> perspective = TransformPaintPropertyNode::create(
-        TransformationMatrix().applyPerspective(style.perspective()),
-        perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.paintOffset),
-        context.current.transform);
-    context.current.transform = perspective.get();
-    object.getMutableForPainting().ensureObjectPaintProperties().setPerspective(perspective.release());
+    FloatPoint3D origin = perspectiveOrigin(toLayoutBox(object)) + toLayoutSize(context.current.paintOffset);
+    updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::perspective, &ObjectPaintProperties::setPerspective>(
+        object, context, context.current.transform, TransformationMatrix().applyPerspective(style.perspective()), origin);
 }
 
 void PaintPropertyTreeBuilder::updateSvgLocalToBorderBoxTransform(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
@@ -270,33 +291,30 @@
     // offset internally.
     context.current.paintOffset = LayoutPoint();
 
-    if (transformToBorderBox.isIdentity())
+    if (transformToBorderBox.isIdentity()) {
+        clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setSvgLocalToBorderBoxTransform>(object);
         return;
+    }
 
-    RefPtr<TransformPaintPropertyNode> svgLocalToBorderBoxTransform = TransformPaintPropertyNode::create(
-        transformToBorderBox, FloatPoint3D(0, 0, 0), context.current.transform);
-    context.current.transform = svgLocalToBorderBoxTransform.get();
-    context.current.paintOffset = LayoutPoint();
-    object.getMutableForPainting().ensureObjectPaintProperties().setSvgLocalToBorderBoxTransform(svgLocalToBorderBoxTransform.release());
+    updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::svgLocalToBorderBoxTransform, &ObjectPaintProperties::setSvgLocalToBorderBoxTransform>(
+        object, context, context.current.transform, transformToBorderBox, FloatPoint3D());
 }
 
 void PaintPropertyTreeBuilder::updateScrollTranslation(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
 {
-    if (!object.isBoxModelObject() || !object.hasOverflowClip())
-        return;
+    if (object.isBoxModelObject() && object.hasOverflowClip()) {
+        PaintLayer* layer = toLayoutBoxModelObject(object).layer();
+        DCHECK(layer);
+        DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset();
 
-    PaintLayer* layer = toLayoutBoxModelObject(object).layer();
-    ASSERT(layer);
-    DoubleSize scrollOffset = layer->getScrollableArea()->scrollOffset();
-    if (scrollOffset.isZero() && !layer->scrollsOverflow())
-        return;
-
-    RefPtr<TransformPaintPropertyNode> scrollTranslation = TransformPaintPropertyNode::create(
-        TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.height()),
-        FloatPoint3D(),
-        context.current.transform);
-    context.current.transform = scrollTranslation.get();
-    object.getMutableForPainting().ensureObjectPaintProperties().setScrollTranslation(scrollTranslation.release());
+        if (!scrollOffset.isZero() || layer->scrollsOverflow()) {
+            TransformationMatrix matrix = TransformationMatrix().translate(-scrollOffset.width(), -scrollOffset.height());
+            updateOrCreatePaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::scrollTranslation, &ObjectPaintProperties::setScrollTranslation>(
+                object, context, context.current.transform, matrix, FloatPoint3D());
+            return;
+        }
+    }
+    clearPaintProperty<TransformPaintPropertyNode, &ObjectPaintProperties::setScrollTranslation>(object);
 }
 
 void PaintPropertyTreeBuilder::updateOutOfFlowContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
@@ -322,16 +340,13 @@
         // context has exactly the same clip. Reuse if possible.
         if (context.fixedPosition.clip == cssClip->parent()) {
             context.fixedPosition.clip = cssClip;
+        } else {
+            updateOrCreatePaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::cssClipFixedPosition, &ObjectPaintProperties::setCssClipFixedPosition>(
+                object, context, context.fixedPosition.clip, const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace()), cssClip->clipRect());
             return;
         }
-
-        RefPtr<ClipPaintPropertyNode> clipFixedPosition = ClipPaintPropertyNode::create(
-            const_cast<TransformPaintPropertyNode*>(cssClip->localTransformSpace()),
-            cssClip->clipRect(),
-            context.fixedPosition.clip);
-        context.fixedPosition.clip = clipFixedPosition.get();
-        object.getMutableForPainting().ensureObjectPaintProperties().setCssClipFixedPosition(clipFixedPosition.release());
     }
+    clearPaintProperty<ClipPaintPropertyNode, &ObjectPaintProperties::setCssClipFixedPosition>(object);
 }
 
 static void deriveBorderBoxFromContainerContext(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
@@ -385,8 +400,6 @@
 
 void PaintPropertyTreeBuilder::buildTreeNodes(const LayoutObject& object, PaintPropertyTreeBuilderContext& context)
 {
-    object.getMutableForPainting().clearObjectPaintProperties();
-
     if (!object.isBoxModelObject() && !object.isSVG())
         return;
 
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
index 16f0708..72a21f3d 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -15,6 +15,7 @@
 
 class FrameView;
 class LayoutObject;
+class ObjectPaintProperties;
 
 // The context for PaintPropertyTreeBuilder.
 // It's responsible for bookkeeping tree state in other order, for example, the most recent
@@ -67,6 +68,16 @@
     void buildTreeNodes(const LayoutObject&, PaintPropertyTreeBuilderContext&);
 
 private:
+    template <typename PropertyNode, void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>)>
+    static void clearPaintProperty(const LayoutObject&);
+
+    template <
+        typename PropertyNode,
+        PropertyNode* (ObjectPaintProperties::*Getter)() const,
+        void (ObjectPaintProperties::*Setter)(PassRefPtr<PropertyNode>),
+        typename... Args>
+    static void updateOrCreatePaintProperty(const LayoutObject&, const PaintPropertyTreeBuilderContext&, PropertyNode*& contextProperty, const Args&...);
+
     static void updatePaintOffsetTranslation(const LayoutObject&, PaintPropertyTreeBuilderContext&);
     static void updateTransform(const LayoutObject&, PaintPropertyTreeBuilderContext&);
     static void updateEffect(const LayoutObject&, PaintPropertyTreeBuilderContext&);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 0bd39b2..9979fdd 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -1109,4 +1109,78 @@
     EXPECT_EQ(svgWithTransformProperties->transform(), rectWithTransformProperties->transform()->parent());
 }
 
+TEST_F(PaintPropertyTreeBuilderTest, CachedProperties)
+{
+    setBodyInnerHTML(
+        "<div id='a' style='transform: translate(33px, 44px)'>"
+        "  <div id='b' style='transform: translate(55px, 66px)'>"
+        "    <div id='c' style='transform: translate(77px, 88px)'>C<div>"
+        "  </div>"
+        "</div>");
+
+    Element* a = document().getElementById("a");
+    ObjectPaintProperties* aProperties = a->layoutObject()->objectPaintProperties();
+    TransformPaintPropertyNode* aTransformNode = aProperties->transform();
+    EXPECT_EQ(TransformationMatrix().translate(33, 44), aTransformNode->matrix());
+
+    Element* b = document().getElementById("b");
+    ObjectPaintProperties* bProperties = b->layoutObject()->objectPaintProperties();
+    TransformPaintPropertyNode* bTransformNode = bProperties->transform();
+    EXPECT_EQ(TransformationMatrix().translate(55, 66), bTransformNode->matrix());
+
+    Element* c = document().getElementById("c");
+    ObjectPaintProperties* cProperties = c->layoutObject()->objectPaintProperties();
+    TransformPaintPropertyNode* cTransformNode = cProperties->transform();
+    EXPECT_EQ(TransformationMatrix().translate(77, 88), cTransformNode->matrix());
+
+    // Change transform of b. B's transform node should be a new node with the new value,
+    // and a and c's transform nodes should be unchanged (with c's parent adjusted).
+    b->setAttribute(HTMLNames::styleAttr, "transform: translate(111px, 222px)");
+    document().view()->updateAllLifecyclePhases();
+
+    EXPECT_EQ(aProperties, a->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(aTransformNode, aProperties->transform());
+
+    EXPECT_EQ(bProperties, b->layoutObject()->objectPaintProperties());
+    bTransformNode = bProperties->transform();
+    EXPECT_EQ(TransformationMatrix().translate(111, 222), bTransformNode->matrix());
+    EXPECT_EQ(aTransformNode, bTransformNode->parent());
+
+    EXPECT_EQ(cProperties, c->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(cTransformNode, cProperties->transform());
+    EXPECT_EQ(bTransformNode, cTransformNode->parent());
+
+    // Remove transform from b. B's transform node should be removed from the tree,
+    // and a and c's transform nodes should be unchanged (with c's parent adjusted).
+    b->setAttribute(HTMLNames::styleAttr, "");
+    document().view()->updateAllLifecyclePhases();
+
+    EXPECT_EQ(aProperties, a->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(aTransformNode, aProperties->transform());
+
+    EXPECT_EQ(bProperties, b->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(nullptr, bProperties->transform());
+
+    EXPECT_EQ(cProperties, c->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(cTransformNode, cProperties->transform());
+    EXPECT_EQ(aTransformNode, cTransformNode->parent());
+
+    // Re-add transform to b. B's transform node should be inserted into the tree,
+    // and a and c's transform nodes should be unchanged (with c's parent adjusted).
+    b->setAttribute(HTMLNames::styleAttr, "transform: translate(4px, 5px)");
+    document().view()->updateAllLifecyclePhases();
+
+    EXPECT_EQ(aProperties, a->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(aTransformNode, aProperties->transform());
+
+    EXPECT_EQ(bProperties, b->layoutObject()->objectPaintProperties());
+    bTransformNode = bProperties->transform();
+    EXPECT_EQ(TransformationMatrix().translate(4, 5), bTransformNode->matrix());
+    EXPECT_EQ(aTransformNode, bTransformNode->parent());
+
+    EXPECT_EQ(cProperties, c->layoutObject()->objectPaintProperties());
+    EXPECT_EQ(cTransformNode, cProperties->transform());
+    EXPECT_EQ(bTransformNode, cTransformNode->parent());
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 8f5d6fb3..eb7388e 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1925,6 +1925,23 @@
     return false;
 }
 
+static inline Vector<GridTrackSize> initialGridAutoTracks()
+{
+    Vector<GridTrackSize> trackSizeList;
+    trackSizeList.append(GridTrackSize(Length(Auto)));
+    return trackSizeList;
+}
+
+Vector<GridTrackSize> ComputedStyle::initialGridAutoColumns()
+{
+    return initialGridAutoTracks();
+}
+
+Vector<GridTrackSize> ComputedStyle::initialGridAutoRows()
+{
+    return initialGridAutoTracks();
+}
+
 int adjustForAbsoluteZoom(int value, float zoomFactor)
 {
     if (zoomFactor == 1)
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index aec7897..fedbec2e 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -848,8 +848,8 @@
     bool isGridAutoFlowDirectionColumn() const { return (m_rareNonInheritedData->m_grid->m_gridAutoFlow & InternalAutoFlowDirectionColumn) == InternalAutoFlowDirectionColumn; }
     bool isGridAutoFlowAlgorithmSparse() const { return (m_rareNonInheritedData->m_grid->m_gridAutoFlow & InternalAutoFlowAlgorithmSparse) == InternalAutoFlowAlgorithmSparse; }
     bool isGridAutoFlowAlgorithmDense() const { return (m_rareNonInheritedData->m_grid->m_gridAutoFlow & InternalAutoFlowAlgorithmDense) == InternalAutoFlowAlgorithmDense; }
-    const GridTrackSize& gridAutoColumns() const { return m_rareNonInheritedData->m_grid->m_gridAutoColumns; }
-    const GridTrackSize& gridAutoRows() const { return m_rareNonInheritedData->m_grid->m_gridAutoRows; }
+    const Vector<GridTrackSize>& gridAutoColumns() const { return m_rareNonInheritedData->m_grid->m_gridAutoColumns; }
+    const Vector<GridTrackSize>& gridAutoRows() const { return m_rareNonInheritedData->m_grid->m_gridAutoRows; }
     const Length& gridColumnGap() const { return m_rareNonInheritedData->m_grid->m_gridColumnGap; }
     const Length& gridRowGap() const { return m_rareNonInheritedData->m_grid->m_gridRowGap; }
 
@@ -1384,8 +1384,8 @@
     void setJustifySelf(const StyleSelfAlignmentData& data) { SET_VAR(m_rareNonInheritedData, m_justifySelf, data); }
     void setJustifySelfPosition(ItemPosition position) { m_rareNonInheritedData.access()->m_justifySelf.setPosition(position); }
     void setJustifySelfOverflow(OverflowAlignment overflow) { m_rareNonInheritedData.access()->m_justifySelf.setOverflow(overflow); }
-    void setGridAutoColumns(const GridTrackSize& length) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoColumns, length); }
-    void setGridAutoRows(const GridTrackSize& length) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoRows, length); }
+    void setGridAutoColumns(const Vector<GridTrackSize>& trackSizeList) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoColumns, trackSizeList); }
+    void setGridAutoRows(const Vector<GridTrackSize>& trackSizeList) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoRows, trackSizeList); }
     void setGridTemplateColumns(const Vector<GridTrackSize>& lengths) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridTemplateColumns, lengths); }
     void setGridTemplateRows(const Vector<GridTrackSize>& lengths) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridTemplateRows, lengths); }
     void setGridAutoRepeatColumns(const Vector<GridTrackSize>& trackSizes) { SET_NESTED_VAR(m_rareNonInheritedData, m_grid, m_gridAutoRepeatColumns, trackSizes); }
@@ -1843,8 +1843,8 @@
 
     static GridAutoFlow initialGridAutoFlow() { return AutoFlowRow; }
 
-    static GridTrackSize initialGridAutoColumns() { return GridTrackSize(Length(Auto)); }
-    static GridTrackSize initialGridAutoRows() { return GridTrackSize(Length(Auto)); }
+    static Vector<GridTrackSize> initialGridAutoColumns();
+    static Vector<GridTrackSize> initialGridAutoRows();
 
     static NamedGridLinesMap initialNamedGridColumnLines() { return NamedGridLinesMap(); }
     static NamedGridLinesMap initialNamedGridRowLines() { return NamedGridLinesMap(); }
diff --git a/third_party/WebKit/Source/core/style/StyleGridData.h b/third_party/WebKit/Source/core/style/StyleGridData.h
index 032d51dd..6eab749 100644
--- a/third_party/WebKit/Source/core/style/StyleGridData.h
+++ b/third_party/WebKit/Source/core/style/StyleGridData.h
@@ -83,8 +83,8 @@
 
     unsigned m_gridAutoFlow : GridAutoFlowBits;
 
-    GridTrackSize m_gridAutoRows;
-    GridTrackSize m_gridAutoColumns;
+    Vector<GridTrackSize> m_gridAutoRows;
+    Vector<GridTrackSize> m_gridAutoColumns;
 
     NamedGridAreaMap m_namedGridArea;
     // Because m_namedGridArea doesn't store the unnamed grid areas, we need to keep track
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
index 88a13ac..d2ef654 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -207,4 +207,12 @@
     invalidateMPathDependencies();
 }
 
+FloatRect SVGPathElement::getBBox()
+{
+    document().updateStyleAndLayoutIgnorePendingStylesheets();
+
+    // We want the exact bounds.
+    return SVGPathElement::asPath().boundingRect(Path::BoundsType::Exact);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.h b/third_party/WebKit/Source/core/svg/SVGPathElement.h
index 921e1bed..70779ef1 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.h
@@ -50,6 +50,8 @@
     bool isPresentationAttribute(const QualifiedName&) const override;
     bool isPresentationAttributeWithSVGDOM(const QualifiedName&) const override;
 
+    FloatRect getBBox() override;
+
     DECLARE_VIRTUAL_TRACE();
 
 private:
diff --git a/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.cpp b/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.cpp
index a4abd53d..bcd755a 100644
--- a/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPreserveAspectRatio.cpp
@@ -23,8 +23,8 @@
 
 #include "core/svg/SVGAnimationElement.h"
 #include "core/svg/SVGParserUtilities.h"
+#include "platform/ParsingUtilities.h"
 #include "platform/geometry/FloatRect.h"
-#include "platform/text/ParserUtilities.h"
 #include "platform/transforms/AffineTransform.h"
 #include "wtf/text/WTFString.h"
 
@@ -65,7 +65,7 @@
         return SVGParsingError(SVGParseStatus::ExpectedEnumeration, ptr - start);
 
     if (*ptr == 'n') {
-        if (!skipString(ptr, end, "none"))
+        if (!skipToken(ptr, end, "none"))
             return SVGParsingError(SVGParseStatus::ExpectedEnumeration, ptr - start);
         align = SVG_PRESERVEASPECTRATIO_NONE;
         skipOptionalSVGSpaces(ptr, end);
@@ -128,11 +128,11 @@
 
     if (ptr < end) {
         if (*ptr == 'm') {
-            if (!skipString(ptr, end, "meet"))
+            if (!skipToken(ptr, end, "meet"))
                 return SVGParsingError(SVGParseStatus::ExpectedEnumeration, ptr - start);
             skipOptionalSVGSpaces(ptr, end);
         } else if (*ptr == 's') {
-            if (!skipString(ptr, end, "slice"))
+            if (!skipToken(ptr, end, "slice"))
                 return SVGParsingError(SVGParseStatus::ExpectedEnumeration, ptr - start);
             skipOptionalSVGSpaces(ptr, end);
             if (align != SVG_PRESERVEASPECTRATIO_NONE)
diff --git a/third_party/WebKit/Source/core/svg/SVGTransformList.cpp b/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
index 32ac2b1..a1c17fc2 100644
--- a/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTransformList.cpp
@@ -26,7 +26,7 @@
 #include "core/SVGNames.h"
 #include "core/svg/SVGParserUtilities.h"
 #include "core/svg/SVGTransformDistance.h"
-#include "platform/text/ParserUtilities.h"
+#include "platform/ParsingUtilities.h"
 #include "wtf/text/StringBuilder.h"
 #include "wtf/text/WTFString.h"
 
@@ -64,13 +64,6 @@
 
 namespace {
 
-const LChar skewXDesc[] =  {'s', 'k', 'e', 'w', 'X'};
-const LChar skewYDesc[] =  {'s', 'k', 'e', 'w', 'Y'};
-const LChar scaleDesc[] =  {'s', 'c', 'a', 'l', 'e'};
-const LChar translateDesc[] =  {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', 'e'};
-const LChar rotateDesc[] =  {'r', 'o', 't', 'a', 't', 'e'};
-const LChar matrixDesc[] =  {'m', 'a', 't', 'r', 'i', 'x'};
-
 template<typename CharType>
 SVGTransformType parseAndSkipTransformType(const CharType*& ptr, const CharType* end)
 {
@@ -78,20 +71,20 @@
         return SVG_TRANSFORM_UNKNOWN;
 
     if (*ptr == 's') {
-        if (skipString(ptr, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc)))
+        if (skipToken(ptr, end, "skewX"))
             return SVG_TRANSFORM_SKEWX;
-        if (skipString(ptr, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc)))
+        if (skipToken(ptr, end, "skewY"))
             return SVG_TRANSFORM_SKEWY;
-        if (skipString(ptr, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc)))
+        if (skipToken(ptr, end, "scale"))
             return SVG_TRANSFORM_SCALE;
 
         return SVG_TRANSFORM_UNKNOWN;
     }
-    if (skipString(ptr, end, translateDesc, WTF_ARRAY_LENGTH(translateDesc)))
+    if (skipToken(ptr, end, "translate"))
         return SVG_TRANSFORM_TRANSLATE;
-    if (skipString(ptr, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc)))
+    if (skipToken(ptr, end, "rotate"))
         return SVG_TRANSFORM_ROTATE;
-    if (skipString(ptr, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc)))
+    if (skipToken(ptr, end, "matrix"))
         return SVG_TRANSFORM_MATRIX;
 
     return SVG_TRANSFORM_UNKNOWN;
diff --git a/third_party/WebKit/Source/core/svg/SVGURIReference.cpp b/third_party/WebKit/Source/core/svg/SVGURIReference.cpp
index 9738759..8ed6a84 100644
--- a/third_party/WebKit/Source/core/svg/SVGURIReference.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGURIReference.cpp
@@ -56,38 +56,49 @@
     return document.completeURL(stripLeadingAndTrailingHTMLSpaces(hrefString()));
 }
 
-AtomicString SVGURIReference::fragmentIdentifierFromIRIString(const String& urlString, const TreeScope& treeScope)
+SVGURLReferenceResolver::SVGURLReferenceResolver(const String& urlString, const Document& document)
+    : m_relativeUrl(urlString)
+    , m_document(&document)
+    , m_isLocal(urlString.startsWith('#'))
 {
-    const Document& document = treeScope.document();
-
-    KURL url = document.completeURL(urlString);
-    if (!url.hasFragmentIdentifier() || !equalIgnoringFragmentIdentifier(url, document.url()))
-        return emptyAtom;
-    return AtomicString(url.fragmentIdentifier());
 }
 
-Element* SVGURIReference::targetElementFromIRIString(const String& urlString, const TreeScope& treeScope, AtomicString* fragmentIdentifier, Document* externalDocument)
+KURL SVGURLReferenceResolver::absoluteUrl() const
 {
-    const Document& document = treeScope.document();
+    if (m_absoluteUrl.isNull())
+        m_absoluteUrl = m_document->completeURL(m_relativeUrl);
+    return m_absoluteUrl;
+}
 
-    KURL url = document.completeURL(urlString);
-    if (!url.hasFragmentIdentifier())
+bool SVGURLReferenceResolver::isLocal() const
+{
+    return m_isLocal || equalIgnoringFragmentIdentifier(absoluteUrl(), m_document->url());
+}
+
+AtomicString SVGURLReferenceResolver::fragmentIdentifier() const
+{
+    // If this is a "fragment-only" URL, then the reference is always local, so
+    // just return what's after the '#' as the fragment.
+    if (m_isLocal)
+        return AtomicString(m_relativeUrl.substring(1));
+    return AtomicString(absoluteUrl().fragmentIdentifier());
+}
+
+AtomicString SVGURIReference::fragmentIdentifierFromIRIString(const String& urlString, const TreeScope& treeScope)
+{
+    SVGURLReferenceResolver resolver(urlString, treeScope.document());
+    if (!resolver.isLocal())
+        return emptyAtom;
+    return resolver.fragmentIdentifier();
+}
+
+Element* SVGURIReference::targetElementFromIRIString(const String& urlString, const TreeScope& treeScope, AtomicString* fragmentIdentifier)
+{
+    AtomicString id = fragmentIdentifierFromIRIString(urlString, treeScope);
+    if (id.isEmpty())
         return nullptr;
-
-    AtomicString id(url.fragmentIdentifier());
     if (fragmentIdentifier)
         *fragmentIdentifier = id;
-
-    if (externalDocument) {
-        // Enforce that the referenced url matches the url of the document that we've loaded for it!
-        ASSERT(equalIgnoringFragmentIdentifier(url, externalDocument->url()));
-        return externalDocument->getElementById(id);
-    }
-
-    // Exit early if the referenced url is external, and we have no externalDocument given.
-    if (!equalIgnoringFragmentIdentifier(url, document.url()))
-        return nullptr;
-
     return treeScope.getElementById(id);
 }
 
diff --git a/third_party/WebKit/Source/core/svg/SVGURIReference.h b/third_party/WebKit/Source/core/svg/SVGURIReference.h
index cc05a4f5..0bf7ddcc 100644
--- a/third_party/WebKit/Source/core/svg/SVGURIReference.h
+++ b/third_party/WebKit/Source/core/svg/SVGURIReference.h
@@ -46,19 +46,7 @@
     KURL legacyHrefURL(const Document&) const;
 
     static AtomicString fragmentIdentifierFromIRIString(const String&, const TreeScope&);
-    static Element* targetElementFromIRIString(const String&, const TreeScope&, AtomicString* = 0, Document* = 0);
-
-    static inline bool isExternalURIReference(const String& uri, const Document& document)
-    {
-        // Fragment-only URIs are always internal if the baseURL is same as the document URL.
-        // This is common case, so check that first to avoid resolving URL (which is relatively expensive). See crbug.com/557979
-        if (document.baseURL() == document.url() && uri.startsWith('#'))
-            return false;
-
-        // If the URI matches our documents URL, we're dealing with a local reference.
-        KURL url = document.completeURL(uri);
-        return !equalIgnoringFragmentIdentifier(url, document.url());
-    }
+    static Element* targetElementFromIRIString(const String&, const TreeScope&, AtomicString* = nullptr);
 
     const String& hrefString() const { return m_href->currentValue()->value(); }
 
@@ -74,6 +62,24 @@
     Member<SVGAnimatedHref> m_href;
 };
 
+// Helper class used to resolve fragment references. Handles the 'local url
+// flag' per https://drafts.csswg.org/css-values/#local-urls .
+class SVGURLReferenceResolver {
+    STACK_ALLOCATED();
+public:
+    SVGURLReferenceResolver(const String& urlString, const Document&);
+
+    bool isLocal() const;
+    KURL absoluteUrl() const;
+    AtomicString fragmentIdentifier() const;
+
+private:
+    const String& m_relativeUrl;
+    Member<const Document> m_document;
+    mutable KURL m_absoluteUrl;
+    bool m_isLocal;
+};
+
 } // namespace blink
 
 #endif // SVGURIReference_h
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index 6ae9e76b..fe8395d 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -59,6 +59,7 @@
     , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(SVGLengthMode::Height)))
     , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(SVGLengthMode::Width)))
     , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(SVGLengthMode::Height)))
+    , m_elementIdentifierIsLocal(true)
     , m_haveFiredLoadEvent(false)
     , m_needsShadowTreeRecreation(false)
 {
@@ -131,15 +132,6 @@
     }
 }
 
-Document* SVGUseElement::externalDocument() const
-{
-    // Gracefully handle error condition.
-    if (!resourceIsValid())
-        return nullptr;
-    ASSERT(m_resource->document());
-    return m_resource->document();
-}
-
 static void transferUseWidthAndHeightIfNeeded(const SVGUseElement& use, SVGElement& shadowElement, const SVGElement& originalElement)
 {
     DEFINE_STATIC_LOCAL(const AtomicString, hundredPercentString, ("100%"));
@@ -192,6 +184,28 @@
         SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style);
 }
 
+bool SVGUseElement::isStructurallyExternal() const
+{
+    return !m_elementIdentifierIsLocal;
+}
+
+void SVGUseElement::updateTargetReference()
+{
+    SVGURLReferenceResolver resolver(hrefString(), document());
+    m_elementIdentifier = resolver.fragmentIdentifier();
+    m_elementIdentifierIsLocal = resolver.isLocal();
+    if (m_elementIdentifierIsLocal) {
+        setDocumentResource(nullptr);
+        return;
+    }
+    KURL resolvedUrl = resolver.absoluteUrl();
+    if (m_elementIdentifier.isEmpty()
+        || (m_resource && equalIgnoringFragmentIdentifier(resolvedUrl, m_resource->url())))
+        return;
+    FetchRequest request(ResourceRequest(resolvedUrl), localName());
+    setDocumentResource(DocumentResource::fetchSVGDocument(request, document().fetcher()));
+}
+
 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
 {
     if (attrName == SVGNames::xAttr
@@ -221,19 +235,8 @@
 
     if (SVGURIReference::isKnownAttribute(attrName)) {
         SVGElement::InvalidationGuard invalidationGuard(this);
-        if (isStructurallyExternal()) {
-            KURL url = document().completeURL(hrefString());
-            const KURL& existingURL = m_resource ? m_resource->url() : KURL();
-            if (url.hasFragmentIdentifier() && !equalIgnoringFragmentIdentifier(url, existingURL)) {
-                FetchRequest request(ResourceRequest(url), localName());
-                setDocumentResource(DocumentResource::fetchSVGDocument(request, document().fetcher()));
-            }
-        } else {
-            setDocumentResource(nullptr);
-        }
-
+        updateTargetReference();
         invalidateShadowTree();
-
         return;
     }
 
@@ -305,6 +308,29 @@
     removeAllOutgoingReferences();
 }
 
+Element* SVGUseElement::resolveTargetElement()
+{
+    if (m_elementIdentifier.isEmpty())
+        return nullptr;
+    const TreeScope* lookupScope = nullptr;
+    if (m_elementIdentifierIsLocal)
+        lookupScope = &treeScope();
+    else if (resourceIsValid())
+        lookupScope = m_resource->document();
+    else
+        return nullptr;
+    Element* target = lookupScope->getElementById(m_elementIdentifier);
+    // TODO(fs): Why would the Element not be "connected" at this point?
+    if (target && target->isConnected())
+        return target;
+    // Don't record any pending references for external resources.
+    if (!m_resource) {
+        document().accessSVGExtensions().addPendingResource(m_elementIdentifier, this);
+        DCHECK(hasPendingResources());
+    }
+    return nullptr;
+}
+
 void SVGUseElement::buildPendingResource()
 {
     if (inUseShadowTree())
@@ -313,26 +339,8 @@
     cancelShadowTreeRecreation();
     if (!isConnected())
         return;
-    Document* externalDocument = this->externalDocument();
-    if (isStructurallyExternal() && !externalDocument)
-        return;
-
-    AtomicString id;
-    Element* target = targetElementFromIRIString(hrefString(), treeScope(), &id, externalDocument);
-    if (!target || !target->isConnected()) {
-        // If we can't find the target of an external element, just give up.
-        // We can't observe if the target somewhen enters the external document, nor should we do it.
-        if (externalDocument)
-            return;
-        if (id.isEmpty())
-            return;
-
-        document().accessSVGExtensions().addPendingResource(id, this);
-        ASSERT(hasPendingResources());
-        return;
-    }
-
-    if (target->isSVGElement()) {
+    Element* target = resolveTargetElement();
+    if (target && target->isSVGElement()) {
         buildShadowAndInstanceTree(toSVGElement(*target));
         invalidateDependentShadowTrees();
     }
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.h b/third_party/WebKit/Source/core/svg/SVGUseElement.h
index e54a8b95..cd8332a 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.h
@@ -73,7 +73,7 @@
     void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) override;
     bool isPresentationAttributeWithSVGDOM(const QualifiedName&) const override;
 
-    bool isStructurallyExternal() const override { return !hrefString().isNull() && isExternalURIReference(hrefString(), document()); }
+    bool isStructurallyExternal() const override;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
     void removedFrom(ContainerNode*) override;
@@ -89,6 +89,7 @@
     bool selfHasRelativeLengths() const override;
 
     // Instance tree handling
+    Element* resolveTargetElement();
     void buildShadowAndInstanceTree(SVGElement& target);
     void clearInstanceRoot();
     Element* createInstanceTree(SVGElement& targetRoot) const;
@@ -102,10 +103,10 @@
 
     bool resourceIsStillLoading() const;
     bool resourceIsValid() const;
-    Document* externalDocument() const;
     bool instanceTreeIsLoading() const;
     void notifyFinished(Resource*) override;
     String debugName() const override { return "SVGUseElement"; }
+    void updateTargetReference();
     void setDocumentResource(DocumentResource*);
 
     Member<SVGAnimatedLength> m_x;
@@ -113,6 +114,8 @@
     Member<SVGAnimatedLength> m_width;
     Member<SVGAnimatedLength> m_height;
 
+    AtomicString m_elementIdentifier;
+    bool m_elementIdentifierIsLocal;
     bool m_haveFiredLoadEvent;
     bool m_needsShadowTreeRecreation;
     Member<SVGElement> m_targetElementInstance;
diff --git a/third_party/WebKit/Source/core/svg/SVGViewSpec.cpp b/third_party/WebKit/Source/core/svg/SVGViewSpec.cpp
index 353a8663..6bfbb2f 100644
--- a/third_party/WebKit/Source/core/svg/SVGViewSpec.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGViewSpec.cpp
@@ -25,7 +25,7 @@
 #include "core/dom/ExceptionCode.h"
 #include "core/svg/SVGAnimatedTransformList.h"
 #include "core/svg/SVGParserUtilities.h"
-#include "platform/text/ParserUtilities.h"
+#include "platform/ParsingUtilities.h"
 
 namespace blink {
 
@@ -132,17 +132,10 @@
     exceptionState.throwDOMException(NoModificationAllowedError, ExceptionMessages::readOnly());
 }
 
-static const LChar svgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'};
-static const LChar viewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'};
-static const LChar preserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'};
-static const LChar transformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'};
-static const LChar zoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'};
-static const LChar viewTargetSpec[] =  {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'};
-
 template<typename CharType>
 bool SVGViewSpec::parseViewSpecInternal(const CharType* ptr, const CharType* end)
 {
-    if (!skipString(ptr, end, svgViewSpec, WTF_ARRAY_LENGTH(svgViewSpec)))
+    if (!skipToken(ptr, end, "svgView"))
         return false;
 
     if (ptr >= end || *ptr != '(')
@@ -151,7 +144,7 @@
 
     while (ptr < end && *ptr != ')') {
         if (*ptr == 'v') {
-            if (skipString(ptr, end, viewBoxSpec, WTF_ARRAY_LENGTH(viewBoxSpec))) {
+            if (skipToken(ptr, end, "viewBox")) {
                 if (ptr >= end || *ptr != '(')
                     return false;
                 ptr++;
@@ -165,7 +158,7 @@
                 if (ptr >= end || *ptr != ')')
                     return false;
                 ptr++;
-            } else if (skipString(ptr, end, viewTargetSpec, WTF_ARRAY_LENGTH(viewTargetSpec))) {
+            } else if (skipToken(ptr, end, "viewTarget")) {
                 if (ptr >= end || *ptr != '(')
                     return false;
                 const CharType* viewTargetStart = ++ptr;
@@ -178,7 +171,7 @@
             } else
                 return false;
         } else if (*ptr == 'z') {
-            if (!skipString(ptr, end, zoomAndPanSpec, WTF_ARRAY_LENGTH(zoomAndPanSpec)))
+            if (!skipToken(ptr, end, "zoomAndPan"))
                 return false;
             if (ptr >= end || *ptr != '(')
                 return false;
@@ -189,7 +182,7 @@
                 return false;
             ptr++;
         } else if (*ptr == 'p') {
-            if (!skipString(ptr, end, preserveAspectRatioSpec, WTF_ARRAY_LENGTH(preserveAspectRatioSpec)))
+            if (!skipToken(ptr, end, "preserveAspectRatio"))
                 return false;
             if (ptr >= end || *ptr != '(')
                 return false;
@@ -200,7 +193,7 @@
                 return false;
             ptr++;
         } else if (*ptr == 't') {
-            if (!skipString(ptr, end, transformSpec, WTF_ARRAY_LENGTH(transformSpec)))
+            if (!skipToken(ptr, end, "transform"))
                 return false;
             if (ptr >= end || *ptr != '(')
                 return false;
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomAndPan.cpp b/third_party/WebKit/Source/core/svg/SVGZoomAndPan.cpp
index 1ad1288f..62b8313ec 100644
--- a/third_party/WebKit/Source/core/svg/SVGZoomAndPan.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGZoomAndPan.cpp
@@ -21,7 +21,7 @@
 
 #include "core/svg/SVGZoomAndPan.h"
 
-#include "platform/text/ParserUtilities.h"
+#include "platform/ParsingUtilities.h"
 
 namespace blink {
 
@@ -40,17 +40,14 @@
     return attrName == SVGNames::zoomAndPanAttr;
 }
 
-static const LChar disable[] =  {'d', 'i', 's', 'a', 'b', 'l', 'e'};
-static const LChar magnify[] =  {'m', 'a', 'g', 'n', 'i', 'f', 'y'};
-
 template<typename CharType>
 static bool parseZoomAndPanInternal(const CharType*& start, const CharType* end, SVGZoomAndPanType& zoomAndPan)
 {
-    if (skipString(start, end, disable, WTF_ARRAY_LENGTH(disable))) {
+    if (skipToken(start, end, "disable")) {
         zoomAndPan = SVGZoomAndPanDisable;
         return true;
     }
-    if (skipString(start, end, magnify, WTF_ARRAY_LENGTH(magnify))) {
+    if (skipToken(start, end, "magnify")) {
         zoomAndPan = SVGZoomAndPanMagnify;
         return true;
     }
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp
index cbe3d52..8e9fc13 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImageTest.cpp
@@ -39,7 +39,7 @@
 
     }
     bool runsTasksOnCurrentThread() override { return true; }
-    WebTaskRunner* clone() override { return nullptr; }
+    std::unique_ptr<WebTaskRunner> clone() override { return nullptr; }
     double virtualTimeSeconds() const override { return 0.0; }
     double monotonicallyIncreasingVirtualTimeSeconds() const override { return m_time; }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerBackingThread.h b/third_party/WebKit/Source/core/workers/WorkerBackingThread.h
index 79321b0..c47a3ac4 100644
--- a/third_party/WebKit/Source/core/workers/WorkerBackingThread.h
+++ b/third_party/WebKit/Source/core/workers/WorkerBackingThread.h
@@ -19,7 +19,7 @@
 
 // WorkerBackingThread represents a WebThread with Oilpan and V8 potentially
 // shared by multiple WebWorker scripts. A WebWorker needs to call initialize()
-// to using V8 and Oilpan functionalities, and call detach() when the script
+// to using V8 and Oilpan functionalities, and call shutdown() when the script
 // no longer needs the thread.
 // A WorkerBackingThread represents a WebThread while a WorkerThread corresponds
 // to a web worker. There is one-to-one correspondence between WorkerThread and
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index b28599c..5a61b75 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -63,7 +63,6 @@
 #include "wtf/RefPtr.h"
 
 namespace blink {
-
 namespace {
 
 void removeURLFromMemoryCacheInternal(const KURL& url)
@@ -297,7 +296,7 @@
     , m_closing(false)
     , m_eventQueue(WorkerEventQueue::create(this))
     , m_workerClients(workerClients)
-    , m_timers(Platform::current()->currentThread()->scheduler()->timerTaskRunner()->adoptClone())
+    , m_timers(Platform::current()->currentThread()->scheduler()->timerTaskRunner()->clone())
     , m_timeOrigin(timeOrigin)
     , m_consoleMessageStorage(new ConsoleMessageStorage())
 {
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi
index 716cb1e..8820cfe 100644
--- a/third_party/WebKit/Source/devtools/devtools.gypi
+++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -781,6 +781,7 @@
             'front_end/cm/javascript.js',
             'front_end/cm/markselection.js',
             'front_end/cm/matchbrackets.js',
+            'front_end/cm/multiplex.js',
             'front_end/cm/overlay.js',
             'front_end/cm/simple.js',
             'front_end/cm/xml.js',
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/LICENSE b/third_party/WebKit/Source/devtools/front_end/cm/LICENSE
index d21bbea5..7661321 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/LICENSE
+++ b/third_party/WebKit/Source/devtools/front_end/cm/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
+Copyright (C) 2016 by Marijn Haverbeke <marijnh@gmail.com> and others
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/activeline.js b/third_party/WebKit/Source/devtools/front_end/cm/activeline.js
index 22da2e0..b0b3f61 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/activeline.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/activeline.js
@@ -18,6 +18,7 @@
   "use strict";
   var WRAP_CLASS = "CodeMirror-activeline";
   var BACK_CLASS = "CodeMirror-activeline-background";
+  var GUTT_CLASS = "CodeMirror-activeline-gutter";
 
   CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
     var prev = old && old != CodeMirror.Init;
@@ -36,6 +37,7 @@
     for (var i = 0; i < cm.state.activeLines.length; i++) {
       cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
       cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
+      cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
     }
   }
 
@@ -60,6 +62,7 @@
       for (var i = 0; i < active.length; i++) {
         cm.addLineClass(active[i], "wrap", WRAP_CLASS);
         cm.addLineClass(active[i], "background", BACK_CLASS);
+        cm.addLineClass(active[i], "gutter", GUTT_CLASS);
       }
       cm.state.activeLines = active;
     });
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/closebrackets.js b/third_party/WebKit/Source/devtools/front_end/cm/closebrackets.js
index 83d4229..a8777b51 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/closebrackets.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/closebrackets.js
@@ -9,135 +9,187 @@
   else // Plain browser env
     mod(CodeMirror);
 })(function(CodeMirror) {
-  var DEFAULT_BRACKETS = "()[]{}''\"\"";
-  var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
-  var SPACE_CHAR_REGEX = /\s/;
+  var defaults = {
+    pairs: "()[]{}''\"\"",
+    triples: "",
+    explode: "[]{}"
+  };
 
   var Pos = CodeMirror.Pos;
 
   CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
-    if (old != CodeMirror.Init && old)
-      cm.removeKeyMap("autoCloseBrackets");
-    if (!val) return;
-    var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER;
-    if (typeof val == "string") pairs = val;
-    else if (typeof val == "object") {
-      if (val.pairs != null) pairs = val.pairs;
-      if (val.explode != null) explode = val.explode;
+    if (old && old != CodeMirror.Init) {
+      cm.removeKeyMap(keyMap);
+      cm.state.closeBrackets = null;
     }
-    var map = buildKeymap(pairs);
-    if (explode) map.Enter = buildExplodeHandler(explode);
-    cm.addKeyMap(map);
+    if (val) {
+      cm.state.closeBrackets = val;
+      cm.addKeyMap(keyMap);
+    }
   });
 
+  function getOption(conf, name) {
+    if (name == "pairs" && typeof conf == "string") return conf;
+    if (typeof conf == "object" && conf[name] != null) return conf[name];
+    return defaults[name];
+  }
+
+  var bind = defaults.pairs + "`";
+  var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
+  for (var i = 0; i < bind.length; i++)
+    keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
+
+  function handler(ch) {
+    return function(cm) { return handleChar(cm, ch); };
+  }
+
+  function getConfig(cm) {
+    var deflt = cm.state.closeBrackets;
+    if (!deflt) return null;
+    var mode = cm.getModeAt(cm.getCursor());
+    return mode.closeBrackets || deflt;
+  }
+
+  function handleBackspace(cm) {
+    var conf = getConfig(cm);
+    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
+
+    var pairs = getOption(conf, "pairs");
+    var ranges = cm.listSelections();
+    for (var i = 0; i < ranges.length; i++) {
+      if (!ranges[i].empty()) return CodeMirror.Pass;
+      var around = charsAround(cm, ranges[i].head);
+      if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
+    }
+    for (var i = ranges.length - 1; i >= 0; i--) {
+      var cur = ranges[i].head;
+      cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
+    }
+  }
+
+  function handleEnter(cm) {
+    var conf = getConfig(cm);
+    var explode = conf && getOption(conf, "explode");
+    if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
+
+    var ranges = cm.listSelections();
+    for (var i = 0; i < ranges.length; i++) {
+      if (!ranges[i].empty()) return CodeMirror.Pass;
+      var around = charsAround(cm, ranges[i].head);
+      if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
+    }
+    cm.operation(function() {
+      cm.replaceSelection("\n\n", null);
+      cm.execCommand("goCharLeft");
+      ranges = cm.listSelections();
+      for (var i = 0; i < ranges.length; i++) {
+        var line = ranges[i].head.line;
+        cm.indentLine(line, null, true);
+        cm.indentLine(line + 1, null, true);
+      }
+    });
+  }
+
+  function contractSelection(sel) {
+    var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
+    return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
+            head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
+  }
+
+  function handleChar(cm, ch) {
+    var conf = getConfig(cm);
+    if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
+
+    var pairs = getOption(conf, "pairs");
+    var pos = pairs.indexOf(ch);
+    if (pos == -1) return CodeMirror.Pass;
+    var triples = getOption(conf, "triples");
+
+    var identical = pairs.charAt(pos + 1) == ch;
+    var ranges = cm.listSelections();
+    var opening = pos % 2 == 0;
+
+    var type;
+    for (var i = 0; i < ranges.length; i++) {
+      var range = ranges[i], cur = range.head, curType;
+      var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
+      if (opening && !range.empty()) {
+        curType = "surround";
+      } else if ((identical || !opening) && next == ch) {
+        if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
+          curType = "skipThree";
+        else
+          curType = "skip";
+      } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
+                 cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
+                 (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
+        curType = "addFour";
+      } else if (identical) {
+        if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
+        else return CodeMirror.Pass;
+      } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
+                             isClosingBracket(next, pairs) ||
+                             /\s/.test(next))) {
+        curType = "both";
+      } else {
+        return CodeMirror.Pass;
+      }
+      if (!type) type = curType;
+      else if (type != curType) return CodeMirror.Pass;
+    }
+
+    var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
+    var right = pos % 2 ? ch : pairs.charAt(pos + 1);
+    cm.operation(function() {
+      if (type == "skip") {
+        cm.execCommand("goCharRight");
+      } else if (type == "skipThree") {
+        for (var i = 0; i < 3; i++)
+          cm.execCommand("goCharRight");
+      } else if (type == "surround") {
+        var sels = cm.getSelections();
+        for (var i = 0; i < sels.length; i++)
+          sels[i] = left + sels[i] + right;
+        cm.replaceSelections(sels, "around");
+        sels = cm.listSelections().slice();
+        for (var i = 0; i < sels.length; i++)
+          sels[i] = contractSelection(sels[i]);
+        cm.setSelections(sels);
+      } else if (type == "both") {
+        cm.replaceSelection(left + right, null);
+        cm.triggerElectric(left + right);
+        cm.execCommand("goCharLeft");
+      } else if (type == "addFour") {
+        cm.replaceSelection(left + left + left + left, "before");
+        cm.execCommand("goCharRight");
+      }
+    });
+  }
+
+  function isClosingBracket(ch, pairs) {
+    var pos = pairs.lastIndexOf(ch);
+    return pos > -1 && pos % 2 == 1;
+  }
+
   function charsAround(cm, pos) {
     var str = cm.getRange(Pos(pos.line, pos.ch - 1),
                           Pos(pos.line, pos.ch + 1));
     return str.length == 2 ? str : null;
   }
 
-  function buildKeymap(pairs) {
-    var map = {
-      name : "autoCloseBrackets",
-      Backspace: function(cm) {
-        if (cm.getOption("disableInput")) return CodeMirror.Pass;
-        var ranges = cm.listSelections();
-        for (var i = 0; i < ranges.length; i++) {
-          if (!ranges[i].empty()) return CodeMirror.Pass;
-          var around = charsAround(cm, ranges[i].head);
-          if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
-        }
-        for (var i = ranges.length - 1; i >= 0; i--) {
-          var cur = ranges[i].head;
-          cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
-        }
-      }
-    };
-    var closingBrackets = "";
-    for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
-      if (left != right) closingBrackets += right;
-      map["'" + left + "'"] = function(cm) {
-        if (cm.getOption("disableInput")) return CodeMirror.Pass;
-        var ranges = cm.listSelections(), type, next;
-        for (var i = 0; i < ranges.length; i++) {
-          var range = ranges[i], cur = range.head, curType;
-          if (left == "'" && cm.getTokenTypeAt(cur) == "comment")
-            return CodeMirror.Pass;
-          var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
-          if (!range.empty())
-            curType = "surround";
-          else if (left == right && next == right) {
-            if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
-              curType = "skipThree";
-            else
-              curType = "skip";
-          } else if (left == right && cur.ch > 1 &&
-                     cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
-                     (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left))
-            curType = "addFour";
-          else if (left == right && CodeMirror.isWordChar(next))
-            return CodeMirror.Pass;
-          else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next))
-            curType = "both";
-          else
-            return CodeMirror.Pass;
-          if (!type) type = curType;
-          else if (type != curType) return CodeMirror.Pass;
-        }
-
-        cm.operation(function() {
-          if (type == "skip") {
-            cm.execCommand("goCharRight");
-          } else if (type == "skipThree") {
-            for (var i = 0; i < 3; i++)
-              cm.execCommand("goCharRight");
-          } else if (type == "surround") {
-            var sels = cm.getSelections();
-            for (var i = 0; i < sels.length; i++)
-              sels[i] = left + sels[i] + right;
-            cm.replaceSelections(sels, "around");
-          } else if (type == "both") {
-            cm.replaceSelection(left + right, null);
-            cm.execCommand("goCharLeft");
-          } else if (type == "addFour") {
-            cm.replaceSelection(left + left + left + left, "before");
-            cm.execCommand("goCharRight");
-          }
-        });
-      };
-      if (left != right) map["'" + right + "'"] = function(cm) {
-        var ranges = cm.listSelections();
-        for (var i = 0; i < ranges.length; i++) {
-          var range = ranges[i];
-          if (!range.empty() ||
-              cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
-            return CodeMirror.Pass;
-        }
-        cm.execCommand("goCharRight");
-      };
-    })(pairs.charAt(i), pairs.charAt(i + 1));
-    return map;
+  // Project the token type that will exists after the given char is
+  // typed, and use it to determine whether it would cause the start
+  // of a string token.
+  function enteringString(cm, pos, ch) {
+    var line = cm.getLine(pos.line);
+    var token = cm.getTokenAt(pos);
+    if (/\bstring2?\b/.test(token.type)) return false;
+    var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
+    stream.pos = stream.start = token.start;
+    for (;;) {
+      var type1 = cm.getMode().token(stream, token.state);
+      if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
+      stream.start = stream.pos;
+    }
   }
-
-  function buildExplodeHandler(pairs) {
-    return function(cm) {
-      if (cm.getOption("disableInput")) return CodeMirror.Pass;
-      var ranges = cm.listSelections();
-      for (var i = 0; i < ranges.length; i++) {
-        if (!ranges[i].empty()) return CodeMirror.Pass;
-        var around = charsAround(cm, ranges[i].head);
-        if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
-      }
-      cm.operation(function() {
-        cm.replaceSelection("\n\n", null);
-        cm.execCommand("goCharLeft");
-        ranges = cm.listSelections();
-        for (var i = 0; i < ranges.length; i++) {
-          var line = ranges[i].head.line;
-          cm.indentLine(line, null, true);
-          cm.indentLine(line + 1, null, true);
-        }
-      });
-    };
-  }
-});
+});
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css b/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css
index ef63109..18b0bf70 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css
+++ b/third_party/WebKit/Source/devtools/front_end/cm/codemirror.css
@@ -4,6 +4,7 @@
   /* Set height, width, borders, and global font properties here */
   font-family: monospace;
   height: 300px;
+  color: black;
 }
 
 /* PADDING */
@@ -32,8 +33,7 @@
   min-width: 20px;
   text-align: right;
   color: #999;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
+  white-space: nowrap;
 }
 
 .CodeMirror-guttermarker { color: black; }
@@ -41,19 +41,21 @@
 
 /* CURSOR */
 
-.CodeMirror div.CodeMirror-cursor {
+.CodeMirror-cursor {
   border-left: 1px solid black;
+  border-right: none;
+  width: 0;
 }
 /* Shown when moving in bi-directional text */
 .CodeMirror div.CodeMirror-secondarycursor {
   border-left: 1px solid silver;
 }
-.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
+.cm-fat-cursor .CodeMirror-cursor {
   width: auto;
-  border: 0;
+  border: 0 !important;
   background: #7e7;
 }
-.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
+.cm-fat-cursor div.CodeMirror-cursors {
   z-index: 1;
 }
 
@@ -63,35 +65,51 @@
   -webkit-animation: blink 1.06s steps(1) infinite;
   -moz-animation: blink 1.06s steps(1) infinite;
   animation: blink 1.06s steps(1) infinite;
+  background-color: #7e7;
 }
 @-moz-keyframes blink {
-  0% { background: #7e7; }
-  50% { background: none; }
-  100% { background: #7e7; }
+  0% {}
+  50% { background-color: transparent; }
+  100% {}
 }
 @-webkit-keyframes blink {
-  0% { background: #7e7; }
-  50% { background: none; }
-  100% { background: #7e7; }
+  0% {}
+  50% { background-color: transparent; }
+  100% {}
 }
 @keyframes blink {
-  0% { background: #7e7; }
-  50% { background: none; }
-  100% { background: #7e7; }
+  0% {}
+  50% { background-color: transparent; }
+  100% {}
 }
 
 /* Can style cursor different in overwrite (non-insert) mode */
-div.CodeMirror-overwrite div.CodeMirror-cursor {}
+.CodeMirror-overwrite .CodeMirror-cursor {}
 
 .cm-tab { display: inline-block; text-decoration: inherit; }
 
+.CodeMirror-rulers {
+  position: absolute;
+  left: 0; right: 0; top: -50px; bottom: -20px;
+  overflow: hidden;
+}
 .CodeMirror-ruler {
   border-left: 1px solid #ccc;
+  top: 0; bottom: 0;
   position: absolute;
 }
 
 /* DEFAULT THEME */
 
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
+
 .cm-s-default .cm-keyword {color: #708;}
 .cm-s-default .cm-atom {color: #219;}
 .cm-s-default .cm-number {color: #164;}
@@ -111,27 +129,20 @@
 .cm-s-default .cm-bracket {color: #997;}
 .cm-s-default .cm-tag {color: #170;}
 .cm-s-default .cm-attribute {color: #00c;}
-.cm-s-default .cm-header {color: blue;}
-.cm-s-default .cm-quote {color: #090;}
 .cm-s-default .cm-hr {color: #999;}
 .cm-s-default .cm-link {color: #00c;}
 
-.cm-negative {color: #d44;}
-.cm-positive {color: #292;}
-.cm-header, .cm-strong {font-weight: bold;}
-.cm-em {font-style: italic;}
-.cm-link {text-decoration: underline;}
-.cm-strikethrough {text-decoration: line-through;}
-
 .cm-s-default .cm-error {color: #f00;}
 .cm-invalidchar {color: #f00;}
 
+.CodeMirror-composing { border-bottom: 2px solid; }
+
 /* Default styles for common addons */
 
 div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
 div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
-.CodeMirror-activeline-background { background: #e8f2ff; }
+.CodeMirror-activeline-background {background: #e8f2ff;}
 
 /* STOP */
 
@@ -139,11 +150,9 @@
    the editor. You probably shouldn't touch them. */
 
 .CodeMirror {
-  line-height: 1;
   position: relative;
   overflow: hidden;
   background: white;
-  color: black;
 }
 
 .CodeMirror-scroll {
@@ -155,18 +164,14 @@
   height: 100%;
   outline: none; /* Prevent dragging from highlighting the element */
   position: relative;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
 }
 .CodeMirror-sizer {
   position: relative;
   border-right: 30px solid transparent;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
 }
 
 /* The fake, visible scrollbars. Used to force redraw during scrolling
-   before actuall scrolling happens, thus preventing shaking and
+   before actual scrolling happens, thus preventing shaking and
    flickering artifacts. */
 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
   position: absolute;
@@ -192,14 +197,14 @@
 
 .CodeMirror-gutters {
   position: absolute; left: 0; top: 0;
+  min-height: 100%;
   z-index: 3;
 }
 .CodeMirror-gutter {
   white-space: normal;
   height: 100%;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
   display: inline-block;
+  vertical-align: top;
   margin-bottom: -30px;
   /* Hack to make IE7 behave */
   *zoom:1;
@@ -208,13 +213,24 @@
 .CodeMirror-gutter-wrapper {
   position: absolute;
   z-index: 4;
-  height: 100%;
+  background: none !important;
+  border: none !important;
+}
+.CodeMirror-gutter-background {
+  position: absolute;
+  top: 0; bottom: 0;
+  z-index: 4;
 }
 .CodeMirror-gutter-elt {
   position: absolute;
   cursor: default;
   z-index: 4;
 }
+.CodeMirror-gutter-wrapper {
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+}
 
 .CodeMirror-lines {
   cursor: text;
@@ -235,6 +251,9 @@
   z-index: 2;
   position: relative;
   overflow: visible;
+  -webkit-tap-highlight-color: transparent;
+  -webkit-font-variant-ligatures: none;
+  font-variant-ligatures: none;
 }
 .CodeMirror-wrap pre {
   word-wrap: break-word;
@@ -256,6 +275,20 @@
 
 .CodeMirror-widget {}
 
+.CodeMirror-code {
+  outline: none;
+}
+
+/* Force content-box sizing for the elements where we expect it */
+.CodeMirror-scroll,
+.CodeMirror-sizer,
+.CodeMirror-gutter,
+.CodeMirror-gutters,
+.CodeMirror-linenumber {
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+}
+
 .CodeMirror-measure {
   position: absolute;
   width: 100%;
@@ -263,19 +296,22 @@
   overflow: hidden;
   visibility: hidden;
 }
-.CodeMirror-measure pre { position: static; }
 
-.CodeMirror div.CodeMirror-cursor {
+.CodeMirror-cursor {
   position: absolute;
-  border-right: none;
-  width: 0;
+  pointer-events: none;
 }
+.CodeMirror-measure pre { position: static; }
 
 div.CodeMirror-cursors {
   visibility: hidden;
   position: relative;
   z-index: 3;
 }
+div.CodeMirror-dragcursors {
+  visibility: visible;
+}
+
 .CodeMirror-focused div.CodeMirror-cursors {
   visibility: visible;
 }
@@ -283,6 +319,8 @@
 .CodeMirror-selected { background: #d9d9d9; }
 .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
 .CodeMirror-crosshair { cursor: crosshair; }
+.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
+.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
 
 .cm-searching {
   background: #ffa;
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/codemirror.js b/third_party/WebKit/Source/devtools/front_end/cm/codemirror.js
index 03a34db..cd73b84 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/codemirror.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/codemirror.js
@@ -13,7 +13,7 @@
   else if (typeof define == "function" && define.amd) // AMD
     return define([], mod);
   else // Plain browser env
-    this.CodeMirror = mod();
+    (this || window).CodeMirror = mod();
 })(function() {
   "use strict";
 
@@ -21,29 +21,30 @@
 
   // Kludges for bugs and behavior differences that can't be feature
   // detected are enabled based on userAgent etc sniffing.
+  var userAgent = navigator.userAgent;
+  var platform = navigator.platform;
 
-  var gecko = /gecko\/\d/i.test(navigator.userAgent);
-  // ie_uptoN means Internet Explorer version N or lower
-  var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
-  var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
+  var gecko = /gecko\/\d/i.test(userAgent);
+  var ie_upto10 = /MSIE \d/.test(userAgent);
+  var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
   var ie = ie_upto10 || ie_11up;
   var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
-  var webkit = /WebKit\//.test(navigator.userAgent);
-  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
-  var chrome = /Chrome\//.test(navigator.userAgent);
-  var presto = /Opera\//.test(navigator.userAgent);
+  var webkit = /WebKit\//.test(userAgent);
+  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
+  var chrome = /Chrome\//.test(userAgent);
+  var presto = /Opera\//.test(userAgent);
   var safari = /Apple Computer/.test(navigator.vendor);
-  var khtml = /KHTML\//.test(navigator.userAgent);
-  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
-  var phantom = /PhantomJS/.test(navigator.userAgent);
+  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
+  var phantom = /PhantomJS/.test(userAgent);
 
-  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
+  var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
   // This is woefully incomplete. Suggestions for alternative methods welcome.
-  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
-  var mac = ios || /Mac/.test(navigator.platform);
-  var windows = /win/i.test(navigator.platform);
+  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
+  var mac = ios || /Mac/.test(platform);
+  var chromeOS = /\bCrOS\b/.test(userAgent);
+  var windows = /win/i.test(platform);
 
-  var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
+  var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
   if (presto_version) presto_version = Number(presto_version[1]);
   if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
   // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
@@ -67,33 +68,40 @@
     setGuttersForLineNumbers(options);
 
     var doc = options.value;
-    if (typeof doc == "string") doc = new Doc(doc, options.mode);
+    if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator);
     this.doc = doc;
 
-    var display = this.display = new Display(place, doc);
+    var input = new CodeMirror.inputStyles[options.inputStyle](this);
+    var display = this.display = new Display(place, doc, input);
     display.wrapper.CodeMirror = this;
     updateGutters(this);
     themeChanged(this);
     if (options.lineWrapping)
       this.display.wrapper.className += " CodeMirror-wrap";
-    if (options.autofocus && !mobile) focusInput(this);
+    if (options.autofocus && !mobile) display.input.focus();
     initScrollbars(this);
 
     this.state = {
       keyMaps: [],  // stores maps added by addKeyMap
       overlays: [], // highlighting overlays, as added by addOverlay
       modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
-      overwrite: false, focused: false,
+      overwrite: false,
+      delayingBlurEvent: false,
+      focused: false,
       suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
-      pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput
+      pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
+      selectingText: false,
       draggingText: false,
       highlight: new Delayed(), // stores highlight worker timeout
-      keySeq: null  // Unfinished key sequence
+      keySeq: null,  // Unfinished key sequence
+      specialChars: null
     };
 
+    var cm = this;
+
     // Override magic textarea content restore that IE sometimes does
     // on our hidden textarea on reload
-    if (ie && ie_version < 11) setTimeout(bind(resetInput, this, true), 20);
+    if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
 
     registerEventHandlers(this);
     ensureGlobalHandlers();
@@ -102,7 +110,7 @@
     this.curOp.forceUpdate = true;
     attachDoc(this, doc);
 
-    if ((options.autofocus && !mobile) || activeElt() == display.input)
+    if ((options.autofocus && !mobile) || cm.hasFocus())
       setTimeout(bind(onFocus, this), 20);
     else
       onBlur(this);
@@ -110,6 +118,7 @@
     for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
       optionHandlers[opt](this, options[opt], Init);
     maybeUpdateLineNumberWidth(this);
+    if (options.finishInit) options.finishInit(this);
     for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
     endOperation(this);
     // Suppress optimizelegibility in Webkit, since it breaks text
@@ -125,31 +134,17 @@
   // and content drawing. It holds references to DOM nodes and
   // display-related state.
 
-  function Display(place, doc) {
+  function Display(place, doc, input) {
     var d = this;
+    this.input = input;
 
-    // The semihidden textarea that is focused when the editor is
-    // focused, and receives input.
-    var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
-    // The textarea is kept positioned near the cursor to prevent the
-    // fact that it'll be scrolled into view on input from scrolling
-    // our fake cursor out of view. On webkit, when wrap=off, paste is
-    // very slow. So make the area wide instead.
-    if (webkit) input.style.width = "1000px";
-    else input.setAttribute("wrap", "off");
-    // If border: 0; -- iOS fails to open keyboard (issue #1287)
-    if (ios) input.style.border = "1px solid black";
-    input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
-
-    // Wraps and hides input textarea
-    d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
     // Covers bottom-right square when both scrollbars are present.
     d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
-    d.scrollbarFiller.setAttribute("not-content", "true");
+    d.scrollbarFiller.setAttribute("cm-not-content", "true");
     // Covers bottom of gutter when coverGutterNextToScrollbar is on
     // and h scrollbar is present.
     d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
-    d.gutterFiller.setAttribute("not-content", "true");
+    d.gutterFiller.setAttribute("cm-not-content", "true");
     // Will contain the actual code, positioned to cover the viewport.
     d.lineDiv = elt("div", null, "CodeMirror-code");
     // Elements are added to these to represent selection and cursors.
@@ -178,15 +173,11 @@
     d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
     d.scroller.setAttribute("tabIndex", "-1");
     // The element in which the editor lives.
-    d.wrapper = elt("div", [d.inputDiv, d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
+    d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
 
     // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
     if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
-    // Needed to hide big blue blinking cursor on Mobile Safari
-    if (ios) input.style.width = "0px";
-    if (!webkit) d.scroller.draggable = true;
-    // Needed to handle Tab key in KHTML
-    if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
+    if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
 
     if (place) {
       if (place.appendChild) place.appendChild(d.wrapper);
@@ -213,25 +204,13 @@
     // Used to only resize the line number gutter when necessary (when
     // the amount of lines crosses a boundary that makes its width change)
     d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
-    // See readInput and resetInput
-    d.prevInput = "";
     // Set to true when a non-horizontal-scrolling line widget is
     // added. As an optimization, line widget aligning is skipped when
     // this is false.
     d.alignWidgets = false;
-    // Flag that indicates whether we expect input to appear real soon
-    // now (after some event like 'keypress' or 'input') and are
-    // polling intensively.
-    d.pollingFast = false;
-    // Self-resetting timeout for the poller
-    d.poll = new Delayed();
 
     d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
 
-    // Tracks when resetInput has punted to just putting a short
-    // string into the textarea instead of the full selection.
-    d.inaccurateSelection = false;
-
     // Tracks the maximum line length so that the horizontal scrollbar
     // can be kept static when scrolling.
     d.maxLine = null;
@@ -247,6 +226,10 @@
     // Used to track whether anything happened since the context menu
     // was opened.
     d.selForContextMenu = null;
+
+    d.activeTouch = null;
+
+    input.init(d);
   }
 
   // STATE UPDATES
@@ -428,7 +411,7 @@
       if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
     });
 
-    this.checkedOverlay = false;
+    this.checkedZeroWidth = false;
     // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
     if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
   }
@@ -463,29 +446,43 @@
         this.horiz.firstChild.style.width = "0";
       }
 
-      if (!this.checkedOverlay && measure.clientHeight > 0) {
-        if (sWidth == 0) this.overlayHack();
-        this.checkedOverlay = true;
+      if (!this.checkedZeroWidth && measure.clientHeight > 0) {
+        if (sWidth == 0) this.zeroWidthHack();
+        this.checkedZeroWidth = true;
       }
 
       return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
     },
     setScrollLeft: function(pos) {
       if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
+      if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz);
     },
     setScrollTop: function(pos) {
       if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
+      if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert);
     },
-    overlayHack: function() {
+    zeroWidthHack: function() {
       var w = mac && !mac_geMountainLion ? "12px" : "18px";
-      this.horiz.style.minHeight = this.vert.style.minWidth = w;
-      var self = this;
-      var barMouseDown = function(e) {
-        if (e_target(e) != self.vert && e_target(e) != self.horiz)
-          operation(self.cm, onMouseDown)(e);
-      };
-      on(this.vert, "mousedown", barMouseDown);
-      on(this.horiz, "mousedown", barMouseDown);
+      this.horiz.style.height = this.vert.style.width = w;
+      this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
+      this.disableHoriz = new Delayed;
+      this.disableVert = new Delayed;
+    },
+    enableZeroWidthBar: function(bar, delay) {
+      bar.style.pointerEvents = "auto";
+      function maybeDisable() {
+        // To find out whether the scrollbar is still visible, we
+        // check whether the element under the pixel in the bottom
+        // left corner of the scrollbar box is the scrollbar box
+        // itself (when the bar is still visible) or its filler child
+        // (when the bar is hidden). If it is still visible, we keep
+        // it enabled, if it's hidden, we disable pointer events.
+        var box = bar.getBoundingClientRect();
+        var elt = document.elementFromPoint(box.left + 1, box.bottom - 1);
+        if (elt != bar) bar.style.pointerEvents = "none";
+        else delay.set(1000, maybeDisable);
+      }
+      delay.set(1000, maybeDisable);
     },
     clear: function() {
       var parent = this.horiz.parentNode;
@@ -514,10 +511,11 @@
 
     cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
       cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
+      // Prevent clicks in the scrollbars from killing focus
       on(node, "mousedown", function() {
-        if (cm.state.focused) setTimeout(bind(focusInput, cm), 0);
+        if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
       });
-      node.setAttribute("not-content", "true");
+      node.setAttribute("cm-not-content", "true");
     }, function(pos, axis) {
       if (axis == "horizontal") setScrollLeft(cm, pos);
       else setScrollTop(cm, pos);
@@ -546,6 +544,7 @@
 
     d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
     d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
+    d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"
 
     if (sizes.right && sizes.bottom) {
       d.scrollbarFiller.style.display = "block";
@@ -614,7 +613,7 @@
                                                  "CodeMirror-linenumber CodeMirror-gutter-elt"));
       var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
       display.lineGutter.style.width = "";
-      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
       display.lineNumWidth = display.lineNumInnerWidth + padding;
       display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
       display.lineGutter.style.width = display.lineNumWidth + "px";
@@ -649,8 +648,18 @@
     this.oldDisplayWidth = displayWidth(cm);
     this.force = force;
     this.dims = getDimensions(cm);
+    this.events = [];
   }
 
+  DisplayUpdate.prototype.signal = function(emitter, type) {
+    if (hasHandler(emitter, type))
+      this.events.push(arguments);
+  };
+  DisplayUpdate.prototype.finish = function() {
+    for (var i = 0; i < this.events.length; i++)
+      signal.apply(null, this.events[i]);
+  };
+
   function maybeClipScrollbars(cm) {
     var display = cm.display;
     if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
@@ -724,7 +733,7 @@
     // width and height.
     removeChildren(display.cursorDiv);
     removeChildren(display.selectionDiv);
-    display.gutters.style.height = 0;
+    display.gutters.style.height = display.sizer.style.minHeight = 0;
 
     if (different) {
       display.lastWrapHeight = update.wrapperHeight;
@@ -738,12 +747,10 @@
   }
 
   function postUpdateDisplay(cm, update) {
-    var force = update.force, viewport = update.viewport;
+    var viewport = update.viewport;
+
     for (var first = true;; first = false) {
-      if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
-        force = true;
-      } else {
-        force = false;
+      if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
         // Clip forced viewport to actual scrollable area.
         if (viewport && viewport.top != null)
           viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
@@ -757,13 +764,13 @@
       updateHeightsInViewport(cm);
       var barMeasure = measureForScrollbars(cm);
       updateSelection(cm);
-      setDocumentHeight(cm, barMeasure);
       updateScrollbars(cm, barMeasure);
+      setDocumentHeight(cm, barMeasure);
     }
 
-    signalLater(cm, "update", cm);
+    update.signal(cm, "update", cm);
     if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
-      signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
+      update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
       cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
     }
   }
@@ -775,16 +782,16 @@
       postUpdateDisplay(cm, update);
       var barMeasure = measureForScrollbars(cm);
       updateSelection(cm);
-      setDocumentHeight(cm, barMeasure);
       updateScrollbars(cm, barMeasure);
+      setDocumentHeight(cm, barMeasure);
+      update.finish();
     }
   }
 
   function setDocumentHeight(cm, measure) {
     cm.display.sizer.style.minHeight = measure.docHeight + "px";
-    var total = measure.docHeight + cm.display.barHeight;
-    cm.display.heightForcer.style.top = total + "px";
-    cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
+    cm.display.heightForcer.style.top = measure.docHeight + "px";
+    cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px";
   }
 
   // Read the actual heights of the rendered lines, and update their
@@ -818,7 +825,7 @@
   // given line.
   function updateWidgetHeight(line) {
     if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
-      line.widgets[i].height = line.widgets[i].node.offsetHeight;
+      line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight;
   }
 
   // Do a bulk-read of the DOM positions and sizes needed to draw the
@@ -861,7 +868,7 @@
     for (var i = 0; i < view.length; i++) {
       var lineView = view[i];
       if (lineView.hidden) {
-      } else if (!lineView.node) { // Not drawn yet
+      } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
         var node = buildLineElement(cm, lineView, lineN, dims);
         container.insertBefore(node, cur);
       } else { // Already drawn
@@ -892,7 +899,7 @@
       if (type == "text") updateLineText(cm, lineView);
       else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
       else if (type == "class") updateLineClasses(lineView);
-      else if (type == "widget") updateLineWidgets(lineView, dims);
+      else if (type == "widget") updateLineWidgets(cm, lineView, dims);
     }
     lineView.changes = null;
   }
@@ -967,14 +974,24 @@
       lineView.node.removeChild(lineView.gutter);
       lineView.gutter = null;
     }
+    if (lineView.gutterBackground) {
+      lineView.node.removeChild(lineView.gutterBackground);
+      lineView.gutterBackground = null;
+    }
+    if (lineView.line.gutterClass) {
+      var wrap = ensureLineWrapped(lineView);
+      lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
+                                      "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
+                                      "px; width: " + dims.gutterTotalWidth + "px");
+      wrap.insertBefore(lineView.gutterBackground, lineView.text);
+    }
     var markers = lineView.line.gutterMarkers;
     if (cm.options.lineNumbers || markers) {
       var wrap = ensureLineWrapped(lineView);
-      var gutterWrap = lineView.gutter =
-        wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
-                              (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
-                              "px; width: " + dims.gutterTotalWidth + "px"),
-                          lineView.text);
+      var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
+                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px");
+      cm.display.input.setUneditable(gutterWrap);
+      wrap.insertBefore(gutterWrap, lineView.text);
       if (lineView.line.gutterClass)
         gutterWrap.className += " " + lineView.line.gutterClass;
       if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
@@ -992,14 +1009,14 @@
     }
   }
 
-  function updateLineWidgets(lineView, dims) {
+  function updateLineWidgets(cm, lineView, dims) {
     if (lineView.alignable) lineView.alignable = null;
     for (var node = lineView.node.firstChild, next; node; node = next) {
       var next = node.nextSibling;
       if (node.className == "CodeMirror-linewidget")
         lineView.node.removeChild(node);
     }
-    insertLineWidgets(lineView, dims);
+    insertLineWidgets(cm, lineView, dims);
   }
 
   // Build a line's DOM representation from scratch
@@ -1011,25 +1028,26 @@
 
     updateLineClasses(lineView);
     updateLineGutter(cm, lineView, lineN, dims);
-    insertLineWidgets(lineView, dims);
+    insertLineWidgets(cm, lineView, dims);
     return lineView.node;
   }
 
   // A lineView may contain multiple logical lines (when merged by
   // collapsed spans). The widgets for all of them need to be drawn.
-  function insertLineWidgets(lineView, dims) {
-    insertLineWidgetsFor(lineView.line, lineView, dims, true);
+  function insertLineWidgets(cm, lineView, dims) {
+    insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
     if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
-      insertLineWidgetsFor(lineView.rest[i], lineView, dims, false);
+      insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
   }
 
-  function insertLineWidgetsFor(line, lineView, dims, allowAbove) {
+  function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
     if (!line.widgets) return;
     var wrap = ensureLineWrapped(lineView);
     for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
       var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
       if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
       positionLineWidget(widget, node, lineView, dims);
+      cm.display.input.setUneditable(node);
       if (allowAbove && widget.above)
         wrap.insertBefore(node, lineView.gutter || lineView.text);
       else
@@ -1072,6 +1090,924 @@
   function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
   function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
 
+  // INPUT HANDLING
+
+  function ensureFocus(cm) {
+    if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
+  }
+
+  // This will be set to a {lineWise: bool, text: [string]} object, so
+  // that, when pasting, we know what kind of selections the copied
+  // text was made out of.
+  var lastCopied = null;
+
+  function applyTextInput(cm, inserted, deleted, sel, origin) {
+    var doc = cm.doc;
+    cm.display.shift = false;
+    if (!sel) sel = doc.sel;
+
+    var paste = cm.state.pasteIncoming || origin == "paste";
+    var textLines = doc.splitLines(inserted), multiPaste = null
+    // When pasing N lines into N selections, insert one line per selection
+    if (paste && sel.ranges.length > 1) {
+      if (lastCopied && lastCopied.text.join("\n") == inserted) {
+        if (sel.ranges.length % lastCopied.text.length == 0) {
+          multiPaste = [];
+          for (var i = 0; i < lastCopied.text.length; i++)
+            multiPaste.push(doc.splitLines(lastCopied.text[i]));
+        }
+      } else if (textLines.length == sel.ranges.length) {
+        multiPaste = map(textLines, function(l) { return [l]; });
+      }
+    }
+
+    // Normal behavior is to insert the new text into every selection
+    for (var i = sel.ranges.length - 1; i >= 0; i--) {
+      var range = sel.ranges[i];
+      var from = range.from(), to = range.to();
+      if (range.empty()) {
+        if (deleted && deleted > 0) // Handle deletion
+          from = Pos(from.line, from.ch - deleted);
+        else if (cm.state.overwrite && !paste) // Handle overwrite
+          to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
+        else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
+          from = to = Pos(from.line, 0)
+      }
+      var updateInput = cm.curOp.updateInput;
+      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
+                         origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
+      makeChange(cm.doc, changeEvent);
+      signalLater(cm, "inputRead", cm, changeEvent);
+    }
+    if (inserted && !paste)
+      triggerElectric(cm, inserted);
+
+    ensureCursorVisible(cm);
+    cm.curOp.updateInput = updateInput;
+    cm.curOp.typing = true;
+    cm.state.pasteIncoming = cm.state.cutIncoming = false;
+  }
+
+  function handlePaste(e, cm) {
+    var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
+    if (pasted) {
+      e.preventDefault();
+      if (!cm.isReadOnly() && !cm.options.disableInput)
+        runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
+      return true;
+    }
+  }
+
+  function triggerElectric(cm, inserted) {
+    // When an 'electric' character is inserted, immediately trigger a reindent
+    if (!cm.options.electricChars || !cm.options.smartIndent) return;
+    var sel = cm.doc.sel;
+
+    for (var i = sel.ranges.length - 1; i >= 0; i--) {
+      var range = sel.ranges[i];
+      if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
+      var mode = cm.getModeAt(range.head);
+      var indented = false;
+      if (mode.electricChars) {
+        for (var j = 0; j < mode.electricChars.length; j++)
+          if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
+            indented = indentLine(cm, range.head.line, "smart");
+            break;
+          }
+      } else if (mode.electricInput) {
+        if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
+          indented = indentLine(cm, range.head.line, "smart");
+      }
+      if (indented) signalLater(cm, "electricInput", cm, range.head.line);
+    }
+  }
+
+  function copyableRanges(cm) {
+    var text = [], ranges = [];
+    for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
+      var line = cm.doc.sel.ranges[i].head.line;
+      var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
+      ranges.push(lineRange);
+      text.push(cm.getRange(lineRange.anchor, lineRange.head));
+    }
+    return {text: text, ranges: ranges};
+  }
+
+  function disableBrowserMagic(field) {
+    field.setAttribute("autocorrect", "off");
+    field.setAttribute("autocapitalize", "off");
+    field.setAttribute("spellcheck", "false");
+  }
+
+  // TEXTAREA INPUT STYLE
+
+  function TextareaInput(cm) {
+    this.cm = cm;
+    // See input.poll and input.reset
+    this.prevInput = "";
+
+    // Flag that indicates whether we expect input to appear real soon
+    // now (after some event like 'keypress' or 'input') and are
+    // polling intensively.
+    this.pollingFast = false;
+    // Self-resetting timeout for the poller
+    this.polling = new Delayed();
+    // Tracks when input.reset has punted to just putting a short
+    // string into the textarea instead of the full selection.
+    this.inaccurateSelection = false;
+    // Used to work around IE issue with selection being forgotten when focus moves away from textarea
+    this.hasSelection = false;
+    this.composing = null;
+  };
+
+  function hiddenTextarea() {
+    var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none");
+    var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
+    // The textarea is kept positioned near the cursor to prevent the
+    // fact that it'll be scrolled into view on input from scrolling
+    // our fake cursor out of view. On webkit, when wrap=off, paste is
+    // very slow. So make the area wide instead.
+    if (webkit) te.style.width = "1000px";
+    else te.setAttribute("wrap", "off");
+    // If border: 0; -- iOS fails to open keyboard (issue #1287)
+    if (ios) te.style.border = "1px solid black";
+    disableBrowserMagic(te);
+    return div;
+  }
+
+  TextareaInput.prototype = copyObj({
+    init: function(display) {
+      var input = this, cm = this.cm;
+
+      // Wraps and hides input textarea
+      var div = this.wrapper = hiddenTextarea();
+      // The semihidden textarea that is focused when the editor is
+      // focused, and receives input.
+      var te = this.textarea = div.firstChild;
+      display.wrapper.insertBefore(div, display.wrapper.firstChild);
+
+      // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
+      if (ios) te.style.width = "0px";
+
+      on(te, "input", function() {
+        if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
+        input.poll();
+      });
+
+      on(te, "paste", function(e) {
+        if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return
+
+        cm.state.pasteIncoming = true;
+        input.fastPoll();
+      });
+
+      function prepareCopyCut(e) {
+        if (signalDOMEvent(cm, e)) return
+        if (cm.somethingSelected()) {
+          lastCopied = {lineWise: false, text: cm.getSelections()};
+          if (input.inaccurateSelection) {
+            input.prevInput = "";
+            input.inaccurateSelection = false;
+            te.value = lastCopied.text.join("\n");
+            selectInput(te);
+          }
+        } else if (!cm.options.lineWiseCopyCut) {
+          return;
+        } else {
+          var ranges = copyableRanges(cm);
+          lastCopied = {lineWise: true, text: ranges.text};
+          if (e.type == "cut") {
+            cm.setSelections(ranges.ranges, null, sel_dontScroll);
+          } else {
+            input.prevInput = "";
+            te.value = ranges.text.join("\n");
+            selectInput(te);
+          }
+        }
+        if (e.type == "cut") cm.state.cutIncoming = true;
+      }
+      on(te, "cut", prepareCopyCut);
+      on(te, "copy", prepareCopyCut);
+
+      on(display.scroller, "paste", function(e) {
+        if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return;
+        cm.state.pasteIncoming = true;
+        input.focus();
+      });
+
+      // Prevent normal selection in the editor (we handle our own)
+      on(display.lineSpace, "selectstart", function(e) {
+        if (!eventInWidget(display, e)) e_preventDefault(e);
+      });
+
+      on(te, "compositionstart", function() {
+        var start = cm.getCursor("from");
+        if (input.composing) input.composing.range.clear()
+        input.composing = {
+          start: start,
+          range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
+        };
+      });
+      on(te, "compositionend", function() {
+        if (input.composing) {
+          input.poll();
+          input.composing.range.clear();
+          input.composing = null;
+        }
+      });
+    },
+
+    prepareSelection: function() {
+      // Redraw the selection and/or cursor
+      var cm = this.cm, display = cm.display, doc = cm.doc;
+      var result = prepareSelection(cm);
+
+      // Move the hidden textarea near the cursor to prevent scrolling artifacts
+      if (cm.options.moveInputWithCursor) {
+        var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
+        var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
+        result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
+                                            headPos.top + lineOff.top - wrapOff.top));
+        result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
+                                             headPos.left + lineOff.left - wrapOff.left));
+      }
+
+      return result;
+    },
+
+    showSelection: function(drawn) {
+      var cm = this.cm, display = cm.display;
+      removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
+      removeChildrenAndAdd(display.selectionDiv, drawn.selection);
+      if (drawn.teTop != null) {
+        this.wrapper.style.top = drawn.teTop + "px";
+        this.wrapper.style.left = drawn.teLeft + "px";
+      }
+    },
+
+    // Reset the input to correspond to the selection (or to be empty,
+    // when not typing and nothing is selected)
+    reset: function(typing) {
+      if (this.contextMenuPending) return;
+      var minimal, selected, cm = this.cm, doc = cm.doc;
+      if (cm.somethingSelected()) {
+        this.prevInput = "";
+        var range = doc.sel.primary();
+        minimal = hasCopyEvent &&
+          (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
+        var content = minimal ? "-" : selected || cm.getSelection();
+        this.textarea.value = content;
+        if (cm.state.focused) selectInput(this.textarea);
+        if (ie && ie_version >= 9) this.hasSelection = content;
+      } else if (!typing) {
+        this.prevInput = this.textarea.value = "";
+        if (ie && ie_version >= 9) this.hasSelection = null;
+      }
+      this.inaccurateSelection = minimal;
+    },
+
+    getField: function() { return this.textarea; },
+
+    supportsTouch: function() { return false; },
+
+    focus: function() {
+      if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
+        try { this.textarea.focus(); }
+        catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
+      }
+    },
+
+    blur: function() { this.textarea.blur(); },
+
+    resetPosition: function() {
+      this.wrapper.style.top = this.wrapper.style.left = 0;
+    },
+
+    receivedFocus: function() { this.slowPoll(); },
+
+    // Poll for input changes, using the normal rate of polling. This
+    // runs as long as the editor is focused.
+    slowPoll: function() {
+      var input = this;
+      if (input.pollingFast) return;
+      input.polling.set(this.cm.options.pollInterval, function() {
+        input.poll();
+        if (input.cm.state.focused) input.slowPoll();
+      });
+    },
+
+    // When an event has just come in that is likely to add or change
+    // something in the input textarea, we poll faster, to ensure that
+    // the change appears on the screen quickly.
+    fastPoll: function() {
+      var missed = false, input = this;
+      input.pollingFast = true;
+      function p() {
+        var changed = input.poll();
+        if (!changed && !missed) {missed = true; input.polling.set(60, p);}
+        else {input.pollingFast = false; input.slowPoll();}
+      }
+      input.polling.set(20, p);
+    },
+
+    // Read input from the textarea, and update the document to match.
+    // When something is selected, it is present in the textarea, and
+    // selected (unless it is huge, in which case a placeholder is
+    // used). When nothing is selected, the cursor sits after previously
+    // seen text (can be empty), which is stored in prevInput (we must
+    // not reset the textarea when typing, because that breaks IME).
+    poll: function() {
+      var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
+      // Since this is called a *lot*, try to bail out as cheaply as
+      // possible when it is clear that nothing happened. hasSelection
+      // will be the case when there is a lot of text in the textarea,
+      // in which case reading its value would be expensive.
+      if (this.contextMenuPending || !cm.state.focused ||
+          (hasSelection(input) && !prevInput && !this.composing) ||
+          cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
+        return false;
+
+      var text = input.value;
+      // If nothing changed, bail.
+      if (text == prevInput && !cm.somethingSelected()) return false;
+      // Work around nonsensical selection resetting in IE9/10, and
+      // inexplicable appearance of private area unicode characters on
+      // some key combos in Mac (#2689).
+      if (ie && ie_version >= 9 && this.hasSelection === text ||
+          mac && /[\uf700-\uf7ff]/.test(text)) {
+        cm.display.input.reset();
+        return false;
+      }
+
+      if (cm.doc.sel == cm.display.selForContextMenu) {
+        var first = text.charCodeAt(0);
+        if (first == 0x200b && !prevInput) prevInput = "\u200b";
+        if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
+      }
+      // Find the part of the input that is actually new
+      var same = 0, l = Math.min(prevInput.length, text.length);
+      while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
+
+      var self = this;
+      runInOp(cm, function() {
+        applyTextInput(cm, text.slice(same), prevInput.length - same,
+                       null, self.composing ? "*compose" : null);
+
+        // Don't leave long text in the textarea, since it makes further polling slow
+        if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
+        else self.prevInput = text;
+
+        if (self.composing) {
+          self.composing.range.clear();
+          self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
+                                             {className: "CodeMirror-composing"});
+        }
+      });
+      return true;
+    },
+
+    ensurePolled: function() {
+      if (this.pollingFast && this.poll()) this.pollingFast = false;
+    },
+
+    onKeyPress: function() {
+      if (ie && ie_version >= 9) this.hasSelection = null;
+      this.fastPoll();
+    },
+
+    onContextMenu: function(e) {
+      var input = this, cm = input.cm, display = cm.display, te = input.textarea;
+      var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
+      if (!pos || presto) return; // Opera is difficult.
+
+      // Reset the current text selection only if the click is done outside of the selection
+      // and 'resetSelectionOnContextMenu' option is true.
+      var reset = cm.options.resetSelectionOnContextMenu;
+      if (reset && cm.doc.sel.contains(pos) == -1)
+        operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
+
+      var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;
+      input.wrapper.style.cssText = "position: absolute"
+      var wrapperBox = input.wrapper.getBoundingClientRect()
+      te.style.cssText = "position: absolute; width: 30px; height: 30px; top: " + (e.clientY - wrapperBox.top - 5) +
+        "px; left: " + (e.clientX - wrapperBox.left - 5) + "px; z-index: 1000; background: " +
+        (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
+        "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
+      if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
+      display.input.focus();
+      if (webkit) window.scrollTo(null, oldScrollY);
+      display.input.reset();
+      // Adds "Select all" to context menu in FF
+      if (!cm.somethingSelected()) te.value = input.prevInput = " ";
+      input.contextMenuPending = true;
+      display.selForContextMenu = cm.doc.sel;
+      clearTimeout(display.detectingSelectAll);
+
+      // Select-all will be greyed out if there's nothing to select, so
+      // this adds a zero-width space so that we can later check whether
+      // it got selected.
+      function prepareSelectAllHack() {
+        if (te.selectionStart != null) {
+          var selected = cm.somethingSelected();
+          var extval = "\u200b" + (selected ? te.value : "");
+          te.value = "\u21da"; // Used to catch context-menu undo
+          te.value = extval;
+          input.prevInput = selected ? "" : "\u200b";
+          te.selectionStart = 1; te.selectionEnd = extval.length;
+          // Re-set this, in case some other handler touched the
+          // selection in the meantime.
+          display.selForContextMenu = cm.doc.sel;
+        }
+      }
+      function rehide() {
+        input.contextMenuPending = false;
+        input.wrapper.style.cssText = oldWrapperCSS
+        te.style.cssText = oldCSS;
+        if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
+
+        // Try to detect the user choosing select-all
+        if (te.selectionStart != null) {
+          if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
+          var i = 0, poll = function() {
+            if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
+                te.selectionEnd > 0 && input.prevInput == "\u200b")
+              operation(cm, commands.selectAll)(cm);
+            else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
+            else display.input.reset();
+          };
+          display.detectingSelectAll = setTimeout(poll, 200);
+        }
+      }
+
+      if (ie && ie_version >= 9) prepareSelectAllHack();
+      if (captureRightClick) {
+        e_stop(e);
+        var mouseup = function() {
+          off(window, "mouseup", mouseup);
+          setTimeout(rehide, 20);
+        };
+        on(window, "mouseup", mouseup);
+      } else {
+        setTimeout(rehide, 50);
+      }
+    },
+
+    readOnlyChanged: function(val) {
+      if (!val) this.reset();
+    },
+
+    setUneditable: nothing,
+
+    needsContentAttribute: false
+  }, TextareaInput.prototype);
+
+  // CONTENTEDITABLE INPUT STYLE
+
+  function ContentEditableInput(cm) {
+    this.cm = cm;
+    this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
+    this.polling = new Delayed();
+    this.gracePeriod = false;
+  }
+
+  ContentEditableInput.prototype = copyObj({
+    init: function(display) {
+      var input = this, cm = input.cm;
+      var div = input.div = display.lineDiv;
+      disableBrowserMagic(div);
+
+      on(div, "paste", function(e) {
+        if (!signalDOMEvent(cm, e)) handlePaste(e, cm);
+      })
+
+      on(div, "compositionstart", function(e) {
+        var data = e.data;
+        input.composing = {sel: cm.doc.sel, data: data, startData: data};
+        if (!data) return;
+        var prim = cm.doc.sel.primary();
+        var line = cm.getLine(prim.head.line);
+        var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
+        if (found > -1 && found <= prim.head.ch)
+          input.composing.sel = simpleSelection(Pos(prim.head.line, found),
+                                                Pos(prim.head.line, found + data.length));
+      });
+      on(div, "compositionupdate", function(e) {
+        input.composing.data = e.data;
+      });
+      on(div, "compositionend", function(e) {
+        var ours = input.composing;
+        if (!ours) return;
+        if (e.data != ours.startData && !/\u200b/.test(e.data))
+          ours.data = e.data;
+        // Need a small delay to prevent other code (input event,
+        // selection polling) from doing damage when fired right after
+        // compositionend.
+        setTimeout(function() {
+          if (!ours.handled)
+            input.applyComposition(ours);
+          if (input.composing == ours)
+            input.composing = null;
+        }, 50);
+      });
+
+      on(div, "touchstart", function() {
+        input.forceCompositionEnd();
+      });
+
+      on(div, "input", function() {
+        if (input.composing) return;
+        if (cm.isReadOnly() || !input.pollContent())
+          runInOp(input.cm, function() {regChange(cm);});
+      });
+
+      function onCopyCut(e) {
+        if (signalDOMEvent(cm, e)) return
+        if (cm.somethingSelected()) {
+          lastCopied = {lineWise: false, text: cm.getSelections()};
+          if (e.type == "cut") cm.replaceSelection("", null, "cut");
+        } else if (!cm.options.lineWiseCopyCut) {
+          return;
+        } else {
+          var ranges = copyableRanges(cm);
+          lastCopied = {lineWise: true, text: ranges.text};
+          if (e.type == "cut") {
+            cm.operation(function() {
+              cm.setSelections(ranges.ranges, 0, sel_dontScroll);
+              cm.replaceSelection("", null, "cut");
+            });
+          }
+        }
+        // iOS exposes the clipboard API, but seems to discard content inserted into it
+        if (e.clipboardData && !ios) {
+          e.preventDefault();
+          e.clipboardData.clearData();
+          e.clipboardData.setData("text/plain", lastCopied.text.join("\n"));
+        } else {
+          // Old-fashioned briefly-focus-a-textarea hack
+          var kludge = hiddenTextarea(), te = kludge.firstChild;
+          cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
+          te.value = lastCopied.text.join("\n");
+          var hadFocus = document.activeElement;
+          selectInput(te);
+          setTimeout(function() {
+            cm.display.lineSpace.removeChild(kludge);
+            hadFocus.focus();
+          }, 50);
+        }
+      }
+      on(div, "copy", onCopyCut);
+      on(div, "cut", onCopyCut);
+    },
+
+    prepareSelection: function() {
+      var result = prepareSelection(this.cm, false);
+      result.focus = this.cm.state.focused;
+      return result;
+    },
+
+    showSelection: function(info, takeFocus) {
+      if (!info || !this.cm.display.view.length) return;
+      if (info.focus || takeFocus) this.showPrimarySelection();
+      this.showMultipleSelections(info);
+    },
+
+    showPrimarySelection: function() {
+      var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
+      var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
+      var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
+      if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
+          cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
+          cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
+        return;
+
+      var start = posToDOM(this.cm, prim.from());
+      var end = posToDOM(this.cm, prim.to());
+      if (!start && !end) return;
+
+      var view = this.cm.display.view;
+      var old = sel.rangeCount && sel.getRangeAt(0);
+      if (!start) {
+        start = {node: view[0].measure.map[2], offset: 0};
+      } else if (!end) { // FIXME dangerously hacky
+        var measure = view[view.length - 1].measure;
+        var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
+        end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
+      }
+
+      try { var rng = range(start.node, start.offset, end.offset, end.node); }
+      catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
+      if (rng) {
+        if (!gecko && this.cm.state.focused) {
+          sel.collapse(start.node, start.offset);
+          if (!rng.collapsed) sel.addRange(rng);
+        } else {
+          sel.removeAllRanges();
+          sel.addRange(rng);
+        }
+        if (old && sel.anchorNode == null) sel.addRange(old);
+        else if (gecko) this.startGracePeriod();
+      }
+      this.rememberSelection();
+    },
+
+    startGracePeriod: function() {
+      var input = this;
+      clearTimeout(this.gracePeriod);
+      this.gracePeriod = setTimeout(function() {
+        input.gracePeriod = false;
+        if (input.selectionChanged())
+          input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
+      }, 20);
+    },
+
+    showMultipleSelections: function(info) {
+      removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
+      removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
+    },
+
+    rememberSelection: function() {
+      var sel = window.getSelection();
+      this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
+      this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
+    },
+
+    selectionInEditor: function() {
+      var sel = window.getSelection();
+      if (!sel.rangeCount) return false;
+      var node = sel.getRangeAt(0).commonAncestorContainer;
+      return contains(this.div, node);
+    },
+
+    focus: function() {
+      if (this.cm.options.readOnly != "nocursor") this.div.focus();
+    },
+    blur: function() { this.div.blur(); },
+    getField: function() { return this.div; },
+
+    supportsTouch: function() { return true; },
+
+    receivedFocus: function() {
+      var input = this;
+      if (this.selectionInEditor())
+        this.pollSelection();
+      else
+        runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
+
+      function poll() {
+        if (input.cm.state.focused) {
+          input.pollSelection();
+          input.polling.set(input.cm.options.pollInterval, poll);
+        }
+      }
+      this.polling.set(this.cm.options.pollInterval, poll);
+    },
+
+    selectionChanged: function() {
+      var sel = window.getSelection();
+      return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
+        sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
+    },
+
+    pollSelection: function() {
+      if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
+        var sel = window.getSelection(), cm = this.cm;
+        this.rememberSelection();
+        var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
+        var head = domToPos(cm, sel.focusNode, sel.focusOffset);
+        if (anchor && head) runInOp(cm, function() {
+          setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
+          if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
+        });
+      }
+    },
+
+    pollContent: function() {
+      var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
+      var from = sel.from(), to = sel.to();
+      if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
+
+      var fromIndex;
+      if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
+        var fromLine = lineNo(display.view[0].line);
+        var fromNode = display.view[0].node;
+      } else {
+        var fromLine = lineNo(display.view[fromIndex].line);
+        var fromNode = display.view[fromIndex - 1].node.nextSibling;
+      }
+      var toIndex = findViewIndex(cm, to.line);
+      if (toIndex == display.view.length - 1) {
+        var toLine = display.viewTo - 1;
+        var toNode = display.lineDiv.lastChild;
+      } else {
+        var toLine = lineNo(display.view[toIndex + 1].line) - 1;
+        var toNode = display.view[toIndex + 1].node.previousSibling;
+      }
+
+      var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
+      var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
+      while (newText.length > 1 && oldText.length > 1) {
+        if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
+        else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
+        else break;
+      }
+
+      var cutFront = 0, cutEnd = 0;
+      var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
+      while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
+        ++cutFront;
+      var newBot = lst(newText), oldBot = lst(oldText);
+      var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
+                               oldBot.length - (oldText.length == 1 ? cutFront : 0));
+      while (cutEnd < maxCutEnd &&
+             newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
+        ++cutEnd;
+
+      newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
+      newText[0] = newText[0].slice(cutFront);
+
+      var chFrom = Pos(fromLine, cutFront);
+      var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
+      if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
+        replaceRange(cm.doc, newText, chFrom, chTo, "+input");
+        return true;
+      }
+    },
+
+    ensurePolled: function() {
+      this.forceCompositionEnd();
+    },
+    reset: function() {
+      this.forceCompositionEnd();
+    },
+    forceCompositionEnd: function() {
+      if (!this.composing || this.composing.handled) return;
+      this.applyComposition(this.composing);
+      this.composing.handled = true;
+      this.div.blur();
+      this.div.focus();
+    },
+    applyComposition: function(composing) {
+      if (this.cm.isReadOnly())
+        operation(this.cm, regChange)(this.cm)
+      else if (composing.data && composing.data != composing.startData)
+        operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
+    },
+
+    setUneditable: function(node) {
+      node.contentEditable = "false"
+    },
+
+    onKeyPress: function(e) {
+      e.preventDefault();
+      if (!this.cm.isReadOnly())
+        operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
+    },
+
+    readOnlyChanged: function(val) {
+      this.div.contentEditable = String(val != "nocursor")
+    },
+
+    onContextMenu: nothing,
+    resetPosition: nothing,
+
+    needsContentAttribute: true
+  }, ContentEditableInput.prototype);
+
+  function posToDOM(cm, pos) {
+    var view = findViewForLine(cm, pos.line);
+    if (!view || view.hidden) return null;
+    var line = getLine(cm.doc, pos.line);
+    var info = mapFromLineView(view, line, pos.line);
+
+    var order = getOrder(line), side = "left";
+    if (order) {
+      var partPos = getBidiPartAt(order, pos.ch);
+      side = partPos % 2 ? "right" : "left";
+    }
+    var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
+    result.offset = result.collapse == "right" ? result.end : result.start;
+    return result;
+  }
+
+  function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
+
+  function domToPos(cm, node, offset) {
+    var lineNode;
+    if (node == cm.display.lineDiv) {
+      lineNode = cm.display.lineDiv.childNodes[offset];
+      if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
+      node = null; offset = 0;
+    } else {
+      for (lineNode = node;; lineNode = lineNode.parentNode) {
+        if (!lineNode || lineNode == cm.display.lineDiv) return null;
+        if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
+      }
+    }
+    for (var i = 0; i < cm.display.view.length; i++) {
+      var lineView = cm.display.view[i];
+      if (lineView.node == lineNode)
+        return locateNodeInLineView(lineView, node, offset);
+    }
+  }
+
+  function locateNodeInLineView(lineView, node, offset) {
+    var wrapper = lineView.text.firstChild, bad = false;
+    if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
+    if (node == wrapper) {
+      bad = true;
+      node = wrapper.childNodes[offset];
+      offset = 0;
+      if (!node) {
+        var line = lineView.rest ? lst(lineView.rest) : lineView.line;
+        return badPos(Pos(lineNo(line), line.text.length), bad);
+      }
+    }
+
+    var textNode = node.nodeType == 3 ? node : null, topNode = node;
+    if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
+      textNode = node.firstChild;
+      if (offset) offset = textNode.nodeValue.length;
+    }
+    while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
+    var measure = lineView.measure, maps = measure.maps;
+
+    function find(textNode, topNode, offset) {
+      for (var i = -1; i < (maps ? maps.length : 0); i++) {
+        var map = i < 0 ? measure.map : maps[i];
+        for (var j = 0; j < map.length; j += 3) {
+          var curNode = map[j + 2];
+          if (curNode == textNode || curNode == topNode) {
+            var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
+            var ch = map[j] + offset;
+            if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
+            return Pos(line, ch);
+          }
+        }
+      }
+    }
+    var found = find(textNode, topNode, offset);
+    if (found) return badPos(found, bad);
+
+    // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
+    for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
+      found = find(after, after.firstChild, 0);
+      if (found)
+        return badPos(Pos(found.line, found.ch - dist), bad);
+      else
+        dist += after.textContent.length;
+    }
+    for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
+      found = find(before, before.firstChild, -1);
+      if (found)
+        return badPos(Pos(found.line, found.ch + dist), bad);
+      else
+        dist += after.textContent.length;
+    }
+  }
+
+  function domTextBetween(cm, from, to, fromLine, toLine) {
+    var text = "", closing = false, lineSep = cm.doc.lineSeparator();
+    function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
+    function walk(node) {
+      if (node.nodeType == 1) {
+        var cmText = node.getAttribute("cm-text");
+        if (cmText != null) {
+          if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
+          text += cmText;
+          return;
+        }
+        var markerID = node.getAttribute("cm-marker"), range;
+        if (markerID) {
+          var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
+          if (found.length && (range = found[0].find()))
+            text += getBetween(cm.doc, range.from, range.to).join(lineSep);
+          return;
+        }
+        if (node.getAttribute("contenteditable") == "false") return;
+        for (var i = 0; i < node.childNodes.length; i++)
+          walk(node.childNodes[i]);
+        if (/^(pre|div|p)$/i.test(node.nodeName))
+          closing = true;
+      } else if (node.nodeType == 3) {
+        var val = node.nodeValue;
+        if (!val) return;
+        if (closing) {
+          text += lineSep;
+          closing = false;
+        }
+        text += val;
+      }
+    }
+    for (;;) {
+      walk(from);
+      if (from == to) break;
+      from = from.nextSibling;
+    }
+    return text;
+  }
+
+  CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
+
   // SELECTION / CURSOR
 
   // Selection objects are immutable. A new one is created every time
@@ -1228,7 +2164,7 @@
 
   // Give beforeSelectionChange handlers a change to influence a
   // selection update.
-  function filterSelectionChange(doc, sel) {
+  function filterSelectionChange(doc, sel, options) {
     var obj = {
       ranges: sel.ranges,
       update: function(ranges) {
@@ -1236,7 +2172,8 @@
         for (var i = 0; i < ranges.length; i++)
           this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
                                      clipPos(doc, ranges[i].head));
-      }
+      },
+      origin: options && options.origin
     };
     signal(doc, "beforeSelectionChange", doc, obj);
     if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
@@ -1262,7 +2199,7 @@
 
   function setSelectionNoUndo(doc, sel, options) {
     if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
-      sel = filterSelectionChange(doc, sel);
+      sel = filterSelectionChange(doc, sel, options);
 
     var bias = options && options.bias ||
       (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
@@ -1296,8 +2233,9 @@
     var out;
     for (var i = 0; i < sel.ranges.length; i++) {
       var range = sel.ranges[i];
-      var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
-      var newHead = skipAtomic(doc, range.head, bias, mayClear);
+      var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
+      var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
+      var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
       if (out || newAnchor != range.anchor || newHead != range.head) {
         if (!out) out = sel.ranges.slice(0, i);
         out[i] = new Range(newAnchor, newHead);
@@ -1306,103 +2244,91 @@
     return out ? normalizeSelection(out, sel.primIndex) : sel;
   }
 
-  // Ensure a given position is not inside an atomic range.
-  function skipAtomic(doc, pos, bias, mayClear) {
-    var flipped = false, curPos = pos;
-    var dir = bias || 1;
-    doc.cantEdit = false;
-    search: for (;;) {
-      var line = getLine(doc, curPos.line);
-      if (line.markedSpans) {
-        for (var i = 0; i < line.markedSpans.length; ++i) {
-          var sp = line.markedSpans[i], m = sp.marker;
-          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
-              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
-            if (mayClear) {
-              signal(m, "beforeCursorEnter");
-              if (m.explicitlyCleared) {
-                if (!line.markedSpans) break;
-                else {--i; continue;}
-              }
-            }
-            if (!m.atomic) continue;
-            var newPos = m.find(dir < 0 ? -1 : 1);
-            if (cmp(newPos, curPos) == 0) {
-              newPos.ch += dir;
-              if (newPos.ch < 0) {
-                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
-                else newPos = null;
-              } else if (newPos.ch > line.text.length) {
-                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
-                else newPos = null;
-              }
-              if (!newPos) {
-                if (flipped) {
-                  // Driven in a corner -- no valid cursor position found at all
-                  // -- try again *with* clearing, if we didn't already
-                  if (!mayClear) return skipAtomic(doc, pos, bias, true);
-                  // Otherwise, turn off editing until further notice, and return the start of the doc
-                  doc.cantEdit = true;
-                  return Pos(doc.first, 0);
-                }
-                flipped = true; newPos = pos; dir = -dir;
-              }
-            }
-            curPos = newPos;
-            continue search;
+  function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
+    var line = getLine(doc, pos.line);
+    if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
+      var sp = line.markedSpans[i], m = sp.marker;
+      if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
+          (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
+        if (mayClear) {
+          signal(m, "beforeCursorEnter");
+          if (m.explicitlyCleared) {
+            if (!line.markedSpans) break;
+            else {--i; continue;}
           }
         }
+        if (!m.atomic) continue;
+
+        if (oldPos) {
+          var near = m.find(dir < 0 ? 1 : -1), diff;
+          if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)
+            near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null);
+          if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
+            return skipAtomicInner(doc, near, pos, dir, mayClear);
+        }
+
+        var far = m.find(dir < 0 ? -1 : 1);
+        if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)
+          far = movePos(doc, far, dir, far.line == pos.line ? line : null);
+        return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null;
       }
-      return curPos;
+    }
+    return pos;
+  }
+
+  // Ensure a given position is not inside an atomic range.
+  function skipAtomic(doc, pos, oldPos, bias, mayClear) {
+    var dir = bias || 1;
+    var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
+        (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
+        skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
+        (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
+    if (!found) {
+      doc.cantEdit = true;
+      return Pos(doc.first, 0);
+    }
+    return found;
+  }
+
+  function movePos(doc, pos, dir, line) {
+    if (dir < 0 && pos.ch == 0) {
+      if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1));
+      else return null;
+    } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
+      if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0);
+      else return null;
+    } else {
+      return new Pos(pos.line, pos.ch + dir);
     }
   }
 
   // SELECTION DRAWING
 
-  // Redraw the selection and/or cursor
-  function drawSelection(cm) {
-    var display = cm.display, doc = cm.doc, result = {};
+  function updateSelection(cm) {
+    cm.display.input.showSelection(cm.display.input.prepareSelection());
+  }
+
+  function prepareSelection(cm, primary) {
+    var doc = cm.doc, result = {};
     var curFragment = result.cursors = document.createDocumentFragment();
     var selFragment = result.selection = document.createDocumentFragment();
 
     for (var i = 0; i < doc.sel.ranges.length; i++) {
+      if (primary === false && i == doc.sel.primIndex) continue;
       var range = doc.sel.ranges[i];
+      if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) continue;
       var collapsed = range.empty();
       if (collapsed || cm.options.showCursorWhenSelecting)
-        drawSelectionCursor(cm, range, curFragment);
+        drawSelectionCursor(cm, range.head, curFragment);
       if (!collapsed)
         drawSelectionRange(cm, range, selFragment);
     }
-
-    // Move the hidden textarea near the cursor to prevent scrolling artifacts
-    if (cm.options.moveInputWithCursor) {
-      var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
-      var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
-      result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
-                                          headPos.top + lineOff.top - wrapOff.top));
-      result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
-                                           headPos.left + lineOff.left - wrapOff.left));
-    }
-
     return result;
   }
 
-  function showSelection(cm, drawn) {
-    removeChildrenAndAdd(cm.display.cursorDiv, drawn.cursors);
-    removeChildrenAndAdd(cm.display.selectionDiv, drawn.selection);
-    if (drawn.teTop != null) {
-      cm.display.inputDiv.style.top = drawn.teTop + "px";
-      cm.display.inputDiv.style.left = drawn.teLeft + "px";
-    }
-  }
-
-  function updateSelection(cm) {
-    showSelection(cm, drawSelection(cm));
-  }
-
   // Draws a cursor for the given range
-  function drawSelectionCursor(cm, range, output) {
-    var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine);
+  function drawSelectionCursor(cm, head, output) {
+    var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
 
     var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
     cursor.style.left = pos.left + "px";
@@ -1526,8 +2452,8 @@
 
     doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
       if (doc.frontier >= cm.display.viewFrom) { // Visible
-        var oldStyles = line.styles;
-        var highlighted = highlightLine(cm, line, state, true);
+        var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength;
+        var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true);
         line.styles = highlighted.styles;
         var oldCls = line.styleClasses, newCls = highlighted.classes;
         if (newCls) line.styleClasses = newCls;
@@ -1536,9 +2462,10 @@
           oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
         for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
         if (ischange) changedLines.push(doc.frontier);
-        line.stateAfter = copyState(doc.mode, state);
+        line.stateAfter = tooLong ? state : copyState(doc.mode, state);
       } else {
-        processLine(cm, line.text, state);
+        if (line.text.length <= cm.options.maxHighlightLength)
+          processLine(cm, line.text, state);
         line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
       }
       ++doc.frontier;
@@ -1683,10 +2610,12 @@
   function prepareMeasureForLine(cm, line) {
     var lineN = lineNo(line);
     var view = findViewForLine(cm, lineN);
-    if (view && !view.text)
+    if (view && !view.text) {
       view = null;
-    else if (view && view.changes)
+    } else if (view && view.changes) {
       updateLineForChanges(cm, view, lineN, getDimensions(cm));
+      cm.curOp.forceUpdate = true;
+    }
     if (!view)
       view = updateExternalMeasurement(cm, line);
 
@@ -1722,9 +2651,7 @@
 
   var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
 
-  function measureCharInner(cm, prepared, ch, bias) {
-    var map = prepared.map;
-
+  function nodeAndOffsetInLineMap(map, ch, bias) {
     var node, start, end, collapse;
     // First, search the line map for the text node corresponding to,
     // or closest to, the target character.
@@ -1758,23 +2685,32 @@
         break;
       }
     }
+    return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
+  }
+
+  function getUsefulRect(rects, bias) {
+    var rect = nullRect
+    if (bias == "left") for (var i = 0; i < rects.length; i++) {
+      if ((rect = rects[i]).left != rect.right) break
+    } else for (var i = rects.length - 1; i >= 0; i--) {
+      if ((rect = rects[i]).left != rect.right) break
+    }
+    return rect
+  }
+
+  function measureCharInner(cm, prepared, ch, bias) {
+    var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
+    var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
 
     var rect;
     if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
       for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
-        while (start && isExtendingChar(prepared.line.text.charAt(mStart + start))) --start;
-        while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end;
-        if (ie && ie_version < 9 && start == 0 && end == mEnd - mStart) {
+        while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
+        while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
+        if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
           rect = node.parentNode.getBoundingClientRect();
-        } else if (ie && cm.options.lineWrapping) {
-          var rects = range(node, start, end).getClientRects();
-          if (rects.length)
-            rect = rects[bias == "right" ? rects.length - 1 : 0];
-          else
-            rect = nullRect;
-        } else {
-          rect = range(node, start, end).getBoundingClientRect() || nullRect;
-        }
+        else
+          rect = getUsefulRect(range(node, start, end).getClientRects(), bias)
         if (rect.left || rect.right || start == 0) break;
         end = start;
         start = start - 1;
@@ -2000,10 +2936,23 @@
     for (;;) {
       if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
         var ch = x < fromX || x - fromX <= toX - x ? from : to;
+        var outside = ch == from ? fromOutside : toOutside
         var xDiff = x - (ch == from ? fromX : toX);
+        // This is a kludge to handle the case where the coordinates
+        // are after a line-wrapped line. We should replace it with a
+        // more general handling of cursor positions around line
+        // breaks. (Issue #4078)
+        if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 &&
+            ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) {
+          var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right");
+          if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) {
+            outside = false
+            ch++
+            xDiff = x - charSize.right
+          }
+        }
         while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
-        var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
-                              xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
+        var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
         return pos;
       }
       var step = Math.ceil(dist / 2), middle = from + step;
@@ -2076,6 +3025,7 @@
       updateMaxLine: false,    // Set when the widest line needs to be determined anew
       scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
       scrollToPos: null,       // Used to scroll to a specific position
+      focus: false,
       id: ++nextOpId           // Unique ID
     };
     if (operationGroup) {
@@ -2094,12 +3044,12 @@
     var callbacks = group.delayedCallbacks, i = 0;
     do {
       for (; i < callbacks.length; i++)
-        callbacks[i]();
+        callbacks[i].call(null);
       for (var j = 0; j < group.ops.length; j++) {
         var op = group.ops[j];
         if (op.cursorActivityHandlers)
           while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
-            op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);
+            op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm);
       }
     } while (i < callbacks.length);
   }
@@ -2169,7 +3119,7 @@
     }
 
     if (op.updatedDisplay || op.selectionChanged)
-      op.newSelectionNodes = drawSelection(cm);
+      op.preparedSelection = display.input.prepareSelection(op.focus);
   }
 
   function endOperation_W2(op) {
@@ -2182,17 +3132,19 @@
       cm.display.maxLineChanged = false;
     }
 
-    if (op.newSelectionNodes)
-      showSelection(cm, op.newSelectionNodes);
-    if (op.updatedDisplay)
-      setDocumentHeight(cm, op.barMeasure);
+    var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus())
+    if (op.preparedSelection)
+      cm.display.input.showSelection(op.preparedSelection, takeFocus);
     if (op.updatedDisplay || op.startHeight != cm.doc.height)
       updateScrollbars(cm, op.barMeasure);
+    if (op.updatedDisplay)
+      setDocumentHeight(cm, op.barMeasure);
 
     if (op.selectionChanged) restartBlink(cm);
 
     if (cm.state.focused && op.updateInput)
-      resetInput(cm, op.typing);
+      cm.display.input.reset(op.typing);
+    if (takeFocus) ensureFocus(op.cm);
   }
 
   function endOperation_finish(op) {
@@ -2211,7 +3163,7 @@
       display.scroller.scrollTop = doc.scrollTop;
     }
     if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
-      doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
+      doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft));
       display.scrollbars.setScrollLeft(doc.scrollLeft);
       display.scroller.scrollLeft = doc.scrollLeft;
       alignHorizontally(cm);
@@ -2237,6 +3189,8 @@
     // Fire change events, and delayed event handlers
     if (op.changeObjs)
       signal(cm, "changes", cm, op.changeObjs);
+    if (op.update)
+      op.update.finish();
   }
 
   // Run the given function in an operation
@@ -2462,167 +3416,6 @@
     return dirty;
   }
 
-  // INPUT HANDLING
-
-  // Poll for input changes, using the normal rate of polling. This
-  // runs as long as the editor is focused.
-  function slowPoll(cm) {
-    if (cm.display.pollingFast) return;
-    cm.display.poll.set(cm.options.pollInterval, function() {
-      readInput(cm);
-      if (cm.state.focused) slowPoll(cm);
-    });
-  }
-
-  // When an event has just come in that is likely to add or change
-  // something in the input textarea, we poll faster, to ensure that
-  // the change appears on the screen quickly.
-  function fastPoll(cm) {
-    var missed = false;
-    cm.display.pollingFast = true;
-    function p() {
-      var changed = readInput(cm);
-      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
-      else {cm.display.pollingFast = false; slowPoll(cm);}
-    }
-    cm.display.poll.set(20, p);
-  }
-
-  // This will be set to an array of strings when copying, so that,
-  // when pasting, we know what kind of selections the copied text
-  // was made out of.
-  var lastCopied = null;
-
-  // Read input from the textarea, and update the document to match.
-  // When something is selected, it is present in the textarea, and
-  // selected (unless it is huge, in which case a placeholder is
-  // used). When nothing is selected, the cursor sits after previously
-  // seen text (can be empty), which is stored in prevInput (we must
-  // not reset the textarea when typing, because that breaks IME).
-  function readInput(cm) {
-    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc;
-    // Since this is called a *lot*, try to bail out as cheaply as
-    // possible when it is clear that nothing happened. hasSelection
-    // will be the case when there is a lot of text in the textarea,
-    // in which case reading its value would be expensive.
-    if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
-      return false;
-    // See paste handler for more on the fakedLastChar kludge
-    if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
-      input.value = input.value.substring(0, input.value.length - 1);
-      cm.state.fakedLastChar = false;
-    }
-    var text = input.value;
-    // If nothing changed, bail.
-    if (text == prevInput && !cm.somethingSelected()) return false;
-    // Work around nonsensical selection resetting in IE9/10, and
-    // inexplicable appearance of private area unicode characters on
-    // some key combos in Mac (#2689).
-    if (ie && ie_version >= 9 && cm.display.inputHasSelection === text ||
-        mac && /[\uf700-\uf7ff]/.test(text)) {
-      resetInput(cm);
-      return false;
-    }
-
-    var withOp = !cm.curOp;
-    if (withOp) startOperation(cm);
-    cm.display.shift = false;
-
-    if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput)
-      prevInput = "\u200b";
-    // Find the part of the input that is actually new
-    var same = 0, l = Math.min(prevInput.length, text.length);
-    while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
-    var inserted = text.slice(same), textLines = splitLines(inserted);
-
-    // When pasing N lines into N selections, insert one line per selection
-    var multiPaste = null;
-    if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) {
-      if (lastCopied && lastCopied.join("\n") == inserted)
-        multiPaste = doc.sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
-      else if (textLines.length == doc.sel.ranges.length)
-        multiPaste = map(textLines, function(l) { return [l]; });
-    }
-
-    // Normal behavior is to insert the new text into every selection
-    for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {
-      var range = doc.sel.ranges[i];
-      var from = range.from(), to = range.to();
-      // Handle deletion
-      if (same < prevInput.length)
-        from = Pos(from.line, from.ch - (prevInput.length - same));
-      // Handle overwrite
-      else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming)
-        to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
-      var updateInput = cm.curOp.updateInput;
-      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
-                         origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};
-      makeChange(cm.doc, changeEvent);
-      signalLater(cm, "inputRead", cm, changeEvent);
-      // When an 'electric' character is inserted, immediately trigger a reindent
-      if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
-          cm.options.smartIndent && range.head.ch < 100 &&
-          (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {
-        var mode = cm.getModeAt(range.head);
-        var end = changeEnd(changeEvent);
-        if (mode.electricChars) {
-          for (var j = 0; j < mode.electricChars.length; j++)
-            if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
-              indentLine(cm, end.line, "smart");
-              break;
-            }
-        } else if (mode.electricInput) {
-          if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
-            indentLine(cm, end.line, "smart");
-        }
-      }
-    }
-    ensureCursorVisible(cm);
-    cm.curOp.updateInput = updateInput;
-    cm.curOp.typing = true;
-
-    // Don't leave long text in the textarea, since it makes further polling slow
-    if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
-    else cm.display.prevInput = text;
-    if (withOp) endOperation(cm);
-    cm.state.pasteIncoming = cm.state.cutIncoming = false;
-    return true;
-  }
-
-  // Reset the input to correspond to the selection (or to be empty,
-  // when not typing and nothing is selected)
-  function resetInput(cm, typing) {
-    if (cm.display.contextMenuPending) return;
-    var minimal, selected, doc = cm.doc;
-    if (cm.somethingSelected()) {
-      cm.display.prevInput = "";
-      var range = doc.sel.primary();
-      minimal = hasCopyEvent &&
-        (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
-      var content = minimal ? "-" : selected || cm.getSelection();
-      cm.display.input.value = content;
-      if (cm.state.focused) selectInput(cm.display.input);
-      if (ie && ie_version >= 9) cm.display.inputHasSelection = content;
-    } else if (!typing) {
-      cm.display.prevInput = cm.display.input.value = "";
-      if (ie && ie_version >= 9) cm.display.inputHasSelection = null;
-    }
-    cm.display.inaccurateSelection = minimal;
-  }
-
-  function focusInput(cm) {
-    if (cm.options.readOnly != "nocursor" && (!mobile || activeElt() != cm.display.input))
-      cm.display.input.focus();
-  }
-
-  function ensureFocus(cm) {
-    if (!cm.state.focused) { focusInput(cm); onFocus(cm); }
-  }
-
-  function isReadOnly(cm) {
-    return cm.options.readOnly || cm.doc.cantEdit;
-  }
-
   // EVENT HANDLERS
 
   // Attach the necessary event handlers when initializing the editor
@@ -2641,15 +3434,64 @@
       }));
     else
       on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
-    // Prevent normal selection in the editor (we handle our own)
-    on(d.lineSpace, "selectstart", function(e) {
-      if (!eventInWidget(d, e)) e_preventDefault(e);
-    });
     // Some browsers fire contextmenu *after* opening the menu, at
     // which point we can't mess with it anymore. Context menu is
     // handled in onMouseDown for these browsers.
     if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
 
+    // Used to suppress mouse event handling when a touch happens
+    var touchFinished, prevTouch = {end: 0};
+    function finishTouch() {
+      if (d.activeTouch) {
+        touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
+        prevTouch = d.activeTouch;
+        prevTouch.end = +new Date;
+      }
+    };
+    function isMouseLikeTouchEvent(e) {
+      if (e.touches.length != 1) return false;
+      var touch = e.touches[0];
+      return touch.radiusX <= 1 && touch.radiusY <= 1;
+    }
+    function farAway(touch, other) {
+      if (other.left == null) return true;
+      var dx = other.left - touch.left, dy = other.top - touch.top;
+      return dx * dx + dy * dy > 20 * 20;
+    }
+    on(d.scroller, "touchstart", function(e) {
+      if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
+        clearTimeout(touchFinished);
+        var now = +new Date;
+        d.activeTouch = {start: now, moved: false,
+                         prev: now - prevTouch.end <= 300 ? prevTouch : null};
+        if (e.touches.length == 1) {
+          d.activeTouch.left = e.touches[0].pageX;
+          d.activeTouch.top = e.touches[0].pageY;
+        }
+      }
+    });
+    on(d.scroller, "touchmove", function() {
+      if (d.activeTouch) d.activeTouch.moved = true;
+    });
+    on(d.scroller, "touchend", function(e) {
+      var touch = d.activeTouch;
+      if (touch && !eventInWidget(d, e) && touch.left != null &&
+          !touch.moved && new Date - touch.start < 300) {
+        var pos = cm.coordsChar(d.activeTouch, "page"), range;
+        if (!touch.prev || farAway(touch, touch.prev)) // Single tap
+          range = new Range(pos, pos);
+        else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
+          range = cm.findWordAt(pos);
+        else // Triple tap
+          range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
+        cm.setSelection(range.anchor, range.head);
+        cm.focus();
+        e_preventDefault(e);
+      }
+      finishTouch();
+    });
+    on(d.scroller, "touchcancel", finishTouch);
+
     // Sync scrolling between fake scrollbars and real scrollable
     // area, ensure viewport is updated when scrolling.
     on(d.scroller, "scroll", function() {
@@ -2667,86 +3509,33 @@
     // Prevent wrapper from ever scrolling
     on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
 
-    on(d.input, "keyup", function(e) { onKeyUp.call(cm, e); });
-    on(d.input, "input", function() {
-      if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
-      readInput(cm);
-    });
-    on(d.input, "keydown", operation(cm, onKeyDown));
-    on(d.input, "keypress", operation(cm, onKeyPress));
-    on(d.input, "focus", bind(onFocus, cm));
-    on(d.input, "blur", bind(onBlur, cm));
+    d.dragFunctions = {
+      enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
+      over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
+      start: function(e){onDragStart(cm, e);},
+      drop: operation(cm, onDrop),
+      leave: function(e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}
+    };
 
-    function drag_(e) {
-      if (!signalDOMEvent(cm, e)) e_stop(e);
-    }
-    if (cm.options.dragDrop) {
-      on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
-      on(d.scroller, "dragenter", drag_);
-      on(d.scroller, "dragover", drag_);
-      on(d.scroller, "drop", operation(cm, onDrop));
-    }
-    on(d.scroller, "paste", function(e) {
-      if (eventInWidget(d, e)) return;
-      cm.state.pasteIncoming = true;
-      focusInput(cm);
-      fastPoll(cm);
-    });
-    on(d.input, "paste", function() {
-      // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
-      // Add a char to the end of textarea before paste occur so that
-      // selection doesn't span to the end of textarea.
-      if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
-        var start = d.input.selectionStart, end = d.input.selectionEnd;
-        d.input.value += "$";
-        // The selection end needs to be set before the start, otherwise there
-        // can be an intermediate non-empty selection between the two, which
-        // can override the middle-click paste buffer on linux and cause the
-        // wrong thing to get pasted.
-        d.input.selectionEnd = end;
-        d.input.selectionStart = start;
-        cm.state.fakedLastChar = true;
-      }
-      cm.state.pasteIncoming = true;
-      fastPoll(cm);
-    });
+    var inp = d.input.getField();
+    on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
+    on(inp, "keydown", operation(cm, onKeyDown));
+    on(inp, "keypress", operation(cm, onKeyPress));
+    on(inp, "focus", bind(onFocus, cm));
+    on(inp, "blur", bind(onBlur, cm));
+  }
 
-    function prepareCopyCut(e) {
-      if (cm.somethingSelected()) {
-        lastCopied = cm.getSelections();
-        if (d.inaccurateSelection) {
-          d.prevInput = "";
-          d.inaccurateSelection = false;
-          d.input.value = lastCopied.join("\n");
-          selectInput(d.input);
-        }
-      } else {
-        var text = [], ranges = [];
-        for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
-          var line = cm.doc.sel.ranges[i].head.line;
-          var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
-          ranges.push(lineRange);
-          text.push(cm.getRange(lineRange.anchor, lineRange.head));
-        }
-        if (e.type == "cut") {
-          cm.setSelections(ranges, null, sel_dontScroll);
-        } else {
-          d.prevInput = "";
-          d.input.value = text.join("\n");
-          selectInput(d.input);
-        }
-        lastCopied = text;
-      }
-      if (e.type == "cut") cm.state.cutIncoming = true;
+  function dragDropChanged(cm, value, old) {
+    var wasOn = old && old != CodeMirror.Init;
+    if (!value != !wasOn) {
+      var funcs = cm.display.dragFunctions;
+      var toggle = value ? on : off;
+      toggle(cm.display.scroller, "dragstart", funcs.start);
+      toggle(cm.display.scroller, "dragenter", funcs.enter);
+      toggle(cm.display.scroller, "dragover", funcs.over);
+      toggle(cm.display.scroller, "dragleave", funcs.leave);
+      toggle(cm.display.scroller, "drop", funcs.drop);
     }
-    on(d.input, "cut", prepareCopyCut);
-    on(d.input, "copy", prepareCopyCut);
-
-    // Needed to handle Tab key in KHTML
-    if (khtml) on(d.sizer, "mouseup", function() {
-      if (activeElt() == d.input) d.input.blur();
-      focusInput(cm);
-    });
   }
 
   // Called when the window resizes
@@ -2778,7 +3567,7 @@
   // coordinates beyond the right of the text.
   function posFromMouse(cm, e, liberal, forRect) {
     var display = cm.display;
-    if (!liberal && e_target(e).getAttribute("not-content") == "true") return null;
+    if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
 
     var x, y, space = display.lineSpace.getBoundingClientRect();
     // Fails unpredictably on IE[67] when mouse is dragged around quickly.
@@ -2798,8 +3587,8 @@
   // middle-click-paste. Or it might be a click on something we should
   // not interfere with, such as a scrollbar or widget.
   function onMouseDown(e) {
-    if (signalDOMEvent(this, e)) return;
     var cm = this, display = cm.display;
+    if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return;
     display.shift = e.shiftKey;
 
     if (eventInWidget(display, e)) {
@@ -2817,7 +3606,10 @@
 
     switch (e_button(e)) {
     case 1:
-      if (start)
+      // #3261: make sure, that we're not starting a second selection
+      if (cm.state.selectingText)
+        cm.state.selectingText(e);
+      else if (start)
         leftButtonDown(cm, e, start);
       else if (e_target(e) == display.scroller)
         e_preventDefault(e);
@@ -2825,18 +3617,20 @@
     case 2:
       if (webkit) cm.state.lastMiddleDown = +new Date;
       if (start) extendSelection(cm.doc, start);
-      setTimeout(bind(focusInput, cm), 20);
+      setTimeout(function() {display.input.focus();}, 20);
       e_preventDefault(e);
       break;
     case 3:
       if (captureRightClick) onContextMenu(cm, e);
+      else delayBlurEvent(cm);
       break;
     }
   }
 
   var lastClick, lastDoubleClick;
   function leftButtonDown(cm, e, start) {
-    setTimeout(bind(ensureFocus, cm), 0);
+    if (ie) setTimeout(bind(ensureFocus, cm), 0);
+    else cm.curOp.focus = activeElt();
 
     var now = +new Date, type;
     if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
@@ -2850,9 +3644,10 @@
     }
 
     var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
-    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
+    if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
         type == "single" && (contained = sel.contains(start)) > -1 &&
-        !sel.ranges[contained].empty())
+        (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
+        (cmp(contained.to(), start) > 0 || start.xRel < 0))
       leftButtonStartDrag(cm, e, start, modifier);
     else
       leftButtonSelect(cm, e, start, type, modifier);
@@ -2861,7 +3656,7 @@
   // Start a text drag. When it ends, see if any dragging actually
   // happen, and treat as a click if it didn't.
   function leftButtonStartDrag(cm, e, start, modifier) {
-    var display = cm.display;
+    var display = cm.display, startTime = +new Date;
     var dragEnd = operation(cm, function(e2) {
       if (webkit) display.scroller.draggable = false;
       cm.state.draggingText = false;
@@ -2869,17 +3664,19 @@
       off(display.scroller, "drop", dragEnd);
       if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
         e_preventDefault(e2);
-        if (!modifier)
+        if (!modifier && +new Date - 200 < startTime)
           extendSelection(cm.doc, start);
-        focusInput(cm);
-        // Work around unexplainable focus problem in IE9 (#2127)
-        if (ie && ie_version == 9)
-          setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);
+        // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
+        if (webkit || ie && ie_version == 9)
+          setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
+        else
+          display.input.focus();
       }
     });
     // Let the drag handler handle this.
     if (webkit) display.scroller.draggable = true;
     cm.state.draggingText = dragEnd;
+    dragEnd.copy = mac ? e.altKey : e.ctrlKey
     // IE's approach to draggable
     if (display.scroller.dragDrop) display.scroller.dragDrop();
     on(document, "mouseup", dragEnd);
@@ -2900,9 +3697,10 @@
         ourRange = new Range(start, start);
     } else {
       ourRange = doc.sel.primary();
+      ourIndex = doc.sel.primIndex;
     }
 
-    if (e.altKey) {
+    if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) {
       type = "rect";
       if (!addNew) ourRange = new Range(start, start);
       start = posFromMouse(cm, e, true, true);
@@ -2931,8 +3729,9 @@
       ourIndex = ranges.length;
       setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
                    {scroll: false, origin: "*mouse"});
-    } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {
-      setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
+    } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
+      setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
+                   {scroll: false, origin: "*mouse"});
       startSel = doc.sel;
     } else {
       replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
@@ -2994,7 +3793,7 @@
       var cur = posFromMouse(cm, e, true, type == "rect");
       if (!cur) return;
       if (cmp(cur, lastPos) != 0) {
-        ensureFocus(cm);
+        cm.curOp.focus = activeElt();
         extendTo(cur);
         var visible = visibleLines(display, doc);
         if (cur.line >= visible.to || cur.line < visible.from)
@@ -3010,9 +3809,10 @@
     }
 
     function done(e) {
+      cm.state.selectingText = false;
       counter = Infinity;
       e_preventDefault(e);
-      focusInput(cm);
+      display.input.focus();
       off(document, "mousemove", move);
       off(document, "mouseup", up);
       doc.history.lastSelOrigin = null;
@@ -3023,13 +3823,14 @@
       else extend(e);
     });
     var up = operation(cm, done);
+    cm.state.selectingText = up;
     on(document, "mousemove", move);
     on(document, "mouseup", up);
   }
 
   // Determines whether an event happened in the gutter, and fires the
   // handlers for the corresponding event.
-  function gutterEvent(cm, e, type, prevent, signalfn) {
+  function gutterEvent(cm, e, type, prevent) {
     try { var mX = e.clientX, mY = e.clientY; }
     catch(e) { return false; }
     if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
@@ -3046,14 +3847,14 @@
       if (g && g.getBoundingClientRect().right >= mX) {
         var line = lineAtHeight(cm.doc, mY);
         var gutter = cm.options.gutters[i];
-        signalfn(cm, type, cm, line, gutter, e);
+        signal(cm, type, cm, line, gutter, e);
         return e_defaultPrevented(e);
       }
     }
   }
 
   function clickInGutter(cm, e) {
-    return gutterEvent(cm, e, "gutterClick", true, signalLater);
+    return gutterEvent(cm, e, "gutterClick", true);
   }
 
   // Kludge to work around strange IE behavior where it'll sometimes
@@ -3062,23 +3863,32 @@
 
   function onDrop(e) {
     var cm = this;
+    clearDragCursor(cm);
     if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
       return;
     e_preventDefault(e);
     if (ie) lastDrop = +new Date;
     var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
-    if (!pos || isReadOnly(cm)) return;
+    if (!pos || cm.isReadOnly()) return;
     // Might be a file drop, in which case we simply extract the text
     // and insert it.
     if (files && files.length && window.FileReader && window.File) {
       var n = files.length, text = Array(n), read = 0;
       var loadFile = function(file, i) {
+        if (cm.options.allowDropFileTypes &&
+            indexOf(cm.options.allowDropFileTypes, file.type) == -1)
+          return;
+
         var reader = new FileReader;
         reader.onload = operation(cm, function() {
-          text[i] = reader.result;
+          var content = reader.result;
+          if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = "";
+          text[i] = content;
           if (++read == n) {
             pos = clipPos(cm.doc, pos);
-            var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"};
+            var change = {from: pos, to: pos,
+                          text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
+                          origin: "paste"};
             makeChange(cm.doc, change);
             setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
           }
@@ -3091,19 +3901,19 @@
       if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
         cm.state.draggingText(e);
         // Ensure the editor is re-focused
-        setTimeout(bind(focusInput, cm), 20);
+        setTimeout(function() {cm.display.input.focus();}, 20);
         return;
       }
       try {
         var text = e.dataTransfer.getData("Text");
         if (text) {
-          if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))
+          if (cm.state.draggingText && !cm.state.draggingText.copy)
             var selected = cm.listSelections();
           setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
           if (selected) for (var i = 0; i < selected.length; ++i)
             replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
           cm.replaceSelection(text, "around", "paste");
-          focusInput(cm);
+          cm.display.input.focus();
         }
       }
       catch(e){}
@@ -3115,6 +3925,7 @@
     if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
 
     e.dataTransfer.setData("Text", cm.getSelection());
+    e.dataTransfer.effectAllowed = "copyMove"
 
     // Use dummy image instead of default browsers image.
     // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
@@ -3132,6 +3943,25 @@
     }
   }
 
+  function onDragOver(cm, e) {
+    var pos = posFromMouse(cm, e);
+    if (!pos) return;
+    var frag = document.createDocumentFragment();
+    drawSelectionCursor(cm, pos, frag);
+    if (!cm.display.dragCursor) {
+      cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
+      cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
+    }
+    removeChildrenAndAdd(cm.display.dragCursor, frag);
+  }
+
+  function clearDragCursor(cm) {
+    if (cm.display.dragCursor) {
+      cm.display.lineSpace.removeChild(cm.display.dragCursor);
+      cm.display.dragCursor = null;
+    }
+  }
+
   // SCROLL EVENTS
 
   // Sync the scrollable area and scrollbars, ensure the viewport
@@ -3196,8 +4026,9 @@
 
     var display = cm.display, scroll = display.scroller;
     // Quit if there's nothing to scroll here
-    if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
-          dy && scroll.scrollHeight > scroll.clientHeight)) return;
+    var canScrollX = scroll.scrollWidth > scroll.clientWidth;
+    var canScrollY = scroll.scrollHeight > scroll.clientHeight;
+    if (!(dx && canScrollX || dy && canScrollY)) return;
 
     // Webkit browsers on OS X abort momentum scrolls when the target
     // of the scroll event is removed from the scrollable element.
@@ -3221,10 +4052,15 @@
     // scrolling entirely here. It'll be slightly off from native, but
     // better than glitching out.
     if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
-      if (dy)
+      if (dy && canScrollY)
         setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
       setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
-      e_preventDefault(e);
+      // Only prevent default scrolling if vertical scrolling is
+      // actually possible. Otherwise, it causes vertical scroll
+      // jitter on OSX trackpads when deltaX is small and deltaY
+      // is large (issue #3579)
+      if (!dy || (dy && canScrollY))
+        e_preventDefault(e);
       display.wheelStartX = null; // Abort measurement, if in progress
       return;
     }
@@ -3270,10 +4106,10 @@
     }
     // Ensure previous input has been read, so that the handler sees a
     // consistent view of the document
-    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
+    cm.display.input.ensurePolled();
     var prevShift = cm.display.shift, done = false;
     try {
-      if (isReadOnly(cm)) cm.state.suppressEdits = true;
+      if (cm.isReadOnly()) cm.state.suppressEdits = true;
       if (dropShift) cm.display.shift = false;
       done = bound(cm) != Pass;
     } finally {
@@ -3300,7 +4136,7 @@
       stopSeq.set(50, function() {
         if (cm.state.keySeq == seq) {
           cm.state.keySeq = null;
-          resetInput(cm);
+          cm.display.input.reset();
         }
       });
       name = seq + " " + name;
@@ -3352,7 +4188,7 @@
   var lastStoppedKey = null;
   function onKeyDown(e) {
     var cm = this;
-    ensureFocus(cm);
+    cm.curOp.focus = activeElt();
     if (signalDOMEvent(cm, e)) return;
     // IE does strange things with escape.
     if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
@@ -3393,36 +4229,49 @@
 
   function onKeyPress(e) {
     var cm = this;
-    if (signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
+    if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
     var keyCode = e.keyCode, charCode = e.charCode;
     if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
-    if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
+    if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
     var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
     if (handleCharBinding(cm, e, ch)) return;
-    if (ie && ie_version >= 9) cm.display.inputHasSelection = null;
-    fastPoll(cm);
+    cm.display.input.onKeyPress(e);
   }
 
   // FOCUS/BLUR EVENTS
 
+  function delayBlurEvent(cm) {
+    cm.state.delayingBlurEvent = true;
+    setTimeout(function() {
+      if (cm.state.delayingBlurEvent) {
+        cm.state.delayingBlurEvent = false;
+        onBlur(cm);
+      }
+    }, 100);
+  }
+
   function onFocus(cm) {
+    if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
+
     if (cm.options.readOnly == "nocursor") return;
     if (!cm.state.focused) {
       signal(cm, "focus", cm);
       cm.state.focused = true;
       addClass(cm.display.wrapper, "CodeMirror-focused");
-      // The prevInput test prevents this from firing when a context
-      // menu is closed (since the resetInput would kill the
+      // This test prevents this from firing when a context
+      // menu is closed (since the input reset would kill the
       // select-all detection hack)
       if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
-        resetInput(cm);
-        if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
+        cm.display.input.reset();
+        if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
       }
+      cm.display.input.receivedFocus();
     }
-    slowPoll(cm);
     restartBlink(cm);
   }
   function onBlur(cm) {
+    if (cm.state.delayingBlurEvent) return;
+
     if (cm.state.focused) {
       signal(cm, "blur", cm);
       cm.state.focused = false;
@@ -3438,85 +4287,14 @@
   // textarea (making it as unobtrusive as possible) to let the
   // right-click take effect on it.
   function onContextMenu(cm, e) {
+    if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
     if (signalDOMEvent(cm, e, "contextmenu")) return;
-    var display = cm.display;
-    if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
-
-    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
-    if (!pos || presto) return; // Opera is difficult.
-
-    // Reset the current text selection only if the click is done outside of the selection
-    // and 'resetSelectionOnContextMenu' option is true.
-    var reset = cm.options.resetSelectionOnContextMenu;
-    if (reset && cm.doc.sel.contains(pos) == -1)
-      operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
-
-    var oldCSS = display.input.style.cssText;
-    display.inputDiv.style.position = "absolute";
-    display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
-      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
-      (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
-      "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
-    if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
-    focusInput(cm);
-    if (webkit) window.scrollTo(null, oldScrollY);
-    resetInput(cm);
-    // Adds "Select all" to context menu in FF
-    if (!cm.somethingSelected()) display.input.value = display.prevInput = " ";
-    display.contextMenuPending = true;
-    display.selForContextMenu = cm.doc.sel;
-    clearTimeout(display.detectingSelectAll);
-
-    // Select-all will be greyed out if there's nothing to select, so
-    // this adds a zero-width space so that we can later check whether
-    // it got selected.
-    function prepareSelectAllHack() {
-      if (display.input.selectionStart != null) {
-        var selected = cm.somethingSelected();
-        var extval = display.input.value = "\u200b" + (selected ? display.input.value : "");
-        display.prevInput = selected ? "" : "\u200b";
-        display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
-        // Re-set this, in case some other handler touched the
-        // selection in the meantime.
-        display.selForContextMenu = cm.doc.sel;
-      }
-    }
-    function rehide() {
-      display.contextMenuPending = false;
-      display.inputDiv.style.position = "relative";
-      display.input.style.cssText = oldCSS;
-      if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
-      slowPoll(cm);
-
-      // Try to detect the user choosing select-all
-      if (display.input.selectionStart != null) {
-        if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
-        var i = 0, poll = function() {
-          if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0)
-            operation(cm, commands.selectAll)(cm);
-          else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
-          else resetInput(cm);
-        };
-        display.detectingSelectAll = setTimeout(poll, 200);
-      }
-    }
-
-    if (ie && ie_version >= 9) prepareSelectAllHack();
-    if (captureRightClick) {
-      e_stop(e);
-      var mouseup = function() {
-        off(window, "mouseup", mouseup);
-        setTimeout(rehide, 20);
-      };
-      on(window, "mouseup", mouseup);
-    } else {
-      setTimeout(rehide, 50);
-    }
+    cm.display.input.onContextMenu(e);
   }
 
   function contextMenuInGutter(cm, e) {
     if (!hasHandler(cm, "gutterContextMenu")) return false;
-    return gutterEvent(cm, e, "gutterContextMenu", false, signal);
+    return gutterEvent(cm, e, "gutterContextMenu", false);
   }
 
   // UPDATING
@@ -3644,7 +4422,7 @@
 
   // Revert a change stored in a document's history.
   function makeChangeFromHistory(doc, type, allowSelectionOnly) {
-    if (doc.cm && doc.cm.state.suppressEdits) return;
+    if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) return;
 
     var hist = doc.history, event, selAfter = doc.sel;
     var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
@@ -3820,7 +4598,7 @@
   function replaceRange(doc, code, from, to, origin) {
     if (!to) to = from;
     if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
-    if (typeof code == "string") code = splitLines(code);
+    if (typeof code == "string") code = doc.splitLines(code);
     makeChange(doc, {from: from, to: to, text: code, origin: origin});
   }
 
@@ -3999,6 +4777,8 @@
 
     if (indentString != curSpaceString) {
       replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
+      line.stateAfter = null;
+      return true;
     } else {
       // Ensure that, if the cursor was in the whitespace at the start
       // of the line, it is moved to the end of that space.
@@ -4011,7 +4791,6 @@
         }
       }
     }
-    line.stateAfter = null;
   }
 
   // Utility for applying a change to a line by handle or number,
@@ -4063,10 +4842,9 @@
   function findPosH(doc, pos, dir, unit, visually) {
     var line = pos.line, ch = pos.ch, origDir = dir;
     var lineObj = getLine(doc, line);
-    var possible = true;
     function findNextLine() {
       var l = line + dir;
-      if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
+      if (l < doc.first || l >= doc.first + doc.size) return false
       line = l;
       return lineObj = getLine(doc, l);
     }
@@ -4076,14 +4854,16 @@
         if (!boundToLine && findNextLine()) {
           if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
           else ch = dir < 0 ? lineObj.text.length : 0;
-        } else return (possible = false);
+        } else return false
       } else ch = next;
       return true;
     }
 
-    if (unit == "char") moveOnce();
-    else if (unit == "column") moveOnce(true);
-    else if (unit == "word" || unit == "group") {
+    if (unit == "char") {
+      moveOnce()
+    } else if (unit == "column") {
+      moveOnce(true)
+    } else if (unit == "word" || unit == "group") {
       var sawType = null, group = unit == "group";
       var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
       for (var first = true;; first = false) {
@@ -4103,8 +4883,8 @@
         if (dir > 0 && !moveOnce(!first)) break;
       }
     }
-    var result = skipAtomic(doc, Pos(line, ch), origDir, true);
-    if (!possible) result.hitSide = true;
+    var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true);
+    if (!cmp(pos, result)) result.hitSide = true;
     return result;
   }
 
@@ -4140,7 +4920,7 @@
 
   CodeMirror.prototype = {
     constructor: CodeMirror,
-    focus: function(){window.focus(); focusInput(this); fastPoll(this);},
+    focus: function(){window.focus(); this.display.input.focus();},
 
     setOption: function(option, value) {
       var options = this.options, old = options[option];
@@ -4251,7 +5031,7 @@
 
     getHelpers: function(pos, type) {
       var found = [];
-      if (!helpers.hasOwnProperty(type)) return helpers;
+      if (!helpers.hasOwnProperty(type)) return found;
       var help = helpers[type], mode = this.getModeAt(pos);
       if (typeof mode[type] == "string") {
         if (help[mode[type]]) found.push(help[mode[type]]);
@@ -4301,10 +5081,15 @@
       return lineAtHeight(this.doc, height + this.display.viewOffset);
     },
     heightAtLine: function(line, mode) {
-      var end = false, last = this.doc.first + this.doc.size - 1;
-      if (line < this.doc.first) line = this.doc.first;
-      else if (line > last) { line = last; end = true; }
-      var lineObj = getLine(this.doc, line);
+      var end = false, lineObj;
+      if (typeof line == "number") {
+        var last = this.doc.first + this.doc.size - 1;
+        if (line < this.doc.first) line = this.doc.first;
+        else if (line > last) { line = last; end = true; }
+        lineObj = getLine(this.doc, line);
+      } else {
+        lineObj = line;
+      }
       return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
         (end ? this.doc.height - heightAtLine(lineObj) : 0);
     },
@@ -4333,12 +5118,6 @@
       });
     }),
 
-    addLineWidget: methodOp(function(handle, node, options) {
-      return addLineWidget(this, handle, node, options);
-    }),
-
-    removeLineWidget: function(widget) { widget.clear(); },
-
     lineInfo: function(line) {
       if (typeof line == "number") {
         if (!isLine(this.doc, line)) return null;
@@ -4362,6 +5141,7 @@
       var top = pos.bottom, left = pos.left;
       node.style.position = "absolute";
       node.setAttribute("cm-ignore-events", "true");
+      this.display.input.setUneditable(node);
       display.sizer.appendChild(node);
       if (vert == "over") {
         top = pos.top;
@@ -4396,9 +5176,11 @@
 
     execCommand: function(cmd) {
       if (commands.hasOwnProperty(cmd))
-        return commands[cmd](this);
+        return commands[cmd].call(null, this);
     },
 
+    triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
+
     findPosH: function(from, amount, unit, visually) {
       var dir = 1;
       if (amount < 0) { dir = -1; amount = -amount; }
@@ -4488,7 +5270,8 @@
 
       signal(this, "overwriteToggle", this, this.state.overwrite);
     },
-    hasFocus: function() { return activeElt() == this.display.input; },
+    hasFocus: function() { return this.display.input.getField() == activeElt(); },
+    isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit); },
 
     scrollTo: methodOp(function(x, y) {
       if (x != null || y != null) resolveScrollToPos(this);
@@ -4564,14 +5347,14 @@
       old.cm = null;
       attachDoc(this, doc);
       clearCaches(this);
-      resetInput(this);
+      this.display.input.reset();
       this.scrollTo(doc.scrollLeft, doc.scrollTop);
       this.curOp.forceScroll = true;
       signalLater(this, "swapDoc", this, old);
       return old;
     }),
 
-    getInputField: function(){return this.display.input;},
+    getInputField: function(){return this.display.input.getField();},
     getWrapperElement: function(){return this.display.wrapper;},
     getScrollerElement: function(){return this.display.scroller;},
     getGutterElement: function(){return this.display.gutters;}
@@ -4612,12 +5395,31 @@
     clearCaches(cm);
     regChange(cm);
   }, true);
-  option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val) {
-    cm.options.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
-    cm.refresh();
-  }, true);
+  option("lineSeparator", null, function(cm, val) {
+    cm.doc.lineSep = val;
+    if (!val) return;
+    var newBreaks = [], lineNo = cm.doc.first;
+    cm.doc.iter(function(line) {
+      for (var pos = 0;;) {
+        var found = line.text.indexOf(val, pos);
+        if (found == -1) break;
+        pos = found + val.length;
+        newBreaks.push(Pos(lineNo, found));
+      }
+      lineNo++;
+    });
+    for (var i = newBreaks.length - 1; i >= 0; i--)
+      replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
+  });
+  option("specialChars", /[\u0000-\u001f\u007f\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
+    cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
+    if (old != CodeMirror.Init) cm.refresh();
+  });
   option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
   option("electricChars", true);
+  option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
+    throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
+  }, true);
   option("rtlMoveVisually", !windows);
   option("wholeLineUpdateBefore", true);
 
@@ -4658,6 +5460,7 @@
   option("showCursorWhenSelecting", false, updateSelection, true);
 
   option("resetSelectionOnContextMenu", true);
+  option("lineWiseCopyCut", true);
 
   option("readOnly", false, function(cm, val) {
     if (val == "nocursor") {
@@ -4666,11 +5469,12 @@
       cm.display.disabled = true;
     } else {
       cm.display.disabled = false;
-      if (!val) resetInput(cm);
     }
+    cm.display.input.readOnlyChanged(val)
   });
-  option("disableInput", false, function(cm, val) {if (!val) resetInput(cm);}, true);
-  option("dragDrop", true);
+  option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
+  option("dragDrop", true, dragDropChanged);
+  option("allowDropFileTypes", null);
 
   option("cursorBlinkRate", 530);
   option("cursorScrollMargin", 0);
@@ -4686,11 +5490,11 @@
   option("viewportMargin", 10, function(cm){cm.refresh();}, true);
   option("maxHighlightLength", 10000, resetModeState, true);
   option("moveInputWithCursor", true, function(cm, val) {
-    if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
+    if (!val) cm.display.input.resetPosition();
   });
 
   option("tabindex", null, function(cm, val) {
-    cm.display.input.tabIndex = val || "";
+    cm.display.input.getField().tabIndex = val || "";
   });
   option("autofocus", null);
 
@@ -4936,7 +5740,7 @@
       for (var i = 0; i < ranges.length; i++) {
         var pos = ranges[i].from();
         var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
-        spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
+        spaces.push(spaceStr(tabSize - col % tabSize));
       }
       cm.replaceSelections(spaces);
     },
@@ -4958,7 +5762,8 @@
             } else if (cur.line > cm.doc.first) {
               var prev = getLine(cm.doc, cur.line - 1).text;
               if (prev)
-                cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
+                cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
+                                prev.charAt(prev.length - 1),
                                 Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
             }
           }
@@ -4972,12 +5777,13 @@
         var len = cm.listSelections().length;
         for (var i = 0; i < len; i++) {
           var range = cm.listSelections()[i];
-          cm.replaceRange("\n", range.anchor, range.head, "+input");
+          cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input");
           cm.indentLine(range.from().line + 1, null, true);
-          ensureCursorVisible(cm);
         }
+        ensureCursorVisible(cm);
       });
     },
+    openLine: function(cm) {cm.replaceSelection("\n", "start")},
     toggleOverwrite: function(cm) {cm.toggleOverwrite();}
   };
 
@@ -5012,7 +5818,8 @@
     "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
     "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
     "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
-    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
+    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
+    "Ctrl-O": "openLine"
   };
   keyMap.macDefault = {
     "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
@@ -5062,7 +5869,7 @@
       for (var i = 0; i < keys.length; i++) {
         var val, name;
         if (i == keys.length - 1) {
-          name = keyname;
+          name = keys.join(" ");
           val = value;
         } else {
           name = keys.slice(0, i + 1).join(" ");
@@ -5121,10 +5928,10 @@
   // FROMTEXTAREA
 
   CodeMirror.fromTextArea = function(textarea, options) {
-    if (!options) options = {};
+    options = options ? copyObj(options) : {};
     options.value = textarea.value;
-    if (!options.tabindex && textarea.tabindex)
-      options.tabindex = textarea.tabindex;
+    if (!options.tabindex && textarea.tabIndex)
+      options.tabindex = textarea.tabIndex;
     if (!options.placeholder && textarea.placeholder)
       options.placeholder = textarea.placeholder;
     // Set autofocus to true if this textarea is focused, or if it has
@@ -5152,23 +5959,26 @@
       }
     }
 
+    options.finishInit = function(cm) {
+      cm.save = save;
+      cm.getTextArea = function() { return textarea; };
+      cm.toTextArea = function() {
+        cm.toTextArea = isNaN; // Prevent this from being ran twice
+        save();
+        textarea.parentNode.removeChild(cm.getWrapperElement());
+        textarea.style.display = "";
+        if (textarea.form) {
+          off(textarea.form, "submit", save);
+          if (typeof textarea.form.submit == "function")
+            textarea.form.submit = realSubmit;
+        }
+      };
+    };
+
     textarea.style.display = "none";
     var cm = CodeMirror(function(node) {
       textarea.parentNode.insertBefore(node, textarea.nextSibling);
     }, options);
-    cm.save = save;
-    cm.getTextArea = function() { return textarea; };
-    cm.toTextArea = function() {
-      cm.toTextArea = isNaN; // Prevent this from being ran twice
-      save();
-      textarea.parentNode.removeChild(cm.getWrapperElement());
-      textarea.style.display = "";
-      if (textarea.form) {
-        off(textarea.form, "submit", save);
-        if (typeof textarea.form.submit == "function")
-          textarea.form.submit = realSubmit;
-      }
-    };
     return cm;
   };
 
@@ -5261,10 +6071,13 @@
   // marker continues beyond the start/end of the line. Markers have
   // links back to the lines they currently touch.
 
+  var nextMarkerId = 0;
+
   var TextMarker = CodeMirror.TextMarker = function(doc, type) {
     this.lines = [];
     this.type = type;
     this.doc = doc;
+    this.id = ++nextMarkerId;
   };
   eventMixin(TextMarker);
 
@@ -5768,8 +6581,8 @@
       var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
       var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
       if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
-      if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
-          fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
+      if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
+          fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
         return true;
     }
   }
@@ -5848,10 +6661,10 @@
 
   // Line widgets are block elements displayed above or below a line.
 
-  var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
+  var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
     if (options) for (var opt in options) if (options.hasOwnProperty(opt))
       this[opt] = options[opt];
-    this.cm = cm;
+    this.doc = doc;
     this.node = node;
   };
   eventMixin(LineWidget);
@@ -5862,52 +6675,55 @@
   }
 
   LineWidget.prototype.clear = function() {
-    var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
+    var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
     if (no == null || !ws) return;
     for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
     if (!ws.length) line.widgets = null;
     var height = widgetHeight(this);
-    runInOp(cm, function() {
+    updateLineHeight(line, Math.max(0, line.height - height));
+    if (cm) runInOp(cm, function() {
       adjustScrollWhenAboveVisible(cm, line, -height);
       regLineChange(cm, no, "widget");
-      updateLineHeight(line, Math.max(0, line.height - height));
     });
   };
   LineWidget.prototype.changed = function() {
-    var oldH = this.height, cm = this.cm, line = this.line;
+    var oldH = this.height, cm = this.doc.cm, line = this.line;
     this.height = null;
     var diff = widgetHeight(this) - oldH;
     if (!diff) return;
-    runInOp(cm, function() {
+    updateLineHeight(line, line.height + diff);
+    if (cm) runInOp(cm, function() {
       cm.curOp.forceUpdate = true;
       adjustScrollWhenAboveVisible(cm, line, diff);
-      updateLineHeight(line, line.height + diff);
     });
   };
 
   function widgetHeight(widget) {
     if (widget.height != null) return widget.height;
+    var cm = widget.doc.cm;
+    if (!cm) return 0;
     if (!contains(document.body, widget.node)) {
       var parentStyle = "position: relative;";
       if (widget.coverGutter)
-        parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;";
+        parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
       if (widget.noHScroll)
-        parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;";
-      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));
+        parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
+      removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
     }
-    return widget.height = widget.node.offsetHeight;
+    return widget.height = widget.node.parentNode.offsetHeight;
   }
 
-  function addLineWidget(cm, handle, node, options) {
-    var widget = new LineWidget(cm, node, options);
-    if (widget.noHScroll) cm.display.alignWidgets = true;
-    changeLine(cm.doc, handle, "widget", function(line) {
+  function addLineWidget(doc, handle, node, options) {
+    var widget = new LineWidget(doc, node, options);
+    var cm = doc.cm;
+    if (cm && widget.noHScroll) cm.display.alignWidgets = true;
+    changeLine(doc, handle, "widget", function(line) {
       var widgets = line.widgets || (line.widgets = []);
       if (widget.insertAt == null) widgets.push(widget);
       else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
       widget.line = line;
-      if (!lineIsHidden(cm.doc, line)) {
-        var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;
+      if (cm && !lineIsHidden(doc, line)) {
+        var aboveVisible = heightAtLine(line) < doc.scrollTop;
         updateLineHeight(line, line.height + widgetHeight(widget));
         if (aboveVisible) addToScrollPos(cm, null, widget.height);
         cm.curOp.forceUpdate = true;
@@ -6083,7 +6899,9 @@
 
   function getLineStyles(cm, line, updateFrontier) {
     if (!line.styles || line.styles[0] != cm.state.modeGen) {
-      var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
+      var state = getStateBefore(cm, lineNo(line));
+      var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state);
+      line.stateAfter = state;
       line.styles = result.styles;
       if (result.classes) line.styleClasses = result.classes;
       else if (line.styleClasses) line.styleClasses = null;
@@ -6100,7 +6918,7 @@
     var stream = new StringStream(text, cm.options.tabSize);
     stream.start = stream.pos = startAt || 0;
     if (text == "") callBlankLine(mode, state);
-    while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
+    while (!stream.eol()) {
       readToken(mode, stream, state);
       stream.start = stream.pos;
     }
@@ -6127,7 +6945,10 @@
     // is needed on Webkit to be able to get line-level bounding
     // rectangles for it (in measureChar).
     var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
-    var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm};
+    var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
+                   col: 0, pos: 0, cm: cm,
+                   trailingSpace: false,
+                   splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
     lineView.measure = {};
 
     // Iterate over the logical lines that make up this visual line.
@@ -6137,8 +6958,6 @@
       builder.addToken = buildToken;
       // Optionally wire in some hacks into the token-rendering
       // algorithm, to deal with browser quirks.
-      if ((ie || webkit) && cm.getOption("lineWrapping"))
-        builder.addToken = buildTokenSplitSpaces(builder.addToken);
       if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
         builder.addToken = buildTokenBadBidi(builder.addToken, order);
       builder.map = [];
@@ -6166,8 +6985,11 @@
     }
 
     // See issue #2901
-    if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
-      builder.content.className = "cm-tab-wrap-hack";
+    if (webkit) {
+      var last = builder.content.lastChild
+      if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
+        builder.content.className = "cm-tab-wrap-hack";
+    }
 
     signal(cm, "renderLine", cm, lineView.line, builder.pre);
     if (builder.pre.className)
@@ -6179,6 +7001,7 @@
   function defaultSpecialCharPlaceholder(ch) {
     var token = elt("span", "\u2022", "cm-invalidchar");
     token.title = "\\u" + ch.charCodeAt(0).toString(16);
+    token.setAttribute("aria-label", token.title);
     return token;
   }
 
@@ -6186,10 +7009,11 @@
   // the line map. Takes care to render special characters separately.
   function buildToken(builder, text, style, startStyle, endStyle, title, css) {
     if (!text) return;
-    var special = builder.cm.options.specialChars, mustWrap = false;
+    var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text
+    var special = builder.cm.state.specialChars, mustWrap = false;
     if (!special.test(text)) {
       builder.col += text.length;
-      var content = document.createTextNode(text);
+      var content = document.createTextNode(displayText);
       builder.map.push(builder.pos, builder.pos + text.length, content);
       if (ie && ie_version < 9) mustWrap = true;
       builder.pos += text.length;
@@ -6200,7 +7024,7 @@
         var m = special.exec(text);
         var skipped = m ? m.index - pos : text.length - pos;
         if (skipped) {
-          var txt = document.createTextNode(text.slice(pos, pos + skipped));
+          var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
           if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
           else content.appendChild(txt);
           builder.map.push(builder.pos, builder.pos + skipped, txt);
@@ -6212,9 +7036,16 @@
         if (m[0] == "\t") {
           var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
           var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
+          txt.setAttribute("role", "presentation");
+          txt.setAttribute("cm-text", "\t");
           builder.col += tabWidth;
+        } else if (m[0] == "\r" || m[0] == "\n") {
+          var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
+          txt.setAttribute("cm-text", m[0]);
+          builder.col += 1;
         } else {
           var txt = builder.cm.options.specialCharPlaceholder(m[0]);
+          txt.setAttribute("cm-text", m[0]);
           if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
           else content.appendChild(txt);
           builder.col += 1;
@@ -6223,6 +7054,7 @@
         builder.pos++;
       }
     }
+    builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32
     if (style || startStyle || endStyle || mustWrap || css) {
       var fullStyle = style || "";
       if (startStyle) fullStyle += startStyle;
@@ -6234,22 +7066,23 @@
     builder.content.appendChild(content);
   }
 
-  function buildTokenSplitSpaces(inner) {
-    function split(old) {
-      var out = " ";
-      for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
-      out += " ";
-      return out;
+  function splitSpaces(text, trailingBefore) {
+    if (text.length > 1 && !/  /.test(text)) return text
+    var spaceBefore = trailingBefore, result = ""
+    for (var i = 0; i < text.length; i++) {
+      var ch = text.charAt(i)
+      if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
+        ch = "\u00a0"
+      result += ch
+      spaceBefore = ch == " "
     }
-    return function(builder, text, style, startStyle, endStyle, title) {
-      inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);
-    };
+    return result
   }
 
   // Work around nonsense dimensions being reported for stretches of
   // right-to-left text.
   function buildTokenBadBidi(inner, order) {
-    return function(builder, text, style, startStyle, endStyle, title) {
+    return function(builder, text, style, startStyle, endStyle, title, css) {
       style = style ? style + " cm-force-border" : "cm-force-border";
       var start = builder.pos, end = start + text.length;
       for (;;) {
@@ -6258,8 +7091,8 @@
           var part = order[i];
           if (part.to > start && part.from <= start) break;
         }
-        if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title);
-        inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);
+        if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
+        inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
         startStyle = null;
         text = text.slice(part.to - start);
         start = part.to;
@@ -6269,11 +7102,18 @@
 
   function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
     var widget = !ignoreWidget && marker.widgetNode;
+    if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
+    if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
+      if (!widget)
+        widget = builder.content.appendChild(document.createElement("span"));
+      widget.setAttribute("cm-marker", marker.id);
+    }
     if (widget) {
-      builder.map.push(builder.pos, builder.pos + size, widget);
+      builder.cm.display.input.setUneditable(widget);
       builder.content.appendChild(widget);
     }
     builder.pos += size;
+    builder.trailingSpace = false
   }
 
   // Outputs a number of spans to make up a line, taking highlighting
@@ -6292,30 +7132,38 @@
       if (nextChange == pos) { // Update current marker set
         spanStyle = spanEndStyle = spanStartStyle = title = css = "";
         collapsed = null; nextChange = Infinity;
-        var foundBookmarks = [];
+        var foundBookmarks = [], endStyles
         for (var j = 0; j < spans.length; ++j) {
           var sp = spans[j], m = sp.marker;
-          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
-            if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
+          if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
+            foundBookmarks.push(m);
+          } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
+            if (sp.to != null && sp.to != pos && nextChange > sp.to) {
+              nextChange = sp.to;
+              spanEndStyle = "";
+            }
             if (m.className) spanStyle += " " + m.className;
-            if (m.css) css = m.css;
+            if (m.css) css = (css ? css + ";" : "") + m.css;
             if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
-            if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
+            if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to)
             if (m.title && !title) title = m.title;
             if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
               collapsed = sp;
           } else if (sp.from > pos && nextChange > sp.from) {
             nextChange = sp.from;
           }
-          if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);
         }
+        if (endStyles) for (var j = 0; j < endStyles.length; j += 2)
+          if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j]
+
+        if (!collapsed || collapsed.from == pos) for (var j = 0; j < foundBookmarks.length; ++j)
+          buildCollapsedSpan(builder, 0, foundBookmarks[j]);
         if (collapsed && (collapsed.from || 0) == pos) {
           buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
                              collapsed.marker, collapsed.from == null);
           if (collapsed.to == null) return;
+          if (collapsed.to == pos) collapsed = false;
         }
-        if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
-          buildCollapsedSpan(builder, 0, foundBookmarks[j]);
       }
       if (pos >= len) break;
 
@@ -6501,13 +7349,16 @@
         if (at <= sz) {
           child.insertInner(at, lines, height);
           if (child.lines && child.lines.length > 50) {
-            while (child.lines.length > 50) {
-              var spilled = child.lines.splice(child.lines.length - 25, 25);
-              var newleaf = new LeafChunk(spilled);
-              child.height -= newleaf.height;
-              this.children.splice(i + 1, 0, newleaf);
-              newleaf.parent = this;
+            // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
+            // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
+            var remaining = child.lines.length % 25 + 25
+            for (var pos = remaining; pos < child.lines.length;) {
+              var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));
+              child.height -= leaf.height;
+              this.children.splice(++i, 0, leaf);
+              leaf.parent = this;
             }
+            child.lines = child.lines.slice(0, remaining);
             this.maybeSpill();
           }
           break;
@@ -6527,7 +7378,7 @@
           copy.parent = me;
           me.children = [copy, sibling];
           me = copy;
-        } else {
+       } else {
           me.size -= sibling.size;
           me.height -= sibling.height;
           var myIndex = indexOf(me.parent.children, me);
@@ -6551,8 +7402,8 @@
   };
 
   var nextDocId = 0;
-  var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
-    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
+  var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) {
+    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep);
     if (firstLine == null) firstLine = 0;
 
     BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
@@ -6566,8 +7417,10 @@
     this.history = new History(null);
     this.id = ++nextDocId;
     this.modeOption = mode;
+    this.lineSep = lineSep;
+    this.extend = false;
 
-    if (typeof text == "string") text = splitLines(text);
+    if (typeof text == "string") text = this.splitLines(text);
     updateDoc(this, {from: start, to: start, text: text});
     setSelection(this, simpleSelection(start), sel_dontScroll);
   };
@@ -6597,12 +7450,12 @@
     getValue: function(lineSep) {
       var lines = getLines(this, this.first, this.first + this.size);
       if (lineSep === false) return lines;
-      return lines.join(lineSep || "\n");
+      return lines.join(lineSep || this.lineSeparator());
     },
     setValue: docMethodOp(function(code) {
       var top = Pos(this.first, 0), last = this.first + this.size - 1;
       makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
-                        text: splitLines(code), origin: "setValue", full: true}, true);
+                        text: this.splitLines(code), origin: "setValue", full: true}, true);
       setSelection(this, simpleSelection(top));
     }),
     replaceRange: function(code, from, to, origin) {
@@ -6613,7 +7466,7 @@
     getRange: function(from, to, lineSep) {
       var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
       if (lineSep === false) return lines;
-      return lines.join(lineSep || "\n");
+      return lines.join(lineSep || this.lineSeparator());
     },
 
     getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
@@ -6653,10 +7506,11 @@
       extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
     }),
     extendSelections: docMethodOp(function(heads, options) {
-      extendSelections(this, clipPosArray(this, heads, options));
+      extendSelections(this, clipPosArray(this, heads), options);
     }),
     extendSelectionsBy: docMethodOp(function(f, options) {
-      extendSelections(this, map(this.sel.ranges, f), options);
+      var heads = map(this.sel.ranges, f);
+      extendSelections(this, clipPosArray(this, heads), options);
     }),
     setSelections: docMethodOp(function(ranges, primary, options) {
       if (!ranges.length) return;
@@ -6679,13 +7533,13 @@
         lines = lines ? lines.concat(sel) : sel;
       }
       if (lineSep === false) return lines;
-      else return lines.join(lineSep || "\n");
+      else return lines.join(lineSep || this.lineSeparator());
     },
     getSelections: function(lineSep) {
       var parts = [], ranges = this.sel.ranges;
       for (var i = 0; i < ranges.length; i++) {
         var sel = getBetween(this, ranges[i].from(), ranges[i].to());
-        if (lineSep !== false) sel = sel.join(lineSep || "\n");
+        if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator());
         parts[i] = sel;
       }
       return parts;
@@ -6700,7 +7554,7 @@
       var changes = [], sel = this.sel;
       for (var i = 0; i < sel.ranges.length; i++) {
         var range = sel.ranges[i];
-        changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};
+        changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
       }
       var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
       for (var i = changes.length - 1; i >= 0; i--)
@@ -6775,13 +7629,19 @@
       });
     }),
 
+    addLineWidget: docMethodOp(function(handle, node, options) {
+      return addLineWidget(this, handle, node, options);
+    }),
+    removeLineWidget: function(widget) { widget.clear(); },
+
     markText: function(from, to, options) {
-      return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
+      return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range");
     },
     setBookmark: function(pos, options) {
       var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
                       insertLeft: options && options.insertLeft,
-                      clearWhenEmpty: false, shared: options && options.shared};
+                      clearWhenEmpty: false, shared: options && options.shared,
+                      handleMouseEvents: options && options.handleMouseEvents};
       pos = clipPos(this, pos);
       return markText(this, pos, pos, realOpts, "bookmark");
     },
@@ -6803,9 +7663,9 @@
         var spans = line.markedSpans;
         if (spans) for (var i = 0; i < spans.length; i++) {
           var span = spans[i];
-          if (!(lineNo == from.line && from.ch > span.to ||
-                span.from == null && lineNo != from.line||
-                lineNo == to.line && span.from > to.ch) &&
+          if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
+                span.from == null && lineNo != from.line ||
+                span.from != null && lineNo == to.line && span.from >= to.ch) &&
               (!filter || filter(span.marker)))
             found.push(span.marker.parent || span.marker);
         }
@@ -6824,9 +7684,9 @@
     },
 
     posFromIndex: function(off) {
-      var ch, lineNo = this.first;
+      var ch, lineNo = this.first, sepSize = this.lineSeparator().length;
       this.iter(function(line) {
-        var sz = line.text.length + 1;
+        var sz = line.text.length + sepSize;
         if (sz > off) { ch = off; return true; }
         off -= sz;
         ++lineNo;
@@ -6837,14 +7697,16 @@
       coords = clipPos(this, coords);
       var index = coords.ch;
       if (coords.line < this.first || coords.ch < 0) return 0;
+      var sepSize = this.lineSeparator().length;
       this.iter(this.first, coords.line, function (line) {
-        index += line.text.length + 1;
+        index += line.text.length + sepSize;
       });
       return index;
     },
 
     copy: function(copyHistory) {
-      var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
+      var doc = new Doc(getLines(this, this.first, this.first + this.size),
+                        this.modeOption, this.first, this.lineSep);
       doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
       doc.sel = this.sel;
       doc.extend = false;
@@ -6860,7 +7722,7 @@
       var from = this.first, to = this.first + this.size;
       if (options.from != null && options.from > from) from = options.from;
       if (options.to != null && options.to < to) to = options.to;
-      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
+      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep);
       if (options.sharedHist) copy.history = this.history;
       (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
       copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
@@ -6889,14 +7751,20 @@
     iterLinkedDocs: function(f) {linkedDocs(this, f);},
 
     getMode: function() {return this.mode;},
-    getEditor: function() {return this.cm;}
+    getEditor: function() {return this.cm;},
+
+    splitLines: function(str) {
+      if (this.lineSep) return str.split(this.lineSep);
+      return splitLinesAuto(str);
+    },
+    lineSeparator: function() { return this.lineSep || "\n"; }
   });
 
   // Public alias.
   Doc.prototype.eachLine = Doc.prototype.iter;
 
   // Set up methods on CodeMirror's prototype to redirect to the editor's document.
-  var dontDelegate = "iter insert remove copy getEditor".split(" ");
+  var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
   for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
     CodeMirror.prototype[prop] = (function(method) {
       return function() {return method.apply(this.doc, arguments);};
@@ -7329,24 +8197,30 @@
     }
   };
 
+  var noHandlers = []
+  function getHandlers(emitter, type, copy) {
+    var arr = emitter._handlers && emitter._handlers[type]
+    if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
+    else return arr || noHandlers
+  }
+
   var off = CodeMirror.off = function(emitter, type, f) {
     if (emitter.removeEventListener)
       emitter.removeEventListener(type, f, false);
     else if (emitter.detachEvent)
       emitter.detachEvent("on" + type, f);
     else {
-      var arr = emitter._handlers && emitter._handlers[type];
-      if (!arr) return;
-      for (var i = 0; i < arr.length; ++i)
-        if (arr[i] == f) { arr.splice(i, 1); break; }
+      var handlers = getHandlers(emitter, type, false)
+      for (var i = 0; i < handlers.length; ++i)
+        if (handlers[i] == f) { handlers.splice(i, 1); break; }
     }
   };
 
   var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
-    var arr = emitter._handlers && emitter._handlers[type];
-    if (!arr) return;
+    var handlers = getHandlers(emitter, type, true)
+    if (!handlers.length) return;
     var args = Array.prototype.slice.call(arguments, 2);
-    for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
+    for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
   };
 
   var orphanDelayedCallbacks = null;
@@ -7359,8 +8233,8 @@
   // them to be executed when the last operation ends, or, if no
   // operation is active, when a timeout fires.
   function signalLater(emitter, type /*, values...*/) {
-    var arr = emitter._handlers && emitter._handlers[type];
-    if (!arr) return;
+    var arr = getHandlers(emitter, type, false)
+    if (!arr.length) return;
     var args = Array.prototype.slice.call(arguments, 2), list;
     if (operationGroup) {
       list = operationGroup.delayedCallbacks;
@@ -7400,8 +8274,7 @@
   }
 
   function hasHandler(emitter, type) {
-    var arr = emitter._handlers && emitter._handlers[type];
-    return arr && arr.length > 0;
+    return getHandlers(emitter, type).length > 0
   }
 
   // Add on and off methods to a constructor's prototype, to make
@@ -7448,7 +8321,7 @@
 
   // The inverse of countColumn -- find the offset that corresponds to
   // a particular column.
-  function findColumn(string, goal, tabSize) {
+  var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {
     for (var pos = 0, col = 0;;) {
       var nextTab = string.indexOf("\t", pos);
       if (nextTab == -1) nextTab = string.length;
@@ -7488,14 +8361,15 @@
     return out;
   }
 
+  function nothing() {}
+
   function createObj(base, props) {
     var inst;
     if (Object.create) {
       inst = Object.create(base);
     } else {
-      var ctor = function() {};
-      ctor.prototype = base;
-      inst = new ctor();
+      nothing.prototype = base;
+      inst = new nothing();
     }
     if (props) copyObj(props, inst);
     return inst;
@@ -7514,7 +8388,7 @@
     return function(){return f.apply(null, args);};
   }
 
-  var nonASCIISingleCaseWordChar = /[\u00df\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
+  var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
   var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
     return /\w/.test(ch) || ch > "\x80" &&
       (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
@@ -7550,9 +8424,9 @@
   }
 
   var range;
-  if (document.createRange) range = function(node, start, end) {
+  if (document.createRange) range = function(node, start, end, endNode) {
     var r = document.createRange();
-    r.setEnd(node, end);
+    r.setEnd(endNode || node, end);
     r.setStart(node, start);
     return r;
   };
@@ -7576,14 +8450,23 @@
     return removeChildren(parent).appendChild(e);
   }
 
-  function contains(parent, child) {
+  var contains = CodeMirror.contains = function(parent, child) {
+    if (child.nodeType == 3) // Android browser always returns false when child is a textnode
+      child = child.parentNode;
     if (parent.contains)
       return parent.contains(child);
-    while (child = child.parentNode)
+    do {
+      if (child.nodeType == 11) child = child.host;
       if (child == parent) return true;
-  }
+    } while (child = child.parentNode);
+  };
 
-  function activeElt() { return document.activeElement; }
+  function activeElt() {
+    var activeElement = document.activeElement;
+    while (activeElement && activeElement.root && activeElement.root.activeElement)
+      activeElement = activeElement.root.activeElement;
+    return activeElement;
+  }
   // Older versions of IE throws unspecified error when touching
   // document.activeElement in some cases (during loading, in iframe)
   if (ie && ie_version < 11) activeElt = function() {
@@ -7666,8 +8549,10 @@
       if (measure.firstChild.offsetHeight != 0)
         zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
     }
-    if (zwspSupported) return elt("span", "\u200b");
-    else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
+    var node = zwspSupported ? elt("span", "\u200b") :
+      elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
+    node.setAttribute("cm-text", "");
+    return node;
   }
 
   // Feature-detect IE's crummy client rect reporting for bidi text
@@ -7676,14 +8561,15 @@
     if (badBidiRects != null) return badBidiRects;
     var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
     var r0 = range(txt, 0, 1).getBoundingClientRect();
-    if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
     var r1 = range(txt, 1, 2).getBoundingClientRect();
+    removeChildren(measure);
+    if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
     return badBidiRects = (r1.right - r0.right < 3);
   }
 
   // See if "".split is the broken IE version, if so, provide an
   // alternative way to split lines.
-  var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
+  var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
     var pos = 0, result = [], l = string.length;
     while (pos <= l) {
       var nl = string.indexOf("\n", pos);
@@ -7729,14 +8615,16 @@
 
   // KEY NAMES
 
-  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
-                  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
-                  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
-                  46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
-                  173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
-                  221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
-                  63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
-  CodeMirror.keyNames = keyNames;
+  var keyNames = CodeMirror.keyNames = {
+    3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
+    19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
+    36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
+    46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
+    106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
+    173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+    221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
+    63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
+  };
   (function() {
     // Number keys
     for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
@@ -8030,6 +8918,8 @@
         lst(order).to -= m[0].length;
         order.push(new BidiSpan(0, len - m[0].length, len));
       }
+      if (order[0].level == 2)
+        order.unshift(new BidiSpan(1, order[0].to, order[0].to));
       if (order[0].level != lst(order).level)
         order.push(new BidiSpan(order[0].level, len, len));
 
@@ -8039,7 +8929,7 @@
 
   // THE END
 
-  CodeMirror.version = "4.12.0";
+  CodeMirror.version = "5.17.1";
 
   return CodeMirror;
-});
+});
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/comment.js b/third_party/WebKit/Source/devtools/front_end/cm/comment.js
index 2dd114d..2c4f975d 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/comment.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/comment.js
@@ -21,26 +21,40 @@
   }
 
   CodeMirror.commands.toggleComment = function(cm) {
-    var minLine = Infinity, ranges = cm.listSelections(), mode = null;
+    cm.toggleComment();
+  };
+
+  CodeMirror.defineExtension("toggleComment", function(options) {
+    if (!options) options = noOptions;
+    var cm = this;
+    var minLine = Infinity, ranges = this.listSelections(), mode = null;
     for (var i = ranges.length - 1; i >= 0; i--) {
       var from = ranges[i].from(), to = ranges[i].to();
       if (from.line >= minLine) continue;
       if (to.line >= minLine) to = Pos(minLine, 0);
       minLine = from.line;
       if (mode == null) {
-        if (cm.uncomment(from, to)) mode = "un";
-        else { cm.lineComment(from, to); mode = "line"; }
+        if (cm.uncomment(from, to, options)) mode = "un";
+        else { cm.lineComment(from, to, options); mode = "line"; }
       } else if (mode == "un") {
-        cm.uncomment(from, to);
+        cm.uncomment(from, to, options);
       } else {
-        cm.lineComment(from, to);
+        cm.lineComment(from, to, options);
       }
     }
-  };
+  });
+
+  // Rough heuristic to try and detect lines that are part of multi-line string
+  function probablyInsideString(cm, pos, line) {
+    return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"`]/.test(line)
+  }
 
   CodeMirror.defineExtension("lineComment", function(from, to, options) {
     if (!options) options = noOptions;
     var self = this, mode = self.getModeAt(from);
+    var firstLine = self.getLine(from.line);
+    if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
+
     var commentString = options.lineComment || mode.lineComment;
     if (!commentString) {
       if (options.blockCommentStart || mode.blockCommentStart) {
@@ -49,15 +63,21 @@
       }
       return;
     }
-    var firstLine = self.getLine(from.line);
-    if (firstLine == null) return;
+
     var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
     var pad = options.padding == null ? " " : options.padding;
     var blankLines = options.commentBlankLines || from.line == to.line;
 
     self.operation(function() {
       if (options.indent) {
-        var baseString = firstLine.slice(0, firstNonWS(firstLine));
+        var baseString = null;
+        for (var i = from.line; i < end; ++i) {
+          var line = self.getLine(i);
+          var whitespace = line.slice(0, firstNonWS(line));
+          if (baseString == null || baseString.length > whitespace.length) {
+            baseString = whitespace;
+          }
+        }
         for (var i = from.line; i < end; ++i) {
           var line = self.getLine(i), cut = baseString.length;
           if (!blankLines && !nonWS.test(line)) continue;
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/css.js b/third_party/WebKit/Source/devtools/front_end/cm/css.js
index 91046d9..5e96a95 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/css.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/css.js
@@ -484,9 +484,9 @@
     "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
     "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
     "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
-    "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
-    "grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
-    "grid-template", "grid-template-areas", "grid-template-columns",
+    "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap",
+    "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap",
+    "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
     "grid-template-rows", "hanging-punctuation", "height", "hyphens",
     "icon", "image-orientation", "image-rendering", "image-resolution",
     "inline-box-align", "justify-content", "left", "letter-spacing",
@@ -601,7 +601,7 @@
     "compact", "condensed", "contain", "content",
     "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
     "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
-    "decimal-leading-zero", "default", "default-button", "destination-atop",
+    "decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
     "destination-in", "destination-out", "destination-over", "devanagari", "difference",
     "disc", "discard", "disclosure-closed", "disclosure-open", "document",
     "dot-dash", "dot-dot-dash",
@@ -615,13 +615,13 @@
     "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
     "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
     "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
-    "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
+    "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
     "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
     "help", "hidden", "hide", "higher", "highlight", "highlighttext",
     "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
     "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
     "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
-    "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
+    "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
     "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
     "katakana", "katakana-iroha", "keep-all", "khmer",
     "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/htmlembedded.js b/third_party/WebKit/Source/devtools/front_end/cm/htmlembedded.js
index e8f7ba8..464dc57f 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/htmlembedded.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/htmlembedded.js
@@ -3,84 +3,26 @@
 
 (function(mod) {
   if (typeof exports == "object" && typeof module == "object") // CommonJS
-    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
+        require("../../addon/mode/multiplex"));
   else if (typeof define == "function" && define.amd) // AMD
-    define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
+            "../../addon/mode/multiplex"], mod);
   else // Plain browser env
     mod(CodeMirror);
 })(function(CodeMirror) {
-"use strict";
+  "use strict";
 
-CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
+  CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
+    return CodeMirror.multiplexingMode(CodeMirror.getMode(config, "htmlmixed"), {
+      open: parserConfig.open || parserConfig.scriptStartRegex || "<%",
+      close: parserConfig.close || parserConfig.scriptEndRegex || "%>",
+      mode: CodeMirror.getMode(config, parserConfig.scriptingModeSpec)
+    });
+  }, "htmlmixed");
 
-  //config settings
-  var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,
-      scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;
-
-  //inner modes
-  var scriptingMode, htmlMixedMode;
-
-  //tokenizer when in html mode
-  function htmlDispatch(stream, state) {
-      if (stream.match(scriptStartRegex, false)) {
-          state.token=scriptingDispatch;
-          return scriptingMode.token(stream, state.scriptState);
-          }
-      else
-          return htmlMixedMode.token(stream, state.htmlState);
-    }
-
-  //tokenizer when in scripting mode
-  function scriptingDispatch(stream, state) {
-      if (stream.match(scriptEndRegex, false))  {
-          state.token=htmlDispatch;
-          return htmlMixedMode.token(stream, state.htmlState);
-         }
-      else
-          return scriptingMode.token(stream, state.scriptState);
-         }
-
-
-  return {
-    startState: function() {
-      scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);
-      htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed");
-      return {
-          token :  parserConfig.startOpen ? scriptingDispatch : htmlDispatch,
-          htmlState : CodeMirror.startState(htmlMixedMode),
-          scriptState : CodeMirror.startState(scriptingMode)
-      };
-    },
-
-    token: function(stream, state) {
-      return state.token(stream, state);
-    },
-
-    indent: function(state, textAfter) {
-      if (state.token == htmlDispatch)
-        return htmlMixedMode.indent(state.htmlState, textAfter);
-      else if (scriptingMode.indent)
-        return scriptingMode.indent(state.scriptState, textAfter);
-    },
-
-    copyState: function(state) {
-      return {
-       token : state.token,
-       htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState),
-       scriptState : CodeMirror.copyState(scriptingMode, state.scriptState)
-      };
-    },
-
-    innerMode: function(state) {
-      if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode};
-      else return {state: state.htmlState, mode: htmlMixedMode};
-    }
-  };
-}, "htmlmixed");
-
-CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"});
-CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
-CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});
-CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"});
-
+  CodeMirror.defineMIME("application/x-ejs", {name: "htmlembedded", scriptingModeSpec:"javascript"});
+  CodeMirror.defineMIME("application/x-aspx", {name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
+  CodeMirror.defineMIME("application/x-jsp", {name: "htmlembedded", scriptingModeSpec:"text/x-java"});
+  CodeMirror.defineMIME("application/x-erb", {name: "htmlembedded", scriptingModeSpec:"ruby"});
 });
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/htmlmixed.js b/third_party/WebKit/Source/devtools/front_end/cm/htmlmixed.js
index 250ef8cd..d74083e 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/htmlmixed.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/htmlmixed.js
@@ -9,113 +9,144 @@
   else // Plain browser env
     mod(CodeMirror);
 })(function(CodeMirror) {
-"use strict";
+  "use strict";
 
-CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
-  var htmlMode = CodeMirror.getMode(config, {name: "xml",
-                                             htmlMode: true,
-                                             multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
-                                             multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
-  var cssMode = CodeMirror.getMode(config, "css");
+  var defaultTags = {
+    script: [
+      ["lang", /(javascript|babel)/i, "javascript"],
+      ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"],
+      ["type", /./, "text/plain"],
+      [null, null, "javascript"]
+    ],
+    style:  [
+      ["lang", /^css$/i, "css"],
+      ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
+      ["type", /./, "text/plain"],
+      [null, null, "css"]
+    ]
+  };
 
-  var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
-  scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
-                    mode: CodeMirror.getMode(config, "javascript")});
-  if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
-    var conf = scriptTypesConf[i];
-    scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
-  }
-  scriptTypes.push({matches: /./,
-                    mode: CodeMirror.getMode(config, "text/plain")});
-
-  function html(stream, state) {
-    var tagName = state.htmlState.tagName;
-    if (tagName) tagName = tagName.toLowerCase();
-    var style = htmlMode.token(stream, state.htmlState);
-    if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
-      // Script block: mode to change to depends on type attribute
-      var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
-      scriptType = scriptType ? scriptType[1] : "";
-      if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
-      for (var i = 0; i < scriptTypes.length; ++i) {
-        var tp = scriptTypes[i];
-        if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
-          if (tp.mode) {
-            state.token = script;
-            state.localMode = tp.mode;
-            state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
-          }
-          break;
-        }
-      }
-    } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
-      state.token = css;
-      state.localMode = cssMode;
-      state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
-    }
-    return style;
-  }
   function maybeBackup(stream, pat, style) {
-    var cur = stream.current();
-    var close = cur.search(pat), m;
-    if (close > -1) stream.backUp(cur.length - close);
-    else if (m = cur.match(/<\/?$/)) {
+    var cur = stream.current(), close = cur.search(pat);
+    if (close > -1) {
+      stream.backUp(cur.length - close);
+    } else if (cur.match(/<\/?$/)) {
       stream.backUp(cur.length);
       if (!stream.match(pat, false)) stream.match(cur);
     }
     return style;
   }
-  function script(stream, state) {
-    if (stream.match(/^<\/\s*script\s*>/i, false)) {
-      state.token = html;
-      state.localState = state.localMode = null;
-      return html(stream, state);
-    }
-    return maybeBackup(stream, /<\/\s*script\s*>/,
-                       state.localMode.token(stream, state.localState));
-  }
-  function css(stream, state) {
-    if (stream.match(/^<\/\s*style\s*>/i, false)) {
-      state.token = html;
-      state.localState = state.localMode = null;
-      return html(stream, state);
-    }
-    return maybeBackup(stream, /<\/\s*style\s*>/,
-                       cssMode.token(stream, state.localState));
+
+  var attrRegexpCache = {};
+  function getAttrRegexp(attr) {
+    var regexp = attrRegexpCache[attr];
+    if (regexp) return regexp;
+    return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
   }
 
-  return {
-    startState: function() {
-      var state = htmlMode.startState();
-      return {token: html, localMode: null, localState: null, htmlState: state};
-    },
+  function getAttrValue(text, attr) {
+    var match = text.match(getAttrRegexp(attr))
+    return match ? match[2] : ""
+  }
 
-    copyState: function(state) {
-      if (state.localState)
-        var local = CodeMirror.copyState(state.localMode, state.localState);
-      return {token: state.token, localMode: state.localMode, localState: local,
-              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
-    },
+  function getTagRegexp(tagName, anchored) {
+    return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
+  }
 
-    token: function(stream, state) {
-      return state.token(stream, state);
-    },
-
-    indent: function(state, textAfter) {
-      if (!state.localMode || /^\s*<\//.test(textAfter))
-        return htmlMode.indent(state.htmlState, textAfter);
-      else if (state.localMode.indent)
-        return state.localMode.indent(state.localState, textAfter);
-      else
-        return CodeMirror.Pass;
-    },
-
-    innerMode: function(state) {
-      return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
+  function addTags(from, to) {
+    for (var tag in from) {
+      var dest = to[tag] || (to[tag] = []);
+      var source = from[tag];
+      for (var i = source.length - 1; i >= 0; i--)
+        dest.unshift(source[i])
     }
-  };
-}, "xml", "javascript", "css");
+  }
 
-CodeMirror.defineMIME("text/html", "htmlmixed");
+  function findMatchingMode(tagInfo, tagText) {
+    for (var i = 0; i < tagInfo.length; i++) {
+      var spec = tagInfo[i];
+      if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
+    }
+  }
 
+  CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
+    var htmlMode = CodeMirror.getMode(config, {
+      name: "xml",
+      htmlMode: true,
+      multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
+      multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
+    });
+
+    var tags = {};
+    var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
+    addTags(defaultTags, tags);
+    if (configTags) addTags(configTags, tags);
+    if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
+      tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
+
+    function html(stream, state) {
+      var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName
+      if (tag && !/[<>\s\/]/.test(stream.current()) &&
+          (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
+          tags.hasOwnProperty(tagName)) {
+        state.inTag = tagName + " "
+      } else if (state.inTag && tag && />$/.test(stream.current())) {
+        var inTag = /^([\S]+) (.*)/.exec(state.inTag)
+        state.inTag = null
+        var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2])
+        var mode = CodeMirror.getMode(config, modeSpec)
+        var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
+        state.token = function (stream, state) {
+          if (stream.match(endTagA, false)) {
+            state.token = html;
+            state.localState = state.localMode = null;
+            return null;
+          }
+          return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
+        };
+        state.localMode = mode;
+        state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
+      } else if (state.inTag) {
+        state.inTag += stream.current()
+        if (stream.eol()) state.inTag += " "
+      }
+      return style;
+    };
+
+    return {
+      startState: function () {
+        var state = CodeMirror.startState(htmlMode);
+        return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
+      },
+
+      copyState: function (state) {
+        var local;
+        if (state.localState) {
+          local = CodeMirror.copyState(state.localMode, state.localState);
+        }
+        return {token: state.token, inTag: state.inTag,
+                localMode: state.localMode, localState: local,
+                htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
+      },
+
+      token: function (stream, state) {
+        return state.token(stream, state);
+      },
+
+      indent: function (state, textAfter) {
+        if (!state.localMode || /^\s*<\//.test(textAfter))
+          return htmlMode.indent(state.htmlState, textAfter);
+        else if (state.localMode.indent)
+          return state.localMode.indent(state.localState, textAfter);
+        else
+          return CodeMirror.Pass;
+      },
+
+      innerMode: function (state) {
+        return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
+      }
+    };
+  }, "xml", "javascript", "css");
+
+  CodeMirror.defineMIME("text/html", "htmlmixed");
 });
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/javascript.js b/third_party/WebKit/Source/devtools/front_end/cm/javascript.js
index c91910f..67f4448d 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/javascript.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/javascript.js
@@ -42,7 +42,8 @@
       "in": operator, "typeof": operator, "instanceof": operator,
       "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
       "this": kw("this"), "class": kw("class"), "super": kw("atom"),
-      "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
+      "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
+      "await": C, "async": kw("async")
     };
 
     // Extend the 'normal' keywords with the TypeScript language extensions
@@ -366,6 +367,7 @@
     if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
     if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
     if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex)
+    if (type == "async") return cont(statement)
     return pass(pushlex("stat"), expression, expect(";"), poplex);
   }
   function expression(type) {
@@ -384,8 +386,8 @@
     var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
     if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
     if (type == "function") return cont(functiondef, maybeop);
-    if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
-    if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
+    if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
+    if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
     if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
     if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
     if (type == "{") return contCommasep(objprop, "}", null, maybeop);
@@ -461,6 +463,7 @@
     if (type == "variable") {cx.marked = "property"; return cont();}
   }
   function objprop(type, value) {
+    if (type == "async") return cont(objprop);
     if (type == "variable" || cx.style == "keyword") {
       cx.marked = "property";
       if (value == "get" || value == "set") return cont(getterSetter);
@@ -488,17 +491,20 @@
     if (type == "(") return pass(functiondef);
   }
   function commasep(what, end) {
-    function proceed(type) {
+    function proceed(type, value) {
       if (type == ",") {
         var lex = cx.state.lexical;
         if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
-        return cont(what, proceed);
+        return cont(function(type, value) {
+          if (type == end || value == end) return pass()
+          return pass(what)
+        }, proceed);
       }
-      if (type == end) return cont();
+      if (type == end || value == end) return cont();
       return cont(expect(end));
     }
-    return function(type) {
-      if (type == end) return cont();
+    return function(type, value) {
+      if (type == end || value == end) return cont();
       return pass(what, proceed);
     };
   }
@@ -512,13 +518,17 @@
     return pass(statement, block);
   }
   function maybetype(type) {
-    if (isTS && type == ":") return cont(typedef);
+    if (isTS && type == ":") return cont(typeexpr);
   }
   function maybedefault(_, value) {
     if (value == "=") return cont(expressionNoComma);
   }
-  function typedef(type) {
-    if (type == "variable") {cx.marked = "variable-3"; return cont();}
+  function typeexpr(type) {
+    if (type == "variable") {cx.marked = "variable-3"; return cont(afterType);}
+  }
+  function afterType(type, value) {
+    if (value == "<") return cont(commasep(typeexpr, ">"), afterType)
+    if (type == "[") return cont(expect("]"), afterType)
   }
   function vardef() {
     return pass(pattern, maybetype, maybeAssign, vardefCont);
@@ -573,7 +583,7 @@
   function functiondef(type, value) {
     if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
     if (type == "variable") {register(value); return cont(functiondef);}
-    if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
+    if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext);
   }
   function funarg(type) {
     if (type == "spread") return cont(funarg);
@@ -631,16 +641,7 @@
   }
   function arrayLiteral(type) {
     if (type == "]") return cont();
-    return pass(expressionNoComma, maybeArrayComprehension);
-  }
-  function maybeArrayComprehension(type) {
-    if (type == "for") return pass(comprehension, expect("]"));
-    if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
-    return pass(commasep(expressionNoComma, "]"));
-  }
-  function comprehension(type) {
-    if (type == "for") return cont(forspec, comprehension);
-    if (type == "if") return cont(expression, comprehension);
+    return pass(expressionNoComma, commasep(expressionNoComma, "]"));
   }
 
   function isContinuedStatement(state, textAfter) {
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/matchbrackets.js b/third_party/WebKit/Source/devtools/front_end/cm/matchbrackets.js
index fa1ae03..70e1ae1 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/matchbrackets.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/matchbrackets.js
@@ -81,7 +81,7 @@
     if (marks.length) {
       // Kludge to work around the IE bug from issue #1193, where text
       // input stops going to the textare whever this fires.
-      if (ie_lt8 && cm.state.focused) cm.display.input.focus();
+      if (ie_lt8 && cm.state.focused) cm.focus();
 
       var clear = function() {
         cm.operation(function() {
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/multiplex.js b/third_party/WebKit/Source/devtools/front_end/cm/multiplex.js
new file mode 100644
index 0000000..3d8b34c
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/cm/multiplex.js
@@ -0,0 +1,123 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.multiplexingMode = function(outer /*, others */) {
+  // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
+  var others = Array.prototype.slice.call(arguments, 1);
+
+  function indexOf(string, pattern, from, returnEnd) {
+    if (typeof pattern == "string") {
+      var found = string.indexOf(pattern, from);
+      return returnEnd && found > -1 ? found + pattern.length : found;
+    }
+    var m = pattern.exec(from ? string.slice(from) : string);
+    return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
+  }
+
+  return {
+    startState: function() {
+      return {
+        outer: CodeMirror.startState(outer),
+        innerActive: null,
+        inner: null
+      };
+    },
+
+    copyState: function(state) {
+      return {
+        outer: CodeMirror.copyState(outer, state.outer),
+        innerActive: state.innerActive,
+        inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
+      };
+    },
+
+    token: function(stream, state) {
+      if (!state.innerActive) {
+        var cutOff = Infinity, oldContent = stream.string;
+        for (var i = 0; i < others.length; ++i) {
+          var other = others[i];
+          var found = indexOf(oldContent, other.open, stream.pos);
+          if (found == stream.pos) {
+            if (!other.parseDelimiters) stream.match(other.open);
+            state.innerActive = other;
+            state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
+            return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
+          } else if (found != -1 && found < cutOff) {
+            cutOff = found;
+          }
+        }
+        if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
+        var outerToken = outer.token(stream, state.outer);
+        if (cutOff != Infinity) stream.string = oldContent;
+        return outerToken;
+      } else {
+        var curInner = state.innerActive, oldContent = stream.string;
+        if (!curInner.close && stream.sol()) {
+          state.innerActive = state.inner = null;
+          return this.token(stream, state);
+        }
+        var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
+        if (found == stream.pos && !curInner.parseDelimiters) {
+          stream.match(curInner.close);
+          state.innerActive = state.inner = null;
+          return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
+        }
+        if (found > -1) stream.string = oldContent.slice(0, found);
+        var innerToken = curInner.mode.token(stream, state.inner);
+        if (found > -1) stream.string = oldContent;
+
+        if (found == stream.pos && curInner.parseDelimiters)
+          state.innerActive = state.inner = null;
+
+        if (curInner.innerStyle) {
+          if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
+          else innerToken = curInner.innerStyle;
+        }
+
+        return innerToken;
+      }
+    },
+
+    indent: function(state, textAfter) {
+      var mode = state.innerActive ? state.innerActive.mode : outer;
+      if (!mode.indent) return CodeMirror.Pass;
+      return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
+    },
+
+    blankLine: function(state) {
+      var mode = state.innerActive ? state.innerActive.mode : outer;
+      if (mode.blankLine) {
+        mode.blankLine(state.innerActive ? state.inner : state.outer);
+      }
+      if (!state.innerActive) {
+        for (var i = 0; i < others.length; ++i) {
+          var other = others[i];
+          if (other.open === "\n") {
+            state.innerActive = other;
+            state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
+          }
+        }
+      } else if (state.innerActive.close === "\n") {
+        state.innerActive = state.inner = null;
+      }
+    },
+
+    electricChars: outer.electricChars,
+
+    innerMode: function(state) {
+      return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
+    }
+  };
+};
+
+});
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/overlay.js b/third_party/WebKit/Source/devtools/front_end/cm/overlay.js
index 393054df..e1b9ed3 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/overlay.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/overlay.js
@@ -28,7 +28,7 @@
         overlay: CodeMirror.startState(overlay),
         basePos: 0, baseCur: null,
         overlayPos: 0, overlayCur: null,
-        lineSeen: null
+        streamSeen: null
       };
     },
     copyState: function(state) {
@@ -41,9 +41,9 @@
     },
 
     token: function(stream, state) {
-      if (stream.sol() || stream.string != state.lineSeen ||
+      if (stream != state.streamSeen ||
           Math.min(state.basePos, state.overlayPos) < stream.start) {
-        state.lineSeen = stream.string;
+        state.streamSeen = stream;
         state.basePos = state.overlayPos = stream.start;
       }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/cm/simple.js b/third_party/WebKit/Source/devtools/front_end/cm/simple.js
index 795328b..df66336 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm/simple.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm/simple.js
@@ -60,7 +60,7 @@
 
   function ensureState(states, name) {
     if (!states.hasOwnProperty(name))
-      throw new Error("Undefined state " + name + "in simple mode");
+      throw new Error("Undefined state " + name + " in simple mode");
   }
 
   function toRegex(val, caret) {
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/LICENSE b/third_party/WebKit/Source/devtools/front_end/cm_modes/LICENSE
index d21bbea5..7661321 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/LICENSE
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
+Copyright (C) 2016 by Marijn Haverbeke <marijnh@gmail.com> and others
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/clike.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/clike.js
index 3e253624..a37921fd 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/clike.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/clike.js
@@ -11,19 +11,63 @@
 })(function(CodeMirror) {
 "use strict";
 
+function Context(indented, column, type, info, align, prev) {
+  this.indented = indented;
+  this.column = column;
+  this.type = type;
+  this.info = info;
+  this.align = align;
+  this.prev = prev;
+}
+function pushContext(state, col, type, info) {
+  var indent = state.indented;
+  if (state.context && state.context.type != "statement" && type != "statement")
+    indent = state.context.indented;
+  return state.context = new Context(indent, col, type, info, null, state.context);
+}
+function popContext(state) {
+  var t = state.context.type;
+  if (t == ")" || t == "]" || t == "}")
+    state.indented = state.context.indented;
+  return state.context = state.context.prev;
+}
+
+function typeBefore(stream, state, pos) {
+  if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
+  if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
+  if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
+}
+
+function isTopScope(context) {
+  for (;;) {
+    if (!context || context.type == "top") return true;
+    if (context.type == "}" && context.prev.info != "namespace") return false;
+    context = context.prev;
+  }
+}
+
 CodeMirror.defineMode("clike", function(config, parserConfig) {
   var indentUnit = config.indentUnit,
       statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
       dontAlignCalls = parserConfig.dontAlignCalls,
       keywords = parserConfig.keywords || {},
+      types = parserConfig.types || {},
       builtin = parserConfig.builtin || {},
       blockKeywords = parserConfig.blockKeywords || {},
+      defKeywords = parserConfig.defKeywords || {},
       atoms = parserConfig.atoms || {},
       hooks = parserConfig.hooks || {},
-      multiLineStrings = parserConfig.multiLineStrings;
-  var isOperatorChar = /[+\-*&%=<>!?|\/]/;
+      multiLineStrings = parserConfig.multiLineStrings,
+      indentStatements = parserConfig.indentStatements !== false,
+      indentSwitch = parserConfig.indentSwitch !== false,
+      namespaceSeparator = parserConfig.namespaceSeparator,
+      isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
+      numberStart = parserConfig.numberStart || /[\d\.]/,
+      number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
+      isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
+      endStatement = parserConfig.endStatement || /^[;:,]$/;
 
-  var curPunc;
+  var curPunc, isDefKeyword;
 
   function tokenBase(stream, state) {
     var ch = stream.next();
@@ -35,13 +79,14 @@
       state.tokenize = tokenString(ch);
       return state.tokenize(stream, state);
     }
-    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+    if (isPunctuationChar.test(ch)) {
       curPunc = ch;
       return null;
     }
-    if (/\d/.test(ch)) {
-      stream.eatWhile(/[\w\.]/);
-      return "number";
+    if (numberStart.test(ch)) {
+      stream.backUp(1)
+      if (stream.match(number)) return "number"
+      stream.next()
     }
     if (ch == "/") {
       if (stream.eat("*")) {
@@ -54,20 +99,25 @@
       }
     }
     if (isOperatorChar.test(ch)) {
-      stream.eatWhile(isOperatorChar);
+      while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {}
       return "operator";
     }
-    stream.eatWhile(/[\w\$_]/);
+    stream.eatWhile(/[\w\$_\xa1-\uffff]/);
+    if (namespaceSeparator) while (stream.match(namespaceSeparator))
+      stream.eatWhile(/[\w\$_\xa1-\uffff]/);
+
     var cur = stream.current();
-    if (keywords.propertyIsEnumerable(cur)) {
-      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+    if (contains(keywords, cur)) {
+      if (contains(blockKeywords, cur)) curPunc = "newstatement";
+      if (contains(defKeywords, cur)) isDefKeyword = true;
       return "keyword";
     }
-    if (builtin.propertyIsEnumerable(cur)) {
-      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+    if (contains(types, cur)) return "variable-3";
+    if (contains(builtin, cur)) {
+      if (contains(blockKeywords, cur)) curPunc = "newstatement";
       return "builtin";
     }
-    if (atoms.propertyIsEnumerable(cur)) return "atom";
+    if (contains(atoms, cur)) return "atom";
     return "variable";
   }
 
@@ -96,24 +146,9 @@
     return "comment";
   }
 
-  function Context(indented, column, type, align, prev) {
-    this.indented = indented;
-    this.column = column;
-    this.type = type;
-    this.align = align;
-    this.prev = prev;
-  }
-  function pushContext(state, col, type) {
-    var indent = state.indented;
-    if (state.context && state.context.type == "statement")
-      indent = state.context.indented;
-    return state.context = new Context(indent, col, type, null, state.context);
-  }
-  function popContext(state) {
-    var t = state.context.type;
-    if (t == ")" || t == "]" || t == "}")
-      state.indented = state.context.indented;
-    return state.context = state.context.prev;
+  function maybeEOL(stream, state) {
+    if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
+      state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
   }
 
   // Interface
@@ -122,9 +157,10 @@
     startState: function(basecolumn) {
       return {
         tokenize: null,
-        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
+        context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
         indented: 0,
-        startOfLine: true
+        startOfLine: true,
+        prevToken: null
       };
     },
 
@@ -135,13 +171,13 @@
         state.indented = stream.indentation();
         state.startOfLine = true;
       }
-      if (stream.eatSpace()) return null;
-      curPunc = null;
+      if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
+      curPunc = isDefKeyword = null;
       var style = (state.tokenize || tokenBase)(stream, state);
       if (style == "comment" || style == "meta") return style;
       if (ctx.align == null) ctx.align = true;
 
-      if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
+      if (endStatement.test(curPunc)) while (state.context.type == "statement") popContext(state);
       else if (curPunc == "{") pushContext(state, stream.column(), "}");
       else if (curPunc == "[") pushContext(state, stream.column(), "]");
       else if (curPunc == "(") pushContext(state, stream.column(), ")");
@@ -151,24 +187,60 @@
         while (ctx.type == "statement") ctx = popContext(state);
       }
       else if (curPunc == ctx.type) popContext(state);
-      else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
-        pushContext(state, stream.column(), "statement");
+      else if (indentStatements &&
+               (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
+                (ctx.type == "statement" && curPunc == "newstatement"))) {
+        pushContext(state, stream.column(), "statement", stream.current());
+      }
+
+      if (style == "variable" &&
+          ((state.prevToken == "def" ||
+            (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
+             isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
+        style = "def";
+
+      if (hooks.token) {
+        var result = hooks.token(stream, state, style);
+        if (result !== undefined) style = result;
+      }
+
+      if (style == "def" && parserConfig.styleDefs === false) style = "variable";
+
       state.startOfLine = false;
+      state.prevToken = isDefKeyword ? "def" : style || curPunc;
+      maybeEOL(stream, state);
       return style;
     },
 
     indent: function(state, textAfter) {
-      if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
+      if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
       var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
       if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
+      if (parserConfig.dontIndentStatements)
+        while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
+          ctx = ctx.prev
+      if (hooks.indent) {
+        var hook = hooks.indent(state, ctx, textAfter);
+        if (typeof hook == "number") return hook
+      }
       var closing = firstChar == ctx.type;
-      if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
-      else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
-      else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
-      else return ctx.indented + (closing ? 0 : indentUnit);
+      var switchBlock = ctx.prev && ctx.prev.info == "switch";
+      if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
+        while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
+        return ctx.indented
+      }
+      if (ctx.type == "statement")
+        return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
+      if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
+        return ctx.column + (closing ? 0 : 1);
+      if (ctx.type == ")" && !closing)
+        return ctx.indented + statementIndentUnit;
+
+      return ctx.indented + (closing ? 0 : indentUnit) +
+        (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
     },
 
-    electricChars: "{}",
+    electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
     blockCommentStart: "/*",
     blockCommentEnd: "*/",
     lineComment: "//",
@@ -181,26 +253,40 @@
     for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
     return obj;
   }
-  var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
-    "double static else struct entry switch extern typedef float union for unsigned " +
-    "goto while enum void const signed volatile";
+  function contains(words, word) {
+    if (typeof words === "function") {
+      return words(word);
+    } else {
+      return words.propertyIsEnumerable(word);
+    }
+  }
+  var cKeywords = "auto if break case register continue return default do sizeof " +
+    "static else struct switch extern typedef union for goto while enum const volatile";
+  var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
 
   function cppHook(stream, state) {
-    if (!state.startOfLine) return false;
-    for (;;) {
-      if (stream.skipTo("\\")) {
-        stream.next();
-        if (stream.eol()) {
-          state.tokenize = cppHook;
-          break;
-        }
-      } else {
-        stream.skipToEnd();
-        state.tokenize = null;
-        break;
+    if (!state.startOfLine) return false
+    for (var ch, next = null; ch = stream.peek();) {
+      if (ch == "\\" && stream.match(/^.$/)) {
+        next = cppHook
+        break
+      } else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) {
+        break
       }
+      stream.next()
     }
-    return "meta";
+    state.tokenize = next
+    return "meta"
+  }
+
+  function pointerHook(_stream, state) {
+    if (state.prevToken == "variable-3") return "variable-3";
+    return false;
+  }
+
+  function cpp14Literal(stream) {
+    stream.eatWhile(/[\w\.']/);
+    return "number";
   }
 
   function cpp11StringHook(stream, state) {
@@ -227,6 +313,11 @@
     return false;
   }
 
+  function cppLooksLikeConstructor(word) {
+    var lastTwo = /(\w+)::(\w+)$/.exec(word);
+    return lastTwo && lastTwo[1] == lastTwo[2];
+  }
+
   // C#-style strings where "" escapes a quote.
   function tokenAtString(stream, state) {
     var next;
@@ -260,6 +351,7 @@
         words.push(prop);
     }
     add(mode.keywords);
+    add(mode.types);
     add(mode.builtin);
     add(mode.atoms);
     if (words.length) {
@@ -274,39 +366,74 @@
   def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
     name: "clike",
     keywords: words(cKeywords),
+    types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " +
+                 "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " +
+                 "uint32_t uint64_t"),
     blockKeywords: words("case do else for if switch while struct"),
-    atoms: words("null"),
-    hooks: {"#": cppHook},
+    defKeywords: words("struct"),
+    typeFirstDefinitions: true,
+    atoms: words("null true false"),
+    hooks: {"#": cppHook, "*": pointerHook},
     modeProps: {fold: ["brace", "include"]}
   });
 
   def(["text/x-c++src", "text/x-c++hdr"], {
     name: "clike",
-    keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
+    keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
                     "static_cast typeid catch operator template typename class friend private " +
                     "this using const_cast inline public throw virtual delete mutable protected " +
-                    "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
+                    "alignas alignof constexpr decltype nullptr noexcept thread_local final " +
                     "static_assert override"),
+    types: words(cTypes + " bool wchar_t"),
     blockKeywords: words("catch class do else finally for if struct switch try while"),
+    defKeywords: words("class namespace struct enum union"),
+    typeFirstDefinitions: true,
     atoms: words("true false null"),
+    dontIndentStatements: /^template$/,
     hooks: {
       "#": cppHook,
+      "*": pointerHook,
       "u": cpp11StringHook,
       "U": cpp11StringHook,
       "L": cpp11StringHook,
-      "R": cpp11StringHook
+      "R": cpp11StringHook,
+      "0": cpp14Literal,
+      "1": cpp14Literal,
+      "2": cpp14Literal,
+      "3": cpp14Literal,
+      "4": cpp14Literal,
+      "5": cpp14Literal,
+      "6": cpp14Literal,
+      "7": cpp14Literal,
+      "8": cpp14Literal,
+      "9": cpp14Literal,
+      token: function(stream, state, style) {
+        if (style == "variable" && stream.peek() == "(" &&
+            (state.prevToken == ";" || state.prevToken == null ||
+             state.prevToken == "}") &&
+            cppLooksLikeConstructor(stream.current()))
+          return "def";
+      }
     },
+    namespaceSeparator: "::",
     modeProps: {fold: ["brace", "include"]}
   });
+
   def("text/x-java", {
     name: "clike",
-    keywords: words("abstract assert boolean break byte case catch char class const continue default " +
-                    "do double else enum extends final finally float for goto if implements import " +
-                    "instanceof int interface long native new package private protected public " +
-                    "return short static strictfp super switch synchronized this throw throws transient " +
-                    "try void volatile while"),
+    keywords: words("abstract assert break case catch class const continue default " +
+                    "do else enum extends final finally float for goto if implements import " +
+                    "instanceof interface native new package private protected public " +
+                    "return static strictfp super switch synchronized this throw throws transient " +
+                    "try volatile while"),
+    types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
+                 "Integer Long Number Object Short String StringBuffer StringBuilder Void"),
     blockKeywords: words("catch class do else finally for if switch try while"),
+    defKeywords: words("class interface package enum"),
+    typeFirstDefinitions: true,
     atoms: words("true false null"),
+    endStatement: /^[;:]$/,
+    number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
     hooks: {
       "@": function(stream) {
         stream.eatWhile(/[\w\$_]/);
@@ -315,20 +442,23 @@
     },
     modeProps: {fold: ["brace", "import"]}
   });
+
   def("text/x-csharp", {
     name: "clike",
-    keywords: words("abstract as base break case catch checked class const continue" +
+    keywords: words("abstract as async await base break case catch checked class const continue" +
                     " default delegate do else enum event explicit extern finally fixed for" +
                     " foreach goto if implicit in interface internal is lock namespace new" +
                     " operator out override params private protected public readonly ref return sealed" +
                     " sizeof stackalloc static struct switch this throw try typeof unchecked" +
                     " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
                     " global group into join let orderby partial remove select set value var yield"),
+    types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
+                 " Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
+                 " UInt64 bool byte char decimal double short int long object"  +
+                 " sbyte float string ushort uint ulong"),
     blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
-    builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
-                    " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
-                    " UInt64 bool byte char decimal double short int long object"  +
-                    " sbyte float string ushort uint ulong"),
+    defKeywords: words("class interface namespace struct var"),
+    typeFirstDefinitions: true,
     atoms: words("true false null"),
     hooks: {
       "@": function(stream, state) {
@@ -341,58 +471,149 @@
       }
     }
   });
+
+  function tokenTripleString(stream, state) {
+    var escaped = false;
+    while (!stream.eol()) {
+      if (!escaped && stream.match('"""')) {
+        state.tokenize = null;
+        break;
+      }
+      escaped = stream.next() == "\\" && !escaped;
+    }
+    return "string";
+  }
+
   def("text/x-scala", {
     name: "clike",
     keywords: words(
 
       /* scala */
-      "abstract case catch class def do else extends false final finally for forSome if " +
+      "abstract case catch class def do else extends final finally for forSome if " +
       "implicit import lazy match new null object override package private protected return " +
-      "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
+      "sealed super this throw trait try type val var while with yield _ : = => <- <: " +
       "<% >: # @ " +
 
       /* package scala */
       "assert assume require print println printf readLine readBoolean readByte readShort " +
       "readChar readInt readLong readFloat readDouble " +
 
+      ":: #:: "
+    ),
+    types: words(
       "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
-      "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
+      "Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " +
       "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
       "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
-      "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
+      "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
 
       /* package java.lang */
       "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
       "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
       "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
       "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
-
-
     ),
+    multiLineStrings: true,
     blockKeywords: words("catch class do else finally for forSome if match switch try while"),
+    defKeywords: words("class def object package trait type val var"),
     atoms: words("true false null"),
+    indentStatements: false,
+    indentSwitch: false,
     hooks: {
       "@": function(stream) {
         stream.eatWhile(/[\w\$_]/);
         return "meta";
+      },
+      '"': function(stream, state) {
+        if (!stream.match('""')) return false;
+        state.tokenize = tokenTripleString;
+        return state.tokenize(stream, state);
+      },
+      "'": function(stream) {
+        stream.eatWhile(/[\w\$_\xa1-\uffff]/);
+        return "atom";
+      },
+      "=": function(stream, state) {
+        var cx = state.context
+        if (cx.type == "}" && cx.align && stream.eat(">")) {
+          state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
+          return "operator"
+        } else {
+          return false
+        }
       }
-    }
+    },
+    modeProps: {closeBrackets: {triples: '"'}}
   });
+
+  function tokenKotlinString(tripleString){
+    return function (stream, state) {
+      var escaped = false, next, end = false;
+      while (!stream.eol()) {
+        if (!tripleString && !escaped && stream.match('"') ) {end = true; break;}
+        if (tripleString && stream.match('"""')) {end = true; break;}
+        next = stream.next();
+        if(!escaped && next == "$" && stream.match('{'))
+          stream.skipTo("}");
+        escaped = !escaped && next == "\\" && !tripleString;
+      }
+      if (end || !tripleString)
+        state.tokenize = null;
+      return "string";
+    }
+  }
+
+  def("text/x-kotlin", {
+    name: "clike",
+    keywords: words(
+      /*keywords*/
+      "package as typealias class interface this super val " +
+      "var fun for is in This throw return " +
+      "break continue object if else while do try when !in !is as? " +
+
+      /*soft keywords*/
+      "file import where by get set abstract enum open inner override private public internal " +
+      "protected catch finally out final vararg reified dynamic companion constructor init " +
+      "sealed field property receiver param sparam lateinit data inline noinline tailrec " +
+      "external annotation crossinline const operator infix"
+    ),
+    types: words(
+      /* package java.lang */
+      "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
+      "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
+      "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
+      "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
+    ),
+    intendSwitch: false,
+    indentStatements: false,
+    multiLineStrings: true,
+    blockKeywords: words("catch class do else finally for if where try while enum"),
+    defKeywords: words("class val var object package interface fun"),
+    atoms: words("true false null this"),
+    hooks: {
+      '"': function(stream, state) {
+        state.tokenize = tokenKotlinString(stream.match('""'));
+        return state.tokenize(stream, state);
+      }
+    },
+    modeProps: {closeBrackets: {triples: '"'}}
+  });
+
   def(["x-shader/x-vertex", "x-shader/x-fragment"], {
     name: "clike",
-    keywords: words("float int bool void " +
-                    "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
-                    "mat2 mat3 mat4 " +
-                    "sampler1D sampler2D sampler3D samplerCube " +
-                    "sampler1DShadow sampler2DShadow" +
+    keywords: words("sampler1D sampler2D sampler3D samplerCube " +
+                    "sampler1DShadow sampler2DShadow " +
                     "const attribute uniform varying " +
                     "break continue discard return " +
                     "for while do if else struct " +
                     "in out inout"),
+    types: words("float int bool void " +
+                 "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
+                 "mat2 mat3 mat4"),
     blockKeywords: words("for while do if else struct"),
     builtin: words("radians degrees sin cos tan asin acos atan " +
                     "pow exp log exp2 sqrt inversesqrt " +
-                    "abs sign floor ceil fract mod min max clamp mix step smootstep " +
+                    "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
                     "length distance dot cross normalize ftransform faceforward " +
                     "reflect refract matrixCompMult " +
                     "lessThan lessThanEqual greaterThan greaterThanEqual " +
@@ -409,12 +630,12 @@
                 "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
                 "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
                 "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
-                "gl_FogCoord " +
+                "gl_FogCoord gl_PointCoord " +
                 "gl_Position gl_PointSize gl_ClipVertex " +
                 "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
                 "gl_TexCoord gl_FogFragCoord " +
                 "gl_FragCoord gl_FrontFacing " +
-                "gl_FragColor gl_FragData gl_FragDepth " +
+                "gl_FragData gl_FragDepth " +
                 "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
                 "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
                 "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
@@ -432,8 +653,134 @@
                 "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
                 "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
                 "gl_MaxDrawBuffers"),
+    indentSwitch: false,
     hooks: {"#": cppHook},
     modeProps: {fold: ["brace", "include"]}
   });
 
+  def("text/x-nesc", {
+    name: "clike",
+    keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
+                    "implementation includes interface module new norace nx_struct nx_union post provides " +
+                    "signal task uses abstract extends"),
+    types: words(cTypes),
+    blockKeywords: words("case do else for if switch while struct"),
+    atoms: words("null true false"),
+    hooks: {"#": cppHook},
+    modeProps: {fold: ["brace", "include"]}
+  });
+
+  def("text/x-objectivec", {
+    name: "clike",
+    keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " +
+                    "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
+    types: words(cTypes),
+    atoms: words("YES NO NULL NILL ON OFF true false"),
+    hooks: {
+      "@": function(stream) {
+        stream.eatWhile(/[\w\$]/);
+        return "keyword";
+      },
+      "#": cppHook,
+      indent: function(_state, ctx, textAfter) {
+        if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
+      }
+    },
+    modeProps: {fold: "brace"}
+  });
+
+  def("text/x-squirrel", {
+    name: "clike",
+    keywords: words("base break clone continue const default delete enum extends function in class" +
+                    " foreach local resume return this throw typeof yield constructor instanceof static"),
+    types: words(cTypes),
+    blockKeywords: words("case catch class else for foreach if switch try while"),
+    defKeywords: words("function local class"),
+    typeFirstDefinitions: true,
+    atoms: words("true false null"),
+    hooks: {"#": cppHook},
+    modeProps: {fold: ["brace", "include"]}
+  });
+
+  // Ceylon Strings need to deal with interpolation
+  var stringTokenizer = null;
+  function tokenCeylonString(type) {
+    return function(stream, state) {
+      var escaped = false, next, end = false;
+      while (!stream.eol()) {
+        if (!escaped && stream.match('"') &&
+              (type == "single" || stream.match('""'))) {
+          end = true;
+          break;
+        }
+        if (!escaped && stream.match('``')) {
+          stringTokenizer = tokenCeylonString(type);
+          end = true;
+          break;
+        }
+        next = stream.next();
+        escaped = type == "single" && !escaped && next == "\\";
+      }
+      if (end)
+          state.tokenize = null;
+      return "string";
+    }
+  }
+
+  def("text/x-ceylon", {
+    name: "clike",
+    keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
+                    " exists extends finally for function given if import in interface is let module new" +
+                    " nonempty object of out outer package return satisfies super switch then this throw" +
+                    " try value void while"),
+    types: function(word) {
+        // In Ceylon all identifiers that start with an uppercase are types
+        var first = word.charAt(0);
+        return (first === first.toUpperCase() && first !== first.toLowerCase());
+    },
+    blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
+    defKeywords: words("class dynamic function interface module object package value"),
+    builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
+                   " native optional sealed see serializable shared suppressWarnings tagged throws variable"),
+    isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
+    isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
+    numberStart: /[\d#$]/,
+    number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,
+    multiLineStrings: true,
+    typeFirstDefinitions: true,
+    atoms: words("true false null larger smaller equal empty finished"),
+    indentSwitch: false,
+    styleDefs: false,
+    hooks: {
+      "@": function(stream) {
+        stream.eatWhile(/[\w\$_]/);
+        return "meta";
+      },
+      '"': function(stream, state) {
+          state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
+          return state.tokenize(stream, state);
+        },
+      '`': function(stream, state) {
+          if (!stringTokenizer || !stream.match('`')) return false;
+          state.tokenize = stringTokenizer;
+          stringTokenizer = null;
+          return state.tokenize(stream, state);
+        },
+      "'": function(stream) {
+        stream.eatWhile(/[\w\$_\xa1-\uffff]/);
+        return "atom";
+      },
+      token: function(_stream, state, style) {
+          if ((style == "variable" || style == "variable-3") &&
+              state.prevToken == ".") {
+            return "variable-2";
+          }
+        }
+    },
+    modeProps: {
+        fold: ["brace", "import"],
+        closeBrackets: {triples: '"'}
+    }
+  });
+
 });
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/clojure.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/clojure.js
index d531022a2..ed6af2c 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/clojure.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/clojure.js
@@ -31,14 +31,70 @@
     var atoms = makeKeywords("true false nil");
 
     var keywords = makeKeywords(
-      "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
+      "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest " +
+      "slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn " +
+      "do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync " +
+      "doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars " +
+      "binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
 
     var builtins = makeKeywords(
-        "* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> ->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? declare default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int rand-nth range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap *default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! set-agent-send-off-executor! some-> some->>");
+        "* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* " +
+        "*compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* " +
+        "*math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* " +
+        "*source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> " +
+        "->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor " +
+        "aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! " +
+        "alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double " +
+        "aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 " +
+        "bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set " +
+        "bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast " +
+        "byte byte-array bytes case cat cast char char-array char-escape-string char-name-string char? chars chunk chunk-append " +
+        "chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors " +
+        "clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement completing concat cond condp " +
+        "conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? " +
+        "declare dedupe default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol " +
+        "defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc " +
+        "dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last " +
+        "drop-while eduction empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info " +
+        "extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword " +
+        "find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? " +
+        "fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? " +
+        "gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash " +
+        "hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? " +
+        "int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep " +
+        "keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file " +
+        "load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array " +
+        "make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods " +
+        "min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty " +
+        "not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias " +
+        "ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all " +
+        "partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers " +
+        "primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str " +
+        "prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues " +
+        "quot rand rand-int rand-nth random-sample range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern " +
+        "re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history " +
+        "ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods " +
+        "remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest " +
+        "restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? " +
+        "seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts " +
+        "shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? " +
+        "special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol " +
+        "symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transduce " +
+        "transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec " +
+        "unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int " +
+        "unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int "+
+        "unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote " +
+        "unquote-splicing update update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of " +
+        "vector? volatile! volatile? vreset! vswap! when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context " +
+        "with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap " +
+        "*default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! " +
+        "set-agent-send-off-executor! some-> some->>");
 
     var indentKeys = makeKeywords(
         // Built-ins
-        "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch " +
+        "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto " +
+        "locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type " +
+        "try catch " +
 
         // Binding forms
         "let letfn binding loop for doseq dotimes when-let if-let " +
@@ -59,7 +115,8 @@
         sign: /[+-]/,
         exponent: /e/i,
         keyword_char: /[^\s\(\[\;\)\]]/,
-        symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/
+        symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/,
+        block_indent: /^(?:def|with)[^\/]+$|\/(?:def|with)/
     };
 
     function stateStack(indent, type, prev) { // represents a state stack object
@@ -96,6 +153,9 @@
             if ( '.' == stream.peek() ) {
                 stream.eat('.');
                 stream.eatWhile(tests.digit);
+            } else if ('/' == stream.peek() ) {
+                stream.eat('/');
+                stream.eatWhile(tests.digit);
             }
 
             if ( stream.eat(tests.exponent) ) {
@@ -139,7 +199,7 @@
             }
 
             // skip spaces
-            if (stream.eatSpace()) {
+            if (state.mode != "string" && stream.eatSpace()) {
                 return null;
             }
             var returnType = null;
@@ -187,7 +247,7 @@
                         }
 
                         if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||
-                                                   /^(?:def|with)/.test(keyWord))) { // indent-word
+                                                   tests.block_indent.test(keyWord))) { // indent-word
                             pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
                         } else { // non-indent word
                             // we continue eating the spaces
@@ -240,5 +300,7 @@
 });
 
 CodeMirror.defineMIME("text/x-clojure", "clojure");
+CodeMirror.defineMIME("text/x-clojurescript", "clojure");
+CodeMirror.defineMIME("application/edn", "clojure");
 
 });
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/coffeescript.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/coffeescript.js
index 1695650..adf2184 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/coffeescript.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/coffeescript.js
@@ -15,17 +15,17 @@
 })(function(CodeMirror) {
 "use strict";
 
-CodeMirror.defineMode("coffeescript", function(conf) {
+CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
   var ERRORCLASS = "error";
 
   function wordRegexp(words) {
     return new RegExp("^((" + words.join(")|(") + "))\\b");
   }
 
-  var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?)/;
+  var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
   var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
   var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
-  var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
+  var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/;
 
   var wordOperators = wordRegexp(["and", "or", "not",
                                   "is", "isnt", "in",
@@ -34,7 +34,7 @@
                         "switch", "try", "catch", "finally", "class"];
   var commonKeywords = ["break", "by", "continue", "debugger", "delete",
                         "do", "in", "of", "new", "return", "then",
-                        "this", "throw", "when", "until"];
+                        "this", "@", "throw", "when", "until", "extends"];
 
   var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
 
@@ -145,6 +145,8 @@
       }
     }
 
+
+
     // Handle operators and delimiters
     if (stream.match(operators) || stream.match(wordOperators)) {
       return "operator";
@@ -157,6 +159,10 @@
       return "atom";
     }
 
+    if (stream.match(atProp) || state.prop && stream.match(identifiers)) {
+      return "property";
+    }
+
     if (stream.match(keywords)) {
       return "keyword";
     }
@@ -165,10 +171,6 @@
       return "variable";
     }
 
-    if (stream.match(properties)) {
-      return "property";
-    }
-
     // Handle non-detected items
     stream.next();
     return ERRORCLASS;
@@ -191,7 +193,7 @@
         }
       }
       if (singleline) {
-        if (conf.mode.singleLineStringErrors) {
+        if (parserConf.singleLineStringErrors) {
           outclass = ERRORCLASS;
         } else {
           state.tokenize = tokenBase;
@@ -217,7 +219,7 @@
     type = type || "coffee";
     var offset = 0, align = false, alignOffset = null;
     for (var scope = state.scope; scope; scope = scope.prev) {
-      if (scope.type === "coffee") {
+      if (scope.type === "coffee" || scope.type == "}") {
         offset = scope.offset + conf.indentUnit;
         break;
       }
@@ -265,24 +267,11 @@
     var style = state.tokenize(stream, state);
     var current = stream.current();
 
-    // Handle "." connected identifiers
-    if (current === ".") {
-      style = state.tokenize(stream, state);
-      current = stream.current();
-      if (/^\.[\w$]+$/.test(current)) {
-        return "variable";
-      } else {
-        return ERRORCLASS;
-      }
-    }
-
     // Handle scope changes.
     if (current === "return") {
-      state.dedent += 1;
+      state.dedent = true;
     }
-    if (((current === "->" || current === "=>") &&
-         !state.lambda &&
-         !stream.peek())
+    if (((current === "->" || current === "=>") && stream.eol())
         || style === "indent") {
       indent(stream, state);
     }
@@ -310,9 +299,10 @@
       if (state.scope.type == current)
         state.scope = state.scope.prev;
     }
-    if (state.dedent > 0 && stream.eol() && state.scope.type == "coffee") {
-      if (state.scope.prev) state.scope = state.scope.prev;
-      state.dedent -= 1;
+    if (state.dedent && stream.eol()) {
+      if (state.scope.type == "coffee" && state.scope.prev)
+        state.scope = state.scope.prev;
+      state.dedent = false;
     }
 
     return style;
@@ -323,8 +313,7 @@
       return {
         tokenize: tokenBase,
         scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
-        lastToken: null,
-        lambda: false,
+        prop: false,
         dedent: 0
       };
     },
@@ -334,12 +323,9 @@
       if (fillAlign && stream.sol()) fillAlign.align = false;
 
       var style = tokenLexer(stream, state);
-      if (fillAlign && style && style != "comment") fillAlign.align = true;
-
-      state.lastToken = {style:style, content: stream.current()};
-
-      if (stream.eol() && stream.lambda) {
-        state.lambda = false;
+      if (style && style != "comment") {
+        if (fillAlign) fillAlign.align = true;
+        state.prop = style == "punctuation" && stream.current() == "."
       }
 
       return style;
@@ -364,5 +350,6 @@
 });
 
 CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
+CodeMirror.defineMIME("text/coffeescript", "coffeescript");
 
 });
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js
index c3d227a..aff01b8 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/jsx.js
@@ -11,75 +11,137 @@
 })(function(CodeMirror) {
   "use strict"
 
-  function copyContext(context) {
-    return {state: CodeMirror.copyState(context.mode, context.state),
-            mode: context.mode,
-            depth: context.depth,
-            prev: context.prev && copyContext(context.prev)}
+  // Depth means the amount of open braces in JS context, in XML
+  // context 0 means not in tag, 1 means in tag, and 2 means in tag
+  // and js block comment.
+  function Context(state, mode, depth, prev) {
+    this.state = state; this.mode = mode; this.depth = depth; this.prev = prev
   }
 
-  CodeMirror.defineMode("jsx", function(config) {
-    var xmlMode = CodeMirror.getMode(config, "xml")
-    var jsMode = CodeMirror.getMode(config, "javascript")
+  function copyContext(context) {
+    return new Context(CodeMirror.copyState(context.mode, context.state),
+                       context.mode,
+                       context.depth,
+                       context.prev && copyContext(context.prev))
+  }
+
+  CodeMirror.defineMode("jsx", function(config, modeConfig) {
+    var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true, multilineTagIndentPastTag: false})
+    var jsMode = CodeMirror.getMode(config, modeConfig && modeConfig.base || "javascript")
+
+    function flatXMLIndent(state) {
+      var tagName = state.tagName
+      state.tagName = null
+      var result = xmlMode.indent(state, "")
+      state.tagName = tagName
+      return result
+    }
+
+    function token(stream, state) {
+      if (state.context.mode == xmlMode)
+        return xmlToken(stream, state, state.context)
+      else
+        return jsToken(stream, state, state.context)
+    }
+
+    function xmlToken(stream, state, cx) {
+      if (cx.depth == 2) { // Inside a JS /* */ comment
+        if (stream.match(/^.*?\*\//)) cx.depth = 1
+        else stream.skipToEnd()
+        return "comment"
+      }
+
+      if (stream.peek() == "{") {
+        xmlMode.skipAttribute(cx.state)
+
+        var indent = flatXMLIndent(cx.state), xmlContext = cx.state.context
+        // If JS starts on same line as tag
+        if (xmlContext && stream.match(/^[^>]*>\s*$/, false)) {
+          while (xmlContext.prev && !xmlContext.startOfLine)
+            xmlContext = xmlContext.prev
+          // If tag starts the line, use XML indentation level
+          if (xmlContext.startOfLine) indent -= config.indentUnit
+          // Else use JS indentation level
+          else if (cx.prev.state.lexical) indent = cx.prev.state.lexical.indented
+        // Else if inside of tag
+        } else if (cx.depth == 1) {
+          indent += config.indentUnit
+        }
+
+        state.context = new Context(CodeMirror.startState(jsMode, indent),
+                                    jsMode, 0, state.context)
+        return null
+      }
+
+      if (cx.depth == 1) { // Inside of tag
+        if (stream.peek() == "<") { // Tag inside of tag
+          xmlMode.skipAttribute(cx.state)
+          state.context = new Context(CodeMirror.startState(xmlMode, flatXMLIndent(cx.state)),
+                                      xmlMode, 0, state.context)
+          return null
+        } else if (stream.match("//")) {
+          stream.skipToEnd()
+          return "comment"
+        } else if (stream.match("/*")) {
+          cx.depth = 2
+          return token(stream, state)
+        }
+      }
+
+      var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop
+      if (/\btag\b/.test(style)) {
+        if (/>$/.test(cur)) {
+          if (cx.state.context) cx.depth = 0
+          else state.context = state.context.prev
+        } else if (/^</.test(cur)) {
+          cx.depth = 1
+        }
+      } else if (!style && (stop = cur.indexOf("{")) > -1) {
+        stream.backUp(cur.length - stop)
+      }
+      return style
+    }
+
+    function jsToken(stream, state, cx) {
+      if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) {
+        jsMode.skipExpression(cx.state)
+        state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")),
+                                    xmlMode, 0, state.context)
+        return null
+      }
+
+      var style = jsMode.token(stream, cx.state)
+      if (!style && cx.depth != null) {
+        var cur = stream.current()
+        if (cur == "{") {
+          cx.depth++
+        } else if (cur == "}") {
+          if (--cx.depth == 0) state.context = state.context.prev
+        }
+      }
+      return style
+    }
 
     return {
       startState: function() {
-        return {context: {state: CodeMirror.startState(jsMode), mode: jsMode}}
+        return {context: new Context(CodeMirror.startState(jsMode), jsMode)}
       },
 
       copyState: function(state) {
         return {context: copyContext(state.context)}
       },
 
-      token: function(stream, state) {
-        var cx = state.context
-        if (cx.mode == xmlMode) {
-          if (stream.peek() == "{") {
-            xmlMode.skipAttribute(cx.state)
-            state.context = {state: CodeMirror.startState(jsMode, xmlMode.indent(cx.state, "")),
-                             mode: jsMode,
-                             depth: 1,
-                             prev: state.context}
-            return jsMode.token(stream, state.context.state)
-          } else { // FIXME skip attribute
-            var style = xmlMode.token(stream, cx.state), cur, brace
-            if (/\btag\b/.test(style) && !cx.state.context && /^\/?>$/.test(stream.current()))
-              state.context = state.context.prev
-            else if (!style && (brace = (cur = stream.current()).indexOf("{")) > -1)
-              stream.backUp(cur.length - brace)
-            return style
-          }
-        } else { // jsMode
-          if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) {
-            jsMode.skipExpression(cx.state)
-            state.context = {state: CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")),
-                             mode: xmlMode,
-                             prev: state.context}
-            return xmlMode.token(stream, state.context.state)
-          } else {
-            var style = jsMode.token(stream, cx.state)
-            if (!style && cx.depth != null) {
-              var cur = stream.current()
-              if (cur == "{") {
-                cx.depth++
-              } else if (cur == "}") {
-                if (--cx.depth == 0) state.context = state.context.prev
-              }
-            }
-            return style
-          }
-        }
-      },
+      token: token,
 
       indent: function(state, textAfter, fullLine) {
         return state.context.mode.indent(state.context.state, textAfter, fullLine)
       },
 
       innerMode: function(state) {
-        return state.context[state.context.length - 1]
+        return state.context
       }
     }
   }, "xml", "javascript")
 
   CodeMirror.defineMIME("text/jsx", "jsx")
-})
+});
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/php.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/php.js
index 72c19d8d..57ba812 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/php.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/php.js
@@ -16,40 +16,32 @@
     for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
     return obj;
   }
-  function heredoc(delim) {
-    return function(stream, state) {
-      if (stream.match(delim)) state.tokenize = null;
-      else stream.skipToEnd();
-      return "string";
-    };
-  }
 
-  // Helper for stringWithEscapes
-  function matchSequence(list) {
-    if (list.length == 0) return stringWithEscapes;
+  // Helper for phpString
+  function matchSequence(list, end, escapes) {
+    if (list.length == 0) return phpString(end);
     return function (stream, state) {
       var patterns = list[0];
       for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {
-        state.tokenize = matchSequence(list.slice(1));
+        state.tokenize = matchSequence(list.slice(1), end);
         return patterns[i][1];
       }
-      state.tokenize = stringWithEscapes;
+      state.tokenize = phpString(end, escapes);
       return "string";
     };
   }
-  function stringWithEscapes(stream, state) {
-    var escaped = false, next, end = false;
-
-    if (stream.current() == '"') return "string";
-
+  function phpString(closing, escapes) {
+    return function(stream, state) { return phpString_(stream, state, closing, escapes); };
+  }
+  function phpString_(stream, state, closing, escapes) {
     // "Complex" syntax
-    if (stream.match("${", false) || stream.match("{$", false)) {
+    if (escapes !== false && stream.match("${", false) || stream.match("{$", false)) {
       state.tokenize = null;
       return "string";
     }
 
     // Simple syntax
-    if (stream.match(/\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
+    if (escapes !== false && stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
       // After the variable name there may appear array or object operator.
       if (stream.match("[", false)) {
         // Match array operator
@@ -59,31 +51,30 @@
            [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"],
            [/[\w\$]+/, "variable"]],
           [["]", null]]
-        ]);
+        ], closing, escapes);
       }
       if (stream.match(/\-\>\w/, false)) {
         // Match object operator
         state.tokenize = matchSequence([
           [["->", null]],
           [[/[\w]+/, "variable"]]
-        ]);
+        ], closing, escapes);
       }
       return "variable-2";
     }
 
+    var escaped = false;
     // Normal string
-    while (
-      !stream.eol() &&
-      (!stream.match("{$", false)) &&
-      (!stream.match(/(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false) || escaped)
-    ) {
-      next = stream.next();
-      if (!escaped && next == '"') { end = true; break; }
-      escaped = !escaped && next == "\\";
-    }
-    if (end) {
-      state.tokenize = null;
-      state.phpEncapsStack.pop();
+    while (!stream.eol() &&
+           (escaped || escapes === false ||
+            (!stream.match("{$", false) &&
+             !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) {
+      if (!escaped && stream.match(closing)) {
+        state.tokenize = null;
+        state.tokStack.pop(); state.tokStack.pop();
+        break;
+      }
+      escaped = stream.next() == "\\" && !escaped;
     }
     return "string";
   }
@@ -95,15 +86,16 @@
     "die echo empty exit eval include include_once isset list require require_once return " +
     "print unset __halt_compiler self static parent yield insteadof finally";
   var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";
-  var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once";
+  var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents file_put_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists array_intersect_key array_combine array_column pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
   CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));
-  CodeMirror.registerHelper("wordChars", "php", /[\\w$]/);
+  CodeMirror.registerHelper("wordChars", "php", /[\w$]/);
 
   var phpConfig = {
     name: "clike",
     helperType: "php",
     keywords: keywords(phpKeywords),
     blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"),
+    defKeywords: keywords("class function interface namespace trait"),
     atoms: keywords(phpAtoms),
     builtin: keywords(phpBuiltin),
     multiLineStrings: true,
@@ -113,10 +105,17 @@
         return "variable-2";
       },
       "<": function(stream, state) {
-        if (stream.match(/<</)) {
+        var before;
+        if (before = stream.match(/<<\s*/)) {
+          var quoted = stream.eat(/['"]/);
           stream.eatWhile(/[\w\.]/);
-          state.tokenize = heredoc(stream.current().slice(3));
-          return state.tokenize(stream, state);
+          var delim = stream.current().slice(before[0].length + (quoted ? 2 : 1));
+          if (quoted) stream.eat(quoted);
+          if (delim) {
+            (state.tokStack || (state.tokStack = [])).push(delim, 0);
+            state.tokenize = phpString(delim, quoted != "'");
+            return "string";
+          }
         }
         return false;
       },
@@ -131,22 +130,21 @@
         }
         return false;
       },
-      '"': function(stream, state) {
-        if (!state.phpEncapsStack)
-          state.phpEncapsStack = [];
-        state.phpEncapsStack.push(0);
-        state.tokenize = stringWithEscapes;
-        return state.tokenize(stream, state);
+      '"': function(_stream, state) {
+        (state.tokStack || (state.tokStack = [])).push('"', 0);
+        state.tokenize = phpString('"');
+        return "string";
       },
       "{": function(_stream, state) {
-        if (state.phpEncapsStack && state.phpEncapsStack.length > 0)
-          state.phpEncapsStack[state.phpEncapsStack.length - 1]++;
+        if (state.tokStack && state.tokStack.length)
+          state.tokStack[state.tokStack.length - 1]++;
         return false;
       },
       "}": function(_stream, state) {
-        if (state.phpEncapsStack && state.phpEncapsStack.length > 0)
-          if (--state.phpEncapsStack[state.phpEncapsStack.length - 1] == 0)
-            state.tokenize = stringWithEscapes;
+        if (state.tokStack && state.tokStack.length > 0 &&
+            !--state.tokStack[state.tokStack.length - 1]) {
+          state.tokenize = phpString(state.tokStack[state.tokStack.length - 2]);
+        }
         return false;
       }
     }
@@ -162,6 +160,7 @@
       if (!isPHP) {
         if (stream.match(/^<\?\w*/)) {
           state.curMode = phpMode;
+          if (!state.php) state.php = CodeMirror.startState(phpMode, htmlMode.indent(state.html, ""))
           state.curState = state.php;
           return "meta";
         }
@@ -185,6 +184,7 @@
       } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
         state.curMode = htmlMode;
         state.curState = state.html;
+        if (!state.php.context.prev) state.php = null;
         return "meta";
       } else {
         return phpMode.token(stream, state.curState);
@@ -193,7 +193,8 @@
 
     return {
       startState: function() {
-        var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
+        var html = CodeMirror.startState(htmlMode)
+        var php = parserConfig.startOpen ? CodeMirror.startState(phpMode) : null
         return {html: html,
                 php: php,
                 curMode: parserConfig.startOpen ? phpMode : htmlMode,
@@ -203,7 +204,7 @@
 
       copyState: function(state) {
         var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
-            php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
+            php = state.php, phpNew = php && CodeMirror.copyState(phpMode, php), cur;
         if (state.curMode == htmlMode) cur = htmlNew;
         else cur = phpNew;
         return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
index 45dd63b..be65ad76 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/python.js
@@ -15,12 +15,12 @@
     return new RegExp("^((" + words.join(")|(") + "))\\b");
   }
 
-  var wordOperators = wordRegexp(["and", "or", "not", "is", "in"]);
+  var wordOperators = wordRegexp(["and", "or", "not", "is"]);
   var commonKeywords = ["as", "assert", "break", "class", "continue",
                         "def", "del", "elif", "else", "except", "finally",
                         "for", "from", "global", "if", "import",
                         "lambda", "pass", "raise", "return",
-                        "try", "while", "with", "yield"];
+                        "try", "while", "with", "yield", "in"];
   var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
                         "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
                         "enumerate", "eval", "filter", "float", "format", "frozenset",
@@ -32,13 +32,6 @@
                         "sorted", "staticmethod", "str", "sum", "super", "tuple",
                         "type", "vars", "zip", "__import__", "NotImplemented",
                         "Ellipsis", "__debug__"];
-  var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
-                        "file", "intern", "long", "raw_input", "reduce", "reload",
-                        "unichr", "unicode", "xrange", "False", "True", "None"],
-             keywords: ["exec", "print"]};
-  var py3 = {builtins: ["ascii", "bytes", "exec", "print"],
-             keywords: ["nonlocal", "False", "True", "None"]};
-
   CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
 
   function top(state) {
@@ -48,28 +41,35 @@
   CodeMirror.defineMode("python", function(conf, parserConf) {
     var ERRORCLASS = "error";
 
-    var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
-    var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
-    var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
-    var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
-    var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
-    var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
+    var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/;
+    var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/;
+    var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/;
+    var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/;
+
     var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
 
     var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
-    if(parserConf.extra_keywords != undefined){
+    if (parserConf.extra_keywords != undefined)
       myKeywords = myKeywords.concat(parserConf.extra_keywords);
-    }
-    if(parserConf.extra_builtins != undefined){
+
+    if (parserConf.extra_builtins != undefined)
       myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
-    }
-    if (parserConf.version && parseInt(parserConf.version, 10) == 3) {
-      myKeywords = myKeywords.concat(py3.keywords);
-      myBuiltins = myBuiltins.concat(py3.builtins);
-      var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
+
+    var py3 = parserConf.version && parseInt(parserConf.version, 10) == 3
+    if (py3) {
+      // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
+      var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/;
+      var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
+      myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
+      myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
+      var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i");
     } else {
-      myKeywords = myKeywords.concat(py2.keywords);
-      myBuiltins = myBuiltins.concat(py2.builtins);
+      var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
+      var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
+      myKeywords = myKeywords.concat(["exec", "print"]);
+      myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
+                                      "file", "intern", "long", "raw_input", "reduce", "reload",
+                                      "unichr", "unicode", "xrange", "False", "True", "None"]);
       var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
     }
     var keywords = wordRegexp(myKeywords);
@@ -77,13 +77,14 @@
 
     // tokenizers
     function tokenBase(stream, state) {
+      if (stream.sol()) state.indent = stream.indentation()
       // Handle scope changes
       if (stream.sol() && top(state).type == "py") {
         var scopeOffset = top(state).offset;
         if (stream.eatSpace()) {
           var lineOffset = stream.indentation();
           if (lineOffset > scopeOffset)
-            pushScope(stream, state, "py");
+            pushPyScope(state);
           else if (lineOffset < scopeOffset && dedent(stream, state))
             state.errorToken = true;
           return null;
@@ -152,17 +153,18 @@
 
       // Handle operators and Delimiters
       if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))
-        return null;
+        return "punctuation";
 
-      if (stream.match(doubleOperators)
-          || stream.match(singleOperators)
-          || stream.match(wordOperators))
+      if (stream.match(doubleOperators) || stream.match(singleOperators))
         return "operator";
 
       if (stream.match(singleDelimiters))
-        return null;
+        return "punctuation";
 
-      if (stream.match(keywords))
+      if (state.lastToken == "." && stream.match(identifiers))
+        return "property";
+
+      if (stream.match(keywords) || stream.match(wordOperators))
         return "keyword";
 
       if (stream.match(builtins))
@@ -215,21 +217,23 @@
       return tokenString;
     }
 
-    function pushScope(stream, state, type) {
-      var offset = 0, align = null;
-      if (type == "py") {
-        while (top(state).type != "py")
-          state.scopes.pop();
-      }
-      offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent);
-      if (type != "py" && !stream.match(/^(\s|#.*)*$/, false))
-        align = stream.column() + 1;
-      state.scopes.push({offset: offset, type: type, align: align});
+    function pushPyScope(state) {
+      while (top(state).type != "py") state.scopes.pop()
+      state.scopes.push({offset: top(state).offset + conf.indentUnit,
+                         type: "py",
+                         align: null})
+    }
+
+    function pushBracketScope(stream, state, type) {
+      var align = stream.match(/^([\s\[\{\(]|#.*)*$/, false) ? null : stream.column() + 1
+      state.scopes.push({offset: state.indent + hangingIndent,
+                         type: type,
+                         align: align})
     }
 
     function dedent(stream, state) {
       var indented = stream.indentation();
-      while (top(state).offset > indented) {
+      while (state.scopes.length > 1 && top(state).offset > indented) {
         if (top(state).type != "py") return true;
         state.scopes.pop();
       }
@@ -237,26 +241,19 @@
     }
 
     function tokenLexer(stream, state) {
+      if (stream.sol()) state.beginningOfLine = true;
+
       var style = state.tokenize(stream, state);
       var current = stream.current();
 
-      // Handle '.' connected identifiers
-      if (current == ".") {
-        style = stream.match(identifiers, false) ? null : ERRORCLASS;
-        if (style == null && state.lastStyle == "meta") {
-          // Apply 'meta' style to '.' connected identifiers when
-          // appropriate.
-          style = "meta";
-        }
-        return style;
-      }
-
       // Handle decorators
-      if (current == "@")
-        return stream.match(identifiers, false) ? "meta" : ERRORCLASS;
+      if (state.beginningOfLine && current == "@")
+        return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS;
+
+      if (/\S/.test(current)) state.beginningOfLine = false;
 
       if ((style == "variable" || style == "builtin")
-          && state.lastStyle == "meta")
+          && state.lastToken == "meta")
         style = "meta";
 
       // Handle scope changes.
@@ -265,15 +262,15 @@
 
       if (current == "lambda") state.lambda = true;
       if (current == ":" && !state.lambda && top(state).type == "py")
-        pushScope(stream, state, "py");
+        pushPyScope(state);
 
       var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;
       if (delimiter_index != -1)
-        pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
+        pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
 
       delimiter_index = "])}".indexOf(current);
       if (delimiter_index != -1) {
-        if (top(state).type == current) state.scopes.pop();
+        if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
         else return ERRORCLASS;
       }
       if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
@@ -289,7 +286,7 @@
         return {
           tokenize: tokenBase,
           scopes: [{offset: basecolumn || 0, type: "py", align: null}],
-          lastStyle: null,
+          indent: basecolumn || 0,
           lastToken: null,
           lambda: false,
           dedent: 0
@@ -301,11 +298,9 @@
         if (addErr) state.errorToken = false;
         var style = tokenLexer(stream, state);
 
-        state.lastStyle = style;
-
-        var current = stream.current();
-        if (current && style)
-          state.lastToken = current;
+        if (style && style != "comment")
+          state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style;
+        if (style == "punctuation") style = null;
 
         if (stream.eol() && state.lambda)
           state.lambda = false;
@@ -316,16 +311,15 @@
         if (state.tokenize != tokenBase)
           return state.tokenize.isString ? CodeMirror.Pass : 0;
 
-        var scope = top(state);
-        var closing = textAfter && textAfter.charAt(0) == scope.type;
+        var scope = top(state), closing = scope.type == textAfter.charAt(0)
         if (scope.align != null)
-          return scope.align - (closing ? 1 : 0);
-        else if (closing && state.scopes.length > 1)
-          return state.scopes[state.scopes.length - 2].offset;
+          return scope.align - (closing ? 1 : 0)
         else
-          return scope.offset;
+          return scope.offset - (closing ? hangingIndent : 0)
       },
 
+      electricInput: /^\s*[\}\]\)]$/,
+      closeBrackets: {triples: "'\""},
       lineComment: "#",
       fold: "indent"
     };
diff --git a/third_party/WebKit/Source/devtools/front_end/cm_modes/shell.js b/third_party/WebKit/Source/devtools/front_end/cm_modes/shell.js
index 77be75b9..a684e8c 100644
--- a/third_party/WebKit/Source/devtools/front_end/cm_modes/shell.js
+++ b/third_party/WebKit/Source/devtools/front_end/cm_modes/shell.js
@@ -128,7 +128,9 @@
     startState: function() {return {tokens:[]};},
     token: function(stream, state) {
       return tokenize(stream, state);
-    }
+    },
+    lineComment: '#',
+    fold: "brace"
   };
 });
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css
index 35718b5..a268e92 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css
@@ -171,6 +171,10 @@
     border-top: 0 none;
 }
 
+.style-panes-wrapper {
+    overflow: auto;
+}
+
 .styles-section.read-only {
     background-color: #eee;
 }
@@ -740,6 +744,10 @@
     padding-left: 10px;
 }
 
+.view > .toolbar {
+    border-bottom: 1px solid #eee;
+}
+
 .events-pane .section:not(:first-of-type) {
     border-top: 1px solid rgb(231, 231, 231);
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js
index 8a84df6..c9aa41c 100644
--- a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionPanel.js
@@ -249,7 +249,7 @@
             delete this._objectPropertiesView;
         }
         if (this._extensionView)
-            this._extensionView.detach(true);
+            this._extensionView.detach();
 
         this._extensionView = new WebInspector.ExtensionView(this._server, this._id, url, "extension fill");
         this._extensionView.show(this.element);
@@ -286,7 +286,7 @@
         if (this._objectPropertiesView)
             return;
         if (this._extensionView) {
-            this._extensionView.detach(true);
+            this._extensionView.detach();
             delete this._extensionView;
         }
         this._objectPropertiesView = new WebInspector.ExtensionNotifierView(this._server, this._id);
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 8e31408..0294bde 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -1023,7 +1023,7 @@
     dialog.setWrapsContent(true);
     dialog.addCloseButton();
     dialog.setDimmed(true);
-    var hideBound = dialog.detach.bind(dialog, false);
+    var hideBound = dialog.detach.bind(dialog);
     debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, hideBound);
 
     new WebInspector.TargetCrashedScreen(onHide).show(dialog.element);
diff --git a/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js b/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
index cf6036a..dd724d14 100644
--- a/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
+++ b/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
@@ -1206,10 +1206,13 @@
         var lineHandle = this._codeMirror.getLineHandle(lineNumber);
         if (!lineHandle)
             return;
-        if (toggled)
+        if (toggled) {
+            this._codeMirror.addLineClass(lineHandle, "gutter", className);
             this._codeMirror.addLineClass(lineHandle, "wrap", className);
-        else
+        } else {
+            this._codeMirror.removeLineClass(lineHandle, "gutter", className);
             this._codeMirror.removeLineClass(lineHandle, "wrap", className);
+        }
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/source_frame/module.json b/third_party/WebKit/Source/devtools/front_end/source_frame/module.json
index 04b93b0..94ff6fe 100644
--- a/third_party/WebKit/Source/devtools/front_end/source_frame/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/source_frame/module.json
@@ -32,6 +32,7 @@
         "../cm/javascript.js",
         "../cm/simple.js",
         "../cm/xml.js",
+        "../cm/multiplex.js",
         "../cm/htmlmixed.js",
         "../cm/htmlembedded.js",
 
@@ -57,6 +58,7 @@
         "../cm/javascript.js",
         "../cm/simple.js",
         "../cm/xml.js",
+        "../cm/multiplex.js",
         "../cm/htmlmixed.js",
         "../cm/htmlembedded.js",
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
index 9d07485c0..49bbec3 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
@@ -182,9 +182,10 @@
     {
         event.consume(true);
         if (this._swatchPopoverHelper.isShowing()) {
-            this._swatchPopoverHelper.hide();
+            this._swatchPopoverHelper.hide(true);
             return;
         }
+        this._hadSpectrumChange = false;
         this._currentSwatch = swatch;
         this._currentColorPosition = colorPosition;
         this.textEditor.setSelection(WebInspector.TextRange.createFromLocation(colorPosition.textRange.startLine, colorPosition.textRange.startColumn));
@@ -209,19 +210,27 @@
     _spectrumChanged: function(event)
     {
         this._muteColorProcessing = true;
+        this._hadSpectrumChange = true;
         var colorString = /** @type {string} */ (event.data);
         this._currentSwatch.setColorText(colorString);
-        this._textEditor.editRange(this._currentColorPosition.textRange, colorString, "*color-text-changed");
+        this.textEditor.editRange(this._currentColorPosition.textRange, colorString, "*color-text-changed");
         this._currentColorPosition.color = WebInspector.Color.parse(colorString);
         this._currentColorPosition.textRange.endColumn = this._currentColorPosition.textRange.startColumn + colorString.length;
     },
 
-    _spectrumHidden: function()
+    /**
+     * @param {boolean} commitEdit
+     */
+    _spectrumHidden: function(commitEdit)
     {
-        this._muteColorProcessing = false;
         this._spectrum.removeEventListener(WebInspector.Spectrum.Events.SizeChanged, this._spectrumResized, this);
         this._spectrum.removeEventListener(WebInspector.Spectrum.Events.ColorChanged, this._spectrumChanged, this);
+        if (!commitEdit && this._hadSpectrumChange)
+            this.textEditor.undo();
         delete this._spectrum;
+        delete this._currentSwatch;
+        delete this._currentColorPosition;
+        this._muteColorProcessing = false;
         this._updateColorSwatches();
     },
 
@@ -258,7 +267,7 @@
     {
         WebInspector.UISourceCodeFrame.prototype.scrollChanged.call(this, lineNumber);
         if (this._swatchPopoverHelper.isShowing())
-            this._swatchPopoverHelper.hide();
+            this._swatchPopoverHelper.hide(true);
     },
 
     __proto__: WebInspector.UISourceCodeFrame.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/sourcesView.css b/third_party/WebKit/Source/devtools/front_end/sources/sourcesView.css
index d7996c4..a4a831f 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/sourcesView.css
+++ b/third_party/WebKit/Source/devtools/front_end/sources/sourcesView.css
@@ -111,7 +111,7 @@
     border-left: 4px solid hsla(144, 55%, 37%, 1);
 }
 
-.diff-entry-insert .CodeMirror-gutter-wrapper {
+.diff-entry-insert .CodeMirror-gutter-background {
     background-color: hsla(144,55%,49%,.2);
 }
 
@@ -119,7 +119,7 @@
     border-left: 4px solid #9C27B0;
 }
 
-.diff-entry-modify .CodeMirror-gutter-wrapper {
+.diff-entry-modify .CodeMirror-gutter-background {
     background-color: rgba(186,104,200,0.2);
 }
 
@@ -130,12 +130,12 @@
     border-bottom: 6px solid transparent;
     border-left: 6px solid #D32F2F;
     position: relative;
-    top: 7px;
+    top: 6px;
     cursor: pointer;
     left: 0px;
 }
 
-.diff-entry-delete .CodeMirror-gutter-wrapper {
+.diff-entry-delete .CodeMirror-gutter-background {
     border-bottom: 2px solid #D32F2F;
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js b/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
index 74ac91b..e603a90 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Dialog.js
@@ -108,7 +108,7 @@
     {
         var closeButton = this.contentElement.createChild("div", "dialog-close-button", "dt-close-button");
         closeButton.gray = true;
-        closeButton.addEventListener("click", this.detach.bind(this, false), false);
+        closeButton.addEventListener("click", this.detach.bind(this), false);
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/RootView.js b/third_party/WebKit/Source/devtools/front_end/ui/RootView.js
index e4b5ef9..00854626 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/RootView.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/RootView.js
@@ -23,7 +23,7 @@
         document.defaultView.addEventListener("resize", this.doResize.bind(this), false);
         this._window = document.defaultView;
         this.doResize();
-        this.show(document.body);
+        this.show(/** @type {!Element} */ (document.body));
     },
 
     doResize: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SidebarPane.js b/third_party/WebKit/Source/devtools/front_end/ui/SidebarPane.js
index 5fbdcaf8..1284f671 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SidebarPane.js
@@ -46,7 +46,7 @@
     _expand: function()
     {
         this.element.classList.add("expanded");
-        this._pane.show(this.element.parentElement, /** @type {?Element} */ (this.element.nextSibling));
+        this._pane.show(/** @type {!Element} */(this.element.parentElement), /** @type {?Element} */ (this.element.nextSibling));
     },
 
     _collapse: function()
@@ -132,17 +132,22 @@
     this.element.classList.add("sidebar-pane-container", "sidebar-tabbed-pane");
 }
 
+WebInspector.SidebarTabbedPane._toolbarSymbol = Symbol("toolbar");
+
 WebInspector.SidebarTabbedPane.prototype = {
     /**
      * @param {!WebInspector.View} pane
      */
     addPane: function(pane)
     {
-        var title = pane.title();
+        // Detach first to trigger toolbar cleanup.
+        pane.detach();
 
+        var title = pane.title();
         var toolbarItems = pane.toolbarItems();
         if (toolbarItems.length) {
             var toolbar = new WebInspector.Toolbar("");
+            pane[WebInspector.SidebarTabbedPane._toolbarSymbol] = toolbar;
             pane.element.insertBefore(toolbar.element, pane.element.firstChild);
             for (var item of toolbarItems)
                 toolbar.appendToolbarItem(item);
@@ -153,6 +158,19 @@
     },
 
     /**
+     * @param {!WebInspector.Widget} widget
+     * @override
+     */
+    childWasDetached: function(widget)
+    {
+        WebInspector.TabbedPane.prototype.childWasDetached.call(this, widget);
+
+        var toolbar = widget[WebInspector.SidebarTabbedPane._toolbarSymbol];
+        if (toolbar)
+            toolbar.element.remove();
+    },
+
+    /**
      * @param {!WebInspector.View} pane
      * @param {boolean} visible
      */
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
index 6a52c0c..3f9e839 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SplitWidget.js
@@ -152,15 +152,18 @@
     {
         if (this._mainWidget === widget)
             return;
+        this.suspendInvalidations();
         if (this._mainWidget)
             this._mainWidget.detach();
         this._mainWidget = widget;
         if (widget) {
             widget.element.classList.add("insertion-point-main");
             widget.element.classList.remove("insertion-point-sidebar");
+            widget.attach(this);
             if (this._showMode === WebInspector.SplitWidget.ShowMode.OnlyMain || this._showMode === WebInspector.SplitWidget.ShowMode.Both)
-                widget.show(this.element);
+                widget.showWidget(this.element);
         }
+        this.resumeInvalidations();
     },
 
     /**
@@ -170,15 +173,18 @@
     {
         if (this._sidebarWidget === widget)
             return;
+        this.suspendInvalidations();
         if (this._sidebarWidget)
             this._sidebarWidget.detach();
         this._sidebarWidget = widget;
         if (widget) {
             widget.element.classList.add("insertion-point-sidebar");
             widget.element.classList.remove("insertion-point-main");
+            widget.attach(this);
             if (this._showMode === WebInspector.SplitWidget.ShowMode.OnlySidebar || this._showMode === WebInspector.SplitWidget.ShowMode.Both)
-                widget.show(this.element);
+                widget.showWidget(this.element);
         }
+        this.resumeInvalidations();
     },
 
     /**
@@ -203,8 +209,6 @@
      */
     childWasDetached: function(widget)
     {
-        if (this._detaching)
-            return;
         if (this._mainWidget === widget)
             delete this._mainWidget;
         if (this._sidebarWidget === widget)
@@ -316,15 +320,12 @@
             if (sideToShow) {
                 // Make sure main is first in the children list.
                 if (sideToShow === this._mainWidget)
-                    this._mainWidget.show(this.element, this._sidebarWidget ? this._sidebarWidget.element : null);
+                    this._mainWidget.showWidget(this.element);
                 else
-                    this._sidebarWidget.show(this.element);
+                    this._sidebarWidget.showWidget(this.element);
             }
-            if (sideToHide) {
-                this._detaching = true;
-                sideToHide.detach();
-                delete this._detaching;
-            }
+            if (sideToHide)
+                sideToHide.hideWidget();
 
             this._resizerElement.classList.add("hidden");
             shadowToShow.classList.remove("hidden");
@@ -379,10 +380,12 @@
         this.setResizable(true);
 
         // Make sure main is the first in the children list.
+        this.suspendInvalidations();
         if (this._sidebarWidget)
-            this._sidebarWidget.show(this.element);
+            this._sidebarWidget.showWidget(this.element);
         if (this._mainWidget)
-            this._mainWidget.show(this.element, this._sidebarWidget ? this._sidebarWidget.element : null);
+            this._mainWidget.showWidget(this.element);
+        this.resumeInvalidations();
         // Order widgets in DOM properly.
         this.setSecondIsSidebar(this._secondIsSidebar);
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
index 5ab0706..0fc7a2dc 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
@@ -208,6 +208,7 @@
         else
             this._tabs.push(tab);
         this._tabsHistory.push(tab);
+        view.attach(this);
         if (this._tabsHistory[0] === tab && this.isShowing())
             this.selectTab(tab.id, userGesture);
         this._updateTabElements();
@@ -258,6 +259,7 @@
         this._tabs.splice(this._tabs.indexOf(tab), 1);
         if (tab._shown)
             this._hideTabElement(tab);
+        tab.view.detach();
 
         var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture };
         this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabClosed, eventData);
@@ -329,8 +331,10 @@
         if (this._currentTab && this._currentTab.id === id)
             return true;
 
+        this.suspendInvalidations();
         this._hideCurrentTab();
         this._showTab(tab);
+        this.resumeInvalidations();
         this._currentTab = tab;
 
         this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1);
@@ -423,13 +427,19 @@
     changeTabView: function(id, view)
     {
         var tab = this._tabsById[id];
-        if (this._currentTab && this._currentTab.id === tab.id) {
-            if (tab.view !== view)
-                this._hideTab(tab);
-            tab.view = view;
+        if (tab.view === view)
+            return;
+
+        this.suspendInvalidations();
+        var isSelected = this._currentTab && this._currentTab.id === id;
+        if (isSelected)
+            this._hideTab(tab);
+        tab.view.detach();
+        tab.view = view;
+        tab.view.attach(this);
+        if (isSelected)
             this._showTab(tab);
-        } else
-            tab.view = view;
+        this.resumeInvalidations();
     },
 
     onResize: function()
@@ -759,7 +769,7 @@
     _showTab: function(tab)
     {
         tab.tabElement.classList.add("selected");
-        tab.view.show(this.element);
+        tab.view.showWidget(this.element);
         this._updateTabSlider();
     },
 
@@ -785,7 +795,7 @@
     _hideTab: function(tab)
     {
         tab.tabElement.classList.remove("selected");
-        tab.view.detach();
+        tab.view.hideWidget();
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Widget.js b/third_party/WebKit/Source/devtools/front_end/ui/Widget.js
index 5558f58..bed99405 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Widget.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Widget.js
@@ -41,12 +41,13 @@
     }
     this._isWebComponent = isWebComponent;
     this.element.__widget = this;
-    this._visible = true;
+    this._visible = false;
     this._isRoot = false;
     this._isShowing = false;
     this._children = [];
     this._hideOnDetach = false;
     this._notificationDepth = 0;
+    this._invalidationsSuspended = 0;
 }
 
 WebInspector.Widget.prototype = {
@@ -93,6 +94,8 @@
      */
     shouldHideOnDetach: function()
     {
+        if (!this.element.parentElement)
+            return false;
         if (this._hideOnDetach)
             return true;
         for (var child of this._children) {
@@ -119,7 +122,7 @@
     {
         if (this._isRoot)
             return true;
-        return this._parentWidget && this._parentWidget.isShowing();
+        return !!this._parentWidget && this._parentWidget.isShowing();
     },
 
     /**
@@ -205,32 +208,56 @@
     },
 
     /**
-     * @param {?Element} parentElement
+     * @param {!Element} parentElement
      * @param {?Element=} insertBefore
      */
     show: function(parentElement, insertBefore)
     {
         WebInspector.Widget.__assert(parentElement, "Attempt to attach widget with no parent element");
 
-        // Update widget hierarchy.
-        if (this.element.parentElement !== parentElement) {
-            if (this.element.parentElement)
-                this.detach();
-
+        if (!this._isRoot) {
+            // Update widget hierarchy.
             var currentParent = parentElement;
             while (currentParent && !currentParent.__widget)
                 currentParent = currentParent.parentElementOrShadowHost();
-
-            if (currentParent) {
-                this._parentWidget = currentParent.__widget;
-                this._parentWidget._children.push(this);
-                this._isRoot = false;
-            } else
-                WebInspector.Widget.__assert(this._isRoot, "Attempt to attach widget to orphan node");
-        } else if (this._visible) {
-            return;
+            WebInspector.Widget.__assert(currentParent, "Attempt to attach widget to orphan node");
+            this.attach(currentParent.__widget);
         }
 
+        this.showWidget(parentElement, insertBefore);
+    },
+
+    /**
+     * @param {!WebInspector.Widget} parentWidget
+     */
+    attach: function(parentWidget)
+    {
+        if (parentWidget === this._parentWidget)
+            return;
+        if (this._parentWidget)
+            this.detach();
+        this._parentWidget = parentWidget;
+        this._parentWidget._children.push(this);
+        this._isRoot = false;
+    },
+
+    /**
+     * @param {!Element} parentElement
+     * @param {?Element=} insertBefore
+     */
+    showWidget: function(parentElement, insertBefore)
+    {
+        var currentParent = parentElement;
+        while (currentParent && !currentParent.__widget)
+            currentParent = currentParent.parentElementOrShadowHost();
+
+        if (this._isRoot)
+            WebInspector.Widget.__assert(!currentParent, "Attempt to show root widget under another widget");
+        else
+            WebInspector.Widget.__assert(currentParent && currentParent.__widget === this._parentWidget, "Attempt to show under node belonging to alien widget");
+
+        if (this._visible)
+            return;
         this._visible = true;
 
         if (this._parentIsShowing())
@@ -256,35 +283,47 @@
             this._processOnResize();
     },
 
+    hideWidget: function()
+    {
+        if (!this._parentWidget)
+            return;
+        this._hideWidget();
+    },
+
     /**
      * @param {boolean=} overrideHideOnDetach
      */
-    detach: function(overrideHideOnDetach)
+    _hideWidget: function(overrideHideOnDetach)
     {
-        var parentElement = this.element.parentElement;
-        if (!parentElement)
+        if (!this._visible)
             return;
+        this._visible = false;
+        var parentElement = this.element.parentElement;
 
         if (this._parentIsShowing())
             this._processWillHide();
 
         if (!overrideHideOnDetach && this.shouldHideOnDetach()) {
             this.element.classList.add("hidden");
-            this._visible = false;
-            if (this._parentIsShowing())
-                this._processWasHidden();
-            if (this._parentWidget && this._hasNonZeroConstraints())
-                this._parentWidget.invalidateConstraints();
-            return;
+        } else {
+            // Force legal removal
+            WebInspector.Widget._decrementWidgetCounter(parentElement, this.element);
+            WebInspector.Widget._originalRemoveChild.call(parentElement, this.element);
         }
 
-        // Force legal removal
-        WebInspector.Widget._decrementWidgetCounter(parentElement, this.element);
-        WebInspector.Widget._originalRemoveChild.call(parentElement, this.element);
-
-        this._visible = false;
         if (this._parentIsShowing())
             this._processWasHidden();
+        if (this._parentWidget && this._hasNonZeroConstraints())
+            this._parentWidget.invalidateConstraints();
+    },
+
+    detach: function()
+    {
+        if (!this._parentWidget && !this._isRoot)
+            return;
+
+        if (this._visible)
+            this._hideWidget(true);
 
         // Update widget hierarchy.
         if (this._parentWidget) {
@@ -294,10 +333,9 @@
             this._parentWidget.childWasDetached(this);
             var parent = this._parentWidget;
             this._parentWidget = null;
-            if (this._hasNonZeroConstraints())
-                parent.invalidateConstraints();
-        } else
+        } else {
             WebInspector.Widget.__assert(this._isRoot, "Removing non-root widget from DOM");
+        }
     },
 
     detachChildWidgets: function()
@@ -479,8 +517,25 @@
         return !!(constraints.minimum.width || constraints.minimum.height || constraints.preferred.width || constraints.preferred.height);
     },
 
+    suspendInvalidations()
+    {
+        ++this._invalidationsSuspended;
+    },
+
+    resumeInvalidations()
+    {
+        --this._invalidationsSuspended;
+        if (!this._invalidationsSuspended && this._invalidationsRequested)
+            this.invalidateConstraints();
+    },
+
     invalidateConstraints: function()
     {
+        if (this._invalidationsSuspended) {
+            this._invalidationsRequested = true;
+            return;
+        }
+        this._invalidationsRequested = false;
         var cached = this._cachedConstraints;
         delete this._cachedConstraints;
         var actual = this.constraints();
@@ -641,6 +696,7 @@
 WebInspector.View = function(title, isWebComponent)
 {
     WebInspector.VBox.call(this, isWebComponent);
+    this.element.classList.add("view");
     this._title = title;
     /** @type {!Array<!WebInspector.ToolbarItem>} */
     this._toolbarItems = [];
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/sidebarPane.css b/third_party/WebKit/Source/devtools/front_end/ui/sidebarPane.css
index 7adef12..5a56671 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/sidebarPane.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/sidebarPane.css
@@ -27,10 +27,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-.sidebar-pane-container {
-    overflow: auto;
-}
-
 .sidebar-pane-container .info {
     text-align: center;
     font-style: italic;
@@ -86,10 +82,6 @@
     -webkit-mask-position: -20px -96px;
 }
 
-.sidebar-pane-container .toolbar {
-    border-bottom: 1px solid #eee;
-}
-
 .sidebar-pane-container .toolbar > * {
     pointer-events: auto;
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
index 334ebf4..8ddeaa45 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/TimelineOverviewPane.js
@@ -476,8 +476,8 @@
 
 WebInspector.TimelineOverview.prototype = {
     /**
-     * @param {?Element} parentElement
-     * @param {!Element=} insertBefore
+     * @param {!Element} parentElement
+     * @param {?Element=} insertBefore
      */
     show: function(parentElement, insertBefore) { },
 
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index 5b3ea2c4..1585354f 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -426,16 +426,16 @@
     if (getLayoutObject() && getLayoutObject()->isTextControl())
         return true;
 
-    if (getNode() && getNode()->isContentEditable())
+    if (getNode() && isContentEditable(*getNode()))
         return true;
 
     if (isWebArea()) {
         Document& document = getLayoutObject()->document();
         HTMLElement* body = document.body();
-        if (body && body->isContentEditable())
+        if (body && isContentEditable(*body))
             return true;
 
-        return document.isContentEditable();
+        return isContentEditable(document);
     }
 
     return AXNodeObject::isEditable();
@@ -445,16 +445,16 @@
 // user-modify. Don't move this logic to AXNodeObject.
 bool AXLayoutObject::isRichlyEditable() const
 {
-    if (getNode() && getNode()->isContentRichlyEditable())
+    if (getNode() && isContentRichlyEditable(*getNode()))
         return true;
 
     if (isWebArea()) {
         Document& document = m_layoutObject->document();
         HTMLElement* body = document.body();
-        if (body && body->isContentRichlyEditable())
+        if (body && isContentRichlyEditable(*body))
             return true;
 
-        return document.isContentRichlyEditable();
+        return isContentRichlyEditable(document);
     }
 
     return AXNodeObject::isRichlyEditable();
diff --git a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
index 7821578..cb553dd 100644
--- a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
+++ b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
@@ -118,6 +118,12 @@
     settings->has_zoom = photoSettings.hasZoom();
     if (settings->has_zoom)
         settings->zoom = photoSettings.zoom();
+    settings->has_height = photoSettings.hasImageHeight();
+    if (settings->has_height)
+        settings->height = photoSettings.imageHeight();
+    settings->has_width = photoSettings.hasImageWidth();
+    if (settings->has_width)
+        settings->width = photoSettings.imageWidth();
 
     m_service->SetOptions(m_streamTrack->component()->source()->id(), std::move(settings), convertToBaseCallback(WTF::bind(&ImageCapture::onSetOptions, wrapPersistent(this), wrapPersistent(resolver))));
     return promise;
@@ -197,8 +203,14 @@
         resolver->reject(DOMException::create(UnknownError, "platform error"));
     } else {
         // TODO(mcasas): Should be using a mojo::StructTraits.
+        MediaSettingsRange* iso = MediaSettingsRange::create(capabilities->iso->max, capabilities->iso->min, capabilities->iso->current);
+        MediaSettingsRange* height = MediaSettingsRange::create(capabilities->height->max, capabilities->height->min, capabilities->height->current);
+        MediaSettingsRange* width = MediaSettingsRange::create(capabilities->width->max, capabilities->width->min, capabilities->width->current);
         MediaSettingsRange* zoom = MediaSettingsRange::create(capabilities->zoom->max, capabilities->zoom->min, capabilities->zoom->current);
         PhotoCapabilities* caps = PhotoCapabilities::create();
+        caps->setIso(iso);
+        caps->setImageHeight(height);
+        caps->setImageWidth(width);
         caps->setZoom(zoom);
         caps->setFocusMode(capabilities->focus_mode);
         resolver->resolve(caps);
@@ -218,15 +230,16 @@
     m_serviceRequests.remove(resolver);
 }
 
-void ImageCapture::onTakePhoto(ScriptPromiseResolver* resolver, const String& mimeType, const Vector<uint8_t>& data)
+void ImageCapture::onTakePhoto(ScriptPromiseResolver* resolver, media::mojom::blink::BlobPtr blob)
 {
     if (!m_serviceRequests.contains(resolver))
         return;
 
-    if (data.isEmpty())
+    // TODO(mcasas): Should be using a mojo::StructTraits.
+    if (blob->data.isEmpty())
         resolver->reject(DOMException::create(UnknownError, "platform error"));
     else
-        resolver->resolve(Blob::create(data.data(), data.size(), mimeType));
+        resolver->resolve(Blob::create(blob->data.data(), blob->data.size(), blob->mime_type));
     m_serviceRequests.remove(resolver);
 }
 
diff --git a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.h b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.h
index 3c86c82..fd4c250 100644
--- a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.h
+++ b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.h
@@ -61,7 +61,7 @@
 
     void onCapabilities(ScriptPromiseResolver*, media::mojom::blink::PhotoCapabilitiesPtr);
     void onSetOptions(ScriptPromiseResolver*, bool);
-    void onTakePhoto(ScriptPromiseResolver*, const String& mimeType, const Vector<uint8_t>& data);
+    void onTakePhoto(ScriptPromiseResolver*, media::mojom::blink::BlobPtr);
     void onServiceConnectionError();
 
     Member<MediaStreamTrack> m_streamTrack;
diff --git a/third_party/WebKit/Source/modules/imagecapture/OWNERS b/third_party/WebKit/Source/modules/imagecapture/OWNERS
new file mode 100644
index 0000000..22ef8b81
--- /dev/null
+++ b/third_party/WebKit/Source/modules/imagecapture/OWNERS
@@ -0,0 +1,2 @@
+mcasas@chromium.org
+reillyg@chromium.org
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp
index c1d7ffd..20340f2 100644
--- a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp
+++ b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp
@@ -12,10 +12,6 @@
     return new PhotoCapabilities();
 }
 
-MediaSettingsRange* PhotoCapabilities::zoom() const { return m_zoom; }
-
-void PhotoCapabilities::setZoom(MediaSettingsRange* value) { m_zoom = value; }
-
 String PhotoCapabilities::focusMode() const
 {
     switch (m_focusMode) {
@@ -31,13 +27,11 @@
     return emptyString();
 }
 
-void PhotoCapabilities::setFocusMode(media::mojom::blink::FocusMode focusMode)
-{
-    m_focusMode = focusMode;
-}
-
 DEFINE_TRACE(PhotoCapabilities)
 {
+    visitor->trace(m_iso);
+    visitor->trace(m_imageHeight);
+    visitor->trace(m_imageWidth);
     visitor->trace(m_zoom);
 }
 
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h
index 4d1e435..c41f745e 100644
--- a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h
+++ b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h
@@ -20,17 +20,29 @@
     static PhotoCapabilities* create();
     virtual ~PhotoCapabilities() = default;
 
-    MediaSettingsRange* zoom() const;
-    void setZoom(MediaSettingsRange* value);
+    MediaSettingsRange* iso() const { return m_iso; }
+    void setIso(MediaSettingsRange* value) { m_iso = value; }
+
+    MediaSettingsRange* imageHeight() const { return m_imageHeight; }
+    void setImageHeight(MediaSettingsRange* value) { m_imageHeight = value; }
+
+    MediaSettingsRange* imageWidth() const { return m_imageWidth; }
+    void setImageWidth(MediaSettingsRange* value) { m_imageWidth = value; }
+
+    MediaSettingsRange* zoom() const { return m_zoom; }
+    void setZoom(MediaSettingsRange* value) { m_zoom = value; }
 
     String focusMode() const;
-    void setFocusMode(media::mojom::blink::FocusMode);
+    void setFocusMode(media::mojom::blink::FocusMode focusMode) { m_focusMode = focusMode; }
 
     DECLARE_VIRTUAL_TRACE();
 
 private:
     PhotoCapabilities() = default;
 
+    Member<MediaSettingsRange> m_iso;
+    Member<MediaSettingsRange> m_imageHeight;
+    Member<MediaSettingsRange> m_imageWidth;
     Member<MediaSettingsRange> m_zoom;
     media::mojom::blink::FocusMode m_focusMode = media::mojom::blink::FocusMode::UNAVAILABLE;
 };
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl
index 0b59ae3..0d2b450 100644
--- a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl
+++ b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl
@@ -13,6 +13,11 @@
 [
     RuntimeEnabled=ImageCapture,
 ] interface PhotoCapabilities {
+    readonly attribute MediaSettingsRange iso;
+    // TODO(mcasas): Replace these two with supported and current resolutions.
+    // https://github.com/w3c/mediacapture-image/issues/30
+    readonly attribute MediaSettingsRange imageHeight;
+    readonly attribute MediaSettingsRange imageWidth;
     readonly attribute MediaSettingsRange zoom;
     readonly attribute FocusMode focusMode;
     // TODO(mcasas): Implement all other PhotoCapabilities fields
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoSettings.idl b/third_party/WebKit/Source/modules/imagecapture/PhotoSettings.idl
index 11e5bee..a16cef1 100644
--- a/third_party/WebKit/Source/modules/imagecapture/PhotoSettings.idl
+++ b/third_party/WebKit/Source/modules/imagecapture/PhotoSettings.idl
@@ -8,6 +8,8 @@
     RuntimeEnabled=ImageCapture
 ] dictionary PhotoSettings {
     unsigned long zoom;
+    unsigned long imageHeight;
+    unsigned long imageWidth;
     // TODO(mcasas): Implement all other PhotoSettings fields
     // https://crbug.com/518807
 };
diff --git a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
index fc4b545..0455d16 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
@@ -157,6 +157,7 @@
 v8::Local<v8::Function> PaymentRequestMockFunctionScope::expectCall(String* captor)
 {
     m_mockFunctions.append(new MockFunction(m_scriptState, captor));
+    EXPECT_CALL(*m_mockFunctions.last(), call(testing::_));
     return m_mockFunctions.last()->bind();
 }
 
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp
index 9daf2ae7..0d4e189 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp
@@ -91,67 +91,50 @@
 
 ScriptPromise PresentationRequest::start(ScriptState* scriptState)
 {
-    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
-    ScriptPromise promise = resolver->promise();
-
     Settings* contextSettings = settings(getExecutionContext());
     bool isUserGestureRequired = !contextSettings || contextSettings->presentationRequiresUserGesture();
 
-    if (isUserGestureRequired && !UserGestureIndicator::utilizeUserGesture()) {
-        resolver->reject(DOMException::create(InvalidAccessError, "PresentationRequest::start() requires user gesture."));
-        return promise;
-    }
+    if (isUserGestureRequired && !UserGestureIndicator::utilizeUserGesture())
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidAccessError, "PresentationRequest::start() requires user gesture."));
 
-    if (toDocument(getExecutionContext())->isSandboxed(SandboxPresentation)) {
-        resolver->reject(DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-presentation' flag."));
-        return promise;
-    }
+    if (toDocument(getExecutionContext())->isSandboxed(SandboxPresentation))
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-presentation' flag."));
 
     WebPresentationClient* client = presentationClient(getExecutionContext());
-    if (!client) {
-        resolver->reject(DOMException::create(InvalidStateError, "The PresentationRequest is no longer associated to a frame."));
-        return promise;
-    }
+    if (!client)
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "The PresentationRequest is no longer associated to a frame."));
+
+    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
     client->startSession(m_url.getString(), new PresentationConnectionCallbacks(resolver, this));
-    return promise;
+    return resolver->promise();
 }
 
 ScriptPromise PresentationRequest::reconnect(ScriptState* scriptState, const String& id)
 {
-    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
-    ScriptPromise promise = resolver->promise();
-
-    if (toDocument(getExecutionContext())->isSandboxed(SandboxPresentation)) {
-        resolver->reject(DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-presentation' flag."));
-        return promise;
-    }
+    if (toDocument(getExecutionContext())->isSandboxed(SandboxPresentation))
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-presentation' flag."));
 
     WebPresentationClient* client = presentationClient(getExecutionContext());
-    if (!client) {
-        resolver->reject(DOMException::create(InvalidStateError, "The PresentationRequest is no longer associated to a frame."));
-        return promise;
-    }
+    if (!client)
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "The PresentationRequest is no longer associated to a frame."));
+
+    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
     client->joinSession(m_url.getString(), id, new PresentationConnectionCallbacks(resolver, this));
-    return promise;
+    return resolver->promise();
 }
 
 ScriptPromise PresentationRequest::getAvailability(ScriptState* scriptState)
 {
-    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
-    ScriptPromise promise = resolver->promise();
-
-    if (toDocument(getExecutionContext())->isSandboxed(SandboxPresentation)) {
-        resolver->reject(DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-presentation' flag."));
-        return promise;
-    }
+    if (toDocument(getExecutionContext())->isSandboxed(SandboxPresentation))
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-presentation' flag."));
 
     WebPresentationClient* client = presentationClient(getExecutionContext());
-    if (!client) {
-        resolver->reject(DOMException::create(InvalidStateError, "The object is no longer associated to a frame."));
-        return promise;
-    }
+    if (!client)
+        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "The PresentationRequest is no longer associated to a frame."));
+
+    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
     client->getAvailability(m_url.getString(), new PresentationAvailabilityCallbacks(resolver, m_url));
-    return promise;
+    return resolver->promise();
 }
 
 const KURL& PresentationRequest::url() const
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp b/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp
index dacfa90..eea7d72 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp
@@ -231,13 +231,15 @@
 
 void AudioListener::createAndLoadHRTFDatabaseLoader(float sampleRate)
 {
+    DCHECK(isMainThread());
+
     if (!m_hrtfDatabaseLoader)
         m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate);
 }
 
 bool AudioListener::isHRTFDatabaseLoaded()
 {
-    return m_hrtfDatabaseLoader->isLoaded();
+    return m_hrtfDatabaseLoader && m_hrtfDatabaseLoader->isLoaded();
 }
 
 void AudioListener::waitForHRTFDatabaseLoaderThreadCompletion()
diff --git a/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp b/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
index 3ef6973c..19d96f76 100644
--- a/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
@@ -67,10 +67,6 @@
     , m_orientationY(orientationY)
     , m_orientationZ(orientationZ)
 {
-    // Load the HRTF database asynchronously so we don't block the Javascript thread while creating the HRTF database.
-    // The HRTF panner will return zeroes until the database is loaded.
-    listener()->createAndLoadHRTFDatabaseLoader(node.context()->sampleRate());
-
     addInput();
     addOutput(2);
 
@@ -276,33 +272,37 @@
 
 void PannerHandler::setPanningModel(const String& model)
 {
+    // WebIDL should guarantee that we are never called with an invalid string
+    // for the model.
     if (model == "equalpower")
         setPanningModel(Panner::PanningModelEqualPower);
     else if (model == "HRTF")
         setPanningModel(Panner::PanningModelHRTF);
+    else
+        NOTREACHED();
 }
 
+// This method should only be called from setPanningModel(const String&)!
 bool PannerHandler::setPanningModel(unsigned model)
 {
     DEFINE_STATIC_LOCAL(EnumerationHistogram, panningModelHistogram,
         ("WebAudio.PannerNode.PanningModel", 2));
     panningModelHistogram.count(model);
 
-    switch (model) {
-    case Panner::PanningModelEqualPower:
-    case Panner::PanningModelHRTF:
-        if (!m_panner.get() || model != m_panningModel) {
-            // This synchronizes with process().
-            MutexLocker processLocker(m_processLock);
-            m_panner = Panner::create(model, sampleRate(), listener()->hrtfDatabaseLoader());
-            m_panningModel = model;
-        }
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-        return false;
+    if (model == Panner::PanningModelHRTF) {
+        // Load the HRTF database asynchronously so we don't block the
+        // Javascript thread while creating the HRTF database. It's ok to call
+        // this multiple times; we won't be constantly loading the database over
+        // and over.
+        listener()->createAndLoadHRTFDatabaseLoader(context()->sampleRate());
     }
 
+    if (!m_panner.get() || model != m_panningModel) {
+        // This synchronizes with process().
+        MutexLocker processLocker(m_processLock);
+        m_panner = Panner::create(model, sampleRate(), listener()->hrtfDatabaseLoader());
+        m_panningModel = model;
+    }
     return true;
 }
 
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp
index cb70f64a3..1c9f9f12 100644
--- a/third_party/WebKit/Source/platform/TimerTest.cpp
+++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -94,7 +94,7 @@
         return true;
     }
 
-    WebTaskRunner* clone() override
+    std::unique_ptr<WebTaskRunner> clone() override
     {
         NOTREACHED();
         return nullptr;
diff --git a/third_party/WebKit/Source/platform/blink_platform.gyp b/third_party/WebKit/Source/platform/blink_platform.gyp
index 65825db..6a88549 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gyp
+++ b/third_party/WebKit/Source/platform/blink_platform.gyp
@@ -162,7 +162,7 @@
       '<(DEPTH)/ui/gfx/gfx.gyp:gfx',
       '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
       '<(DEPTH)/url/url.gyp:url_lib',
-      '<(DEPTH)/url/url.gyp:url_interfaces_mojom_for_blink',
+      '<(DEPTH)/url/url.gyp:url_mojom_for_blink',
       '<(DEPTH)/v8/src/v8.gyp:v8',
       '<(libjpeg_gyp_path):libjpeg',
     ],
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi
index fbc001d..00de0c5 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gypi
+++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -1000,7 +1000,6 @@
       'text/LocaleToScriptMapping.h',
       'text/LocaleWin.cpp',
       'text/LocaleWin.h',
-      'text/ParserUtilities.h',
       'text/PlatformLocale.cpp',
       'text/PlatformLocale.h',
       'text/QuotedPrintable.cpp',
diff --git a/third_party/WebKit/Source/platform/graphics/Path.cpp b/third_party/WebKit/Source/platform/graphics/Path.cpp
index 2fd75f8..65f73ce7 100644
--- a/third_party/WebKit/Source/platform/graphics/Path.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Path.cpp
@@ -115,14 +115,31 @@
     return strokePath(strokeData).contains(WebCoreFloatToSkScalar(point.x()), WebCoreFloatToSkScalar(point.y()));
 }
 
-FloatRect Path::boundingRect() const
+namespace {
+
+FloatRect pathBounds(const SkPath& path, Path::BoundsType boundsType)
 {
-    return m_path.getBounds();
+    SkRect bounds;
+    if (boundsType == Path::BoundsType::Conservative
+        || !TightBounds(path, &bounds)
+        || bounds.isEmpty()) // workaround for https://bugs.chromium.org/p/skia/issues/detail?id=5555
+        return path.getBounds();
+
+    DCHECK_EQ(boundsType, Path::BoundsType::Exact);
+    return bounds;
 }
 
-FloatRect Path::strokeBoundingRect(const StrokeData& strokeData) const
+} // anonymous ns
+
+// TODO(fmalita): evaluate returning exact bounds in all cases.
+FloatRect Path::boundingRect(BoundsType boundsType) const
 {
-    return strokePath(strokeData).getBounds();
+    return pathBounds(m_path, boundsType);
+}
+
+FloatRect Path::strokeBoundingRect(const StrokeData& strokeData, BoundsType boundsType) const
+{
+    return pathBounds(strokePath(strokeData), boundsType);
 }
 
 static FloatPoint* convertPathPoints(FloatPoint dst[], const SkPoint src[], int count)
diff --git a/third_party/WebKit/Source/platform/graphics/Path.h b/third_party/WebKit/Source/platform/graphics/Path.h
index 5497706..c84b809 100644
--- a/third_party/WebKit/Source/platform/graphics/Path.h
+++ b/third_party/WebKit/Source/platform/graphics/Path.h
@@ -78,8 +78,13 @@
     bool contains(const FloatPoint&) const;
     bool contains(const FloatPoint&, WindRule) const;
     bool strokeContains(const FloatPoint&, const StrokeData&) const;
-    FloatRect boundingRect() const;
-    FloatRect strokeBoundingRect(const StrokeData&) const;
+
+    enum class BoundsType {
+        Conservative, // Fast version, includes control points.
+        Exact, // Tight, slower version.
+    };
+    FloatRect boundingRect(BoundsType = BoundsType::Conservative) const;
+    FloatRect strokeBoundingRect(const StrokeData&, BoundsType = BoundsType::Conservative) const;
 
     float length() const;
     FloatPoint pointAtLength(float length) const;
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
index 4563839..dd956ebc 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -264,7 +264,7 @@
             return true;
         }
 
-        WebTaskRunner* clone() override
+        std::unique_ptr<WebTaskRunner> clone() override
         {
             NOTREACHED();
             return nullptr;
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
index f51287bf..3e51ec8 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -37,7 +37,7 @@
 
 EffectPaintPropertyNode* dummyRootEffect()
 {
-    DEFINE_STATIC_REF(EffectPaintPropertyNode, node, EffectPaintPropertyNode::create(1.0));
+    DEFINE_STATIC_REF(EffectPaintPropertyNode, node, EffectPaintPropertyNode::create(nullptr, 1.0));
     return node;
 }
 
@@ -102,7 +102,7 @@
 {
     // A 90 degree clockwise rotation about (100, 100).
     RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(
-        TransformationMatrix().rotate(90), FloatPoint3D(100, 100, 0));
+        nullptr, TransformationMatrix().rotate(90), FloatPoint3D(100, 100, 0));
 
     TestPaintArtifact artifact;
     artifact.chunk(transform, nullptr, dummyRootEffect())
@@ -142,9 +142,9 @@
 {
     // A translation by (5, 5) within a 2x scale about (10, 10).
     RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(
-        TransformationMatrix().scale(2), FloatPoint3D(10, 10, 0));
+        nullptr, TransformationMatrix().scale(2), FloatPoint3D(10, 10, 0));
     RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(
-        TransformationMatrix().translate(5, 5), FloatPoint3D(), transform1);
+        transform1, TransformationMatrix().translate(5, 5), FloatPoint3D());
 
     TestPaintArtifact artifact;
     artifact.chunk(transform1, nullptr, dummyRootEffect())
@@ -175,9 +175,9 @@
 TEST_F(PaintArtifactCompositorTest, LayerOriginCancellation)
 {
     RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(100, 100, 100, 100));
+        nullptr, nullptr, FloatRoundedRect(100, 100, 100, 100));
     RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(
-        TransformationMatrix().scale(2), FloatPoint3D());
+        nullptr, TransformationMatrix().scale(2), FloatPoint3D());
 
     TestPaintArtifact artifact;
     artifact.chunk(transform, clip, nullptr)
@@ -203,7 +203,7 @@
 TEST_F(PaintArtifactCompositorTest, OneClip)
 {
     RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(100, 100, 300, 200));
+        nullptr, nullptr, FloatRoundedRect(100, 100, 300, 200));
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, clip, nullptr)
@@ -226,9 +226,9 @@
 TEST_F(PaintArtifactCompositorTest, NestedClips)
 {
     RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(100, 100, 700, 700));
+        nullptr, nullptr, FloatRoundedRect(100, 100, 700, 700));
     RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(200, 200, 700, 100), clip1);
+        clip1, nullptr, FloatRoundedRect(200, 200, 700, 100));
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, clip1, dummyRootEffect())
@@ -289,8 +289,8 @@
     Vector<RefPtr<ClipPaintPropertyNode>> clips;
     for (unsigned i = 1; i <= 10; i++) {
         clips.append(ClipPaintPropertyNode::create(
-            nullptr, FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i),
-            clips.isEmpty() ? nullptr : clips.last()));
+            clips.isEmpty() ? nullptr : clips.last(),
+            nullptr, FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i)));
     }
 
     TestPaintArtifact artifact;
@@ -319,11 +319,11 @@
 TEST_F(PaintArtifactCompositorTest, SiblingClips)
 {
     RefPtr<ClipPaintPropertyNode> commonClip = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(0, 0, 800, 600));
+        nullptr, nullptr, FloatRoundedRect(0, 0, 800, 600));
     RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(0, 0, 400, 600), commonClip);
+        commonClip, nullptr, FloatRoundedRect(0, 0, 400, 600));
     RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(400, 0, 400, 600), commonClip);
+        commonClip, nullptr, FloatRoundedRect(400, 0, 400, 600));
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, clip1, nullptr)
@@ -454,7 +454,7 @@
 {
     // A 90 degree clockwise rotation about (100, 100).
     RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(
-        TransformationMatrix().rotate(90), FloatPoint3D(100, 100, 0));
+        nullptr, TransformationMatrix().rotate(90), FloatPoint3D(100, 100, 0));
 
     TestPaintArtifact artifact;
     artifact.chunk(transform, nullptr, dummyRootEffect())
@@ -494,9 +494,9 @@
 {
     // A translation by (5, 5) within a 2x scale about (10, 10).
     RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(
-        TransformationMatrix().scale(2), FloatPoint3D(10, 10, 0));
+        nullptr, TransformationMatrix().scale(2), FloatPoint3D(10, 10, 0));
     RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(
-        TransformationMatrix().translate(5, 5), FloatPoint3D(), transform1);
+        transform1, TransformationMatrix().translate(5, 5), FloatPoint3D());
 
     TestPaintArtifact artifact;
     artifact.chunk(transform1, nullptr, dummyRootEffect())
@@ -530,7 +530,7 @@
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OneClip)
 {
     RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(100, 100, 300, 200));
+        nullptr, nullptr, FloatRoundedRect(100, 100, 300, 200));
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, clip, nullptr)
@@ -552,9 +552,9 @@
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, NestedClips)
 {
     RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(100, 100, 700, 700));
+        nullptr, nullptr, FloatRoundedRect(100, 100, 700, 700));
     RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(200, 200, 700, 100), clip1);
+        clip1, nullptr, FloatRoundedRect(200, 200, 700, 100));
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, clip1, dummyRootEffect())
@@ -608,8 +608,8 @@
     Vector<RefPtr<ClipPaintPropertyNode>> clips;
     for (unsigned i = 1; i <= 10; i++) {
         clips.append(ClipPaintPropertyNode::create(
-            nullptr, FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i),
-            clips.isEmpty() ? nullptr : clips.last()));
+            clips.isEmpty() ? nullptr : clips.last(),
+            nullptr, FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i)));
     }
 
     TestPaintArtifact artifact;
@@ -638,11 +638,11 @@
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SiblingClips)
 {
     RefPtr<ClipPaintPropertyNode> commonClip = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(0, 0, 800, 600));
+        nullptr, nullptr, FloatRoundedRect(0, 0, 800, 600));
     RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(0, 0, 400, 600), commonClip);
+        commonClip, nullptr, FloatRoundedRect(0, 0, 400, 600));
     RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(400, 0, 400, 600), commonClip);
+        commonClip, nullptr, FloatRoundedRect(400, 0, 400, 600));
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, clip1, dummyRootEffect())
@@ -695,9 +695,9 @@
 
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EffectTreeConversion)
 {
-    RefPtr<EffectPaintPropertyNode> effect1 = EffectPaintPropertyNode::create(0.5, dummyRootEffect());
-    RefPtr<EffectPaintPropertyNode> effect2 = EffectPaintPropertyNode::create(0.3, effect1.get());
-    RefPtr<EffectPaintPropertyNode> effect3 = EffectPaintPropertyNode::create(0.2, dummyRootEffect());
+    RefPtr<EffectPaintPropertyNode> effect1 = EffectPaintPropertyNode::create(dummyRootEffect(), 0.5);
+    RefPtr<EffectPaintPropertyNode> effect2 = EffectPaintPropertyNode::create(effect1, 0.3);
+    RefPtr<EffectPaintPropertyNode> effect3 = EffectPaintPropertyNode::create(dummyRootEffect(), 0.2);
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, nullptr, effect2.get())
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h
index 943de30..2cabc7b 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/ClipPaintPropertyNode.h
@@ -17,16 +17,23 @@
 namespace blink {
 
 // A clip rect created by a css property such as "overflow" or "clip".
-// Along with a refernce to the transform space the clip rect is based on,
+// Along with a reference to the transform space the clip rect is based on,
 // and an (optional) parent ClipPaintPropertyNode for inherited clips.
 class PLATFORM_EXPORT ClipPaintPropertyNode : public RefCounted<ClipPaintPropertyNode> {
 public:
     static PassRefPtr<ClipPaintPropertyNode> create(
+        PassRefPtr<ClipPaintPropertyNode> parent,
         PassRefPtr<TransformPaintPropertyNode> localTransformSpace,
-        const FloatRoundedRect& clipRect,
-        PassRefPtr<ClipPaintPropertyNode> parent = nullptr)
+        const FloatRoundedRect& clipRect)
     {
-        return adoptRef(new ClipPaintPropertyNode(localTransformSpace, clipRect, parent));
+        return adoptRef(new ClipPaintPropertyNode(parent, localTransformSpace, clipRect));
+    }
+
+    void update(PassRefPtr<ClipPaintPropertyNode> parent, PassRefPtr<TransformPaintPropertyNode> localTransformSpace, const FloatRoundedRect& clipRect)
+    {
+        m_parent = parent;
+        m_localTransformSpace = localTransformSpace;
+        m_clipRect = clipRect;
     }
 
     const TransformPaintPropertyNode* localTransformSpace() const { return m_localTransformSpace.get(); }
@@ -36,12 +43,12 @@
     const ClipPaintPropertyNode* parent() const { return m_parent.get(); }
 
 private:
-    ClipPaintPropertyNode(PassRefPtr<TransformPaintPropertyNode> localTransformSpace, const FloatRoundedRect& clipRect, PassRefPtr<ClipPaintPropertyNode> parent)
-        : m_localTransformSpace(localTransformSpace), m_clipRect(clipRect), m_parent(parent) { }
+    ClipPaintPropertyNode(PassRefPtr<ClipPaintPropertyNode> parent, PassRefPtr<TransformPaintPropertyNode> localTransformSpace, const FloatRoundedRect& clipRect)
+        : m_parent(parent), m_localTransformSpace(localTransformSpace), m_clipRect(clipRect) { }
 
-    RefPtr<TransformPaintPropertyNode> m_localTransformSpace;
-    const FloatRoundedRect m_clipRect;
     RefPtr<ClipPaintPropertyNode> m_parent;
+    RefPtr<TransformPaintPropertyNode> m_localTransformSpace;
+    FloatRoundedRect m_clipRect;
 };
 
 // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
index 46cf9c51..a143354f 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
@@ -19,9 +19,15 @@
 // TODO(pdr): Support more effects than just opacity.
 class PLATFORM_EXPORT EffectPaintPropertyNode : public RefCounted<EffectPaintPropertyNode> {
 public:
-    static PassRefPtr<EffectPaintPropertyNode> create(float opacity, PassRefPtr<EffectPaintPropertyNode> parent = nullptr)
+    static PassRefPtr<EffectPaintPropertyNode> create(PassRefPtr<EffectPaintPropertyNode> parent, float opacity)
     {
-        return adoptRef(new EffectPaintPropertyNode(opacity, parent));
+        return adoptRef(new EffectPaintPropertyNode(parent, opacity));
+    }
+
+    void update(PassRefPtr<EffectPaintPropertyNode> parent, float opacity)
+    {
+        m_parent = parent;
+        m_opacity = opacity;
     }
 
     float opacity() const { return m_opacity; }
@@ -30,11 +36,11 @@
     const EffectPaintPropertyNode* parent() const { return m_parent.get(); }
 
 private:
-    EffectPaintPropertyNode(float opacity, PassRefPtr<EffectPaintPropertyNode> parent)
-        : m_opacity(opacity), m_parent(parent) { }
+    EffectPaintPropertyNode(PassRefPtr<EffectPaintPropertyNode> parent, float opacity)
+        : m_parent(parent), m_opacity(opacity) { }
 
-    const float m_opacity;
     RefPtr<EffectPaintPropertyNode> m_parent;
+    float m_opacity;
 };
 
 // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index 3daa150..6003d402 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -35,9 +35,9 @@
 private:
     void SetUp() override
     {
-        rootTransformNode = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr);
-        rootClipNode = ClipPaintPropertyNode::create(rootTransformNode, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr);
-        rootEffectNode = EffectPaintPropertyNode::create(1.0, nullptr);
+        rootTransformNode = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(), FloatPoint3D());
+        rootClipNode = ClipPaintPropertyNode::create(nullptr, rootTransformNode, FloatRoundedRect(LayoutRect::infiniteIntRect()));
+        rootEffectNode = EffectPaintPropertyNode::create(nullptr, 1.0);
         geometryMapper = wrapUnique(new GeometryMapper());
     }
 
@@ -80,7 +80,7 @@
 
 TEST_F(GeometryMapperTest, IdentityTransform)
 {
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, TransformationMatrix(), FloatPoint3D());
     PropertyTreeState localState = rootPropertyTreeState();
     localState.transform = transform.get();
 
@@ -93,7 +93,7 @@
 {
     TransformationMatrix transformMatrix;
     transformMatrix.translate(20, 10);
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(transformMatrix, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, transformMatrix, FloatPoint3D());
     PropertyTreeState localState = rootPropertyTreeState();
     localState.transform = transform.get();
 
@@ -113,7 +113,7 @@
     TransformationMatrix transformMatrix;
     transformMatrix.rotate(45);
     transformMatrix.scale(2);
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(transformMatrix, FloatPoint3D(0, 0, 0), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, transformMatrix, FloatPoint3D(0, 0, 0));
     PropertyTreeState localState = rootPropertyTreeState();
     localState.transform = transform.get();
 
@@ -128,7 +128,7 @@
     TransformationMatrix transformMatrix;
     transformMatrix.rotate(45);
     transformMatrix.scale(2);
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(transformMatrix, FloatPoint3D(50, 50, 0), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, transformMatrix, FloatPoint3D(50, 50, 0));
     PropertyTreeState localState = rootPropertyTreeState();
     localState.transform = transform.get();
 
@@ -143,11 +143,11 @@
 {
     TransformationMatrix rotateTransform;
     rotateTransform.rotate(45);
-    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform, FloatPoint3D());
 
     TransformationMatrix scaleTransform;
     scaleTransform.scale(2);
-    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(scaleTransform, FloatPoint3D(), transform1);
+    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(transform1, scaleTransform, FloatPoint3D());
 
     PropertyTreeState localState = rootPropertyTreeState();
     localState.transform = transform2.get();
@@ -166,11 +166,11 @@
 {
     TransformationMatrix rotateTransform;
     rotateTransform.rotate(45);
-    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform, FloatPoint3D());
 
     TransformationMatrix scaleTransform;
     scaleTransform.scale(2);
-    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(scaleTransform, FloatPoint3D(), transform1);
+    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(transform1, scaleTransform, FloatPoint3D());
 
     PropertyTreeState localState = rootPropertyTreeState();
     localState.transform = transform2.get();
@@ -186,7 +186,7 @@
 
 TEST_F(GeometryMapperTest, SimpleClip)
 {
-    RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootTransformNode, FloatRoundedRect(10, 10, 50, 50), rootClipNode);
+    RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootClipNode, rootTransformNode, FloatRoundedRect(10, 10, 50, 50));
 
     PropertyTreeState localState = rootPropertyTreeState();
     localState.clip = clip.get();
@@ -207,9 +207,9 @@
 {
     TransformationMatrix rotateTransform;
     rotateTransform.rotate(45);
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform, FloatPoint3D());
 
-    RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(transform.get(), FloatRoundedRect(10, 10, 50, 50), rootClipNode);
+    RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootClipNode, transform.get(), FloatRoundedRect(10, 10, 50, 50));
 
     PropertyTreeState localState = rootPropertyTreeState();
     localState.clip = clip.get();
@@ -233,9 +233,9 @@
 {
     TransformationMatrix rotateTransform;
     rotateTransform.rotate(45);
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform, FloatPoint3D());
 
-    RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootTransformNode.get(), FloatRoundedRect(10, 10, 200, 200), rootClipNode);
+    RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create(rootClipNode, rootTransformNode.get(), FloatRoundedRect(10, 10, 200, 200));
 
     PropertyTreeState localState = rootPropertyTreeState();
     localState.clip = clip.get();
@@ -257,13 +257,13 @@
 
 TEST_F(GeometryMapperTest, TwoClipsWithTransformBetween)
 {
-    RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(rootTransformNode.get(), FloatRoundedRect(10, 10, 200, 200), rootClipNode);
+    RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(rootClipNode, rootTransformNode.get(), FloatRoundedRect(10, 10, 200, 200));
 
     TransformationMatrix rotateTransform;
     rotateTransform.rotate(45);
-    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rotateTransform, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform, FloatPoint3D());
 
-    RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(transform.get(), FloatRoundedRect(10, 10, 200, 200), clip1.get());
+    RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(clip1, transform.get(), FloatRoundedRect(10, 10, 200, 200));
 
     FloatRect input(0, 0, 100, 100);
 
@@ -317,11 +317,11 @@
     // These transforms are siblings. Thus mapping from one to the other requires going through the root.
     TransformationMatrix rotateTransform1;
     rotateTransform1.rotate(45);
-    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(rotateTransform1, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform1, FloatPoint3D());
 
     TransformationMatrix rotateTransform2;
     rotateTransform2.rotate(-45);
-    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(rotateTransform2, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, rotateTransform2, FloatPoint3D());
 
     PropertyTreeState transform1State = rootPropertyTreeState();
     transform1State.transform = transform1;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp
index 7a01b94..8c6397d0 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintArtifactToSkCanvasTest.cpp
@@ -120,10 +120,10 @@
     TransformationMatrix matrix1;
     matrix1.scale(2);
     FloatPoint3D origin1(10, 10, 0);
-    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(matrix1, origin1);
+    RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(nullptr, matrix1, origin1);
     TransformationMatrix matrix2;
     matrix2.translate(5, 5);
-    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(matrix2, FloatPoint3D(), transform1.get());
+    RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::create(transform1, matrix2, FloatPoint3D());
 
     TestPaintArtifact artifact;
     artifact.chunk(transform1.get(), nullptr, nullptr)
@@ -147,8 +147,8 @@
     }
 
     // Build an opacity effect tree.
-    RefPtr<EffectPaintPropertyNode> opacityEffect1 = EffectPaintPropertyNode::create(0.5);
-    RefPtr<EffectPaintPropertyNode> opacityEffect2 = EffectPaintPropertyNode::create(0.25, opacityEffect1);
+    RefPtr<EffectPaintPropertyNode> opacityEffect1 = EffectPaintPropertyNode::create(nullptr, 0.5);
+    RefPtr<EffectPaintPropertyNode> opacityEffect2 = EffectPaintPropertyNode::create(opacityEffect1, 0.25);
 
     TestPaintArtifact artifact;
     artifact.chunk(nullptr, nullptr, opacityEffect1.get())
@@ -181,10 +181,10 @@
     // 0.1  a      c  0.3
     //      |      |
     // 0.2  b      d  0.4
-    RefPtr<EffectPaintPropertyNode> opacityEffectA = EffectPaintPropertyNode::create(0.1);
-    RefPtr<EffectPaintPropertyNode> opacityEffectB = EffectPaintPropertyNode::create(0.2, opacityEffectA);
-    RefPtr<EffectPaintPropertyNode> opacityEffectC = EffectPaintPropertyNode::create(0.3);
-    RefPtr<EffectPaintPropertyNode> opacityEffectD = EffectPaintPropertyNode::create(0.4, opacityEffectC);
+    RefPtr<EffectPaintPropertyNode> opacityEffectA = EffectPaintPropertyNode::create(nullptr, 0.1);
+    RefPtr<EffectPaintPropertyNode> opacityEffectB = EffectPaintPropertyNode::create(opacityEffectA, 0.2);
+    RefPtr<EffectPaintPropertyNode> opacityEffectC = EffectPaintPropertyNode::create(nullptr, 0.3);
+    RefPtr<EffectPaintPropertyNode> opacityEffectD = EffectPaintPropertyNode::create(opacityEffectC, 0.4);
 
     // Build a two-chunk artifact directly.
     // chunk1 references opacity node b, chunk2 references opacity node d.
@@ -220,13 +220,13 @@
 
     // Setup transform tree.
     RefPtr<TransformPaintPropertyNode> transform1 = TransformPaintPropertyNode::create(
-        TransformationMatrix().translate(0, -100), FloatPoint3D());
+        nullptr, TransformationMatrix().translate(0, -100), FloatPoint3D());
 
     // Setup clip tree.
     RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create(
-        transform1.get(), FloatRoundedRect(100, 200, 100, 100));
+        nullptr, transform1.get(), FloatRoundedRect(100, 200, 100, 100));
     RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create(
-        nullptr, FloatRoundedRect(150, 150, 100, 100), clip1.get());
+        clip1, nullptr, FloatRoundedRect(150, 150, 100, 100));
 
     MockCanvas canvas(kCanvasWidth, kCanvasHeight);
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
index 6463eb2..a4301ee1 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkerTest.cpp
@@ -108,13 +108,13 @@
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransform;
-    simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+    simpleTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
 
     chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties anotherTransform;
-    anotherTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+    anotherTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
     chunker.updateCurrentPaintChunkProperties(nullptr, anotherTransform);
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
@@ -133,21 +133,21 @@
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransform;
-    simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
+    simpleTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
     chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransformAndEffect;
     simpleTransformAndEffect.transform = simpleTransform.transform;
-    simpleTransformAndEffect.effect = EffectPaintPropertyNode::create(0.5f);
+    simpleTransformAndEffect.effect = EffectPaintPropertyNode::create(nullptr, 0.5f);
     chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransformAndEffect);
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransformAndEffectWithUpdatedTransform;
-    simpleTransformAndEffectWithUpdatedTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(1, 1, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
-    simpleTransformAndEffectWithUpdatedTransform.effect = EffectPaintPropertyNode::create(simpleTransformAndEffect.effect->opacity());
+    simpleTransformAndEffectWithUpdatedTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(1, 1, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
+    simpleTransformAndEffectWithUpdatedTransform.effect = EffectPaintPropertyNode::create(nullptr, simpleTransformAndEffect.effect->opacity());
     chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransformAndEffectWithUpdatedTransform);
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
@@ -177,7 +177,7 @@
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransform;
-    simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+    simpleTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
     chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
@@ -201,11 +201,11 @@
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties firstTransform;
-    firstTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+    firstTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
     chunker.updateCurrentPaintChunkProperties(nullptr, firstTransform);
 
     PaintChunkProperties secondTransform;
-    secondTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
+    secondTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
     chunker.updateCurrentPaintChunkProperties(nullptr, secondTransform);
 
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
@@ -263,7 +263,7 @@
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransform;
-    simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+    simpleTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
     chunker.updateCurrentPaintChunkProperties(&id1, simpleTransform);
 
     chunker.incrementDisplayItemIndex(i1);
@@ -296,7 +296,7 @@
     chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
 
     PaintChunkProperties simpleTransform;
-    simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+    simpleTransform.transform = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
     chunker.updateCurrentPaintChunkProperties(&id1, simpleTransform);
 
     chunker.incrementDisplayItemIndex(i1);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
index 0093ebef..d816a4e 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
@@ -27,20 +27,20 @@
 private:
     void SetUp() override
     {
-        rootTransformNode = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr);
-        rootClipNode = ClipPaintPropertyNode::create(rootTransformNode, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr);
-        rootEffectNode = EffectPaintPropertyNode::create(1.0, nullptr);
+        rootTransformNode = TransformPaintPropertyNode::create(nullptr, TransformationMatrix(), FloatPoint3D());
+        rootClipNode = ClipPaintPropertyNode::create(nullptr, rootTransformNode, FloatRoundedRect(LayoutRect::infiniteIntRect()));
+        rootEffectNode = EffectPaintPropertyNode::create(nullptr, 1.0);
     }
 };
 
 TEST_F(PropertyTreeStateTest, LeastCommonAncestor)
 {
     TransformationMatrix matrix;
-    RefPtr<TransformPaintPropertyNode> child1 = TransformPaintPropertyNode::create(matrix, FloatPoint3D(), rootPropertyTreeState().transform);
-    RefPtr<TransformPaintPropertyNode> child2 = TransformPaintPropertyNode::create(matrix, FloatPoint3D(), rootPropertyTreeState().transform);
+    RefPtr<TransformPaintPropertyNode> child1 = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, matrix, FloatPoint3D());
+    RefPtr<TransformPaintPropertyNode> child2 = TransformPaintPropertyNode::create(rootPropertyTreeState().transform, matrix, FloatPoint3D());
 
-    RefPtr<TransformPaintPropertyNode> childOfChild1 = TransformPaintPropertyNode::create(matrix, FloatPoint3D(), child1);
-    RefPtr<TransformPaintPropertyNode> childOfChild2 = TransformPaintPropertyNode::create(matrix, FloatPoint3D(), child2);
+    RefPtr<TransformPaintPropertyNode> childOfChild1 = TransformPaintPropertyNode::create(child1, matrix, FloatPoint3D());
+    RefPtr<TransformPaintPropertyNode> childOfChild2 = TransformPaintPropertyNode::create(child2, matrix, FloatPoint3D());
 
     EXPECT_EQ(rootPropertyTreeState().transform, propertyTreeNearestCommonAncestor<TransformPaintPropertyNode>(childOfChild1.get(), childOfChild2.get()));
     EXPECT_EQ(rootPropertyTreeState().transform, propertyTreeNearestCommonAncestor<TransformPaintPropertyNode>(childOfChild1.get(), child2.get()));
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
index 0398008..1481e60 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -21,9 +21,16 @@
 // for the root.
 class PLATFORM_EXPORT TransformPaintPropertyNode : public RefCounted<TransformPaintPropertyNode> {
 public:
-    static PassRefPtr<TransformPaintPropertyNode> create(const TransformationMatrix& matrix, const FloatPoint3D& origin, PassRefPtr<TransformPaintPropertyNode> parent = nullptr)
+    static PassRefPtr<TransformPaintPropertyNode> create(PassRefPtr<TransformPaintPropertyNode> parent, const TransformationMatrix& matrix, const FloatPoint3D& origin)
     {
-        return adoptRef(new TransformPaintPropertyNode(matrix, origin, parent));
+        return adoptRef(new TransformPaintPropertyNode(parent, matrix, origin));
+    }
+
+    void update(PassRefPtr<TransformPaintPropertyNode> parent, const TransformationMatrix& matrix, const FloatPoint3D& origin)
+    {
+        m_parent = parent;
+        m_matrix = matrix;
+        m_origin = origin;
     }
 
     const TransformationMatrix& matrix() const { return m_matrix; }
@@ -34,13 +41,12 @@
     TransformPaintPropertyNode* parent() const { return m_parent.get(); }
 
 private:
+    TransformPaintPropertyNode(PassRefPtr<TransformPaintPropertyNode> parent, const TransformationMatrix& matrix, const FloatPoint3D& origin)
+        : m_parent(parent), m_matrix(matrix), m_origin(origin) { }
 
-    TransformPaintPropertyNode(const TransformationMatrix& matrix, const FloatPoint3D& origin, PassRefPtr<TransformPaintPropertyNode> parent)
-        : m_matrix(matrix), m_origin(origin), m_parent(parent) { }
-
-    const TransformationMatrix m_matrix;
-    const FloatPoint3D m_origin;
     RefPtr<TransformPaintPropertyNode> m_parent;
+    TransformationMatrix m_matrix;
+    FloatPoint3D m_origin;
 };
 
 // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm
index e148eca..1fe3d76 100644
--- a/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm
+++ b/third_party/WebKit/Source/platform/mac/ScrollAnimatorMac.mm
@@ -683,7 +683,7 @@
     : ScrollAnimatorBase(scrollableArea)
     , m_initialScrollbarPaintTaskFactory(CancellableTaskFactory::create(this, &ScrollAnimatorMac::initialScrollbarPaintTask))
     , m_sendContentAreaScrolledTaskFactory(CancellableTaskFactory::create(this, &ScrollAnimatorMac::sendContentAreaScrolledTask))
-    , m_taskRunner(wrapUnique(Platform::current()->currentThread()->scheduler()->timerTaskRunner()->clone()))
+    , m_taskRunner(Platform::current()->currentThread()->scheduler()->timerTaskRunner()->clone())
     , m_haveScrolledSincePageLoad(false)
     , m_needsScrollerStyleUpdate(false)
 {
diff --git a/third_party/WebKit/Source/platform/mojo/blink_typemaps.gni b/third_party/WebKit/Source/platform/mojo/blink_typemaps.gni
index e5f50b0..0d07bc8 100644
--- a/third_party/WebKit/Source/platform/mojo/blink_typemaps.gni
+++ b/third_party/WebKit/Source/platform/mojo/blink_typemaps.gni
@@ -5,6 +5,4 @@
 typemaps = [
   "//third_party/WebKit/Source/platform/mojo/KURL.typemap",
   "//third_party/WebKit/Source/platform/mojo/SecurityOrigin.typemap",
-  "//cc/ipc/surface_id.typemap",
-  "//cc/ipc/surface_sequence.typemap",
 ]
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
index 34ec0bc..528f9e3 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
@@ -90,9 +90,9 @@
         return true;
     }
 
-    WebTaskRunner* clone() override
+    std::unique_ptr<WebTaskRunner> clone() override
     {
-        return new TestingPlatformMockWebTaskRunner(m_tasks);
+        return WTF::wrapUnique(new TestingPlatformMockWebTaskRunner(m_tasks));
     }
 
     double virtualTimeSeconds() const override
diff --git a/third_party/WebKit/Source/platform/text/ParserUtilities.h b/third_party/WebKit/Source/platform/text/ParserUtilities.h
deleted file mode 100644
index 074a0a84..0000000
--- a/third_party/WebKit/Source/platform/text/ParserUtilities.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- * Copyright (C) 2002, 2003 The Karbon Developers
- * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef ParserUtilities_h
-#define ParserUtilities_h
-
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-
-template<typename CharType>
-inline bool skipString(const CharType*& ptr, const CharType* end, const CharType* name, int length)
-{
-    if (end - ptr < length)
-        return false;
-    if (memcmp(name, ptr, sizeof(CharType) * length))
-        return false;
-    ptr += length;
-    return true;
-}
-
-inline bool skipString(const UChar*& ptr, const UChar* end, const LChar* name, int length)
-{
-    if (end - ptr < length)
-        return false;
-    for (int i = 0; i < length; ++i) {
-        if (ptr[i] != name[i])
-            return false;
-    }
-    ptr += length;
-    return true;
-}
-
-template<typename CharType>
-inline bool skipString(const CharType*& ptr, const CharType* end, const char* str)
-{
-    int length = strlen(str);
-    if (end - ptr < length)
-        return false;
-    for (int i = 0; i < length; ++i) {
-        if (ptr[i] != str[i])
-            return false;
-    }
-    ptr += length;
-    return true;
-}
-
-} // namespace blink
-
-#endif // ParserUtilities_h
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp
index 0761f87..719f982 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp
@@ -13,6 +13,9 @@
 
 #include <vector>
 
+#define ENSURE_V8_VERSION(major, minor) \
+    (V8_MAJOR_VERSION * 1000 + V8_MINOR_VERSION >= (major) * 1000 + (minor))
+
 namespace blink {
 
 namespace ProfilerAgentState {
@@ -128,6 +131,7 @@
 V8ProfilerAgentImpl::V8ProfilerAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state)
     : m_session(session)
     , m_isolate(m_session->debugger()->isolate())
+    , m_profiler(nullptr)
     , m_state(state)
     , m_frontend(frontendChannel)
     , m_enabled(false)
@@ -137,6 +141,10 @@
 
 V8ProfilerAgentImpl::~V8ProfilerAgentImpl()
 {
+#if ENSURE_V8_VERSION(5, 4)
+    if (m_profiler)
+        m_profiler->Dispose();
+#endif
 }
 
 void V8ProfilerAgentImpl::consoleProfile(const String16& title)
@@ -186,6 +194,10 @@
     if (m_enabled)
         return;
     m_enabled = true;
+#if ENSURE_V8_VERSION(5, 4)
+    DCHECK(!m_profiler);
+    m_profiler = v8::CpuProfiler::New(m_isolate);
+#endif
     m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
 }
 
@@ -197,6 +209,10 @@
         stopProfiling(m_startedProfiles[i - 1].m_id, false);
     m_startedProfiles.clear();
     stop(nullptr, nullptr);
+#if ENSURE_V8_VERSION(5, 4)
+    m_profiler->Dispose();
+    m_profiler = nullptr;
+#endif
     m_enabled = false;
     m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
 }
@@ -208,7 +224,7 @@
         return;
     }
     m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
-    m_isolate->GetCpuProfiler()->SetSamplingInterval(interval);
+    profiler()->SetSamplingInterval(interval);
 }
 
 void V8ProfilerAgentImpl::restore()
@@ -217,10 +233,14 @@
     if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false))
         return;
     m_enabled = true;
+#if ENSURE_V8_VERSION(5, 4)
+    DCHECK(!m_profiler);
+    m_profiler = v8::CpuProfiler::New(m_isolate);
+#endif
     int interval = 0;
     m_state->getInteger(ProfilerAgentState::samplingInterval, &interval);
     if (interval)
-        m_isolate->GetCpuProfiler()->SetSamplingInterval(interval);
+        profiler()->SetSamplingInterval(interval);
     if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling, false)) {
         ErrorString error;
         start(&error);
@@ -269,13 +289,13 @@
 void V8ProfilerAgentImpl::startProfiling(const String16& title)
 {
     v8::HandleScope handleScope(m_isolate);
-    m_isolate->GetCpuProfiler()->StartProfiling(toV8String(m_isolate, title), true);
+    profiler()->StartProfiling(toV8String(m_isolate, title), true);
 }
 
 std::unique_ptr<protocol::Profiler::CPUProfile> V8ProfilerAgentImpl::stopProfiling(const String16& title, bool serialize)
 {
     v8::HandleScope handleScope(m_isolate);
-    v8::CpuProfile* profile = m_isolate->GetCpuProfiler()->StopProfiling(toV8String(m_isolate, title));
+    v8::CpuProfile* profile = profiler()->StopProfiling(toV8String(m_isolate, title));
     if (!profile)
         return nullptr;
     std::unique_ptr<protocol::Profiler::CPUProfile> result;
@@ -290,4 +310,13 @@
     return m_recordingCPUProfile || !m_startedProfiles.empty();
 }
 
+v8::CpuProfiler* V8ProfilerAgentImpl::profiler()
+{
+#if ENSURE_V8_VERSION(5, 4)
+    return m_profiler;
+#else
+    return m_isolate->GetCpuProfiler();
+#endif
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.h
index 03b8f70..4bbe00be6 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 namespace v8 {
+class CpuProfiler;
 class Isolate;
 }
 
@@ -39,6 +40,7 @@
 
 private:
     String16 nextProfileId();
+    v8::CpuProfiler* profiler();
 
     void startProfiling(const String16& title);
     std::unique_ptr<protocol::Profiler::CPUProfile> stopProfiling(const String16& title, bool serialize);
@@ -47,6 +49,7 @@
 
     V8InspectorSessionImpl* m_session;
     v8::Isolate* m_isolate;
+    v8::CpuProfiler* m_profiler;
     protocol::DictionaryValue* m_state;
     protocol::Profiler::Frontend m_frontend;
     bool m_enabled;
@@ -58,5 +61,4 @@
 
 } // namespace blink
 
-
 #endif // !defined(V8ProfilerAgentImpl_h)
diff --git a/third_party/WebKit/Source/web/TextFinder.cpp b/third_party/WebKit/Source/web/TextFinder.cpp
index 8ed0892..b3e0c3ca 100644
--- a/third_party/WebKit/Source/web/TextFinder.cpp
+++ b/third_party/WebKit/Source/web/TextFinder.cpp
@@ -114,9 +114,6 @@
 
 bool TextFinder::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect, bool* activeNow)
 {
-    if (!ownerFrame().frame() || !ownerFrame().frame()->page())
-        return false;
-
     if (!options.findNext)
         unmarkAllTextMatches();
     else
@@ -252,6 +249,8 @@
 
 void TextFinder::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset)
 {
+    // TODO(dglazkov): The reset/continue cases need to be untangled into two separate functions. This collation of logic
+    // is unnecessary and adds to overall complexity of the code.
     if (reset) {
         // This is a brand new search, so we need to reset everything.
         // Scoping is just about to begin.
@@ -300,6 +299,10 @@
             return;
     }
 
+    // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
+    // see http://crbug.com/590369 for more details.
+    searchStart.document()->updateStyleAndLayoutIgnorePendingStylesheets();
+
     // This timeout controls how long we scope before releasing control. This
     // value does not prevent us from running for longer than this, but it is
     // periodically checked to see if we have exceeded our allocated time.
diff --git a/third_party/WebKit/Source/web/WebElement.cpp b/third_party/WebKit/Source/web/WebElement.cpp
index 13db3d81..cbc2b52 100644
--- a/third_party/WebKit/Source/web/WebElement.cpp
+++ b/third_party/WebKit/Source/web/WebElement.cpp
@@ -61,7 +61,7 @@
 {
     const Element* element = constUnwrap<Element>();
 
-    if (element->isContentEditable())
+    if (blink::isContentEditable(*element))
         return true;
 
     if (element->isTextFormControl()) {
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index c1fb533..be708ee3 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -460,7 +460,7 @@
                 // no caret and does respond to keyboard inputs.
                 if (element->isTextFormControl()) {
                     element->updateFocusAppearance(SelectionBehaviorOnFocus::Restore);
-                } else if (element->isContentEditable()) {
+                } else if (isContentEditable(*element)) {
                     // updateFocusAppearance() selects all the text of
                     // contentseditable DIVs. So we set the selection explicitly
                     // instead. Note that this has the side effect of moving the
@@ -517,7 +517,7 @@
     const EphemeralRange range = inputMethodController.compositionEphemeralRange();
     if (range.isNotNull()) {
         Node* node = range.startPosition().computeContainerNode();
-        if (!node || !node->isContentEditable())
+        if (!node || !isContentEditable(*node))
             return false;
     }
 
@@ -715,7 +715,7 @@
             return WebTextInputTypeDateTimeField;
     }
 
-    if (element->isContentEditable())
+    if (isContentEditable(*element))
         return WebTextInputTypeContentEditable;
 
     return WebTextInputTypeNone;
diff --git a/third_party/WebKit/Source/web/WebInputEvent.cpp b/third_party/WebKit/Source/web/WebInputEvent.cpp
index bf8e4db..5c195d06 100644
--- a/third_party/WebKit/Source/web/WebInputEvent.cpp
+++ b/third_party/WebKit/Source/web/WebInputEvent.cpp
@@ -59,7 +59,7 @@
 };
 
 struct SameSizeAsWebTouchEvent : public SameSizeAsWebInputEvent {
-    WebTouchPoint touchPoints[WebTouchEvent::touchesLengthCap];
+    WebTouchPoint touchPoints[WebTouchEvent::kTouchesLengthCap];
     int touchData[4];
 };
 
diff --git a/third_party/WebKit/Source/web/WebInputEventConversion.cpp b/third_party/WebKit/Source/web/WebInputEventConversion.cpp
index db569d1..d07463b7 100644
--- a/third_party/WebKit/Source/web/WebInputEventConversion.cpp
+++ b/third_party/WebKit/Source/web/WebInputEventConversion.cpp
@@ -718,7 +718,7 @@
     unsigned initialTouchPointsLength = *touchPointsLength;
     for (unsigned i = 0; i < touches->length(); ++i) {
         const unsigned pointIndex = *touchPointsLength;
-        if (pointIndex >= static_cast<unsigned>(WebTouchEvent::touchesLengthCap))
+        if (pointIndex >= static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap))
             return;
 
         const Touch* touch = touches->item(i);
@@ -754,7 +754,7 @@
     movedBeyondSlopRegion = event.causesScrollingIfUncanceled();
 
     // Currently touches[] is empty, add stationary points as-is.
-    for (unsigned i = 0; i < event.touches()->length() && i < static_cast<unsigned>(WebTouchEvent::touchesLengthCap); ++i) {
+    for (unsigned i = 0; i < event.touches()->length() && i < static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap); ++i) {
         touches[i] = toWebTouchPoint(event.touches()->item(i), layoutItem, WebTouchPoint::StateStationary);
         ++touchesLength;
     }
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index 75ed977..6fc3d8e 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1962,12 +1962,22 @@
 
 bool WebLocalFrameImpl::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect, bool* activeNow)
 {
+    if (!frame())
+        return false;
+
+    // Unlikely, but just in case we try to find-in-page on a detached frame.
+    DCHECK(frame()->host());
+
     // Search for an active match only if this frame is focused or if this is a
     // find next request.
-    if (isFocused() || options.findNext)
-        return ensureTextFinder().find(identifier, searchText, options, wrapWithinFrame, selectionRect, activeNow);
+    if (!isFocused() && !options.findNext)
+        return false;
 
-    return false;
+    // Up-to-date, clean tree is required for finding text in page, since it relies
+    // on TextIterator to look over the text.
+    frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();
+
+    return ensureTextFinder().find(identifier, searchText, options, wrapWithinFrame, selectionRect, activeNow);
 }
 
 void WebLocalFrameImpl::stopFinding(StopFindAction action)
diff --git a/third_party/WebKit/Source/web/WebNode.cpp b/third_party/WebKit/Source/web/WebNode.cpp
index 60933df..44ef00b95 100644
--- a/third_party/WebKit/Source/web/WebNode.cpp
+++ b/third_party/WebKit/Source/web/WebNode.cpp
@@ -171,7 +171,7 @@
 
 bool WebNode::isContentEditable() const
 {
-    return m_private->isContentEditable();
+    return blink::isContentEditable(*m_private);
 }
 
 bool WebNode::isInsideFocusableElementOrARIAWidget() const
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
index 36b72dcf..90a8c5e 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -121,7 +121,7 @@
 
     void scheduleAnimation(Widget*) override
     {
-        // Calling scheduleAnimation on m_webView so WebTestProxy will call beginFrame.
+        // Calling scheduleAnimation on m_webView so WebViewTestProxy will call beginFrame.
         if (LayoutTestSupport::isRunningLayoutTest())
             m_popup->m_webView->mainFrameImpl()->frameWidget()->scheduleAnimation();
 
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 575fd6d..fd50765a 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2275,7 +2275,7 @@
                 // no caret and does respond to keyboard inputs.
                 if (element->isTextFormControl()) {
                     element->updateFocusAppearance(SelectionBehaviorOnFocus::Restore);
-                } else if (element->isContentEditable()) {
+                } else if (isContentEditable(*element)) {
                     // updateFocusAppearance() selects all the text of
                     // contentseditable DIVs. So we set the selection explicitly
                     // instead. Note that this has the side effect of moving the
@@ -2344,7 +2344,7 @@
     const EphemeralRange range = inputMethodController.compositionEphemeralRange();
     if (range.isNotNull()) {
         Node* node = range.startPosition().computeContainerNode();
-        if (!node || !node->isContentEditable())
+        if (!node || !isContentEditable(*node))
             return false;
     }
 
@@ -2542,7 +2542,7 @@
             return WebTextInputTypeDateTimeField;
     }
 
-    if (element->isContentEditable())
+    if (isContentEditable(*element))
         return WebTextInputTypeContentEditable;
 
     return WebTextInputTypeNone;
@@ -2997,7 +2997,7 @@
     // knows to remove selection from it. Otherwise, the text field is still
     // processing keyboard events even though focus has been moved to the page and
     // keystrokes get eaten as a result.
-    if (oldFocusedElement->isContentEditable() || oldFocusedElement->isTextFormControl())
+    if (isContentEditable(*oldFocusedElement) || oldFocusedElement->isTextFormControl())
         localFrame->selection().clear();
 }
 
@@ -3005,7 +3005,7 @@
 // http://crbug.com/612560
 static bool isElementEditable(const Element* element)
 {
-    if (element->isContentEditable())
+    if (isContentEditable(*element))
         return true;
 
     if (element->isTextFormControl()) {
diff --git a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
index c40f851..9bce1b51 100644
--- a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
+++ b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
@@ -10,6 +10,7 @@
 #include "core/dom/Range.h"
 #include "core/dom/shadow/ShadowRoot.h"
 #include "core/frame/FrameHost.h"
+#include "core/frame/FrameView.h"
 #include "core/frame/VisualViewport.h"
 #include "core/html/HTMLElement.h"
 #include "core/layout/TextAutosizer.h"
@@ -69,6 +70,7 @@
 TEST_F(TextFinderTest, FindTextSimple)
 {
     document().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
     Node* textNode = document().body()->firstChild();
 
     int identifier = 0;
@@ -138,6 +140,7 @@
 TEST_F(TextFinderTest, FindTextAutosizing)
 {
     document().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
 
     int identifier = 0;
     WebString searchText(String("FindMe"));
@@ -153,6 +156,7 @@
     document().settings()->setTextAutosizingEnabled(true);
     document().settings()->setTextAutosizingWindowSizeOverride(IntSize(20, 20));
     document().textAutosizer()->updatePageInfo();
+    document().updateStyleAndLayout();
 
     // In case of autosizing, scale _should_ change
     ASSERT_TRUE(textFinder().find(identifier, searchText, findOptions, wrapWithinFrame, selectionRect));
@@ -163,6 +167,7 @@
     visualViewport.setScale(20);
     document().settings()->setTextAutosizingEnabled(false);
     document().textAutosizer()->updatePageInfo();
+    document().updateStyleAndLayout();
 
     ASSERT_TRUE(textFinder().find(identifier, searchText, findOptions, wrapWithinFrame, selectionRect));
     ASSERT_TRUE(textFinder().activeMatch());
@@ -172,6 +177,7 @@
 TEST_F(TextFinderTest, FindTextNotFound)
 {
     document().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
 
     int identifier = 0;
     WebString searchText(String("Boo"));
@@ -191,6 +197,7 @@
     Node* textInBElement = document().body()->firstChild()->firstChild();
     Node* textInIElement = document().body()->lastChild()->firstChild();
     Node* textInUElement = shadowRoot->childNodes()->item(1)->firstChild();
+    document().updateStyleAndLayout();
 
     int identifier = 0;
     WebString searchText(String("foo"));
@@ -278,6 +285,8 @@
 TEST_F(TextFinderTest, ScopeTextMatchesSimple)
 {
     document().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
+
     Node* textNode = document().body()->firstChild();
 
     int identifier = 0;
@@ -305,6 +314,7 @@
     Node* textInBElement = document().body()->firstChild()->firstChild();
     Node* textInIElement = document().body()->lastChild()->firstChild();
     Node* textInUElement = shadowRoot->childNodes()->item(1)->firstChild();
+    document().updateStyleAndLayout();
 
     int identifier = 0;
     WebString searchText(String("fOO"));
@@ -330,6 +340,8 @@
 TEST_F(TextFinderTest, ScopeRepeatPatternTextMatches)
 {
     document().body()->setInnerHTML("ab ab ab ab ab", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
+
     Node* textNode = document().body()->firstChild();
 
     int identifier = 0;
@@ -352,6 +364,8 @@
 TEST_F(TextFinderTest, OverlappingMatches)
 {
     document().body()->setInnerHTML("aababaa", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
+
     Node* textNode = document().body()->firstChild();
 
     int identifier = 0;
@@ -374,6 +388,8 @@
 TEST_F(TextFinderTest, SequentialMatches)
 {
     document().body()->setInnerHTML("ababab", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
+
     Node* textNode = document().body()->firstChild();
 
     int identifier = 0;
@@ -397,6 +413,7 @@
 TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOM)
 {
     document().body()->setInnerHTML("<b>XXXXFindMeYYYY</b><i></i>", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
 
     int identifier = 0;
     WebString searchText(String("FindMe"));
@@ -420,6 +437,7 @@
     Element* iElement = toElement(document().body()->lastChild());
     ASSERT_TRUE(iElement);
     iElement->setInnerHTML("ZZFindMe", ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
 
     ASSERT_TRUE(textFinder().find(identifier, searchText, findOptions, wrapWithinFrame, selectionRect, &activeNow));
     Range* activeMatch = textFinder().activeMatch();
@@ -485,6 +503,7 @@
     text.insert(searchPattern, 90);
 
     document().body()->setInnerHTML(text, ASSERT_NO_EXCEPTION);
+    document().updateStyleAndLayout();
 
     int identifier = 0;
     WebFindOptions findOptions; // Default.
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 3b224ef7..84f9eb1 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -5545,13 +5545,13 @@
     runPendingTasks();
     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
 
-    // Access the initial document by modifying the body. We normally set a
-    // timer to notify the client.
+    // Access the initial document by modifying the body.
     newView->mainFrame()->executeScript(
         WebScriptSource("window.opener.document.body.innerHTML += 'Modified';"));
-    EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
+    EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
 
-    // Make sure that a modal dialog forces us to notify right away.
+    // Run a modal dialog, which used to run a nested message loop and require
+    // a special case for notifying about the access.
     newView->mainFrame()->executeScript(
         WebScriptSource("window.opener.confirm('Modal');"));
     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
@@ -5585,13 +5585,13 @@
     EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
 
     // Access the initial document with document.write, which moves us past the
-    // initial empty document state of the state machine. We normally set a
-    // timer to notify the client.
+    // initial empty document state of the state machine.
     newView->mainFrame()->executeScript(
         WebScriptSource("window.opener.document.write('Modified'); window.opener.document.close();"));
-    EXPECT_FALSE(webFrameClient.m_didAccessInitialDocument);
+    EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
 
-    // Make sure that a modal dialog forces us to notify right away.
+    // Run a modal dialog, which used to run a nested message loop and require
+    // a special case for notifying about the access.
     newView->mainFrame()->executeScript(
         WebScriptSource("window.opener.confirm('Modal');"));
     EXPECT_TRUE(webFrameClient.m_didAccessInitialDocument);
diff --git a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
index 489aac8c..c9500412a 100644
--- a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
@@ -231,7 +231,7 @@
     {
         TouchList* touchList = TouchList::create();
         TouchList* changedTouchList = TouchList::create();
-        for (int i = 0; i <= static_cast<int>(WebTouchEvent::touchesLengthCap) * 2; ++i) {
+        for (int i = 0; i <= static_cast<int>(WebTouchEvent::kTouchesLengthCap) * 2; ++i) {
             Touch* touch = Touch::create(toLocalFrame(webViewImpl->page()->mainFrame()), document, i, p0.screenPosition, p0.position, FloatSize(p0.radiusX, p0.radiusY), p0.rotationAngle, p0.force, String());
             touchList->append(touch);
             changedTouchList->append(touch);
@@ -239,7 +239,7 @@
         TouchEvent* touchEvent = TouchEvent::create(touchList, touchList, touchList, EventTypeNames::touchstart, domWindow, PlatformEvent::NoModifiers, false, false, true, 0);
 
         WebTouchEventBuilder webTouchBuilder(documentLayoutView, *touchEvent);
-        ASSERT_EQ(static_cast<unsigned>(WebTouchEvent::touchesLengthCap), webTouchBuilder.touchesLength);
+        ASSERT_EQ(static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap), webTouchBuilder.touchesLength);
     }
 }
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py
index 88527011..f74cfec2 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py
@@ -230,11 +230,12 @@
         to LayoutTest/TestExpectations. Checks the file for the string
         '# Tests added from W3C auto import bot' and writes expectation
         lines directly under it. If not found, it writes to the end of
-        the file.
+        the file. If the test name is already in LayoutTests/TestExpectations,
+        the line will be skipped.
 
         Args:
             host: A Host object.
-            path: The path to the file LayoutTest/TestExpectations.
+            path: The path to the file LayoutTests/TestExpectations.
             line_list: A list of w3c test expectations lines.
 
         Returns:
@@ -245,6 +246,10 @@
         w3c_comment_line_index = file_contents.find(comment_line)
         all_lines = ''
         for line in line_list:
+            end_bracket_index = line.split().index(']')
+            test_name = line.split()[end_bracket_index + 1]
+            if test_name in file_contents:
+                continue
             all_lines += str(line) + '\n'
         all_lines = all_lines[:-1]
         if w3c_comment_line_index == -1:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
index d215849..7ae39f4 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
@@ -90,18 +90,28 @@
         host = MockHost()
         line_adder = W3CExpectationsLineAdder(host)
         line_adder._host.filesystem.files = {'TestExpectations': '# Tests added from W3C auto import bot\n'}
-        line_list = ['fake crbug [foo] fake/file/path.html [Pass]']
+        line_list = ['fake crbug [ foo ] fake/file/path.html [Pass]']
         path = 'TestExpectations'
         line_adder.write_to_test_expectations(line_adder, path, line_list)
         value = line_adder._host.filesystem.read_text_file(path)
-        self.assertEqual(value, '# Tests added from W3C auto import bot\nfake crbug [foo] fake/file/path.html [Pass]\n')
+        self.assertEqual(value, '# Tests added from W3C auto import bot\nfake crbug [ foo ] fake/file/path.html [Pass]\n')
 
     def test_write_to_test_expectations_to_eof(self):
         host = MockHost()
         line_adder = W3CExpectationsLineAdder(host)
         line_adder._host.filesystem.files['TestExpectations'] = 'not empty\n'
-        line_list = ['fake crbug [foo] fake/file/path.html [Pass]']
+        line_list = ['fake crbug [ foo ] fake/file/path.html [Pass]']
         path = 'TestExpectations'
         line_adder.write_to_test_expectations(line_adder, path, line_list)
         value = line_adder.filesystem.read_text_file(path)
-        self.assertEqual(value, 'not empty\n\n# Tests added from W3C auto import bot\nfake crbug [foo] fake/file/path.html [Pass]')
+        self.assertEqual(value, 'not empty\n\n# Tests added from W3C auto import bot\nfake crbug [ foo ] fake/file/path.html [Pass]')
+
+    def test_write_to_test_expectations_skip_lines(self):
+        host = MockHost()
+        line_adder = W3CExpectationsLineAdder(host)
+        line_adder._host.filesystem.files['TestExpectations'] = 'dont copy me\n'
+        line_list = ['[ ] dont copy me', '[ ] but copy me']
+        path = 'TestExpectations'
+        line_adder.write_to_test_expectations(line_adder, path, line_list)
+        value = line_adder.filesystem.read_text_file(path)
+        self.assertEqual(value, 'dont copy me\n\n# Tests added from W3C auto import bot\n[ ] but copy me')
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index e4189be..10bd00d 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -87,7 +87,7 @@
   java_cpp_enum("blink_headers_java_enums_srcjar") {
     sources = [
       "./platform/WebDisplayMode.h",
-      "./web/WebInputEvent.h",
+      "./platform/WebInputEvent.h",
       "./web/WebTextInputType.h",
     ]
   }
diff --git a/third_party/WebKit/public/blink.gyp b/third_party/WebKit/public/blink.gyp
index c447a1f..95d123d 100644
--- a/third_party/WebKit/public/blink.gyp
+++ b/third_party/WebKit/public/blink.gyp
@@ -54,6 +54,10 @@
         'blink_android_mojo_sources': [
             'platform/modules/payments/payment_request.mojom',
         ],
+        'blink_typemap_sources': [
+            '<(DEPTH)/cc/ipc/surface_id.typemap',
+            '<(DEPTH)/cc/ipc/surface_sequence.typemap',
+        ],
     },
     'targets': [
         {
@@ -118,9 +122,8 @@
                     '<@(blink_android_mojo_sources)',
                 ],
                 'mojom_typemaps': [
-                    '<(DEPTH)/cc/ipc/surface_id.typemap',
-                    '<(DEPTH)/cc/ipc/surface_sequence.typemap',
                     '../Source/platform/mojo/SecurityOrigin.typemap',
+                    '<@(blink_typemap_sources)',
                 ],
                 'for_blink': 'true',
                 'use_new_wrapper_types': 'false',
@@ -143,10 +146,9 @@
                     '<@(blink_android_mojo_sources)',
                 ],
                 'mojom_typemaps': [
-                  '../../../device/bluetooth/public/interfaces/bluetooth_uuid.typemap',
-                    '<(DEPTH)/cc/ipc/surface_id.typemap',
-                    '<(DEPTH)/cc/ipc/surface_sequence.typemap',
+                    '../../../device/bluetooth/public/interfaces/bluetooth_uuid.typemap',
                     '<(DEPTH)/url/mojo/origin.typemap',
+                    '<@(blink_typemap_sources)',
                 ],
                 'use_new_wrapper_types': 'false',
             },
diff --git a/third_party/WebKit/public/blink_headers.gyp b/third_party/WebKit/public/blink_headers.gyp
index aa69e3cf..96f615f 100644
--- a/third_party/WebKit/public/blink_headers.gyp
+++ b/third_party/WebKit/public/blink_headers.gyp
@@ -27,7 +27,7 @@
                     'target_name': 'web_input_event_java',
                     'type': 'none',
                     'variables': {
-                        'source_file': 'web/WebInputEvent.h',
+                        'source_file': 'platform/WebInputEvent.h',
                     },
                     'includes': [ '../../../build/android/java_cpp_enum.gypi' ],
                 },
diff --git a/third_party/WebKit/public/blink_headers.gypi b/third_party/WebKit/public/blink_headers.gypi
index bda10619..2b84a18 100644
--- a/third_party/WebKit/public/blink_headers.gypi
+++ b/third_party/WebKit/public/blink_headers.gypi
@@ -110,6 +110,7 @@
       "platform/WebImageLayer.h",
       "platform/WebInbandTextTrack.h",
       "platform/WebInbandTextTrackClient.h",
+      "platform/WebInputEvent.h",
       "platform/WebInputEventResult.h",
       "platform/WebInsecureRequestPolicy.h",
       "platform/WebLayer.h",
@@ -209,6 +210,7 @@
       "platform/WebThreadSafeData.h",
       "platform/WebTimeRange.h",
       "platform/WebTopControlsState.h",
+      "platform/WebTouchPoint.h",
       "platform/WebTraceLocation.h",
       "platform/WebURL.h",
       "platform/WebURLError.h",
@@ -453,7 +455,6 @@
       "web/WebTextInputInfo.h",
       "web/WebTextInputType.h",
       "web/WebTouchAction.h",
-      "web/WebTouchPoint.h",
       "web/WebTreeScopeType.h",
       "web/WebURLLoaderOptions.h",
       "web/WebUserGestureIndicator.h",
diff --git a/third_party/WebKit/public/blink_typemaps.gni b/third_party/WebKit/public/blink_typemaps.gni
new file mode 100644
index 0000000..453d848
--- /dev/null
+++ b/third_party/WebKit/public/blink_typemaps.gni
@@ -0,0 +1,8 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+typemaps = [
+  "//cc/ipc/surface_id.typemap",
+  "//cc/ipc/surface_sequence.typemap",
+]
diff --git a/third_party/WebKit/public/platform/WebInputEvent.h b/third_party/WebKit/public/platform/WebInputEvent.h
new file mode 100644
index 0000000..04d6d32
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebInputEvent.h
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebInputEvent_h
+#define WebInputEvent_h
+
+#include "WebCommon.h"
+#include "WebGestureDevice.h"
+#include "WebPointerProperties.h"
+#include "WebRect.h"
+#include "WebTouchPoint.h"
+
+#include <string.h>
+
+namespace blink {
+
+// The classes defined in this file are intended to be used with
+// WebWidget's handleInputEvent method.  These event types are cross-
+// platform and correspond closely to WebCore's Platform*Event classes.
+//
+// WARNING! These classes must remain PODs (plain old data).  They are
+// intended to be "serializable" by copying their raw bytes, so they must
+// not contain any non-bit-copyable member variables!
+//
+// Furthermore, the class members need to be packed so they are aligned
+// properly and don't have paddings/gaps, otherwise memory check tools
+// like Valgrind will complain about uninitialized memory usage when
+// transferring these classes over the wire.
+
+#pragma pack(push, 4)
+
+// WebInputEvent --------------------------------------------------------------
+
+class WebInputEvent {
+public:
+    // When we use an input method (or an input method editor), we receive
+    // two events for a keypress. The former event is a keydown, which
+    // provides a keycode, and the latter is a textinput, which provides
+    // a character processed by an input method. (The mapping from a
+    // keycode to a character code is not trivial for non-English
+    // keyboards.)
+    // To support input methods, Safari sends keydown events to WebKit for
+    // filtering. WebKit sends filtered keydown events back to Safari,
+    // which sends them to input methods.
+    // Unfortunately, it is hard to apply this design to Chrome because of
+    // our multiprocess architecture. An input method is running in a
+    // browser process. On the other hand, WebKit is running in a renderer
+    // process. So, this design results in increasing IPC messages.
+    // To support input methods without increasing IPC messages, Chrome
+    // handles keyboard events in a browser process and send asynchronous
+    // input events (to be translated to DOM events) to a renderer
+    // process.
+    // This design is mostly the same as the one of Windows and Mac Carbon.
+    // So, for what it's worth, our Linux and Mac front-ends emulate our
+    // Windows front-end. To emulate our Windows front-end, we can share
+    // our back-end code among Windows, Linux, and Mac.
+    // TODO(hbono): Issue 18064: remove the KeyDown type since it isn't
+    // used in Chrome any longer.
+
+    // A Java counterpart will be generated for this enum.
+    // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
+    // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventType
+    enum Type {
+        Undefined = -1,
+        TypeFirst = Undefined,
+
+        // WebMouseEvent
+        MouseDown,
+        MouseTypeFirst = MouseDown,
+        MouseUp,
+        MouseMove,
+        MouseEnter,
+        MouseLeave,
+        ContextMenu,
+        MouseTypeLast = ContextMenu,
+
+        // WebMouseWheelEvent
+        MouseWheel,
+
+        // WebKeyboardEvent
+        RawKeyDown,
+        KeyboardTypeFirst = RawKeyDown,
+        KeyDown,
+        KeyUp,
+        Char,
+        KeyboardTypeLast = Char,
+
+        // WebGestureEvent
+        GestureScrollBegin,
+        GestureTypeFirst = GestureScrollBegin,
+        GestureScrollEnd,
+        GestureScrollUpdate,
+        GestureFlingStart,
+        GestureFlingCancel,
+        GestureShowPress,
+        GestureTap,
+        GestureTapUnconfirmed,
+        GestureTapDown,
+        GestureTapCancel,
+        GestureDoubleTap,
+        GestureTwoFingerTap,
+        GestureLongPress,
+        GestureLongTap,
+        GesturePinchBegin,
+        GesturePinchEnd,
+        GesturePinchUpdate,
+        GestureTypeLast = GesturePinchUpdate,
+
+        // WebTouchEvent
+        TouchStart,
+        TouchTypeFirst = TouchStart,
+        TouchMove,
+        TouchEnd,
+        TouchCancel,
+        TouchScrollStarted,
+        TouchTypeLast = TouchScrollStarted,
+
+        TypeLast = TouchTypeLast
+    };
+
+    // The modifier constants cannot change their values since pepper
+    // does a 1-1 mapping of its values; see
+    // content/renderer/pepper/event_conversion.cc
+    //
+    // A Java counterpart will be generated for this enum.
+    // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
+    // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventModifier
+    enum Modifiers {
+        // modifiers for all events:
+        ShiftKey         = 1 << 0,
+        ControlKey       = 1 << 1,
+        AltKey           = 1 << 2,
+        MetaKey          = 1 << 3,
+
+        // modifiers for keyboard events:
+        IsKeyPad         = 1 << 4,
+        IsAutoRepeat     = 1 << 5,
+
+        // modifiers for mouse events:
+        LeftButtonDown   = 1 << 6,
+        MiddleButtonDown = 1 << 7,
+        RightButtonDown  = 1 << 8,
+
+        // Toggle modifers for all events.
+        CapsLockOn       = 1 << 9,
+        NumLockOn        = 1 << 10,
+
+        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,
+
+        IsComposing      = 1 << 14,
+
+        AltGrKey         = 1 << 15,
+        FnKey            = 1 << 16,
+        SymbolKey        = 1 << 17,
+
+        ScrollLockOn     = 1 << 18,
+    };
+
+    // Indicates whether the browser needs to block on the ACK result for
+    // this event, and if not why note (for metrics/diagnostics purposes).
+    // These values are direct mappings of the values in PlatformEvent
+    // so the values can be cast between the enumerations. static_asserts
+    // checking this are in web/WebInputEventConversion.cpp.
+    enum DispatchType {
+        // Event can be canceled.
+        Blocking,
+        // Event can not be canceled.
+        EventNonBlocking,
+        // All listeners are passive; not cancelable.
+        ListenersNonBlockingPassive,
+        // This value represents a state which would have normally blocking
+        // but was forced to be non-blocking; not cancelable.
+        ListenersForcedNonBlockingPassive,
+    };
+
+    // The rail mode for a wheel event specifies the axis on which scrolling is
+    // expected to stick. If this axis is set to Free, then scrolling is not
+    // stuck to any axis.
+    enum RailsMode {
+        RailsModeFree       = 0,
+        RailsModeHorizontal = 1,
+        RailsModeVertical   = 2,
+    };
+
+    static const int InputModifiers = ShiftKey | ControlKey | AltKey | MetaKey;
+
+    double timeStampSeconds; // Seconds since platform start with microsecond resolution.
+    unsigned size; // The size of this structure, for serialization.
+    Type type;
+    int modifiers;
+
+    // Returns true if the WebInputEvent |type| is a mouse event.
+    static bool isMouseEventType(int type)
+    {
+        return MouseTypeFirst <= type && type <= MouseTypeLast;
+    }
+
+    // Returns true if the WebInputEvent |type| is a keyboard event.
+    static bool isKeyboardEventType(int type)
+    {
+        return KeyboardTypeFirst <= type && type <= KeyboardTypeLast;
+    }
+
+    // Returns true if the WebInputEvent |type| is a touch event.
+    static bool isTouchEventType(int type)
+    {
+        return TouchTypeFirst <= type && type <= TouchTypeLast;
+    }
+
+    // Returns true if the WebInputEvent is a gesture event.
+    static bool isGestureEventType(int type)
+    {
+        return GestureTypeFirst <= type && type <= GestureTypeLast;
+    }
+
+protected:
+    explicit WebInputEvent(unsigned sizeParam)
+    {
+        memset(this, 0, sizeParam);
+        timeStampSeconds = 0.0;
+        size = sizeParam;
+        type = Undefined;
+        modifiers = 0;
+    }
+};
+
+// WebKeyboardEvent -----------------------------------------------------------
+
+class WebKeyboardEvent : public WebInputEvent {
+public:
+    // Caps on string lengths so we can make them static arrays and keep
+    // them PODs.
+    static const size_t textLengthCap = 4;
+
+    // |windowsKeyCode| is the Windows key code associated with this key
+    // event.  Sometimes it's direct from the event (i.e. on Windows),
+    // sometimes it's via a mapping function.  If you want a list, see
+    // WebCore/platform/chromium/KeyboardCodes* . Note that this should
+    // ALWAYS store the non-locational version of a keycode as this is
+    // what is returned by the Windows API. For example, it should
+    // store VK_SHIFT instead of VK_RSHIFT. The location information
+    // should be stored in |modifiers|.
+    int windowsKeyCode;
+
+    // The actual key code genenerated by the platform.  The DOM spec runs
+    // on Windows-equivalent codes (thus |windowsKeyCode| above) but it
+    // doesn't hurt to have this one around.
+    int nativeKeyCode;
+
+    // The DOM code enum of the key pressed as passed by the embedder. DOM
+    // code enum are defined in ui/events/keycodes/dom4/keycode_converter_data.h.
+    int domCode;
+
+    // The DOM key enum of the key pressed as passed by the embedder. DOM
+    // key enum are defined in ui/events/keycodes/dom3/dom_key_data.h
+    int domKey;
+
+    // This identifies whether this event was tagged by the system as being
+    // a "system key" event (see
+    // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for
+    // details). Other platforms don't have this concept, but it's just
+    // easier to leave it always false than ifdef.
+    bool isSystemKey;
+
+    // Whether the event forms part of a browser-handled keyboard shortcut.
+    // This can be used to conditionally suppress Char events after a
+    // shortcut-triggering RawKeyDown goes unhandled.
+    bool isBrowserShortcut;
+
+    // |text| is the text generated by this keystroke.  |unmodifiedText| is
+    // |text|, but unmodified by an concurrently-held modifiers (except
+    // shift).  This is useful for working out shortcut keys.  Linux and
+    // Windows guarantee one character per event.  The Mac does not, but in
+    // reality that's all it ever gives.  We're generous, and cap it a bit
+    // longer.
+    WebUChar text[textLengthCap];
+    WebUChar unmodifiedText[textLengthCap];
+
+    WebKeyboardEvent()
+        : WebInputEvent(sizeof(WebKeyboardEvent))
+        , windowsKeyCode(0)
+        , nativeKeyCode(0)
+        , isSystemKey(false)
+        , isBrowserShortcut(false)
+    {
+        memset(&text, 0, sizeof(text));
+        memset(&unmodifiedText, 0, sizeof(unmodifiedText));
+    }
+};
+
+// WebMouseEvent --------------------------------------------------------------
+
+class WebMouseEvent : public WebInputEvent, public WebPointerProperties {
+public:
+    // Renderer coordinates. Similar to viewport coordinates but without
+    // DevTools emulation transform or overscroll applied. i.e. the coordinates
+    // in Chromium's RenderView bounds.
+    int x;
+    int y;
+
+    // DEPRECATED (crbug.com/507787)
+    int windowX;
+    int windowY;
+
+    // Screen coordinate
+    int globalX;
+    int globalY;
+
+    int movementX;
+    int movementY;
+    int clickCount;
+
+    WebMouseEvent()
+        : WebInputEvent(sizeof(WebMouseEvent))
+        , WebPointerProperties()
+        , x(0)
+        , y(0)
+        , windowX(0)
+        , windowY(0)
+        , globalX(0)
+        , globalY(0)
+        , movementX(0)
+        , movementY(0)
+        , clickCount(0)
+    {
+    }
+
+protected:
+    explicit WebMouseEvent(unsigned sizeParam)
+        : WebInputEvent(sizeParam)
+        , WebPointerProperties()
+        , x(0)
+        , y(0)
+        , windowX(0)
+        , windowY(0)
+        , globalX(0)
+        , globalY(0)
+        , movementX(0)
+        , movementY(0)
+        , clickCount(0)
+    {
+    }
+};
+
+// WebMouseWheelEvent ---------------------------------------------------------
+
+class WebMouseWheelEvent : public WebMouseEvent {
+public:
+    enum Phase {
+        PhaseNone        = 0,
+        PhaseBegan       = 1 << 0,
+        PhaseStationary  = 1 << 1,
+        PhaseChanged     = 1 << 2,
+        PhaseEnded       = 1 << 3,
+        PhaseCancelled   = 1 << 4,
+        PhaseMayBegin    = 1 << 5,
+    };
+
+    float deltaX;
+    float deltaY;
+    float wheelTicksX;
+    float wheelTicksY;
+
+    float accelerationRatioX;
+    float accelerationRatioY;
+
+    // This field exists to allow BrowserPlugin to mark MouseWheel events as
+    // 'resent' to handle the case where an event is not consumed when first
+    // encountered; it should be handled differently by the plugin when it is
+    // sent for thesecond time. No code within Blink touches this, other than to
+    // plumb it through event conversions.
+    int resendingPluginId;
+
+    Phase phase;
+    Phase momentumPhase;
+
+    // Rubberbanding is an OSX visual effect. When a user scrolls the content
+    // area with a track pad, and the content area is already at its limit in
+    // the direction being scrolled, the entire content area is allowed to
+    // scroll slightly off screen, revealing a grey background. When the user
+    // lets go, the content area snaps back into place. Blink is responsible
+    // for this rubberbanding effect, but the embedder may wish to disable
+    // rubber banding in the left or right direction, if the scroll should have
+    // an alternate effect. The common case is that a scroll in the left or
+    // right directions causes a back or forwards navigation, respectively.
+    //
+    // These flags prevent rubber banding from starting in a given direction,
+    // but have no effect on an ongoing rubber banding. A rubber banding that
+    // started in the vertical direction is allowed to continue in the right
+    // direction, even if canRubberbandRight is 0.
+    bool canRubberbandLeft;
+    bool canRubberbandRight;
+
+    bool scrollByPage;
+    bool hasPreciseScrollingDeltas;
+
+    RailsMode railsMode;
+
+    // Whether the event is blocking, non-blocking, all event
+    // listeners were passive or was forced to be non-blocking.
+    DispatchType dispatchType;
+
+    WebMouseWheelEvent()
+        : WebMouseEvent(sizeof(WebMouseWheelEvent))
+        , deltaX(0.0f)
+        , deltaY(0.0f)
+        , wheelTicksX(0.0f)
+        , wheelTicksY(0.0f)
+        , accelerationRatioX(1.0f)
+        , accelerationRatioY(1.0f)
+        , resendingPluginId(-1)
+        , phase(PhaseNone)
+        , momentumPhase(PhaseNone)
+        , canRubberbandLeft(true)
+        , canRubberbandRight(true)
+        , scrollByPage(false)
+        , hasPreciseScrollingDeltas(false)
+        , railsMode(RailsModeFree)
+        , dispatchType(Blocking)
+    {
+    }
+};
+
+// WebGestureEvent --------------------------------------------------------------
+
+class WebGestureEvent : public WebInputEvent {
+public:
+    enum ScrollUnits {
+        PrecisePixels = 0, // generated by high precision devices.
+        Pixels, // large pixel jump duration; should animate to delta.
+        Page // page (visible viewport) based scrolling.
+    };
+
+    enum InertialPhaseState {
+        UnknownMomentumPhase = 0, // No phase information.
+        NonMomentumPhase, // Regular scrolling phase.
+        MomentumPhase, // Momentum phase.
+    };
+
+    int x;
+    int y;
+    int globalX;
+    int globalY;
+    WebGestureDevice sourceDevice;
+
+    // If the WebGestureEvent has sourceDevice=WebGestureDeviceTouchscreen, this
+    // field contains the unique identifier for the touch event that released
+    // this event at TouchDispositionGestureFilter. If the WebGestureEvents was
+    // not released through a touch event (e.g. timer-released gesture events or
+    // gesture events with sourceDevice!=WebGestureDeviceTouchscreen), the field
+    // contains 0. See crbug.com/618738.
+    uint32_t uniqueTouchEventId;
+
+    // This field exists to allow BrowserPlugin to mark GestureScroll events as
+    // 'resent' to handle the case where an event is not consumed when first
+    // encountered; it should be handled differently by the plugin when it is
+    // sent for thesecond time. No code within Blink touches this, other than to
+    // plumb it through event conversions.
+    int resendingPluginId;
+
+    union {
+        // Tap information must be set for GestureTap, GestureTapUnconfirmed,
+        // and GestureDoubleTap events.
+        struct {
+            int tapCount;
+            float width;
+            float height;
+        } tap;
+
+        struct {
+            float width;
+            float height;
+        } tapDown;
+
+        struct {
+            float width;
+            float height;
+        } showPress;
+
+        struct {
+            float width;
+            float height;
+        } longPress;
+
+        struct {
+            float firstFingerWidth;
+            float firstFingerHeight;
+        } twoFingerTap;
+
+        struct {
+            // Initial motion that triggered the scroll.
+            // May be redundant with deltaX/deltaY in the first scrollUpdate.
+            float deltaXHint;
+            float deltaYHint;
+            // Default initialized to ScrollUnits::PrecisePixels.
+            ScrollUnits deltaHintUnits;
+            // If true, this event will skip hit testing to find a scroll
+            // target and instead just scroll the viewport.
+            bool targetViewport;
+            // The state of inertial phase scrolling. OSX has unique phases for normal and
+            // momentum scroll events. Should always be UnknownMomentumPhase for touch based
+            // input as it generates GestureFlingStart instead.
+            InertialPhaseState inertialPhase;
+            // True if this event was synthesized in order to force a hit test; avoiding scroll
+            // latching behavior until crbug.com/526463 is fully implemented.
+            bool synthetic;
+        } scrollBegin;
+
+        struct {
+            float deltaX;
+            float deltaY;
+            float velocityX;
+            float velocityY;
+            // Whether any previous GestureScrollUpdate in the current scroll
+            // sequence was suppressed (e.g., the causal touchmove was
+            // preventDefault'ed). This bit is particularly useful for
+            // determining whether the observed scroll update sequence captures
+            // the entirety of the generative motion.
+            bool previousUpdateInSequencePrevented;
+            bool preventPropagation;
+            InertialPhaseState inertialPhase;
+            // Default initialized to ScrollUnits::PrecisePixels.
+            ScrollUnits deltaUnits;
+        } scrollUpdate;
+
+        struct {
+            // The original delta units the scrollBegin and scrollUpdates
+            // were sent as.
+            ScrollUnits deltaUnits;
+            // The state of inertial phase scrolling. OSX has unique phases for normal and
+            // momentum scroll events. Should always be UnknownMomentumPhase for touch based
+            // input as it generates GestureFlingStart instead.
+            InertialPhaseState inertialPhase;
+            // True if this event was synthesized in order to generate the proper
+            // GSB/GSU/GSE matching sequences. This is a temporary so that a future
+            // GSB will generate a hit test so latching behavior is avoided
+            // until crbug.com/526463 is fully implemented.
+            bool synthetic;
+        } scrollEnd;
+
+        struct {
+            float velocityX;
+            float velocityY;
+            // If true, this event will skip hit testing to find a scroll
+            // target and instead just scroll the viewport.
+            bool targetViewport;
+        } flingStart;
+
+        struct {
+            // If set to true, don't treat flingCancel
+            // as a part of fling boost events sequence.
+            bool preventBoosting;
+        } flingCancel;
+
+        struct {
+            bool zoomDisabled;
+            float scale;
+        } pinchUpdate;
+    } data;
+
+    WebGestureEvent()
+        : WebInputEvent(sizeof(WebGestureEvent))
+        , x(0)
+        , y(0)
+        , globalX(0)
+        , globalY(0)
+        , sourceDevice(WebGestureDeviceUninitialized)
+        , resendingPluginId(-1)
+    {
+        memset(&data, 0, sizeof(data));
+    }
+};
+
+// WebTouchEvent --------------------------------------------------------------
+
+// TODO(e_hakkinen): Replace with WebPointerEvent. crbug.com/508283
+class WebTouchEvent : public WebInputEvent {
+public:
+    // Maximum number of simultaneous touches supported on
+    // Ash/Aura.
+    enum { kTouchesLengthCap = 16 };
+
+    unsigned touchesLength;
+    // List of all touches, regardless of state.
+    WebTouchPoint touches[kTouchesLengthCap];
+
+    // Whether the event is blocking, non-blocking, all event
+    // listeners were passive or was forced to be non-blocking.
+    DispatchType dispatchType;
+
+    // For a single touch, this is true after the touch-point has moved beyond
+    // the platform slop region. For a multitouch, this is true after any
+    // touch-point has moved (by whatever amount).
+    bool movedBeyondSlopRegion;
+
+    // Whether there was an active fling animation when the event was
+    // dispatched.
+    bool dispatchedDuringFling;
+
+    // A unique identifier for the touch event. Valid ids start at one and
+    // increase monotonically. Zero means an unknown id.
+    uint32_t uniqueTouchEventId;
+
+    WebTouchEvent()
+        : WebInputEvent(sizeof(WebTouchEvent))
+        , touchesLength(0)
+        , dispatchType(Blocking)
+        , movedBeyondSlopRegion(false)
+        , dispatchedDuringFling(false)
+        , uniqueTouchEventId(0)
+    {
+    }
+};
+
+#pragma pack(pop)
+
+} // namespace blink
+
+#endif
diff --git a/third_party/WebKit/public/platform/WebTaskRunner.h b/third_party/WebKit/public/platform/WebTaskRunner.h
index fc59596..3f4c35c 100644
--- a/third_party/WebKit/public/platform/WebTaskRunner.h
+++ b/third_party/WebKit/public/platform/WebTaskRunner.h
@@ -7,11 +7,10 @@
 
 #include "WebCommon.h"
 #include "public/platform/WebTraceLocation.h"
+#include <memory>
 
 #ifdef INSIDE_BLINK
 #include "wtf/Functional.h"
-#include "wtf/PtrUtil.h"
-#include <memory>
 #endif
 
 namespace blink {
@@ -36,7 +35,7 @@
     virtual void postDelayedTask(const WebTraceLocation&, Task*, double delayMs) = 0;
 
     // Returns a clone of the WebTaskRunner.
-    virtual WebTaskRunner* clone() = 0;
+    virtual std::unique_ptr<WebTaskRunner> clone() = 0;
 
     // Returns true if the current thread is a thread on which a task may be run.
     // Can be called from any thread.
@@ -70,11 +69,6 @@
     // For same-thread posting. Must be called from the associated WebThread.
     void postTask(const WebTraceLocation&, std::unique_ptr<WTF::Closure>);
     void postDelayedTask(const WebTraceLocation&, std::unique_ptr<WTF::Closure>, long long delayMs);
-
-    std::unique_ptr<WebTaskRunner> adoptClone()
-    {
-        return wrapUnique(clone());
-    }
 #endif
 };
 
diff --git a/third_party/WebKit/public/web/WebTouchPoint.h b/third_party/WebKit/public/platform/WebTouchPoint.h
similarity index 100%
rename from third_party/WebKit/public/web/WebTouchPoint.h
rename to third_party/WebKit/public/platform/WebTouchPoint.h
diff --git a/third_party/WebKit/public/web/WebInputEvent.h b/third_party/WebKit/public/web/WebInputEvent.h
index 98a1b18..a1fef8b 100644
--- a/third_party/WebKit/public/web/WebInputEvent.h
+++ b/third_party/WebKit/public/web/WebInputEvent.h
@@ -28,625 +28,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef WebInputEvent_h
-#define WebInputEvent_h
-
-#include "../platform/WebCommon.h"
-#include "../platform/WebGestureDevice.h"
-#include "../platform/WebPointerProperties.h"
-#include "../platform/WebRect.h"
-#include "WebTouchPoint.h"
-
-#include <string.h>
-
-namespace blink {
-
-// The classes defined in this file are intended to be used with
-// WebWidget's handleInputEvent method.  These event types are cross-
-// platform and correspond closely to WebCore's Platform*Event classes.
-//
-// WARNING! These classes must remain PODs (plain old data).  They are
-// intended to be "serializable" by copying their raw bytes, so they must
-// not contain any non-bit-copyable member variables!
-//
-// Furthermore, the class members need to be packed so they are aligned
-// properly and don't have paddings/gaps, otherwise memory check tools
-// like Valgrind will complain about uninitialized memory usage when
-// transferring these classes over the wire.
-
-#pragma pack(push, 4)
-
-// WebInputEvent --------------------------------------------------------------
-
-class WebInputEvent {
-public:
-    // When we use an input method (or an input method editor), we receive
-    // two events for a keypress. The former event is a keydown, which
-    // provides a keycode, and the latter is a textinput, which provides
-    // a character processed by an input method. (The mapping from a
-    // keycode to a character code is not trivial for non-English
-    // keyboards.)
-    // To support input methods, Safari sends keydown events to WebKit for
-    // filtering. WebKit sends filtered keydown events back to Safari,
-    // which sends them to input methods.
-    // Unfortunately, it is hard to apply this design to Chrome because of
-    // our multiprocess architecture. An input method is running in a
-    // browser process. On the other hand, WebKit is running in a renderer
-    // process. So, this design results in increasing IPC messages.
-    // To support input methods without increasing IPC messages, Chrome
-    // handles keyboard events in a browser process and send asynchronous
-    // input events (to be translated to DOM events) to a renderer
-    // process.
-    // This design is mostly the same as the one of Windows and Mac Carbon.
-    // So, for what it's worth, our Linux and Mac front-ends emulate our
-    // Windows front-end. To emulate our Windows front-end, we can share
-    // our back-end code among Windows, Linux, and Mac.
-    // TODO(hbono): Issue 18064: remove the KeyDown type since it isn't
-    // used in Chrome any longer.
-
-    // A Java counterpart will be generated for this enum.
-    // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
-    // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventType
-    enum Type {
-        Undefined = -1,
-        TypeFirst = Undefined,
-
-        // WebMouseEvent
-        MouseDown,
-        MouseTypeFirst = MouseDown,
-        MouseUp,
-        MouseMove,
-        MouseEnter,
-        MouseLeave,
-        ContextMenu,
-        MouseTypeLast = ContextMenu,
-
-        // WebMouseWheelEvent
-        MouseWheel,
-
-        // WebKeyboardEvent
-        RawKeyDown,
-        KeyboardTypeFirst = RawKeyDown,
-        KeyDown,
-        KeyUp,
-        Char,
-        KeyboardTypeLast = Char,
-
-        // WebGestureEvent
-        GestureScrollBegin,
-        GestureTypeFirst = GestureScrollBegin,
-        GestureScrollEnd,
-        GestureScrollUpdate,
-        GestureFlingStart,
-        GestureFlingCancel,
-        GestureShowPress,
-        GestureTap,
-        GestureTapUnconfirmed,
-        GestureTapDown,
-        GestureTapCancel,
-        GestureDoubleTap,
-        GestureTwoFingerTap,
-        GestureLongPress,
-        GestureLongTap,
-        GesturePinchBegin,
-        GesturePinchEnd,
-        GesturePinchUpdate,
-        GestureTypeLast = GesturePinchUpdate,
-
-        // WebTouchEvent
-        TouchStart,
-        TouchTypeFirst = TouchStart,
-        TouchMove,
-        TouchEnd,
-        TouchCancel,
-        TouchScrollStarted,
-        TouchTypeLast = TouchScrollStarted,
-
-        TypeLast = TouchTypeLast
-    };
-
-    // The modifier constants cannot change their values since pepper
-    // does a 1-1 mapping of its values; see
-    // content/renderer/pepper/event_conversion.cc
-    //
-    // A Java counterpart will be generated for this enum.
-    // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.web
-    // GENERATED_JAVA_CLASS_NAME_OVERRIDE: WebInputEventModifier
-    enum Modifiers {
-        // modifiers for all events:
-        ShiftKey         = 1 << 0,
-        ControlKey       = 1 << 1,
-        AltKey           = 1 << 2,
-        MetaKey          = 1 << 3,
-
-        // modifiers for keyboard events:
-        IsKeyPad         = 1 << 4,
-        IsAutoRepeat     = 1 << 5,
-
-        // modifiers for mouse events:
-        LeftButtonDown   = 1 << 6,
-        MiddleButtonDown = 1 << 7,
-        RightButtonDown  = 1 << 8,
-
-        // Toggle modifers for all events.
-        CapsLockOn       = 1 << 9,
-        NumLockOn        = 1 << 10,
-
-        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,
-
-        IsComposing      = 1 << 14,
-
-        AltGrKey         = 1 << 15,
-        FnKey            = 1 << 16,
-        SymbolKey        = 1 << 17,
-
-        ScrollLockOn     = 1 << 18,
-    };
-
-    // Indicates whether the browser needs to block on the ACK result for
-    // this event, and if not why note (for metrics/diagnostics purposes).
-    // These values are direct mappings of the values in PlatformEvent
-    // so the values can be cast between the enumerations. static_asserts
-    // checking this are in web/WebInputEventConversion.cpp.
-    enum DispatchType {
-        // Event can be canceled.
-        Blocking,
-        // Event can not be canceled.
-        EventNonBlocking,
-        // All listeners are passive; not cancelable.
-        ListenersNonBlockingPassive,
-        // This value represents a state which would have normally blocking
-        // but was forced to be non-blocking; not cancelable.
-        ListenersForcedNonBlockingPassive,
-    };
-
-    // The rail mode for a wheel event specifies the axis on which scrolling is
-    // expected to stick. If this axis is set to Free, then scrolling is not
-    // stuck to any axis.
-    enum RailsMode {
-        RailsModeFree       = 0,
-        RailsModeHorizontal = 1,
-        RailsModeVertical   = 2,
-    };
-
-    static const int InputModifiers = ShiftKey | ControlKey | AltKey | MetaKey;
-
-    double timeStampSeconds; // Seconds since platform start with microsecond resolution.
-    unsigned size; // The size of this structure, for serialization.
-    Type type;
-    int modifiers;
-
-    // Returns true if the WebInputEvent |type| is a mouse event.
-    static bool isMouseEventType(int type)
-    {
-        return MouseTypeFirst <= type && type <= MouseTypeLast;
-    }
-
-    // Returns true if the WebInputEvent |type| is a keyboard event.
-    static bool isKeyboardEventType(int type)
-    {
-        return KeyboardTypeFirst <= type && type <= KeyboardTypeLast;
-    }
-
-    // Returns true if the WebInputEvent |type| is a touch event.
-    static bool isTouchEventType(int type)
-    {
-        return TouchTypeFirst <= type && type <= TouchTypeLast;
-    }
-
-    // Returns true if the WebInputEvent is a gesture event.
-    static bool isGestureEventType(int type)
-    {
-        return GestureTypeFirst <= type && type <= GestureTypeLast;
-    }
-
-protected:
-    explicit WebInputEvent(unsigned sizeParam)
-    {
-        memset(this, 0, sizeParam);
-        timeStampSeconds = 0.0;
-        size = sizeParam;
-        type = Undefined;
-        modifiers = 0;
-    }
-};
-
-// WebKeyboardEvent -----------------------------------------------------------
-
-class WebKeyboardEvent : public WebInputEvent {
-public:
-    // Caps on string lengths so we can make them static arrays and keep
-    // them PODs.
-    static const size_t textLengthCap = 4;
-
-    // |windowsKeyCode| is the Windows key code associated with this key
-    // event.  Sometimes it's direct from the event (i.e. on Windows),
-    // sometimes it's via a mapping function.  If you want a list, see
-    // WebCore/platform/chromium/KeyboardCodes* . Note that this should
-    // ALWAYS store the non-locational version of a keycode as this is
-    // what is returned by the Windows API. For example, it should
-    // store VK_SHIFT instead of VK_RSHIFT. The location information
-    // should be stored in |modifiers|.
-    int windowsKeyCode;
-
-    // The actual key code genenerated by the platform.  The DOM spec runs
-    // on Windows-equivalent codes (thus |windowsKeyCode| above) but it
-    // doesn't hurt to have this one around.
-    int nativeKeyCode;
-
-    // The DOM code enum of the key pressed as passed by the embedder. DOM
-    // code enum are defined in ui/events/keycodes/dom4/keycode_converter_data.h.
-    int domCode;
-
-    // The DOM key enum of the key pressed as passed by the embedder. DOM
-    // key enum are defined in ui/events/keycodes/dom3/dom_key_data.h
-    int domKey;
-
-    // This identifies whether this event was tagged by the system as being
-    // a "system key" event (see
-    // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for
-    // details). Other platforms don't have this concept, but it's just
-    // easier to leave it always false than ifdef.
-    bool isSystemKey;
-
-    // Whether the event forms part of a browser-handled keyboard shortcut.
-    // This can be used to conditionally suppress Char events after a
-    // shortcut-triggering RawKeyDown goes unhandled.
-    bool isBrowserShortcut;
-
-    // |text| is the text generated by this keystroke.  |unmodifiedText| is
-    // |text|, but unmodified by an concurrently-held modifiers (except
-    // shift).  This is useful for working out shortcut keys.  Linux and
-    // Windows guarantee one character per event.  The Mac does not, but in
-    // reality that's all it ever gives.  We're generous, and cap it a bit
-    // longer.
-    WebUChar text[textLengthCap];
-    WebUChar unmodifiedText[textLengthCap];
-
-    WebKeyboardEvent()
-        : WebInputEvent(sizeof(WebKeyboardEvent))
-        , windowsKeyCode(0)
-        , nativeKeyCode(0)
-        , isSystemKey(false)
-        , isBrowserShortcut(false)
-    {
-        memset(&text, 0, sizeof(text));
-        memset(&unmodifiedText, 0, sizeof(unmodifiedText));
-    }
-};
-
-// WebMouseEvent --------------------------------------------------------------
-
-class WebMouseEvent : public WebInputEvent, public WebPointerProperties {
-public:
-    // Renderer coordinates. Similar to viewport coordinates but without
-    // DevTools emulation transform or overscroll applied. i.e. the coordinates
-    // in Chromium's RenderView bounds.
-    int x;
-    int y;
-
-    // DEPRECATED (crbug.com/507787)
-    int windowX;
-    int windowY;
-
-    // Screen coordinate
-    int globalX;
-    int globalY;
-
-    int movementX;
-    int movementY;
-    int clickCount;
-
-    WebMouseEvent()
-        : WebInputEvent(sizeof(WebMouseEvent))
-        , WebPointerProperties()
-        , x(0)
-        , y(0)
-        , windowX(0)
-        , windowY(0)
-        , globalX(0)
-        , globalY(0)
-        , movementX(0)
-        , movementY(0)
-        , clickCount(0)
-    {
-    }
-
-protected:
-    explicit WebMouseEvent(unsigned sizeParam)
-        : WebInputEvent(sizeParam)
-        , WebPointerProperties()
-        , x(0)
-        , y(0)
-        , windowX(0)
-        , windowY(0)
-        , globalX(0)
-        , globalY(0)
-        , movementX(0)
-        , movementY(0)
-        , clickCount(0)
-    {
-    }
-};
-
-// WebMouseWheelEvent ---------------------------------------------------------
-
-class WebMouseWheelEvent : public WebMouseEvent {
-public:
-    enum Phase {
-        PhaseNone        = 0,
-        PhaseBegan       = 1 << 0,
-        PhaseStationary  = 1 << 1,
-        PhaseChanged     = 1 << 2,
-        PhaseEnded       = 1 << 3,
-        PhaseCancelled   = 1 << 4,
-        PhaseMayBegin    = 1 << 5,
-    };
-
-    float deltaX;
-    float deltaY;
-    float wheelTicksX;
-    float wheelTicksY;
-
-    float accelerationRatioX;
-    float accelerationRatioY;
-
-    // This field exists to allow BrowserPlugin to mark MouseWheel events as
-    // 'resent' to handle the case where an event is not consumed when first
-    // encountered; it should be handled differently by the plugin when it is
-    // sent for thesecond time. No code within Blink touches this, other than to
-    // plumb it through event conversions.
-    int resendingPluginId;
-
-    Phase phase;
-    Phase momentumPhase;
-
-    // Rubberbanding is an OSX visual effect. When a user scrolls the content
-    // area with a track pad, and the content area is already at its limit in
-    // the direction being scrolled, the entire content area is allowed to
-    // scroll slightly off screen, revealing a grey background. When the user
-    // lets go, the content area snaps back into place. Blink is responsible
-    // for this rubberbanding effect, but the embedder may wish to disable
-    // rubber banding in the left or right direction, if the scroll should have
-    // an alternate effect. The common case is that a scroll in the left or
-    // right directions causes a back or forwards navigation, respectively.
-    //
-    // These flags prevent rubber banding from starting in a given direction,
-    // but have no effect on an ongoing rubber banding. A rubber banding that
-    // started in the vertical direction is allowed to continue in the right
-    // direction, even if canRubberbandRight is 0.
-    bool canRubberbandLeft;
-    bool canRubberbandRight;
-
-    bool scrollByPage;
-    bool hasPreciseScrollingDeltas;
-
-    RailsMode railsMode;
-
-    // Whether the event is blocking, non-blocking, all event
-    // listeners were passive or was forced to be non-blocking.
-    DispatchType dispatchType;
-
-    WebMouseWheelEvent()
-        : WebMouseEvent(sizeof(WebMouseWheelEvent))
-        , deltaX(0.0f)
-        , deltaY(0.0f)
-        , wheelTicksX(0.0f)
-        , wheelTicksY(0.0f)
-        , accelerationRatioX(1.0f)
-        , accelerationRatioY(1.0f)
-        , resendingPluginId(-1)
-        , phase(PhaseNone)
-        , momentumPhase(PhaseNone)
-        , canRubberbandLeft(true)
-        , canRubberbandRight(true)
-        , scrollByPage(false)
-        , hasPreciseScrollingDeltas(false)
-        , railsMode(RailsModeFree)
-        , dispatchType(Blocking)
-    {
-    }
-};
-
-// WebGestureEvent --------------------------------------------------------------
-
-class WebGestureEvent : public WebInputEvent {
-public:
-    enum ScrollUnits {
-        PrecisePixels = 0, // generated by high precision devices.
-        Pixels, // large pixel jump duration; should animate to delta.
-        Page // page (visible viewport) based scrolling.
-    };
-
-    enum InertialPhaseState {
-        UnknownMomentumPhase = 0, // No phase information.
-        NonMomentumPhase, // Regular scrolling phase.
-        MomentumPhase, // Momentum phase.
-    };
-
-    int x;
-    int y;
-    int globalX;
-    int globalY;
-    WebGestureDevice sourceDevice;
-
-    // If the WebGestureEvent has sourceDevice=WebGestureDeviceTouchscreen, this
-    // field contains the unique identifier for the touch event that released
-    // this event at TouchDispositionGestureFilter. If the WebGestureEvents was
-    // not released through a touch event (e.g. timer-released gesture events or
-    // gesture events with sourceDevice!=WebGestureDeviceTouchscreen), the field
-    // contains 0. See crbug.com/618738.
-    uint32_t uniqueTouchEventId;
-
-    // This field exists to allow BrowserPlugin to mark GestureScroll events as
-    // 'resent' to handle the case where an event is not consumed when first
-    // encountered; it should be handled differently by the plugin when it is
-    // sent for thesecond time. No code within Blink touches this, other than to
-    // plumb it through event conversions.
-    int resendingPluginId;
-
-    union {
-        // Tap information must be set for GestureTap, GestureTapUnconfirmed,
-        // and GestureDoubleTap events.
-        struct {
-            int tapCount;
-            float width;
-            float height;
-        } tap;
-
-        struct {
-            float width;
-            float height;
-        } tapDown;
-
-        struct {
-            float width;
-            float height;
-        } showPress;
-
-        struct {
-            float width;
-            float height;
-        } longPress;
-
-        struct {
-            float firstFingerWidth;
-            float firstFingerHeight;
-        } twoFingerTap;
-
-        struct {
-            // Initial motion that triggered the scroll.
-            // May be redundant with deltaX/deltaY in the first scrollUpdate.
-            float deltaXHint;
-            float deltaYHint;
-            // Default initialized to ScrollUnits::PrecisePixels.
-            ScrollUnits deltaHintUnits;
-            // If true, this event will skip hit testing to find a scroll
-            // target and instead just scroll the viewport.
-            bool targetViewport;
-            // The state of inertial phase scrolling. OSX has unique phases for normal and
-            // momentum scroll events. Should always be UnknownMomentumPhase for touch based
-            // input as it generates GestureFlingStart instead.
-            InertialPhaseState inertialPhase;
-            // True if this event was synthesized in order to force a hit test; avoiding scroll
-            // latching behavior until crbug.com/526463 is fully implemented.
-            bool synthetic;
-        } scrollBegin;
-
-        struct {
-            float deltaX;
-            float deltaY;
-            float velocityX;
-            float velocityY;
-            // Whether any previous GestureScrollUpdate in the current scroll
-            // sequence was suppressed (e.g., the causal touchmove was
-            // preventDefault'ed). This bit is particularly useful for
-            // determining whether the observed scroll update sequence captures
-            // the entirety of the generative motion.
-            bool previousUpdateInSequencePrevented;
-            bool preventPropagation;
-            InertialPhaseState inertialPhase;
-            // Default initialized to ScrollUnits::PrecisePixels.
-            ScrollUnits deltaUnits;
-        } scrollUpdate;
-
-        struct {
-            // The original delta units the scrollBegin and scrollUpdates
-            // were sent as.
-            ScrollUnits deltaUnits;
-            // The state of inertial phase scrolling. OSX has unique phases for normal and
-            // momentum scroll events. Should always be UnknownMomentumPhase for touch based
-            // input as it generates GestureFlingStart instead.
-            InertialPhaseState inertialPhase;
-            // True if this event was synthesized in order to generate the proper
-            // GSB/GSU/GSE matching sequences. This is a temporary so that a future
-            // GSB will generate a hit test so latching behavior is avoided
-            // until crbug.com/526463 is fully implemented.
-            bool synthetic;
-        } scrollEnd;
-
-        struct {
-            float velocityX;
-            float velocityY;
-            // If true, this event will skip hit testing to find a scroll
-            // target and instead just scroll the viewport.
-            bool targetViewport;
-        } flingStart;
-
-        struct {
-            // If set to true, don't treat flingCancel
-            // as a part of fling boost events sequence.
-            bool preventBoosting;
-        } flingCancel;
-
-        struct {
-            bool zoomDisabled;
-            float scale;
-        } pinchUpdate;
-    } data;
-
-    WebGestureEvent()
-        : WebInputEvent(sizeof(WebGestureEvent))
-        , x(0)
-        , y(0)
-        , globalX(0)
-        , globalY(0)
-        , sourceDevice(WebGestureDeviceUninitialized)
-        , resendingPluginId(-1)
-    {
-        memset(&data, 0, sizeof(data));
-    }
-};
-
-// WebTouchEvent --------------------------------------------------------------
-
-// TODO(e_hakkinen): Replace with WebPointerEvent. crbug.com/508283
-class WebTouchEvent : public WebInputEvent {
-public:
-    // Maximum number of simultaneous touches supported on
-    // Ash/Aura.
-    enum { touchesLengthCap = 16 };
-
-    unsigned touchesLength;
-    // List of all touches, regardless of state.
-    WebTouchPoint touches[touchesLengthCap];
-
-    // Whether the event is blocking, non-blocking, all event
-    // listeners were passive or was forced to be non-blocking.
-    DispatchType dispatchType;
-
-    // For a single touch, this is true after the touch-point has moved beyond
-    // the platform slop region. For a multitouch, this is true after any
-    // touch-point has moved (by whatever amount).
-    bool movedBeyondSlopRegion;
-
-    // Whether there was an active fling animation when the event was
-    // dispatched.
-    bool dispatchedDuringFling;
-
-    // A unique identifier for the touch event. Valid ids start at one and
-    // increase monotonically. Zero means an unknown id.
-    uint32_t uniqueTouchEventId;
-
-    WebTouchEvent()
-        : WebInputEvent(sizeof(WebTouchEvent))
-        , touchesLength(0)
-        , dispatchType(Blocking)
-        , movedBeyondSlopRegion(false)
-        , dispatchedDuringFling(false)
-        , uniqueTouchEventId(0)
-    {
-    }
-};
-
-#pragma pack(pop)
-
-} // namespace blink
-
-#endif
+// TODO(dtapuska): This is a temporarily placeholder file
+// while crbug.com/625684 is fixed.
+#include "../platform/WebInputEvent.h"
diff --git a/third_party/android_platform/development/scripts/stack_core.py b/third_party/android_platform/development/scripts/stack_core.py
index 1dceb2e..119bd40 100755
--- a/third_party/android_platform/development/scripts/stack_core.py
+++ b/third_party/android_platform/development/scripts/stack_core.py
@@ -273,7 +273,7 @@
       match = _TRACE_LINE.match(line)
       if match:
         lib, symbol_present = match.group('lib', 'symbol_present')
-        if os.path.splitext(lib)[1] == '.apk':
+        if os.path.splitext(lib)[1] == '.apk' and symbol_present:
           soname = self._DetectSharedLibrary(lib, symbol_present)
           if soname:
             line = line.replace('/' + os.path.basename(lib), '/' + soname)
diff --git a/third_party/closure_compiler/README.chromium b/third_party/closure_compiler/README.chromium
index 06ffc423..e489043 100644
--- a/third_party/closure_compiler/README.chromium
+++ b/third_party/closure_compiler/README.chromium
@@ -3,7 +3,7 @@
 URL: http://github.com/google/closure-compiler
 Version: v20150729-236-gad656a1
 Date: 2015/08/26 08:46
-Revision: 2f95290ea61dd4f1b5a3bf9d0fe3aa8e3244babf
+Revision: c64418fd5518bb60aeb6a627d2bcc46a3d4be788
 License: Apache 2.0
 License File: LICENSE
 Security Critical: no
diff --git a/third_party/closure_compiler/compiler/compiler.jar b/third_party/closure_compiler/compiler/compiler.jar
index 9c126dd..2b95321 100644
--- a/third_party/closure_compiler/compiler/compiler.jar
+++ b/third_party/closure_compiler/compiler/compiler.jar
Binary files differ
diff --git a/third_party/closure_compiler/externs/chrome_extensions.js b/third_party/closure_compiler/externs/chrome_extensions.js
index 351584b..6c046f6 100644
--- a/third_party/closure_compiler/externs/chrome_extensions.js
+++ b/third_party/closure_compiler/externs/chrome_extensions.js
@@ -9341,7 +9341,7 @@
 
 /**
  * @const
- * @see http://goo.gl/bKHibo
+ * @see https://cs.chromium.org/chromium/src/extensions/common/api/bluetooth_private.idl
  */
 chrome.bluetoothPrivate = {};
 
@@ -9442,6 +9442,75 @@
 chrome.bluetoothPrivate.onPairing;
 
 
+/**
+ * @param {string} deviceAddress
+ * @param {function(number, string): void=} opt_callback
+ */
+chrome.bluetoothPrivate.pair = function(deviceAddress, opt_callback) {};
+
+
+/**
+ * @enum {string}
+ * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingResponse
+ */
+chrome.bluetoothPrivate.PairingResponse = {
+  CONFIRM: '',
+  REJECT: '',
+  CANCEL: '',
+};
+
+
+/**
+ * @enum {string}
+ * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-PairingEventType
+ */
+chrome.bluetoothPrivate.PairingEventType = {
+  REQUEST_PINCODE: '',
+  DISPLAY_PINCODE: '',
+  REQUEST_PASSKEY: '',
+  DISPLAY_PASSKEY: '',
+  KEYS_ENTERED: '',
+  CONFIRM_PASSKEY: '',
+  REQUEST_AUTHORIZATION: '',
+  COMPLETE: '',
+};
+
+
+/**
+ * @enum {string}
+ * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-ConnectResultType
+ */
+chrome.bluetoothPrivate.ConnectResultType = {
+  ALREADY_CONNECTED: '',
+  ATTRIBUTE_LENGTH_INVALID: '',
+  AUTH_CANCELED: '',
+  AUTH_FAILED: '',
+  AUTH_REJECTED: '',
+  AUTH_TIMEOUT: '',
+  CONNECTION_CONGESTED: '',
+  FAILED: '',
+  IN_PROGRESS: '',
+  INSUFFICIENT_ENCRYPTION: '',
+  OFFSET_INVALID: '',
+  READ_NOT_PERMITTED: '',
+  REQUEST_NOT_SUPPORTED: '',
+  SUCCESS: '',
+  UNKNOWN_ERROR: '',
+  UNSUPPORTED_DEVICE: '',
+  WRITE_NOT_PERMITTED: '',
+};
+
+
+/**
+ * @enum {string}
+ * @see https://developer.chrome.com/extensions/bluetoothPrivate#type-TransportType
+ */
+chrome.bluetoothPrivate.TransportType = {
+  LE: '',
+  BREDR: '',
+  DUAL: '',
+};
+
 
 /**
  * @const
diff --git a/third_party/closure_compiler/runner/runner.jar b/third_party/closure_compiler/runner/runner.jar
index ba2a03b..8594a93 100644
--- a/third_party/closure_compiler/runner/runner.jar
+++ b/third_party/closure_compiler/runner/runner.jar
Binary files differ
diff --git a/third_party/dom_distiller_js/README.chromium b/third_party/dom_distiller_js/README.chromium
index 1c6c7af..a06490b 100644
--- a/third_party/dom_distiller_js/README.chromium
+++ b/third_party/dom_distiller_js/README.chromium
@@ -1,6 +1,6 @@
 Name: dom-distiller-js
 URL: https://github.com/chromium/dom-distiller
-Version: 54d05ba208
+Version: 6c16f14405
 License: BSD
 Security Critical: yes
 
diff --git a/third_party/google_toolbox_for_mac/BUILD.gn b/third_party/google_toolbox_for_mac/BUILD.gn
index 5791180..abbff2a 100644
--- a/third_party/google_toolbox_for_mac/BUILD.gn
+++ b/third_party/google_toolbox_for_mac/BUILD.gn
@@ -60,12 +60,16 @@
     ]
   } else {  # is_ios
     sources += [
+      "src/DebugUtils/GTMMethodCheck.h",
+      "src/DebugUtils/GTMMethodCheck.m",
       "src/Foundation/GTMLightweightProxy.h",
       "src/Foundation/GTMLightweightProxy.m",
 
       # GTMLogger is used by breakpad, which is still used on iOS.
       "src/Foundation/GTMLogger.h",
       "src/Foundation/GTMLogger.m",
+      "src/Foundation/GTMNSDictionary+URLArguments.h",
+      "src/Foundation/GTMNSDictionary+URLArguments.m",
       "src/Foundation/GTMNSString+URLArguments.h",
       "src/Foundation/GTMNSString+URLArguments.m",
       "src/iPhone/GTMFadeTruncatingLabel.h",
diff --git a/third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp b/third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp
index a39b6d7..1598250 100644
--- a/third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp
+++ b/third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp
@@ -45,11 +45,15 @@
         'src/AppKit/GTMUILocalizerAndLayoutTweaker.h',
         'src/AppKit/GTMUILocalizerAndLayoutTweaker.m',
         'src/DebugUtils/GTMDebugSelectorValidation.h',
+        'src/DebugUtils/GTMMethodCheck.h',
+        'src/DebugUtils/GTMMethodCheck.m',
         'src/DebugUtils/GTMTypeCasting.h',
         'src/Foundation/GTMLightweightProxy.h',
         'src/Foundation/GTMLightweightProxy.m',
         'src/Foundation/GTMLogger.h',
         'src/Foundation/GTMLogger.m',
+        'src/Foundation/GTMNSDictionary+URLArguments.h',
+        'src/Foundation/GTMNSDictionary+URLArguments.m',
         'src/Foundation/GTMNSString+URLArguments.h',
         'src/Foundation/GTMNSString+URLArguments.m',
         'src/Foundation/GTMServiceManagement.c',
@@ -83,7 +87,9 @@
         ['OS!="ios"', {
           'sources/': [
             ['exclude', '^src/iPhone/'],
+            ['exclude', '^src/DebugUtils/GTMMethodCheck\\.m$'],
             ['exclude', '^src/Foundation/GTMLogger\\.m$'],
+            ['exclude', '^src/Foundation/GTMNSDictionary\\+URLArguments\\.m$'],
           ],
           'link_settings': {
             'libraries': [
@@ -98,8 +104,10 @@
           'sources/': [
             # Exclude everything except what's needed for iOS.
             ['exclude', '\\.(c|m)$'],
+            ['include', '^src/DebugUtils/GTMMethodCheck\\.m$'],
             ['include', '^src/Foundation/GTMLightweightProxy\\.m$'],
             ['include', '^src/Foundation/GTMLogger\\.m$'],
+            ['include', '^src/Foundation/GTMNSDictionary\\+URLArguments\\.m$'],
             ['include', '^src/Foundation/GTMNSString\\+URLArguments\\.m$'],
             ['include', '^src/Foundation/GTMStringEncoding\\.m$'],
             ['include', '^src/iPhone/'],
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index 4a32303d..6d84c53 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -18,3 +18,6 @@
 removed or added files and update our build recipes in BUILD.gn and
 harfbuzz.gyp accordingly, update the NEWS file from HarfBuzz' release notes,
 and bump the version numbers in README.chromium.
+
+Applied a local fix for an infinite recursion crash in hb-coretext on OS X 10.9,
+skipping the font cascade list reconfiguration on this OS version.
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.cc b/third_party/harfbuzz-ng/src/hb-coretext.cc
index f4d9716..c5053734 100644
--- a/third_party/harfbuzz-ng/src/hb-coretext.cc
+++ b/third_party/harfbuzz-ng/src/hb-coretext.cc
@@ -145,6 +145,14 @@
     DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
     return NULL;
   }
+
+  /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
+   * bug indicate that the cascade list reconfiguration occasionally causes
+   * crashes in CoreText on OS X 10.9, thus let's skip this step on older
+   * operating system versions. */
+  if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < kCTVersionNumber10_10)
+    return ct_font;
+
   CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
 
   /* Create font copy with cascade list that has LastResort first; this speeds up CoreText
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index 969a4982..8e96d6d1 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -7,7 +7,7 @@
 
 Date: Thursday July 21 2016
 Branch: master
-Commit: 18c7f46c125c107fc08d31f617b2178482fed011
+Commit: 4b073bc39a39283577c485ed1e56c92cf0eaaa89
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index b4e42b2d..a8e4573 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  6
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "170-g18c7f46"
+#define VERSION_EXTRA  "173-g4b073bc"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.6.0-170-g18c7f46"
-#define VERSION_STRING      " v1.6.0-170-g18c7f46"
+#define VERSION_STRING_NOSP "v1.6.0-173-g4b073bc"
+#define VERSION_STRING      " v1.6.0-173-g4b073bc"
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 421fee4..520903da 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -854,6 +854,11 @@
       print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
       return 0
 
+  if use_head_revision:
+    # TODO(hans): Remove after the next roll.
+    global VERSION
+    VERSION = '4.0.0'
+
   global CLANG_REVISION, PACKAGE_VERSION
   if args.print_revision:
     if use_head_revision or args.llvm_force_head_revision:
diff --git a/tools/ipc_fuzzer/fuzzer/BUILD.gn b/tools/ipc_fuzzer/fuzzer/BUILD.gn
index 6a1dc83..17cadc1c 100644
--- a/tools/ipc_fuzzer/fuzzer/BUILD.gn
+++ b/tools/ipc_fuzzer/fuzzer/BUILD.gn
@@ -23,6 +23,6 @@
   if (is_asan && is_chromeos) {
     # Compiling fuzzer.cc with ASan takes too long, see
     # http://crbug.com/360158.
-    config -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
+    configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
   }
 }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 6cb0b3b..507d6fb 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -117,12 +117,12 @@
       'Chromium Mac 10.9 Goma Canary (dbg)': 'gn_debug_bot',
       'Chromium Mac 10.9 Goma Canary (dbg)(clobber)': 'gn_debug_bot',
       'Chromium Win PGO Builder': [
-        'gyp_official_chrome_pgo_phase_1_x86',
-        'gyp_official_chrome_pgo_phase_2_x86'
+        'gyp_official_optimize_chrome_pgo_phase_1_x86',
+        'gyp_official_optimize_chrome_pgo_phase_2_x86'
       ],
       'Chromium Win x64 PGO Builder': [
-        'gyp_official_chrome_pgo_phase_1_x64',
-        'gyp_official_chrome_pgo_phase_2_x64',
+        'gyp_official_optimize_chrome_pgo_phase_1_x64',
+        'gyp_official_optimize_chrome_pgo_phase_2_x64',
       ],
       'Chromium Windows Analyze': 'gn_windows_analyze',
       'CrWin7Goma': 'gn_release_bot_minimal_symbols_x86',
@@ -336,16 +336,16 @@
     },
 
     'chromium.lkgr': {
-      'ASAN Debug': 'gyp_asan_lsan_edge_debug_bot',
+      'ASAN Debug': 'gn_asan_lsan_edge_debug_bot',
       'ASAN Release Media':
-        'gyp_asan_lsan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot',
-      'ASAN Release': 'gyp_asan_lsan_edge_fuzzer_v8_heap_release_bot',
+        'gn_asan_lsan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot',
+      'ASAN Release': 'gn_asan_lsan_edge_fuzzer_v8_heap_release_bot',
       'ASan Debug (32-bit x86 with V8-ARM)':
-        'gyp_asan_edge_v8_heap_debug_bot_hybrid',
+        'gn_asan_edge_v8_heap_debug_bot_hybrid',
       'ASan Release (32-bit x86 with V8-ARM)':
-        'gyp_asan_edge_fuzzer_v8_heap_release_bot_hybrid',
+        'gn_asan_edge_fuzzer_v8_heap_release_bot_hybrid',
       'ASan Release Media (32-bit x86 with V8-ARM)':
-        'gyp_asan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid',
+        'gn_asan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid',
       'ChromiumOS ASAN Release':
         'gn_chromeos_asan_lsan_edge_fuzzer_v8_heap_release_bot',
       'MSAN Release (chained origins)': 'gn_msan_edge_release_bot',
@@ -354,11 +354,11 @@
       'Mac ASAN Release Media':
         'gyp_asan_edge_fuzzer_v8_heap_chrome_with_codecs_release_bot',
       'Mac ASAN Release': 'gyp_asan_edge_fuzzer_v8_heap_release_bot',
-      'TSAN Debug': 'gyp_tsan_disable_nacl_line_tables_debug_bot',
-      'TSAN Release': 'gyp_tsan_disable_nacl_line_tables_release_bot',
+      'TSAN Debug': 'gn_tsan_disable_nacl_line_tables_debug_bot',
+      'TSAN Release': 'gn_tsan_disable_nacl_line_tables_release_bot',
       'Telemetry Harness Upload': 'none',
-      'UBSan Release': 'gyp_ubsan_release_bot',
-      'UBSan vptr Release': 'gyp_ubsan_vptr_edge_release_bot',
+      'UBSan Release': 'gn_ubsan_release_bot',
+      'UBSan vptr Release': 'gn_ubsan_vptr_edge_release_bot',
       'Win ASan Release Coverage':
         'gyp_asan_edge_fuzzer_v8_heap_release_bot_x86',
       'Win ASan Release Media':
@@ -922,8 +922,8 @@
       'win_optional_gpu_tests_rel':
         'swarming_gpu_tests_deqp_gles_gn_release_trybot_x86',
       'win_pgo': [
-        'gyp_official_chrome_pgo_phase_1_x86',
-        'gyp_official_chrome_pgo_phase_2_x86',
+        'gyp_official_optimize_chrome_pgo_phase_1_x86',
+        'gyp_official_optimize_chrome_pgo_phase_2_x86',
       ],
       'win_upload_clang': 'gn_release_bot',
       'win_chrome_official': 'gn_official_goma_minimal_symbols_x86',
@@ -1255,17 +1255,17 @@
       'gn', 'ubsan_vptr', 'ubsan_no_recover_hack', 'release_bot',
     ],
 
-    'gyp_asan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid': [
-      'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'chromeos_codecs',
+    'gn_asan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid': [
+      'gn', 'asan', 'edge', 'fuzzer', 'v8_heap', 'chromeos_codecs',
       'release_bot', 'hybrid',
     ],
 
-    'gyp_asan_edge_v8_heap_debug_bot_hybrid': [
+    'gn_asan_edge_v8_heap_debug_bot_hybrid': [
       'gyp', 'asan', 'edge', 'v8_heap', 'debug_bot', 'hybrid',
     ],
 
-    'gyp_asan_edge_fuzzer_v8_heap_release_bot_hybrid': [
-      'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', 'hybrid',
+    'gn_asan_edge_fuzzer_v8_heap_release_bot_hybrid': [
+      'gn', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', 'hybrid',
     ],
 
     'gyp_asan_edge_fuzzer_v8_heap_release_bot_x86': [
@@ -1298,17 +1298,13 @@
       'gn', 'asan', 'lsan', 'edge', 'debug_bot',
     ],
 
-    'gyp_asan_lsan_edge_debug_bot': [
-      'gyp', 'asan', 'lsan', 'edge', 'debug_bot',
-    ],
-
-    'gyp_asan_lsan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot': [
-      'gyp', 'asan', 'lsan', 'edge', 'v8_heap', 'chromeos_codecs',
+    'gn_asan_lsan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot': [
+      'gn', 'asan', 'lsan', 'edge', 'v8_heap', 'chromeos_codecs',
       'release_bot',
     ],
 
-    'gyp_asan_lsan_edge_fuzzer_v8_heap_release_bot': [
-      'gyp', 'asan', 'lsan', 'edge', 'fuzzer', 'v8_heap', 'release_bot',
+    'gn_asan_lsan_edge_fuzzer_v8_heap_release_bot': [
+      'gn', 'asan', 'lsan', 'edge', 'fuzzer', 'v8_heap', 'release_bot',
     ],
 
     'gn_asan_lsan_edge_fuzzer_v8_heap_symbolized_release_bot': [
@@ -1381,7 +1377,23 @@
     ],
 
     'gyp_official_chrome_pgo_phase_2_x86': [
-      'gyp', 'official', 'chrome_pgo_phase_2', 'x86',
+      'gyp', 'official_optimize', 'chrome_pgo_phase_2', 'x86',
+    ],
+
+    'gyp_official_optimize_chrome_pgo_phase_1_x64': [
+      'gyp', 'official_optimize', 'chrome_pgo_phase_1', 'x64',
+    ],
+
+    'gyp_official_optimize_chrome_pgo_phase_2_x64': [
+      'gyp', 'official_optimize', 'chrome_pgo_phase_2', 'x64',
+    ],
+
+    'gyp_official_optimize_chrome_pgo_phase_1_x86': [
+      'gyp', 'official_optimize', 'chrome_pgo_phase_1', 'x86',
+    ],
+
+    'gyp_official_optimize_chrome_pgo_phase_2_x86': [
+      'gyp', 'official_optimize', 'chrome_pgo_phase_2', 'x86',
     ],
 
     'gyp_official_x64': [
@@ -1408,20 +1420,20 @@
       'gyp', 'syzyasan', 'no_pch', 'win_z7', 'x86',
     ],
 
-    'gyp_tsan_disable_nacl_line_tables_debug_bot': [
-      'gyp', 'tsan', 'disable_nacl', 'line_tables', 'debug_bot',
+    'gn_tsan_disable_nacl_line_tables_debug_bot': [
+      'gn', 'tsan', 'disable_nacl', 'line_tables', 'debug_bot',
     ],
 
-    'gyp_tsan_disable_nacl_line_tables_release_bot': [
-      'gyp', 'tsan', 'disable_nacl', 'line_tables', 'release_bot',
+    'gn_tsan_disable_nacl_line_tables_release_bot': [
+      'gn', 'tsan', 'disable_nacl', 'line_tables', 'release_bot',
     ],
 
-    'gyp_ubsan_release_bot': [
-      'gyp', 'ubsan', 'release_bot',
+    'gn_ubsan_release_bot': [
+      'gn', 'ubsan', 'release_bot',
     ],
 
-    'gyp_ubsan_vptr_edge_release_bot': [
-      'gyp', 'ubsan_vptr', 'edge', 'release_bot',
+    'gn_ubsan_vptr_edge_release_bot': [
+      'gn', 'ubsan_vptr', 'edge', 'release_bot',
     ],
 
     # The 'ios' configs are just used for auditing. iOS bots
@@ -2223,9 +2235,14 @@
     },
 
     'official': {
-      'gn_args': ('is_chrome_branded=true is_official_build=true '
-                  'is_debug=false'),
-      'gyp_defines': 'branding=Chrome buildtype=Official',
+      'mixins': ['official_optimize'],
+      'gn_args': 'is_chrome_branded=true',
+      'gyp_defines': 'branding=Chrome',
+    },
+
+    'official_optimize': {
+      'gn_args': 'is_official_build=true is_debug=false',
+      'gyp_defines': 'buildtype=Official',
     },
 
     'ozone': {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 13c1695..0f798ce 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -13520,6 +13520,14 @@
   <obsolete>Removed from codebase.</obsolete>
 </action>
 
+<action name="Signin_MoreButton_Shown">
+  <owner>gogerald@chromium.org</owner>
+  <owner>bzanotti@chromium.org</owner>
+  <description>
+    Recorded when the More button is shown on the sign in confirmation screen.
+  </description>
+</action>
+
 <action name="Signin_Show_EnterpriseAccountPrompt">
   <owner>gogerald@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b3d546a8b..1e1a78e 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -5642,7 +5642,8 @@
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The length of time between a dangerous download appearing on the downloads
-    shelf, and the &quot;Dismiss&quot; button being clicked.
+    shelf, and the &quot;Dismiss&quot; button being clicked. Deprecated since
+    M54.
   </summary>
 </histogram>
 
@@ -35051,6 +35052,28 @@
   </summary>
 </histogram>
 
+<histogram name="NewTabPage.RequestThrottler.PerDay" units="requests">
+  <owner>jkrcal@chromium.org</owner>
+  <summary>
+    Records how many requests of the given type the browser tried to perform
+    each day where the type is specified by the _suffix of the histogram. The
+    histogram is emitted only after midnight of the given day passes - right
+    before the first following request (which can be several days later if the
+    user does not use Chrome in the meantime). The histogram counts requests
+    with both QUOTA_GRANTED and QUOTA_EXCEEDED status, i.e. the count can easily
+    exceed the daily quota. Forced requests are not counted here.
+  </summary>
+</histogram>
+
+<histogram name="NewTabPage.RequestThrottler.RequestStatus"
+    enum="NtpRequestThrottlerStatus">
+  <owner>jkrcal@chromium.org</owner>
+  <summary>
+    Records the status w.r.t. the quota for all requests of the given type. The
+    type of request is specified by the _suffix of the histogram.
+  </summary>
+</histogram>
+
 <histogram name="NewTabPage.SearchURLs.Total">
   <obsolete>
     Deprecated 2016-02 (and not recorded for some time before that).
@@ -37784,14 +37807,6 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.PaintTiming.ForegroundToFirstPaint" units="ms">
-  <owner>pkotwicz@chromium.org</owner>
-  <summary>
-    Measures the time from a background tab being switched to the foreground to
-    the time the first paint is performed, for main frame documents.
-  </summary>
-</histogram>
-
 <histogram name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"
     units="ms">
   <owner>ksakamoto@chromium.org</owner>
@@ -37934,9 +37949,6 @@
 
 <histogram name="PageLoad.Timing2.ForegroundToFirstPaint" units="ms">
   <owner>pkotwicz@chromium.org</owner>
-  <obsolete>
-    deprecated in favor of PageLoad.PaintTiming.ForegroundToFirstPaint
-  </obsolete>
   <summary>
     Measures the time from a background tab being switched to the foreground to
     the time the first paint is performed, for main frame documents.
@@ -40964,6 +40976,10 @@
 </histogram>
 
 <histogram name="PlatformFile.FlushTime" units="ms">
+  <obsolete>
+    Deprecated as of 2016-07 because the histogram's purpose of adding colour to
+    the description of File::Flush() has been fulfilled.
+  </obsolete>
   <owner>tnagel@chromium.org</owner>
   <summary>The time it takes to run File::Flush().</summary>
 </histogram>
@@ -81884,6 +81900,7 @@
   <int value="-1319688939" label="ignore-gpu-blacklist"/>
   <int value="-1302904242" label="enable-navigation-tracing"/>
   <int value="-1285021473" label="save-page-as-mhtml"/>
+  <int value="-1276912933" label="enable-quick-unlock-pin"/>
   <int value="-1271563519" label="enable-appcontainer"/>
   <int value="-1269084216" label="ash-md"/>
   <int value="-1268836676" label="disable-out-of-process-pdf"/>
@@ -82003,6 +82020,7 @@
   <int value="-488779992" label="blink-settings"/>
   <int value="-478462945" label="enable-ephemeral-apps"/>
   <int value="-475049740" label="disable-vr-shell"/>
+  <int value="-474322576" label="disable-quick-unlock-pin"/>
   <int value="-462205750" label="enable-service-worker-sync"/>
   <int value="-455203267" label="use_new_features_summary"/>
   <int value="-430360431" label="disable-password-generation"/>
@@ -85066,6 +85084,12 @@
   <int value="2" label="NTP Promo link clicked"/>
 </enum>
 
+<enum name="NtpRequestThrottlerStatus" type="int">
+  <int value="0" label="Forced request"/>
+  <int value="1" label="Quota granted"/>
+  <int value="2" label="Quota exceeded"/>
+</enum>
+
 <enum name="NtpSnippetsFetchResult" type="int">
   <int value="0" label="Success"/>
   <int value="1" label="Empty hosts"/>
@@ -100230,6 +100254,13 @@
   <affected-histogram name="Media.EME.RequestMediaKeySystemAccess"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="RequestThrottlerTypes">
+  <suffix name="SuggestionFetcher"
+      label="Fetcher for content suggestions on mobile NTP"/>
+  <affected-histogram name="NewTabPage.RequestThrottler.PerDay"/>
+  <affected-histogram name="NewTabPage.RequestThrottler.RequestStatus"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="ResourceLoaderSizeSlice" separator=".">
   <suffix name="LT_2kB" label="Sliced for resources smaller than 2kB."/>
   <suffix name="LT_32kB"
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py
index 3a82f439..e8e79c8 100644
--- a/tools/perf/benchmarks/smoothness.py
+++ b/tools/perf/benchmarks/smoothness.py
@@ -296,7 +296,11 @@
 
   @classmethod
   def ShouldDisable(cls, possible_browser):
-    return cls.IsSvelte(possible_browser)  # http://crbug.com/564008
+    return (
+       # http://crbug.com/564008
+       cls.IsSvelte(possible_browser) or
+       # http://crbug.com/630701
+       possible_browser.platform.GetDeviceTypeName() == 'Nexus 5X')
 
 
 @benchmark.Enabled('mac')
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index c79dfdc..71460af 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -32,11 +32,15 @@
 
 
 _DISABLED_TESTS = frozenset({
+  # crbug.com/630686
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:news:nytimes',  # pylint: disable=line-too-long
   # crbug.com/622409
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:news:cnn',  # pylint: disable=line-too-long
   # crbug.com/629123
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.browse:news:hackernews',  # pylint: disable=line-too-long
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.browse:news:nytimes',  # pylint: disable=line-too-long
+  # crbug.com/630765
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:news:reddit',  # pylint: disable=line-too-long
 })
 
 
diff --git a/tools/perf/benchmarks/v8.py b/tools/perf/benchmarks/v8.py
index 6d7eb7ac..ffadae43 100644
--- a/tools/perf/benchmarks/v8.py
+++ b/tools/perf/benchmarks/v8.py
@@ -240,9 +240,6 @@
 
 
 @benchmark.Disabled('reference')
-# TODO(crbug.com/617814): Temporarily disable this benchmark for mac. Scrolling
-# does not work on for google.com web page. Remove this once it is fixed.
-@benchmark.Disabled('mac')
 class V8MobileCodeSizeIgnition(_V8MemoryAndCodeSizeBenchmark):
   """Measures V8 heap and code size with ignition enabled on mobile web pages.
 
@@ -259,9 +256,6 @@
 
 
 @benchmark.Disabled('reference')
-# TODO(crbug.com/617914): Temporarily disable this benchmark for mac. Scrolling
-# does not work on for google.com web page. Remove this once it is fixed.
-@benchmark.Disabled('mac')
 class V8MobileCodeSize(_V8MemoryAndCodeSizeBenchmark):
   """Measures V8 heap and code size on mobile web pages.
 
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json
index ad01029..6c68215 100644
--- a/tools/perf/page_sets/data/system_health_mobile.json
+++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -65,9 +65,6 @@
         "system_health_mobile_014.wpr": [
             "browse:news:cnn"
         ],
-        "system_health_mobile_015.wpr": [
-            "browse:social:facebook"
-        ],
         "system_health_mobile_016.wpr": [
             "browse:news:hackernews"
         ],
@@ -77,9 +74,6 @@
         "system_health_mobile_018.wpr": [
             "browse:news:qq"
         ],
-        "system_health_mobile_019.wpr": [
-            "browse:news:reddit"
-        ],
         "system_health_mobile_021.wpr": [
             "browse:news:washingtonpost"
         ],
@@ -94,6 +88,12 @@
         ],
         "system_health_mobile_025.wpr": [
             "browse:news:flipboard"
+        ],
+        "system_health_mobile_026.wpr": [
+            "browse:social:facebook"
+        ],
+        "system_health_mobile_027.wpr": [
+            "browse:news:reddit"
         ]
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
diff --git a/tools/perf/page_sets/data/system_health_mobile_026.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_026.wpr.sha1
new file mode 100644
index 0000000..3a10412b
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_026.wpr.sha1
@@ -0,0 +1 @@
+06c515c82c7f750766b75fef81f1ef2ed9fdc460
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile_027.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_027.wpr.sha1
new file mode 100644
index 0000000..f97c38e
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_027.wpr.sha1
@@ -0,0 +1 @@
+67e8d07bce769132a282f93303bd06bad2c5810d
\ No newline at end of file
diff --git a/tools/perf/page_sets/login_helpers/mobile_facebook_login.py b/tools/perf/page_sets/login_helpers/facebook_login.py
similarity index 98%
rename from tools/perf/page_sets/login_helpers/mobile_facebook_login.py
rename to tools/perf/page_sets/login_helpers/facebook_login.py
index d8d20734..360cf28 100644
--- a/tools/perf/page_sets/login_helpers/mobile_facebook_login.py
+++ b/tools/perf/page_sets/login_helpers/facebook_login.py
@@ -4,7 +4,7 @@
 from page_sets.login_helpers import login_utils
 
 
-def LoginAccount(
+def LoginWithMobileSite(
     action_runner, credential,
     credentials_path=login_utils.DEFAULT_CREDENTIAL_PATH):
   """Logs in into mobile Facebook account.
diff --git a/tools/perf/page_sets/mobile_facebook_page.py b/tools/perf/page_sets/mobile_facebook_page.py
index edd93a04..0dc1438 100644
--- a/tools/perf/page_sets/mobile_facebook_page.py
+++ b/tools/perf/page_sets/mobile_facebook_page.py
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from page_sets.login_helpers import mobile_facebook_login
+from page_sets.login_helpers import facebook_login
 
 from telemetry.page import page as page_module
 
+
 class MobileFacebookPage(page_module.Page):
   def __init__(self, url, page_set, shared_page_state_class, name='facebook'):
     super(MobileFacebookPage, self).__init__(
@@ -13,6 +14,6 @@
         credentials_path='data/credentials.json',
         shared_page_state_class=shared_page_state_class)
   def RunNavigateSteps(self, action_runner):
-    mobile_facebook_login.LoginAccount(action_runner, 'facebook3',
+    facebook_login.LoginWithMobileSite(action_runner, 'facebook3',
                                        self.credentials_path)
     super(MobileFacebookPage, self).RunNavigateSteps(action_runner)
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index b6347a98..45c5dde 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -198,17 +198,14 @@
   ITEM_SELECTOR = '.hed > a'
   SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
   _CLOSE_BUTTON_SELECTOR = '.close'
-  _MAIL_BUTTON_SELECTOR = '.mailBlock'
 
   def _DidLoadDocument(self, action_runner):
     # Close the popup window. On Nexus 9 (and probably other tables) the popup
     # window does not have a "Close" button, instead it has only a "Send link
     # to phone" button. So on tablets we run with the popup window open. The
     # popup is transparent, so this is mostly an aesthetical issue.
-    action_runner.WaitForElement(selector="%s, %s" %
-        (self._CLOSE_BUTTON_SELECTOR, self._MAIL_BUTTON_SELECTOR))
-    has_close_button = action_runner.EvaluateJavaScript(
+    has_button = action_runner.EvaluateJavaScript(
         '!!document.querySelector("%s")' % self._CLOSE_BUTTON_SELECTOR)
-    if has_close_button:
+    if has_button:
       action_runner.ClickElement(selector=self._CLOSE_BUTTON_SELECTOR)
     super(WashingtonPostMobileStory, self)._DidLoadDocument(action_runner)
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py
index cb3e5efe..b470d769 100644
--- a/tools/perf/page_sets/system_health/loading_stories.py
+++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -178,18 +178,15 @@
   URL = 'https://www.washingtonpost.com/pwa'
   SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
   _CLOSE_BUTTON_SELECTOR = '.close'
-  _MAIL_BUTTON_SELECTOR = '.mailBlock'
 
   def _DidLoadDocument(self, action_runner):
     # Close the popup window. On Nexus 9 (and probably other tables) the popup
     # window does not have a "Close" button, instead it has only a "Send link
     # to phone" button. So on tablets we run with the popup window open. The
     # popup is transparent, so this is mostly an aesthetical issue.
-    action_runner.WaitForElement(selector="%s, %s" %
-        (self._CLOSE_BUTTON_SELECTOR, self._MAIL_BUTTON_SELECTOR))
-    has_close_button = action_runner.EvaluateJavaScript(
+    has_button = action_runner.EvaluateJavaScript(
         '!!document.querySelector("%s")' % self._CLOSE_BUTTON_SELECTOR)
-    if has_close_button:
+    if has_button:
       action_runner.ClickElement(selector=self._CLOSE_BUTTON_SELECTOR)
 
 
diff --git a/tools/perf/record_wpr b/tools/perf/record_wpr
index 90743c8..a87bc14 100755
--- a/tools/perf/record_wpr
+++ b/tools/perf/record_wpr
@@ -25,10 +25,9 @@
           'For best recording results, please run record_wpr with Python '
           'version 2.7.9 or after (See '
           'https://github.com/chromium/web-page-replay/issues/73 '
-          'for more information).'))
-
-  print ('For instructions on how to upgrade Python on Ubuntu 14.04, see:\n'
-         'http://mbless.de/blog/2016/01/09/upgrade-to-python-2711-on-ubuntu-1404-lts.html')
+          'for more information).\n'
+          'For instructions on how to upgrade Python on Ubuntu 14.04, see:\n'
+          'http://mbless.de/blog/2016/01/09/upgrade-to-python-2711-on-ubuntu-1404-lts.html'))
 
 
 if __name__ == '__main__':
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index 3328823..94033b2 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1218,8 +1218,8 @@
 
 UNINITIALIZED READ
 name=bug_176616_a
-*!WebTestRunner::WebTestProxyBase::didCreateDataSource
-*!WebTestRunner::WebTestProxy<>::didCreateDataSource
+*!WebTestRunner::WebViewTestProxyBase::didCreateDataSource
+*!WebTestRunner::WebViewTestProxy<>::didCreateDataSource
 *!blink::FrameLoaderClientImpl::createDocumentLoader
 *!blink::FrameLoader::init
 *!blink::Frame::init
diff --git a/ui/android/DEPS b/ui/android/DEPS
index 4935ec680..2f1d5f88 100644
--- a/ui/android/DEPS
+++ b/ui/android/DEPS
@@ -6,7 +6,7 @@
   "+cc/resources/scoped_ui_resource.h",
   "+cc/resources/ui_resource_client.h",
   "+cc/resources/ui_resource_bitmap.h",
-  "+cc/test/fake_layer_tree_host_client.h",
+  "+cc/test/stub_layer_tree_host_client.h",
   "+cc/test/test_task_graph_runner.h",
   "+cc/trees/layer_tree_host.h",
   "+jni",
diff --git a/ui/android/resources/resource_manager_impl_unittest.cc b/ui/android/resources/resource_manager_impl_unittest.cc
index c863b52..e3b6974 100644
--- a/ui/android/resources/resource_manager_impl_unittest.cc
+++ b/ui/android/resources/resource_manager_impl_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/macros.h"
 #include "cc/animation/animation_host.h"
 #include "cc/resources/ui_resource_bitmap.h"
-#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/stub_layer_tree_host_client.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_host.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -90,11 +90,10 @@
  public:
   ResourceManagerTest()
       : window_android_(WindowAndroid::createForTesting()),
-        resource_manager_(window_android_),
-        fake_client_(cc::FakeLayerTreeHostClient::DIRECT_3D) {
+        resource_manager_(window_android_) {
     cc::LayerTreeHost::InitParams params;
     cc::LayerTreeSettings settings;
-    params.client = &fake_client_;
+    params.client = &stub_client_;
     params.settings = &settings;
     params.task_graph_runner = &task_graph_runner_;
     params.animation_host =
@@ -127,7 +126,7 @@
   std::unique_ptr<MockLayerTreeHost> host_;
   TestResourceManagerImpl resource_manager_;
   cc::TestTaskGraphRunner task_graph_runner_;
-  cc::FakeLayerTreeHostClient fake_client_;
+  cc::StubLayerTreeHostClient stub_client_;
 };
 
 TEST_F(ResourceManagerTest, GetResource) {
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index e8b301d..783b1b4 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -58,11 +58,6 @@
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/x/x11_error_tracker.h"
 
-#if !defined(OS_CHROMEOS)
-#include "base/command_line.h"
-#include "ui/gfx/x/x11_switches.h"
-#endif
-
 #if defined(OS_FREEBSD)
 #include <sys/sysctl.h>
 #include <sys/types.h>
@@ -1417,7 +1412,9 @@
 }
 
 #if !defined(OS_CHROMEOS)
-void ChooseVisualForWindow(Visual** visual, int* depth) {
+void ChooseVisualForWindow(bool enable_transparent_visuals,
+                           Visual** visual,
+                           int* depth) {
   static Visual* s_visual = NULL;
   static int s_depth = 0;
 
@@ -1425,8 +1422,7 @@
     XDisplay* display = gfx::GetXDisplay();
     XAtom NET_WM_CM_S0 = XInternAtom(display, "_NET_WM_CM_S0", False);
 
-    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kEnableTransparentVisuals) &&
+    if (enable_transparent_visuals &&
         XGetSelectionOwner(display, NET_WM_CM_S0) != None) {
       // Choose the first ARGB8888 visual
       XVisualInfo visual_template;
@@ -1439,12 +1435,6 @@
         // Why support only 8888 ARGB? Because it's all that GTK+ supports. In
         // gdkvisual-x11.cc, they look for this specific visual and use it for
         // all their alpha channel using needs.
-        //
-        // TODO(erg): While the following does find a valid visual, some GL
-        // drivers
-        // don't believe that this has an alpha channel. According to marcheu@,
-        // this should work on open source driver though. (It doesn't work with
-        // NVidia's binaries currently.) http://crbug.com/369209
         const XVisualInfo& info = visual_list[i];
         if (info.depth == 32 && info.visual->red_mask == 0xff0000 &&
             info.visual->green_mask == 0x00ff00 &&
diff --git a/ui/base/x/x11_util_internal.h b/ui/base/x/x11_util_internal.h
index 3b7419d..6efc75f 100644
--- a/ui/base/x/x11_util_internal.h
+++ b/ui/base/x/x11_util_internal.h
@@ -51,7 +51,9 @@
 // supports transparency. NULL parameters are allowed to install or query the
 // cached visual and depth.
 #if !defined(OS_CHROMEOS)
-UI_BASE_X_EXPORT void ChooseVisualForWindow(Visual** visual, int* depth);
+UI_BASE_X_EXPORT void ChooseVisualForWindow(bool enable_transparent_visuals,
+                                            Visual** visual,
+                                            int* depth);
 #endif
 
 }  // namespace ui
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index b217cdd..1c3f3bc 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -29,6 +29,7 @@
 #include "cc/output/latency_info_swap_promise.h"
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/surfaces/surface_id_allocator.h"
+#include "cc/surfaces/surface_manager.h"
 #include "cc/trees/layer_tree_host.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/compositor/compositor_observer.h"
@@ -82,7 +83,8 @@
       widget_(gfx::kNullAcceleratedWidget),
       widget_valid_(false),
       output_surface_requested_(false),
-      surface_id_allocator_(context_factory->CreateSurfaceIdAllocator()),
+      surface_id_allocator_(new cc::SurfaceIdAllocator(
+          context_factory->AllocateSurfaceClientId())),
       task_runner_(task_runner),
       vsync_manager_(new CompositorVSyncManager()),
       device_scale_factor_(0.0f),
@@ -90,6 +92,10 @@
       compositor_lock_(NULL),
       layer_animator_collection_(this),
       weak_ptr_factory_(this) {
+  if (context_factory->GetSurfaceManager()) {
+    context_factory->GetSurfaceManager()->RegisterSurfaceClientId(
+        surface_id_allocator_->client_id());
+  }
   root_web_layer_ = cc::Layer::Create();
 
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -238,6 +244,10 @@
   host_.reset();
 
   context_factory_->RemoveCompositor(this);
+  if (context_factory_->GetSurfaceManager()) {
+    context_factory_->GetSurfaceManager()->InvalidateSurfaceClientId(
+        surface_id_allocator_->client_id());
+  }
 }
 
 void Compositor::SetOutputSurface(
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index ee39c59..05c3bcc 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -128,9 +128,8 @@
   // Gets the task graph runner.
   virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0;
 
-  // Creates a Surface ID allocator with a new namespace.
-  virtual std::unique_ptr<cc::SurfaceIdAllocator>
-  CreateSurfaceIdAllocator() = 0;
+  // Allocate a new client ID for the display compositor.
+  virtual uint32_t AllocateSurfaceClientId() = 0;
 
   // Gets the surface manager.
   virtual cc::SurfaceManager* GetSurfaceManager() = 0;
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index 30d73b1b..6e9b961 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -247,13 +247,8 @@
   return &task_graph_runner_;
 }
 
-std::unique_ptr<cc::SurfaceIdAllocator>
-InProcessContextFactory::CreateSurfaceIdAllocator() {
-  std::unique_ptr<cc::SurfaceIdAllocator> allocator(
-      new cc::SurfaceIdAllocator(next_surface_client_id_++));
-  if (surface_manager_)
-    allocator->RegisterSurfaceClientId(surface_manager_);
-  return allocator;
+uint32_t InProcessContextFactory::AllocateSurfaceClientId() {
+  return next_surface_client_id_++;
 }
 
 cc::SurfaceManager* InProcessContextFactory::GetSurfaceManager() {
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h
index e84cd285..6603fa1 100644
--- a/ui/compositor/test/in_process_context_factory.h
+++ b/ui/compositor/test/in_process_context_factory.h
@@ -60,7 +60,7 @@
   cc::SharedBitmapManager* GetSharedBitmapManager() override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
-  std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
+  uint32_t AllocateSurfaceClientId() override;
   cc::SurfaceManager* GetSurfaceManager() override;
   void ResizeDisplay(ui::Compositor* compositor,
                      const gfx::Size& size) override;
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
index fcf950b..a7cba9d 100644
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -164,7 +164,7 @@
     const MotionEvent& event,
     bool moved_beyond_slop_region) {
   static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) ==
-                    static_cast<int>(blink::WebTouchEvent::touchesLengthCap),
+                    static_cast<int>(blink::WebTouchEvent::kTouchesLengthCap),
                 "inconsistent maximum number of active touch points");
 
   blink::WebTouchEvent result;
@@ -180,7 +180,7 @@
   result.uniqueTouchEventId = event.GetUniqueEventId();
   result.touchesLength =
       std::min(static_cast<unsigned>(event.GetPointerCount()),
-               static_cast<unsigned>(WebTouchEvent::touchesLengthCap));
+               static_cast<unsigned>(WebTouchEvent::kTouchesLengthCap));
   DCHECK_GT(result.touchesLength, 0U);
 
   for (size_t i = 0; i < result.touchesLength; ++i)
diff --git a/ui/events/events_unittests.gyp b/ui/events/events_unittests.gyp
index f0f66c3..580ce3e 100644
--- a/ui/events/events_unittests.gyp
+++ b/ui/events/events_unittests.gyp
@@ -65,9 +65,6 @@
         'win/event_utils_win_unittest.cc',
         'x/events_x_unittest.cc',
       ],
-      'include_dirs': [
-        '../../testing/gmock/include',
-      ],
       'conditions': [
         ['use_x11==1', {
           'dependencies': [
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
index 3e8164a..540ffd7a5c 100644
--- a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
+++ b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
@@ -333,14 +333,9 @@
   if (!cursor_)
     return;  // No cursor!
 
-  // We may receive a request for a GESTURE_FLING_START with zero velocity; in
-  // this case send a ET_SCROLL_FLING_CANCEL in case it's needed to stop a
-  // fling in progress.
-  // TODO(wjmaclean): is it possible to get consecutive GESTURE_FLING_STARTs?
-  bool should_fling_start = fling->fling_state == GESTURES_FLING_START &&
-                            (fling->vx != 0 || fling->vy != 0);
   EventType type =
-      (should_fling_start ? ET_SCROLL_FLING_START : ET_SCROLL_FLING_CANCEL);
+      (fling->fling_state == GESTURES_FLING_START ? ET_SCROLL_FLING_START
+                                                  : ET_SCROLL_FLING_CANCEL);
 
   // Fling is like 2-finger scrolling but with velocity instead of displacement.
   dispatcher_->DispatchScrollEvent(ScrollEventParams(
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 cbe6d0e..b643f737 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1804,7 +1804,6 @@
 #list-container list li .detail-thumbnail {
   height: 28px;
   overflow: hidden;
-  position: absolute;
   width: 28px;
 }
 
@@ -1816,7 +1815,6 @@
   border-radius: 14px;
   height: 100%;
   opacity: 1;
-  position: absolute;
   width: 100%;
 }
 
diff --git a/ui/gfx/x/x11_switches.cc b/ui/gfx/x/x11_switches.cc
index fd48792..931bfb9 100644
--- a/ui/gfx/x/x11_switches.cc
+++ b/ui/gfx/x/x11_switches.cc
@@ -8,13 +8,6 @@
 namespace switches {
 
 #if !defined(OS_CHROMEOS)
-// When enabled, tries to get a transparent X11 visual so that we can have
-// per-pixel alpha in windows.
-//
-// TODO(erg): Remove this switch once we've stabilized the code
-// path. http://crbug.com/369209
-const char kEnableTransparentVisuals[] = "enable-transparent-visuals";
-
 // Color bit depth of the main window created in the browser process and matches
 // XWindowAttributes.depth.
 const char kWindowDepth[] = "window-depth";
diff --git a/ui/gfx/x/x11_switches.h b/ui/gfx/x/x11_switches.h
index dc445d4..64605b0 100644
--- a/ui/gfx/x/x11_switches.h
+++ b/ui/gfx/x/x11_switches.h
@@ -11,7 +11,6 @@
 namespace switches {
 
 #if !defined(OS_CHROMEOS)
-GFX_EXPORT extern const char kEnableTransparentVisuals[];
 GFX_EXPORT extern const char kWindowDepth[];
 GFX_EXPORT extern const char kX11Display[];
 GFX_EXPORT extern const char kX11VisualID[];
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
index ece1b8e..fb9eb78 100644
--- a/ui/gl/gl_context_cgl.cc
+++ b/ui/gl/gl_context_cgl.cc
@@ -206,7 +206,7 @@
 
 YUVToRGBConverter* GLContextCGL::GetYUVToRGBConverter() {
   if (!yuv_to_rgb_converter_)
-    yuv_to_rgb_converter_.reset(new YUVToRGBConverter);
+    yuv_to_rgb_converter_.reset(new YUVToRGBConverter(*GetVersionInfo()));
   return yuv_to_rgb_converter_.get();
 }
 
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index f990084..5930a32 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -30,7 +30,7 @@
 bool GLFence::IsSupported() {
   DCHECK(GetGLVersionInfo());
   return g_driver_gl.ext.b_GL_ARB_sync || GetGLVersionInfo()->is_es3 ||
-         GetGLImplementation() == kGLImplementationDesktopGLCoreProfile ||
+         GetGLVersionInfo()->is_desktop_core_profile ||
 #if defined(OS_MACOSX)
          g_driver_gl.ext.b_GL_APPLE_fence ||
 #else
@@ -52,7 +52,7 @@
   } else
 #endif
       if (g_driver_gl.ext.b_GL_ARB_sync || GetGLVersionInfo()->is_es3 ||
-          GetGLImplementation() == kGLImplementationDesktopGLCoreProfile) {
+          GetGLVersionInfo()->is_desktop_core_profile) {
     // Prefer ARB_sync which supports server-side wait.
     fence.reset(new GLFenceARB);
 #if defined(OS_MACOSX)
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index cb12bcc..033a129f 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -217,7 +217,7 @@
 }
 
 static inline GLenum GetTexType(GLenum type) {
-  if (GetGLImplementation() != kGLImplementationEGLGLES2) {
+  if (!g_version_info->is_es) {
     if (type == GL_HALF_FLOAT_OES)
       return GL_HALF_FLOAT_ARB;
   }
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h
index 3cf1178..fe333fa1 100644
--- a/ui/gl/test/gl_image_test_template.h
+++ b/ui/gl/test/gl_image_test_template.h
@@ -22,8 +22,8 @@
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_helper.h"
 #include "ui/gl/gl_image.h"
-#include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_version_info.h"
 #include "ui/gl/init/gl_factory.h"
 #include "ui/gl/test/gl_image_test_support.h"
 #include "ui/gl/test/gl_test_helper.h"
@@ -51,7 +51,7 @@
   );
   // clang-format on
 
-  bool is_gles = GetGLImplementation() == kGLImplementationEGLGLES2;
+  bool is_gles = GLContext::GetCurrent()->GetVersionInfo()->is_es;
   switch (target) {
     case GL_TEXTURE_2D:
       return GLHelper::LoadShader(
diff --git a/ui/gl/yuv_to_rgb_converter.cc b/ui/gl/yuv_to_rgb_converter.cc
index 95124f0..35c16ef 100644
--- a/ui/gl/yuv_to_rgb_converter.cc
+++ b/ui/gl/yuv_to_rgb_converter.cc
@@ -7,7 +7,7 @@
 #include "base/strings/stringize_macros.h"
 #include "base/strings/stringprintf.h"
 #include "ui/gl/gl_helper.h"
-#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_version_info.h"
 #include "ui/gl/scoped_api.h"
 #include "ui/gl/scoped_binders.h"
 
@@ -70,9 +70,8 @@
 
 }  // namespace
 
-YUVToRGBConverter::YUVToRGBConverter() {
-  bool use_core_profile =
-      GetGLImplementation() == kGLImplementationDesktopGLCoreProfile;
+YUVToRGBConverter::YUVToRGBConverter(const GLVersionInfo& gl_version_info) {
+  bool use_core_profile = gl_version_info.is_desktop_core_profile;
   ScopedSetGLToRealGLApi scoped_set_gl_api;
   glGenFramebuffersEXT(1, &framebuffer_);
   vertex_buffer_ = GLHelper::SetupQuadVertexBuffer();
diff --git a/ui/gl/yuv_to_rgb_converter.h b/ui/gl/yuv_to_rgb_converter.h
index c1d5e97e..7d9f8222 100644
--- a/ui/gl/yuv_to_rgb_converter.h
+++ b/ui/gl/yuv_to_rgb_converter.h
@@ -9,9 +9,11 @@
 
 namespace gl {
 
+struct GLVersionInfo;
+
 class YUVToRGBConverter {
  public:
-  YUVToRGBConverter();
+  explicit YUVToRGBConverter(const GLVersionInfo& gl_version_info);
   ~YUVToRGBConverter();
 
   // The input Y and UV textures should be bound to these texture objects
diff --git a/ui/shell_dialogs/select_file_dialog_mac.mm b/ui/shell_dialogs/select_file_dialog_mac.mm
index 1ac8122..bf5a86256 100644
--- a/ui/shell_dialogs/select_file_dialog_mac.mm
+++ b/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -310,8 +310,11 @@
       if (ext == default_extension)
         default_extension_index = i;
 
+      // Crash reports suggest that CreateUTIFromExtension may return nil. Hence
+      // we nil check before adding to |file_type_set|. See crbug.com/630101.
       base::ScopedCFTypeRef<CFStringRef> uti(CreateUTIFromExtension(ext));
-      [file_type_set addObject:base::mac::CFToNSCast(uti.get())];
+      if (uti)
+        [file_type_set addObject:base::mac::CFToNSCast(uti.get())];
 
       // Always allow the extension itself, in case the UTI doesn't map
       // back to the original extension correctly. This occurs with dynamic
diff --git a/ui/snapshot/screenshot_grabber.cc b/ui/snapshot/screenshot_grabber.cc
index 4534a857..ebccaae 100644
--- a/ui/snapshot/screenshot_grabber.cc
+++ b/ui/snapshot/screenshot_grabber.cc
@@ -24,6 +24,7 @@
 #include "ui/snapshot/snapshot.h"
 
 #if defined(USE_AURA)
+#include "ui/aura/client/cursor_client.h"
 #include "ui/aura/window.h"
 #endif
 
@@ -108,6 +109,35 @@
       base::Bind(EnsureLocalDirectoryExists, path, callback_on_blocking_pool));
 }
 
+#if defined(USE_AURA)
+class ScreenshotGrabber::ScopedCursorHider {
+ public:
+  // The nullptr might be returned when GetCursorClient is nullptr.
+  static std::unique_ptr<ScopedCursorHider> Create(aura::Window* window) {
+    DCHECK(window->IsRootWindow());
+    aura::client::CursorClient* cursor_client =
+        aura::client::GetCursorClient(window);
+    if (!cursor_client)
+      return nullptr;
+    cursor_client->HideCursor();
+    return std::unique_ptr<ScopedCursorHider>(
+        base::WrapUnique(new ScopedCursorHider(window)));
+  }
+
+  ~ScopedCursorHider() {
+    aura::client::CursorClient* cursor_client =
+        aura::client::GetCursorClient(window_);
+    cursor_client->ShowCursor();
+  }
+
+ private:
+  explicit ScopedCursorHider(aura::Window* window) : window_(window) {}
+  aura::Window* window_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedCursorHider);
+};
+#endif
+
 ScreenshotGrabber::ScreenshotGrabber(
     ScreenshotGrabberDelegate* client,
     scoped_refptr<base::TaskRunner> blocking_task_runner)
@@ -134,6 +164,8 @@
   aura::Window* aura_window = static_cast<aura::Window*>(window);
   is_partial = rect.size() != aura_window->bounds().size();
   window_identifier = aura_window->GetBoundsInScreen().ToString();
+
+  cursor_hider_ = ScopedCursorHider::Create(aura_window->GetRootWindow());
 #endif
   ui::GrabWindowSnapshotAsync(
       window, rect, blocking_task_runner_,
@@ -152,6 +184,9 @@
     ScreenshotGrabberObserver::Result screenshot_result,
     const base::FilePath& screenshot_path) {
   DCHECK(base::MessageLoopForUI::IsCurrent());
+#if defined(USE_AURA)
+  cursor_hider_.reset();
+#endif
   FOR_EACH_OBSERVER(ScreenshotGrabberObserver, observers_,
                     OnScreenshotCompleted(screenshot_result, screenshot_path));
 }
diff --git a/ui/snapshot/screenshot_grabber.h b/ui/snapshot/screenshot_grabber.h
index 4484be6..555f863 100644
--- a/ui/snapshot/screenshot_grabber.h
+++ b/ui/snapshot/screenshot_grabber.h
@@ -76,6 +76,10 @@
   bool HasObserver(const ScreenshotGrabberObserver* observer) const;
 
  private:
+#if defined(USE_AURA)
+  class ScopedCursorHider;
+#endif
+
   void GrabWindowSnapshotAsyncCallback(
       const std::string& window_identifier,
       base::FilePath screenshot_path,
@@ -91,6 +95,11 @@
   // Task runner for blocking tasks.
   scoped_refptr<base::TaskRunner> blocking_task_runner_;
 
+#if defined(USE_AURA)
+  // The object to hide cursor when taking screenshot.
+  std::unique_ptr<ScopedCursorHider> cursor_hider_;
+#endif
+
   base::ObserverList<ScreenshotGrabberObserver> observers_;
   base::WeakPtrFactory<ScreenshotGrabber> factory_;
 
diff --git a/ui/strings/translations/ui_strings_ca.xtb b/ui/strings/translations/ui_strings_ca.xtb
index fd9e5c2b..27f3d67 100644
--- a/ui/strings/translations/ui_strings_ca.xtb
+++ b/ui/strings/translations/ui_strings_ca.xtb
@@ -50,7 +50,7 @@
 <translation id="4320177379694898372">No hi ha connexió a Internet</translation>
 <translation id="436869212180315161">Prem</translation>
 <translation id="4588090240171750605">Desplaçament a la dreta</translation>
-<translation id="459417155289402299">Funció Quick Unlock</translation>
+<translation id="459417155289402299">Funció Desbloqueig ràpid</translation>
 <translation id="4820616160060340806">Ordre+<ph name="KEY_COMBO_NAME" /></translation>
 <translation id="4968171027979920686">{SECONDS,plural, =1{1 segon}other{# segons}}</translation>
 <translation id="4971687151119236543">Fitxer multimèdia: pista anterior</translation>
diff --git a/ui/strings/translations/ui_strings_it.xtb b/ui/strings/translations/ui_strings_it.xtb
index c99a64a7..4fd1c09c4 100644
--- a/ui/strings/translations/ui_strings_it.xtb
+++ b/ui/strings/translations/ui_strings_it.xtb
@@ -50,7 +50,7 @@
 <translation id="4320177379694898372">Nessuna connessione Internet</translation>
 <translation id="436869212180315161">Premi</translation>
 <translation id="4588090240171750605">Scorri a destra</translation>
-<translation id="459417155289402299">Funzione Sblocco rapido</translation>
+<translation id="459417155289402299">Funzione di sblocco rapido</translation>
 <translation id="4820616160060340806">Comando+<ph name="KEY_COMBO_NAME" /></translation>
 <translation id="4968171027979920686">{SECONDS,plural, =1{1 secondo}other{# secondi}}</translation>
 <translation id="4971687151119236543">Traccia precedente contenuti multimediali</translation>
diff --git a/ui/views/bubble/bubble_dialog_delegate_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_unittest.cc
index b72ee494..ea787f8d 100644
--- a/ui/views/bubble/bubble_dialog_delegate_unittest.cc
+++ b/ui/views/bubble/bubble_dialog_delegate_unittest.cc
@@ -11,7 +11,7 @@
 #include "ui/base/hit_test.h"
 #include "ui/events/event_utils.h"
 #include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/label_button.h"
 #include "ui/views/test/test_widget_observer.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
@@ -321,7 +321,7 @@
         BubbleDialogDelegateView::CreateBubble(bubble_delegate);
     bubble_widget->Show();
     BubbleFrameView* frame_view = bubble_delegate->GetBubbleFrameView();
-    ImageButton* close_button = frame_view->close_;
+    LabelButton* close_button = frame_view->close_;
     ASSERT_TRUE(close_button);
     frame_view->ButtonPressed(
         close_button,
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index a3f4bf16..43bac84 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -99,15 +99,15 @@
 BubbleFrameView::~BubbleFrameView() {}
 
 // static
-ImageButton* BubbleFrameView::CreateCloseButton(ButtonListener* listener) {
+LabelButton* BubbleFrameView::CreateCloseButton(ButtonListener* listener) {
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  ImageButton* close = new ImageButton(listener);
+  LabelButton* close = new LabelButton(listener, base::string16());
   close->SetImage(CustomButton::STATE_NORMAL,
-                  rb.GetImageNamed(IDR_CLOSE_DIALOG).ToImageSkia());
+                  *rb.GetImageNamed(IDR_CLOSE_DIALOG).ToImageSkia());
   close->SetImage(CustomButton::STATE_HOVERED,
-                  rb.GetImageNamed(IDR_CLOSE_DIALOG_H).ToImageSkia());
+                  *rb.GetImageNamed(IDR_CLOSE_DIALOG_H).ToImageSkia());
   close->SetImage(CustomButton::STATE_PRESSED,
-                  rb.GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia());
+                  *rb.GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia());
   close->SetBorder(nullptr);
   close->SetSize(close->GetPreferredSize());
 #if !defined(OS_WIN)
@@ -245,9 +245,7 @@
   const int title_padding = has_title ? title_margins_.height() : 0;
   const int title_height = std::max(icon_height, label_height) + title_padding;
   const int close_height = close_->visible() ? close_->height() : 0;
-  const int min_height = !has_title ? close_->height() : 0;
-  insets +=
-      gfx::Insets(std::max({title_height, close_height, min_height}), 0, 0, 0);
+  insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0);
   return insets;
 }
 
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h
index 72fd43a..90f1030c 100644
--- a/ui/views/bubble/bubble_frame_view.h
+++ b/ui/views/bubble/bubble_frame_view.h
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/views/controls/button/button.h"
-#include "ui/views/controls/button/image_button.h"
 #include "ui/views/window/non_client_view.h"
 
 namespace gfx {
@@ -36,7 +35,7 @@
   ~BubbleFrameView() override;
 
   // Creates a close button used in the corner of the dialog.
-  static ImageButton* CreateCloseButton(ButtonListener* listener);
+  static LabelButton* CreateCloseButton(ButtonListener* listener);
 
   // NonClientFrameView overrides:
   gfx::Rect GetBoundsForClientView() const override;
@@ -86,7 +85,7 @@
 
   bool close_button_clicked() const { return close_button_clicked_; }
 
-  ImageButton* GetCloseButtonForTest() { return close_; }
+  LabelButton* GetCloseButtonForTest() { return close_; }
 
  protected:
   // Returns the available screen bounds if the frame were to show in |rect|.
@@ -126,7 +125,7 @@
   // The optional title icon, title, and (x) close button.
   views::ImageView* title_icon_;
   Label* title_;
-  ImageButton* close_;
+  LabelButton* close_;
 
   // A view to contain the footnote view, if it exists.
   View* footnote_container_;
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index c8d4ebf..9e338c5 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -12,7 +12,6 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/bubble/bubble_border.h"
-#include "ui/views/controls/button/image_button.h"
 #include "ui/views/test/test_views.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
@@ -37,8 +36,7 @@
 // These account for non-client areas like the title bar, footnote etc. However
 // these do not take the bubble border into consideration.
 const int kExpectedAdditionalWidth = 12;
-// 12 for the builtin margin, 14 for the close button margin
-const int kExpectedAdditionalHeight = 12 + 14;
+const int kExpectedAdditionalHeight = 12;
 
 class TestBubbleFrameViewWidgetDelegate : public WidgetDelegate {
  public:
@@ -121,11 +119,9 @@
 
   int margin_x = frame.content_margins().left();
   int margin_y = frame.content_margins().top();
-  int close_y = frame.GetCloseButtonForTest()->height();
   gfx::Insets insets = frame.bubble_border()->GetInsets();
   EXPECT_EQ(insets.left() + margin_x, frame.GetBoundsForClientView().x());
-  EXPECT_EQ(insets.top() + margin_y + close_y,
-            frame.GetBoundsForClientView().y());
+  EXPECT_EQ(insets.top() + margin_y, frame.GetBoundsForClientView().y());
 }
 
 // Tests that the arrow is mirrored as needed to better fit the screen.
@@ -441,9 +437,6 @@
   // Expect that a border has been added to the minimum size.
   minimum_rect.Inset(frame.bubble_border()->GetInsets());
 
-  ImageButton* button = frame.GetCloseButtonForTest();
-  EXPECT_EQ(button->height(), 14);
-  EXPECT_EQ(nullptr, frame.GetCloseButtonForTest()->border());
   gfx::Size expected_size(kMinimumClientWidth + kExpectedAdditionalWidth,
                           kMinimumClientHeight + kExpectedAdditionalHeight);
   EXPECT_EQ(expected_size, minimum_rect.size());
diff --git a/ui/views/controls/button/toggle_button.cc b/ui/views/controls/button/toggle_button.cc
index 9d700a8b..4a4cb3d 100644
--- a/ui/views/controls/button/toggle_button.cc
+++ b/ui/views/controls/button/toggle_button.cc
@@ -4,6 +4,8 @@
 
 #include "ui/views/controls/button/toggle_button.h"
 
+#include "third_party/skia/include/core/SkDrawLooper.h"
+#include "third_party/skia/include/core/SkPaint.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/views/border.h"
@@ -16,10 +18,13 @@
 const int kTrackHeight = 14;
 const int kTrackWidth = 36;
 // Margins from edge of track to edge of view.
-const int kTrackVerticalMargin = 4;
-const int kTrackHorizontalMargin = 1;
-// Margin from edge of thumb to closest three edges of view.
-const int kThumbMargin = 1;
+const int kTrackVerticalMargin = 6;
+const int kTrackHorizontalMargin = 2;
+// Margin from edge of thumb to closest edge of view. Note that the thumb
+// margins must be sufficiently large to allow space for the shadow.
+const int kThumbHorizontalMargin = 2;
+// Margin from top/bottom edge of thumb to top/bottom edge of view.
+const int kThumbVerticalMargin = 3;
 
 }  // namespace
 
@@ -57,38 +62,43 @@
   SkAlpha blend =
       static_cast<SkAlpha>(SK_AlphaOPAQUE * slide_animation_.GetCurrentValue());
 
-  gfx::RectF track_rect(GetContentsBounds());
-  SkPaint paint;
-  paint.setAntiAlias(true);
-
   // Track.
+  gfx::RectF track_rect(GetContentsBounds());
+  SkPaint track_paint;
+  track_paint.setAntiAlias(true);
   const SkColor track_on_color =
       SkColorSetA(GetNativeTheme()->GetSystemColor(
                       ui::NativeTheme::kColorId_CallToActionColor),
                   0xFF / 2);
   // TODO(estade): get this color from the theme.
   const SkColor track_off_color = SkColorSetA(SK_ColorBLACK, 0x61);
-  paint.setColor(
+  track_paint.setColor(
       color_utils::AlphaBlend(track_on_color, track_off_color, blend));
-  canvas->DrawRoundRect(track_rect, track_rect.height() / 2, paint);
+  canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint);
 
   // Thumb.
-  const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_CallToActionColor);
-  // TODO(estade): get this color from the theme.
-  const SkColor thumb_off_color = SkColorSetRGB(0xFA, 0xFA, 0xFA);
-  paint.setColor(
-      color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
   gfx::Rect thumb_bounds = GetLocalBounds();
-  thumb_bounds.Inset(gfx::Insets(kThumbMargin));
+  thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin));
   thumb_bounds.set_x(thumb_bounds.x() +
                      slide_animation_.GetCurrentValue() *
                          (thumb_bounds.width() - thumb_bounds.height()));
   thumb_bounds.set_width(thumb_bounds.height());
   thumb_bounds.set_x(GetMirroredXForRect(thumb_bounds));
+  SkPaint thumb_paint;
+  std::vector<gfx::ShadowValue> shadows;
+  shadows.emplace_back(gfx::Vector2d(0, 1), 5.f,
+                       SkColorSetA(SK_ColorBLACK, 0x99));
+  thumb_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows));
+  thumb_paint.setStyle(SkPaint::kStrokeAndFill_Style);
+  thumb_paint.setAntiAlias(true);
+  const SkColor thumb_on_color = GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_CallToActionColor);
+  // TODO(estade): get this color from the theme.
+  const SkColor thumb_off_color = SkColorSetRGB(0xFA, 0xFA, 0xFA);
+  thumb_paint.setColor(
+      color_utils::AlphaBlend(thumb_on_color, thumb_off_color, blend));
   canvas->DrawCircle(gfx::RectF(thumb_bounds).CenterPoint(),
-                     thumb_bounds.height() / 2.f, paint);
-  // TODO(estade): add a shadow to the thumb.
+                     thumb_bounds.height() / 2.f, thumb_paint);
 }
 
 void ToggleButton::NotifyClick(const ui::Event& event) {
diff --git a/ui/views/corewm/tooltip_aura.cc b/ui/views/corewm/tooltip_aura.cc
index f33eaca7..7bf43ad 100644
--- a/ui/views/corewm/tooltip_aura.cc
+++ b/ui/views/corewm/tooltip_aura.cc
@@ -29,13 +29,19 @@
 // be wrapped.
 const int kTooltipMaxWidthPixels = 400;
 
-// Corner radius of tooltip background used with Material Design.
-const float kTooltipCornerRadius = 2.f;
-
 // FIXME: get cursor offset from actual cursor size.
 const int kCursorOffsetX = 10;
 const int kCursorOffsetY = 15;
 
+// TODO(varkha): Update if native widget can be transparent on Linux.
+bool CanUseTranslucentTooltipWidget() {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  return false;
+#else
+  return ui::MaterialDesignController::IsModeMaterial();
+#endif
+}
+
 // Creates a widget of type TYPE_TOOLTIP
 views::Widget* CreateTooltipWidget(aura::Window* tooltip_window) {
   views::Widget* widget = new views::Widget;
@@ -47,10 +53,10 @@
   DCHECK(params.context);
   params.keep_on_top = true;
   params.accept_events = false;
-  if (ui::MaterialDesignController::IsModeMaterial()) {
+  if (CanUseTranslucentTooltipWidget())
     params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+  if (ui::MaterialDesignController::IsModeMaterial())
     params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
-  }
   widget->Init(params);
   return widget;
 }
@@ -119,8 +125,10 @@
   }
 
   void SetBackgroundColor(SkColor background_color) {
+    // Corner radius of tooltip background used with Material Design.
+    const float kTooltipCornerRadius = 2.f;
     views::Background* background =
-        ui::MaterialDesignController::IsModeMaterial()
+        CanUseTranslucentTooltipWidget()
             ? views::Background::CreateBackgroundPainter(
                   true, views::Painter::CreateSolidRoundRectPainter(
                             background_color, kTooltipCornerRadius))
diff --git a/ui/views/mus/surface_context_factory.cc b/ui/views/mus/surface_context_factory.cc
index 36d2d68..5a697ee 100644
--- a/ui/views/mus/surface_context_factory.cc
+++ b/ui/views/mus/surface_context_factory.cc
@@ -90,10 +90,8 @@
   return raster_thread_helper_.task_graph_runner();
 }
 
-std::unique_ptr<cc::SurfaceIdAllocator>
-SurfaceContextFactory::CreateSurfaceIdAllocator() {
-  return base::WrapUnique(
-      new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
+uint32_t SurfaceContextFactory::AllocateSurfaceClientId() {
+  return next_surface_id_namespace_++;
 }
 
 cc::SurfaceManager* SurfaceContextFactory::GetSurfaceManager() {
diff --git a/ui/views/mus/surface_context_factory.h b/ui/views/mus/surface_context_factory.h
index b62ed00..c0aa550c 100644
--- a/ui/views/mus/surface_context_factory.h
+++ b/ui/views/mus/surface_context_factory.h
@@ -47,7 +47,7 @@
   cc::SharedBitmapManager* GetSharedBitmapManager() override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
-  std::unique_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
+  uint32_t AllocateSurfaceClientId() override;
   cc::SurfaceManager* GetSurfaceManager() override;
   void ResizeDisplay(ui::Compositor* compositor,
                      const gfx::Size& size) override;
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc
index ba6ee94..6ad4195 100644
--- a/ui/views/mus/window_manager_connection.cc
+++ b/ui/views/mus/window_manager_connection.cc
@@ -20,7 +20,7 @@
 #include "ui/views/mus/clipboard_mus.h"
 #include "ui/views/mus/native_widget_mus.h"
 #include "ui/views/mus/screen_mus.h"
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 #include "ui/views/touch_event_watcher.h"
 #include "ui/views/views_delegate.h"
 
@@ -95,12 +95,11 @@
                              ui::mojom::SurfaceType::DEFAULT);
 }
 
-void WindowManagerConnection::AddPointerDownWatcher(
-    PointerDownWatcher* watcher) {
+void WindowManagerConnection::AddPointerWatcher(PointerWatcher* watcher) {
   // TODO(riajiang): Support multiple event matchers (crbug.com/627146).
   DCHECK(!HasTouchEventWatcher());
-  bool had_watcher = HasPointerDownWatcher();
-  pointer_down_watchers_.AddObserver(watcher);
+  bool had_watcher = HasPointerWatcher();
+  pointer_watchers_.AddObserver(watcher);
   if (!had_watcher) {
     // Start a watcher for pointer down.
     // TODO(jamescook): Extend event observers to handle multiple event types.
@@ -111,18 +110,17 @@
   }
 }
 
-void WindowManagerConnection::RemovePointerDownWatcher(
-    PointerDownWatcher* watcher) {
-  pointer_down_watchers_.RemoveObserver(watcher);
-  if (!HasPointerDownWatcher()) {
-    // Last PointerDownWatcher removed, stop the event observer.
+void WindowManagerConnection::RemovePointerWatcher(PointerWatcher* watcher) {
+  pointer_watchers_.RemoveObserver(watcher);
+  if (!HasPointerWatcher()) {
+    // Last PointerWatcher removed, stop the event observer.
     client_->SetEventObserver(nullptr);
   }
 }
 
 void WindowManagerConnection::AddTouchEventWatcher(TouchEventWatcher* watcher) {
   // TODO(riajiang): Support multiple event matchers (crbug.com/627146).
-  DCHECK(!HasPointerDownWatcher());
+  DCHECK(!HasPointerWatcher());
   bool had_watcher = HasTouchEventWatcher();
   touch_event_watchers_.AddObserver(watcher);
   if (!had_watcher) {
@@ -170,12 +168,11 @@
       std::map<std::string, std::vector<uint8_t>>()));
 }
 
-bool WindowManagerConnection::HasPointerDownWatcher() {
+bool WindowManagerConnection::HasPointerWatcher() {
   // Check to see if we really have any observers left. This doesn't use
   // base::ObserverList<>::might_have_observers() because that returns true
   // during iteration over the list even when the last observer is removed.
-  base::ObserverList<PointerDownWatcher>::Iterator iterator(
-      &pointer_down_watchers_);
+  base::ObserverList<PointerWatcher>::Iterator iterator(&pointer_watchers_);
   return !!iterator.GetNext();
 }
 
@@ -212,13 +209,13 @@
   // to store screen coordinates. Screen coordinates really should be returned
   // separately. See http://crbug.com/608547
   gfx::Point location_in_screen = event.AsLocatedEvent()->root_location();
-  if (HasPointerDownWatcher()) {
+  if (HasPointerWatcher()) {
     if (event.type() == ui::ET_MOUSE_PRESSED) {
-      FOR_EACH_OBSERVER(PointerDownWatcher, pointer_down_watchers_,
+      FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_,
                         OnMousePressed(*event.AsMouseEvent(),
                                        location_in_screen, target_widget));
     } else if (event.type() == ui::ET_TOUCH_PRESSED) {
-      FOR_EACH_OBSERVER(PointerDownWatcher, pointer_down_watchers_,
+      FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_,
                         OnTouchPressed(*event.AsTouchEvent(),
                                        location_in_screen, target_widget));
     }
diff --git a/ui/views/mus/window_manager_connection.h b/ui/views/mus/window_manager_connection.h
index 6d05fb2..867e97b 100644
--- a/ui/views/mus/window_manager_connection.h
+++ b/ui/views/mus/window_manager_connection.h
@@ -27,7 +27,7 @@
 namespace views {
 class ClipboardMus;
 class NativeWidget;
-class PointerDownWatcher;
+class PointerWatcher;
 class TouchEventWatcher;
 class ScreenMus;
 namespace internal {
@@ -65,8 +65,8 @@
       const Widget::InitParams& init_params,
       internal::NativeWidgetDelegate* delegate);
 
-  void AddPointerDownWatcher(PointerDownWatcher* watcher);
-  void RemovePointerDownWatcher(PointerDownWatcher* watcher);
+  void AddPointerWatcher(PointerWatcher* watcher);
+  void RemovePointerWatcher(PointerWatcher* watcher);
 
   void AddTouchEventWatcher(TouchEventWatcher* watcher);
   void RemoveTouchEventWatcher(TouchEventWatcher* watcher);
@@ -80,7 +80,7 @@
                           const shell::Identity& identity);
 
   // Returns true if there is one or more watchers for this client.
-  bool HasPointerDownWatcher();
+  bool HasPointerWatcher();
   bool HasTouchEventWatcher();
 
   // ui::WindowTreeClientDelegate:
@@ -97,7 +97,7 @@
   std::unique_ptr<ScreenMus> screen_;
   std::unique_ptr<ui::WindowTreeClient> client_;
   // Must be empty on destruction.
-  base::ObserverList<PointerDownWatcher, true> pointer_down_watchers_;
+  base::ObserverList<PointerWatcher, true> pointer_watchers_;
   base::ObserverList<TouchEventWatcher, true> touch_event_watchers_;
 
   DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);
diff --git a/ui/views/mus/window_manager_connection_unittest.cc b/ui/views/mus/window_manager_connection_unittest.cc
index eaf51f4..e84d9ea 100644
--- a/ui/views/mus/window_manager_connection_unittest.cc
+++ b/ui/views/mus/window_manager_connection_unittest.cc
@@ -9,17 +9,17 @@
 #include "base/message_loop/message_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event.h"
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 #include "ui/views/test/scoped_views_test_helper.h"
 #include "ui/views/touch_event_watcher.h"
 
 namespace views {
 namespace {
 
-class TestPointerDownWatcher : public PointerDownWatcher {
+class TestPointerWatcher : public PointerWatcher {
  public:
-  TestPointerDownWatcher() {}
-  ~TestPointerDownWatcher() override {}
+  TestPointerWatcher() {}
+  ~TestPointerWatcher() override {}
 
   bool mouse_pressed() const { return mouse_pressed_; }
   bool touch_pressed() const { return touch_pressed_; }
@@ -29,7 +29,7 @@
     touch_pressed_ = false;
   }
 
-  // PointerDownWatcher:
+  // PointerWatcher:
   void OnMousePressed(const ui::MouseEvent& event,
                       const gfx::Point& location_in_screen,
                       Widget* target) override {
@@ -45,7 +45,7 @@
   bool mouse_pressed_ = false;
   bool touch_pressed_ = false;
 
-  DISALLOW_COPY_AND_ASSIGN(TestPointerDownWatcher);
+  DISALLOW_COPY_AND_ASSIGN(TestPointerWatcher);
 };
 
 }  // namespace
@@ -88,7 +88,7 @@
   DISALLOW_COPY_AND_ASSIGN(WindowManagerConnectionTest);
 };
 
-TEST_F(WindowManagerConnectionTest, PointerDownWatcher) {
+TEST_F(WindowManagerConnectionTest, PointerWatcher) {
   base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
   ScopedViewsTestHelper helper;
   WindowManagerConnection* connection = WindowManagerConnection::Get();
@@ -99,43 +99,43 @@
                                base::TimeTicks());
   ui::KeyEvent key_pressed(ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
 
-  // PointerDownWatchers receive mouse events.
-  TestPointerDownWatcher watcher1;
-  connection->AddPointerDownWatcher(&watcher1);
+  // PointerWatchers receive mouse events.
+  TestPointerWatcher watcher1;
+  connection->AddPointerWatcher(&watcher1);
   OnEventObserved(mouse_pressed);
   EXPECT_TRUE(watcher1.mouse_pressed());
   watcher1.Reset();
 
-  // PointerDownWatchers receive touch events.
+  // PointerWatchers receive touch events.
   OnEventObserved(touch_pressed);
   EXPECT_TRUE(watcher1.touch_pressed());
   watcher1.Reset();
 
-  // PointerDownWatchers do not trigger for key events.
+  // PointerWatchers do not trigger for key events.
   OnEventObserved(key_pressed);
   EXPECT_FALSE(watcher1.mouse_pressed());
   EXPECT_FALSE(watcher1.touch_pressed());
   watcher1.Reset();
 
-  // Two PointerDownWatchers can both receive a single observed event.
-  TestPointerDownWatcher watcher2;
-  connection->AddPointerDownWatcher(&watcher2);
+  // Two PointerWatchers can both receive a single observed event.
+  TestPointerWatcher watcher2;
+  connection->AddPointerWatcher(&watcher2);
   OnEventObserved(mouse_pressed);
   EXPECT_TRUE(watcher1.mouse_pressed());
   EXPECT_TRUE(watcher2.mouse_pressed());
   watcher1.Reset();
   watcher2.Reset();
 
-  // Removing the first PointerDownWatcher stops sending events to it.
-  connection->RemovePointerDownWatcher(&watcher1);
+  // Removing the first PointerWatcher stops sending events to it.
+  connection->RemovePointerWatcher(&watcher1);
   OnEventObserved(mouse_pressed);
   EXPECT_FALSE(watcher1.mouse_pressed());
   EXPECT_TRUE(watcher2.mouse_pressed());
   watcher1.Reset();
   watcher2.Reset();
 
-  // Removing the last PointerDownWatcher stops sending events to it.
-  connection->RemovePointerDownWatcher(&watcher2);
+  // Removing the last PointerWatcher stops sending events to it.
+  connection->RemovePointerWatcher(&watcher2);
   OnEventObserved(mouse_pressed);
   EXPECT_FALSE(watcher1.mouse_pressed());
   EXPECT_FALSE(watcher1.touch_pressed());
diff --git a/ui/views/pointer_down_watcher.h b/ui/views/pointer_watcher.h
similarity index 81%
rename from ui/views/pointer_down_watcher.h
rename to ui/views/pointer_watcher.h
index bad1d99..5ca10ef 100644
--- a/ui/views/pointer_down_watcher.h
+++ b/ui/views/pointer_watcher.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 UI_VIEWS_POINTER_DOWN_WATCHER_H_
-#define UI_VIEWS_POINTER_DOWN_WATCHER_H_
+#ifndef UI_VIEWS_POINTER_WATCHER_H_
+#define UI_VIEWS_POINTER_WATCHER_H_
 
 #include "base/macros.h"
 #include "ui/views/views_export.h"
@@ -26,9 +26,9 @@
 // NOTE: On mus this allows observation of events outside of windows owned
 // by the current process, in which case the |target| will be null. On mus
 // event.target() is always null.
-class VIEWS_EXPORT PointerDownWatcher {
+class VIEWS_EXPORT PointerWatcher {
  public:
-  PointerDownWatcher() {}
+  PointerWatcher() {}
   virtual void OnMousePressed(const ui::MouseEvent& event,
                               const gfx::Point& location_in_screen,
                               Widget* target) = 0;
@@ -37,12 +37,12 @@
                               Widget* target) = 0;
 
  protected:
-  virtual ~PointerDownWatcher() {}
+  virtual ~PointerWatcher() {}
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(PointerDownWatcher);
+  DISALLOW_COPY_AND_ASSIGN(PointerWatcher);
 };
 
 }  // namespace views
 
-#endif  // UI_VIEWS_POINTER_DOWN_WATCHER_H_
+#endif  // UI_VIEWS_POINTER_WATCHER_H_
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 107c82e..c810da3 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -282,7 +282,7 @@
       'native_theme_delegate.h',
       'painter.cc',
       'painter.h',
-      'pointer_down_watcher.h',
+      'pointer_watcher.h',
       'rect_based_targeting_utils.cc',
       'rect_based_targeting_utils.h',
       'repeat_controller.cc',
diff --git a/ui/views/views_exports.cc b/ui/views/views_exports.cc
index 5d3a976f..1aeec123 100644
--- a/ui/views/views_exports.cc
+++ b/ui/views/views_exports.cc
@@ -7,5 +7,5 @@
 // that linker will know to include the symbols, defined by these headers, in
 // the resulting dynamic library.
 
-#include "ui/views/pointer_down_watcher.h"
+#include "ui/views/pointer_watcher.h"
 #include "ui/views/touch_event_watcher.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 0475bf7..51fc0e45 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -1158,7 +1158,7 @@
 
   Visual* visual;
   int depth;
-  ui::ChooseVisualForWindow(&visual, &depth);
+  ui::ChooseVisualForWindow(true, &visual, &depth);
   if (depth == 32) {
     attribute_mask |= CWColormap;
     swa.colormap =
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index cf6ee51..41d666e 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -7,7 +7,7 @@
 #include <set>
 
 #include "base/bind.h"
-#include "base/command_line.h"
+#include "base/environment.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
@@ -3740,13 +3740,14 @@
     Widget::InitParams init_params,
     const Widget::InitParams::WindowOpacity opacity) {
 #if defined(USE_X11)
-  // On Linux, transparent visuals is currently not activated by default.
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  command_line->AppendSwitch(switches::kEnableTransparentVisuals);
-
+  // testing/xvfb.py runs xvfb and xcompmgr.
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  bool has_compositing_manager = env->HasVar("_CHROMIUM_INSIDE_XVFB");
   int depth = 0;
-  ui::ChooseVisualForWindow(NULL, &depth);
-  EXPECT_EQ(depth, 32);
+  ui::ChooseVisualForWindow(has_compositing_manager, NULL, &depth);
+
+  if (has_compositing_manager)
+    EXPECT_EQ(depth, 32);
 #endif
 
   init_params.opacity = opacity;
@@ -3758,7 +3759,8 @@
   widget.Init(init_params);
 
 #if defined(USE_X11)
-  EXPECT_TRUE(widget.IsTranslucentWindowOpacitySupported());
+  if (has_compositing_manager)
+    EXPECT_TRUE(widget.IsTranslucentWindowOpacitySupported());
 #endif
 }
 
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 0dc5a1ab..4366e51 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -222,14 +222,6 @@
   return !parent || (parent == ::GetDesktopWindow());
 }
 
-void AddScrollStylesToWindow(HWND window) {
-  if (::IsWindow(window)) {
-    long current_style = ::GetWindowLong(window, GWL_STYLE);
-    ::SetWindowLong(window, GWL_STYLE,
-                    current_style | WS_VSCROLL | WS_HSCROLL);
-  }
-}
-
 const int kTouchDownContextResetTimeout = 500;
 
 // Windows does not flag synthesized mouse messages from touch in all cases.
@@ -332,7 +324,6 @@
       is_first_nccalc_(true),
       menu_depth_(0),
       id_generator_(0),
-      needs_scroll_styles_(false),
       in_size_loop_(false),
       touch_down_contexts_(0),
       last_mouse_hwheel_time_(0),
@@ -357,28 +348,6 @@
 
   // Create the window.
   WindowImpl::Init(parent, bounds);
-  // TODO(ananta)
-  // Remove the scrolling hack code once we have scrolling working well.
-#if defined(ENABLE_SCROLL_HACK)
-  // Certain trackpad drivers on Windows have bugs where in they don't generate
-  // WM_MOUSEWHEEL messages for the trackpoint and trackpad scrolling gestures
-  // unless there is an entry for Chrome with the class name of the Window.
-  // These drivers check if the window under the trackpoint has the WS_VSCROLL/
-  // WS_HSCROLL style and if yes they generate the legacy WM_VSCROLL/WM_HSCROLL
-  // messages. We add these styles to ensure that trackpad/trackpoint scrolling
-  // work.
-  // TODO(ananta)
-  // Look into moving the WS_VSCROLL and WS_HSCROLL style setting logic to the
-  // CalculateWindowStylesFromInitParams function. Doing it there seems to
-  // cause some interactive tests to fail. Investigation needed.
-  if (IsTopLevelWindow(hwnd())) {
-    long current_style = ::GetWindowLong(hwnd(), GWL_STYLE);
-    if (!(current_style & WS_POPUP)) {
-      AddScrollStylesToWindow(hwnd());
-      needs_scroll_styles_ = true;
-    }
-  }
-#endif
 
   prop_window_target_.reset(new ui::ViewProp(hwnd(),
                             ui::WindowEventTarget::kWin32InputEventTarget,
@@ -1438,13 +1407,6 @@
 }
 
 void 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
-  // that a paint flicker does not occur while sizing.
-  if (in_size_loop_ && needs_scroll_styles_)
-    ShowScrollBar(hwnd(), SB_BOTH, FALSE);
-
   delegate_->HandleBeginWMSizeMove();
   SetMsgHandled(FALSE);
 }
@@ -1463,13 +1425,6 @@
 void HWNDMessageHandler::OnExitSizeMove() {
   delegate_->HandleEndWMSizeMove();
   SetMsgHandled(FALSE);
-  // Please refer to the notes in the OnSize function for information about
-  // the scrolling hack.
-  // We hide the Windows scrollbar in the OnEnterSizeMove function. We need
-  // to add the scroll styles back to ensure that scrolling works in legacy
-  // trackpoint drivers.
-  if (in_size_loop_ && needs_scroll_styles_)
-    AddScrollStylesToWindow(hwnd());
   // If the window was moved to a monitor which has a fullscreen window active,
   // we need to reduce the size of the fullscreen window by 1px.
   CheckAndHandleBackgroundFullscreenOnMonitor(hwnd());
@@ -1853,49 +1808,6 @@
   // us.
   LRESULT hit_test_code = DefWindowProc(hwnd(), WM_NCHITTEST, 0,
                                         MAKELPARAM(point.x(), point.y()));
-  if (needs_scroll_styles_) {
-    switch (hit_test_code) {
-      // If we faked the WS_VSCROLL and WS_HSCROLL styles for this window, then
-      // Windows returns the HTVSCROLL or HTHSCROLL hit test codes if we hover
-      // or click on the non client portions of the window where the OS
-      // scrollbars would be drawn. These hittest codes are returned even when
-      // the scrollbars are hidden, which is the case in Aura. We fake the
-      // hittest code as HTCLIENT in this case to ensure that we receive client
-      // mouse messages as opposed to non client mouse messages.
-      case HTVSCROLL:
-      case HTHSCROLL:
-        hit_test_code = HTCLIENT;
-        break;
-
-      case HTBOTTOMRIGHT: {
-        // Normally the HTBOTTOMRIGHT hittest code is received when we hover
-        // near the bottom right of the window. However due to our fake scroll
-        // styles, we get this code even when we hover around the area where
-        // the vertical scrollar down arrow would be drawn.
-        // We check if the hittest coordinates lie in this region and if yes
-        // we return HTCLIENT.
-        int border_width = ::GetSystemMetrics(SM_CXSIZEFRAME);
-        int border_height = ::GetSystemMetrics(SM_CYSIZEFRAME);
-        int scroll_width = ::GetSystemMetrics(SM_CXVSCROLL);
-        int scroll_height = ::GetSystemMetrics(SM_CYVSCROLL);
-        RECT window_rect;
-        ::GetWindowRect(hwnd(), &window_rect);
-        window_rect.bottom -= border_height;
-        window_rect.right -= border_width;
-        window_rect.left = window_rect.right - scroll_width;
-        window_rect.top = window_rect.bottom - scroll_height;
-        POINT pt;
-        pt.x = point.x();
-        pt.y = point.y();
-        if (::PtInRect(&window_rect, pt))
-          hit_test_code = HTCLIENT;
-        break;
-      }
-
-      default:
-        break;
-    }
-  }
   return hit_test_code;
 }
 
@@ -2143,19 +2055,6 @@
   // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
   // invoked OnSize we ensure the RootView has been laid out.
   ResetWindowRegion(false, true);
-
-  // We add the WS_VSCROLL and WS_HSCROLL styles to top level windows to ensure
-  // that legacy trackpad/trackpoint drivers generate the WM_VSCROLL and
-  // WM_HSCROLL messages and scrolling works.
-  // We want the scroll styles to be present on the window. However we don't
-  // want Windows to draw the scrollbars. To achieve this we hide the scroll
-  // bars and readd them to the window style in a posted task to ensure that we
-  // don't get nested WM_SIZE messages.
-  if (needs_scroll_styles_ && !in_size_loop_) {
-    ShowScrollBar(hwnd(), SB_BOTH, FALSE);
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&AddScrollStylesToWindow, hwnd()));
-  }
 }
 
 void HWNDMessageHandler::OnSysCommand(UINT notification_code,
@@ -2444,15 +2343,15 @@
   // TODO(ananta)
   // Windows does not reliably set the touch flag on mouse messages. Look into
   // a better way of identifying mouse messages originating from touch.
-  if (ui::IsMouseEventFromTouch(message)) {
+  if ((message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) &&
+      (ui::IsMouseEventFromTouch(message))) {
     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.
-    if (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) {
-      POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param_ht);
-      MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
-      l_param_ht = MAKELPARAM(screen_point.x, screen_point.y);
-    }
+    POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param_ht);
+    MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
+    l_param_ht = MAKELPARAM(screen_point.x, screen_point.y);
+
     LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht);
     if (hittest == HTCLIENT || hittest == HTNOWHERE)
       return 0;
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index 55d2d36..458addb3 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -609,9 +609,6 @@
   // Generates touch-ids for touch-events.
   ui::SequentialIDGenerator id_generator_;
 
-  // Indicates if the window needs the WS_VSCROLL and WS_HSCROLL styles.
-  bool needs_scroll_styles_;
-
   // Set to true if we are in the context of a sizing operation.
   bool in_size_loop_;
 
diff --git a/ui/webui/resources/cr_elements/network/cr_network_list.html b/ui/webui/resources/cr_elements/network/cr_network_list.html
index 2f6d373..7f77369 100644
--- a/ui/webui/resources/cr_elements/network/cr_network_list.html
+++ b/ui/webui/resources/cr_elements/network/cr_network_list.html
@@ -7,7 +7,7 @@
 
 <dom-module id="cr-network-list">
   <template>
-    <style>
+    <style include="cr-shared-style">
       #container {
         max-height: 1000px;
         min-height: 50px;
@@ -20,11 +20,11 @@
       }
 
       cr-network-list-network-item:not(:last-of-type) {
-        border-bottom: 1px solid lightgrey;
+        border-bottom: var(--cr-separator-line);
       }
 
       cr-network-list-custom-item {
-        border-top: 1px solid lightgrey;
+        border-top: var(--cr-separator-line);
       }
     </style>
     <iron-collapse opened="{{opened}}">
diff --git a/ui/webui/resources/cr_elements/network/cr_network_list_custom_item.html b/ui/webui/resources/cr_elements/network/cr_network_list_custom_item.html
index 5c473665..ffed609f 100644
--- a/ui/webui/resources/cr_elements/network/cr_network_list_custom_item.html
+++ b/ui/webui/resources/cr_elements/network/cr_network_list_custom_item.html
@@ -9,7 +9,7 @@
 <dom-module id="cr-network-list-custom-item">
   <template>
     <style include="cr-network-list-item-css"></style>
-    <div id="divOuter" hoverable>
+    <div id="divOuter" selectable>
       <div id="divIcon">
         <iron-icon id="icon"
             icon="[[itemState.polymerIcon]]"
diff --git a/ui/webui/resources/cr_elements/network/cr_network_list_item_css.html b/ui/webui/resources/cr_elements/network/cr_network_list_item_css.html
index ff78d31b..9633dd6 100644
--- a/ui/webui/resources/cr_elements/network/cr_network_list_item_css.html
+++ b/ui/webui/resources/cr_elements/network/cr_network_list_item_css.html
@@ -1,15 +1,13 @@
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+
 <!-- Common styles <cr-network-list/> items. -->
 <dom-module id="cr-network-list-item-css">
   <template>
-    <style>
+    <style include="cr-shared-style">
       :host {
         display: inline-block;
       }
 
-      span {
-        cursor: pointer;
-      }
-
       #divOuter {
         border-style: none;
         display: flex;
@@ -18,8 +16,13 @@
         padding: 4px;
       }
 
-      #divOuter[hoverable]:hover {
-        background-color: lightgrey;
+      [selectable] {
+        @apply(--cr-actionable);
+      }
+
+      /* TODO(stevenjb): remove once list item focus is fixed. */
+      [selectable]:hover {
+        background-color: var(--cr-focused-item-color);
       }
 
       #divIcon {
diff --git a/ui/webui/resources/cr_elements/network/cr_network_list_network_item.html b/ui/webui/resources/cr_elements/network/cr_network_list_network_item.html
index 77861ca..07504619 100644
--- a/ui/webui/resources/cr_elements/network/cr_network_list_network_item.html
+++ b/ui/webui/resources/cr_elements/network/cr_network_list_network_item.html
@@ -9,7 +9,7 @@
 <dom-module id="cr-network-list-network-item">
   <template>
     <style include="cr-network-list-item-css"></style>
-    <div id="divOuter" hoverable$="[[isListItem_(listItemType)]]">
+    <div id="divOuter" selectable$="[[isListItem_(listItemType)]]">
       <div id="divIcon">
         <cr-network-icon id="icon" is-list-item="[[isListItem_(listItemType)]]"
             network-state="[[networkState]]">
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html
index 1f6cf1a5..eff2d6bc 100644
--- a/ui/webui/resources/cr_elements/shared_style_css.html
+++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -1,4 +1,5 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 
 <!-- Common styles for Material Design WebUI. Included directly in
   settings_shared_css.html. -->
@@ -27,6 +28,10 @@
       .cancel-button {
         font-weight: 500;
       }
+
+      [actionable] {
+        @apply(--cr-actionable);
+      }
     </style>
   </template>
 </dom-module>
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html
new file mode 100644
index 0000000..dceff2a6
--- /dev/null
+++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -0,0 +1,12 @@
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+
+<!-- Common css variables for Material Design WebUI. -->
+<style is="custom-style">
+  :root {
+    --cr-actionable: {
+      cursor: pointer;
+    };
+    --cr-focused-item-color: var(--google-grey-300);
+    --cr-separator-line: 1px solid rgba(0, 0, 0, 0.06);
+  }
+</style>
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp
index 70fb239c..d3ebed1 100644
--- a/ui/webui/resources/cr_elements_resources.grdp
+++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -137,6 +137,9 @@
   <structure name="IDR_CR_ELEMENTS_CR_SHARED_STYLE_CSS_HTML"
              file="../../webui/resources/cr_elements/shared_style_css.html"
              type="chrome_html" />
+  <structure name="IDR_CR_ELEMENTS_CR_SHARED_VARS_CSS_HTML"
+             file="../../webui/resources/cr_elements/shared_vars_css.html"
+             type="chrome_html" />
   <structure name="IDR_CR_ELEMENTS_CR_SLIDER_HTML"
              file="../../webui/resources/cr_elements/cr_slider/cr_slider.html"
              type="chrome_html" />
diff --git a/ui/webui/resources/js/cr/ui/compiled_resources2.gyp b/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
index 1bc7c7f..afb4b27 100644
--- a/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
+++ b/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
@@ -20,6 +20,14 @@
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
+      'target_name': 'drag_wrapper',
+      'dependencies': [
+        '../../compiled_resources2.gyp:assert',
+        '../../compiled_resources2.gyp:cr',
+      ],
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'focus_grid',
       'dependencies': [
         '../../compiled_resources2.gyp:assert',
diff --git a/ui/webui/resources/js/cr/ui/drag_wrapper.js b/ui/webui/resources/js/cr/ui/drag_wrapper.js
index fc83d78..c2b17536 100644
--- a/ui/webui/resources/js/cr/ui/drag_wrapper.js
+++ b/ui/webui/resources/js/cr/ui/drag_wrapper.js
@@ -8,22 +8,45 @@
  * handle the nitty gritty of nested drag enters and leaves.
  */
 cr.define('cr.ui', function() {
+  /** @interface */
+  var DragWrapperDelegate = function() {};
+
+  // TODO(devlin): The only method this "delegate" actually needs is
+  // shouldAcceptDrag(); the rest can be events emitted by the DragWrapper.
+  DragWrapperDelegate.prototype = {
+    /**
+     * @param {MouseEvent} e The event for the drag.
+     * @return {boolean} Whether the drag should be accepted. If false,
+     *     subsequent methods (doDrag*) will not be called.
+     */
+    shouldAcceptDrag: assertNotReached,
+
+    /** @param {MouseEvent} e */
+    doDragEnter: assertNotReached,
+
+    /** @param {MouseEvent} e */
+    doDragLeave: assertNotReached,
+
+    /** @param {MouseEvent} e */
+    doDragOver: assertNotReached,
+
+    /** @param {MouseEvent} e */
+    doDrop: assertNotReached,
+  };
+
   /**
    * Creates a DragWrapper which listens for drag target events on |target| and
-   * delegates event handling to |handler|. The |handler| must implement:
-   *   shouldAcceptDrag
-   *   doDragEnter
-   *   doDragLeave
-   *   doDragOver
-   *   doDrop
+   * delegates event handling to |delegate|.
+   * @param {!Element} target
+   * @param {!cr.ui.DragWrapperDelegate} delegate
    * @constructor
    */
-  function DragWrapper(target, handler) {
-    this.initialize(target, handler);
+  function DragWrapper(target, delegate) {
+    this.initialize(target, delegate);
   }
 
   DragWrapper.prototype = {
-    initialize: function(target, handler) {
+    initialize: function(target, delegate) {
       target.addEventListener('dragenter',
                               this.onDragEnter_.bind(this));
       target.addEventListener('dragover', this.onDragOver_.bind(this));
@@ -31,7 +54,7 @@
       target.addEventListener('dragleave', this.onDragLeave_.bind(this));
 
       this.target_ = target;
-      this.handler_ = handler;
+      this.delegate_ = delegate;
     },
 
     /**
@@ -55,20 +78,20 @@
     },
 
     /**
-     * Handler for dragenter events fired on |target_|.
-     * @param {Event} e A MouseEvent for the drag.
+     * Delegate for dragenter events fired on |target_|.
+     * @param {MouseEvent} e A MouseEvent for the drag.
      * @private
      */
     onDragEnter_: function(e) {
       if (++this.dragEnters_ == 1) {
-        if (this.handler_.shouldAcceptDrag(e)) {
+        if (this.delegate_.shouldAcceptDrag(e)) {
           this.target_.classList.add('drag-target');
-          this.handler_.doDragEnter(e);
+          this.delegate_.doDragEnter(e);
         }
       } else {
         // Sometimes we'll get an enter event over a child element without an
         // over event following it. In this case we have to still call the
-        // drag over handler so that we make the necessary updates (one visible
+        // drag over delegate so that we make the necessary updates (one visible
         // symptom of not doing this is that the cursor's drag state will
         // flicker during drags).
         this.onDragOver_(e);
@@ -83,7 +106,7 @@
     onDragOver_: function(e) {
       if (!this.target_.classList.contains('drag-target'))
         return;
-      this.handler_.doDragOver(e);
+      this.delegate_.doDragOver(e);
     },
 
     /**
@@ -96,7 +119,7 @@
       if (!this.target_.classList.contains('drag-target'))
         return;
       this.target_.classList.remove('drag-target');
-      this.handler_.doDrop(e);
+      this.delegate_.doDrop(e);
     },
 
     /**
@@ -109,11 +132,12 @@
         return;
 
       this.target_.classList.remove('drag-target');
-      this.handler_.doDragLeave(e);
+      this.delegate_.doDragLeave(e);
     },
   };
 
   return {
-    DragWrapper: DragWrapper
+    DragWrapper: DragWrapper,
+    DragWrapperDelegate: DragWrapperDelegate,
   };
 });