diff --git a/BUILD.gn b/BUILD.gn
index e8b26f5..8c08120 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -931,6 +931,7 @@
     testonly = true
     data_deps = [
       "//content/shell:content_shell",
+      "//third_party/mesa:osmesa",
       "//tools/imagediff",
     ]
 
diff --git a/DEPS b/DEPS
index 4cd0bafd..a0ca4b7 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # 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': '16c2739bc02e8dec32a7d78b6878de4252aea1a7',
+  'v8_revision': '68b4bdf587f5da8bce63e56c1de7bae9c5f48997',
   # 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.
@@ -232,7 +232,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '7b22067e4e6bdc8c5c1bc971c489e92028fd8872', # commit position 16638
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'c78eb98bfddb7a54352a56cd039558d75fca7ee0', # commit position 16656
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/WATCHLISTS b/WATCHLISTS
index 0e3c156d..7b3e284 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1081,8 +1081,10 @@
     },
     'virtual_keyboard': {
       'filepath': 'ui/keyboard/'\
-                  'chrome/test/data/chromeos/virtual_keyboard/'\
-                  'chrome/common/extensions/api/virtual_keyboard',
+                  '|chrome/test/data/chromeos/virtual_keyboard/'\
+                  '|extensions/browser/api/virtual_keyboard_private/'\
+                  '|ash/common/system/chromeos/virtual_keyboard/'\
+                  '|ash/virtual_keyboard',
     },
     'virtual_reality': {
       'filepath': 'vr_shell/|'\
@@ -1687,7 +1689,7 @@
                                 'dongseong.hwang@intel.com',
                                 'drott+blinkwatch@chromium.org',
                                 'dschulze@chromium.org',
-                                'fmalita@chromium.org',
+                                'fmalita+watch@chromium.org',
                                 'jbroman@chromium.org',
                                 'junov@chromium.org',
                                 'pdr+graphicswatchlist@chromium.org',
@@ -1722,7 +1724,7 @@
                                 'pdr+virtualspv2watchlist@chromium.org'],
     'blink_style': ['blink-reviews-style@chromium.org'],
     'blink_svg': ['dschulze@chromium.org',
-                  'fmalita@chromium.org',
+                  'fmalita+watch@chromium.org',
                   'fs@opera.com',
                   'gyuyoung.kim@chromium.org',
                   'kouhei+svg@chromium.org',
@@ -2108,7 +2110,9 @@
                       'chfremer+watch@chromium.org'],
     'views': ['tfarina@chromium.org'],
     'virtual_keyboard': ['dfaden+virtualkb@google.com',
-                         'groby+virtualkb@chromium.org'],
+                         'groby+virtualkb@chromium.org',
+                         'oka+watchvk@chromium.org',
+                         'yhanada+watchvk@chromium.org'],
     'virtual_reality': ['feature-vr-reviews@chromium.org'],
     'webrtc_browser_tests': ['phoglund+watch@chromium.org'],
     'website_settings': ['markusheintz@chromium.org',
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc
index 6ffb42e6..751b553 100644
--- a/android_webview/browser/surfaces_instance.cc
+++ b/android_webview/browser/surfaces_instance.cc
@@ -169,7 +169,9 @@
 
 void SurfacesInstance::OnBeginFrame(const cc::BeginFrameArgs& args) {}
 
-void SurfacesInstance::WillDrawSurface() {}
+void SurfacesInstance::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {}
 
 void SurfacesInstance::ReclaimResources(
     const cc::ReturnedResourceArray& resources) {
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h
index 1ba1316..ab5cf1a 100644
--- a/android_webview/browser/surfaces_instance.h
+++ b/android_webview/browser/surfaces_instance.h
@@ -66,7 +66,8 @@
   // cc::CompositorFrameSinkSupportClient implementation.
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
 
   void SetEmptyRootFrame();
diff --git a/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc b/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
index ed7284f..6ad8627 100644
--- a/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
+++ b/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
@@ -450,12 +450,17 @@
 
   void HandleButtonPressed(views::Button* sender,
                            const ui::Event& event) override {
-    if (sender == toggle_)
-      WmShell::Get()->system_tray_delegate()->ToggleBluetooth();
-    else if (sender == settings_)
+    if (sender == toggle_) {
+      SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate();
+      WmShell::Get()->RecordUserMetricsAction(
+          delegate->GetBluetoothEnabled() ? UMA_STATUS_AREA_BLUETOOTH_DISABLED
+                                          : UMA_STATUS_AREA_BLUETOOTH_ENABLED);
+      delegate->ToggleBluetooth();
+    } else if (sender == settings_) {
       ShowSettings();
-    else
+    } else {
       NOTREACHED();
+    }
   }
 
   void CreateExtraTitleRowButtons() override {
diff --git a/base/id_map.h b/base/id_map.h
index 8545de8..d171fb14 100644
--- a/base/id_map.h
+++ b/base/id_map.h
@@ -81,9 +81,8 @@
     }
   }
 
-  // Replaces the value for |id| with |new_data| and returns the existing value
-  // (as a unique_ptr<> if in IDMapOwnPointer mode).  Should only be called with
-  // an already added id.
+  // Replaces the value for |id| with |new_data| and returns the existing value.
+  // Should only be called with an already added id.
   V Replace(KeyType id, V new_data) {
     DCHECK(sequence_checker_.CalledOnValidSequence());
     DCHECK(!check_on_null_data_ || new_data);
diff --git a/build/android/gradle/android.jinja b/build/android/gradle/android.jinja
index f944e9a..511831b 100644
--- a/build/android/gradle/android.jinja
+++ b/build/android/gradle/android.jinja
@@ -10,11 +10,13 @@
                 "{{ path }}",
 {% endfor %}
             ]
+{% if variables.java_excludes %}
             java.filter.exclude(
 {% for path in variables.java_excludes %}
                 "{{ path }}",
 {% endfor %}
             )
+{% endif %}
             jniLibs.srcDirs = [
 {% for path in variables.jni_libs %}
                 "{{ path }}",
@@ -94,4 +96,9 @@
     tasksToDisable.each { Task task ->
       task.enabled = false
     }
+{% if bootclasspath is defined %}
+    tasks.withType(JavaCompile) {
+      options.bootClasspath = "{{ bootclasspath }}"
+    }
+{% endif %}
 }
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index 2b529f0..1170b63 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -37,7 +37,9 @@
 _RES_SUBDIR = 'extracted-res'
 
 _DEFAULT_TARGETS = [
-    # TODO(agrieve): Requires alternate android.jar to compile.
+    # TODO(agrieve): .build_config seem not quite right for this target
+    # because it has resources as deps of android_apk() rather than using an
+    #  android_library() intermediate target.
     # '//android_webview:system_webview_apk',
     '//android_webview/test:android_webview_apk',
     '//android_webview/test:android_webview_test_apk',
@@ -458,6 +460,10 @@
       build_vars['android_sdk_build_tools_version'])
   variables['compile_sdk_version'] = build_vars['android_sdk_version']
   variables['main'] = generator.Generate(entry)
+  bootclasspath = gradle.get('bootclasspath')
+  if bootclasspath:
+    # Must use absolute path here.
+    variables['bootclasspath'] = _RebasePath(bootclasspath)
   if entry.android_test_entry:
     variables['android_test'] = generator.Generate(
         entry.android_test_entry)
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 251df4e..b90f06f8 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -293,6 +293,7 @@
                     help='Path to JAR that contains java resources. Everything '
                     'from this JAR except meta-inf/ content and .class files '
                     'will be added to the final APK.')
+  parser.add_option('--bootclasspath', help='Path to custom android.jar/rt.jar')
 
   # android library options
   parser.add_option('--dex-path', help='Path to target\'s dex output.')
@@ -419,6 +420,8 @@
     gradle['dependent_java_projects'] = []
     gradle['dependent_prebuilt_jars'] = deps.GradlePrebuiltJarPaths()
 
+    if options.bootclasspath:
+      gradle['bootclasspath'] = options.bootclasspath
     if options.main_class:
       gradle['main_class'] = options.main_class
 
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index e1a11e2..d2d9f99 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -353,6 +353,12 @@
         invoker.main_class,
       ]
     }
+    if (defined(invoker.alternative_android_sdk_ijar)) {
+      args += [
+        "--bootclasspath",
+        rebase_path(invoker.alternative_android_sdk_ijar, root_build_dir),
+      ]
+    }
     if (current_toolchain != default_toolchain) {
       # This has to be a built-time error rather than a GN assert because many
       # packages have a mix of java and non-java targets. For example, the
@@ -2307,6 +2313,7 @@
       write_build_config(build_config_target_name) {
         forward_variables_from(invoker,
                                [
+                                 "alternative_android_sdk_ijar",
                                  "gradle_treat_as_prebuilt",
                                  "input_jars_paths",
                                  "main_class",
diff --git a/cc/ipc/mojo_compositor_frame_sink.mojom b/cc/ipc/mojo_compositor_frame_sink.mojom
index bf2e196..a38af96 100644
--- a/cc/ipc/mojo_compositor_frame_sink.mojom
+++ b/cc/ipc/mojo_compositor_frame_sink.mojom
@@ -6,11 +6,13 @@
 
 import "cc/ipc/begin_frame_args.mojom";
 import "cc/ipc/compositor_frame.mojom";
+import "cc/ipc/copy_output_request.mojom";
 import "cc/ipc/frame_sink_id.mojom";
 import "cc/ipc/local_surface_id.mojom";
 import "cc/ipc/surface_reference.mojom";
 import "cc/ipc/returned_resource.mojom";
 import "cc/ipc/surface_sequence.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
 
 // A MojoCompositorFrameSink is an interface for receiving CompositorFrame
 // structs. A CompositorFrame contains the complete output meant for display.
@@ -46,8 +48,6 @@
 
   // Mark the sequence as satisfied and garbage collect surfaces.
   Satisfy(cc.mojom.SurfaceSequence sequence);
-
-  // TODO(fsamuel): ReadbackBitmap API would be useful here.
 };
 
 interface MojoCompositorFrameSinkClient {
@@ -67,7 +67,7 @@
   ReclaimResources(ReturnedResourceArray resources);
 
   // Called when surface is being scheduled for a draw.
-  WillDrawSurface();
+  WillDrawSurface(LocalSurfaceId local_surface_id, gfx.mojom.Rect damage_rect);
 };
 
 // MojoCompositorFrameSinkPrivate is used by the display compositor host to set
@@ -77,4 +77,9 @@
 interface MojoCompositorFrameSinkPrivate {
   AddChildFrameSink(FrameSinkId child_frame_sink_id);
   RemoveChildFrameSink(FrameSinkId child_frame_sink_id);
+
+  // Requests that the renderer send back a copy of the surface that this
+  // CompositorFrameSink submits to. The result can be in form of a bitmap
+  // or a texture. See cc::CopyOutputRequest.
+  RequestCopyOfSurface(cc.mojom.CopyOutputRequest request);
 };
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc
index 2cbae61..0edb96e 100644
--- a/cc/surfaces/compositor_frame_sink_support.cc
+++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -216,7 +216,7 @@
     const LocalSurfaceId& local_surface_id,
     const gfx::Rect& damage_rect) {
   if (client_)
-    client_->WillDrawSurface();
+    client_->WillDrawSurface(local_surface_id, damage_rect);
 }
 
 void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
@@ -247,4 +247,9 @@
     begin_frame_source_->RemoveObserver(this);
 }
 
+void CompositorFrameSinkSupport::RequestCopyOfSurface(
+    std::unique_ptr<CopyOutputRequest> request) {
+  surface_factory_.RequestCopyOfSurface(std::move(request));
+}
+
 }  // namespace cc
diff --git a/cc/surfaces/compositor_frame_sink_support.h b/cc/surfaces/compositor_frame_sink_support.h
index 7e10800..406c51e 100644
--- a/cc/surfaces/compositor_frame_sink_support.h
+++ b/cc/surfaces/compositor_frame_sink_support.h
@@ -55,6 +55,7 @@
   void Satisfy(const SurfaceSequence& sequence);
   void AddChildFrameSink(const FrameSinkId& child_frame_sink_id);
   void RemoveChildFrameSink(const FrameSinkId& child_frame_sink_id);
+  void RequestCopyOfSurface(std::unique_ptr<CopyOutputRequest> request);
 
  private:
   // Update surface references with SurfaceManager for current CompositorFrame
diff --git a/cc/surfaces/compositor_frame_sink_support_client.h b/cc/surfaces/compositor_frame_sink_support_client.h
index e3f6dab..905f6db 100644
--- a/cc/surfaces/compositor_frame_sink_support_client.h
+++ b/cc/surfaces/compositor_frame_sink_support_client.h
@@ -7,8 +7,14 @@
 
 #include "cc/resources/returned_resource.h"
 
+namespace gfx {
+class Rect;
+}
+
 namespace cc {
 
+class LocalSurfaceId;
+
 struct BeginFrameArgs;
 
 class CompositorFrameSinkSupportClient {
@@ -29,7 +35,8 @@
   virtual void ReclaimResources(const ReturnedResourceArray& resources) = 0;
 
   // Called when surface is being scheduled for a draw.
-  virtual void WillDrawSurface() = 0;
+  virtual void WillDrawSurface(const LocalSurfaceId& local_surface_id,
+                               const gfx::Rect& damage_rect) = 0;
 
  protected:
   virtual ~CompositorFrameSinkSupportClient() {}
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc
index e9b4f56..7f5342d1 100644
--- a/cc/surfaces/compositor_frame_sink_support_unittest.cc
+++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -165,7 +165,8 @@
   void ReclaimResources(const ReturnedResourceArray& resources) override {
     last_returned_resources_ = resources;
   }
-  void WillDrawSurface() override {}
+  void WillDrawSurface(const LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override {}
 
  private:
   SurfaceManager surface_manager_;
diff --git a/chrome/VERSION b/chrome/VERSION
index 26bc6fd1..8eecc75b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=58
 MINOR=0
-BUILD=3015
+BUILD=3016
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
index af2153a..e55fee0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
+import org.chromium.chrome.browser.banners.AppBannerManager;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.share.ShareHelper;
@@ -106,6 +107,7 @@
             MenuItem bookmarkItem = menu.findItem(R.id.bookmark_this_page_id);
             MenuItem downloadItem = menu.findItem(R.id.offline_page_id);
             MenuItem addToHomeScreenItem = menu.findItem(R.id.add_to_homescreen_id);
+            addToHomeScreenItem.setTitle(AppBannerManager.getHomescreenLanguageOption());
 
             // Hide request desktop site on all chrome:// pages except for the NTP. Check request
             // desktop site if it's activated on this page.
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index c9322e1d..93970e1 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5482,6 +5482,12 @@
       <message name="IDS_FLAGS_WEBRTC_STUN_ORIGIN_DESCRIPTION" desc="Description of chrome:flags option to turn on Origin header for WebRTC STUN messages">
         When enabled, Stun messages generated by WebRTC will contain the Origin header.
       </message>
+      <message name="IDS_FLAGS_WEBRTC_ECHO_CANCELLER_3_NAME" desc="Name of chrome:flags option to enable WebRTC Echo Canceller 3.">
+        WebRTC Echo Canceller 3.
+      </message>
+      <message name="IDS_FLAGS_WEBRTC_ECHO_CANCELLER_3_DESCRIPTION" desc="Description of chrome:flags option to enable WebRTC Echo Canceller 3.">
+        Experimental WebRTC echo canceller (AEC3).
+      </message>
       <if expr="is_android">
        <message name="IDS_FLAGS_MEDIA_SCREEN_CAPTURE_NAME" desc="Name of chrome:flags option to enable screen capture." translateable="false">
          Experimental ScreenCapture.
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 340e0d4..19ec3f8b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4182,9 +4182,8 @@
 
   if (use_vulcanize) {
     deps += [
-      "//chrome/browser/resources/md_downloads:vulcanize",
-      "//chrome/browser/resources/md_history:vulcanize_app",
-      "//chrome/browser/resources/md_history:vulcanize_lazy_load",
+      "//chrome/browser/resources/md_downloads:build",
+      "//chrome/browser/resources/md_history:build",
     ]
   }
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 4d058e2a9..7cb46b7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -761,6 +761,9 @@
     {"enable-webrtc-stun-origin", IDS_FLAGS_WEBRTC_STUN_ORIGIN_NAME,
      IDS_FLAGS_WEBRTC_STUN_ORIGIN_DESCRIPTION, kOsAll,
      SINGLE_VALUE_TYPE(switches::kEnableWebRtcStunOrigin)},
+    {"WebRtcUseEchoCanceller3", IDS_FLAGS_WEBRTC_ECHO_CANCELLER_3_NAME,
+     IDS_FLAGS_WEBRTC_ECHO_CANCELLER_3_DESCRIPTION, kOsAll,
+     FEATURE_VALUE_TYPE(features::kWebRtcUseEchoCanceller3)},
 #endif  // ENABLE_WEBRTC
 #if defined(OS_ANDROID)
     {"enable-osk-overscroll", IDS_FLAGS_ENABLE_OSK_OVERSCROLL_NAME,
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.cc b/chrome/browser/android/offline_pages/recent_tab_helper.cc
index 1be59e3..dd9ff36 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper.cc
+++ b/chrome/browser/android/offline_pages/recent_tab_helper.cc
@@ -13,6 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/browser/android/offline_pages/downloads/offline_page_notification_bridge.h"
@@ -35,7 +36,7 @@
 namespace {
 class DefaultDelegate: public offline_pages::RecentTabHelper::Delegate {
  public:
-  DefaultDelegate() {}
+  DefaultDelegate() : is_low_end_device_(base::SysInfo::IsLowEndDevice()) {}
 
   // offline_pages::RecentTabHelper::Delegate
   std::unique_ptr<offline_pages::OfflinePageArchiver> CreatePageArchiver(
@@ -49,6 +50,11 @@
   bool GetTabId(content::WebContents* web_contents, int* tab_id) override {
     return offline_pages::OfflinePageUtils::GetTabId(web_contents, tab_id);
   }
+  bool IsLowEndDevice() override { return is_low_end_device_; }
+
+ private:
+  // Cached value of whether low end device.
+  bool is_low_end_device_;
 };
 }  // namespace
 
@@ -212,7 +218,8 @@
 
   if (!can_save)
     snapshot_controller_->Stop();
-  last_n_listen_to_tab_hidden_ = can_save && IsOffliningRecentPagesEnabled();
+  last_n_listen_to_tab_hidden_ = can_save && !delegate_->IsLowEndDevice() &&
+                                 IsOffliningRecentPagesEnabled();
   last_n_latest_saved_quality_ = PageQuality::POOR;
 }
 
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.h b/chrome/browser/android/offline_pages/recent_tab_helper.h
index b5f095f..d1bbf5b7 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper.h
+++ b/chrome/browser/android/offline_pages/recent_tab_helper.h
@@ -54,6 +54,7 @@
     virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() = 0;
     // There is no expectations that tab_id is always present.
     virtual bool GetTabId(content::WebContents* web_contents, int* tab_id) = 0;
+    virtual bool IsLowEndDevice() = 0;
   };
   void SetDelegate(std::unique_ptr<RecentTabHelper::Delegate> delegate);
 
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
index 205db07..6fa2440 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
+++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -52,6 +52,7 @@
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
     // There is no expectations that tab_id is always present.
   bool GetTabId(content::WebContents* web_contents, int* tab_id) override;
+  bool IsLowEndDevice() override { return is_low_end_device_; }
 
   void set_archive_result(
       offline_pages::OfflinePageArchiver::ArchiverResult result) {
@@ -60,6 +61,8 @@
 
   void set_archive_size(int64_t size) { archive_size_ = size; }
 
+  void SetAsLowEndDevice() { is_low_end_device_ = true; }
+
  private:
   OfflinePageTestArchiver::Observer* observer_;  // observer owns this.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -71,6 +74,7 @@
   offline_pages::OfflinePageArchiver::ArchiverResult archive_result_ =
       offline_pages::OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED;
   int64_t archive_size_ = kArchiveSizeToReport;
+  bool is_low_end_device_ = false;
 };
 
 class RecentTabHelperTest
@@ -104,6 +108,8 @@
 
   OfflinePageModel* model() const { return model_; }
 
+  TestDelegate* default_test_delegate() { return default_test_delegate_; }
+
   // Returns a OfflinePageItem pointer from |all_pages| that matches the
   // provided |offline_id|. If a match is not found returns nullptr.
   const OfflinePageItem* FindPageForOfflineId(int64_t offline_id) {
@@ -141,8 +147,9 @@
  private:
   void OnGetAllPagesDone(const std::vector<OfflinePageItem>& result);
 
-  RecentTabHelper* recent_tab_helper_;  // Owned by WebContents.
-  OfflinePageModel* model_;  // Keyed service
+  RecentTabHelper* recent_tab_helper_;   // Owned by WebContents.
+  OfflinePageModel* model_;              // Keyed service.
+  TestDelegate* default_test_delegate_;  // Created at SetUp.
   size_t page_added_count_;
   size_t model_removed_count_;
   std::vector<OfflinePageItem> all_pages_;
@@ -187,6 +194,7 @@
 RecentTabHelperTest::RecentTabHelperTest()
     : recent_tab_helper_(nullptr),
       model_(nullptr),
+      default_test_delegate_(nullptr),
       page_added_count_(0),
       model_removed_count_(0),
       all_pages_needs_updating_(true),
@@ -208,8 +216,10 @@
   RecentTabHelper::CreateForWebContents(web_contents());
   recent_tab_helper_ = RecentTabHelper::FromWebContents(web_contents());
 
-  recent_tab_helper_->SetDelegate(base::MakeUnique<TestDelegate>(
-      this, task_runner(), kTabId, true));
+  std::unique_ptr<TestDelegate> test_delegate(
+      new TestDelegate(this, task_runner(), kTabId, true));
+  default_test_delegate_ = test_delegate.get();
+  recent_tab_helper_->SetDelegate(std::move(test_delegate));
 
   model_ = OfflinePageModelFactory::GetForBrowserContext(browser_context());
   model_->AddObserver(this);
@@ -333,6 +343,30 @@
   ASSERT_EQ(0U, GetAllPages().size());
 }
 
+// Checks that last_n is disabled if the device is low-end (aka svelte) but that
+// download requests still work.
+TEST_F(RecentTabHelperTest, LastNDisabledOnSvelte) {
+  // Simulates a low end device.
+  default_test_delegate()->SetAsLowEndDevice();
+
+  // Navigate and finish loading then hide the tab. Nothing should be saved.
+  NavigateAndCommit(kTestPageUrl);
+  recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
+  FastForwardSnapshotController();
+  recent_tab_helper()->WasHidden();
+  RunUntilIdle();
+  EXPECT_TRUE(model()->is_loaded());
+  EXPECT_EQ(0U, page_added_count());
+  ASSERT_EQ(0U, GetAllPages().size());
+
+  // But the following download request should work normally
+  recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(),
+                                                     123L);
+  RunUntilIdle();
+  EXPECT_EQ(1U, page_added_count());
+  ASSERT_EQ(1U, GetAllPages().size());
+}
+
 // Triggers two last_n snapshot captures during a single page load. Should end
 // up with one snapshot, the 1st being replaced by the 2nd.
 TEST_F(RecentTabHelperTest, TwoCapturesSamePageLoad) {
@@ -390,15 +424,11 @@
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
   int64_t first_offline_id = GetAllPages()[0].offline_id;
 
-  // Sets a new delegate that will make the second snapshot fail.
-  TestDelegate* failing_delegate =
-      new TestDelegate(this, task_runner(), kTabId, true);
-  failing_delegate->set_archive_size(-1);
-  failing_delegate->set_archive_result(
+  // Updates the delegate so that will make the second snapshot fail.
+  default_test_delegate()->set_archive_size(-1);
+  default_test_delegate()->set_archive_result(
       offline_pages::OfflinePageArchiver::ArchiverResult::
           ERROR_ARCHIVE_CREATION_FAILED);
-  recent_tab_helper()->SetDelegate(
-      std::unique_ptr<TestDelegate>(failing_delegate));
 
   // Advance loading to the 2nd and final stage and then hide the tab. A new
   // capture is requested but its creation will fail. The exact same snapshot
@@ -463,15 +493,11 @@
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
 
-  // Sets a new delegate that will make the second snapshot fail.
-  TestDelegate* failing_delegate =
-      new TestDelegate(this, task_runner(), kTabId, true);
-  failing_delegate->set_archive_size(-1);
-  failing_delegate->set_archive_result(
+  // Updates the delegate so that will make the second snapshot fail.
+  default_test_delegate()->set_archive_size(-1);
+  default_test_delegate()->set_archive_result(
       offline_pages::OfflinePageArchiver::ArchiverResult::
           ERROR_ARCHIVE_CREATION_FAILED);
-  recent_tab_helper()->SetDelegate(
-      std::unique_ptr<TestDelegate>(failing_delegate));
 
   // Fully load the page once more then hide the tab again. A capture happens
   // and fails but no snapshot should remain.
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
index 576bbc3a..2dea7aa 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/location.h"
 #include "base/strings/string16.h"
+#include "base/task_runner_util.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/android/offline_pages/offline_page_utils.h"
 #include "chrome/browser/android/shortcut_helper.h"
@@ -74,6 +75,10 @@
     bool check_webapk_compatibility,
     Observer* observer)
     : WebContentsObserver(web_contents),
+      background_task_runner_(
+          content::BrowserThread::GetBlockingPool()
+              ->GetTaskRunnerWithShutdownBehavior(
+                  base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
       weak_observer_(observer),
       shortcut_info_(GetShortcutUrl(web_contents->GetBrowserContext(),
                                     web_contents->GetLastCommittedURL())),
@@ -286,14 +291,16 @@
   if (!web_contents() || !weak_observer_ || is_icon_saved_)
     return;
 
-  content::BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
-      FROM_HERE, base::Bind(&AddToHomescreenDataFetcher::
-                                CreateLauncherIconFromFaviconInBackground,
-                            this, bitmap_result),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  base::PostTaskAndReplyWithResult(
+      background_task_runner_.get(), FROM_HERE,
+      base::Bind(&AddToHomescreenDataFetcher::
+                     CreateLauncherIconFromFaviconInBackground,
+                 base::Unretained(this), bitmap_result),
+      base::Bind(&AddToHomescreenDataFetcher::NotifyObserver,
+                 base::RetainedRef(this)));
 }
 
-void AddToHomescreenDataFetcher::CreateLauncherIconFromFaviconInBackground(
+SkBitmap AddToHomescreenDataFetcher::CreateLauncherIconFromFaviconInBackground(
     const favicon_base::FaviconRawBitmapResult& bitmap_result) {
   DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
 
@@ -304,19 +311,20 @@
   }
 
   shortcut_info_.best_primary_icon_url = bitmap_result.icon_url;
-  CreateLauncherIconInBackground(raw_icon);
+  return CreateLauncherIconInBackground(raw_icon);
 }
 
 void AddToHomescreenDataFetcher::CreateLauncherIcon(const SkBitmap& raw_icon) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  content::BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
-      FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      background_task_runner_.get(), FROM_HERE,
       base::Bind(&AddToHomescreenDataFetcher::CreateLauncherIconInBackground,
-                 this, raw_icon),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+                 base::Unretained(this), raw_icon),
+      base::Bind(&AddToHomescreenDataFetcher::NotifyObserver,
+                 base::RetainedRef(this)));
 }
 
-void AddToHomescreenDataFetcher::CreateLauncherIconInBackground(
+SkBitmap AddToHomescreenDataFetcher::CreateLauncherIconInBackground(
     const SkBitmap& raw_icon) {
   DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
 
@@ -330,10 +338,7 @@
   if (is_generated)
     shortcut_info_.best_primary_icon_url = GURL();
 
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&AddToHomescreenDataFetcher::NotifyObserver, this,
-                 primary_icon));
+  return primary_icon;
 }
 
 void AddToHomescreenDataFetcher::NotifyObserver(const SkBitmap& primary_icon) {
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
index 631b1d0..ee209ab 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
@@ -14,6 +14,10 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
+namespace base {
+class TaskRunner;
+}
+
 namespace content {
 class WebContents;
 }
@@ -114,16 +118,18 @@
   // Creates the launcher icon from the given bitmap. shortcut_info_.url is
   // used to generate an icon if there is no bitmap in |bitmap_result| or the
   // bitmap is not large enough.
-  void CreateLauncherIconFromFaviconInBackground(
+  SkBitmap CreateLauncherIconFromFaviconInBackground(
       const favicon_base::FaviconRawBitmapResult& bitmap_result);
 
   // Creates the launcher icon from the given |raw_icon|.
   void CreateLauncherIcon(const SkBitmap& raw_icon);
-  void CreateLauncherIconInBackground(const SkBitmap& raw_icon);
+  SkBitmap CreateLauncherIconInBackground(const SkBitmap& raw_icon);
 
   // Notifies the observer that the shortcut data is all available.
   void NotifyObserver(const SkBitmap& icon);
 
+  scoped_refptr<base::TaskRunner> background_task_runner_;
+
   Observer* weak_observer_;
 
   // The icons must only be set on the UI thread for thread safety.
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
index 27bab62..62ddc312 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
@@ -5,7 +5,9 @@
 #include "chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h"
 
 #include "ash/shell.h"
+#include "chrome/browser/speech/tts_controller.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
+#include "content/public/browser/browser_thread.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
 #include "ui/events/event.h"
@@ -26,7 +28,33 @@
 }
 
 void SelectToSpeakEventHandler::OnKeyEvent(ui::KeyEvent* event) {
-  if (event->key_code() == ui::VKEY_LWIN) {
+  // We can only call TtsController on the UI thread, make sure we
+  // don't ever try to run this code on some other thread.
+  CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  ui::KeyboardCode key_code = event->key_code();
+
+  // Stop speech when the user taps and releases Control or Search
+  // without pressing any other keys along the way.
+  if (state_ != MOUSE_RELEASED && event->type() == ui::ET_KEY_RELEASED &&
+      (key_code == ui::VKEY_CONTROL || key_code == ui::VKEY_LWIN) &&
+      keys_pressed_together_.find(key_code) != keys_pressed_together_.end() &&
+      keys_pressed_together_.size() == 1) {
+    TtsController::GetInstance()->Stop();
+  }
+
+  // Update keys_currently_down_ and keys_pressed_together_.
+  if (event->type() == ui::ET_KEY_PRESSED) {
+    keys_currently_down_.insert(key_code);
+    keys_pressed_together_.insert(key_code);
+  } else if (event->type() == ui::ET_KEY_RELEASED) {
+    keys_currently_down_.erase(key_code);
+    if (keys_currently_down_.empty())
+      keys_pressed_together_.clear();
+  }
+
+  // Update the state when pressing and releasing the Search key (VKEY_LWIN).
+  if (key_code == ui::VKEY_LWIN) {
     if (event->type() == ui::ET_KEY_PRESSED && state_ == INACTIVE) {
       state_ = SEARCH_DOWN;
     } else if (event->type() == ui::ET_KEY_RELEASED) {
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
index 10f2c75..012fb9e 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
@@ -5,8 +5,11 @@
 #ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SELECT_TO_SPEAK_EVENT_HANDLER_H_
 #define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SELECT_TO_SPEAK_EVENT_HANDLER_H_
 
+#include <set>
+
 #include "base/macros.h"
 #include "ui/events/event_handler.h"
+#include "ui/events/keycodes/keyboard_codes.h"
 
 namespace chromeos {
 
@@ -52,6 +55,13 @@
 
   State state_ = INACTIVE;
 
+  // The set of keys that are currently down. Updated whenever a key is
+  // pressed or released.
+  std::set<ui::KeyboardCode> keys_currently_down_;
+  // The set of keys that have been pressed together. Updated whenever a key
+  // is pressed, and only cleared when all keys are released.
+  std::set<ui::KeyboardCode> keys_pressed_together_;
+
   int last_view_storage_id_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(SelectToSpeakEventHandler);
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc
index d17a534..e166838 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_unittest.cc
@@ -11,6 +11,7 @@
 #include "ash/test/ash_test_helper.h"
 #include "ash/test/ash_test_views_delegate.h"
 #include "base/macros.h"
+#include "chrome/browser/chromeos/accessibility/speech_monitor.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
 #include "chrome/test/base/testing_profile.h"
 #include "ui/aura/window.h"
@@ -114,6 +115,8 @@
 
 }  // namespace
 
+namespace chromeos {
+
 TEST_F(SelectToSpeakEventHandlerTest, PressAndReleaseSearchNotHandled) {
   // If the user presses and releases the Search key, with no mouse
   // presses, the key events won't be handled by the SelectToSpeakEventHandler
@@ -275,3 +278,37 @@
   ASSERT_TRUE(event_capturer_.last_key_event());
   EXPECT_FALSE(event_capturer_.last_key_event()->handled());
 }
+
+TEST_F(SelectToSpeakEventHandlerTest, TappingControlStopsSpeech) {
+  SpeechMonitor monitor;
+  EXPECT_FALSE(monitor.DidStop());
+  generator_->PressKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN);
+  generator_->ReleaseKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN);
+  EXPECT_TRUE(monitor.DidStop());
+}
+
+TEST_F(SelectToSpeakEventHandlerTest, TappingSearchStopsSpeech) {
+  SpeechMonitor monitor;
+  EXPECT_FALSE(monitor.DidStop());
+  generator_->PressKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
+  generator_->ReleaseKey(ui::VKEY_LWIN, ui::EF_COMMAND_DOWN);
+  EXPECT_TRUE(monitor.DidStop());
+}
+
+TEST_F(SelectToSpeakEventHandlerTest, TappingShiftDoesNotStopSpeech) {
+  SpeechMonitor monitor;
+  generator_->PressKey(ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN);
+  generator_->ReleaseKey(ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN);
+  EXPECT_FALSE(monitor.DidStop());
+}
+
+TEST_F(SelectToSpeakEventHandlerTest, PressingControlZDoesNotStopSpeech) {
+  SpeechMonitor monitor;
+  generator_->PressKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN);
+  generator_->PressKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
+  generator_->ReleaseKey(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
+  generator_->ReleaseKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN);
+  EXPECT_FALSE(monitor.DidStop());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.cc b/chrome/browser/chromeos/accessibility/speech_monitor.cc
index 9d83fa54..ff89f832 100644
--- a/chrome/browser/chromeos/accessibility/speech_monitor.cc
+++ b/chrome/browser/chromeos/accessibility/speech_monitor.cc
@@ -36,6 +36,10 @@
   return SkipChromeVoxMessage(kChromeVoxEnabledMessage);
 }
 
+bool SpeechMonitor::DidStop() {
+  return did_stop_;
+}
+
 bool SpeechMonitor::SkipChromeVoxMessage(const std::string& message) {
   while (true) {
     if (utterance_queue_.empty()) {
@@ -70,6 +74,7 @@
 }
 
 bool SpeechMonitor::StopSpeaking() {
+  did_stop_ = true;
   return true;
 }
 
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.h b/chrome/browser/chromeos/accessibility/speech_monitor.h
index 2c8522f..86c4262 100644
--- a/chrome/browser/chromeos/accessibility/speech_monitor.h
+++ b/chrome/browser/chromeos/accessibility/speech_monitor.h
@@ -30,6 +30,10 @@
   bool SkipChromeVoxEnabledMessage();
   bool SkipChromeVoxMessage(const std::string& message);
 
+  // Returns true if StopSpeaking() was called on TtsController.
+  bool DidStop();
+
+ private:
   // TtsPlatformImpl implementation.
   bool PlatformImplAvailable() override;
   bool Speak(int utterance_id,
@@ -48,9 +52,9 @@
   void WillSpeakUtteranceWithVoice(const Utterance* utterance,
                                    const VoiceData& voice_data) override;
 
- private:
   scoped_refptr<content::MessageLoopRunner> loop_runner_;
   std::deque<std::string> utterance_queue_;
+  bool did_stop_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(SpeechMonitor);
 };
diff --git a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
index f8946df..150f3500 100644
--- a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
+++ b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
@@ -92,8 +92,8 @@
                       const base::FilePath::StringType& default_extension,
                       gfx::NativeWindow owning_window,
                       void* params) override {
-    listener_->FileSelected(
-        base::FilePath("/special/drive-user/root/test_dir"), 0, NULL);
+    listener_->FileSelected(base::FilePath("/special/drive-user/root/test_dir"),
+                            0, nullptr);
   }
 
   bool IsRunning(gfx::NativeWindow owning_window) const override {
@@ -165,168 +165,83 @@
   return true;
 }
 
-std::unique_ptr<google_apis::FileResource> UpdateDriveEntryTime(
-    drive::FakeDriveService* fake_drive_service,
-    const std::string& resource_id,
-    const std::string& last_modified,
-    const std::string& last_viewed_by_me) {
+void IgnoreDriveEntryResult(google_apis::DriveApiErrorCode error,
+                            std::unique_ptr<google_apis::FileResource> entry) {}
+
+void UpdateDriveEntryTime(drive::FakeDriveService* fake_drive_service,
+                          const std::string& resource_id,
+                          const std::string& last_modified,
+                          const std::string& last_viewed_by_me) {
   base::Time last_modified_time, last_viewed_by_me_time;
-  if (!google_apis::util::GetTimeFromString(last_modified,
-                                            &last_modified_time) ||
-      !google_apis::util::GetTimeFromString(last_viewed_by_me,
-                                            &last_viewed_by_me_time))
-    return std::unique_ptr<google_apis::FileResource>();
-
-  google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
-  std::unique_ptr<google_apis::FileResource> entry;
-  fake_drive_service->UpdateResource(
-      resource_id,
-      std::string(),  // parent_resource_id
-      std::string(),  // title
-      last_modified_time, last_viewed_by_me_time,
-      google_apis::drive::Properties(),
-      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  base::RunLoop().RunUntilIdle();
-  if (error != google_apis::HTTP_SUCCESS)
-    return std::unique_ptr<google_apis::FileResource>();
-
-  return entry;
+  ASSERT_TRUE(google_apis::util::GetTimeFromString(last_modified,
+                                                   &last_modified_time) &&
+              google_apis::util::GetTimeFromString(last_viewed_by_me,
+                                                   &last_viewed_by_me_time));
+  fake_drive_service->UpdateResource(resource_id,
+                                     std::string(),  // parent_resource_id
+                                     std::string(),  // title
+                                     last_modified_time, last_viewed_by_me_time,
+                                     google_apis::drive::Properties(),
+                                     base::Bind(&IgnoreDriveEntryResult));
 }
 
-std::unique_ptr<google_apis::FileResource> AddFileToDriveService(
-    drive::FakeDriveService* fake_drive_service,
-    const std::string& mime_type,
-    const std::string& content,
-    const std::string& parent_resource_id,
-    const std::string& title,
-    const std::string& last_modified,
-    const std::string& last_viewed_by_me) {
-  google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
-  std::unique_ptr<google_apis::FileResource> entry;
-  fake_drive_service->AddNewFile(
-      mime_type,
-      content,
-      parent_resource_id,
-      title,
+void AddFileToDriveService(drive::FakeDriveService* fake_drive_service,
+                           const std::string& mime_type,
+                           const std::string& content,
+                           const std::string& parent_resource_id,
+                           const std::string& title,
+                           const std::string& last_modified,
+                           const std::string& last_viewed_by_me) {
+  fake_drive_service->AddNewFileWithResourceId(
+      title, mime_type, content, parent_resource_id, title,
       false,  // shared_with_me
-      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  base::RunLoop().RunUntilIdle();
-  if (error != google_apis::HTTP_CREATED)
-    return std::unique_ptr<google_apis::FileResource>();
-
-  return UpdateDriveEntryTime(fake_drive_service, entry->file_id(),
-                              last_modified, last_viewed_by_me);
+      base::Bind(&IgnoreDriveEntryResult));
+  UpdateDriveEntryTime(fake_drive_service, title, last_modified,
+                       last_viewed_by_me);
 }
 
-std::unique_ptr<google_apis::FileResource> AddDirectoryToDriveService(
-    drive::FakeDriveService* fake_drive_service,
-    const std::string& parent_resource_id,
-    const std::string& title,
-    const std::string& last_modified,
-    const std::string& last_viewed_by_me) {
-  google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
-  std::unique_ptr<google_apis::FileResource> entry;
-  fake_drive_service->AddNewDirectory(
-      parent_resource_id, title, drive::AddNewDirectoryOptions(),
-      google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-  base::RunLoop().RunUntilIdle();
-  if (error != google_apis::HTTP_CREATED)
-    return std::unique_ptr<google_apis::FileResource>();
-
-  return UpdateDriveEntryTime(fake_drive_service, entry->file_id(),
-                              last_modified, last_viewed_by_me);
+void AddDirectoryToDriveService(drive::FakeDriveService* fake_drive_service,
+                                const std::string& parent_resource_id,
+                                const std::string& title,
+                                const std::string& last_modified,
+                                const std::string& last_viewed_by_me) {
+  fake_drive_service->AddNewDirectoryWithResourceId(
+      title, parent_resource_id, title, drive::AddNewDirectoryOptions(),
+      base::Bind(&IgnoreDriveEntryResult));
+  UpdateDriveEntryTime(fake_drive_service, title, last_modified,
+                       last_viewed_by_me);
 }
 
 // Sets up the drive service state.
 // The hierarchy is the same as for the local file system.
-bool InitializeDriveService(
-    drive::FakeDriveService* fake_drive_service,
-    std::map<std::string, std::string>* out_resource_ids) {
-  std::unique_ptr<google_apis::FileResource> entry;
-
-  entry = AddDirectoryToDriveService(fake_drive_service,
-                                     fake_drive_service->GetRootResourceId(),
-                                     "test_dir",
-                                     "2012-01-02T00:00:00.000Z",
-                                     "2012-01-02T00:00:01.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddDirectoryToDriveService(fake_drive_service,
-                                     (*out_resource_ids)["test_dir"],
-                                     "empty_test_dir",
-                                     "2011-11-02T04:00:00.000Z",
-                                     "2011-11-02T04:00:00.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddDirectoryToDriveService(fake_drive_service,
-                                     (*out_resource_ids)["test_dir"],
-                                     "subdir",
-                                     "2011-04-01T18:34:08.234Z",
-                                     "2012-01-02T00:00:01.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddFileToDriveService(fake_drive_service,
-                                "application/vnd.mozilla.xul+xml",
-                                kTestFileContent,
-                                (*out_resource_ids)["test_dir"],
-                                "test_file.xul",
-                                "2011-12-14T00:40:47.330Z",
-                                "2012-01-02T00:00:00.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddFileToDriveService(fake_drive_service,
-                                "test/ro",
-                                kTestFileContent,
-                                (*out_resource_ids)["test_dir"],
-                                "test_file.xul.foo",
-                                "2012-01-01T10:00:30.000Z",
-                                "2012-01-01T00:00:00.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddFileToDriveService(fake_drive_service,
-                                "image/tiff",
-                                kTestFileContent,
-                                (*out_resource_ids)["test_dir"],
-                                "test_file.tiff",
-                                "2011-04-03T11:11:10.000Z",
-                                "2012-01-02T00:00:00.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddFileToDriveService(fake_drive_service,
-                                "test/rw",
-                                kTestFileContent,
-                                (*out_resource_ids)["test_dir"],
-                                "test_file.tiff.foo",
-                                "2011-12-14T00:40:47.330Z",
-                                "2010-01-02T00:00:00.000Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  entry = AddFileToDriveService(fake_drive_service,
-                                "test/rw",
-                                "",
-                                (*out_resource_ids)["test_dir"],
-                                "empty_test_file.foo",
-                                "2011-12-14T00:40:47.330Z",
-                                "2011-12-14T00:40:47.330Z");
-  if (!entry)
-    return false;
-  (*out_resource_ids)[entry->title()] = entry->file_id();
-
-  return true;
+drive::FakeDriveService* CreateDriveService() {
+  drive::FakeDriveService* service = new drive::FakeDriveService;
+  service->LoadAppListForDriveApi("drive/applist.json");
+  AddDirectoryToDriveService(service, service->GetRootResourceId(), "test_dir",
+                             "2012-01-02T00:00:00.000Z",
+                             "2012-01-02T00:00:01.000Z");
+  AddDirectoryToDriveService(service, "test_dir", "empty_test_dir",
+                             "2011-11-02T04:00:00.000Z",
+                             "2011-11-02T04:00:00.000Z");
+  AddDirectoryToDriveService(service, "test_dir", "subdir",
+                             "2011-04-01T18:34:08.234Z",
+                             "2012-01-02T00:00:01.000Z");
+  AddFileToDriveService(service, "application/vnd.mozilla.xul+xml",
+                        kTestFileContent, "test_dir", "test_file.xul",
+                        "2011-12-14T00:40:47.330Z", "2012-01-02T00:00:00.000Z");
+  AddFileToDriveService(service, "test/ro", kTestFileContent, "test_dir",
+                        "test_file.xul.foo", "2012-01-01T10:00:30.000Z",
+                        "2012-01-01T00:00:00.000Z");
+  AddFileToDriveService(service, "image/tiff", kTestFileContent, "test_dir",
+                        "test_file.tiff", "2011-04-03T11:11:10.000Z",
+                        "2012-01-02T00:00:00.000Z");
+  AddFileToDriveService(service, "test/rw", kTestFileContent, "test_dir",
+                        "test_file.tiff.foo", "2011-12-14T00:40:47.330Z",
+                        "2010-01-02T00:00:00.000Z");
+  AddFileToDriveService(service, "test/rw", "", "test_dir",
+                        "empty_test_file.foo", "2011-12-14T00:40:47.330Z",
+                        "2011-12-14T00:40:47.330Z");
+  return service;
 }
 
 // Helper class to wait for a background page to load or close again.
@@ -518,7 +433,7 @@
 // Tests for a drive file system.
 class DriveFileSystemExtensionApiTest : public FileSystemExtensionApiTestBase {
  public:
-  DriveFileSystemExtensionApiTest() : fake_drive_service_(NULL) {}
+  DriveFileSystemExtensionApiTest() {}
   ~DriveFileSystemExtensionApiTest() override {}
 
   // FileSystemExtensionApiTestBase override.
@@ -545,7 +460,7 @@
   // FileSystemExtensionApiTestBase override.
   void TearDown() override {
     FileSystemExtensionApiTestBase::TearDown();
-    ui::SelectFileDialog::SetFactory(NULL);
+    ui::SelectFileDialog::SetFactory(nullptr);
   }
 
  protected:
@@ -554,24 +469,19 @@
       Profile* profile) {
     // Ignore signin profile.
     if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir())
-      return NULL;
+      return nullptr;
 
     // DriveFileSystemExtensionApiTest doesn't expect that several user profiles
     // could exist simultaneously.
-    DCHECK(fake_drive_service_ == NULL);
-    fake_drive_service_ = new drive::FakeDriveService;
-    fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
-
-    std::map<std::string, std::string> resource_ids;
-    EXPECT_TRUE(InitializeDriveService(fake_drive_service_, &resource_ids));
-
+    DCHECK(!fake_drive_service_);
+    fake_drive_service_ = CreateDriveService();
     return new drive::DriveIntegrationService(
         profile, nullptr, fake_drive_service_, "", test_cache_root_.GetPath(),
         nullptr);
   }
 
   base::ScopedTempDir test_cache_root_;
-  drive::FakeDriveService* fake_drive_service_;
+  drive::FakeDriveService* fake_drive_service_ = nullptr;
   DriveIntegrationServiceFactory::FactoryCallback
       create_drive_integration_service_;
   std::unique_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest>
@@ -582,7 +492,7 @@
 class MultiProfileDriveFileSystemExtensionApiTest :
     public FileSystemExtensionApiTestBase {
  public:
-  MultiProfileDriveFileSystemExtensionApiTest() : second_profile_(NULL) {}
+  MultiProfileDriveFileSystemExtensionApiTest() {}
 
   void SetUpOnMainThread() override {
     base::FilePath user_data_directory;
@@ -626,16 +536,12 @@
     base::CreateTemporaryDirInDir(tmp_dir_.GetPath(),
                                   base::FilePath::StringType(), &cache_dir);
 
-    drive::FakeDriveService* const fake_drive_service =
-        new drive::FakeDriveService;
-    fake_drive_service->LoadAppListForDriveApi("drive/applist.json");
-    EXPECT_TRUE(InitializeDriveService(fake_drive_service, &resource_ids_));
-
+    drive::FakeDriveService* const service = CreateDriveService();
     return new drive::DriveIntegrationService(
-        profile, NULL, fake_drive_service, std::string(), cache_dir, NULL);
+        profile, nullptr, service, std::string(), cache_dir, nullptr);
   }
 
-  bool AddTestHostedDocuments() {
+  void AddTestHostedDocuments() {
     const char kResourceId[] = "unique-id-for-multiprofile-copy-test";
     drive::FakeDriveService* const main_service =
         static_cast<drive::FakeDriveService*>(
@@ -644,28 +550,16 @@
         static_cast<drive::FakeDriveService*>(
             drive::util::GetDriveServiceByProfile(second_profile_));
 
-    google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
-    std::unique_ptr<google_apis::FileResource> entry;
-
     // Place a hosted document under root/test_dir of the sub profile.
     sub_service->AddNewFileWithResourceId(
-        kResourceId,
-        "application/vnd.google-apps.document", "",
-        resource_ids_["test_dir"], "hosted_doc", true,
-        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-    content::RunAllBlockingPoolTasksUntilIdle();
-    if (error != google_apis::HTTP_CREATED)
-      return false;
+        kResourceId, "application/vnd.google-apps.document", "", "test_dir",
+        "hosted_doc", true, base::Bind(&IgnoreDriveEntryResult));
 
     // Place the hosted document with no parent in the main profile, for
     // simulating the situation that the document is shared to the main profile.
-    error = google_apis::DRIVE_OTHER_ERROR;
     main_service->AddNewFileWithResourceId(
-        kResourceId,
-        "application/vnd.google-apps.document", "", "", "hosted_doc", true,
-        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-    content::RunAllBlockingPoolTasksUntilIdle();
-    return (error == google_apis::HTTP_CREATED);
+        kResourceId, "application/vnd.google-apps.document", "", "",
+        "hosted_doc", true, base::Bind(&IgnoreDriveEntryResult));
   }
 
   base::ScopedTempDir tmp_dir_;
@@ -673,8 +567,7 @@
       create_drive_integration_service_;
   std::unique_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest>
       service_factory_for_test_;
-  Profile* second_profile_;
-  std::map<std::string, std::string> resource_ids_;
+  Profile* second_profile_ = nullptr;
 };
 
 class LocalAndDriveFileSystemExtensionApiTest
@@ -721,12 +614,7 @@
   // DriveIntegrationService factory function for this test.
   drive::DriveIntegrationService* CreateDriveIntegrationService(
       Profile* profile) {
-    fake_drive_service_ = new drive::FakeDriveService;
-    fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
-
-    std::map<std::string, std::string> resource_ids;
-    EXPECT_TRUE(InitializeDriveService(fake_drive_service_, &resource_ids));
-
+    fake_drive_service_ = CreateDriveService();
     return new drive::DriveIntegrationService(
         profile, nullptr, fake_drive_service_, "drive",
         test_cache_root_.GetPath(), nullptr);
@@ -739,7 +627,7 @@
 
   // For drive volume.
   base::ScopedTempDir test_cache_root_;
-  drive::FakeDriveService* fake_drive_service_;
+  drive::FakeDriveService* fake_drive_service_ = nullptr;
   DriveIntegrationServiceFactory::FactoryCallback
       create_drive_integration_service_;
   std::unique_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest>
@@ -866,7 +754,7 @@
 
 IN_PROC_BROWSER_TEST_F(MultiProfileDriveFileSystemExtensionApiTest,
                        CrossProfileCopy) {
-  ASSERT_TRUE(AddTestHostedDocuments());
+  AddTestHostedDocuments();
   EXPECT_TRUE(RunFileSystemExtensionApiTest(
       "file_browser/multi_profile_copy",
       FILE_PATH_LITERAL("manifest.json"),
diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
index ecab875..c96373a 100644
--- a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
@@ -25,6 +25,7 @@
 #include "components/drive/service/fake_drive_service.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/event_router.h"
+#include "google_apis/drive/base_requests.h"
 #include "google_apis/drive/drive_api_parser.h"
 #include "google_apis/drive/test_util.h"
 #include "storage/browser/fileapi/external_mount_points.h"
@@ -45,6 +46,9 @@
 // ID of a testing extension.
 const char kTestingExtensionId[] = "pkplfbidichfdicaijlchgnapepdginl";
 
+void IgnoreDriveEntryResult(google_apis::DriveApiErrorCode error,
+                            std::unique_ptr<google_apis::FileResource> entry) {}
+
 }  // namespace
 
 // Skips the user consent dialog for chrome.fileSystem.requestFileSystem() and
@@ -103,10 +107,7 @@
 // the integrated Google Drive support.
 class FileSystemApiTestForDrive : public PlatformAppBrowserTest {
  public:
-  FileSystemApiTestForDrive()
-      : fake_drive_service_(NULL),
-        integration_service_(NULL) {
-  }
+  FileSystemApiTestForDrive() {}
 
   // Sets up fake Drive service for tests (this has to be injected before the
   // real DriveIntegrationService instance is created.)
@@ -148,59 +149,52 @@
       Profile* profile) {
     // Ignore signin profile.
     if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir())
-      return NULL;
+      return nullptr;
 
     // FileSystemApiTestForDrive doesn't expect that several user profiles could
     // exist simultaneously.
-    DCHECK(fake_drive_service_ == NULL);
+    DCHECK(!fake_drive_service_);
     fake_drive_service_ = new drive::FakeDriveService;
     fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
 
     SetUpTestFileHierarchy();
 
     integration_service_ = new drive::DriveIntegrationService(
-        profile, NULL, fake_drive_service_, std::string(),
-        test_cache_root_.GetPath(), NULL);
+        profile, nullptr, fake_drive_service_, std::string(),
+        test_cache_root_.GetPath(), nullptr);
     return integration_service_;
   }
 
   void SetUpTestFileHierarchy() {
     const std::string root = fake_drive_service_->GetRootResourceId();
-    ASSERT_TRUE(AddTestFile("open_existing.txt", "Can you see me?", root));
-    ASSERT_TRUE(AddTestFile("open_existing1.txt", "Can you see me?", root));
-    ASSERT_TRUE(AddTestFile("open_existing2.txt", "Can you see me?", root));
-    ASSERT_TRUE(AddTestFile("save_existing.txt", "Can you see me?", root));
-    const std::string subdir = AddTestDirectory("subdir", root);
-    ASSERT_FALSE(subdir.empty());
-    ASSERT_TRUE(AddTestFile("open_existing.txt", "Can you see me?", subdir));
+    AddTestFile("open_existing.txt", "Can you see me?", root);
+    AddTestFile("open_existing1.txt", "Can you see me?", root);
+    AddTestFile("open_existing2.txt", "Can you see me?", root);
+    AddTestFile("save_existing.txt", "Can you see me?", root);
+
+    const char kSubdirResourceId[] = "subdir_resource_id";
+    AddTestDirectory(kSubdirResourceId, "subdir", root);
+    AddTestFile("open_existing.txt", "Can you see me?", kSubdirResourceId);
   }
 
-  bool AddTestFile(const std::string& title,
+  void AddTestFile(const std::string& title,
                    const std::string& data,
                    const std::string& parent_id) {
-    std::unique_ptr<google_apis::FileResource> entry;
-    google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
-    fake_drive_service_->AddNewFile(
-        "text/plain", data, parent_id, title, false,
-        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-    content::RunAllPendingInMessageLoop();
-    return error == google_apis::HTTP_CREATED && entry;
+    fake_drive_service_->AddNewFile("text/plain", data, parent_id, title, false,
+                                    base::Bind(&IgnoreDriveEntryResult));
   }
 
-  std::string AddTestDirectory(const std::string& title,
-                               const std::string& parent_id) {
-    std::unique_ptr<google_apis::FileResource> entry;
-    google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
-    fake_drive_service_->AddNewDirectory(
-        parent_id, title, drive::AddNewDirectoryOptions(),
-        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
-    content::RunAllPendingInMessageLoop();
-    return error == google_apis::HTTP_CREATED && entry ? entry->file_id() : "";
+  void AddTestDirectory(const std::string& resource_id,
+                        const std::string& title,
+                        const std::string& parent_id) {
+    fake_drive_service_->AddNewDirectoryWithResourceId(
+        resource_id, parent_id, title, drive::AddNewDirectoryOptions(),
+        base::Bind(&IgnoreDriveEntryResult));
   }
 
   base::ScopedTempDir test_cache_root_;
-  drive::FakeDriveService* fake_drive_service_;
-  drive::DriveIntegrationService* integration_service_;
+  drive::FakeDriveService* fake_drive_service_ = nullptr;
+  drive::DriveIntegrationService* integration_service_ = nullptr;
   drive::DriveIntegrationServiceFactory::FactoryCallback
       create_drive_integration_service_;
   std::unique_ptr<drive::DriveIntegrationServiceFactory::ScopedFactoryForTest>
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index d4d06ee7..a905b440 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -7,6 +7,7 @@
 
 #include "base/command_line.h"
 #include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/media/media_browsertest.h"
@@ -43,6 +44,8 @@
 
 #include "widevine_cdm_version.h"  //  In SHARED_INTERMEDIATE_DIR.
 
+namespace chrome {
+
 // Available key systems.
 const char kClearKeyKeySystem[] = "org.w3.clearkey";
 const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
@@ -101,9 +104,14 @@
 const char kDefaultEmePlayer[] = "eme_player.html";
 
 // The type of video src used to load media.
-enum SrcType {
-  SRC,
-  MSE
+enum class SrcType { SRC, MSE };
+
+// Must be in sync with CONFIG_CHANGE_TYPE in eme_player_js/global.js
+enum class ConfigChangeType {
+  CLEAR_TO_CLEAR = 0,
+  CLEAR_TO_ENCRYPTED = 1,
+  ENCRYPTED_TO_CLEAR = 2,
+  ENCRYPTED_TO_ENCRYPTED = 3,
 };
 
 // Whether the video should be played once or twice.
@@ -164,7 +172,7 @@
     query_params.push_back(std::make_pair("mediaFile", media_file));
     query_params.push_back(std::make_pair("mediaType", media_type));
     query_params.push_back(std::make_pair("keySystem", key_system));
-    if (src_type == MSE)
+    if (src_type == SrcType::MSE)
       query_params.push_back(std::make_pair("useMSE", "1"));
     if (force_invalid_response)
       query_params.push_back(std::make_pair("forceInvalidResponse", "1"));
@@ -301,7 +309,7 @@
     // Since we do not test playback, arbitrarily choose a test file and source
     // type.
     RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
-                          kWebMVorbisAudioOnly, key_system, SRC,
+                          kWebMVorbisAudioOnly, key_system, SrcType::SRC,
                           kNoSessionToLoad, false, PlayCount::ONCE,
                           expected_title);
   }
@@ -310,8 +318,9 @@
                         const std::string& session_to_load,
                         const std::string& expected_title) {
     RunEncryptedMediaTest(kDefaultEmePlayer, "bear-320x240-v_enc-v.webm",
-                          kWebMVP8VideoOnly, key_system, SRC, session_to_load,
-                          false, PlayCount::ONCE, expected_title);
+                          kWebMVP8VideoOnly, key_system, SrcType::SRC,
+                          session_to_load, false, PlayCount::ONCE,
+                          expected_title);
   }
 
  protected:
@@ -381,14 +390,26 @@
         kNoSessionToLoad, false, PlayCount::ONCE, kEnded);
   }
 
-  void TestConfigChange() {
+  void TestConfigChange(ConfigChangeType config_change_type) {
+    // TODO(xhwang): Even when config change or playback is not supported we
+    // still start Chrome only to return directly here. We probably should not
+    // run these test cases at all. See http://crbug.com/693288
+    if (CurrentSourceType() != SrcType::MSE) {
+      DVLOG(0) << "Config change only happens when using MSE.";
+      return;
+    }
+    if (!IsPlayBackPossible(CurrentKeySystem())) {
+      DVLOG(0) << "Skipping test - ConfigChange test requires video playback.";
+      return;
+    }
+
     base::StringPairs query_params;
     query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
-    query_params.push_back(std::make_pair("runEncrypted", "1"));
-    RunEncryptedMediaTestPage("mse_config_change.html",
-                              CurrentKeySystem(),
-                              query_params,
-                              kEnded);
+    query_params.push_back(std::make_pair(
+        "configChangeType",
+        base::IntToString(static_cast<int>(config_change_type))));
+    RunEncryptedMediaTestPage("mse_config_change.html", CurrentKeySystem(),
+                              query_params, kEnded);
   }
 
   std::string ConvertContainerFormat(EncryptedContainer format) {
@@ -437,24 +458,26 @@
 #if !defined(OS_ANDROID)
 INSTANTIATE_TEST_CASE_P(SRC_ClearKey,
                         EncryptedMediaTest,
-                        Combine(Values(kClearKeyKeySystem), Values(SRC)));
+                        Combine(Values(kClearKeyKeySystem),
+                                Values(SrcType::SRC)));
 #endif  // !defined(OS_ANDROID)
 
 INSTANTIATE_TEST_CASE_P(MSE_ClearKey,
                         EncryptedMediaTest,
-                        Combine(Values(kClearKeyKeySystem), Values(MSE)));
+                        Combine(Values(kClearKeyKeySystem),
+                                Values(SrcType::MSE)));
 
 // External Clear Key is currently only used on platforms that use Pepper CDMs.
 #if BUILDFLAG(ENABLE_PEPPER_CDMS)
 INSTANTIATE_TEST_CASE_P(SRC_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyKeySystem),
-                                Values(SRC)));
+                                Values(SrcType::SRC)));
 
 INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyKeySystem),
-                                Values(MSE)));
+                                Values(SrcType::MSE)));
 
 const char kExternalClearKeyDecryptOnlyKeySystem[] =
     "org.chromium.externalclearkey.decryptonly";
@@ -463,14 +486,15 @@
 INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKeyDecryptOnly,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyDecryptOnlyKeySystem),
-                                Values(MSE)));
+                                Values(SrcType::MSE)));
 #endif  // BUILDFLAG(ENABLE_PEPPER_CDMS)
 
 #if defined(WIDEVINE_CDM_AVAILABLE)
 #if !defined(OS_CHROMEOS)
 INSTANTIATE_TEST_CASE_P(MSE_Widevine,
                         EncryptedMediaTest,
-                        Combine(Values(kWidevineKeySystem), Values(MSE)));
+                        Combine(Values(kWidevineKeySystem),
+                                Values(SrcType::MSE)));
 #endif  // !defined(OS_CHROMEOS)
 #endif  // defined(WIDEVINE_CDM_AVAILABLE)
 
@@ -529,12 +553,28 @@
   RunInvalidResponseTest();
 }
 
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
-  if (!IsPlayBackPossible(CurrentKeySystem())) {
-    DVLOG(0) << "Skipping test - ConfigChange test requires video playback.";
-    return;
-  }
-  TestConfigChange();
+// Strictly speaking this is not an "encrypted" media test. Keep it here for
+// completeness.
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_ClearToClear) {
+  TestConfigChange(ConfigChangeType::CLEAR_TO_CLEAR);
+}
+
+// TODO(xhwang): Support switching from clear to encrypted and fix the test
+// expectation. Currently this test passes when we do decrypt-and-decode but
+// fails when we do decrypt-only due to how decoder reselection during config
+// change is handled. See http://crbug.com/597443
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+                       DISABLED_ConfigChangeVideo_ClearToEncrypted) {
+  TestConfigChange(ConfigChangeType::CLEAR_TO_ENCRYPTED);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_EncryptedToClear) {
+  TestConfigChange(ConfigChangeType::ENCRYPTED_TO_CLEAR);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+                       ConfigChangeVideo_EncryptedToEncrypted) {
+  TestConfigChange(ConfigChangeType::ENCRYPTED_TO_ENCRYPTED);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
@@ -567,7 +607,7 @@
 #endif
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_Playback_VideoOnly_MP4) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
-  if (CurrentSourceType() != MSE) {
+  if (CurrentSourceType() != SrcType::MSE) {
     DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
     return;
   }
@@ -576,7 +616,7 @@
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
-  if (CurrentSourceType() != MSE) {
+  if (CurrentSourceType() != SrcType::MSE) {
     DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
     return;
   }
@@ -585,7 +625,7 @@
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
-  if (CurrentSourceType() != MSE) {
+  if (CurrentSourceType() != SrcType::MSE) {
     DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
     return;
   }
@@ -595,7 +635,7 @@
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                        Playback_EncryptedVideo_MP4_ClearAudio_WEBM) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
-  if (CurrentSourceType() != MSE) {
+  if (CurrentSourceType() != SrcType::MSE) {
     DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
     return;
   }
@@ -610,7 +650,7 @@
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                        Playback_ClearVideo_WEBM_EncryptedAudio_MP4) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
-  if (CurrentSourceType() != MSE) {
+  if (CurrentSourceType() != SrcType::MSE) {
     DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
     return;
   }
@@ -625,7 +665,7 @@
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                        Playback_EncryptedVideo_WEBM_EncryptedAudio_MP4) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
-  if (CurrentSourceType() != MSE) {
+  if (CurrentSourceType() != SrcType::MSE) {
     DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
     return;
   }
@@ -642,7 +682,7 @@
 // The parent key system cannot be used when creating MediaKeys.
 IN_PROC_BROWSER_TEST_F(WVEncryptedMediaTest, ParentThrowsException) {
   RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
-                        kWebMVorbisAudioOnly, "com.widevine", MSE,
+                        kWebMVorbisAudioOnly, "com.widevine", SrcType::MSE,
                         kNoSessionToLoad, false, PlayCount::ONCE,
                         kEmeNotSupportedError);
 }
@@ -705,3 +745,5 @@
 }
 
 #endif  // BUILDFLAG(ENABLE_PEPPER_CDMS)
+
+}  // namespace chrome
diff --git a/chrome/browser/media/media_browsertest.cc b/chrome/browser/media/media_browsertest.cc
index 4cbb771c..e35484c 100644
--- a/chrome/browser/media/media_browsertest.cc
+++ b/chrome/browser/media/media_browsertest.cc
@@ -17,14 +17,18 @@
 #include "media/base/test_data_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
+namespace chrome {
+
+// TODO(sandersd): Change the tests to use a more unique message.
+// See http://crbug.com/592067
+
 // Normal failure title.
 const char MediaBrowserTest::kFailed[] = "FAILED";
 
-// Capitalized event name set by Utils.installTitleEventHandler().
+// Upper case event name set by Utils.installTitleEventHandler().
 const char MediaBrowserTest::kEnded[] = "ENDED";
 
-// Uncapitalized event name as set by Utils.failTest().
-// TODO(sandersd): Change the tests to use a more unique message.
+// Lower case event name as set by Utils.failTest().
 const char MediaBrowserTest::kError[] = "error";
 
 MediaBrowserTest::MediaBrowserTest() : ignore_plugin_crash_(false) {}
@@ -85,3 +89,5 @@
 void MediaBrowserTest::IgnorePluginCrash() {
   ignore_plugin_crash_ = true;
 }
+
+}  // namespace chrome
diff --git a/chrome/browser/media/media_browsertest.h b/chrome/browser/media/media_browsertest.h
index 1ad9c6cc..fda6b72 100644
--- a/chrome/browser/media/media_browsertest.h
+++ b/chrome/browser/media/media_browsertest.h
@@ -15,6 +15,8 @@
 class TitleWatcher;
 }
 
+namespace chrome {
+
 // Class used to automate running media related browser tests. The functions
 // assume that media files are located under media/ folder known to the test
 // http server.
@@ -57,4 +59,6 @@
   bool ignore_plugin_crash_;
 };
 
+}  // namespace chrome
+
 #endif  // CHROME_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.css b/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
index 0911b07..4ada0f6 100644
--- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
+++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
@@ -14,10 +14,7 @@
 }
 
 paper-toggle-button {
-  min-height: 20px;
-  min-width: 32px;
-  /* paper-toggle-button has fixed width of 36px. Make it 32. */
-  transform: scale(.8888);
+  width: 36px;
 }
 
 #titleContainer {
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.html b/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
index f008e5e..a130a33 100644
--- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
+++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.html
@@ -4,6 +4,30 @@
 
 <dom-module name="oobe-a11y-option">
   <template>
+    <style>
+      :root {
+          --oobe-toggle-button-size: {
+            box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4);
+            height: 16px;
+            top: -2px;
+            width: 16px;
+          };
+          --oobe-toggle-bar-size: {
+            height: 12px;
+            left: 4px;
+            width: 24px;
+          };
+          --paper-toggle-button-checked-bar: var(--oobe-toggle-bar-size);
+          --paper-toggle-button-checked-button: {
+            @apply(--oobe-toggle-button-size);
+            transform: translate(14px, 0);
+          };
+          --paper-toggle-button-label-spacing: 0;
+          --paper-toggle-button-unchecked-bar: var(--oobe-toggle-bar-size);
+          --paper-toggle-button-unchecked-button:
+              var(--oobe-toggle-button-size);
+      }
+    </style>
     <link rel="stylesheet" href="oobe_a11y_option.css">
     <div id="elementBox" class="layout horizontal">
       <div class="flex layout vertical center-justified">
diff --git a/chrome/browser/resources/md_downloads/BUILD.gn b/chrome/browser/resources/md_downloads/BUILD.gn
index b852bd4..b0e66aa 100644
--- a/chrome/browser/resources/md_downloads/BUILD.gn
+++ b/chrome/browser/resources/md_downloads/BUILD.gn
@@ -1,11 +1,21 @@
 import("../vulcanize.gni")
 
+vulcanized_unbuilt = "vulcanized.unbuilt.html"
+
 vulcanize("vulcanize") {
   deps = []
   host = "downloads"
   html_in_file = "downloads.html"
-  html_out_file = "vulcanized.html"
+  html_out_file = vulcanized_unbuilt
   input = rebase_path(".", root_build_dir)
   insert_in_head = "<base href=chrome://downloads>"
   js_out_file = "crisper.js"
 }
+
+polymer_css_build("build") {
+  input_files = [ vulcanized_unbuilt ]
+  output_files = [ "vulcanized.html" ]
+  deps = [
+    ":vulcanize",
+  ]
+}
diff --git a/chrome/browser/resources/md_history/BUILD.gn b/chrome/browser/resources/md_history/BUILD.gn
index 982772f..6f9eada 100644
--- a/chrome/browser/resources/md_history/BUILD.gn
+++ b/chrome/browser/resources/md_history/BUILD.gn
@@ -1,9 +1,12 @@
 import("../vulcanize.gni")
 
+app_unbuilt = "app.vulcanized.unbuilt.html"
+lazy_load_unbuilt = "lazy_load.vulcanized.unbuilt.html"
+
 vulcanize("vulcanize_app") {
   host = "history"
   html_in_file = "app.html"
-  html_out_file = "app.vulcanized.html"
+  html_out_file = app_unbuilt
 
   input = rebase_path(".", root_build_dir)
   js_out_file = "app.crisper.js"
@@ -19,7 +22,7 @@
 vulcanize("vulcanize_lazy_load") {
   host = "history"
   html_in_file = "lazy_load.html"
-  html_out_file = "lazy_load.vulcanized.html"
+  html_out_file = lazy_load_unbuilt
 
   input = rebase_path(".", root_build_dir)
   js_out_file = "lazy_load.crisper.js"
@@ -31,3 +34,18 @@
 
   deps = []
 }
+
+polymer_css_build("build") {
+  input_files = [
+    app_unbuilt,
+    lazy_load_unbuilt,
+  ]
+  output_files = [
+    "app.vulcanized.html",
+    "lazy_load.vulcanized.html",
+  ]
+  deps = [
+    ":vulcanize_app",
+    ":vulcanize_lazy_load",
+  ]
+}
diff --git a/chrome/browser/resources/polymer_css_build_gn.py b/chrome/browser/resources/polymer_css_build_gn.py
new file mode 100755
index 0000000..7a55fde
--- /dev/null
+++ b/chrome/browser/resources/polymer_css_build_gn.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+
+_HERE_PATH = os.path.dirname(__file__)
+_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..'))
+_CWD = os.getcwd()
+
+sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
+import node
+import node_modules
+
+def _css_build(out_folder, input_files, output_files):
+  out_path = os.path.join(_CWD, out_folder)
+  in_paths = map(lambda f: os.path.join(out_path, f), input_files)
+  out_paths = map(lambda f: os.path.join(out_path, f), output_files)
+
+  node.RunNode([node_modules.PathToPolymerCssBuild(), '-f'] + in_paths +
+               ['-o'] + out_paths)
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--out_folder')
+  parser.add_argument('--input_files', nargs='+')
+  parser.add_argument('--output_files', nargs='+')
+  args = parser.parse_args()
+
+  _css_build(
+      args.out_folder,
+      input_files=args.input_files,
+      output_files=args.output_files)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/chrome/browser/resources/vulcanize.gni b/chrome/browser/resources/vulcanize.gni
index bbb6410..454f92a9 100644
--- a/chrome/browser/resources/vulcanize.gni
+++ b/chrome/browser/resources/vulcanize.gni
@@ -2,13 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-template("vulcanize") {
+template("node") {
   action(target_name) {
-    script = "//chrome/browser/resources/vulcanize_gn.py"
+    forward_variables_from(invoker, "*")
 
     # Declare dependencies to all involved tools.
-    inputs = [
-      "//chrome/browser/resources/unpack_pak.py",
+    inputs += [
       "//third_party/node/node.py",
       "//third_party/node/node_modules.py",
       "//third_party/node/node_modules.tar.gz.sha1",
@@ -23,7 +22,18 @@
     if (is_mac) {
       inputs += [ "//third_party/node/mac/node-darwin-x64.tar.gz.sha1" ]
     }
+  }
+}
 
+template("vulcanize") {
+  node(target_name) {
+    script = "//chrome/browser/resources/vulcanize_gn.py"
+
+    inputs = [
+      "//chrome/browser/resources/unpack_pak.py",
+    ]
+
+    # This depfile is generated by vulcanize_gn.py
     depfile = "${target_gen_dir}/${target_name}.d"
 
     outputs = [
@@ -63,3 +73,28 @@
     }
   }
 }
+
+template("polymer_css_build") {
+  node(target_name) {
+    script = "//chrome/browser/resources/polymer_css_build_gn.py"
+
+    # Input and outputs files must be in the same order.
+    inputs = []
+    foreach(_input, invoker.input_files) {
+      inputs += [ "$target_gen_dir/$_input" ]
+    }
+
+    outputs = []
+    foreach(_output, invoker.output_files) {
+      outputs += [ "$target_gen_dir/$_output" ]
+    }
+
+    deps = invoker.deps
+
+    args = [
+             "--out_folder",
+             rebase_path(target_gen_dir, root_build_dir),
+             "--input_files",
+           ] + invoker.input_files + [ "--output_files" ] + invoker.output_files
+  }
+}
diff --git a/chrome/browser/resources/vulcanize_gn.py b/chrome/browser/resources/vulcanize_gn.py
index 4962d08..0cfca6e41 100755
--- a/chrome/browser/resources/vulcanize_gn.py
+++ b/chrome/browser/resources/vulcanize_gn.py
@@ -8,7 +8,6 @@
 import os
 import platform
 import re
-import subprocess
 import sys
 import tempfile
 
@@ -74,19 +73,6 @@
 _PAK_UNPACK_FOLDER = 'flattened'
 
 
-def _run_node(cmd_parts, stdout=None):
-  cmd = " ".join([node.GetBinaryPath()] + cmd_parts)
-  process = subprocess.Popen(
-      cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
-  stdout, stderr = process.communicate()
-
-  if stderr:
-    print >> sys.stderr, '%s failed: %s' % (cmd, stderr)
-    raise
-
-  return stdout
-
-
 def _undo_mapping(mappings, url):
   for (redirect_url, file_path) in mappings:
     if url.startswith(redirect_url):
@@ -154,7 +140,7 @@
     exclude_args.append('--exclude')
     exclude_args.append(f)
 
-  output = _run_node(
+  output = node.RunNode(
       [node_modules.PathToVulcanize()] +
       _VULCANIZE_BASE_ARGS + _VULCANIZE_REDIRECT_ARGS + exclude_args +
       ['--out-request-list', _request_list_path(out_path, args.html_out_file),
@@ -179,26 +165,19 @@
     tmp.write(output)
 
   try:
-    _run_node([node_modules.PathToCrisper(),
-             '--source', tmp.name,
-             '--script-in-head', 'false',
-             '--html', html_out_path,
-             '--js', js_out_path])
+    node.RunNode([node_modules.PathToCrisper(),
+                 '--source', tmp.name,
+                 '--script-in-head', 'false',
+                 '--html', html_out_path,
+                 '--js', js_out_path])
 
-    _run_node([node_modules.PathToUglifyJs(), js_out_path,
-              '--comments', '"/Copyright|license|LICENSE|\<\/?if/"',
-              '--output', js_out_path])
+    node.RunNode([node_modules.PathToUglifyJs(), js_out_path,
+                  '--comments', '"/Copyright|license|LICENSE|\<\/?if/"',
+                  '--output', js_out_path])
   finally:
     os.remove(tmp.name)
 
 
-def _css_build(out_folder, files):
-  out_path = os.path.join(_CWD, out_folder)
-  paths = [os.path.join(out_path, f) for f in files]
-
-  _run_node([node_modules.PathToPolymerCssBuild()] + paths)
-
-
 def main(argv):
   parser = argparse.ArgumentParser()
   parser.add_argument('--depfile', required=True)
@@ -230,7 +209,6 @@
     vulcanize_input_folder = output_folder
 
   _vulcanize(vulcanize_input_folder, args)
-  _css_build(args.out_folder, files=[args.html_out_file])
 
   _update_dep_file(vulcanize_input_folder, args)
 
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index be7339df..704a968 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -372,9 +372,11 @@
     case IDC_SELECT_TAB_5:
     case IDC_SELECT_TAB_6:
     case IDC_SELECT_TAB_7:
+      content::RecordAction(base::UserMetricsAction("Accel_SelectNumberedTab"));
       SelectNumberedTab(browser_, id - IDC_SELECT_TAB_0);
       break;
     case IDC_SELECT_LAST_TAB:
+      content::RecordAction(base::UserMetricsAction("Accel_SelectNumberedTab"));
       SelectLastTab(browser_);
       break;
     case IDC_DUPLICATE_TAB:
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 9af374e..8ddd56220 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1651,10 +1651,6 @@
       [[AvatarIconController alloc] initWithBrowser:browser_.get()]);
   }
   view = [avatarButtonController_ view];
-  if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout())
-    [view setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
-  else
-    [view setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
   [view setHidden:![self shouldShowAvatar]];
 
   // Install the view.
diff --git a/chrome/browser/ui/cocoa/location_bar/security_state_bubble_decoration.mm b/chrome/browser/ui/cocoa/location_bar/security_state_bubble_decoration.mm
index 7d105a92..63d57f3 100644
--- a/chrome/browser/ui/cocoa/location_bar/security_state_bubble_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/security_state_bubble_decoration.mm
@@ -80,6 +80,8 @@
   base::scoped_nsobject<NSMutableParagraphStyle> style(
       [[NSMutableParagraphStyle alloc] init]);
   [style setLineBreakMode:NSLineBreakByClipping];
+  if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout())
+    [style setAlignment:NSRightTextAlignment];
   [attributes_ setObject:style forKey:NSParagraphStyleAttributeName];
   animation_.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
 }
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
index c868408..d749a22 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_button_controller.mm
@@ -186,7 +186,7 @@
       [[avatarButton cell] setHighlightsBy:NSNoCellMask];
     [avatarButton setBordered:YES];
 
-    if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout())
+    if (cocoa_l10n_util::ShouldFlipWindowControlsInRTL())
       [avatarButton setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
     else
       [avatarButton setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 0494117..e1f40f7 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -313,6 +313,20 @@
   gfx::Size preferred_size_;
 };
 
+// NonInteractiveContainer -------------------------------------------------
+
+// A simple container view that does not process events within subtree.
+class NonInteractiveContainer : public views::View {
+ public:
+  NonInteractiveContainer() {}
+
+  // views::CanProcessEventsWithinSubtree:
+  bool CanProcessEventsWithinSubtree() const override { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NonInteractiveContainer);
+};
+
 // A view to host the GAIA webview overlapped with a back button.  This class
 // is needed to reparent the back button inside a native view so that on
 // windows, user input can be be properly routed to the button.
@@ -1746,7 +1760,8 @@
       ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta(
           1, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::MEDIUM));
   current_profile_name->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  views::View* profile_name_container = new views::View();
+  NonInteractiveContainer* profile_name_container =
+      new NonInteractiveContainer();
   int name_container_v_spacing =
       (current_profile_photo->GetPreferredSize().height() -
        current_profile_name->GetPreferredSize().height()) / 2;
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index 337732a..68410be 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -65,9 +65,11 @@
   # Indicates if the build is using PGO.
   pgo_build = chrome_pgo_phase > 0
 
-  # Use vulcanized HTML/CSS/JS resources to speed up WebUI (chrome://)
-  # pages. https://github.com/polymer/vulcanize
-  use_vulcanize = true
+  # Optimize parts of Chrome's UI written with web technologies (HTML/CSS/JS)
+  # for runtime performance purposes. This does more work at compile time for
+  # speed benefits at runtime (so we skip in debug builds). TODO(dbeam): rename
+  # this flag "optimize_web_uis" because we run more than vulcanize these days.
+  use_vulcanize = !is_debug
 }
 
 # Use brlapi from brltty for braille display support.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a9cb97e..46a800e 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -217,6 +217,10 @@
     ]
   }
   if (is_chromeos) {
+    sources += [
+      "../browser/chromeos/accessibility/speech_monitor.cc",
+      "../browser/chromeos/accessibility/speech_monitor.h",
+    ]
     public_deps += [
       "//components/ownership",
       "//components/user_manager:test_support",
@@ -617,8 +621,6 @@
         "../../ash/accelerators/accelerator_interactive_uitest_chromeos.cc",
         "../browser/chromeos/accessibility/accessibility_highlight_manager_interactive_uitest.cc",
         "../browser/chromeos/accessibility/magnification_controller_browsertest.cc",
-        "../browser/chromeos/accessibility/speech_monitor.cc",
-        "../browser/chromeos/accessibility/speech_monitor.h",
         "../browser/chromeos/accessibility/spoken_feedback_browsertest.cc",
         "../browser/chromeos/accessibility/sticky_keys_browsertest.cc",
         "../browser/chromeos/input_method/textinput_browsertest.cc",
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
index 32592872..a4f41d7 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -174,3 +174,22 @@
 TEST_F('CrElementsScrollableBehaviorTest', 'All', function() {
   mocha.run();
 });
+
+function CrElementsPolicyPrefIndicatorTest() {}
+
+CrElementsPolicyPrefIndicatorTest.prototype = {
+  __proto__: CrElementsBrowserTest.prototype,
+
+  /** @override */
+  browsePreload:
+      'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html',
+
+  /** @override */
+  extraLibraries: CrElementsBrowserTest.prototype.extraLibraries.concat([
+    'cr_policy_pref_indicator_tests.js',
+  ]),
+};
+
+TEST_F('CrElementsPolicyPrefIndicatorTest', 'All', function() {
+  mocha.run();
+});
diff --git a/chrome/test/data/webui/cr_elements/cr_policy_pref_indicator_tests.js b/chrome/test/data/webui/cr_elements/cr_policy_pref_indicator_tests.js
new file mode 100644
index 0000000..13169cb
--- /dev/null
+++ b/chrome/test/data/webui/cr_elements/cr_policy_pref_indicator_tests.js
@@ -0,0 +1,103 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Suite of tests for cr_policy-pref-indicator. */
+suite('CrPolicyPrefIndicator', function() {
+  /** @type {!CrPolicyPrefIndicatorElement|undefined} */
+  var indicator;
+
+  /** @type {!PaperTooltipElement|undefined} */
+  var tooltip;
+
+  suiteSetup(function() {
+    // Define chrome.settingsPrivate enums, normally provided by chrome WebUI.
+    // NOTE: These need to be kept in sync with settings_private.idl.
+
+    chrome.settingsPrivate = chrome.settingsPrivate || {};
+
+    /** @enum {string} */
+    chrome.settingsPrivate.ControlledBy = {
+      DEVICE_POLICY: 'DEVICE_POLICY',
+      USER_POLICY: 'USER_POLICY',
+      OWNER: 'OWNER',
+      PRIMARY_USER: 'PRIMARY_USER',
+      EXTENSION: 'EXTENSION',
+    };
+
+    /** @enum {string} */
+    chrome.settingsPrivate.Enforcement = {
+      ENFORCED: 'ENFORCED',
+      RECOMMENDED: 'RECOMMENDED',
+    };
+
+    /** @enum {string} */
+    chrome.settingsPrivate.PrefType = {
+      BOOLEAN: 'BOOLEAN',
+      NUMBER: 'NUMBER',
+      STRING: 'STRING',
+      URL: 'URL',
+      LIST: 'LIST',
+      DICTIONARY: 'DICTIONARY',
+    };
+
+    // Set up strings used by policy indicator elements.
+    CrPolicyStrings = {
+      controlledSettingPolicy: 'policy',
+      controlledSettingRecommendedMatches: 'matches',
+      controlledSettingRecommendedDiffers: 'differs',
+      controlledSettingShared: 'shared: $1',
+      controlledSettingOwner: 'owner: $1',
+    };
+  });
+
+  setup(function() {
+    PolymerTest.clearBody();
+
+    indicator = document.createElement('cr-policy-pref-indicator');
+    document.body.appendChild(indicator);
+    tooltip = indicator.$$('paper-tooltip');
+  });
+
+  teardown(function() {
+    PolymerTest.clearBody();  // crbug.com/680169
+  });
+
+  test('none', function() {
+    assertTrue(indicator.$.indicator.hidden);
+  });
+
+  test('pref', function() {
+    /** @type {!chrome.settingsPrivate.PrefObject} */
+    indicator.pref = {
+      key: 'foo',
+      type: chrome.settingsPrivate.PrefType.BOOLEAN,
+      value: false,
+    };
+    Polymer.dom.flush();
+    assertTrue(indicator.$.indicator.hidden);
+
+    indicator.set(
+        'pref.controlledBy', chrome.settingsPrivate.ControlledBy.OWNER);
+    indicator.set('pref.controlledByName', 'owner_name');
+    indicator.set(
+        'pref.enforcement', chrome.settingsPrivate.Enforcement.ENFORCED);
+    Polymer.dom.flush();
+    assertFalse(indicator.$.indicator.hidden);
+    assertEquals('cr:person', indicator.$.indicator.icon);
+    assertEquals('owner: owner_name', tooltip.textContent.trim());
+
+    indicator.set('pref.value', 'foo');
+    indicator.set('pref.recommendedValue', 'bar');
+    indicator.set(
+        'pref.enforcement', chrome.settingsPrivate.Enforcement.RECOMMENDED);
+    Polymer.dom.flush();
+    assertFalse(indicator.$.indicator.hidden);
+    assertEquals('cr20:domain', indicator.$.indicator.icon);
+    assertEquals('differs', tooltip.textContent.trim());
+
+    indicator.set('pref.value', 'bar');
+    Polymer.dom.flush();
+    assertEquals('matches', tooltip.textContent.trim());
+  });
+});
diff --git a/chromecast/media/cdm/cast_cdm.cc b/chromecast/media/cdm/cast_cdm.cc
index e2ead965..1f49273 100644
--- a/chromecast/media/cdm/cast_cdm.cc
+++ b/chromecast/media/cdm/cast_cdm.cc
@@ -51,6 +51,10 @@
     cast_cdm_->SetKeyStatus(key_id, key_status, system_code);
   }
 
+  void SetVideoResolution(int width, int height) override {
+    cast_cdm_->SetVideoResolution(width, height);
+  }
+
  private:
   // The CastCdm object which owns |this|.
   CastCdm* const cast_cdm_;
diff --git a/chromecast/media/cdm/cast_cdm.h b/chromecast/media/cdm/cast_cdm.h
index 14ec594d..6ceefd81 100644
--- a/chromecast/media/cdm/cast_cdm.h
+++ b/chromecast/media/cdm/cast_cdm.h
@@ -65,6 +65,9 @@
                             CastKeyStatus key_status,
                             uint32_t system_code) = 0;
 
+  // Notifies of current decoded video resolution.
+  virtual void SetVideoResolution(int width, int height) = 0;
+
   // ::media::ContentDecryptionModule implementation.
   ::media::CdmContext* GetCdmContext() override;
 
diff --git a/chromecast/media/cdm/cast_cdm_context.h b/chromecast/media/cdm/cast_cdm_context.h
index 2c69498..606509d 100644
--- a/chromecast/media/cdm/cast_cdm_context.h
+++ b/chromecast/media/cdm/cast_cdm_context.h
@@ -44,6 +44,10 @@
   virtual void SetKeyStatus(const std::string& key_id,
                             CastKeyStatus key_status,
                             uint32_t system_code) = 0;
+
+  // Notifies of current decoded video resolution (used for licence policy
+  // enforcement).
+  virtual void SetVideoResolution(int width, int height) = 0;
 };
 
 }  // namespace media
diff --git a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
index 5872e35..597052a 100644
--- a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
+++ b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
@@ -88,6 +88,8 @@
                     CastKeyStatus key_status,
                     uint32_t system_code) override {}
 
+  void SetVideoResolution(int width, int height) override {}
+
  private:
   bool license_installed_;
   base::Closure new_key_cb_;
diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.h b/chromecast/media/cma/pipeline/av_pipeline_impl.h
index ab86e76..3558694 100644
--- a/chromecast/media/cma/pipeline/av_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/av_pipeline_impl.h
@@ -70,6 +70,7 @@
   State state() const { return state_; }
   void set_state(State state) { state_ = state; }
   const AvPipelineClient& client() const { return client_; }
+  CastCdmContext* cdm_context() const { return cast_cdm_context_; }
 
   virtual void OnUpdateConfig(
       StreamId id,
diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
index c8758745..518f7731 100644
--- a/chromecast/media/cma/pipeline/video_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "chromecast/base/metrics/cast_metrics_helper.h"
+#include "chromecast/media/cdm/cast_cdm_context.h"
 #include "chromecast/media/cma/base/buffering_defs.h"
 #include "chromecast/media/cma/base/cma_logging.h"
 #include "chromecast/media/cma/base/coded_frame_provider.h"
@@ -92,6 +93,11 @@
   if (!natural_size_changed_cb_.is_null()) {
     natural_size_changed_cb_.Run(gfx::Size(size.width, size.height));
   }
+
+  CastCdmContext* cdm = cdm_context();
+  if (cdm) {
+    cdm->SetVideoResolution(size.width, size.height);
+  }
 }
 
 void VideoPipelineImpl::OnUpdateConfig(
diff --git a/components/display_compositor/gpu_compositor_frame_sink.cc b/components/display_compositor/gpu_compositor_frame_sink.cc
index ac1584b..a5bd246 100644
--- a/components/display_compositor/gpu_compositor_frame_sink.cc
+++ b/components/display_compositor/gpu_compositor_frame_sink.cc
@@ -76,9 +76,11 @@
     client_->ReclaimResources(resources);
 }
 
-void GpuCompositorFrameSink::WillDrawSurface() {
+void GpuCompositorFrameSink::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {
   if (client_)
-    client_->WillDrawSurface();
+    client_->WillDrawSurface(local_surface_id, damage_rect);
 }
 
 void GpuCompositorFrameSink::OnClientConnectionLost() {
@@ -95,4 +97,9 @@
                                      client_connection_lost_);
 }
 
+void GpuCompositorFrameSink::RequestCopyOfSurface(
+    std::unique_ptr<cc::CopyOutputRequest> request) {
+  support_->RequestCopyOfSurface(std::move(request));
+}
+
 }  // namespace display_compositor
diff --git a/components/display_compositor/gpu_compositor_frame_sink.h b/components/display_compositor/gpu_compositor_frame_sink.h
index 0b1acb9..c724539 100644
--- a/components/display_compositor/gpu_compositor_frame_sink.h
+++ b/components/display_compositor/gpu_compositor_frame_sink.h
@@ -47,6 +47,8 @@
   void AddChildFrameSink(const cc::FrameSinkId& child_frame_sink_id) override;
   void RemoveChildFrameSink(
       const cc::FrameSinkId& child_frame_sink_id) override;
+  void RequestCopyOfSurface(
+      std::unique_ptr<cc::CopyOutputRequest> request) override;
 
  protected:
   void OnClientConnectionLost();
@@ -60,7 +62,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
   bool client_connection_lost_ = false;
   bool private_connection_lost_ = false;
diff --git a/components/exo/compositor_frame_sink.cc b/components/exo/compositor_frame_sink.cc
index b834ad3c..0c197afc 100644
--- a/components/exo/compositor_frame_sink.cc
+++ b/components/exo/compositor_frame_sink.cc
@@ -70,8 +70,10 @@
   client_->ReclaimResources(resources);
 }
 
-void CompositorFrameSink::WillDrawSurface() {
-  client_->WillDrawSurface();
+void CompositorFrameSink::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {
+  client_->WillDrawSurface(local_surface_id, damage_rect);
 }
 
 }  // namespace exo
diff --git a/components/exo/compositor_frame_sink.h b/components/exo/compositor_frame_sink.h
index da24d178..c269004 100644
--- a/components/exo/compositor_frame_sink.h
+++ b/components/exo/compositor_frame_sink.h
@@ -38,7 +38,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
  private:
   cc::CompositorFrameSinkSupport support_;
diff --git a/components/exo/compositor_frame_sink_holder.cc b/components/exo/compositor_frame_sink_holder.cc
index 7d5d5f7..df76d11 100644
--- a/components/exo/compositor_frame_sink_holder.cc
+++ b/components/exo/compositor_frame_sink_holder.cc
@@ -76,7 +76,9 @@
   }
 }
 
-void CompositorFrameSinkHolder::WillDrawSurface() {
+void CompositorFrameSinkHolder::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {
   if (surface_)
     surface_->WillDraw();
 
diff --git a/components/exo/compositor_frame_sink_holder.h b/components/exo/compositor_frame_sink_holder.h
index 7efa6ded..1309bf8 100644
--- a/components/exo/compositor_frame_sink_holder.h
+++ b/components/exo/compositor_frame_sink_holder.h
@@ -54,7 +54,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
   // Overridden from cc::BeginFrameObserver:
   const cc::BeginFrameArgs& LastUsedBeginFrameArgs() const override;
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index c057729..9e76be17 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -2217,6 +2217,54 @@
     return CreateTextMarker(position->CreatePreviousWordStartPosition());
   }
 
+  if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
+    AXPlatformPositionInstance position =
+        CreatePositionFromTextMarker(parameter);
+    if (position->IsNullPosition())
+      return nil;
+
+    AXPlatformPositionInstance startPosition =
+        position->CreatePreviousLineStartPosition();
+    AXPlatformPositionInstance endPosition =
+        position->CreateNextLineEndPosition();
+    AXPlatformRange range(std::move(startPosition), std::move(endPosition));
+    return CreateTextMarkerRange(std::move(range));
+  }
+
+  if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
+    AXPlatformPositionInstance endPosition =
+        CreatePositionFromTextMarker(parameter);
+    if (endPosition->IsNullPosition())
+      return nil;
+
+    AXPlatformPositionInstance startLinePosition =
+        endPosition->CreatePreviousLineStartPosition();
+    AXPlatformPositionInstance endLinePosition =
+        endPosition->CreatePreviousLineEndPosition();
+    AXPlatformPositionInstance startPosition =
+        *startLinePosition <= *endLinePosition ? std::move(endLinePosition)
+                                               : std::move(startLinePosition);
+    AXPlatformRange range(std::move(startPosition), std::move(endPosition));
+    return CreateTextMarkerRange(std::move(range));
+  }
+
+  if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
+    AXPlatformPositionInstance startPosition =
+        CreatePositionFromTextMarker(parameter);
+    if (startPosition->IsNullPosition())
+      return nil;
+
+    AXPlatformPositionInstance startLinePosition =
+        startPosition->CreateNextLineStartPosition();
+    AXPlatformPositionInstance endLinePosition =
+        startPosition->CreateNextLineEndPosition();
+    AXPlatformPositionInstance endPosition =
+        *startLinePosition <= *endLinePosition ? std::move(startLinePosition)
+                                               : std::move(endLinePosition);
+    AXPlatformRange range(std::move(startPosition), std::move(endPosition));
+    return CreateTextMarkerRange(std::move(range));
+  }
+
   if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
     AXPlatformPositionInstance position =
         CreatePositionFromTextMarker(parameter);
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc
index 2b18cd2d..1503a16 100644
--- a/content/browser/media/encrypted_media_browsertest.cc
+++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "content/browser/media/media_browsertest.h"
@@ -29,6 +30,8 @@
 #define SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL
 #endif
 
+namespace content {
+
 // Available key systems.
 const char kClearKeyKeySystem[] = "org.w3.clearkey";
 
@@ -51,20 +54,24 @@
 const char kDefaultEmePlayer[] = "eme_player.html";
 
 // The type of video src used to load media.
-enum SrcType {
-  SRC,
-  MSE
-};
+enum class SrcType { SRC, MSE };
 
-namespace content {
+// Must be in sync with CONFIG_CHANGE_TYPE in eme_player_js/global.js
+enum class ConfigChangeType {
+  CLEAR_TO_CLEAR = 0,
+  CLEAR_TO_ENCRYPTED = 1,
+  ENCRYPTED_TO_CLEAR = 2,
+  ENCRYPTED_TO_ENCRYPTED = 3,
+};
 
 // Tests encrypted media playback with a combination of parameters:
 // - char*: Key system name.
 // - SrcType: The type of video src used to load media, MSE or SRC.
 // It is okay to run this test as a non-parameterized test, in this case,
 // GetParam() should not be called.
-class EncryptedMediaTest : public content::MediaBrowserTest,
-    public testing::WithParamInterface<std::tr1::tuple<const char*, SrcType> > {
+class EncryptedMediaTest : public MediaBrowserTest,
+                           public testing::WithParamInterface<
+                               std::tr1::tuple<const char*, SrcType>> {
  public:
   // Can only be used in parameterized (*_P) tests.
   const std::string CurrentKeySystem() {
@@ -89,10 +96,20 @@
                           CurrentSourceType(), kEnded);
   }
 
-  void TestConfigChange() {
+  void TestConfigChange(ConfigChangeType config_change_type) {
+    // TODO(xhwang): Even when config change is not supported we still start
+    // content shell only to return directly here. We probably should not run
+    // these test cases at all.
+    if (CurrentSourceType() != SrcType::MSE) {
+      DVLOG(0) << "Config change only happens when using MSE.";
+      return;
+    }
+
     base::StringPairs query_params;
     query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
-    query_params.push_back(std::make_pair("runEncrypted", "1"));
+    query_params.push_back(std::make_pair(
+        "configChangeType",
+        base::IntToString(static_cast<int>(config_change_type))));
     RunMediaTestPage("mse_config_change.html", query_params, kEnded, true);
   }
 
@@ -106,7 +123,7 @@
     query_params.push_back(std::make_pair("mediaFile", media_file));
     query_params.push_back(std::make_pair("mediaType", media_type));
     query_params.push_back(std::make_pair("keySystem", key_system));
-    if (src_type == MSE)
+    if (src_type == SrcType::MSE)
       query_params.push_back(std::make_pair("useMSE", "1"));
     RunMediaTestPage(html_page, query_params, expectation, true);
   }
@@ -144,22 +161,26 @@
 using ::testing::Combine;
 using ::testing::Values;
 
-INSTANTIATE_TEST_CASE_P(SRC_ClearKey, EncryptedMediaTest,
-                        Combine(Values(kClearKeyKeySystem), Values(SRC)));
+INSTANTIATE_TEST_CASE_P(SRC_ClearKey,
+                        EncryptedMediaTest,
+                        Combine(Values(kClearKeyKeySystem),
+                                Values(SrcType::SRC)));
 
-INSTANTIATE_TEST_CASE_P(MSE_ClearKey, EncryptedMediaTest,
-                        Combine(Values(kClearKeyKeySystem), Values(MSE)));
+INSTANTIATE_TEST_CASE_P(MSE_ClearKey,
+                        EncryptedMediaTest,
+                        Combine(Values(kClearKeyKeySystem),
+                                Values(SrcType::MSE)));
 
 #if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL)
 INSTANTIATE_TEST_CASE_P(SRC_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyKeySystem),
-                                Values(SRC)));
+                                Values(SrcType::SRC)));
 
 INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyKeySystem),
-                                Values(MSE)));
+                                Values(SrcType::MSE)));
 #endif
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
@@ -217,8 +238,26 @@
   TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMOpusAudioVP9Video);
 }
 
-IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
-  TestConfigChange();
+// Strictly speaking this is not an "encrypted" media test. Keep it here for
+// completeness.
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_ClearToClear) {
+  TestConfigChange(ConfigChangeType::CLEAR_TO_CLEAR);
+}
+
+// TODO(xhwang): Support switching from clear to encrypted and enable this test.
+// See http://crbug.com/597443
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+                       DISABLED_ConfigChangeVideo_ClearToEncrypted) {
+  TestConfigChange(ConfigChangeType::CLEAR_TO_ENCRYPTED);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_EncryptedToClear) {
+  TestConfigChange(ConfigChangeType::ENCRYPTED_TO_CLEAR);
+}
+
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
+                       ConfigChangeVideo_EncryptedToEncrypted) {
+  TestConfigChange(ConfigChangeType::ENCRYPTED_TO_ENCRYPTED);
 }
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
@@ -227,7 +266,7 @@
 
 IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
   RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
-                        kWebMVorbisAudioOnly, "com.example.foo", MSE,
+                        kWebMVorbisAudioOnly, "com.example.foo", SrcType::MSE,
                         kEmeNotSupportedError);
 }
 
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc
index d19bfe2c..b831a98 100644
--- a/content/browser/media/media_browsertest.cc
+++ b/content/browser/media/media_browsertest.cc
@@ -20,11 +20,19 @@
 
 namespace content {
 
+// TODO(sandersd): Change the tests to use a more unique message.
+// See http://crbug.com/592067
+
 // Common test results.
-const char MediaBrowserTest::kEnded[] = "ENDED";
-const char MediaBrowserTest::kError[] = "ERROR";
 const char MediaBrowserTest::kFailed[] = "FAILED";
 
+// Upper case event name set by Utils.installTitleEventHandler().
+const char MediaBrowserTest::kEnded[] = "ENDED";
+const char MediaBrowserTest::kErrorEvent[] = "ERROR";
+
+// Lower case event name as set by Utils.failTest().
+const char MediaBrowserTest::kError[] = "error";
+
 void MediaBrowserTest::SetUpCommandLine(base::CommandLine* command_line) {
   command_line->AppendSwitch(
       switches::kDisableGestureRequirementForMediaPlayback);
@@ -65,6 +73,7 @@
 void MediaBrowserTest::AddTitlesToAwait(content::TitleWatcher* title_watcher) {
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEnded));
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kError));
+  title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kErrorEvent));
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kFailed));
 }
 
diff --git a/content/browser/media/media_browsertest.h b/content/browser/media/media_browsertest.h
index 5baa302..238b667 100644
--- a/content/browser/media/media_browsertest.h
+++ b/content/browser/media/media_browsertest.h
@@ -20,6 +20,7 @@
   // Common test results.
   static const char kEnded[];
   static const char kError[];
+  static const char kErrorEvent[];
   static const char kFailed[];
 
   // ContentBrowserTest implementation.
diff --git a/content/browser/media/media_source_browsertest.cc b/content/browser/media/media_source_browsertest.cc
index 9423d90..127c125 100644
--- a/content/browser/media/media_source_browsertest.cc
+++ b/content/browser/media/media_source_browsertest.cc
@@ -78,7 +78,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_Type_Error) {
-  TestSimplePlayback("bear-320x240-video-only.webm", kWebMAudioOnly, kError);
+  TestSimplePlayback("bear-320x240-video-only.webm", kWebMAudioOnly,
+                     kErrorEvent);
 }
 
 // Flaky test crbug.com/246308
diff --git a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
index 29306b4..e52843a 100644
--- a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
+++ b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.cc
@@ -80,9 +80,11 @@
     client_->ReclaimResources(resources);
 }
 
-void OffscreenCanvasCompositorFrameSink::WillDrawSurface() {
+void OffscreenCanvasCompositorFrameSink::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {
   if (client_)
-    client_->WillDrawSurface();
+    client_->WillDrawSurface(local_surface_id, damage_rect);
 }
 
 void OffscreenCanvasCompositorFrameSink::OnClientConnectionLost() {
diff --git a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h
index 0cdc3792..af97705 100644
--- a/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h
+++ b/content/browser/renderer_host/offscreen_canvas_compositor_frame_sink.h
@@ -41,7 +41,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
  private:
   void OnClientConnectionLost();
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 30f61379..04f6549 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -709,10 +709,9 @@
   results->is_monochrome = false;
   results->device_scale_factor = display.device_scale_factor();
   results->icc_profile = gfx::ICCProfile::FromBestMonitor();
-  if (results->icc_profile == gfx::ICCProfile()) {
-    results->icc_profile =
-        gfx::ICCProfile::FromColorSpace(gfx::ColorSpace::CreateSRGB());
-  }
+  if (!results->icc_profile.IsValid())
+    gfx::ColorSpace::CreateSRGB().GetICCProfile(&results->icc_profile);
+  DCHECK(results->icc_profile.IsValid());
 
   // The Display rotation and the ScreenInfo orientation are not the same
   // angle. The former is the physical display rotation while the later is the
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index e9a64b51..0c3057a 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -249,6 +249,12 @@
 const base::Feature kWebRtcHWH264Encoding{
     "WebRtcHWH264Encoding", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables the WebRTC Echo Canceller version 3 (AEC3). Feature for
+// http://crbug.com/688388. This value is sent to WebRTC's echo canceller to
+// toggle which echo canceller should be used.
+const base::Feature kWebRtcUseEchoCanceller3{"WebRtcUseEchoCanceller3",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Controls whether the WebUSB API is enabled:
 // https://wicg.github.io/webusb
 const base::Feature kWebUsb{"WebUSB", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 359a9515..f447a60 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -65,6 +65,7 @@
 CONTENT_EXPORT extern const base::Feature kWebGLImageChromium;
 CONTENT_EXPORT extern const base::Feature kWebRtcEcdsaDefault;
 CONTENT_EXPORT extern const base::Feature kWebRtcHWH264Encoding;
+CONTENT_EXPORT extern const base::Feature kWebRtcUseEchoCanceller3;
 CONTENT_EXPORT extern const base::Feature kWebRtcUseGpuMemoryBufferVideoFrames;
 CONTENT_EXPORT extern const base::Feature kWebUsb;
 CONTENT_EXPORT
diff --git a/content/renderer/android/synchronous_compositor_frame_sink.cc b/content/renderer/android/synchronous_compositor_frame_sink.cc
index 8edefc70..6f3b6b9c 100644
--- a/content/renderer/android/synchronous_compositor_frame_sink.cc
+++ b/content/renderer/android/synchronous_compositor_frame_sink.cc
@@ -471,6 +471,8 @@
   client_->ReclaimResources(resources);
 }
 
-void SynchronousCompositorFrameSink::WillDrawSurface() {}
+void SynchronousCompositorFrameSink::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {}
 
 }  // namespace content
diff --git a/content/renderer/android/synchronous_compositor_frame_sink.h b/content/renderer/android/synchronous_compositor_frame_sink.h
index 34f373f..771a73c2 100644
--- a/content/renderer/android/synchronous_compositor_frame_sink.h
+++ b/content/renderer/android/synchronous_compositor_frame_sink.h
@@ -98,7 +98,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& args) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
  private:
   class SoftwareOutputSurface;
diff --git a/content/renderer/media/cdm/ppapi_decryptor.cc b/content/renderer/media/cdm/ppapi_decryptor.cc
index ae9d90a..bfca0d1 100644
--- a/content/renderer/media/cdm/ppapi_decryptor.cc
+++ b/content/renderer/media/cdm/ppapi_decryptor.cc
@@ -248,6 +248,8 @@
     return;
   }
 
+  // TODO(xhwang): If the buffer is not encrypted, return it directly.
+
   DVLOG(3) << __func__ << " - stream_type: " << stream_type;
   if (!CdmDelegate() ||
       !CdmDelegate()->Decrypt(stream_type, encrypted, decrypt_cb)) {
@@ -279,7 +281,6 @@
   }
 
   DVLOG(2) << __func__;
-  DCHECK(config.is_encrypted());
   DCHECK(config.IsValidConfig());
 
   audio_decoder_init_cb_ = init_cb;
@@ -303,7 +304,6 @@
   }
 
   DVLOG(2) << __func__;
-  DCHECK(config.is_encrypted());
   DCHECK(config.IsValidConfig());
 
   video_decoder_init_cb_ = init_cb;
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc
index 6f7afe6..4c6f65c2 100644
--- a/content/renderer/media/media_stream_audio_processor.cc
+++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -18,6 +18,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/renderer/media/media_stream_audio_processor_options.h"
 #include "content/renderer/media/webrtc_audio_device_impl.h"
@@ -676,6 +677,11 @@
     // Prepare for logging echo information. If there are data remaining in
     // |echo_information_| we simply discard it.
     echo_information_.reset(new EchoInformation());
+
+    apm_config.echo_canceller3.enabled =
+        base::FeatureList::IsEnabled(features::kWebRtcUseEchoCanceller3);
+  } else {
+    apm_config.echo_canceller3.enabled = false;
   }
 
   if (goog_ns) {
diff --git a/content/renderer/media/midi_message_filter.cc b/content/renderer/media/midi_message_filter.cc
index 311d76b..bbc3556 100644
--- a/content/renderer/media/midi_message_filter.cc
+++ b/content/renderer/media/midi_message_filter.cc
@@ -51,6 +51,11 @@
 }
 
 void MidiMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) {
+  DCHECK(clients_.find(client) != clients_.end() ||
+         std::find(clients_waiting_session_queue_.begin(),
+                   clients_waiting_session_queue_.end(),
+                   client) != clients_waiting_session_queue_.end())
+      << "RemoveClient call was not ballanced with AddClient call";
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   clients_.erase(client);
   ClientsQueue::iterator it = std::find(clients_waiting_session_queue_.begin(),
diff --git a/content/renderer/media/renderer_webmidiaccessor_impl.cc b/content/renderer/media/renderer_webmidiaccessor_impl.cc
index b67f48a..842a508 100644
--- a/content/renderer/media/renderer_webmidiaccessor_impl.cc
+++ b/content/renderer/media/renderer_webmidiaccessor_impl.cc
@@ -12,16 +12,18 @@
 
 RendererWebMIDIAccessorImpl::RendererWebMIDIAccessorImpl(
     blink::WebMIDIAccessorClient* client)
-    : client_(client) {
+    : client_(client), is_client_added_(false) {
   DCHECK(client_);
 }
 
 RendererWebMIDIAccessorImpl::~RendererWebMIDIAccessorImpl() {
-  midi_message_filter()->RemoveClient(client_);
+  if (is_client_added_)
+    midi_message_filter()->RemoveClient(client_);
 }
 
 void RendererWebMIDIAccessorImpl::startSession() {
   midi_message_filter()->AddClient(client_);
+  is_client_added_ = true;
 }
 
 void RendererWebMIDIAccessorImpl::sendMIDIData(
diff --git a/content/renderer/media/renderer_webmidiaccessor_impl.h b/content/renderer/media/renderer_webmidiaccessor_impl.h
index 0058c5c..2745915 100644
--- a/content/renderer/media/renderer_webmidiaccessor_impl.h
+++ b/content/renderer/media/renderer_webmidiaccessor_impl.h
@@ -33,6 +33,8 @@
  private:
   blink::WebMIDIAccessorClient* client_;
 
+  bool is_client_added_;
+
   MidiMessageFilter* midi_message_filter();
 
   DISALLOW_COPY_AND_ASSIGN(RendererWebMIDIAccessorImpl);
diff --git a/content/renderer/pepper/content_decryptor_delegate.cc b/content/renderer/pepper/content_decryptor_delegate.cc
index 88126db9..0048699 100644
--- a/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/content/renderer/pepper/content_decryptor_delegate.cc
@@ -95,32 +95,31 @@
   return true;
 }
 
-// Fills the |block_info| with information from |encrypted_buffer|.
+// Fills the |block_info| with information from |buffer|.
 //
 // Returns true if |block_info| is successfully filled. Returns false
 // otherwise.
-bool MakeEncryptedBlockInfo(
-    const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
-    uint32_t request_id,
-    PP_EncryptedBlockInfo* block_info) {
+bool MakeEncryptedBlockInfo(const scoped_refptr<media::DecoderBuffer>& buffer,
+                            uint32_t request_id,
+                            PP_EncryptedBlockInfo* block_info) {
   // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and
   // anywhere else.
   memset(block_info, 0, sizeof(*block_info));
   block_info->tracking_info.request_id = request_id;
 
   // EOS buffers need a request ID and nothing more.
-  if (encrypted_buffer->end_of_stream())
+  if (buffer->end_of_stream())
     return true;
 
-  DCHECK(encrypted_buffer->data_size())
-      << "DecryptConfig is set on an empty buffer";
+  DCHECK(buffer->data_size()) << "DecryptConfig is set on an empty buffer";
 
-  block_info->tracking_info.timestamp =
-      encrypted_buffer->timestamp().InMicroseconds();
-  block_info->data_size = encrypted_buffer->data_size();
+  block_info->tracking_info.timestamp = buffer->timestamp().InMicroseconds();
+  block_info->data_size = buffer->data_size();
 
-  const media::DecryptConfig* decrypt_config =
-      encrypted_buffer->decrypt_config();
+  const media::DecryptConfig* decrypt_config = buffer->decrypt_config();
+  // There's no need to fill encryption related fields for unencrypted buffer.
+  if (!decrypt_config)
+    return true;
 
   if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) ||
       !CopyStringToArray(decrypt_config->iv(), block_info->iv))
@@ -529,7 +528,6 @@
   DVLOG(2) << "Decrypt() - request_id " << request_id;
 
   PP_EncryptedBlockInfo block_info = {};
-  DCHECK(encrypted_buffer->decrypt_config());
   if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) {
     return false;
   }
@@ -1113,12 +1111,12 @@
 
 bool ContentDecryptorDelegate::MakeMediaBufferResource(
     Decryptor::StreamType stream_type,
-    const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
+    const scoped_refptr<media::DecoderBuffer>& buffer,
     scoped_refptr<PPB_Buffer_Impl>* resource) {
   TRACE_EVENT0("media", "ContentDecryptorDelegate::MakeMediaBufferResource");
 
   // End of stream buffers are represented as null resources.
-  if (encrypted_buffer->end_of_stream()) {
+  if (buffer->end_of_stream()) {
     *resource = NULL;
     return true;
   }
@@ -1128,7 +1126,7 @@
       (stream_type == Decryptor::kAudio) ? audio_input_resource_
                                          : video_input_resource_;
 
-  const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size());
+  const size_t data_size = static_cast<size_t>(buffer->data_size());
   if (!media_resource.get() || media_resource->size() < data_size) {
     // Either the buffer hasn't been created yet, or we have one that isn't big
     // enough to fit |size| bytes.
@@ -1159,7 +1157,7 @@
     media_resource = NULL;
     return false;
   }
-  memcpy(mapper.data(), encrypted_buffer->data(), data_size);
+  memcpy(mapper.data(), buffer->data(), data_size);
 
   *resource = media_resource;
   return true;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 96c1e721..7e510c2 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -815,10 +815,6 @@
                  base::Unretained(this))));
 
   if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
-    // Currently it is not possible to enable both PurgeAndSuspend and
-    // MemoryCoordinator at the same time.
-    DCHECK(!base::FeatureList::IsEnabled(features::kPurgeAndSuspend));
-
     // Disable MemoryPressureListener when memory coordinator is enabled.
     base::MemoryPressureListener::SetNotificationsSuppressed(true);
 
@@ -1634,11 +1630,6 @@
     needs_to_record_first_active_paint_ = false;
   } else {
     renderer_scheduler_->OnRendererForegrounded();
-    // TODO(tasak): after enabling MemoryCoordinator, remove this Notify
-    // and follow MemoryCoordinator's request.
-    if (base::FeatureList::IsEnabled(features::kPurgeAndSuspend))
-      base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(
-          base::MemoryState::NORMAL);
 
     record_purge_suspend_metric_closure_.Cancel();
     record_purge_suspend_metric_closure_.Reset(
@@ -1656,13 +1647,7 @@
   if (!RendererIsHidden())
     return;
 
-  // TODO(bashi): Enable the tab suspension when MemoryCoordinator is enabled.
-  if (base::FeatureList::IsEnabled(features::kMemoryCoordinator))
-    return;
-
   if (base::FeatureList::IsEnabled(features::kPurgeAndSuspend)) {
-    // TODO(tasak): After enabling MemoryCoordinator, remove this Notify
-    // and follow MemoryCoordinator's request.
     base::MemoryCoordinatorClientRegistry::GetInstance()->PurgeMemory();
   }
   // Since purging is not a synchronous task (e.g. v8 GC, oilpan GC, ...),
@@ -1835,24 +1820,6 @@
                         total_allocated_mb) * 1024);
 }
 
-void RenderThreadImpl::OnProcessResume() {
-  ChildThreadImpl::OnProcessResume();
-
-  if (!RendererIsHidden())
-    return;
-
-  // TODO(bashi): Enable the tab suspension when MemoryCoordinator is enabled.
-  if (base::FeatureList::IsEnabled(features::kMemoryCoordinator))
-    return;
-
-  if (base::FeatureList::IsEnabled(features::kPurgeAndSuspend)) {
-    // TODO(tasak): after enabling MemoryCoordinator, remove this Notify
-    // and follow MemoryCoordinator's request.
-    base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(
-        base::MemoryState::NORMAL);
-  }
-}
-
 scoped_refptr<gpu::GpuChannelHost> RenderThreadImpl::EstablishGpuChannelSync() {
   TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync");
 
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 9b37b79..2266103 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -515,7 +515,6 @@
   // ChildThread
   bool OnControlMessageReceived(const IPC::Message& msg) override;
   void OnProcessBackgrounded(bool backgrounded) override;
-  void OnProcessResume() override;
   void OnProcessPurgeAndSuspend() override;
   void RecordAction(const base::UserMetricsAction& action) override;
   void RecordComputedAction(const std::string& action) override;
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 7f50fda..ea65b56 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -515,6 +515,10 @@
         ['mac', ('amd', 0x679e)], bug=483282)
 
     # Mac Multi-vendor failures.
+    self.Fail('deqp/functional/gles3/fborender/recreate_color_02.html',
+        ['mac', 'nvidia', 'amd'], bug=679682)
+    self.Fail('deqp/functional/gles3/fborender/resize_01.html',
+        ['mac', 'nvidia', 'amd'], bug=679682)
     self.Fail('deqp/functional/gles3/fragmentoutput/basic.float.html',
         ['mac', 'nvidia', 'amd'], bug=679684)
     self.Fail('deqp/functional/gles3/fragmentoutput/array.float.html',
diff --git a/device/sensors/ambient_light_mac.cc b/device/sensors/ambient_light_mac.cc
index 9d2417d4..c9f36f5d 100644
--- a/device/sensors/ambient_light_mac.cc
+++ b/device/sensors/ambient_light_mac.cc
@@ -33,8 +33,7 @@
     IOServiceClose(io_connection_);
 }
 
-AmbientLightSensor::AmbientLightSensor() : io_connection_(IO_OBJECT_NULL) {
-}
+AmbientLightSensor::AmbientLightSensor() : io_connection_(IO_OBJECT_NULL) {}
 
 bool AmbientLightSensor::Init() {
   // Tested and verified by riju that the following call works on
diff --git a/device/sensors/android/java/src/org/chromium/device/sensors/DeviceSensors.java b/device/sensors/android/java/src/org/chromium/device/sensors/DeviceSensors.java
index 90f59f8..1b3ef89 100644
--- a/device/sensors/android/java/src/org/chromium/device/sensors/DeviceSensors.java
+++ b/device/sensors/android/java/src/org/chromium/device/sensors/DeviceSensors.java
@@ -28,8 +28,7 @@
  */
 @JNINamespace("device")
 class DeviceSensors implements SensorEventListener {
-
-    private static final String TAG = "cr.DeviceSensors";
+    private static final String TAG = "DeviceSensors";
 
     // Matches kEnableExperimentalWebPlatformFeatures.
     private static final String EXPERIMENTAL_WEB_PLAFTORM_FEATURES =
@@ -71,22 +70,18 @@
     private static DeviceSensors sSingleton;
     private static Object sSingletonLock = new Object();
 
-    static final Set<Integer> DEVICE_ORIENTATION_SENSORS_A = CollectionUtil.newHashSet(
-            Sensor.TYPE_GAME_ROTATION_VECTOR);
-    static final Set<Integer> DEVICE_ORIENTATION_SENSORS_B = CollectionUtil.newHashSet(
-            Sensor.TYPE_ROTATION_VECTOR);
+    static final Set<Integer> DEVICE_ORIENTATION_SENSORS_A =
+            CollectionUtil.newHashSet(Sensor.TYPE_GAME_ROTATION_VECTOR);
+    static final Set<Integer> DEVICE_ORIENTATION_SENSORS_B =
+            CollectionUtil.newHashSet(Sensor.TYPE_ROTATION_VECTOR);
     // Option C backup sensors are used when options A and B are not available.
-    static final Set<Integer> DEVICE_ORIENTATION_SENSORS_C = CollectionUtil.newHashSet(
-            Sensor.TYPE_ACCELEROMETER,
-            Sensor.TYPE_MAGNETIC_FIELD);
-    static final Set<Integer> DEVICE_ORIENTATION_ABSOLUTE_SENSORS = CollectionUtil.newHashSet(
-            Sensor.TYPE_ROTATION_VECTOR);
+    static final Set<Integer> DEVICE_ORIENTATION_SENSORS_C =
+            CollectionUtil.newHashSet(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAGNETIC_FIELD);
+    static final Set<Integer> DEVICE_ORIENTATION_ABSOLUTE_SENSORS =
+            CollectionUtil.newHashSet(Sensor.TYPE_ROTATION_VECTOR);
     static final Set<Integer> DEVICE_MOTION_SENSORS = CollectionUtil.newHashSet(
-            Sensor.TYPE_ACCELEROMETER,
-            Sensor.TYPE_LINEAR_ACCELERATION,
-            Sensor.TYPE_GYROSCOPE);
-    static final Set<Integer> DEVICE_LIGHT_SENSORS = CollectionUtil.newHashSet(
-            Sensor.TYPE_LIGHT);
+            Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_LINEAR_ACCELERATION, Sensor.TYPE_GYROSCOPE);
+    static final Set<Integer> DEVICE_LIGHT_SENSORS = CollectionUtil.newHashSet(Sensor.TYPE_LIGHT);
 
     @VisibleForTesting
     final Set<Integer> mActiveSensors = new HashSet<Integer>();
@@ -103,8 +98,7 @@
         mAppContext = context.getApplicationContext();
 
         mOrientationSensorSets = CollectionUtil.newArrayList(DEVICE_ORIENTATION_SENSORS_A,
-                                                             DEVICE_ORIENTATION_SENSORS_B,
-                                                             DEVICE_ORIENTATION_SENSORS_C);
+                DEVICE_ORIENTATION_SENSORS_B, DEVICE_ORIENTATION_SENSORS_C);
     }
 
     // For orientation we use a 3-way fallback approach where up to 3 different sets of sensors
@@ -160,8 +154,8 @@
                     break;
                 case ConsumerType.ORIENTATION_ABSOLUTE:
                     ensureRotationStructuresAllocated();
-                    success = registerSensors(DEVICE_ORIENTATION_ABSOLUTE_SENSORS,
-                            rateInMicroseconds, true);
+                    success = registerSensors(
+                            DEVICE_ORIENTATION_ABSOLUTE_SENSORS, rateInMicroseconds, true);
                     break;
                 case ConsumerType.MOTION:
                     // note: device motion spec does not require all sensors to be available
@@ -204,7 +198,7 @@
             return OrientationSensorType.ACCELEROMETER_MAGNETIC;
         }
 
-        assert false;  // should never happen
+        assert false; // should never happen
         return OrientationSensorType.NOT_AVAILABLE;
     }
 
@@ -283,8 +277,8 @@
             case Sensor.TYPE_ROTATION_VECTOR:
                 if (mDeviceOrientationAbsoluteIsActive) {
                     convertRotationVectorToAngles(values, mRotationAngles);
-                    gotOrientationAbsolute(mRotationAngles[0], mRotationAngles[1],
-                            mRotationAngles[2]);
+                    gotOrientationAbsolute(
+                            mRotationAngles[0], mRotationAngles[1], mRotationAngles[2]);
                 }
                 if (mDeviceOrientationIsActive
                         && mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_B) {
@@ -306,8 +300,8 @@
                     if (mMagneticFieldVector == null) {
                         mMagneticFieldVector = new float[3];
                     }
-                    System.arraycopy(values, 0, mMagneticFieldVector, 0,
-                            mMagneticFieldVector.length);
+                    System.arraycopy(
+                            values, 0, mMagneticFieldVector, 0, mMagneticFieldVector.length);
                 }
                 break;
             case Sensor.TYPE_LIGHT:
@@ -416,8 +410,8 @@
             // For the purposes of this class the first 4 values of the
             // rotation vector are sufficient (see crbug.com/335298 for details).
             System.arraycopy(rotationVector, 0, mTruncatedRotationVector, 0, 4);
-            SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix,
-                    mTruncatedRotationVector);
+            SensorManager.getRotationMatrixFromVector(
+                    mDeviceRotationMatrix, mTruncatedRotationVector);
         } else {
             SensorManager.getRotationMatrixFromVector(mDeviceRotationMatrix, rotationVector);
         }
@@ -436,9 +430,8 @@
         }
         computeDeviceOrientationFromRotationMatrix(mDeviceRotationMatrix, mRotationAngles);
 
-        gotOrientation(Math.toDegrees(mRotationAngles[0]),
-                       Math.toDegrees(mRotationAngles[1]),
-                       Math.toDegrees(mRotationAngles[2]));
+        gotOrientation(Math.toDegrees(mRotationAngles[0]), Math.toDegrees(mRotationAngles[1]),
+                Math.toDegrees(mRotationAngles[2]));
     }
 
     private SensorManagerProxy getSensorManagerProxy() {
@@ -465,8 +458,8 @@
         switch (eventType) {
             case ConsumerType.ORIENTATION:
                 mDeviceOrientationIsActive = active;
-                mDeviceOrientationIsActiveWithBackupSensors = active
-                        && (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C);
+                mDeviceOrientationIsActiveWithBackupSensors =
+                        active && (mDeviceOrientationSensors == DEVICE_ORIENTATION_SENSORS_C);
                 return;
             case ConsumerType.ORIENTATION_ABSOLUTE:
                 mDeviceOrientationAbsoluteIsActive = active;
@@ -499,8 +492,8 @@
      *                            activated. When false the method return true if at least one
      *                            sensor in sensorTypes could be activated.
      */
-    private boolean registerSensors(Set<Integer> sensorTypes, int rateInMicroseconds,
-            boolean failOnMissingSensor) {
+    private boolean registerSensors(
+            Set<Integer> sensorTypes, int rateInMicroseconds, boolean failOnMissingSensor) {
         Set<Integer> sensorsToActivate = new HashSet<Integer>(sensorTypes);
         sensorsToActivate.removeAll(mActiveSensors);
         if (sensorsToActivate.isEmpty()) return true;
@@ -594,7 +587,7 @@
             if (mHandler == null) {
                 HandlerThread thread = new HandlerThread("DeviceMotionAndOrientation");
                 thread.start();
-                mHandler = new Handler(thread.getLooper());  // blocks on thread start
+                mHandler = new Handler(thread.getLooper()); // blocks on thread start
             }
             return mHandler;
         }
@@ -619,50 +612,43 @@
      * Orientation of the device with respect to its reference frame.
      */
     private native void nativeGotOrientation(
-            long nativeSensorManagerAndroid,
-            double alpha, double beta, double gamma);
+            long nativeSensorManagerAndroid, double alpha, double beta, double gamma);
 
     /**
      * Absolute orientation of the device with respect to its reference frame.
      */
     private native void nativeGotOrientationAbsolute(
-            long nativeSensorManagerAndroid,
-            double alpha, double beta, double gamma);
+            long nativeSensorManagerAndroid, double alpha, double beta, double gamma);
 
     /**
      * Linear acceleration without gravity of the device with respect to its body frame.
      */
     private native void nativeGotAcceleration(
-            long nativeSensorManagerAndroid,
-            double x, double y, double z);
+            long nativeSensorManagerAndroid, double x, double y, double z);
 
     /**
      * Acceleration including gravity of the device with respect to its body frame.
      */
     private native void nativeGotAccelerationIncludingGravity(
-            long nativeSensorManagerAndroid,
-            double x, double y, double z);
+            long nativeSensorManagerAndroid, double x, double y, double z);
 
     /**
      * Rotation rate of the device with respect to its body frame.
      */
     private native void nativeGotRotationRate(
-            long nativeSensorManagerAndroid,
-            double alpha, double beta, double gamma);
+            long nativeSensorManagerAndroid, double alpha, double beta, double gamma);
 
     /**
      * Device Light value from Ambient Light sensors.
      */
-    private native void nativeGotLight(
-            long nativeSensorManagerAndroid,
-            double value);
+    private native void nativeGotLight(long nativeSensorManagerAndroid, double value);
 
     /**
      * Need the an interface for SensorManager for testing.
      */
     interface SensorManagerProxy {
-        public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
-                Handler handler);
+        public boolean registerListener(
+                SensorEventListener listener, int sensorType, int rate, Handler handler);
         public void unregisterListener(SensorEventListener listener, int sensorType);
     }
 
@@ -674,8 +660,8 @@
         }
 
         @Override
-        public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
-                Handler handler) {
+        public boolean registerListener(
+                SensorEventListener listener, int sensorType, int rate, Handler handler) {
             List<Sensor> sensors = mSensorManager.getSensorList(sensorType);
             if (sensors.isEmpty()) {
                 return false;
@@ -699,5 +685,4 @@
             }
         }
     }
-
 }
diff --git a/device/sensors/android/javatests/src/org/chromium/device/sensors/DeviceSensorsTest.java b/device/sensors/android/javatests/src/org/chromium/device/sensors/DeviceSensorsTest.java
index 988f092..faf4137 100644
--- a/device/sensors/android/javatests/src/org/chromium/device/sensors/DeviceSensorsTest.java
+++ b/device/sensors/android/javatests/src/org/chromium/device/sensors/DeviceSensorsTest.java
@@ -19,7 +19,6 @@
  * Test suite for DeviceSensors.
  */
 public class DeviceSensorsTest extends AndroidTestCase {
-
     private DeviceSensorsForTests mDeviceSensors;
     private MockSensorManager mMockSensorManager;
 
@@ -37,14 +36,12 @@
 
         assertTrue(start);
         assertTrue("should contain all motion sensors",
-                mDeviceSensors.mActiveSensors.containsAll(
-                        DeviceSensors.DEVICE_MOTION_SENSORS));
+                mDeviceSensors.mActiveSensors.containsAll(DeviceSensors.DEVICE_MOTION_SENSORS));
         assertTrue(mDeviceSensors.mDeviceMotionIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
         assertFalse(mDeviceSensors.mDeviceLightIsActive);
 
-        assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(),
-                mMockSensorManager.mNumRegistered);
+        assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(), mMockSensorManager.mNumRegistered);
         assertEquals(0, mMockSensorManager.mNumUnRegistered);
         assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(),
                 mDeviceSensors.getNumberActiveDeviceMotionSensors());
@@ -126,8 +123,8 @@
         assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActiveWithBackupSensors);
         assertTrue(mDeviceSensors.mActiveSensors.isEmpty());
-        assertEquals(OrientationSensorType.NOT_AVAILABLE,
-                mDeviceSensors.getOrientationSensorTypeUsed());
+        assertEquals(
+                OrientationSensorType.NOT_AVAILABLE, mDeviceSensors.getOrientationSensorTypeUsed());
 
         assertEquals(0, mockSensorManager.mNumRegistered);
         assertEquals(0, mockSensorManager.mNumUnRegistered);
@@ -141,8 +138,7 @@
         assertTrue(startOrientation);
         assertTrue(startMotion);
         assertTrue("should contain all motion sensors",
-                mDeviceSensors.mActiveSensors.containsAll(
-                        DeviceSensors.DEVICE_MOTION_SENSORS));
+                mDeviceSensors.mActiveSensors.containsAll(DeviceSensors.DEVICE_MOTION_SENSORS));
         assertTrue("should contain all orientation sensors",
                 mDeviceSensors.mActiveSensors.containsAll(
                         DeviceSensors.DEVICE_ORIENTATION_SENSORS_A));
@@ -184,8 +180,7 @@
         mDeviceSensors.start(0, ConsumerType.ORIENTATION_ABSOLUTE, 100);
         mDeviceSensors.stop(ConsumerType.ORIENTATION_ABSOLUTE);
 
-        assertTrue("should contain no sensors",
-                mDeviceSensors.mActiveSensors.isEmpty());
+        assertTrue("should contain no sensors", mDeviceSensors.mActiveSensors.isEmpty());
         assertFalse(mDeviceSensors.mDeviceMotionIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActiveWithBackupSensors);
@@ -197,8 +192,8 @@
     @SmallTest
     public void testRegisterSensorsDeviceOrientationAndOrientationAbsolute() {
         boolean startOrientation = mDeviceSensors.start(0, ConsumerType.ORIENTATION, 100);
-        boolean startOrientationAbsolute = mDeviceSensors.start(0,
-                ConsumerType.ORIENTATION_ABSOLUTE, 100);
+        boolean startOrientationAbsolute =
+                mDeviceSensors.start(0, ConsumerType.ORIENTATION_ABSOLUTE, 100);
 
         assertTrue(startOrientation);
         assertTrue(startOrientationAbsolute);
@@ -230,8 +225,7 @@
         assertFalse(mDeviceSensors.mDeviceMotionIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
 
-        assertEquals(DeviceSensors.DEVICE_LIGHT_SENSORS.size(),
-                mMockSensorManager.mNumRegistered);
+        assertEquals(DeviceSensors.DEVICE_LIGHT_SENSORS.size(), mMockSensorManager.mNumRegistered);
         assertEquals(0, mMockSensorManager.mNumUnRegistered);
     }
 
@@ -240,13 +234,12 @@
         mDeviceSensors.start(0, ConsumerType.MOTION, 100);
         mDeviceSensors.stop(ConsumerType.MOTION);
 
-        assertTrue("should contain no sensors",
-                mDeviceSensors.mActiveSensors.isEmpty());
+        assertTrue("should contain no sensors", mDeviceSensors.mActiveSensors.isEmpty());
         assertFalse(mDeviceSensors.mDeviceMotionIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
         assertFalse(mDeviceSensors.mDeviceLightIsActive);
-        assertEquals(DeviceSensors.DEVICE_MOTION_SENSORS.size(),
-                mMockSensorManager.mNumUnRegistered);
+        assertEquals(
+                DeviceSensors.DEVICE_MOTION_SENSORS.size(), mMockSensorManager.mNumUnRegistered);
         assertEquals(0, mDeviceSensors.getNumberActiveDeviceMotionSensors());
     }
 
@@ -255,8 +248,7 @@
         mDeviceSensors.start(0, ConsumerType.ORIENTATION, 100);
         mDeviceSensors.stop(ConsumerType.ORIENTATION);
 
-        assertTrue("should contain no sensors",
-                mDeviceSensors.mActiveSensors.isEmpty());
+        assertTrue("should contain no sensors", mDeviceSensors.mActiveSensors.isEmpty());
         assertFalse(mDeviceSensors.mDeviceMotionIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActive);
         assertFalse(mDeviceSensors.mDeviceOrientationIsActiveWithBackupSensors);
@@ -316,8 +308,8 @@
      * Helper method to trigger an orientation change using the given sensorType.
      */
     private void changeOrientation(int sensorType, boolean absolute, String expectedChange) {
-        boolean startOrientation = mDeviceSensors.start(0,
-                absolute ? ConsumerType.ORIENTATION_ABSOLUTE : ConsumerType.ORIENTATION, 100);
+        boolean startOrientation = mDeviceSensors.start(
+                0, absolute ? ConsumerType.ORIENTATION_ABSOLUTE : ConsumerType.ORIENTATION, 100);
 
         assertTrue(startOrientation);
         assertTrue(absolute ? mDeviceSensors.mDeviceOrientationAbsoluteIsActive
@@ -345,8 +337,8 @@
 
     @SmallTest
     public void testSensorChangedGotOrientationAbsoluteViaRotationVector() {
-        changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */,
-                "gotOrientationAbsolute");
+        changeOrientation(
+                Sensor.TYPE_ROTATION_VECTOR, true /* absolute */, "gotOrientationAbsolute");
     }
 
     @SmallTest
@@ -357,8 +349,8 @@
     @SmallTest
     public void testSensorChangedGotOrientationAndOrientationAbsolute() {
         changeOrientation(Sensor.TYPE_GAME_ROTATION_VECTOR, false /* absolute */, "gotOrientation");
-        changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */,
-                "gotOrientation" + "gotOrientationAbsolute");
+        changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */, "gotOrientation"
+                        + "gotOrientationAbsolute");
     }
 
     @SmallTest
@@ -368,8 +360,9 @@
         mDeviceSensors.setSensorManagerProxy(mockSensorManager);
 
         changeOrientation(Sensor.TYPE_ROTATION_VECTOR, false /* absolute */, "gotOrientation");
-        changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */,
-                "gotOrientation" + "gotOrientationAbsolute" + "gotOrientation");
+        changeOrientation(Sensor.TYPE_ROTATION_VECTOR, true /* absolute */, "gotOrientation"
+                        + "gotOrientationAbsolute"
+                        + "gotOrientation");
     }
 
     @SmallTest
@@ -420,7 +413,8 @@
 
         float[] values2 = {1, 2, 3};
         mDeviceSensors.sensorChanged(Sensor.TYPE_ACCELEROMETER, values2);
-        mDeviceSensors.verifyCalls("gotOrientation" + "gotAccelerationIncludingGravity");
+        mDeviceSensors.verifyCalls("gotOrientation"
+                + "gotAccelerationIncludingGravity");
         mDeviceSensors.verifyValues(1, 2, 3);
     }
 
@@ -466,7 +460,7 @@
     public void testOrientationAnglesFromRotationMatrixGimbalLock() {
         float[] gravity = {0, 1, 0};
         float[] magnetic = {(float) Math.sin(Math.PI / 4), 0, -(float) Math.cos(Math.PI / 4)};
-        double[] expectedAngles = {Math.PI / 4, Math.PI / 2, 0};  // favor yaw instead of roll
+        double[] expectedAngles = {Math.PI / 4, Math.PI / 2, 0}; // favor yaw instead of roll
 
         verifyOrientationAngles(gravity, magnetic, expectedAngles);
     }
@@ -503,8 +497,8 @@
      *        expectedAngles[1] rotation angle in radians around the X-axis
      *        expectedAngles[2] rotation angle in radians around the Y-axis
      */
-    private void verifyOrientationAngles(float[] gravity, float[] magnetic,
-            double[] expectedAngles) {
+    private void verifyOrientationAngles(
+            float[] gravity, float[] magnetic, double[] expectedAngles) {
         float[] r = new float[9];
         double[] values = new double[3];
         SensorManager.getRotationMatrix(r, null, gravity, magnetic);
@@ -515,13 +509,11 @@
         for (int i = 0; i < expectedAngles.length; ++i) {
             assertEquals(expectedAngles[i], values[i], epsilon);
         }
-
     }
 
     // -- End Tests for correct Device Orientation angles.
 
     private static class DeviceSensorsForTests extends DeviceSensors {
-
         private double mValue1 = 0;
         private double mValue2 = 0;
         private double mValue3 = 0;
@@ -603,15 +595,13 @@
     }
 
     private static class MockSensorManager implements DeviceSensors.SensorManagerProxy {
-
         private int mNumRegistered = 0;
         private int mNumUnRegistered = 0;
         private boolean mRotationVectorAvailable = true;
         private boolean mGameRotationVectorAvailable = true;
         private boolean mAccelerometerAvailable = true;
 
-        private MockSensorManager() {
-        }
+        private MockSensorManager() {}
 
         public void setGameRotationVectorAvailable(boolean available) {
             mGameRotationVectorAvailable = available;
@@ -627,16 +617,19 @@
 
         private boolean isSensorTypeAvailable(int sensorType) {
             switch (sensorType) {
-                case Sensor.TYPE_ROTATION_VECTOR : return mRotationVectorAvailable;
-                case Sensor.TYPE_GAME_ROTATION_VECTOR : return mGameRotationVectorAvailable;
-                case Sensor.TYPE_ACCELEROMETER : return mAccelerometerAvailable;
+                case Sensor.TYPE_ROTATION_VECTOR:
+                    return mRotationVectorAvailable;
+                case Sensor.TYPE_GAME_ROTATION_VECTOR:
+                    return mGameRotationVectorAvailable;
+                case Sensor.TYPE_ACCELEROMETER:
+                    return mAccelerometerAvailable;
             }
             return true;
         }
 
         @Override
-        public boolean registerListener(SensorEventListener listener, int sensorType, int rate,
-                Handler handler) {
+        public boolean registerListener(
+                SensorEventListener listener, int sensorType, int rate, Handler handler) {
             if (isSensorTypeAvailable(sensorType)) {
                 mNumRegistered++;
                 return true;
diff --git a/device/sensors/data_fetcher_shared_memory.h b/device/sensors/data_fetcher_shared_memory.h
index 8ad3074..e1e22e7 100644
--- a/device/sensors/data_fetcher_shared_memory.h
+++ b/device/sensors/data_fetcher_shared_memory.h
@@ -32,7 +32,6 @@
 
 class DEVICE_SENSOR_EXPORT DataFetcherSharedMemory
     : public DataFetcherSharedMemoryBase {
-
  public:
   DataFetcherSharedMemory();
   ~DataFetcherSharedMemory() override;
@@ -70,8 +69,9 @@
 
   FetcherType GetType() const override;
 
-  bool RegisterForSensor(REFSENSOR_TYPE_ID sensor_type, ISensor** sensor,
-      scoped_refptr<SensorEventSink> event_sink);
+  bool RegisterForSensor(REFSENSOR_TYPE_ID sensor_type,
+                         ISensor** sensor,
+                         scoped_refptr<SensorEventSink> event_sink);
   void DisableSensors(ConsumerType consumer_type);
   void SetBufferAvailableState(ConsumerType consumer_type, bool enabled);
 
diff --git a/device/sensors/data_fetcher_shared_memory_android.cc b/device/sensors/data_fetcher_shared_memory_android.cc
index d86b24a..5dec86a 100644
--- a/device/sensors/data_fetcher_shared_memory_android.cc
+++ b/device/sensors/data_fetcher_shared_memory_android.cc
@@ -12,11 +12,9 @@
 
 namespace device {
 
-DataFetcherSharedMemory::DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::DataFetcherSharedMemory() {}
 
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {}
 
 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
   DCHECK(buffer);
@@ -31,8 +29,8 @@
           static_cast<DeviceOrientationHardwareBuffer*>(buffer));
       return true;
     case CONSUMER_TYPE_ORIENTATION_ABSOLUTE:
-      SensorManagerAndroid::GetInstance()->
-          StartFetchingDeviceOrientationAbsoluteData(
+      SensorManagerAndroid::GetInstance()
+          ->StartFetchingDeviceOrientationAbsoluteData(
               static_cast<DeviceOrientationHardwareBuffer*>(buffer));
       return true;
     case CONSUMER_TYPE_LIGHT:
diff --git a/device/sensors/data_fetcher_shared_memory_base.cc b/device/sensors/data_fetcher_shared_memory_base.cc
index 84dde1c..21a72f1f 100644
--- a/device/sensors/data_fetcher_shared_memory_base.cc
+++ b/device/sensors/data_fetcher_shared_memory_base.cc
@@ -64,17 +64,15 @@
 // --- PollingThread methods
 
 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
-    const char* name, DataFetcherSharedMemoryBase* fetcher)
-    : base::Thread(name),
-      consumers_bitmask_(0),
-      fetcher_(fetcher) {
-}
+    const char* name,
+    DataFetcherSharedMemoryBase* fetcher)
+    : base::Thread(name), consumers_bitmask_(0), fetcher_(fetcher) {}
 
-DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
-}
+DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {}
 
 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
-    ConsumerType consumer_type, void* buffer) {
+    ConsumerType consumer_type,
+    void* buffer) {
   DCHECK(fetcher_);
   if (!fetcher_->Start(consumer_type, buffer))
     return;
@@ -83,9 +81,8 @@
 
   if (!timer_ && fetcher_->GetType() == FETCHER_TYPE_POLLING_CALLBACK) {
     timer_.reset(new base::RepeatingTimer());
-    timer_->Start(FROM_HERE,
-                  fetcher_->GetInterval(),
-                  this, &PollingThread::DoPoll);
+    timer_->Start(FROM_HERE, fetcher_->GetInterval(), this,
+                  &PollingThread::DoPoll);
   }
 }
 
@@ -110,8 +107,7 @@
 // --- end of PollingThread methods
 
 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
-    : started_consumers_(0) {
-}
+    : started_consumers_(0) {}
 
 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
   DCHECK_EQ(0u, started_consumers_);
@@ -204,8 +200,8 @@
   NOTIMPLEMENTED();
 }
 
-DataFetcherSharedMemoryBase::FetcherType
-DataFetcherSharedMemoryBase::GetType() const {
+DataFetcherSharedMemoryBase::FetcherType DataFetcherSharedMemoryBase::GetType()
+    const {
   return FETCHER_TYPE_DEFAULT;
 }
 
diff --git a/device/sensors/data_fetcher_shared_memory_base_unittest.cc b/device/sensors/data_fetcher_shared_memory_base_unittest.cc
index a393f20d..910f8bab 100644
--- a/device/sensors/data_fetcher_shared_memory_base_unittest.cc
+++ b/device/sensors/data_fetcher_shared_memory_base_unittest.cc
@@ -118,9 +118,7 @@
 
   DeviceLightHardwareBuffer* GetLightBuffer() const { return light_buffer_; }
 
-  DeviceMotionHardwareBuffer* GetMotionBuffer() const {
-    return motion_buffer_;
-  }
+  DeviceMotionHardwareBuffer* GetMotionBuffer() const { return motion_buffer_; }
 
   DeviceOrientationHardwareBuffer* GetOrientationBuffer() const {
     return orientation_buffer_;
@@ -213,19 +211,23 @@
     Init(consumer_type, buffer);
     switch (consumer_type) {
       case CONSUMER_TYPE_MOTION:
-        if (update_) UpdateMotion();
+        if (update_)
+          UpdateMotion();
         start_motion_.Signal();
         break;
       case CONSUMER_TYPE_ORIENTATION:
-        if (update_) UpdateOrientation();
+        if (update_)
+          UpdateOrientation();
         start_orientation_.Signal();
         break;
       case CONSUMER_TYPE_ORIENTATION_ABSOLUTE:
-        if (update_) UpdateOrientationAbsolute();
+        if (update_)
+          UpdateOrientationAbsolute();
         start_orientation_absolute_.Signal();
         break;
       case CONSUMER_TYPE_LIGHT:
-        if (update_) UpdateLight();
+        if (update_)
+          UpdateLight();
         start_light_.Signal();
         break;
       default:
@@ -256,7 +258,7 @@
 
   void Fetch(unsigned consumer_bitmask) override {
     FAIL() << "fetch should not be called, "
-        << "because this is a non-polling fetcher";
+           << "because this is a non-polling fetcher";
   }
 
   FetcherType GetType() const override { return FakeDataFetcher::GetType(); }
@@ -270,7 +272,7 @@
 
 class FakePollingDataFetcher : public FakeDataFetcher {
  public:
-  FakePollingDataFetcher() { }
+  FakePollingDataFetcher() {}
   ~FakePollingDataFetcher() override {}
 
   bool Start(ConsumerType consumer_type, void* buffer) override {
@@ -346,7 +348,7 @@
 
 class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
  public:
-  FakeZeroDelayPollingDataFetcher() { }
+  FakeZeroDelayPollingDataFetcher() {}
   ~FakeZeroDelayPollingDataFetcher() override {}
 
   bool Start(ConsumerType consumer_type, void* buffer) override {
@@ -410,11 +412,10 @@
   DISALLOW_COPY_AND_ASSIGN(FakeZeroDelayPollingDataFetcher);
 };
 
-
 TEST(DataFetcherSharedMemoryBaseTest, DoesStartMotion) {
   FakeNonPollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
   EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
@@ -429,10 +430,10 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientation) {
   FakeNonPollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_ORIENTATION));
+  EXPECT_TRUE(
+      fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_ORIENTATION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
 
   EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
@@ -444,7 +445,7 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientationAbsolute) {
   FakeNonPollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
   EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
       CONSUMER_TYPE_ORIENTATION_ABSOLUTE));
@@ -474,7 +475,7 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) {
   FakePollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
   EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
@@ -490,10 +491,10 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientation) {
   FakePollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_ORIENTATION));
+  EXPECT_TRUE(
+      fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_ORIENTATION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
   fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_ORIENTATION);
 
@@ -506,7 +507,7 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientationAbsolute) {
   FakePollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
   EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
       CONSUMER_TYPE_ORIENTATION_ABSOLUTE));
@@ -538,16 +539,15 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
   FakePollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_ORIENTATION));
+  EXPECT_TRUE(
+      fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_ORIENTATION));
   mojo::ScopedSharedBufferHandle handle_orientation =
       fake_data_fetcher.GetSharedMemoryHandle(CONSUMER_TYPE_ORIENTATION);
   EXPECT_TRUE(handle_orientation.is_valid());
 
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_MOTION));
+  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
   mojo::ScopedSharedBufferHandle handle_motion =
       fake_data_fetcher.GetSharedMemoryHandle(CONSUMER_TYPE_MOTION);
   EXPECT_TRUE(handle_motion.is_valid());
@@ -571,10 +571,10 @@
 TEST(DataFetcherSharedMemoryBaseTest, DoesNotPollZeroDelay) {
   FakeZeroDelayPollingDataFetcher fake_data_fetcher;
   EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_SEPARATE_THREAD,
-      fake_data_fetcher.GetType());
+            fake_data_fetcher.GetType());
 
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_ORIENTATION));
+  EXPECT_TRUE(
+      fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_ORIENTATION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
 
   EXPECT_FALSE(fake_data_fetcher.IsPollingTimerRunningForTesting());
@@ -586,8 +586,8 @@
 
 TEST(DataFetcherSharedMemoryBaseTest, DoesClearBufferOnStart) {
   FakeNonPollingDataFetcher fake_data_fetcher;
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_ORIENTATION));
+  EXPECT_TRUE(
+      fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_ORIENTATION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
   EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
   fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
@@ -596,8 +596,8 @@
   // Restart orientation without updating the memory buffer and check that
   // it has been cleared to its initial state.
   fake_data_fetcher.set_update(false);
-  EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(
-      CONSUMER_TYPE_ORIENTATION));
+  EXPECT_TRUE(
+      fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_ORIENTATION));
   fake_data_fetcher.WaitForStart(CONSUMER_TYPE_ORIENTATION);
   EXPECT_EQ(0, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
   fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
diff --git a/device/sensors/data_fetcher_shared_memory_chromeos.cc b/device/sensors/data_fetcher_shared_memory_chromeos.cc
index d9d3a24..fc57ef1 100644
--- a/device/sensors/data_fetcher_shared_memory_chromeos.cc
+++ b/device/sensors/data_fetcher_shared_memory_chromeos.cc
@@ -8,11 +8,9 @@
 
 namespace device {
 
-DataFetcherSharedMemory::DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::DataFetcherSharedMemory() {}
 
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {}
 
 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
   DCHECK(buffer);
diff --git a/device/sensors/data_fetcher_shared_memory_default.cc b/device/sensors/data_fetcher_shared_memory_default.cc
index d6dd665..354879f 100644
--- a/device/sensors/data_fetcher_shared_memory_default.cc
+++ b/device/sensors/data_fetcher_shared_memory_default.cc
@@ -9,8 +9,7 @@
 
 namespace {
 
-bool SetMotionBuffer(device::DeviceMotionHardwareBuffer* buffer,
-    bool enabled) {
+bool SetMotionBuffer(device::DeviceMotionHardwareBuffer* buffer, bool enabled) {
   if (!buffer)
     return false;
   buffer->seqlock.WriteBegin();
@@ -19,8 +18,8 @@
   return true;
 }
 
-bool SetOrientationBuffer(
-    device::DeviceOrientationHardwareBuffer* buffer, bool enabled) {
+bool SetOrientationBuffer(device::DeviceOrientationHardwareBuffer* buffer,
+                          bool enabled) {
   if (!buffer)
     return false;
   buffer->seqlock.WriteBegin();
@@ -29,8 +28,7 @@
   return true;
 }
 
-bool SetLightBuffer(device::DeviceLightHardwareBuffer* buffer,
-                           double lux) {
+bool SetLightBuffer(device::DeviceLightHardwareBuffer* buffer, double lux) {
   if (!buffer)
     return false;
   buffer->seqlock.WriteBegin();
@@ -45,8 +43,7 @@
 
 DataFetcherSharedMemory::DataFetcherSharedMemory() {}
 
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {}
 
 bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
   DCHECK(buffer);
@@ -60,7 +57,7 @@
       orientation_buffer_ =
           static_cast<DeviceOrientationHardwareBuffer*>(buffer);
       UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationDefaultAvailable",
-          false);
+                            false);
       return SetOrientationBuffer(orientation_buffer_, true);
     case CONSUMER_TYPE_ORIENTATION_ABSOLUTE:
       orientation_absolute_buffer_ =
diff --git a/device/sensors/data_fetcher_shared_memory_mac.cc b/device/sensors/data_fetcher_shared_memory_mac.cc
index 1826068b..3d89ebfe 100644
--- a/device/sensors/data_fetcher_shared_memory_mac.cc
+++ b/device/sensors/data_fetcher_shared_memory_mac.cc
@@ -97,9 +97,9 @@
 
   // At this point, DCHECKing is paranoia. Never hurts.
   DCHECK_GE(beta, -180.0);
-  DCHECK_LT(beta,  180.0);
+  DCHECK_LT(beta, 180.0);
   DCHECK_GE(gamma, -90.0);
-  DCHECK_LT(gamma,  90.0);
+  DCHECK_LT(gamma, 90.0);
 
   buffer->seqlock.WriteBegin();
   buffer->data.beta = beta;
@@ -110,11 +110,9 @@
   buffer->seqlock.WriteEnd();
 }
 
-DataFetcherSharedMemory::DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::DataFetcherSharedMemory() {}
 
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {}
 
 void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) {
   DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread());
@@ -147,7 +145,7 @@
 
       motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
       UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable",
-          sudden_motion_sensor_available);
+                            sudden_motion_sensor_available);
       if (!sudden_motion_sensor_available) {
         // No motion sensor available, fire an all-null event.
         motion_buffer_->seqlock.WriteBegin();
@@ -165,7 +163,7 @@
       orientation_buffer_ =
           static_cast<DeviceOrientationHardwareBuffer*>(buffer);
       UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable",
-          sudden_motion_sensor_available);
+                            sudden_motion_sensor_available);
       if (sudden_motion_sensor_available) {
         // On Mac we cannot provide absolute orientation.
         orientation_buffer_->seqlock.WriteBegin();
diff --git a/device/sensors/data_fetcher_shared_memory_win.cc b/device/sensors/data_fetcher_shared_memory_win.cc
index 38e81dbe..4c3c09e 100644
--- a/device/sensors/data_fetcher_shared_memory_win.cc
+++ b/device/sensors/data_fetcher_shared_memory_win.cc
@@ -31,19 +31,16 @@
 namespace device {
 
 class DataFetcherSharedMemory::SensorEventSink
-    : public ISensorEvents, public base::win::IUnknownImpl {
+    : public ISensorEvents,
+      public base::win::IUnknownImpl {
  public:
   SensorEventSink() {}
   ~SensorEventSink() override {}
 
   // IUnknown interface
-  ULONG STDMETHODCALLTYPE AddRef() override {
-    return IUnknownImpl::AddRef();
-  }
+  ULONG STDMETHODCALLTYPE AddRef() override { return IUnknownImpl::AddRef(); }
 
-  ULONG STDMETHODCALLTYPE Release() override {
-    return IUnknownImpl::Release();
-  }
+  ULONG STDMETHODCALLTYPE Release() override { return IUnknownImpl::Release(); }
 
   STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override {
     if (riid == __uuidof(ISensorEvents)) {
@@ -61,9 +58,7 @@
     return S_OK;
   }
 
-  STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) override {
-    return S_OK;
-  }
+  STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) override { return S_OK; }
 
   STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) override {
     return S_OK;
@@ -77,11 +72,13 @@
   }
 
  protected:
-  virtual bool UpdateSharedMemoryBuffer(
-      ISensor* sensor, ISensorDataReport* new_data) = 0;
+  virtual bool UpdateSharedMemoryBuffer(ISensor* sensor,
+                                        ISensorDataReport* new_data) = 0;
 
-  void GetSensorValue(REFPROPERTYKEY property, ISensorDataReport* new_data,
-      double* value, bool* has_value) {
+  void GetSensorValue(REFPROPERTYKEY property,
+                      ISensorDataReport* new_data,
+                      double* value,
+                      bool* has_value) {
     PROPVARIANT variant_value = {};
     if (SUCCEEDED(new_data->GetSensorValue(property, &variant_value))) {
       if (variant_value.vt == VT_R8)
@@ -96,7 +93,6 @@
   }
 
  private:
-
   DISALLOW_COPY_AND_ASSIGN(SensorEventSink);
 };
 
@@ -104,21 +100,21 @@
     : public DataFetcherSharedMemory::SensorEventSink {
  public:
   explicit SensorEventSinkOrientation(
-      DeviceOrientationHardwareBuffer* const buffer) : buffer_(buffer) {}
+      DeviceOrientationHardwareBuffer* const buffer)
+      : buffer_(buffer) {}
   ~SensorEventSinkOrientation() override {}
 
  protected:
-  bool UpdateSharedMemoryBuffer(
-      ISensor* sensor, ISensorDataReport* new_data) override {
+  bool UpdateSharedMemoryBuffer(ISensor* sensor,
+                                ISensorDataReport* new_data) override {
     double alpha, beta, gamma;
     bool has_alpha, has_beta, has_gamma;
 
-    GetSensorValue(SENSOR_DATA_TYPE_TILT_X_DEGREES, new_data, &beta,
-        &has_beta);
+    GetSensorValue(SENSOR_DATA_TYPE_TILT_X_DEGREES, new_data, &beta, &has_beta);
     GetSensorValue(SENSOR_DATA_TYPE_TILT_Y_DEGREES, new_data, &gamma,
-        &has_gamma);
+                   &has_gamma);
     GetSensorValue(SENSOR_DATA_TYPE_TILT_Z_DEGREES, new_data, &alpha,
-        &has_alpha);
+                   &has_alpha);
 
     if (buffer_) {
       buffer_->seqlock.WriteBegin();
@@ -150,9 +146,8 @@
   ~SensorEventSinkMotion() override {}
 
  protected:
-  bool UpdateSharedMemoryBuffer(
-      ISensor* sensor, ISensorDataReport* new_data) override {
-
+  bool UpdateSharedMemoryBuffer(ISensor* sensor,
+                                ISensorDataReport* new_data) override {
     SENSOR_TYPE_ID sensor_type = GUID_NULL;
     if (!SUCCEEDED(sensor->GetType(&sensor_type)))
       return false;
@@ -166,14 +161,14 @@
       bool has_acceleration_including_gravity_z;
 
       GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, new_data,
-          &acceleration_including_gravity_x,
-          &has_acceleration_including_gravity_x);
+                     &acceleration_including_gravity_x,
+                     &has_acceleration_including_gravity_x);
       GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, new_data,
-          &acceleration_including_gravity_y,
-          &has_acceleration_including_gravity_y);
+                     &acceleration_including_gravity_y,
+                     &has_acceleration_including_gravity_y);
       GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, new_data,
-          &acceleration_including_gravity_z,
-          &has_acceleration_including_gravity_z);
+                     &acceleration_including_gravity_z,
+                     &has_acceleration_including_gravity_z);
 
       if (buffer_) {
         buffer_->seqlock.WriteBegin();
@@ -200,11 +195,11 @@
       bool has_alpha, has_beta, has_gamma;
 
       GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND,
-          new_data, &alpha, &has_alpha);
+                     new_data, &alpha, &has_alpha);
       GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND,
-          new_data, &beta, &has_beta);
+                     new_data, &beta, &has_beta);
       GetSensorValue(SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND,
-          new_data, &gamma, &has_gamma);
+                     new_data, &gamma, &has_gamma);
 
       if (buffer_) {
         buffer_->seqlock.WriteBegin();
@@ -237,13 +232,13 @@
 
  protected:
   bool UpdateSharedMemoryBuffer(ISensor* sensor,
-                                        ISensorDataReport* new_data) override {
+                                ISensorDataReport* new_data) override {
     double lux;
     bool has_lux;
 
     GetSensorValue(SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, new_data, &lux, &has_lux);
 
-    if(!has_lux) {
+    if (!has_lux) {
       // Could not get lux value.
       return false;
     }
@@ -261,8 +256,7 @@
 
 DataFetcherSharedMemory::DataFetcherSharedMemory() {}
 
-DataFetcherSharedMemory::~DataFetcherSharedMemory() {
-}
+DataFetcherSharedMemory::~DataFetcherSharedMemory() {}
 
 DataFetcherSharedMemory::FetcherType DataFetcherSharedMemory::GetType() const {
   return FETCHER_TYPE_SEPARATE_THREAD;
@@ -272,80 +266,71 @@
   DCHECK(buffer);
 
   switch (consumer_type) {
-    case CONSUMER_TYPE_ORIENTATION:
-      {
-        orientation_buffer_ =
-            static_cast<DeviceOrientationHardwareBuffer*>(buffer);
-        scoped_refptr<SensorEventSink> sink(
-            new SensorEventSinkOrientation(orientation_buffer_));
-        bool inclinometer_available = RegisterForSensor(
-            SENSOR_TYPE_INCLINOMETER_3D, sensor_inclinometer_.Receive(), sink);
-        UMA_HISTOGRAM_BOOLEAN("InertialSensor.InclinometerWindowsAvailable",
-            inclinometer_available);
-        if (inclinometer_available)
-          return true;
-        // if no sensors are available set buffer to ready, to fire null-events.
-        SetBufferAvailableState(consumer_type, true);
+    case CONSUMER_TYPE_ORIENTATION: {
+      orientation_buffer_ =
+          static_cast<DeviceOrientationHardwareBuffer*>(buffer);
+      scoped_refptr<SensorEventSink> sink(
+          new SensorEventSinkOrientation(orientation_buffer_));
+      bool inclinometer_available = RegisterForSensor(
+          SENSOR_TYPE_INCLINOMETER_3D, sensor_inclinometer_.Receive(), sink);
+      UMA_HISTOGRAM_BOOLEAN("InertialSensor.InclinometerWindowsAvailable",
+                            inclinometer_available);
+      if (inclinometer_available)
+        return true;
+      // if no sensors are available set buffer to ready, to fire null-events.
+      SetBufferAvailableState(consumer_type, true);
+    } break;
+    case CONSUMER_TYPE_ORIENTATION_ABSOLUTE: {
+      orientation_absolute_buffer_ =
+          static_cast<DeviceOrientationHardwareBuffer*>(buffer);
+      scoped_refptr<SensorEventSink> sink(
+          new SensorEventSinkOrientation(orientation_absolute_buffer_));
+      // Currently we use the same sensor as for orientation which provides
+      // absolute angles.
+      bool inclinometer_available =
+          RegisterForSensor(SENSOR_TYPE_INCLINOMETER_3D,
+                            sensor_inclinometer_absolute_.Receive(), sink);
+      // TODO(timvolodine): consider adding UMA.
+      if (inclinometer_available)
+        return true;
+      // if no sensors are available set buffer to ready, to fire null-events.
+      SetBufferAvailableState(consumer_type, true);
+    } break;
+    case CONSUMER_TYPE_MOTION: {
+      motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
+      scoped_refptr<SensorEventSink> sink(
+          new SensorEventSinkMotion(motion_buffer_));
+      bool accelerometer_available = RegisterForSensor(
+          SENSOR_TYPE_ACCELEROMETER_3D, sensor_accelerometer_.Receive(), sink);
+      bool gyrometer_available = RegisterForSensor(
+          SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.Receive(), sink);
+      UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerWindowsAvailable",
+                            accelerometer_available);
+      UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyrometerWindowsAvailable",
+                            gyrometer_available);
+      if (accelerometer_available || gyrometer_available) {
+        motion_buffer_->seqlock.WriteBegin();
+        motion_buffer_->data.interval = GetInterval().InMilliseconds();
+        motion_buffer_->seqlock.WriteEnd();
+        return true;
       }
-      break;
-    case CONSUMER_TYPE_ORIENTATION_ABSOLUTE:
-      {
-        orientation_absolute_buffer_ =
-            static_cast<DeviceOrientationHardwareBuffer*>(buffer);
-        scoped_refptr<SensorEventSink> sink(
-            new SensorEventSinkOrientation(orientation_absolute_buffer_));
-        // Currently we use the same sensor as for orientation which provides
-        // absolute angles.
-        bool inclinometer_available = RegisterForSensor(
-            SENSOR_TYPE_INCLINOMETER_3D,
-            sensor_inclinometer_absolute_.Receive(), sink);
-        // TODO(timvolodine): consider adding UMA.
-        if (inclinometer_available)
-          return true;
-        // if no sensors are available set buffer to ready, to fire null-events.
-        SetBufferAvailableState(consumer_type, true);
+      // if no sensors are available set buffer to ready, to fire null-events.
+      SetBufferAvailableState(consumer_type, true);
+    } break;
+    case CONSUMER_TYPE_LIGHT: {
+      light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer);
+      scoped_refptr<SensorEventSink> sink(
+          new SensorEventSinkLight(light_buffer_));
+      bool sensor_light_available = RegisterForSensor(
+          SENSOR_TYPE_AMBIENT_LIGHT, sensor_light_.Receive(), sink);
+      if (sensor_light_available) {
+        SetLightBuffer(light_buffer_, -1);
+        return true;
       }
-      break;
-    case CONSUMER_TYPE_MOTION:
-      {
-        motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
-        scoped_refptr<SensorEventSink> sink(
-            new SensorEventSinkMotion(motion_buffer_));
-        bool accelerometer_available = RegisterForSensor(
-            SENSOR_TYPE_ACCELEROMETER_3D, sensor_accelerometer_.Receive(),
-            sink);
-        bool gyrometer_available = RegisterForSensor(
-            SENSOR_TYPE_GYROMETER_3D, sensor_gyrometer_.Receive(), sink);
-        UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerWindowsAvailable",
-            accelerometer_available);
-        UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyrometerWindowsAvailable",
-            gyrometer_available);
-        if (accelerometer_available || gyrometer_available) {
-          motion_buffer_->seqlock.WriteBegin();
-          motion_buffer_->data.interval = GetInterval().InMilliseconds();
-          motion_buffer_->seqlock.WriteEnd();
-          return true;
-        }
-        // if no sensors are available set buffer to ready, to fire null-events.
-        SetBufferAvailableState(consumer_type, true);
-      }
-      break;
-    case CONSUMER_TYPE_LIGHT:
-      {
-        light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer);
-        scoped_refptr<SensorEventSink> sink(
-            new SensorEventSinkLight(light_buffer_));
-        bool sensor_light_available = RegisterForSensor(
-            SENSOR_TYPE_AMBIENT_LIGHT, sensor_light_.Receive(), sink);
-        if (sensor_light_available) {
-          SetLightBuffer(light_buffer_, -1);
-          return true;
-        }
 
-        // if no sensors are available, fire an Infinity event.
-        SetLightBuffer(light_buffer_, std::numeric_limits<double>::infinity());
-      }
-      break;
+      // if no sensors are available, fire an Infinity event.
+      SetLightBuffer(light_buffer_, std::numeric_limits<double>::infinity());
+    } break;
     default:
       NOTREACHED();
   }
@@ -390,8 +375,8 @@
     return false;
 
   base::win::ScopedComPtr<ISensorCollection> sensor_collection;
-  hr = sensor_manager->GetSensorsByType(
-      sensor_type, sensor_collection.Receive());
+  hr = sensor_manager->GetSensorsByType(sensor_type,
+                                        sensor_collection.Receive());
 
   if (FAILED(hr) || !sensor_collection.get())
     return false;
@@ -408,16 +393,16 @@
   base::win::ScopedComPtr<IPortableDeviceValues> device_values;
   if (SUCCEEDED(device_values.CreateInstance(CLSID_PortableDeviceValues))) {
     if (SUCCEEDED(device_values->SetUnsignedIntegerValue(
-        SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
-        GetInterval().InMilliseconds()))) {
+            SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
+            GetInterval().InMilliseconds()))) {
       base::win::ScopedComPtr<IPortableDeviceValues> return_values;
       (*sensor)->SetProperties(device_values.get(), return_values.Receive());
     }
   }
 
   base::win::ScopedComPtr<ISensorEvents> sensor_events;
-  hr = event_sink->QueryInterface(
-      __uuidof(ISensorEvents), sensor_events.ReceiveVoid());
+  hr = event_sink->QueryInterface(__uuidof(ISensorEvents),
+                                  sensor_events.ReceiveVoid());
   if (FAILED(hr) || !sensor_events.get())
     return false;
 
@@ -429,7 +414,7 @@
 }
 
 void DataFetcherSharedMemory::DisableSensors(ConsumerType consumer_type) {
-  switch(consumer_type) {
+  switch (consumer_type) {
     case CONSUMER_TYPE_ORIENTATION:
       if (sensor_inclinometer_.get()) {
         sensor_inclinometer_->SetEventSink(nullptr);
@@ -464,8 +449,9 @@
 }
 
 void DataFetcherSharedMemory::SetBufferAvailableState(
-    ConsumerType consumer_type, bool enabled) {
-  switch(consumer_type) {
+    ConsumerType consumer_type,
+    bool enabled) {
+  switch (consumer_type) {
     case CONSUMER_TYPE_ORIENTATION:
       if (orientation_buffer_) {
         orientation_buffer_->seqlock.WriteBegin();
diff --git a/device/sensors/sensor_manager_android.cc b/device/sensors/sensor_manager_android.cc
index 0be7338..c896e1a7 100644
--- a/device/sensors/sensor_manager_android.cc
+++ b/device/sensors/sensor_manager_android.cc
@@ -27,7 +27,9 @@
 }
 
 void SetOrientation(device::DeviceOrientationHardwareBuffer* buffer,
-    double alpha, double beta, double gamma) {
+                    double alpha,
+                    double beta,
+                    double gamma) {
   buffer->seqlock.WriteBegin();
   buffer->data.alpha = alpha;
   buffer->data.hasAlpha = true;
@@ -65,8 +67,7 @@
       AttachCurrentThread(), base::android::GetApplicationContext()));
 }
 
-SensorManagerAndroid::~SensorManagerAndroid() {
-}
+SensorManagerAndroid::~SensorManagerAndroid() {}
 
 bool SensorManagerAndroid::Register(JNIEnv* env) {
   return RegisterNativesImpl(env);
@@ -95,7 +96,7 @@
     OrientationSensorType type =
         static_cast<OrientationSensorType>(GetOrientationSensorTypeUsed());
     SetOrientationBufferStatus(device_orientation_buffer_, true,
-        type != GAME_ROTATION_VECTOR);
+                               type != GAME_ROTATION_VECTOR);
     orientation_buffer_initialized_ = true;
     UpdateDeviceOrientationHistogram(type);
   }
@@ -330,8 +331,9 @@
 
 void SensorManagerAndroid::CheckMotionBufferReadyToRead() {
   if (received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] +
-      received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
-      received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
+          received_motion_data_
+              [RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] +
+          received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
       number_active_device_motion_sensors_) {
     device_motion_buffer_->seqlock.WriteBegin();
     device_motion_buffer_->data.interval =
@@ -339,13 +341,15 @@
     device_motion_buffer_->seqlock.WriteEnd();
     SetMotionBufferReadyStatus(true);
 
-    UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable",
+    UMA_HISTOGRAM_BOOLEAN(
+        "InertialSensor.AccelerometerAndroidAvailable",
         received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0);
     UMA_HISTOGRAM_BOOLEAN(
         "InertialSensor.AccelerometerIncGravityAndroidAvailable",
-        received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY]
-        > 0);
-    UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable",
+        received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] >
+            0);
+    UMA_HISTOGRAM_BOOLEAN(
+        "InertialSensor.GyroscopeAndroidAvailable",
         received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0);
   }
 }
@@ -383,7 +387,7 @@
     // If Start() was unsuccessful then set the buffer ready flag to true
     // to start firing all-null events.
     SetOrientationBufferStatus(buffer, !success /* ready */,
-        false /* absolute */);
+                               false /* absolute */);
     orientation_buffer_initialized_ = !success;
   }
 
@@ -425,7 +429,7 @@
     // If Start() was unsuccessful then set the buffer ready flag to true
     // to start firing all-null events.
     SetOrientationBufferStatus(buffer, !success /* ready */,
-        false /* absolute */);
+                               false /* absolute */);
     orientation_absolute_buffer_initialized_ = !success;
   }
 }
@@ -440,7 +444,7 @@
     base::AutoLock autolock(orientation_absolute_buffer_lock_);
     if (device_orientation_absolute_buffer_) {
       SetOrientationBufferStatus(device_orientation_absolute_buffer_, false,
-          false);
+                                 false);
       orientation_absolute_buffer_initialized_ = false;
       device_orientation_absolute_buffer_ = nullptr;
     }
diff --git a/device/sensors/sensor_manager_android_unittest.cc b/device/sensors/sensor_manager_android_unittest.cc
index b98dfb8..b584eed 100644
--- a/device/sensors/sensor_manager_android_unittest.cc
+++ b/device/sensors/sensor_manager_android_unittest.cc
@@ -52,7 +52,9 @@
 
   void VerifyOrientationBufferValues(
       const DeviceOrientationHardwareBuffer* buffer,
-      double alpha, double beta, double gamma) {
+      double alpha,
+      double beta,
+      double gamma) {
     ASSERT_TRUE(buffer->data.allAvailableSensorsAreActive);
     ASSERT_EQ(alpha, buffer->data.alpha);
     ASSERT_TRUE(buffer->data.hasAlpha);
diff --git a/device/sensors/sensor_manager_chromeos.cc b/device/sensors/sensor_manager_chromeos.cc
index 02dfb93..9cb940b3 100644
--- a/device/sensors/sensor_manager_chromeos.cc
+++ b/device/sensors/sensor_manager_chromeos.cc
@@ -19,11 +19,9 @@
 namespace device {
 
 SensorManagerChromeOS::SensorManagerChromeOS()
-    : motion_buffer_(nullptr), orientation_buffer_(nullptr) {
-}
+    : motion_buffer_(nullptr), orientation_buffer_(nullptr) {}
 
-SensorManagerChromeOS::~SensorManagerChromeOS() {
-}
+SensorManagerChromeOS::~SensorManagerChromeOS() {}
 
 void SensorManagerChromeOS::StartFetchingDeviceMotionData(
     DeviceMotionHardwareBuffer* buffer) {
diff --git a/device/sensors/sensor_manager_chromeos_unittest.cc b/device/sensors/sensor_manager_chromeos_unittest.cc
index 10b95a2..db10215d 100644
--- a/device/sensors/sensor_manager_chromeos_unittest.cc
+++ b/device/sensors/sensor_manager_chromeos_unittest.cc
@@ -22,7 +22,7 @@
 class TestSensorManagerChromeOS : public device::SensorManagerChromeOS {
  public:
   TestSensorManagerChromeOS() {}
-  ~TestSensorManagerChromeOS() override {};
+  ~TestSensorManagerChromeOS() override {}
 
  protected:
   void StartObservingAccelerometer() override {}
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc b/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc
index e594ded..37bd2ea 100644
--- a/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc
+++ b/gpu/ipc/client/gpu_memory_buffer_impl_io_surface.cc
@@ -116,15 +116,20 @@
   if (color_space == color_space_)
     return;
   color_space_ = color_space;
-  std::vector<char> icc_profile =
-      gfx::ICCProfile::FromColorSpace(color_space).GetData();
-  if (icc_profile.size()) {
-    base::ScopedCFTypeRef<CFDataRef> cf_data_icc_profile(CFDataCreate(
-        nullptr, reinterpret_cast<const UInt8*>(icc_profile.data()),
-        icc_profile.size()));
-    IOSurfaceSetValue(io_surface_, CFSTR("IOSurfaceColorSpace"),
-                      cf_data_icc_profile);
+
+  // Retrieve the ICC profile data.
+  gfx::ICCProfile icc_profile;
+  if (!color_space_.GetICCProfile(&icc_profile)) {
+    DLOG(ERROR) << "Failed to set color space for scanout: no ICC profile.";
+    return;
   }
+
+  // Package it as a CFDataRef and send it to the IOSurface.
+  base::ScopedCFTypeRef<CFDataRef> cf_data_icc_profile(CFDataCreate(
+      nullptr, reinterpret_cast<const UInt8*>(icc_profile.GetData().data()),
+      icc_profile.GetData().size()));
+  IOSurfaceSetValue(io_surface_, CFSTR("IOSurfaceColorSpace"),
+                    cf_data_icc_profile);
 }
 
 gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const {
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h
index eb5af5e..e622227 100644
--- a/headless/lib/browser/headless_browser_impl.h
+++ b/headless/lib/browser/headless_browser_impl.h
@@ -72,8 +72,8 @@
   // Helper for one time initialization of application
   void PlatformInitialize();
   void PlatformCreateWindow();
-  void PlatformSetWebContents(const gfx::Size& initial_size,
-                              content::WebContents* web_contents);
+  void PlatformInitializeWebContents(const gfx::Size& initial_size,
+                                     content::WebContents* web_contents);
 
  protected:
 #if defined(USE_AURA)
diff --git a/headless/lib/browser/headless_browser_impl_aura.cc b/headless/lib/browser/headless_browser_impl_aura.cc
index d1159d18..9237e34 100644
--- a/headless/lib/browser/headless_browser_impl_aura.cc
+++ b/headless/lib/browser/headless_browser_impl_aura.cc
@@ -31,7 +31,7 @@
   window_tree_host_->SetParentWindow(window_tree_host_->window());
 }
 
-void HeadlessBrowserImpl::PlatformSetWebContents(
+void HeadlessBrowserImpl::PlatformInitializeWebContents(
     const gfx::Size& initial_size,
     content::WebContents* web_contents) {
   gfx::NativeView contents = web_contents->GetNativeView();
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index 6320a12..9d4b7ad 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -134,7 +134,7 @@
 }
 
 void HeadlessWebContentsImpl::InitializeScreen(const gfx::Size& initial_size) {
-  browser()->PlatformSetWebContents(initial_size, web_contents_.get());
+  browser()->PlatformInitializeWebContents(initial_size, web_contents_.get());
 }
 
 HeadlessWebContentsImpl::HeadlessWebContentsImpl(
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc
index fc8f645..1aa61b4 100644
--- a/headless/lib/headless_content_main_delegate.cc
+++ b/headless/lib/headless_content_main_delegate.cc
@@ -160,9 +160,14 @@
 void HeadlessContentMainDelegate::PreSandboxStartup() {
   const base::CommandLine& command_line(
       *base::CommandLine::ForCurrentProcess());
-  const std::string process_type =
-      command_line.GetSwitchValueASCII(switches::kProcessType);
+#if defined(OS_WIN)
+  // Windows always needs to initialize logging, otherwise you get a renderer
+  // crash.
   InitLogging(command_line);
+#else
+  if (command_line.HasSwitch(switches::kEnableLogging))
+    InitLogging(command_line);
+#endif
   InitCrashReporter(command_line);
   InitializeResourceBundle();
 }
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
index 7adacf0..655fd6a 100644
--- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
+++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -99,25 +99,31 @@
   // TODO(xhwang): Get rid of this copy.
   scoped_refptr<media::DecoderBuffer> output_buffer =
       media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size);
-
-  std::vector<media::SubsampleEntry> subsamples;
-  for (uint32_t i = 0; i < input_buffer.num_subsamples; ++i) {
-    subsamples.push_back(
-        media::SubsampleEntry(input_buffer.subsamples[i].clear_bytes,
-                              input_buffer.subsamples[i].cipher_bytes));
-  }
-
-  std::unique_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig(
-      std::string(reinterpret_cast<const char*>(input_buffer.key_id),
-                  input_buffer.key_id_size),
-      std::string(reinterpret_cast<const char*>(input_buffer.iv),
-                  input_buffer.iv_size),
-      subsamples));
-
-  output_buffer->set_decrypt_config(std::move(decrypt_config));
   output_buffer->set_timestamp(
       base::TimeDelta::FromMicroseconds(input_buffer.timestamp));
 
+  // TODO(xhwang): Unify how to check whether a buffer is encrypted.
+  // See http://crbug.com/675003
+  if (input_buffer.iv_size != 0) {
+    DCHECK_GT(input_buffer.key_id_size, 0u);
+    std::vector<media::SubsampleEntry> subsamples;
+    for (uint32_t i = 0; i < input_buffer.num_subsamples; ++i) {
+      subsamples.push_back(
+          media::SubsampleEntry(input_buffer.subsamples[i].clear_bytes,
+                                input_buffer.subsamples[i].cipher_bytes));
+    }
+
+    std::unique_ptr<media::DecryptConfig> decrypt_config(
+        new media::DecryptConfig(
+            std::string(reinterpret_cast<const char*>(input_buffer.key_id),
+                        input_buffer.key_id_size),
+            std::string(reinterpret_cast<const char*>(input_buffer.iv),
+                        input_buffer.iv_size),
+            subsamples));
+
+    output_buffer->set_decrypt_config(std::move(decrypt_config));
+  }
+
   return output_buffer;
 }
 
@@ -729,7 +735,10 @@
   scoped_refptr<media::DecoderBuffer> buffer =
       CopyDecoderBufferFrom(encrypted_buffer);
 
-  if (buffer->end_of_stream()) {
+  // TODO(xhwang): Unify how to check whether a buffer is encrypted.
+  // See http://crbug.com/675003
+  if (buffer->end_of_stream() || !buffer->decrypt_config() ||
+      !buffer->decrypt_config()->is_encrypted()) {
     *decrypted_buffer = buffer;
     return cdm::kSuccess;
   }
diff --git a/media/filters/decoder_stream.h b/media/filters/decoder_stream.h
index cf9dcd9..00562693 100644
--- a/media/filters/decoder_stream.h
+++ b/media/filters/decoder_stream.h
@@ -205,12 +205,14 @@
   std::unique_ptr<DecoderSelector<StreamType>> decoder_selector_;
 
   std::unique_ptr<Decoder> decoder_;
+
   // When falling back from H/W decoding to S/W decoding, destructing the
   // GpuVideoDecoder too early results in black frames being displayed.
   // |previous_decoder_| is used to keep it alive.  It is destroyed once we've
   // decoded at least media::limits::kMaxVideoFrames frames after fallback.
   int decoded_frames_since_fallback_;
   std::unique_ptr<Decoder> previous_decoder_;
+
   std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
 
   ConfigChangeObserverCB config_change_observer_cb_;
diff --git a/media/filters/decrypting_audio_decoder.cc b/media/filters/decrypting_audio_decoder.cc
index 6ae354c..764946903 100644
--- a/media/filters/decrypting_audio_decoder.cc
+++ b/media/filters/decrypting_audio_decoder.cc
@@ -63,23 +63,20 @@
   init_cb_ = BindToCurrentLoop(init_cb);
   output_cb_ = BindToCurrentLoop(output_cb);
 
-  // TODO(xhwang): We should be able to DCHECK config.IsValidConfig() and
-  // config.is_encrypted().
+  // TODO(xhwang): We should be able to DCHECK config.IsValidConfig().
   if (!config.IsValidConfig()) {
     DLOG(ERROR) << "Invalid audio stream config.";
     base::ResetAndReturn(&init_cb_).Run(false);
     return;
   }
 
-  // DecryptingAudioDecoder only accepts potentially encrypted stream.
-  if (!config.is_encrypted()) {
-    base::ResetAndReturn(&init_cb_).Run(false);
-    return;
-  }
-
   config_ = config;
 
   if (state_ == kUninitialized) {
+    // DecoderSelector only chooses |this| when the stream is encrypted.
+    // TODO(xhwang): We may also select this decoder for clear stream if a CDM
+    // is attached. Then we need to update this. See http://crbug.com/597443
+    DCHECK(config.is_encrypted());
     DCHECK(cdm_context);
     if (!cdm_context->GetDecryptor()) {
       MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor";
@@ -89,7 +86,8 @@
 
     decryptor_ = cdm_context->GetDecryptor();
   } else {
-    // Reinitialization (i.e. upon a config change)
+    // Reinitialization (i.e. upon a config change). The new config can be
+    // encrypted or clear.
     decryptor_->DeinitializeDecoder(Decryptor::kAudio);
   }
 
diff --git a/media/filters/decrypting_audio_decoder_unittest.cc b/media/filters/decrypting_audio_decoder_unittest.cc
index bd12003..830a5a11 100644
--- a/media/filters/decrypting_audio_decoder_unittest.cc
+++ b/media/filters/decrypting_audio_decoder_unittest.cc
@@ -281,15 +281,6 @@
   Initialize();
 }
 
-// Ensure that DecryptingAudioDecoder only accepts encrypted audio.
-TEST_F(DecryptingAudioDecoderTest, Initialize_UnencryptedAudioConfig) {
-  AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32,
-                            CHANNEL_LAYOUT_STEREO, kSampleRate,
-                            EmptyExtraData(), Unencrypted());
-
-  InitializeAndExpectResult(config, false);
-}
-
 // Ensure decoder handles invalid audio configs without crashing.
 TEST_F(DecryptingAudioDecoderTest, Initialize_InvalidAudioConfig) {
   AudioDecoderConfig config(kUnknownAudioCodec, kUnknownSampleFormat,
@@ -368,8 +359,8 @@
   EnterEndOfStreamState();
 }
 
-// Test reinitializing decode with a new config
-TEST_F(DecryptingAudioDecoderTest, Reinitialize_ConfigChange) {
+// Test reinitializing decode with a new encrypted config.
+TEST_F(DecryptingAudioDecoderTest, Reinitialize_EncryptedToEncrypted) {
   Initialize();
 
   EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
@@ -384,6 +375,29 @@
   EXPECT_NE(new_config.bits_per_channel(), config_.bits_per_channel());
   EXPECT_NE(new_config.channel_layout(), config_.channel_layout());
   EXPECT_NE(new_config.samples_per_second(), config_.samples_per_second());
+  ASSERT_TRUE(new_config.is_encrypted());
+
+  ReinitializeConfigChange(new_config);
+  base::RunLoop().RunUntilIdle();
+}
+
+// Test reinitializing decode with a new clear config.
+TEST_F(DecryptingAudioDecoderTest, Reinitialize_EncryptedToClear) {
+  Initialize();
+
+  EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
+      .Times(AtMost(1))
+      .WillOnce(RunCallback<1>(true));
+
+  // The new config is different from the initial config in bits-per-channel,
+  // channel layout and samples_per_second.
+  AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarS16,
+                                CHANNEL_LAYOUT_5_1, 88200, EmptyExtraData(),
+                                Unencrypted());
+  EXPECT_NE(new_config.bits_per_channel(), config_.bits_per_channel());
+  EXPECT_NE(new_config.channel_layout(), config_.channel_layout());
+  EXPECT_NE(new_config.samples_per_second(), config_.samples_per_second());
+  ASSERT_FALSE(new_config.is_encrypted());
 
   ReinitializeConfigChange(new_config);
   base::RunLoop().RunUntilIdle();
diff --git a/media/filters/decrypting_demuxer_stream.cc b/media/filters/decrypting_demuxer_stream.cc
index 54052a74..7213aef4 100644
--- a/media/filters/decrypting_demuxer_stream.cc
+++ b/media/filters/decrypting_demuxer_stream.cc
@@ -17,13 +17,11 @@
 
 namespace media {
 
-static bool IsStreamValidAndEncrypted(DemuxerStream* stream) {
+static bool IsStreamValid(DemuxerStream* stream) {
   return ((stream->type() == DemuxerStream::AUDIO &&
-           stream->audio_decoder_config().IsValidConfig() &&
-           stream->audio_decoder_config().is_encrypted()) ||
+           stream->audio_decoder_config().IsValidConfig()) ||
           (stream->type() == DemuxerStream::VIDEO &&
-           stream->video_decoder_config().IsValidConfig() &&
-           stream->video_decoder_config().is_encrypted()));
+           stream->video_decoder_config().IsValidConfig()));
 }
 
 DecryptingDemuxerStream::DecryptingDemuxerStream(
@@ -213,16 +211,26 @@
     return;
   }
 
+  DCHECK_EQ(kOk, status);
+
   if (buffer->end_of_stream()) {
     DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
     state_ = kIdle;
-    base::ResetAndReturn(&read_cb_).Run(status, buffer);
+    base::ResetAndReturn(&read_cb_).Run(kOk, buffer);
     return;
   }
 
-  DCHECK(buffer->decrypt_config());
+  // TODO(xhwang): Unify clear buffer handling in clear and encrypted stream.
+  // See http://crbug.com/675003
+  if (!buffer->decrypt_config()) {
+    DVLOG(2) << "DoDecryptBuffer() - clear buffer in clear stream.";
+    state_ = kIdle;
+    base::ResetAndReturn(&read_cb_).Run(kOk, buffer);
+    return;
+  }
+
   if (!buffer->decrypt_config()->is_encrypted()) {
-    DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
+    DVLOG(2) << "DoDecryptBuffer() - clear buffer in encrypted stream.";
     scoped_refptr<DecoderBuffer> decrypted = DecoderBuffer::CopyFrom(
         buffer->data(), buffer->data_size());
     decrypted->set_timestamp(buffer->timestamp());
@@ -348,9 +356,8 @@
 }
 
 void DecryptingDemuxerStream::InitializeDecoderConfig() {
-  // The decoder selector or upstream demuxer make sure the stream is valid and
-  // potentially encrypted.
-  DCHECK(IsStreamValidAndEncrypted(demuxer_stream_));
+  // The decoder selector or upstream demuxer make sure the stream is valid.
+  DCHECK(IsStreamValid(demuxer_stream_));
 
   switch (demuxer_stream_->type()) {
     case AUDIO: {
diff --git a/media/filters/decrypting_demuxer_stream_unittest.cc b/media/filters/decrypting_demuxer_stream_unittest.cc
index d13aec42..e6a57e2 100644
--- a/media/filters/decrypting_demuxer_stream_unittest.cc
+++ b/media/filters/decrypting_demuxer_stream_unittest.cc
@@ -72,7 +72,8 @@
             new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)),
         input_video_stream_(
             new StrictMock<MockDemuxerStream>(DemuxerStream::VIDEO)),
-        clear_buffer_(CreateFakeEncryptedStreamBuffer(true)),
+        clear_buffer_(new DecoderBuffer(kFakeBufferSize)),
+        clear_encrypted_stream_buffer_(CreateFakeEncryptedStreamBuffer(true)),
         encrypted_buffer_(CreateFakeEncryptedStreamBuffer(false)),
         decrypted_buffer_(new DecoderBuffer(kFakeBufferSize)) {}
 
@@ -158,10 +159,12 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  void EnterClearReadingState() {
-    EXPECT_TRUE(clear_buffer_->decrypt_config());
+  void EnterClearReadingState(bool is_stream_encrytped) {
+    EXPECT_TRUE(clear_encrypted_stream_buffer_->decrypt_config());
     EXPECT_CALL(*input_audio_stream_, Read(_))
-        .WillOnce(ReturnBuffer(clear_buffer_));
+        .WillOnce(ReturnBuffer(is_stream_encrytped
+                                   ? clear_encrypted_stream_buffer_
+                                   : clear_buffer_));
 
     // For clearbuffer, decryptor->Decrypt() will not be called.
 
@@ -266,6 +269,7 @@
   // Constant buffers to be returned by the input demuxer streams and the
   // |decryptor_|.
   scoped_refptr<DecoderBuffer> clear_buffer_;
+  scoped_refptr<DecoderBuffer> clear_encrypted_stream_buffer_;
   scoped_refptr<DecoderBuffer> encrypted_buffer_;
   scoped_refptr<DecoderBuffer> decrypted_buffer_;
 
@@ -313,9 +317,17 @@
 }
 
 // Test normal read case where the buffer is clear.
-TEST_F(DecryptingDemuxerStreamTest, Read_Clear) {
+// TODO(xhwang): Unify clear buffer handling in clear and encrypted stream.
+// See http://crbug.com/675003
+
+TEST_F(DecryptingDemuxerStreamTest, Read_ClearBufferInEncryptedStream) {
   Initialize();
-  EnterClearReadingState();
+  EnterClearReadingState(true);
+}
+
+TEST_F(DecryptingDemuxerStreamTest, Read_ClearBufferInClearStream) {
+  Initialize();
+  EnterClearReadingState(false);
 }
 
 // Test the case where the decryptor returns error during read.
diff --git a/media/filters/decrypting_video_decoder.cc b/media/filters/decrypting_video_decoder.cc
index 1b541d96..3a869440 100644
--- a/media/filters/decrypting_video_decoder.cc
+++ b/media/filters/decrypting_video_decoder.cc
@@ -52,7 +52,6 @@
   DCHECK(decode_cb_.is_null());
   DCHECK(reset_cb_.is_null());
   DCHECK(config.IsValidConfig());
-  DCHECK(config.is_encrypted());
 
   init_cb_ = BindToCurrentLoop(init_cb);
   output_cb_ = BindToCurrentLoop(output_cb);
@@ -60,6 +59,10 @@
   config_ = config;
 
   if (state_ == kUninitialized) {
+    // DecoderSelector only chooses |this| when the stream is encrypted.
+    // TODO(xhwang): We may also select this decoder for clear stream if a CDM
+    // is attached. Then we need to update this. See http://crbug.com/597443
+    DCHECK(config.is_encrypted());
     DCHECK(cdm_context);
     if (!cdm_context->GetDecryptor()) {
       MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor";
@@ -69,7 +72,8 @@
 
     decryptor_ = cdm_context->GetDecryptor();
   } else {
-    // Reinitialization.
+    // Reinitialization (i.e. upon a config change). The new config can be
+    // encrypted or clear.
     decryptor_->DeinitializeDecoder(Decryptor::kVideo);
   }
 
diff --git a/media/filters/decrypting_video_decoder_unittest.cc b/media/filters/decrypting_video_decoder_unittest.cc
index 7f17248..0e3b169 100644
--- a/media/filters/decrypting_video_decoder_unittest.cc
+++ b/media/filters/decrypting_video_decoder_unittest.cc
@@ -107,14 +107,14 @@
   }
 
   // Reinitialize the |decoder_| and expects it to succeed.
-  void Reinitialize() {
+  void Reinitialize(const VideoDecoderConfig& new_config) {
     EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kVideo));
     EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
         .WillOnce(RunCallback<1>(true));
     EXPECT_CALL(*decryptor_, RegisterNewKeyCB(Decryptor::kVideo, _))
         .WillOnce(SaveArg<1>(&key_added_cb_));
 
-    InitializeAndExpectResult(TestVideoConfig::LargeEncrypted(), true);
+    InitializeAndExpectResult(new_config, true);
   }
 
   // Decode |buffer| and expect DecodeDone to get called with |status|.
@@ -273,10 +273,17 @@
   InitializeAndExpectResult(TestVideoConfig::NormalEncrypted(), false);
 }
 
-TEST_F(DecryptingVideoDecoderTest, Reinitialize_Normal) {
+TEST_F(DecryptingVideoDecoderTest, Reinitialize_EncryptedToEncrypted) {
   Initialize();
   EnterNormalDecodingState();
-  Reinitialize();
+  Reinitialize(TestVideoConfig::LargeEncrypted());
+}
+
+// Test reinitializing decode with a new clear config.
+TEST_F(DecryptingVideoDecoderTest, Reinitialize_EncryptedToClear) {
+  Initialize();
+  EnterNormalDecodingState();
+  Reinitialize(TestVideoConfig::Normal());
 }
 
 TEST_F(DecryptingVideoDecoderTest, Reinitialize_Failure) {
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index 471ae384..f6cb9d1 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -1580,12 +1580,6 @@
     return false;
   }
 
-  if (!audio_configs_[0].encryption_scheme().Matches(
-          config.encryption_scheme())) {
-    MEDIA_LOG(ERROR, media_log_) << "Audio encryption changes not allowed.";
-    return false;
-  }
-
   // Check to see if the new config matches an existing one.
   for (size_t i = 0; i < audio_configs_.size(); ++i) {
     if (config.Matches(audio_configs_[i])) {
@@ -1612,12 +1606,6 @@
     return false;
   }
 
-  if (!video_configs_[0].encryption_scheme().Matches(
-          config.encryption_scheme())) {
-    MEDIA_LOG(ERROR, media_log_) << "Video encryption changes not allowed.";
-    return false;
-  }
-
   // Check to see if the new config matches an existing one.
   for (size_t i = 0; i < video_configs_.size(); ++i) {
     if (config.Matches(video_configs_[i])) {
diff --git a/media/test/data/eme_player.html b/media/test/data/eme_player.html
index 3e84538..4b73da8 100644
--- a/media/test/data/eme_player.html
+++ b/media/test/data/eme_player.html
@@ -145,6 +145,8 @@
 
     function start() {
       initApp();  
+      // TODO(jrummell): Support setMediaKeys() after play().
+      // See http://crbug.com/675011
       emeApp.createPlayer()
           .then(function(p) {
               player = p;
diff --git a/media/test/data/eme_player_js/globals.js b/media/test/data/eme_player_js/globals.js
index 81e344e1..bdc7d25 100644
--- a/media/test/data/eme_player_js/globals.js
+++ b/media/test/data/eme_player_js/globals.js
@@ -55,6 +55,13 @@
   'External Clearkey': EXTERNAL_CLEARKEY
 };
 
+var CONFIG_CHANGE_TYPE = {
+  CLEAR_TO_CLEAR : '0',
+  CLEAR_TO_ENCRYPTED : '1',
+  ENCRYPTED_TO_CLEAR : '2',
+  ENCRYPTED_TO_ENCRYPTED : '3'
+};
+
 // General WebM and MP4 name:content_type map to show on the document page.
 var MEDIA_TYPES = {
   'WebM - Audio Video': 'video/webm; codecs="vorbis, vp8"',
diff --git a/media/test/data/eme_player_js/test_config.js b/media/test/data/eme_player_js/test_config.js
index 07e8658..a8fba4b 100644
--- a/media/test/data/eme_player_js/test_config.js
+++ b/media/test/data/eme_player_js/test_config.js
@@ -12,6 +12,7 @@
   this.useMSE = false;
   this.runFPS = false;
   this.playTwice = false;
+  this.configChangeType = CONFIG_CHANGE_TYPE.CLEAR_TO_CLEAR;
 }
 
 TestConfig.prototype.loadQueryParams = function() {
diff --git a/media/test/data/mse_config_change.html b/media/test/data/mse_config_change.html
index 9234b65..bb75d258 100644
--- a/media/test/data/mse_config_change.html
+++ b/media/test/data/mse_config_change.html
@@ -31,17 +31,43 @@
       // Append MEDIA_2 source at APPEND_TIME, so expected total duration is:
       var TOTAL_DURATION = APPEND_TIME + MEDIA_2_LENGTH;
 
+      var firstFile;
+      var secondFile;
+
       function initTestConfig() {
         testConfig = new TestConfig();
         testConfig.loadQueryParams();
       }
 
+      function setMediaFiles() {
+        switch (testConfig.configChangeType) {
+          case CONFIG_CHANGE_TYPE.CLEAR_TO_CLEAR:
+            console.log('Config change type: clear to clear.');
+            firstFile = CLEAR_MEDIA_1;
+            secondFile = CLEAR_MEDIA_2;
+            break;
+          case CONFIG_CHANGE_TYPE.CLEAR_TO_ENCRYPTED:
+            console.log('Config change type: clear to encrypted.');
+            firstFile = CLEAR_MEDIA_1;
+            secondFile = ENCRYPTED_MEDIA_2;
+            break;
+          case CONFIG_CHANGE_TYPE.ENCRYPTED_TO_CLEAR:
+            console.log('Config change type: encrypted to clear.');
+            firstFile = ENCRYPTED_MEDIA_1;
+            secondFile = CLEAR_MEDIA_2;
+            break;
+          case CONFIG_CHANGE_TYPE.ENCRYPTED_TO_ENCRYPTED:
+            console.log('Config change type: encrypted to encrypted.');
+            firstFile = ENCRYPTED_MEDIA_1;
+            secondFile = ENCRYPTED_MEDIA_2;
+            break;
+        }
+      }
+
       function appendNextSource(mediaSource) {
         console.log('Appending next media source at ' + APPEND_TIME + 'sec.');
         var xhr = new XMLHttpRequest();
-        var mediaFile =
-            (testConfig.runEncrypted == 1) ? ENCRYPTED_MEDIA_2 : CLEAR_MEDIA_2;
-        xhr.open("GET", mediaFile);
+        xhr.open("GET", secondFile);
         xhr.responseType = 'arraybuffer';
         xhr.addEventListener('load', function(e) {
           var onUpdateEnd = function(e) {
@@ -121,14 +147,14 @@
 
       function runTest() {
         initTestConfig();
-        testConfig.mediaFile =
-            (testConfig.runEncrypted == 1) ? ENCRYPTED_MEDIA_1 : CLEAR_MEDIA_1;
+        setMediaFiles();
+        testConfig.mediaFile = firstFile;
         testConfig.mediaType = mediaType;
         video.addEventListener('timeupdate', onTimeUpdate);
         video.addEventListener('ended', Utils.failTest);
         var mediaSource = MediaSourceUtils.loadMediaSourceFromTestConfig(
             testConfig, appendNextSource);
-        if (testConfig.runEncrypted == 1) {
+        if (testConfig.configChangeType != CONFIG_CHANGE_TYPE.CLEAR_TO_CLEAR) {
           var emePlayer = PlayerUtils.createPlayer(video, testConfig);
           emePlayer.registerEventListeners()
               .then(function(player) {
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index 9ef8f36..428a5372 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -120,7 +120,6 @@
 const int kAppendTimeSec = 1;
 const int kAppendTimeMs = kAppendTimeSec * 1000;
 const int k320WebMFileDurationMs = 2736;
-const int k320EncWebMFileDurationMs = 2737;
 const int k640WebMFileDurationMs = 2749;
 const int kOpusEndTrimmingWebMFileDurationMs = 2741;
 const int kVP9WebMFileDurationMs = 2736;
@@ -1532,7 +1531,9 @@
   Stop();
 }
 
-// Config changes from encrypted to clear are not currently supported.
+// TODO(xhwang): Config change from clear to encrypted is allowed by the
+// demuxer, but is not currently supported by the Renderer. See
+// http://crbug.com/597443
 TEST_F(PipelineIntegrationTest,
        MAYBE_EME(MediaSource_ConfigChange_ClearThenEncrypted_WebM)) {
   MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
@@ -1544,28 +1545,25 @@
   scoped_refptr<DecoderBuffer> second_file =
       ReadTestDataFile("bear-640x360-av_enc-av.webm");
 
-  ASSERT_FALSE(source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
-                                   second_file->data(),
-                                   second_file->data_size()));
-
+  EXPECT_TRUE(source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
+                                  second_file->data(),
+                                  second_file->data_size()));
   source.EndOfStream();
 
-  base::RunLoop().Run();
-  EXPECT_EQ(CHUNK_DEMUXER_ERROR_APPEND_FAILED, pipeline_status_);
-
-  EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
-  EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
-  // The second video was not added, so its time has not been added.
-  EXPECT_EQ(k320WebMFileDurationMs,
-            pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
-
   Play();
 
-  EXPECT_EQ(CHUNK_DEMUXER_ERROR_APPEND_FAILED, WaitUntilEndedOrError());
+  EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
+
+  EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
+  EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
+  EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
+            pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
+
   source.Shutdown();
 }
 
-// Config changes from clear to encrypted are not currently supported.
+// Config change from encrypted to clear is allowed by the demuxer, and is
+// supported by the Renderer.
 TEST_F(PipelineIntegrationTest,
        MAYBE_EME(MediaSource_ConfigChange_EncryptedThenClear_WebM)) {
   MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
@@ -1574,25 +1572,25 @@
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
 
+  EXPECT_CALL(*this, OnVideoNaturalSizeChange(gfx::Size(640, 360))).Times(1);
   scoped_refptr<DecoderBuffer> second_file =
       ReadTestDataFile("bear-640x360.webm");
 
-  ASSERT_FALSE(source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
-                                   second_file->data(),
-                                   second_file->data_size()));
-
+  ASSERT_TRUE(source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
+                                  second_file->data(),
+                                  second_file->data_size()));
   source.EndOfStream();
 
+  Play();
+  ASSERT_TRUE(WaitUntilOnEnded());
+
   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
-  // The second video was not added, so its time has not been added.
-  EXPECT_EQ(k320EncWebMFileDurationMs,
+  EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
 
-  Play();
-
-  EXPECT_EQ(CHUNK_DEMUXER_ERROR_APPEND_FAILED, WaitUntilEndedOrError());
   source.Shutdown();
+  Stop();
 }
 
 #if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_ANDROID)
diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
index a020ee6b..1621bbf 100644
--- a/mojo/edk/system/channel.cc
+++ b/mojo/edk/system/channel.cc
@@ -37,7 +37,7 @@
 }  // namespace
 
 const size_t kReadBufferSize = 4096;
-const size_t kMaxUnusedReadBufferCapacity = 64 * 1024;
+const size_t kMaxUnusedReadBufferCapacity = 4096;
 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024;
 const size_t kMaxAttachedHandles = 128;
 
diff --git a/services/service_manager/public/cpp/lib/service.cc b/services/service_manager/public/cpp/lib/service.cc
index 72222ef..1044226e 100644
--- a/services/service_manager/public/cpp/lib/service.cc
+++ b/services/service_manager/public/cpp/lib/service.cc
@@ -44,6 +44,10 @@
 
 bool Service::OnStop() { return true; }
 
+void Service::OnStartFailed() {
+  context()->QuitNow();
+}
+
 ServiceContext* Service::context() const {
   DCHECK(service_context_)
       << "Service::context() may only be called during or after OnStart().";
@@ -64,6 +68,19 @@
   return target_->OnConnect(remote_info, registry);
 }
 
+void ForwardingService::OnBindInterface(
+    const ServiceInfo& remote_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  target_->OnBindInterface(remote_info, interface_name,
+                           std::move(interface_pipe));
+}
+
 bool ForwardingService::OnStop() { return target_->OnStop(); }
 
+void ForwardingService::OnStartFailed() {
+  target_->set_context(context());
+  return target_->OnStartFailed();
+}
+
 }  // namespace service_manager
diff --git a/services/service_manager/public/cpp/lib/service_context.cc b/services/service_manager/public/cpp/lib/service_context.cc
index f45202e..2158bef 100644
--- a/services/service_manager/public/cpp/lib/service_context.cc
+++ b/services/service_manager/public/cpp/lib/service_context.cc
@@ -80,6 +80,7 @@
 
 void ServiceContext::OnStart(const ServiceInfo& info,
                              const OnStartCallback& callback) {
+  service_started_ = true;
   local_info_ = info;
   callback.Run(std::move(pending_connector_request_),
                mojo::MakeRequest(&service_control_));
@@ -140,6 +141,13 @@
 }
 
 void ServiceContext::OnConnectionError() {
+  if (!service_started_) {
+    // The pipe was broken before we even received OnStart().
+    service_->set_context(this);
+    service_->OnStartFailed();
+    return;
+  }
+
   // Note that the Service doesn't technically have to quit now, it may live
   // on to service existing connections. All existing Connectors however are
   // invalid.
diff --git a/services/service_manager/public/cpp/service.h b/services/service_manager/public/cpp/service.h
index 250b8ab..02d9e0c 100644
--- a/services/service_manager/public/cpp/service.h
+++ b/services/service_manager/public/cpp/service.h
@@ -23,11 +23,22 @@
   Service();
   virtual ~Service();
 
-  // Called exactly once, when a bidirectional connection with the Service
-  // Manager has been established. No calls to OnConnect() will be received
-  // before this.
+  // Called exactly once when a bidirectional connection with the Service
+  // Manager has been established. No calls to OnConnect(), OnBindInterface(),
+  // or OnStop() will be made before this. Note that this call is mutually
+  // exclusive to OnStartFailed() - either one or the other will be the first
+  // call on any given Service instance.
   virtual void OnStart();
 
+  // Called if the Service loses its connection to the Service Manager before
+  // OnStart() could be invoked. Once this called, none of the other public
+  // Service interface methods will be called.  Note that this call is mutually
+  // exclusive to OnStart() - either one or the other will be the first call on
+  // any given Service instance.
+  //
+  // The default implementation calls QuitNow() on context().
+  virtual void OnStartFailed();
+
   // Called each time a connection to this service is brokered by the Service
   // Manager. Implement this to expose interfaces to other services.
   //
@@ -51,24 +62,23 @@
   // service should use this as a signal to shut down, and in fact its process
   // may be reaped shortly afterward if applicable.
   //
-  // Return true from this method to tell the ServiceContext to signal its
-  // shutdown externally (i.e. to invoke its "connection lost" closure if set),
-  // or return false to defer the signal. If deferred, the Service should
-  // explicitly call QuitNow() on the ServiceContext when it's ready to be
-  // torn down.
+  // Returning true from this method signals that the Service instance can be
+  // destroyed immediately. More precisely, it will cause the context()'s
+  // QuitNow() method to be invoked immediately after this OnStop() call.
+  //
+  // If shutdown is deferred by returning false, the Service itself is
+  // responsible for explicitly calling QuitNow() on context() when it's ready
+  // to be destroyed.
   //
   // The default implementation returns true.
   //
-  // While it's possible for this to be invoked before either OnStart() or
-  // OnConnect() is invoked, neither will be invoked at any point after this
-  // OnStop().
+  // NOTE: This will only be called after OnStart(), and none of the other
+  // public Service methods will be called after this.
   virtual bool OnStop();
 
  protected:
-  // Access the ServiceContext associated with this Service. Note that this is
-  // only valid to call during or after OnStart(), but never before! As such,
-  // it's always safe to call in OnStart() and OnConnect(), but should generally
-  // be avoided in OnStop().
+  // Accesses the ServiceContext associated with this Service. Note that this is
+  // only valid during or after OnStart() or OnStartFailed(), but never before.
   ServiceContext* context() const;
 
  private:
@@ -95,7 +105,11 @@
   void OnStart() override;
   bool OnConnect(const ServiceInfo& remote_info,
                  InterfaceRegistry* registry) override;
+  void OnBindInterface(const ServiceInfo& remote_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override;
   bool OnStop() override;
+  void OnStartFailed() override;
 
  private:
   Service* const target_ = nullptr;
diff --git a/services/service_manager/public/cpp/service_context.h b/services/service_manager/public/cpp/service_context.h
index a1af32c..f86dfa0 100644
--- a/services/service_manager/public/cpp/service_context.h
+++ b/services/service_manager/public/cpp/service_context.h
@@ -146,6 +146,7 @@
   // is unbound and therefore invalid until OnStart() is called.
   mojom::ServiceControlAssociatedPtr service_control_;
 
+  bool service_started_ = false;
   bool service_quit_ = false;
 
   base::Closure connection_lost_closure_;
diff --git a/services/ui/public/cpp/window_compositor_frame_sink.cc b/services/ui/public/cpp/window_compositor_frame_sink.cc
index 2e7876f..9529895 100644
--- a/services/ui/public/cpp/window_compositor_frame_sink.cc
+++ b/services/ui/public/cpp/window_compositor_frame_sink.cc
@@ -116,7 +116,9 @@
   client_->ReclaimResources(resources);
 }
 
-void WindowCompositorFrameSink::WillDrawSurface() {
+void WindowCompositorFrameSink::WillDrawSurface(
+    const cc::LocalSurfaceId& local_surface_id,
+    const gfx::Rect& damage_rect) {
   // TODO(fsamuel, staraz): Implement this.
 }
 
diff --git a/services/ui/public/cpp/window_compositor_frame_sink.h b/services/ui/public/cpp/window_compositor_frame_sink.h
index 90123a1..cfae582 100644
--- a/services/ui/public/cpp/window_compositor_frame_sink.h
+++ b/services/ui/public/cpp/window_compositor_frame_sink.h
@@ -50,7 +50,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_args) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
   // cc::ExternalBeginFrameSourceClient implementation.
   void OnNeedsBeginFrames(bool needs_begin_frames) override;
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index 7ce4797e..9dc197d 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -106,7 +106,8 @@
   DCHECK(resources.empty());
 }
 
-void FrameGenerator::WillDrawSurface() {
+void FrameGenerator::WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                                     const gfx::Rect& damage_rect) {
   // TODO(fsamuel, staraz): Implement this.
 }
 
diff --git a/services/ui/ws/frame_generator.h b/services/ui/ws/frame_generator.h
index 1275a2a..bfad392a 100644
--- a/services/ui/ws/frame_generator.h
+++ b/services/ui/ws/frame_generator.h
@@ -59,7 +59,8 @@
   void DidReceiveCompositorFrameAck() override;
   void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_arags) override;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) override;
-  void WillDrawSurface() override;
+  void WillDrawSurface(const cc::LocalSurfaceId& local_surface_id,
+                       const gfx::Rect& damage_rect) override;
 
   // Generates the CompositorFrame.
   cc::CompositorFrame GenerateCompositorFrame(const gfx::Rect& output_rect);
diff --git a/third_party/WebKit/LayoutTests/animations/interpolation/order-interpolation.html b/third_party/WebKit/LayoutTests/animations/interpolation/order-interpolation.html
new file mode 100644
index 0000000..c226576c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/interpolation/order-interpolation.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<body>
+<style>
+.parent {
+  order: 30;
+}
+.target {
+  order: 10;
+}
+</style>
+<script src="resources/interpolation-test.js"></script>
+<script>
+assertInterpolation({
+  property: 'order',
+  from: neutralKeyframe,
+  to: '20',
+}, [
+  {at: -3, is: '-20'},
+  {at: -0.5, is: '5'},
+  {at: 0, is: '10'},
+  {at: 0.3, is: '13'},
+  {at: 0.6, is: '16'},
+  {at: 1, is: '20'},
+  {at: 1.5, is: '25'},
+]);
+
+assertInterpolation({
+  property: 'order',
+  from: 'initial',
+  to: '20',
+}, [
+  {at: -3, is: '-60'},
+  {at: -0.5, is: '-10'},
+  {at: 0, is: '0'},
+  {at: 0.3, is: '6'},
+  {at: 0.6, is: '12'},
+  {at: 1, is: '20'},
+  {at: 1.5, is: '30'},
+]);
+
+assertInterpolation({
+  property: 'order',
+  from: 'inherit',
+  to: '20',
+}, [
+  {at: -3, is: '60'},
+  {at: -0.5, is: '35'},
+  {at: 0, is: '30'},
+  {at: 0.3, is: '27'},
+  {at: 0.6, is: '24'},
+  {at: 1, is: '20'},
+  {at: 1.5, is: '15'},
+]);
+
+assertInterpolation({
+  property: 'order',
+  from: 'unset',
+  to: '20',
+}, [
+  {at: -3, is: '-60'},
+  {at: -0.5, is: '-10'},
+  {at: 0, is: '0'},
+  {at: 0.3, is: '6'},
+  {at: 0.6, is: '12'},
+  {at: 1, is: '20'},
+  {at: 1.5, is: '30'},
+]);
+
+assertInterpolation({
+  property: 'order',
+  from: '10',
+  to: '20'
+}, [
+  {at: -3.0, is: '-20'},
+  {at: -0.5, is: '5'},
+  {at: 0, is: '10'},
+  {at: 0.3, is: '13'},
+  {at: 0.6, is: '16'},
+  {at: 1, is: '20'},
+  {at: 1.5, is: '25'}
+]);
+
+assertInterpolation({
+  property: 'order',
+  from: '2',
+  to: '4'
+}, [
+  {at: -3.0, is: '-4'},
+  {at: -0.5, is: '1'},
+  {at: 0, is: '2'},
+  {at: 0.3, is: '3'},
+  {at: 0.6, is: '3'},
+  {at: 1, is: '4'},
+  {at: 1.5, is: '5'}
+]);
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/README.md b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/README.md
index e8e58e71..2489799 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/README.md
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/README.md
@@ -214,7 +214,7 @@
 
 * Expand each field's pattern (single, any of, or all) to list of allowed values (defined by the ```test_expansion_schema```)
 
-* Permute - Recursively enumerate all **selections** accross all fields
+* Permute - Recursively enumerate all **selections** across all fields
 
 Be aware that if there is more than one pattern expanding into a same selection (which also shares the same ```name``` field), the pattern appearing later in the spec JSON will overwrite a previously generated selection. To make sure this is not undetected when generating, set the value of the ```expansion``` field to ```default``` for an expansion appearing earlier and ```override``` for the one appearing later.
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js
index 74502235..0cd38c9 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js
@@ -14,6 +14,20 @@
 InspectorTest.TestFileSystem._instances = {};
 
 InspectorTest.TestFileSystem.prototype = {
+    dumpAsText: function() {
+        var result = [];
+        dfs(this.root, '');
+        result[0] = this.fileSystemPath;
+        return result.join('\n');
+
+        function dfs(node, indent) {
+            result.push(indent + node.name);
+            var newIndent = indent + '    ';
+            for (var child of node._children)
+                dfs(child, newIndent);
+        }
+    },
+
     reportCreated: function(callback)
     {
         var fileSystemPath = this.fileSystemPath;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/filesystem-delete-file-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/filesystem-delete-file-expected.txt
new file mode 100644
index 0000000..d641e29
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/filesystem-delete-file-expected.txt
@@ -0,0 +1,11 @@
+Verifies that uiSourceCode.delete actually deltes file from IsolatedFileSystem.
+
+BEFORE:
+file:///var/www
+    script.js
+    bar.js
+
+AFTER:
+file:///var/www
+    bar.js
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/filesystem-delete-file.html b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/filesystem-delete-file.html
new file mode 100644
index 0000000..3d4fae1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/filesystem-delete-file.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+<script src="../inspector-test.js"></script>
+<script src="../isolated-filesystem-test.js"></script>
+<script src="./persistence-test.js"></script>
+<script src="./automapping-test.js"></script>
+<script>
+
+function test()
+{
+    var fs = new InspectorTest.TestFileSystem("file:///var/www");
+    InspectorTest.addFiles(fs, {
+        "script.js": { content: "testme" },
+        "bar.js": { content: "another" },
+    });
+    fs.reportCreated(function() { });
+    InspectorTest.waitForUISourceCode("script.js").then(onUISourceCode);
+
+    function onUISourceCode(uiSourceCode) {
+        InspectorTest.addResult("BEFORE:\n" + fs.dumpAsText());
+        uiSourceCode.remove();
+        InspectorTest.addResult("\nAFTER:\n" + fs.dumpAsText());
+        InspectorTest.completeTest();
+    }
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Verifies that uiSourceCode.delete actually deltes file from IsolatedFileSystem.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/worklet-should-report-context-destroyed-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/worklet-should-report-context-destroyed-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/http/tests/worklet/worklet-should-report-context-destroyed-expected.txt
rename to third_party/WebKit/LayoutTests/http/tests/worklet/chromium/worklet-should-report-context-destroyed-expected.txt
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/worklet-should-report-context-destroyed.html b/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/worklet-should-report-context-destroyed.html
new file mode 100644
index 0000000..692c4e9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/worklet-should-report-context-destroyed.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<html>
+<title>Worklet: Worklet should report context destroyed</title>
+<body>
+<script>
+// This test was added for confirming a crash bug fix (see
+// https://crbug.com/657450). This should be in chromium/ because of using
+// testRunner and GCController.
+if (window.testRunner) {
+  testRunner.waitUntilDone();
+  testRunner.dumpAsText();
+}
+
+function gc()
+{
+  if (window.GCController) {
+    GCController.collect();
+  } else {
+    for (var i = 0; i < 10000; ++i)
+      new Object;
+  }
+}
+
+function tryCrash()
+{
+  document.frame.paintWorklet;
+  tCF1.outerHTML = "";
+  gc();
+  if (window.testRunner)
+    testRunner.notifyDone();
+}
+</script>
+<div id=tCF1><iframe onload="tryCrash()" name=frame id=frame></iframe></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/worklet-should-report-context-destroyed.html b/third_party/WebKit/LayoutTests/http/tests/worklet/worklet-should-report-context-destroyed.html
deleted file mode 100644
index e2c7bab..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/worklet-should-report-context-destroyed.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-<script>
-    if (window.testRunner) {
-        testRunner.waitUntilDone();
-        testRunner.dumpAsText();
-    }
-
-    function gc()
-    {
-      if (window.GCController) {
-        GCController.collect();
-      } else {
-        for (var i = 0; i < 10000; ++i)
-          new Object;
-      }
-    }
-
-    function tryCrash()
-    {
-        document.frame.paintWorklet;
-        tCF1.outerHTML = "";
-        gc();
-        if (window.testRunner)
-            testRunner.notifyDone();
-    }
-</script>
-<div id=tCF1><iframe onload="tryCrash()" name=frame id=frame></iframe></div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html
index 27a1341..3b147c6 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html
@@ -136,8 +136,8 @@
 
                 function onContentDumped()
                 {
-                    Snippets.scriptSnippetModel.project().deleteFile(uiSourceCode1.url());
-                    Snippets.scriptSnippetModel.project().deleteFile(uiSourceCode2.url());
+                    Snippets.scriptSnippetModel.project().deleteFile(uiSourceCode1);
+                    Snippets.scriptSnippetModel.project().deleteFile(uiSourceCode2);
                     Snippets.scriptSnippetModel.project().createFile("", null, "", step4.bind(this));
                 }
             }
@@ -146,7 +146,7 @@
             {
                 var uiSourceCode3 = uiSourceCode;
                 InspectorTest.addResult("Snippet3 created.");
-                Snippets.scriptSnippetModel.project().deleteFile(uiSourceCode3.url());
+                Snippets.scriptSnippetModel.project().deleteFile(uiSourceCode3);
                 InspectorTest.addResult("Snippet3 deleted.");
 
                 InspectorTest.addResult("Number of uiSourceCodes in workspace: " + workspace.uiSourceCodes().filter(filterSnippet).length);
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/select-option-background-color-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/select-option-background-color-expected.txt
deleted file mode 100644
index f7aa4527..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/select-option-background-color-expected.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow OPTION id='option'",
-          "rect": [1, 35, 12, 15],
-          "reason": "style change"
-        }
-      ]
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow OPTION id='option'",
-      "reason": "style change"
-    },
-    {
-      "object": "RootInlineBox",
-      "reason": "style change"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/select-option-background-color-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/select-option-background-color-expected.txt
index 25617f4..f7aa4527 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/select-option-background-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/select-option-background-color-expected.txt
@@ -8,7 +8,7 @@
       "paintInvalidations": [
         {
           "object": "LayoutBlockFlow OPTION id='option'",
-          "rect": [1, 35, 11, 15],
+          "rect": [1, 35, 12, 15],
           "reason": "style change"
         }
       ]
diff --git a/third_party/WebKit/Source/core/animation/CSSImageListInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSImageListInterpolationType.cpp
index 54d3954..cd81de4 100644
--- a/third_party/WebKit/Source/core/animation/CSSImageListInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSImageListInterpolationType.cpp
@@ -62,7 +62,7 @@
   return ListInterpolationFunctions::createList(
       imageList.size(), [&imageList](size_t index) {
         return CSSImageInterpolationType::maybeConvertStyleImage(
-            *imageList[index], false);
+            imageList[index].get(), false);
       });
 }
 
diff --git a/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp b/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp
index e77d94e..b8bc222a 100644
--- a/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSInterpolationTypesMap.cpp
@@ -146,6 +146,7 @@
     case CSSPropertyFloodOpacity:
     case CSSPropertyFontSizeAdjust:
     case CSSPropertyOpacity:
+    case CSSPropertyOrder:
     case CSSPropertyOrphans:
     case CSSPropertyShapeImageThreshold:
     case CSSPropertyStopOpacity:
diff --git a/third_party/WebKit/Source/core/animation/ImageListPropertyFunctions.h b/third_party/WebKit/Source/core/animation/ImageListPropertyFunctions.h
index cbea878..82558d6 100644
--- a/third_party/WebKit/Source/core/animation/ImageListPropertyFunctions.h
+++ b/third_party/WebKit/Source/core/animation/ImageListPropertyFunctions.h
@@ -36,7 +36,7 @@
     }
 
     result.clear();
-    while (fillLayer && fillLayer->image()) {
+    while (fillLayer) {
       result.push_back(fillLayer->image());
       fillLayer = fillLayer->next();
     }
diff --git a/third_party/WebKit/Source/core/animation/NumberPropertyFunctions.cpp b/third_party/WebKit/Source/core/animation/NumberPropertyFunctions.cpp
index f79aa10..15d0b31 100644
--- a/third_party/WebKit/Source/core/animation/NumberPropertyFunctions.cpp
+++ b/third_party/WebKit/Source/core/animation/NumberPropertyFunctions.cpp
@@ -32,6 +32,9 @@
     case CSSPropertyOpacity:
       result = style.opacity();
       return true;
+    case CSSPropertyOrder:
+      result = style.order();
+      return true;
     case CSSPropertyOrphans:
       result = style.orphans();
       return true;
@@ -117,6 +120,7 @@
     case CSSPropertyColumnRuleWidth:
       return clampTo<unsigned short>(round(value));
 
+    case CSSPropertyOrder:
     case CSSPropertyZIndex:
       return clampTo<int>(round(value));
 
@@ -149,6 +153,9 @@
     case CSSPropertyOpacity:
       style.setOpacity(value);
       return true;
+    case CSSPropertyOrder:
+      style.setOrder(value);
+      return true;
     case CSSPropertyOrphans:
       style.setOrphans(value);
       return true;
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
index c4660496..ba31237 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimatableValueFactory.cpp
@@ -494,6 +494,8 @@
       return createFromLengthPoint(style.objectPosition(), style);
     case CSSPropertyOpacity:
       return createFromDouble(style.opacity());
+    case CSSPropertyOrder:
+      return createFromDouble(style.order());
     case CSSPropertyOrphans:
       return createFromDouble(style.orphans());
     case CSSPropertyOutlineColor:
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index 8954bc8..35ca028 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1361,6 +1361,7 @@
       name: "order",
       api_class: true,
       api_methods: ["parseSingleValue"],
+      interpolable: true,
       type_name: "int",
     },
     {
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp b/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp
index f6fd625..8c69d8ac 100644
--- a/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPropertyEquality.cpp
@@ -203,6 +203,8 @@
       return a.offsetRotation() == b.offsetRotation();
     case CSSPropertyOpacity:
       return a.opacity() == b.opacity();
+    case CSSPropertyOrder:
+      return a.order() == b.order();
     case CSSPropertyOrphans:
       return a.orphans() == b.orphans();
     case CSSPropertyOutlineColor:
diff --git a/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp b/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
index f49bf4de7..5501d85 100644
--- a/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp
@@ -549,6 +549,10 @@
       style->setOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0,
                                        nextafterf(1, 0)));
       return;
+    case CSSPropertyOrder:
+      style->setOrder(
+          clampTo<int>(round(toAnimatableDouble(value)->toDouble())));
+      return;
     case CSSPropertyOrphans:
       style->setOrphans(
           clampTo<short>(round(toAnimatableDouble(value)->toDouble()), 1));
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_break_token.h b/third_party/WebKit/Source/core/layout/ng/ng_block_break_token.h
index 14e50e4..39e9f48 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_break_token.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_break_token.h
@@ -12,24 +12,57 @@
 
 class NGBlockNode;
 
+// Represents a break token for a block node.
 class NGBlockBreakToken : public NGBreakToken {
  public:
+  // Creates a break token for a node which did fragment, and can potentially
+  // produce more fragments.
+  NGBlockBreakToken(NGBlockNode* node,
+                    LayoutUnit used_block_size,
+                    HeapVector<Member<NGBreakToken>>& child_break_tokens)
+      : NGBreakToken(kBlockBreakToken, /* is_finished */ false, node),
+        used_block_size_(used_block_size) {
+    child_break_tokens_.swap(child_break_tokens);
+  }
+
+  // Creates a break token for a node which cannot produce any more fragments.
+  explicit NGBlockBreakToken(NGBlockNode* node)
+      : NGBreakToken(kBlockBreakToken, /* is_finished */ true, node) {}
+
+  // TODO(ikilpatrick): Remove this constructor and break_offset once we've
+  // switched to new multi-col approach.
   NGBlockBreakToken(NGBlockNode* node, LayoutUnit break_offset)
-      : NGBreakToken(kBlockBreakToken),
-        node_(node),
+      : NGBreakToken(kBlockBreakToken, false, node),
         break_offset_(break_offset) {}
 
-  NGBlockNode& InputNode() const { return *node_.get(); }
+  // Represents the amount of block size used in previous fragments.
+  //
+  // E.g. if the layout block specifies a block size of 200px, and the previous
+  // fragments of this block used 150px (used block size), the next fragment
+  // should have a size of 50px (assuming no additional fragmentation).
+  LayoutUnit UsedBlockSize() const { return used_block_size_; }
+
+  // The break tokens for children of the layout node.
+  //
+  // This is used to resume layout of any children which fragmented, it may
+  // contain "finished" break tokens so we know which children to skip for the
+  // next fragment.
+  const HeapVector<Member<NGBreakToken>>& ChildBreakTokens() const {
+    return child_break_tokens_;
+  }
+
+  // TODO(ikilpatrick): Remove this accessor.
   LayoutUnit BreakOffset() const { return break_offset_; }
 
   DEFINE_INLINE_VIRTUAL_TRACE() {
     NGBreakToken::trace(visitor);
-    visitor->trace(node_);
+    visitor->trace(child_break_tokens_);
   }
 
  private:
-  Member<NGBlockNode> node_;
   LayoutUnit break_offset_;
+  LayoutUnit used_block_size_;
+  HeapVector<Member<NGBreakToken>> child_break_tokens_;
 };
 
 DEFINE_TYPE_CASTS(NGBlockBreakToken,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_break_token.h b/third_party/WebKit/Source/core/layout/ng/ng_break_token.h
index 7a1778f..15f0b1e 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_break_token.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_break_token.h
@@ -10,6 +10,27 @@
 
 namespace blink {
 
+class NGLayoutInputNode;
+
+// A break token is a continuation token for layout. A single layout input node
+// can have multiple fragments asssociated with it.
+//
+// Each fragment has a break token which can be used to determine if a layout
+// input node has finished producing fragments (aka. is "exhausted" of
+// fragments), and optionally used to produce the next fragment in the chain.
+//
+// See CSS Fragmentation (https://drafts.csswg.org/css-break/) for a detailed
+// description of different types of breaks which can occur in CSS.
+//
+// Each layout algorithm which can fragment, e.g. block-flow can optionally
+// accept a break token. For example:
+//
+// NGLayoutInputNode* node = ...;
+// NGPhysicalFragment* fragment = node->Layout(space);
+// DCHECK(!fragment->BreakToken()->IsFinished());
+// NGPhysicalFragment* fragment2 = node->Layout(space, fragment->BreakToken());
+//
+// The break token should encapsulate enough information to "resume" the layout.
 class CORE_EXPORT NGBreakToken
     : public GarbageCollectedFinalized<NGBreakToken> {
  public:
@@ -18,13 +39,24 @@
   enum NGBreakTokenType { kBlockBreakToken, kTextBreakToken };
   NGBreakTokenType Type() const { return static_cast<NGBreakTokenType>(type_); }
 
-  DEFINE_INLINE_VIRTUAL_TRACE() {}
+  // Whether the layout node cannot produce any more fragments.
+  bool IsFinished() const { return is_finished_; }
+
+  // Returns the node associated with this break token. A break token cannot be
+  // used with any other node.
+  NGLayoutInputNode* InputNode() const { return node_; }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() { visitor->trace(node_); }
 
  protected:
-  NGBreakToken(NGBreakTokenType type) : type_(type) {}
+  NGBreakToken(NGBreakTokenType type, bool is_finished, NGLayoutInputNode* node)
+      : type_(type), is_finished_(is_finished), node_(node) {}
 
  private:
   unsigned type_ : 1;
+  unsigned is_finished_ : 1;
+
+  Member<NGLayoutInputNode> node_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
index 309a0d2..d3a651d 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
@@ -39,6 +39,7 @@
 #include "platform/loader/fetch/FetchInitiatorInfo.h"
 #include "platform/loader/fetch/FetchRequest.h"
 #include "platform/loader/fetch/MemoryCache.h"
+#include "platform/loader/fetch/MockFetchContext.h"
 #include "platform/loader/fetch/MockResourceClient.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
 #include "platform/loader/fetch/ResourceLoader.h"
@@ -175,44 +176,18 @@
   imageResource->finish();
 }
 
-class ImageResourceTestMockFetchContext : public FetchContext {
- public:
-  static ImageResourceTestMockFetchContext* create() {
-    return new ImageResourceTestMockFetchContext;
-  }
-
-  virtual ~ImageResourceTestMockFetchContext() {}
-
-  bool allowImage(bool imagesEnabled, const KURL&) const override {
-    return true;
-  }
-  ResourceRequestBlockedReason canRequest(
-      Resource::Type,
-      const ResourceRequest&,
-      const KURL&,
-      const ResourceLoaderOptions&,
-      SecurityViolationReportingPolicy,
-      FetchRequest::OriginRestriction) const override {
-    return ResourceRequestBlockedReason::None;
-  }
-  bool shouldLoadNewResource(Resource::Type) const override { return true; }
-  RefPtr<WebTaskRunner> loadingTaskRunner() const override { return m_runner; }
-
- private:
-  ImageResourceTestMockFetchContext()
-      : m_runner(adoptRef(new scheduler::FakeWebTaskRunner)) {}
-
-  RefPtr<scheduler::FakeWebTaskRunner> m_runner;
-};
-
 AtomicString buildContentRange(size_t rangeLength, size_t totalLength) {
   return AtomicString(String("bytes 0-" + String::number(rangeLength - 1) +
                              "/" + String::number(totalLength)));
 }
 
+ResourceFetcher* createFetcher() {
+  return ResourceFetcher::create(
+      MockFetchContext::create(MockFetchContext::kShouldLoadNewResource));
+}
+
 TEST(ImageResourceTest, MultipartImage) {
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
@@ -295,8 +270,7 @@
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
 
   // Emulate starting a real load.
   ImageResource* imageResource =
@@ -397,8 +371,7 @@
 
   std::unique_ptr<MockImageResourceObserver> observer =
       MockImageResourceObserver::create(imageResource->getContent());
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
 
   // Send the image response.
   ResourceResponse resourceResponse(KURL(), "image/jpeg", sizeof(kJpegImage),
@@ -452,8 +425,7 @@
 }
 
 TEST(ImageResourceTest, ReloadIfLoFiOrPlaceholderViaResourceFetcher) {
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
 
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
@@ -519,8 +491,7 @@
   ResourceRequest request(testURL);
   request.setPreviewsState(WebURLRequest::ServerLoFiOn);
   FetchRequest fetchRequest(request, FetchInitiatorInfo());
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
 
   ImageResource* imageResource = ImageResource::fetch(fetchRequest, fetcher);
   std::unique_ptr<MockImageResourceObserver> observer =
@@ -585,8 +556,7 @@
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
   ImageResource* imageResource = ImageResource::fetch(request, fetcher);
@@ -892,8 +862,7 @@
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   FetchRequest request(testURL, FetchInitiatorInfo());
   ImageResource* imageResource = ImageResource::fetch(request, fetcher);
   std::unique_ptr<MockImageResourceObserver> observer =
@@ -920,8 +889,7 @@
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   FetchRequest request(testURL, FetchInitiatorInfo());
   ImageResource* imageResource = ImageResource::fetch(request, fetcher);
   std::unique_ptr<MockImageResourceObserver> observer =
@@ -955,8 +923,7 @@
   ResourceRequest resourceRequest(testURL);
   resourceRequest.setHTTPHeaderField("range", "bytes=0-2");
   FetchRequest request(resourceRequest, FetchInitiatorInfo());
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   ImageResource* imageResource = ImageResource::fetch(request, fetcher);
   std::unique_ptr<MockImageResourceObserver> observer =
       MockImageResourceObserver::create(imageResource->getContent());
@@ -997,9 +964,7 @@
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
   FetchRequest request(testURL, FetchInitiatorInfo());
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::DisallowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ(nullAtom,
@@ -1036,9 +1001,7 @@
                                 sizeof(kJpegImage)));
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::DisallowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ(nullAtom,
@@ -1053,9 +1016,7 @@
   resourceRequest.setHTTPMethod("POST");
   FetchRequest request(resourceRequest, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::DisallowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ(nullAtom,
@@ -1072,9 +1033,7 @@
   resourceRequest.setHTTPHeaderField("range", "bytes=128-255");
   FetchRequest request(resourceRequest, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::DisallowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ("bytes=128-255",
@@ -1090,9 +1049,7 @@
 
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::AllowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ("bytes=0-2047",
@@ -1138,9 +1095,7 @@
 
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::AllowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ("bytes=0-2047",
@@ -1203,9 +1158,7 @@
 
   FetchRequest request(testURL, FetchInitiatorInfo());
   request.setAllowImagePlaceholder();
-  ImageResource* imageResource = ImageResource::fetch(
-      request,
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+  ImageResource* imageResource = ImageResource::fetch(request, createFetcher());
   EXPECT_EQ(FetchRequest::AllowPlaceholder,
             request.placeholderImageRequestType());
   EXPECT_EQ("bytes=0-2047",
@@ -1274,8 +1227,7 @@
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   FetchRequest placeholderRequest(testURL, FetchInitiatorInfo());
   placeholderRequest.setAllowImagePlaceholder();
   ImageResource* imageResource =
@@ -1304,8 +1256,7 @@
   KURL testURL(ParsedURLString, kTestURL);
   ScopedMockedURLLoad scopedMockedURLLoad(testURL, GetTestFilePath());
 
-  ResourceFetcher* fetcher =
-      ResourceFetcher::create(ImageResourceTestMockFetchContext::create());
+  ResourceFetcher* fetcher = createFetcher();
   FetchRequest placeholderRequest(testURL, FetchInitiatorInfo());
   placeholderRequest.setAllowImagePlaceholder();
   ImageResource* imageResource =
@@ -1365,9 +1316,8 @@
 
     FetchRequest request(testURL, FetchInitiatorInfo());
     request.setAllowImagePlaceholder();
-    ImageResource* imageResource = ImageResource::fetch(
-        request,
-        ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+    ImageResource* imageResource =
+        ImageResource::fetch(request, createFetcher());
     EXPECT_EQ(FetchRequest::AllowPlaceholder,
               request.placeholderImageRequestType());
     EXPECT_EQ("bytes=0-2047",
@@ -1423,9 +1373,8 @@
 
     FetchRequest request(testURL, FetchInitiatorInfo());
     request.setAllowImagePlaceholder();
-    ImageResource* imageResource = ImageResource::fetch(
-        request,
-        ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+    ImageResource* imageResource =
+        ImageResource::fetch(request, createFetcher());
     EXPECT_EQ(FetchRequest::AllowPlaceholder,
               request.placeholderImageRequestType());
     EXPECT_EQ("bytes=0-2047",
@@ -1456,9 +1405,8 @@
 
     FetchRequest request(testURL, FetchInitiatorInfo());
     request.setAllowImagePlaceholder();
-    ImageResource* imageResource = ImageResource::fetch(
-        request,
-        ResourceFetcher::create(ImageResourceTestMockFetchContext::create()));
+    ImageResource* imageResource =
+        ImageResource::fetch(request, createFetcher());
     EXPECT_EQ(FetchRequest::AllowPlaceholder,
               request.placeholderImageRequestType());
     EXPECT_EQ("bytes=0-2047",
diff --git a/third_party/WebKit/Source/core/paint/ClipRect.h b/third_party/WebKit/Source/core/paint/ClipRect.h
index 5999fbc..d1b13ab 100644
--- a/third_party/WebKit/Source/core/paint/ClipRect.h
+++ b/third_party/WebKit/Source/core/paint/ClipRect.h
@@ -27,6 +27,7 @@
 #define ClipRect_h
 
 #include "platform/geometry/LayoutRect.h"
+#include "platform/graphics/paint/FloatClipRect.h"
 #include "wtf/Allocator.h"
 
 namespace blink {
@@ -41,6 +42,9 @@
 
   ClipRect(const LayoutRect& rect) : m_rect(rect), m_hasRadius(false) {}
 
+  ClipRect(const FloatClipRect& rect)
+      : m_rect(LayoutRect(rect.rect())), m_hasRadius(rect.hasRadius()) {}
+
   const LayoutRect& rect() const { return m_rect; }
 
   bool hasRadius() const { return m_hasRadius; }
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
index 75febdd..cc5c551 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -105,7 +105,7 @@
   return b == a;
 }
 
-ClipRect PrePaintTreeWalk::clipRectForContext(
+FloatClipRect PrePaintTreeWalk::clipRectForContext(
     const PaintPropertyTreeBuilderContext::ContainingBlockContext& context,
     const EffectPaintPropertyNode* effect,
     const PropertyTreeState& ancestorState,
@@ -115,20 +115,16 @@
   // actually an ancestor clip. This ensures no accuracy issues due to
   // transforms applied to infinite rects.
   if (isAncestorOfOrEqualTo(context.clip, ancestorState.clip()))
-    return ClipRect(LayoutRect(LayoutRect::infiniteIntRect()));
+    return FloatClipRect();
 
   hasClip = true;
 
   PropertyTreeState localState(context.transform, context.clip, effect);
 
-  // TODO(chrishtr): remove need for this.
-  LayoutRect localRect(LayoutRect::infiniteIntRect());
+  FloatClipRect rect(
+      m_geometryMapper.sourceToDestinationClipRect(localState, ancestorState));
 
-  LayoutRect rect(m_geometryMapper
-                      .sourceToDestinationVisualRect(FloatRect(localRect),
-                                                     localState, ancestorState)
-                      .rect());
-  rect.moveBy(-ancestorPaintOffset);
+  rect.moveBy(-FloatPoint(ancestorPaintOffset));
   return rect;
 }
 
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
index a5d55411..e32f835e 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h
@@ -40,7 +40,7 @@
   // Returns the clip applied to children for the given
   // contaiing block context + effect, in the space of ancestorState adjusted
   // by ancestorPaintOffset. Sets hasClip to true if a clip was applied.
-  ClipRect clipRectForContext(
+  FloatClipRect clipRectForContext(
       const PaintPropertyTreeBuilderContext::ContainingBlockContext&,
       const EffectPaintPropertyNode*,
       const PropertyTreeState& ancestorState,
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index bfa6043..338a75d 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -332,6 +332,8 @@
   "front_end/network_conditions/module.json",
   "front_end/network_conditions/NetworkConditionsSelector.js",
   "front_end/network_conditions/networkConditionsSettingsTab.css",
+  "front_end/network_group_lookup/module.json",
+  "front_end/network_group_lookup/NetworkProductGroupLookup.js",
   "front_end/perf_ui/ChartViewport.js",
   "front_end/perf_ui/filmStripDialog.css",
   "front_end/perf_ui/filmStripView.css",
@@ -849,6 +851,7 @@
   "$resources_out_dir/cm_modes/cm_modes_module.js",
   "$resources_out_dir/emulated_devices/emulated_devices_module.js",
   "$resources_out_dir/gonzales/gonzales_module.js",
+  "$resources_out_dir/network_group_lookup/network_group_lookup_module.js",
   "$resources_out_dir/product_registry/product_registry_module.js",
   "$resources_out_dir/screencast/screencast_module.js",
 ]
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/ContentProviderBasedProject.js b/third_party/WebKit/Source/devtools/front_end/bindings/ContentProviderBasedProject.js
index be51053..a251593 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/ContentProviderBasedProject.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/ContentProviderBasedProject.js
@@ -162,9 +162,9 @@
 
   /**
    * @override
-   * @param {string} path
+   * @param {!Workspace.UISourceCode} uiSourceCode
    */
-  deleteFile(path) {
+  deleteFile(uiSourceCode) {
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/externs.js b/third_party/WebKit/Source/devtools/front_end/externs.js
index 22849bd..524ed16 100644
--- a/third_party/WebKit/Source/devtools/front_end/externs.js
+++ b/third_party/WebKit/Source/devtools/front_end/externs.js
@@ -875,6 +875,8 @@
 /** @type {!Object} */
 var NetworkConditions = {};
 /** @type {!Object} */
+var NetworkGroupLookup = {};
+/** @type {!Object} */
 var PerfUI = {};
 /** @type {!Object} */
 var Persistence = {};
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector.json b/third_party/WebKit/Source/devtools/front_end/inspector.json
index 20aa652..cfff81c 100644
--- a/third_party/WebKit/Source/devtools/front_end/inspector.json
+++ b/third_party/WebKit/Source/devtools/front_end/inspector.json
@@ -17,6 +17,7 @@
         { "name": "services", "type": "autostart" },
         { "name": "elements", "condition": "!v8only" },
         { "name": "network", "condition": "!v8only" },
+        { "name": "network_group_lookup", "condition": "!v8only", "type": "remote" },
         { "name": "sources" },
         { "name": "timeline", "condition": "!v8only" },
         { "name": "timeline_model", "condition": "!v8only" },
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
index b408c94d..e83ecc0 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -57,6 +57,9 @@
     this._durationCalculator = new Network.NetworkTransferDurationCalculator();
     this._calculator = this._timeCalculator;
 
+    /** @type {?Network.NetworkGroupLookupInterface} */
+    this._activeGroupLookup = null;
+
     /**
      * @this {Network.NetworkLogView}
      */
@@ -345,6 +348,14 @@
   }
 
   /**
+   * @param {?Network.NetworkGroupLookupInterface} grouping
+   */
+  setGrouping(grouping) {
+    this._activeGroupLookup = grouping;
+    this._invalidateAllItems();
+  }
+
+  /**
    * @param {!SDK.NetworkRequest} request
    * @return {?Network.NetworkRequestNode}
    */
@@ -846,25 +857,21 @@
 
   /**
    * @param {!Network.NetworkRequestNode} node
-   * @return {!Network.NetworkNode}
+   * @return {?Network.NetworkNode}
    */
   _parentNodeForInsert(node) {
-    if (!Runtime.experiments.isEnabled('networkGroupingRequests'))
-      return /** @type {!Network.NetworkNode} */ (this._dataGrid.rootNode());
+    if (!this._activeGroupLookup)
+      return this._dataGrid.rootNode();
 
-    var request = node.request();
-    // TODO(allada) Make this dynamic and allow multiple grouping types.
-    var groupKey = request.connectionId;
-    var group = this._nodeGroups.get(groupKey);
+    var groupName = this._activeGroupLookup.lookup(node.request());
+    if (!groupName)
+      return this._dataGrid.rootNode();
+
+    var group = this._nodeGroups.get(groupName);
     if (group)
       return group;
-
-    var parsedURL = request.url().asParsedURL();
-    var host = '';
-    if (parsedURL)
-      host = parsedURL.host;
-    group = new Network.NetworkGroupNode(this, host + ' - ' + groupKey);
-    this._nodeGroups.set(groupKey, group);
+    group = new Network.NetworkGroupNode(this, groupName);
+    this._nodeGroups.set(groupName, group);
     return group;
   }
 
@@ -1779,3 +1786,16 @@
 
 /** @typedef {function(!SDK.NetworkRequest): boolean} */
 Network.NetworkLogView.Filter;
+
+/**
+ * @interface
+ */
+Network.NetworkGroupLookupInterface = function() {};
+
+Network.NetworkGroupLookupInterface.prototype = {
+  /**
+   * @param {!SDK.NetworkRequest} request
+   * @return {?string}
+   */
+  lookup(request) {}
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
index c145cd9..f09dbed 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
@@ -67,7 +67,6 @@
     this._splitWidget.show(this.element);
 
     this._progressBarContainer = createElement('div');
-    this._createToolbarButtons();
 
     this._searchableView = new UI.SearchableView(this);
     this._searchableView.setPlaceholder(Common.UIString('Find by filename or path'));
@@ -90,6 +89,10 @@
     this._networkLogLargeRowsSetting.addChangeListener(this._toggleLargerRequests, this);
     this._networkRecordFilmStripSetting.addChangeListener(this._toggleRecordFilmStrip, this);
 
+    /** @type {!Map<string, !Runtime.Extension>} */
+    this._groupingExtensions = new Map();
+    this._createToolbarButtons();
+
     this._toggleRecord(true);
     this._toggleShowOverview();
     this._toggleLargerRequests();
@@ -179,9 +182,44 @@
     this._panelToolbar.appendToolbarItem(this._createBlockedURLsButton());
     this._panelToolbar.appendToolbarItem(NetworkConditions.NetworkConditionsSelector.createOfflineToolbarCheckbox());
     this._panelToolbar.appendToolbarItem(this._createNetworkConditionsSelect());
+
+    this._setupGroupingCombo();
+
     this._panelToolbar.appendToolbarItem(new UI.ToolbarItem(this._progressBarContainer));
   }
 
+  _setupGroupingCombo() {
+    var extensions = self.runtime.extensions(Network.NetworkGroupLookupInterface);
+    if (!extensions.length)
+      return;
+
+    var setting = Common.settings.createSetting('networkGrouping', '');
+    /** @type {!Array<!{value: string, label: string, title: string}>} */
+    var options = [{value: '', label: Common.UIString('No grouping'), title: Common.UIString('No grouping')}];
+
+    extensions.forEach(extension => {
+      var identifier = extension.descriptor()['id'];
+      this._groupingExtensions.set(identifier, extension);
+      options.push({value: identifier, label: extension.title(), title: extension.title()});
+    });
+    this._panelToolbar.appendToolbarItem(new UI.ToolbarSettingComboBox(options, setting, Common.UIString('Group by')));
+    setting.addChangeListener(event => this._groupingChanged(/** @type {string} */ (event.data)));
+    this._groupingChanged(setting.get());
+  }
+
+  /**
+   * @param {string} identifier
+   */
+  _groupingChanged(identifier) {
+    var extension = this._groupingExtensions.get(identifier);
+    if (extension) {
+      extension.instance().then(
+          grouping => this._networkLogView.setGrouping(/** @type {?Network.NetworkGroupLookupInterface} */ (grouping)));
+    } else {
+      this._networkLogView.setGrouping(null);
+    }
+  }
+
   /**
    * @return {!UI.ToolbarItem}
    */
diff --git a/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js b/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js
new file mode 100644
index 0000000..e8594675
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/network_group_lookup/NetworkProductGroupLookup.js
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+/**
+ * @implements {Network.NetworkGroupLookupInterface}
+ */
+NetworkGroupLookup.NetworkProductGroupLookup = class {
+  /**
+   * @override
+   * @param {!SDK.NetworkRequest} request
+   * @return {?string}
+   */
+  lookup(request) {
+    return ProductRegistry.nameForUrl(request.parsedURL);
+  }
+};
diff --git a/third_party/WebKit/Source/devtools/front_end/network_group_lookup/module.json b/third_party/WebKit/Source/devtools/front_end/network_group_lookup/module.json
new file mode 100644
index 0000000..6da0180
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/network_group_lookup/module.json
@@ -0,0 +1,19 @@
+{
+    "extensions": [
+        {
+          "type": "@Network.NetworkGroupLookupInterface",
+          "className": "NetworkGroupLookup.NetworkProductGroupLookup",
+          "title": "Product",
+          "id": "product"
+        }
+    ],
+    "dependencies": [
+        "network",
+        "product_registry",
+        "sdk"
+    ],
+    "experiment": "networkGroupingRequests",
+    "scripts": [
+        "NetworkProductGroupLookup.js"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemWorkspaceBinding.js b/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemWorkspaceBinding.js
index fec928ab..22a2ec40 100644
--- a/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemWorkspaceBinding.js
+++ b/third_party/WebKit/Source/devtools/front_end/persistence/FileSystemWorkspaceBinding.js
@@ -542,11 +542,12 @@
 
   /**
    * @override
-   * @param {string} path
+   * @param {!Workspace.UISourceCode} uiSourceCode
    */
-  deleteFile(path) {
-    this._fileSystem.deleteFile(path);
-    this.removeUISourceCode(path);
+  deleteFile(uiSourceCode) {
+    var relativePath = this._filePathForUISourceCode(uiSourceCode);
+    this._fileSystem.deleteFile(relativePath);
+    this.removeUISourceCode(uiSourceCode.url());
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js b/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js
index 2cbd3f1..edbbdff0 100644
--- a/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js
+++ b/third_party/WebKit/Source/devtools/front_end/product_registry/ProductNameForURL.js
@@ -33,4 +33,4 @@
 };
 
 /** @type {!Map<string, !{url: string, name: string, exact: boolean}>} */
-ProductRegistry._productsByDomain;
+ProductRegistry._productsByDomain = new Map();
diff --git a/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js b/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js
index 38d66abb..ca8b6ca 100644
--- a/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js
@@ -121,12 +121,9 @@
   }
 
   /**
-   * @param {string} url
+   * @param {!Workspace.UISourceCode} uiSourceCode
    */
-  deleteScriptSnippet(url) {
-    var uiSourceCode = this._project.uiSourceCodeForURL(url);
-    if (!uiSourceCode)
-      return;
+  deleteScriptSnippet(uiSourceCode) {
     var snippetId = this._snippetIdForUISourceCode.get(uiSourceCode) || '';
     var snippet = this._snippetStorage.snippetForId(snippetId);
     if (!snippet)
@@ -612,10 +609,10 @@
 
   /**
    * @override
-   * @param {string} url
+   * @param {!Workspace.UISourceCode} uiSourceCode
    */
-  deleteFile(url) {
-    this._model.deleteScriptSnippet(url);
+  deleteFile(uiSourceCode) {
+    this._model.deleteScriptSnippet(uiSourceCode);
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
index b6babd0..0a517f82 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -615,7 +615,7 @@
   _handleContextMenuDelete(uiSourceCode) {
     var shouldDelete = window.confirm(Common.UIString('Are you sure you want to delete this file?'));
     if (shouldDelete)
-      uiSourceCode.project().deleteFile(uiSourceCode.url());
+      uiSourceCode.project().deleteFile(uiSourceCode);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
index cf37c690..4fa5b55 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
@@ -166,7 +166,7 @@
   }
 
   remove() {
-    this._project.deleteFile(this.url());
+    this._project.deleteFile(this);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js b/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js
index 28539df..a7208aa 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/Workspace.js
@@ -147,9 +147,9 @@
   createFile(path, name, content, callback) {},
 
   /**
-   * @param {string} path
+   * @param {!Workspace.UISourceCode} uiSourceCode
    */
-  deleteFile(path) {},
+  deleteFile(uiSourceCode) {},
 
   remove() {},
 
diff --git a/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp b/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp
index ed923d4..0fc83ca 100644
--- a/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp
+++ b/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp
@@ -37,6 +37,7 @@
 #include "modules/quota/StorageErrorCallback.h"
 #include "modules/quota/StorageQuotaCallback.h"
 #include "modules/quota/StorageUsageCallback.h"
+#include "platform/WebTaskRunner.h"
 #include "public/platform/WebTraceLocation.h"
 
 namespace blink {
@@ -53,10 +54,10 @@
   DeprecatedStorageQuota* storageQuota = getStorageQuota(storageType);
   if (!storageQuota) {
     // Unknown storage type is requested.
-    scriptState->getExecutionContext()->postTask(
-        TaskType::MiscPlatformAPI, BLINK_FROM_HERE,
-        StorageErrorCallback::createSameThreadTask(errorCallback,
-                                                   NotSupportedError));
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI,
+                          scriptState->getExecutionContext())
+        ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
+                                        errorCallback, NotSupportedError));
     return;
   }
   storageQuota->queryUsageAndQuota(scriptState, successCallback, errorCallback);
@@ -72,10 +73,10 @@
   DeprecatedStorageQuota* storageQuota = getStorageQuota(storageType);
   if (!storageQuota) {
     // Unknown storage type is requested.
-    scriptState->getExecutionContext()->postTask(
-        TaskType::MiscPlatformAPI, BLINK_FROM_HERE,
-        StorageErrorCallback::createSameThreadTask(errorCallback,
-                                                   NotSupportedError));
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI,
+                          scriptState->getExecutionContext())
+        ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
+                                        errorCallback, NotSupportedError));
     return;
   }
   storageQuota->requestQuota(scriptState, newQuotaInBytes, successCallback,
diff --git a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
index 98d4669..f24868ab 100644
--- a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
+++ b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
@@ -39,6 +39,7 @@
 #include "modules/quota/StorageQuotaClient.h"
 #include "modules/quota/StorageUsageCallback.h"
 #include "platform/StorageQuotaCallbacks.h"
+#include "platform/WebTaskRunner.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/Platform.h"
@@ -61,17 +62,17 @@
   if (storageType != WebStorageQuotaTypeTemporary &&
       storageType != WebStorageQuotaTypePersistent) {
     // Unknown storage type is requested.
-    executionContext->postTask(TaskType::MiscPlatformAPI, BLINK_FROM_HERE,
-                               StorageErrorCallback::createSameThreadTask(
-                                   errorCallback, NotSupportedError));
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+        ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
+                                        errorCallback, NotSupportedError));
     return;
   }
 
   SecurityOrigin* securityOrigin = executionContext->getSecurityOrigin();
   if (securityOrigin->isUnique()) {
-    executionContext->postTask(TaskType::MiscPlatformAPI, BLINK_FROM_HERE,
-                               StorageErrorCallback::createSameThreadTask(
-                                   errorCallback, NotSupportedError));
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+        ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
+                                        errorCallback, NotSupportedError));
     return;
   }
 
@@ -94,17 +95,17 @@
   if (storageType != WebStorageQuotaTypeTemporary &&
       storageType != WebStorageQuotaTypePersistent) {
     // Unknown storage type is requested.
-    executionContext->postTask(TaskType::MiscPlatformAPI, BLINK_FROM_HERE,
-                               StorageErrorCallback::createSameThreadTask(
-                                   errorCallback, NotSupportedError));
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+        ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
+                                        errorCallback, NotSupportedError));
     return;
   }
 
   StorageQuotaClient* client = StorageQuotaClient::from(executionContext);
   if (!client) {
-    executionContext->postTask(TaskType::MiscPlatformAPI, BLINK_FROM_HERE,
-                               StorageErrorCallback::createSameThreadTask(
-                                   errorCallback, NotSupportedError));
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+        ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
+                                        errorCallback, NotSupportedError));
     return;
   }
 
diff --git a/third_party/WebKit/Source/modules/quota/StorageErrorCallback.cpp b/third_party/WebKit/Source/modules/quota/StorageErrorCallback.cpp
index ecd7f60..c6b2d414 100644
--- a/third_party/WebKit/Source/modules/quota/StorageErrorCallback.cpp
+++ b/third_party/WebKit/Source/modules/quota/StorageErrorCallback.cpp
@@ -34,11 +34,10 @@
 
 namespace blink {
 
-std::unique_ptr<ExecutionContextTask>
-StorageErrorCallback::createSameThreadTask(StorageErrorCallback* callback,
-                                           ExceptionCode ec) {
-  return blink::createSameThreadTask(&StorageErrorCallback::run,
-                                     wrapPersistent(callback), ec);
+std::unique_ptr<WTF::Closure> StorageErrorCallback::createSameThreadTask(
+    StorageErrorCallback* callback,
+    ExceptionCode ec) {
+  return WTF::bind(&StorageErrorCallback::run, wrapPersistent(callback), ec);
 }
 
 void StorageErrorCallback::run(StorageErrorCallback* callback,
diff --git a/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h b/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h
index 194f5489..6b2792f 100644
--- a/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h
+++ b/third_party/WebKit/Source/modules/quota/StorageErrorCallback.h
@@ -32,8 +32,6 @@
 #define StorageErrorCallback_h
 
 #include "core/dom/ExceptionCode.h"
-#include "core/dom/ExecutionContext.h"
-#include "core/dom/ExecutionContextTask.h"
 #include "modules/ModulesExport.h"
 #include "platform/heap/Handle.h"
 #include "wtf/Forward.h"
@@ -49,8 +47,9 @@
   DEFINE_INLINE_VIRTUAL_TRACE() {}
   virtual void handleEvent(DOMError*) = 0;
 
-  MODULES_EXPORT static std::unique_ptr<ExecutionContextTask>
-  createSameThreadTask(StorageErrorCallback*, ExceptionCode);
+  MODULES_EXPORT static std::unique_ptr<WTF::Closure> createSameThreadTask(
+      StorageErrorCallback*,
+      ExceptionCode);
 
  private:
   static void run(StorageErrorCallback*, ExceptionCode);
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index a750d224..5b469fe 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1719,6 +1719,7 @@
     "graphics/paint/DisplayItemClientTest.cpp",
     "graphics/paint/DisplayItemListTest.cpp",
     "graphics/paint/DisplayItemTest.cpp",
+    "graphics/paint/FloatClipRectTest.cpp",
     "graphics/paint/GeometryMapperTest.cpp",
     "graphics/paint/PaintChunkTest.cpp",
     "graphics/paint/PaintChunkerTest.cpp",
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
index 3660f788..bf8a9a3 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -410,7 +410,9 @@
   }
 }
 
-void OffscreenCanvasFrameDispatcherImpl::WillDrawSurface() {
+void OffscreenCanvasFrameDispatcherImpl::WillDrawSurface(
+    const cc::LocalSurfaceId& localSurfaceId,
+    ::gfx::mojom::blink::RectPtr damageRect) {
   // TODO(fsamuel, staraz): Implement this.
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
index cb197b7..94331a5 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
@@ -43,7 +43,8 @@
   void DidReceiveCompositorFrameAck() final;
   void OnBeginFrame(const cc::BeginFrameArgs&) final;
   void ReclaimResources(const cc::ReturnedResourceArray& resources) final;
-  void WillDrawSurface() final;
+  void WillDrawSurface(const cc::LocalSurfaceId&,
+                       ::gfx::mojom::blink::RectPtr damageRect) final;
 
   // This enum is used in histogram, so it should be append-only.
   enum OffscreenCanvasCommitType {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FloatClipRect.h b/third_party/WebKit/Source/platform/graphics/paint/FloatClipRect.h
index bb09206..cf663ef 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/FloatClipRect.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/FloatClipRect.h
@@ -35,8 +35,8 @@
   }
 
   bool hasRadius() const { return m_hasRadius; }
-  void setHasRadius(bool hasRadius) {
-    m_hasRadius = hasRadius;
+  void setHasRadius() {
+    m_hasRadius = true;
     m_isInfinite = false;
   }
 
@@ -45,6 +45,12 @@
     m_isInfinite = false;
   }
 
+  void moveBy(const FloatPoint& offset) {
+    if (m_isInfinite)
+      return;
+    m_rect.moveBy(offset);
+  }
+
   bool isInfinite() const { return m_isInfinite; }
 
  private:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/FloatClipRectTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/FloatClipRectTest.cpp
new file mode 100644
index 0000000..7b14dcd1d
--- /dev/null
+++ b/third_party/WebKit/Source/platform/graphics/paint/FloatClipRectTest.cpp
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/graphics/paint/FloatClipRect.h"
+
+#include "platform/geometry/FloatRect.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class FloatClipRectTest : public ::testing::Test {
+ public:
+};
+
+TEST_F(FloatClipRectTest, InfinitRect) {
+  FloatClipRect rect;
+  EXPECT_TRUE(rect.isInfinite());
+
+  FloatClipRect rect2((FloatRect(1, 2, 3, 4)));
+  EXPECT_FALSE(rect2.isInfinite());
+}
+
+TEST_F(FloatClipRectTest, MoveBy) {
+  FloatClipRect rect;
+  rect.moveBy(FloatPoint(1, 2));
+  EXPECT_EQ(rect.rect(), FloatClipRect().rect());
+}
+
+TEST_F(FloatClipRectTest, SetRect) {
+  FloatClipRect rect;
+  rect.setRect(FloatRect(1, 2, 3, 4));
+  EXPECT_FALSE(rect.isInfinite());
+  EXPECT_EQ(FloatRect(1, 2, 3, 4), rect.rect());
+}
+
+TEST_F(FloatClipRectTest, SetHasRadius) {
+  FloatClipRect rect;
+  rect.setHasRadius();
+  EXPECT_FALSE(rect.isInfinite());
+  EXPECT_TRUE(rect.hasRadius());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
index a74c867..00d8f6f 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
@@ -149,12 +149,14 @@
         success);
     hasRadius |= result.hasRadius();
     if (!success) {
-      result.setHasRadius(hasRadius);
+      if (hasRadius)
+        result.setHasRadius();
       return result;
     }
 
     result = effect->mapRect(result.rect());
-    result.setHasRadius(hasRadius);
+    if (hasRadius)
+      result.setHasRadius();
     lastTransformAndClipState = transformAndClipState;
   }
 
@@ -164,7 +166,8 @@
   result = sourceToDestinationVisualRectInternal(
       result.rect(), lastTransformAndClipState, finalTransformAndClipState,
       success);
-  result.setHasRadius(hasRadius || result.hasRadius());
+  if (hasRadius || result.hasRadius())
+    result.setHasRadius();
   return result;
 }
 
@@ -348,7 +351,7 @@
     FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect());
     clip.intersect(mappedRect);
     if ((*it)->clipRect().isRounded())
-      clip.setHasRadius(true);
+      clip.setHasRadius();
     clipCache.set(*it, clip);
   }
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index f4a913e..528b271d 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -365,7 +365,7 @@
   FloatRect output(10, 10, 50, 50);
 
   FloatClipRect expectedClip(clip->clipRect().rect());
-  expectedClip.setHasRadius(true);
+  expectedClip.setHasRadius();
 
   bool hasRadius = true;
   CHECK_MAPPINGS(input,   // Input
@@ -400,7 +400,7 @@
   FloatRect output1(10, 10, 30, 40);
 
   FloatClipRect clipRect(clip1->clipRect().rect());
-  clipRect.setHasRadius(true);
+  clipRect.setHasRadius();
 
   bool hasRadius = true;
   CHECK_MAPPINGS(input,    // Input
@@ -453,7 +453,7 @@
   FloatRect output1(10, 10, 30, 40);
 
   FloatClipRect expectedClip(clip2->clipRect().rect());
-  expectedClip.setHasRadius(true);
+  expectedClip.setHasRadius();
 
   bool hasRadius = true;
   CHECK_MAPPINGS(input,    // Input
diff --git a/third_party/WebKit/Source/platform/loader/fetch/MockFetchContext.h b/third_party/WebKit/Source/platform/loader/fetch/MockFetchContext.h
index dc7817a..b3b6b32 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/MockFetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/MockFetchContext.h
@@ -21,8 +21,6 @@
 struct ResourceLoaderOptions;
 
 // Mocked FetchContext for testing.
-// TODO(toyoshim): Use this class by other unit tests that currently have own
-// mocked FetchContext respectively.
 class MockFetchContext : public FetchContext {
  public:
   enum LoadPolicy {
diff --git a/third_party/node/node.py b/third_party/node/node.py
index e2e9a37..0194f561 100755
--- a/third_party/node/node.py
+++ b/third_party/node/node.py
@@ -5,6 +5,8 @@
 
 from os import path as os_path
 import platform
+import subprocess
+import sys
 
 
 def GetBinaryPath():
@@ -13,3 +15,16 @@
     'Linux': ('linux', 'node-linux-x64', 'bin', 'node'),
     'Windows': ('win', 'node.exe'),
   }[platform.system()])
+
+
+def RunNode(cmd_parts, stdout=None):
+  cmd = " ".join([GetBinaryPath()] + cmd_parts)
+  process = subprocess.Popen(
+      cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+  stdout, stderr = process.communicate()
+
+  if stderr:
+    print >> sys.stderr, '%s failed: %s' % (cmd, stderr)
+    raise
+
+  return stdout
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 0886fdfd..77a98b9 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -787,6 +787,14 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="Accel_SelectNumberedTab">
+  <owner>calamity@chromium.org</owner>
+  <description>
+    Logged when a user press Ctrl/Command + 1-9 to change to a tab in a browser
+    window.
+  </description>
+</action>
+
 <action name="Accel_SelectPreviousTab">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c07837d..a17139a2 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -97253,6 +97253,7 @@
   <int value="-535208779" label="enable-native-cups"/>
   <int value="-531810064" label="saveas-menu-label"/>
   <int value="-528927088" label="AutofillCreditCardPopupLayout:disabled"/>
+  <int value="-528149352" label="WebRtcUseEchoCanceller3:enabled"/>
   <int value="-519960638" label="enable-site-engagement-service"/>
   <int value="-518104091" label="NewAudioRenderingMixingStrategy:enabled"/>
   <int value="-516845951" label="enable-embedded-extension-options"/>
@@ -97646,6 +97647,7 @@
   <int value="1220171692" label="SpeculativeLaunchServiceWorker:enabled"/>
   <int value="1220464509" label="enable-first-run-ui-transitions"/>
   <int value="1221559505" label="enable-spelling-feedback-field-trial"/>
+  <int value="1222017136" label="WebRtcUseEchoCanceller3:disabled"/>
   <int value="1235800887" label="V8Ignition:enabled"/>
   <int value="1237297772" label="no-pings"/>
   <int value="1242632259" label="ContentSuggestionsCategoryOrder:disabled"/>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js
index cc3508a..3a8990a7 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js
@@ -73,6 +73,8 @@
  * @return {!ImageOrientation}
  */
 ImageOrientation.fromDriveOrientation = function(rotation90) {
+  // TODO(yamaguchi): Examine the spec of Drive Orientation and share logic
+  // with |fromClockwiseRotation|. This looks (counterclockwise / 90) actually.
   switch (~~(rotation90 % 4)) {
     case 0:
       return new ImageOrientation(1, 0, 0, 1);
@@ -89,6 +91,56 @@
 };
 
 /**
+ * @param {number} rotation90 Clockwise degrees / 90.
+ * @return {!ImageOrientation}
+ */
+ImageOrientation.fromClockwiseRotation = function(rotation90) {
+  switch (~~(rotation90 % 4)) {
+    case 0:
+      return new ImageOrientation(1, 0, 0, 1);
+    case 1:
+    case -3:
+      return new ImageOrientation(0, 1, -1, 0);
+    case 2:
+    case -2:
+      return new ImageOrientation(-1, 0, 0, -1);
+    case 3:
+    case -1:
+      return new ImageOrientation(0, -1, 1, 0);
+    default:
+      console.error('Invalid orientation number.');
+      return new ImageOrientation(1, 0, 0, 1);
+  }
+};
+
+/**
+ * Builds a transformation matrix from the image transform parameters.
+ * @param {{scaleX: number, scaleY: number, rotate90: number}} transform
+ *     rotate90: clockwise degrees / 90.
+ * @return {!ImageOrientation}
+ */
+ImageOrientation.fromRotationAndScale = function(transform) {
+  var scaleX = transform.scaleX;
+  var scaleY = transform.scaleY;
+  var rotate90 = transform.rotate90;
+
+  var orientation = ImageOrientation.fromClockwiseRotation(rotate90);
+
+  // Flip X and Y.
+  // In the Files app., CSS transformations are applied like
+  // "transform: rotate(90deg) scaleX(-1)".
+  // Since the image is scaled based on the X,Y axes pinned to the original,
+  // it is equivalent to scale first and then rotate.
+  // |a c| |s_x 0 | |x|   |a*s_x c*s_y| |x|
+  // |b d| | 0 s_y| |y| = |b*s_x d*s_y| |y|
+  return new ImageOrientation(
+    orientation.a * scaleX,
+    orientation.b * scaleX,
+    orientation.c * scaleY,
+    orientation.d * scaleY);
+}
+
+/**
  * Obtains the image size after cancelling its orientation.
  * @param {number} imageWidth
  * @param {number} imageHeight
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js
index a3d9496..fd77e3b 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js
@@ -41,3 +41,52 @@
   var destinationImageData = destinationContext.getImageData(0, 0, 1, 2);
   assertArrayEquals([255, 0, 0, 100, 0, 0, 0, 100], destinationImageData.data);
 }
+
+function assertImageOrientationEquals(expected, actual, message) {
+  assertEquals(expected.a, actual.a, message);
+  assertEquals(expected.b, actual.b, message);
+  assertEquals(expected.c, actual.c, message);
+  assertEquals(expected.d, actual.d, message);
+}
+
+function testFromRotationAndScale() {
+  var rotate270 = {scaleX: 1, scaleY: 1, rotate90: -1};
+  var rotate90 = {scaleX: 1, scaleY: 1, rotate90: 1};
+  var flipX = {scaleX: -1, scaleY: 1, rotate90: 0 };
+  var flipY = {scaleX: 1, scaleY: -1, rotate90: 0 };
+  var flipBoth = {scaleX: -1, scaleY: -1, rotate90: 0};
+  var rotate180 = {scaleX: 1, scaleY: 1, rotate90: 2};
+  var flipXAndRotate90 = {scaleX: -1, scaleY: 1, rotate90: 1};
+  var flipYAndRotate90 = {scaleX: 1, scaleY: -1, rotate90: 1};
+  var rotate1080 = {scaleX: 1, scaleY: 1, rotate90: 12};
+  var flipBothAndRotate180 = {scaleX: -1, scaleY: -1, rotate90: 2};
+  /*
+   The image coordinate system is aligned to the screen. (Y+ pointing down)
+   O----> e_x                 ^
+   |           rotate 270 CW  | e'_x = (0, -1)' = (a, b)'
+   |             =====>       |
+   V e_y                      O----> e'_y = (1, 0)' = (c, d)'
+  */
+  assertImageOrientationEquals(new ImageOrientation(0, -1, 1, 0),
+      ImageOrientation.fromRotationAndScale(rotate270), 'rotate270');
+  assertImageOrientationEquals(new ImageOrientation(0, 1, -1, 0),
+      ImageOrientation.fromRotationAndScale(rotate90), 'rotate90');
+  assertImageOrientationEquals(new ImageOrientation(-1, 0, 0, 1),
+      ImageOrientation.fromRotationAndScale(flipX), 'flipX');
+  assertImageOrientationEquals(new ImageOrientation(1, 0, 0, -1),
+      ImageOrientation.fromRotationAndScale(flipY), 'flipY');
+  assertImageOrientationEquals(new ImageOrientation(-1, 0, 0, -1),
+      ImageOrientation.fromRotationAndScale(flipBoth), 'flipBoth');
+  assertImageOrientationEquals(new ImageOrientation(-1, 0, 0, -1),
+      ImageOrientation.fromRotationAndScale(rotate180), 'rotate180');
+  assertImageOrientationEquals(new ImageOrientation(0, -1, -1, 0),
+      ImageOrientation.fromRotationAndScale(flipXAndRotate90),
+      'flipXAndRotate90');
+  assertImageOrientationEquals(new ImageOrientation(0, 1, 1, 0),
+      ImageOrientation.fromRotationAndScale(flipYAndRotate90),
+      'flipYAndRotate90');
+  assertTrue(ImageOrientation.fromRotationAndScale(flipBothAndRotate180)
+      .isIdentity(), 'flipBothAndRotate180');
+  assertTrue(ImageOrientation.fromRotationAndScale(rotate1080).isIdentity(),
+      'rotate1080');
+}
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js b/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js
index 65d012f..49898f02 100644
--- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js
+++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js
@@ -460,16 +460,27 @@
                          this.metadata_.filesystem &&
                          this.metadata_.filesystem.modificationTime &&
                          this.metadata_.filesystem.modificationTime.getTime();
+  var loaderOptions = {
+      maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH,
+      maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT,
+      cache: true,
+      priority: this.priority_,
+      timestamp: modificationTime
+  };
+  if (this.metadata_ && this.metadata_.media &&
+      this.metadata_.media.imageTransform) {
+    loaderOptions.orientation = this.metadata_.media.imageTransform;
+  }
+  // Comsume the transform parameter to avoid duplicated transformation in
+  // getImage().
+  // TODO(yamaguchi): remove this line when we move the image transformation
+  // logic out of this class.
+  this.transform_ = undefined;
+
   this.taskId_ = ImageLoaderClient.loadToImage(
       this.thumbnailUrl_,
       this.image_,
-      {
-        maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH,
-        maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT,
-        cache: true,
-        priority: this.priority_,
-        timestamp: modificationTime
-      },
+      loaderOptions,
       function() {},
       function() {
         this.image_.onerror(new Event('load-error'));
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
index f972dd1..509a4b0 100644
--- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.js
@@ -169,13 +169,15 @@
       }), callback);
 }
 
-function testLoadDetachedFromExifInCavnasModeThumbnailRotate(callback) {
+function testLoadDetachedFromExifInCavnasModeThumbnailDoesNotRotate(callback) {
   ImageLoaderClient.getInstance = function() {
     return {
       load: function(url, callback, opt_option) {
         // Assert that data url is passed.
         assertTrue(/^data:/i.test(url));
-        callback({status: 'success', data: url, width: 64, height: 32});
+        // ImageLoader returns rotated image.
+        callback({status: 'success', data: generateSampleImageDataUrl(32, 64),
+            width: 32, height: 64});
       }
     };
   };
@@ -201,6 +203,7 @@
       thumbnailLoader.loadDetachedImage(resolve);
     }).then(function() {
       var image = thumbnailLoader.getImage();
+      // No need to rotate by loadDetachedImage() as it's already done.
       assertEquals(32, image.width);
       assertEquals(64, image.height);
     }), callback);
diff --git a/ui/file_manager/image_loader/image_loader.js b/ui/file_manager/image_loader/image_loader.js
index 3f26ea172..72d0f1ee 100644
--- a/ui/file_manager/image_loader/image_loader.js
+++ b/ui/file_manager/image_loader/image_loader.js
@@ -71,6 +71,9 @@
           if (typeof request.orientation === 'number') {
             request.orientation =
                 ImageOrientation.fromDriveOrientation(request.orientation);
+          } else if (request.orientation) {
+            request.orientation =
+                ImageOrientation.fromRotationAndScale(request.orientation);
           } else {
             request.orientation = new ImageOrientation(1, 0, 0, 1);
           }
@@ -127,4 +130,4 @@
   if (!ImageLoader.instance_)
     ImageLoader.instance_ = new ImageLoader();
   return ImageLoader.instance_;
-};
\ No newline at end of file
+};
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc
index 7483663..a20f011 100644
--- a/ui/gfx/color_space.cc
+++ b/ui/gfx/color_space.cc
@@ -9,6 +9,8 @@
 #include "base/lazy_instance.h"
 #include "base/synchronization/lock.h"
 #include "third_party/skia/include/core/SkColorSpace.h"
+#include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkICC.h"
 #include "ui/gfx/icc_profile.h"
 #include "ui/gfx/skia_color_space_util.h"
 #include "ui/gfx/transform.h"
@@ -199,6 +201,28 @@
 }
 
 // static
+ColorSpace ColorSpace::CreateCustom(const SkMatrix44& to_XYZD50,
+                                    const SkColorSpaceTransferFn& fn) {
+  ColorSpace result(ColorSpace::PrimaryID::CUSTOM,
+                    ColorSpace::TransferID::CUSTOM, ColorSpace::MatrixID::RGB,
+                    ColorSpace::RangeID::FULL);
+  for (int row = 0; row < 3; ++row) {
+    for (int col = 0; col < 3; ++col) {
+      result.custom_primary_matrix_[3 * row + col] = to_XYZD50.get(row, col);
+    }
+  }
+  result.custom_transfer_params_[0] = fn.fA;
+  result.custom_transfer_params_[1] = fn.fB;
+  result.custom_transfer_params_[2] = fn.fC;
+  result.custom_transfer_params_[3] = fn.fD;
+  result.custom_transfer_params_[4] = fn.fE;
+  result.custom_transfer_params_[5] = fn.fF;
+  result.custom_transfer_params_[6] = fn.fG;
+  // TODO(ccameron): Use enums for near matches to know color spaces.
+  return result;
+}
+
+// static
 ColorSpace ColorSpace::CreateSCRGBLinear() {
   return ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR, MatrixID::RGB,
                     RangeID::FULL);
@@ -343,6 +367,34 @@
   return SkColorSpace::MakeRGB(fn, to_xyz_d50);
 }
 
+bool ColorSpace::GetICCProfile(ICCProfile* icc_profile) const {
+  if (!IsValid())
+    return false;
+
+  // If this was created from an ICC profile, retrieve that exact profile.
+  ICCProfile result;
+  if (ICCProfile::FromId(icc_profile_id_, false, icc_profile))
+    return true;
+
+  // Otherwise, construct an ICC profile based on the best approximated
+  // primaries and matrix.
+  SkMatrix44 to_XYZD50_matrix;
+  GetPrimaryMatrix(&to_XYZD50_matrix);
+  SkColorSpaceTransferFn fn;
+  if (!GetTransferFunction(&fn)) {
+    DLOG(ERROR) << "Failed to get ColorSpace transfer function for ICCProfile.";
+    return false;
+  }
+  sk_sp<SkData> data = SkICC::WriteToICC(fn, to_XYZD50_matrix);
+  if (!data) {
+    DLOG(ERROR) << "Failed to create SkICC.";
+    return false;
+  }
+  *icc_profile = ICCProfile::FromData(data->data(), data->size());
+  DCHECK(icc_profile->IsValid());
+  return true;
+}
+
 void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const {
   SkColorSpacePrimaries primaries = {0};
   switch (primaries_) {
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h
index 6e424f7..117f1a75 100644
--- a/ui/gfx/color_space.h
+++ b/ui/gfx/color_space.h
@@ -144,6 +144,13 @@
   // range, and unspecified spaces.
   sk_sp<SkColorSpace> ToSkColorSpace() const;
 
+  // Populate |icc_profile| with an ICC profile that represents this color
+  // space. Returns false if this space is not representable. This ICC profile
+  // will be constructed ignoring the range adjust and transfer matrices (this
+  // is to match the IOSurface interface which takes the ICC profile and range
+  // and transfer matrices separately).
+  bool GetICCProfile(ICCProfile* icc_profile) const;
+
   void GetPrimaryMatrix(SkMatrix44* to_XYZD50) const;
   bool GetTransferFunction(SkColorSpaceTransferFn* fn) const;
   bool GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const;
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc
index e88f3a5..933252a 100644
--- a/ui/gfx/color_transform.cc
+++ b/ui/gfx/color_transform.cc
@@ -277,6 +277,11 @@
                                              ColorTransform::Intent intent);
   void Simplify();
 
+  // Retrieve the ICC profile from which |color_space| was created, only if that
+  // is a more precise representation of the color space than the primaries and
+  // transfer function in |color_space|.
+  ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space);
+
   std::list<std::unique_ptr<ColorTransformStep>> steps_;
 };
 
@@ -653,9 +658,10 @@
   ScopedQcmsProfile to_;
 };
 
-ScopedQcmsProfile GetQCMSProfileIfAvailable(const ColorSpace& color_space) {
-  ICCProfile icc_profile = ICCProfile::FromColorSpace(color_space);
-  if (icc_profile.GetData().empty())
+ScopedQcmsProfile ColorTransformInternal::GetQCMSProfileIfNecessary(
+    const ColorSpace& color_space) {
+  ICCProfile icc_profile;
+  if (!ICCProfile::FromId(color_space.icc_profile_id_, true, &icc_profile))
     return nullptr;
   return ScopedQcmsProfile(qcms_profile_from_memory(
       icc_profile.GetData().data(), icc_profile.GetData().size()));
@@ -690,8 +696,8 @@
   if (!from.IsValid())
     return;
 
-  ScopedQcmsProfile from_profile = GetQCMSProfileIfAvailable(from);
-  ScopedQcmsProfile to_profile = GetQCMSProfileIfAvailable(to);
+  ScopedQcmsProfile from_profile = GetQCMSProfileIfNecessary(from);
+  ScopedQcmsProfile to_profile = GetQCMSProfileIfNecessary(to);
   bool has_from_profile = !!from_profile;
   bool has_to_profile = !!to_profile;
 
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc
index e566ff9..36e3ab2 100644
--- a/ui/gfx/color_transform_unittest.cc
+++ b/ui/gfx/color_transform_unittest.cc
@@ -97,8 +97,8 @@
   std::unique_ptr<ColorTransform> toxyzd50_fromicc(
       ColorTransform::NewColorTransform(
           srgb_fromicc, xyzd50, ColorTransform::Intent::INTENT_ABSOLUTE));
-  // This will have 1 step, namely, the QCMS transform.
-  EXPECT_EQ(toxyzd50_fromicc->NumberOfStepsForTesting(), 1u);
+  // This will be converted to a transfer function and then linear transform.
+  EXPECT_EQ(toxyzd50_fromicc->NumberOfStepsForTesting(), 2u);
   toxyzd50_fromicc->Transform(&value_fromicc, 1);
 
   std::unique_ptr<ColorTransform> toxyzd50_default(
diff --git a/ui/gfx/icc_profile.cc b/ui/gfx/icc_profile.cc
index 2635586..9f04bd8 100644
--- a/ui/gfx/icc_profile.cc
+++ b/ui/gfx/icc_profile.cc
@@ -9,7 +9,6 @@
 #include "base/containers/mru_cache.h"
 #include "base/lazy_instance.h"
 #include "base/synchronization/lock.h"
-#include "third_party/skia/include/core/SkData.h"
 #include "third_party/skia/include/core/SkICC.h"
 #include "ui/gfx/color_transform.h"
 
@@ -57,6 +56,10 @@
   return !(*this == other);
 }
 
+bool ICCProfile::IsValid() const {
+  return successfully_parsed_by_sk_icc_;
+}
+
 // static
 ICCProfile ICCProfile::FromData(const void* data, size_t size) {
   return FromDataWithId(data, size, 0);
@@ -107,43 +110,6 @@
 #endif
 
 // static
-ICCProfile ICCProfile::FromColorSpace(const gfx::ColorSpace& color_space) {
-  if (color_space == gfx::ColorSpace())
-    return ICCProfile();
-
-  // If |color_space| was created from an ICC profile, retrieve that exact
-  // profile.
-  if (color_space.icc_profile_id_) {
-    Cache& cache = g_cache.Get();
-    base::AutoLock lock(cache.lock);
-    auto found = cache.id_to_icc_profile_mru.Get(color_space.icc_profile_id_);
-    if (found != cache.id_to_icc_profile_mru.end())
-      return found->second;
-  }
-
-  // Otherwise, construct an ICC profile based on the best approximated
-  // primaries and matrix.
-  SkMatrix44 to_XYZD50_matrix;
-  color_space.GetPrimaryMatrix(&to_XYZD50_matrix);
-  SkColorSpaceTransferFn fn;
-  if (!color_space.GetTransferFunction(&fn)) {
-    DLOG(ERROR) << "Failed to get ColorSpace transfer function for ICCProfile.";
-    return ICCProfile();
-  }
-
-  sk_sp<SkData> data = SkICC::WriteToICC(fn, to_XYZD50_matrix);
-  if (!data) {
-    DLOG(ERROR) << "Failed to create SkICC.";
-    return ICCProfile();
-  }
-
-  // gfx::ColorTransform assumes that this will return an empty profile for any
-  // color space that was not constructed from an ICC profile.
-  // TODO(ccameron): Fix this assumption.
-  // return FromData(data->data(), data->size());
-  return ICCProfile();
-}
-
 const std::vector<char>& ICCProfile::GetData() const {
   return data_;
 }
@@ -161,6 +127,28 @@
   return color_space_;
 }
 
+// static
+bool ICCProfile::FromId(uint64_t id,
+                        bool only_if_needed,
+                        ICCProfile* icc_profile) {
+  if (!id)
+    return false;
+
+  Cache& cache = g_cache.Get();
+  base::AutoLock lock(cache.lock);
+
+  auto found = cache.id_to_icc_profile_mru.Get(id);
+  if (found == cache.id_to_icc_profile_mru.end())
+    return false;
+
+  const ICCProfile& found_icc_profile = found->second;
+  if (found_icc_profile.color_space_is_accurate_ && only_if_needed)
+    return false;
+
+  *icc_profile = found_icc_profile;
+  return true;
+}
+
 void ICCProfile::ComputeColorSpaceAndCache() {
   if (!id_)
     return;
@@ -172,55 +160,47 @@
     auto found = cache.id_to_icc_profile_mru.Get(id_);
     if (found != cache.id_to_icc_profile_mru.end()) {
       color_space_ = found->second.color_space_;
+      successfully_parsed_by_sk_icc_ =
+          found->second.successfully_parsed_by_sk_icc_;
       return;
     }
   }
 
-  // Compute the color space.
-  color_space_ = gfx::ColorSpace(
-      ColorSpace::PrimaryID::CUSTOM, ColorSpace::TransferID::CUSTOM,
-      ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
-  color_space_.icc_profile_id_ = id_;
-  color_space_.icc_profile_sk_color_space_ =
-      SkColorSpace::MakeICC(data_.data(), data_.size());
-
+  color_space_is_accurate_ = true;
+  SkMatrix44 to_XYZD50_matrix;
+  SkColorSpaceTransferFn fn;
   sk_sp<SkICC> sk_icc = SkICC::Make(data_.data(), data_.size());
   if (sk_icc) {
-    bool result;
-    SkMatrix44 to_XYZD50_matrix;
-    result = sk_icc->toXYZD50(&to_XYZD50_matrix);
-    if (result) {
-      for (int row = 0; row < 3; ++row) {
-        for (int col = 0; col < 3; ++col) {
-          color_space_.custom_primary_matrix_[3 * row + col] =
-              to_XYZD50_matrix.get(row, col);
-        }
-      }
-    } else {
+    successfully_parsed_by_sk_icc_ = true;
+    if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) {
       // Just say that the primaries were the sRGB primaries if we can't
       // extract them.
-      color_space_.primaries_ = ColorSpace::PrimaryID::BT709;
+      gfx::ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_matrix);
+      color_space_is_accurate_ = false;
       DLOG(ERROR) << "Unable to handle ICCProfile primaries.";
     }
-    SkColorSpaceTransferFn fn;
-    result = sk_icc->isNumericalTransferFn(&fn);
-    if (result) {
-      color_space_.custom_transfer_params_[0] = fn.fA;
-      color_space_.custom_transfer_params_[1] = fn.fB;
-      color_space_.custom_transfer_params_[2] = fn.fC;
-      color_space_.custom_transfer_params_[3] = fn.fD;
-      color_space_.custom_transfer_params_[4] = fn.fE;
-      color_space_.custom_transfer_params_[5] = fn.fF;
-      color_space_.custom_transfer_params_[6] = fn.fG;
-    } else {
+    if (!sk_icc->isNumericalTransferFn(&fn)) {
       // Just say that the transfer function was sRGB if we cannot read it.
       // TODO(ccameron): Use a least squares approximation of the transfer
       // function when it is not numerical.
-      color_space_.transfer_ = ColorSpace::TransferID::IEC61966_2_1;
+      gfx::ColorSpace::CreateSRGB().GetTransferFunction(&fn);
+      color_space_is_accurate_ = false;
       DLOG(ERROR) << "Unable to handle ICCProfile transfer function.";
     }
+  } else {
+    successfully_parsed_by_sk_icc_ = false;
+    gfx::ColorSpace::CreateSRGB().GetPrimaryMatrix(&to_XYZD50_matrix);
+    gfx::ColorSpace::CreateSRGB().GetTransferFunction(&fn);
+    color_space_is_accurate_ = false;
+    DLOG(ERROR) << "Unable parse ICCProfile.";
   }
 
+  // Compute the color space.
+  color_space_ = gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, fn);
+  color_space_.icc_profile_id_ = id_;
+  color_space_.icc_profile_sk_color_space_ =
+      SkColorSpace::MakeICC(data_.data(), data_.size());
+
   // Add to the cache.
   {
     Cache& cache = g_cache.Get();
diff --git a/ui/gfx/icc_profile.h b/ui/gfx/icc_profile.h
index cdbbf590..a07edf6 100644
--- a/ui/gfx/icc_profile.h
+++ b/ui/gfx/icc_profile.h
@@ -38,6 +38,9 @@
   bool operator==(const ICCProfile& other) const;
   bool operator!=(const ICCProfile& other) const;
 
+  // Returns true if this profile was successfully parsed by SkICC.
+  bool IsValid() const;
+
   // Returns the color profile of the monitor that can best represent color.
   // This profile should be used for creating content that does not know on
   // which monitor it will be displayed.
@@ -77,6 +80,12 @@
   static const uint64_t test_id_generic_rgb_;
   static const uint64_t test_id_srgb_;
 
+  // Populate |icc_profile| with the ICCProfile corresponding to id |id|. Return
+  // false if |id| is not in the cache. If |only_if_needed| is true, then return
+  // false if |color_space_is_accurate_| is true for this profile (that is, if
+  // the ICCProfile is needed to know the space precisely).
+  static bool FromId(uint64_t id, bool only_if_needed, ICCProfile* icc_profile);
+
   // This method is used to hard-code the |id_| to a specific value, and is
   // used by test methods to ensure that they don't conflict with the values
   // generated in the browser.
@@ -95,10 +104,18 @@
 
   gfx::ColorSpace color_space_;
 
+  // True if |color_space_| accurately represents this color space (this is
+  // false e.g, for lookup-based profiles).
+  bool color_space_is_accurate_ = false;
+
+  // This is set to true if SkICC successfully parsed this profile.
+  bool successfully_parsed_by_sk_icc_ = false;
+
   FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, BT709toSRGBICC);
   FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace);
   friend int ::LLVMFuzzerTestOneInput(const uint8_t*, size_t);
   friend class ColorSpace;
+  friend class ColorTransformInternal;
   friend struct IPC::ParamTraits<gfx::ICCProfile>;
 };
 
diff --git a/ui/gfx/icc_profile_unittest.cc b/ui/gfx/icc_profile_unittest.cc
index ae04314..c4e3db8 100644
--- a/ui/gfx/icc_profile_unittest.cc
+++ b/ui/gfx/icc_profile_unittest.cc
@@ -14,8 +14,10 @@
   ICCProfile icc_profile = ICCProfileForTestingColorSpin();
   ColorSpace color_space_from_icc_profile = icc_profile.GetColorSpace();
 
-  ICCProfile icc_profile_from_color_space =
-      ICCProfile::FromColorSpace(color_space_from_icc_profile);
+  ICCProfile icc_profile_from_color_space;
+  bool result =
+      color_space_from_icc_profile.GetICCProfile(&icc_profile_from_color_space);
+  EXPECT_TRUE(result);
   EXPECT_TRUE(icc_profile == icc_profile_from_color_space);
 }
 
@@ -42,10 +44,18 @@
   EXPECT_FALSE(spin_space == adobe_space);
   EXPECT_TRUE(spin_space != adobe_space);
 
-  EXPECT_TRUE(spin_profile == ICCProfile::FromColorSpace(spin_space));
-  EXPECT_FALSE(spin_profile != ICCProfile::FromColorSpace(spin_space));
-  EXPECT_FALSE(spin_profile == ICCProfile::FromColorSpace(adobe_space));
-  EXPECT_TRUE(spin_profile != ICCProfile::FromColorSpace(adobe_space));
+  ICCProfile temp;
+  bool get_icc_result = false;
+
+  get_icc_result = spin_space.GetICCProfile(&temp);
+  EXPECT_TRUE(get_icc_result);
+  EXPECT_TRUE(spin_profile == temp);
+  EXPECT_FALSE(spin_profile != temp);
+
+  get_icc_result = adobe_space.GetICCProfile(&temp);
+  EXPECT_TRUE(get_icc_result);
+  EXPECT_FALSE(spin_profile == temp);
+  EXPECT_TRUE(spin_profile != temp);
 
   EXPECT_TRUE(!!spin_space.ToSkColorSpace());
   EXPECT_TRUE(!!adobe_space.ToSkColorSpace());
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index 7b29a7d1..0c71b3b 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -354,6 +354,10 @@
   return surface_->BuffersFlipped();
 }
 
+void GLSurfaceAdapter::OnSetSwapInterval(int interval) {
+  surface_->OnSetSwapInterval(interval);
+}
+
 GLSurfaceAdapter::~GLSurfaceAdapter() {}
 
 scoped_refptr<GLSurface> InitializeGLSurfaceWithFormat(
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index 6c2e0f1..270e0ca9 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -273,6 +273,7 @@
   bool IsSurfaceless() const override;
   bool FlipsVertically() const override;
   bool BuffersFlipped() const override;
+  void OnSetSwapInterval(int interval) override;
 
   GLSurface* surface() const { return surface_.get(); }
 
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js b/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
index 205465c..fb6eb7c 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
@@ -71,7 +71,7 @@
   },
 
   /**
-   * @param {CrPolicyIndicatorType} type
+   * @param {!CrPolicyIndicatorType} type
    * @param {string} name The name associated with the indicator. See
    *     chrome.settingsPrivate.PrefObject.controlledByName
    * @param {boolean=} opt_matches For RECOMMENDED only, whether the indicator
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_behavior.js b/ui/webui/resources/cr_elements/policy/cr_policy_pref_behavior.js
index 47ca23bc..0fd367c 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_behavior.js
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_behavior.js
@@ -18,8 +18,8 @@
   },
 
   /**
-   * @param {chrome.settingsPrivate.ControlledBy} controlledBy
-   * @param {chrome.settingsPrivate.Enforcement} enforcement
+   * @param {!chrome.settingsPrivate.ControlledBy|undefined} controlledBy
+   * @param {!chrome.settingsPrivate.Enforcement|undefined} enforcement
    * @return {CrPolicyIndicatorType} The indicator type based on |controlledBy|
    *     and |enforcement|.
    */
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
index d0e0390..a1cccce1 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
@@ -19,11 +19,11 @@
   </style>
   <template>
     <iron-icon id="indicator" tabindex=0 aria-describedby="tooltip"
-        hidden$="[[!isIndicatorVisible(indicatorType)]]"
-        icon="[[getPolicyIndicatorIcon(indicatorType)]]"></iron-icon>
+        hidden$="[[!isIndicatorVisible(indicatorType_)]]"
+        icon="[[getPolicyIndicatorIcon(indicatorType_)]]"></iron-icon>
     <paper-tooltip id="tooltip" for="indicator" position="top"
         fit-to-visible-bounds>
-      [[getTooltip_(indicatorType, pref)]]
+      [[getTooltip_(indicatorType_, pref.*)]]
     </paper-tooltip>
   </template>
   <script src="cr_policy_pref_indicator.js"></script>
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
index 5526eb5..37487ec 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
@@ -22,8 +22,9 @@
     /**
      * Which indicator type to show (or NONE).
      * @type {CrPolicyIndicatorType}
+     * @private
      */
-    indicatorType: {
+    indicatorType_: {
       type: String,
       value: CrPolicyIndicatorType.NONE,
       computed: 'getIndicatorType(pref.controlledBy, pref.enforcement)',
@@ -32,20 +33,19 @@
 
   /**
    * @param {CrPolicyIndicatorType} type
-   * @param {!chrome.settingsPrivate.PrefObject} pref
    * @return {string} The tooltip text for |type|.
    * @private
    */
-  getTooltip_: function(type, pref) {
-    var matches = pref && pref.value == pref.recommendedValue;
+  getTooltip_: function(type) {
+    var matches = !!this.pref && this.pref.value == this.pref.recommendedValue;
     return this.getPolicyIndicatorTooltip(
-        type, pref.controlledByName || '', matches);
+        type, this.pref.controlledByName || '', matches);
   },
 
   /**
    * @return {boolean} Whether the policy indicator is on. Useful for testing.
    */
   isActive: function() {
-    return this.isIndicatorVisible(this.indicatorType);
+    return this.isIndicatorVisible(this.indicatorType_);
   },
 });