diff --git a/DEPS b/DEPS
index 9ad3259..43651905 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': '19769c12f2a6390893ccfc0a03a4784cebe7b180',
+  'v8_revision': '726c1912373d6c58237b2c4d8dd1e5aad2a81d7c',
   # 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.
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index a113979..137b2c3a 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -120,6 +120,10 @@
       # archives and understands bitcode (for lto builds).
       lib = "$prefix/$lld_link /lib /llvmlibthin"
       link = "$prefix/$lld_link"
+      if (host_os != "win") {
+        # See comment adding --rsp-quoting to $cl above for more information.
+        link = "$link --rsp-quoting=posix"
+      }
     } else {
       lib = "lib.exe"
       link = "link.exe"
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index 3d7f41e..51fe1c1 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -17,6 +17,7 @@
 #include "cc/test/fake_raster_source.h"
 #include "cc/test/fake_recording_source.h"
 #include "cc/test/pixel_test.h"
+#include "cc/test/test_in_process_context_provider.h"
 #include "components/viz/service/display/gl_renderer.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "media/base/video_frame.h"
@@ -302,10 +303,20 @@
     bits_per_channel = 10;
   }
 
+  viz::ResourceFormat yuv_highbit_resource_format =
+      resource_provider->YuvResourceFormat(bits_per_channel);
+
+  float multiplier = 1.0;
+
+  if (yuv_highbit_resource_format != viz::R16_EXT)
+    bits_per_channel = 8;
+  else
+    multiplier = 65535.0f / ((1 << bits_per_channel) - 1);
+
   yuv_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
                    ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
                    uv_tex_size, y_resource, u_resource, v_resource, a_resource,
-                   color_space, video_color_space, 0.0f, 1.0f,
+                   color_space, video_color_space, 0.0f, multiplier,
                    bits_per_channel);
 }
 
@@ -1304,9 +1315,35 @@
   std::unique_ptr<VideoResourceUpdater> video_resource_updater_;
 };
 
+enum class HighbitTexture {
+  Y8,
+  R16_EXT,
+};
+
 class VideoGLRendererPixelHiLoTest
     : public VideoGLRendererPixelTest,
-      public ::testing::WithParamInterface<bool> {};
+      public ::testing::WithParamInterface<
+          ::testing::tuple<bool, HighbitTexture>> {
+ public:
+  void SetSupportHighbitTexture(HighbitTexture texture) {
+    TestInProcessContextProvider* context_provider =
+        GetTestInProcessContextProvider();
+    switch (texture) {
+      case HighbitTexture::Y8:
+        break;
+      case HighbitTexture::R16_EXT:
+        context_provider->SetSupportTextureNorm16(true);
+        video_resource_updater_->SetUseR16ForTesting(true);
+        break;
+    }
+  }
+
+ private:
+  TestInProcessContextProvider* GetTestInProcessContextProvider() {
+    return static_cast<TestInProcessContextProvider*>(
+        output_surface_->context_provider());
+  }
+};
 
 TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) {
   gfx::Rect rect(this->device_viewport_size_);
@@ -1320,7 +1357,10 @@
   SharedQuadState* shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 
-  bool highbit = GetParam();
+  const bool highbit = testing::get<0>(GetParam());
+  const HighbitTexture format = testing::get<1>(GetParam());
+  SetSupportHighbitTexture(format);
+
   CreateTestYUVVideoDrawQuad_Striped(
       shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_SD_REC601,
       false, highbit, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
@@ -1349,7 +1389,10 @@
   SharedQuadState* shared_state =
       CreateTestSharedQuadState(gfx::Transform(), viewport, pass.get());
 
-  bool highbit = GetParam();
+  const bool highbit = testing::get<0>(GetParam());
+  const HighbitTexture format = testing::get<1>(GetParam());
+  SetSupportHighbitTexture(format);
+
   CreateTestYUVVideoDrawQuad_Striped(
       shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_SD_REC601,
       false, highbit, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
@@ -1418,7 +1461,12 @@
 }
 
 // First argument (test case prefix) is intentionally left empty.
-INSTANTIATE_TEST_CASE_P(, VideoGLRendererPixelHiLoTest, ::testing::Bool());
+INSTANTIATE_TEST_CASE_P(
+    ,
+    VideoGLRendererPixelHiLoTest,
+    testing::Combine(testing::Bool(),
+                     testing::Values(HighbitTexture::Y8,
+                                     HighbitTexture::R16_EXT)));
 
 TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
   gfx::Rect rect(this->device_viewport_size_);
diff --git a/cc/raster/raster_buffer_provider.cc b/cc/raster/raster_buffer_provider.cc
index 1eb0fd03..081aaf5 100644
--- a/cc/raster/raster_buffer_provider.cc
+++ b/cc/raster/raster_buffer_provider.cc
@@ -37,6 +37,7 @@
     case viz::RED_8:
     case viz::LUMINANCE_F16:
     case viz::RGBA_F16:
+    case viz::R16_EXT:
       return false;
   }
   NOTREACHED();
@@ -130,6 +131,7 @@
     case viz::RGB_565:
     case viz::RED_8:
     case viz::LUMINANCE_F16:
+    case viz::R16_EXT:
       NOTREACHED();
       return;
   }
@@ -153,6 +155,7 @@
     case viz::RED_8:
     case viz::LUMINANCE_F16:
     case viz::RGBA_F16:
+    case viz::R16_EXT:
       return false;
   }
   NOTREACHED();
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index b9ed1ba..ce45d13 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -106,6 +106,7 @@
     case viz::ETC1:
     case viz::RED_8:
     case viz::LUMINANCE_F16:
+    case viz::R16_EXT:
       NOTREACHED();
       break;
   }
@@ -127,6 +128,7 @@
     case viz::ETC1:
     case viz::RED_8:
     case viz::LUMINANCE_F16:
+    case viz::R16_EXT:
       return false;
   }
   return false;
@@ -325,6 +327,9 @@
     : default_resource_type(resource_settings.use_gpu_memory_buffer_resources
                                 ? RESOURCE_TYPE_GPU_MEMORY_BUFFER
                                 : RESOURCE_TYPE_GL_TEXTURE),
+      yuv_highbit_resource_format(resource_settings.high_bit_for_testing
+                                      ? viz::R16_EXT
+                                      : viz::LUMINANCE_8),
       enable_color_correct_rasterization(enable_color_correct_rasterization),
       delegated_sync_points_required(delegated_sync_points_required) {
   if (!compositor_context_provider) {
@@ -347,9 +352,10 @@
     yuv_resource_format = yuv_highbit_resource_format = viz::RGBA_8888;
   } else {
     yuv_resource_format = caps.texture_rg ? viz::RED_8 : viz::LUMINANCE_8;
-    yuv_highbit_resource_format = caps.texture_half_float_linear
-                                      ? viz::LUMINANCE_F16
-                                      : yuv_resource_format;
+    if (resource_settings.use_r16_texture && caps.texture_norm16)
+      yuv_highbit_resource_format = viz::R16_EXT;
+    else if (caps.texture_half_float_linear)
+      yuv_highbit_resource_format = viz::LUMINANCE_F16;
   }
 
   GLES2Interface* gl = compositor_context_provider->ContextGL();
@@ -449,6 +455,8 @@
       return caps.texture_format_etc1;
     case viz::RED_8:
       return caps.texture_rg;
+    case viz::R16_EXT:
+      return caps.texture_norm16;
     case viz::LUMINANCE_F16:
     case viz::RGBA_F16:
       return caps.texture_half_float_linear;
@@ -482,6 +490,7 @@
     case viz::RED_8:
     case viz::ETC1:
     case viz::LUMINANCE_F16:
+    case viz::R16_EXT:
       // We don't currently render into these formats. If we need to render into
       // these eventually, we should expand this logic.
       return false;
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index f27a011..f573170 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -464,12 +464,29 @@
   }
 
   std::unique_ptr<media::HalfFloatMaker> half_float_maker;
-  if (resource_provider_->YuvResourceFormat(bits_per_channel) ==
-      viz::LUMINANCE_F16) {
-    half_float_maker =
-        media::HalfFloatMaker::NewHalfFloatMaker(bits_per_channel);
-    external_resources.offset = half_float_maker->Offset();
-    external_resources.multiplier = half_float_maker->Multiplier();
+
+  switch (resource_provider_->YuvResourceFormat(bits_per_channel)) {
+    case viz::LUMINANCE_F16:
+      half_float_maker =
+          media::HalfFloatMaker::NewHalfFloatMaker(bits_per_channel);
+      external_resources.offset = half_float_maker->Offset();
+      external_resources.multiplier = half_float_maker->Multiplier();
+      break;
+    case viz::R16_EXT:
+      external_resources.multiplier = 65535.0f / ((1 << bits_per_channel) - 1);
+      external_resources.offset = 0;
+      break;
+    case viz::LUMINANCE_8:
+    case viz::RED_8:
+      break;
+    case viz::ALPHA_8:
+    case viz::RGBA_8888:
+    case viz::RGBA_4444:
+    case viz::BGRA_8888:
+    case viz::RGB_565:
+    case viz::ETC1:
+    case viz::RGBA_F16:
+      NOTREACHED();
   }
 
   for (size_t i = 0; i < plane_resources.size(); ++i) {
@@ -504,6 +521,9 @@
       // step.
       if (plane_resource.resource_format() == viz::LUMINANCE_F16) {
         needs_conversion = true;
+      } else if (plane_resource.resource_format() == viz::R16_EXT) {
+        // R16_EXT can represent 16-bit int, so we don't need a conversion step.
+        needs_conversion = false;
       } else if (bits_per_channel > 8) {
         // If bits_per_channel > 8 and we can't use viz::LUMINANCE_F16, we need
         // to shift the data down and create an 8-bit texture.
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h
index a7ac7e5..50ec17c 100644
--- a/cc/resources/video_resource_updater.h
+++ b/cc/resources/video_resource_updater.h
@@ -86,6 +86,10 @@
   VideoFrameExternalResources CreateExternalResourcesFromVideoFrame(
       scoped_refptr<media::VideoFrame> video_frame);
 
+  void SetUseR16ForTesting(bool use_r16_for_testing) {
+    use_r16_for_testing_ = use_r16_for_testing;
+  }
+
  private:
   class PlaneResource {
    public:
@@ -184,6 +188,7 @@
   const bool use_stream_video_draw_quad_;
   std::unique_ptr<media::SkCanvasVideoRenderer> video_renderer_;
   std::vector<uint8_t> upload_pixels_;
+  bool use_r16_for_testing_ = false;
 
   // Recycle resources so that we can reduce the number of allocations and
   // data transfers.
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index 8c0f6ca6..3054a23 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -105,12 +105,12 @@
 
   void SetUp() override {
     testing::Test::SetUp();
-
     shared_bitmap_manager_.reset(new SharedBitmapManagerAllocationCounter());
     resource_provider3d_ = FakeResourceProvider::Create(
-        context_provider_.get(), shared_bitmap_manager_.get());
-    resource_provider_software_ =
-        FakeResourceProvider::Create(nullptr, shared_bitmap_manager_.get());
+        context_provider_.get(), shared_bitmap_manager_.get(),
+        high_bit_for_testing_);
+    resource_provider_software_ = FakeResourceProvider::Create(
+        nullptr, shared_bitmap_manager_.get(), high_bit_for_testing_);
   }
 
   scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
@@ -251,6 +251,7 @@
   std::unique_ptr<ResourceProvider> resource_provider3d_;
   std::unique_ptr<ResourceProvider> resource_provider_software_;
   gpu::SyncToken release_sync_token_;
+  bool high_bit_for_testing_;
 };
 
 const gpu::SyncToken VideoResourceUpdaterTest::kMailboxSyncToken =
@@ -312,6 +313,40 @@
   EXPECT_NEAR(resources2.offset, 0.5, 0.1);
 }
 
+class VideoResourceUpdaterTestWithR16 : public VideoResourceUpdaterTest {
+ public:
+  VideoResourceUpdaterTestWithR16() : VideoResourceUpdaterTest() {
+    high_bit_for_testing_ = true;
+    context3d_->set_support_texture_norm16(true);
+  }
+};
+
+TEST_F(VideoResourceUpdaterTestWithR16, HighBitFrame) {
+  bool use_stream_video_draw_quad = false;
+  VideoResourceUpdater updater(context_provider_.get(),
+                               resource_provider3d_.get(),
+                               use_stream_video_draw_quad);
+  updater.SetUseR16ForTesting(true);
+  scoped_refptr<media::VideoFrame> video_frame = CreateTestHighBitFrame();
+
+  VideoFrameExternalResources resources =
+      updater.CreateExternalResourcesFromVideoFrame(video_frame);
+  EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
+
+  // Max 10-bit values as read by a sampler.
+  double max_10bit_value = ((1 << 10) - 1) / 65535.0;
+  EXPECT_NEAR(resources.multiplier * max_10bit_value, 1.0, 0.0001);
+  EXPECT_NEAR(resources.offset, 0.0, 0.1);
+
+  // Create the resource again, to test the path where the
+  // resources are cached.
+  VideoFrameExternalResources resources2 =
+      updater.CreateExternalResourcesFromVideoFrame(video_frame);
+  EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources2.type);
+  EXPECT_NEAR(resources2.multiplier * max_10bit_value, 1.0, 0.0001);
+  EXPECT_NEAR(resources2.offset, 0.0, 0.1);
+}
+
 TEST_F(VideoResourceUpdaterTest, HighBitFrameSoftwareCompositor) {
   bool use_stream_video_draw_quad = false;
   VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
diff --git a/cc/test/fake_resource_provider.h b/cc/test/fake_resource_provider.h
index e5ecb355..07e7638 100644
--- a/cc/test/fake_resource_provider.h
+++ b/cc/test/fake_resource_provider.h
@@ -18,11 +18,13 @@
  public:
   static std::unique_ptr<FakeResourceProvider> Create(
       viz::ContextProvider* context_provider,
-      viz::SharedBitmapManager* shared_bitmap_manager) {
+      viz::SharedBitmapManager* shared_bitmap_manager,
+      bool high_bit_for_testing = false) {
     viz::ResourceSettings resource_settings;
     resource_settings.texture_id_allocation_chunk_size = 1;
     resource_settings.buffer_to_texture_target_map =
         viz::DefaultBufferToTextureTargetMapForTesting();
+    resource_settings.high_bit_for_testing = high_bit_for_testing;
     return base::WrapUnique(new FakeResourceProvider(
         context_provider, shared_bitmap_manager, nullptr, nullptr, true, false,
         resource_settings));
@@ -44,11 +46,13 @@
   static std::unique_ptr<FakeResourceProvider> Create(
       viz::ContextProvider* context_provider,
       viz::SharedBitmapManager* shared_bitmap_manager,
-      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) {
+      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+      bool high_bit_for_testing = false) {
     viz::ResourceSettings resource_settings;
     resource_settings.texture_id_allocation_chunk_size = 1;
     resource_settings.buffer_to_texture_target_map =
         viz::DefaultBufferToTextureTargetMapForTesting();
+    resource_settings.high_bit_for_testing = high_bit_for_testing;
     return base::WrapUnique(new FakeResourceProvider(
         context_provider, shared_bitmap_manager, gpu_memory_buffer_manager,
         nullptr, true, false, resource_settings));
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc
index 1243e35..7ae32d0 100644
--- a/cc/test/test_context_provider.cc
+++ b/cc/test/test_context_provider.cc
@@ -28,9 +28,9 @@
 
 // Various tests rely on functionality (capabilities) enabled by these extension
 // strings.
-const char* const kExtensions[] = {"GL_EXT_stencil_wrap",
-                                   "GL_EXT_texture_format_BGRA8888",
-                                   "GL_OES_rgb8_rgba8"};
+const char* const kExtensions[] = {
+    "GL_EXT_stencil_wrap", "GL_EXT_texture_format_BGRA8888",
+    "GL_OES_rgb8_rgba8", "GL_EXT_texture_norm16"};
 
 class TestGLES2InterfaceForContextProvider : public TestGLES2Interface {
  public:
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 6c566277..1ca0806 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -110,6 +110,7 @@
   gpu::Capabilities capabilities;
   capabilities.texture_rectangle = true;
   capabilities.sync_query = true;
+  capabilities.texture_norm16 = true;
   switch (viz::PlatformColor::Format()) {
     case viz::PlatformColor::SOURCE_FORMAT_RGBA8:
       capabilities.texture_format_bgra8888 = false;
diff --git a/cc/test/test_in_process_context_provider.h b/cc/test/test_in_process_context_provider.h
index 7e3033a9..3568792b 100644
--- a/cc/test/test_in_process_context_provider.h
+++ b/cc/test/test_in_process_context_provider.h
@@ -49,6 +49,9 @@
   gpu::Capabilities ContextCapabilities() override;
   void SetLostContextCallback(
       const LostContextCallback& lost_context_callback) override;
+  void SetSupportTextureNorm16(bool support) {
+    capabilities_texture_norm16_ = support;
+  }
 
  protected:
   friend class base::RefCountedThreadSafe<TestInProcessContextProvider>;
@@ -61,6 +64,7 @@
   std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
   std::unique_ptr<viz::ContextCacheController> cache_controller_;
   base::Lock context_lock_;
+  bool capabilities_texture_norm16_ = false;
 };
 
 }  // namespace cc
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index c50893f90..ea35d2ac 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -344,6 +344,9 @@
   void set_support_texture_half_float_linear(bool support) {
     test_capabilities_.texture_half_float_linear = support;
   }
+  void set_support_texture_norm16(bool support) {
+    test_capabilities_.texture_norm16 = support;
+  }
   void set_msaa_is_slow(bool msaa_is_slow) {
     test_capabilities_.msaa_is_slow = msaa_is_slow;
   }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 78ecd75f..dcb43869 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7971,6 +7971,10 @@
         desc="Used to indicate that the speech recognition service didn't receive any voice input.">
         Please check your microphone and audio levels.
       </message>
+      <message name="IDS_NEW_TAB_VOICE_OTHER_ERROR"
+        desc="Used to indicate that the speech recognition service failed in an unknown way.">
+        Unknown error.
+      </message>
       <message name="IDS_NEW_TAB_VOICE_PERMISSION_ERROR"
         desc="Used to indicate that the speech recognition service did not get permission to use the microphone.">
         Voice search has been turned off.
diff --git a/chrome/browser/extensions/extension_navigation_throttle_unittest.cc b/chrome/browser/extensions/extension_navigation_throttle_unittest.cc
index d458e075..6b56caf 100644
--- a/chrome/browser/extensions/extension_navigation_throttle_unittest.cc
+++ b/chrome/browser/extensions/extension_navigation_throttle_unittest.cc
@@ -70,7 +70,7 @@
   void CheckTestCase(
       content::RenderFrameHost* host,
       const GURL& extension_url,
-      NavigationThrottle::ThrottleCheckResult expected_will_start_result) {
+      NavigationThrottle::ThrottleAction expected_will_start_result) {
     // First subtest: direct navigation to |extension_url|.
     std::unique_ptr<content::NavigationHandle> handle =
         content::NavigationHandle::CreateNavigationHandleForTesting(
@@ -91,7 +91,7 @@
     // TODO(nick): https://crbug.com/695421 Once PlzNavigate is enabled 100%, it
     // should be possible to support return values other than PROCEED and CANCEL
     // from ExtensionNavigationThrottle::WillRedirectRequest.
-    NavigationThrottle::ThrottleCheckResult expected_will_redirect_result =
+    NavigationThrottle::ThrottleAction expected_will_redirect_result =
         (expected_will_start_result == NavigationThrottle::PROCEED)
             ? NavigationThrottle::PROCEED
             : NavigationThrottle::CANCEL;
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index fce991e..41c3eab 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -552,12 +552,8 @@
                 unresponsive_threshold, crash_on_hang_threads);
   StartWatching(BrowserThread::IO, "IO", kSleepTime, kUnresponsiveTime,
                 unresponsive_threshold, crash_on_hang_threads);
-  StartWatching(BrowserThread::DB, "DB", kSleepTime, kUnresponsiveTime,
-                unresponsive_threshold, crash_on_hang_threads);
   StartWatching(BrowserThread::FILE, "FILE", kSleepTime, kUnresponsiveTime,
                 unresponsive_threshold, crash_on_hang_threads);
-  StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, kUnresponsiveTime,
-                unresponsive_threshold, crash_on_hang_threads);
 }
 
 // static
diff --git a/chrome/browser/resources/local_ntp/voice.js b/chrome/browser/resources/local_ntp/voice.js
index 6f8ed916..3627dea7 100644
--- a/chrome/browser/resources/local_ntp/voice.js
+++ b/chrome/browser/resources/local_ntp/voice.js
@@ -86,6 +86,7 @@
  *   networkError: string,
  *   noTranslation: string,
  *   noVoice: string,
+ *   otherError: string,
  *   permissionError: string,
  *   ready: string,
  *   tryAgain: string,
@@ -101,6 +102,7 @@
   networkError: '',
   noTranslation: '',
   noVoice: '',
+  otherError: '',
   permissionError: '',
   ready: '',
   tryAgain: '',
@@ -279,12 +281,12 @@
   fakeboxMicrophoneElem.onmouseup = function(event) {
     // If propagated, closes the overlay (click on the background).
     event.stopPropagation();
-    speech.toggleStartStop();
+    speech.start();
   };
   fakeboxMicrophoneElem.onkeydown = function(event) {
     if (!event.repeat &&
         (event.code == KEYCODE.ENTER || event.code == KEYCODE.NUMPAD_ENTER)) {
-      speech.toggleStartStop();
+      speech.start();
     }
   };
   window.addEventListener('keydown', speech.onKeyDown);
@@ -304,6 +306,7 @@
     networkError: translatedStrings.networkError,
     noTranslation: translatedStrings.noTranslation,
     noVoice: translatedStrings.noVoice,
+    otherError: translatedStrings.otherError,
     permissionError: translatedStrings.permissionError,
     ready: translatedStrings.ready,
     tryAgain: translatedStrings.tryAgain,
@@ -324,7 +327,6 @@
   speech.recognition_.continuous = false;
   speech.recognition_.interimResults = true;
   speech.recognition_.lang = getChromeUILanguage();
-  speech.recognition_.maxAlternatives = 4;
   speech.recognition_.onaudiostart = speech.handleRecognitionAudioStart_;
   speech.recognition_.onend = speech.handleRecognitionEnd_;
   speech.recognition_.onerror = speech.handleRecognitionError_;
@@ -337,9 +339,8 @@
 /**
  * Sets up the necessary states for voice search and then starts the
  * speech recognition interface.
- * @private
  */
-speech.start_ = function() {
+speech.start = function() {
   view.show();
 
   speech.resetIdleTimer_(speech.IDLE_TIMEOUT_MS_);
@@ -352,7 +353,7 @@
     speech.initWebkitSpeech_();
   }
 
-  // If |speech.start_()| is called too soon after |speech.stop_()| then the
+  // If |speech.start()| is called too soon after |speech.stop()| then the
   // recognition interface hasn't yet reset and an error occurs. In this case
   // we need to hard-reset it and reissue the |recognition_.start()| command.
   try {
@@ -364,7 +365,7 @@
       speech.recognition_.start();
       speech.currentState_ = speech.State_.STARTED;
     } catch (error2) {
-      speech.stop_();
+      speech.stop();
     }
   }
 };
@@ -372,9 +373,8 @@
 
 /**
  * Hides the overlay and resets the speech state.
- * @private
  */
-speech.stop_ = function() {
+speech.stop = function() {
   speech.recognition_.abort();
   speech.currentState_ = speech.State_.STOPPED;
   view.hide();
@@ -586,13 +586,13 @@
         event.ctrlKey || (speech.isUserAgentMac_() && event.metaKey);
     if (speech.currentState_ == speech.State_.READY &&
         event.code == KEYCODE.PERIOD && event.shiftKey && ctrlKeyPressed) {
-      speech.toggleStartStop();
+      speech.start();
     }
   } else {
     // Ensures that keyboard events are not propagated during voice input.
     event.stopPropagation();
     if (event.code == KEYCODE.ESC) {
-      speech.stop_();
+      speech.stop();
     } else if (
         (event.code == KEYCODE.ENTER || event.code == KEYCODE.NUMPAD_ENTER) &&
         speech.finalResult_) {
@@ -621,7 +621,7 @@
     case speech.State_.SPEECH_RECEIVED:
     case speech.State_.RESULT_RECEIVED:
     case speech.State_.ERROR_RECEIVED:
-      speech.stop_();
+      speech.stop();
       break;
   }
 };
@@ -638,7 +638,7 @@
   }
 
   if (document.webkitHidden) {
-    speech.stop_();
+    speech.stop();
   }
 };
 
@@ -648,7 +648,7 @@
  */
 speech.onOmniboxFocused = function() {
   if (!speech.isUiDefinitelyHidden_()) {
-    speech.stop_();
+    speech.stop();
   }
 };
 
@@ -684,7 +684,7 @@
   const queryUrl = new URL('/search', speech.googleBaseUrl_);
   queryUrl.search = searchParams;
 
-  speech.stop_();
+  speech.stop();
   speech.navigateToUrl_(queryUrl);
 };
 
@@ -761,7 +761,7 @@
  */
 speech.resetErrorTimer_ = function(duration) {
   window.clearTimeout(speech.errorTimer_);
-  speech.errorTimer_ = window.setTimeout(speech.stop_, duration);
+  speech.errorTimer_ = window.setTimeout(speech.stop, duration);
 };
 
 
@@ -802,18 +802,6 @@
 
 
 /**
- * Toggles starting and stopping of speech recognition by the speech tool.
- */
-speech.toggleStartStop = function() {
-  if (speech.currentState_ == speech.State_.READY) {
-    speech.start_();
-  } else {
-    speech.stop_();
-  }
-};
-
-
-/**
  * Handles click events during speech recognition.
  * @param {boolean} shouldSubmit True if a query should be submitted.
  * @param {boolean} shouldRetry True if the interface should be restarted.
@@ -830,17 +818,16 @@
     // If the user clicks on a "Learn more" or "Details" support page link
     // from an error message, do nothing, and let Chrome navigate to that page.
   } else {
-    speech.stop_();
+    speech.stop();
   }
 };
 
 /**
  * Restarts voice recognition. Used for the 'Try again' error link.
- * @private
  */
 speech.restart = function() {
   speech.reset_();
-  speech.toggleStartStop();
+  speech.start();
 };
 
 
@@ -929,6 +916,15 @@
 
 
 /**
+ * Base link target for help regarding voice search. To be appended
+ * with a locale string for proper target site localization.
+ * @const @private
+ */
+text.SUPPORT_LINK_BASE_ =
+    'https://support.google.com/chrome/?p=ui_voice_search&hl=';
+
+
+/**
  * The final / high confidence speech recognition result element.
  * @private {Element}
  */
@@ -957,15 +953,6 @@
 
 
 /**
- * Base link target for help regarding voice search. To be appended
- * with a locale string for proper target site localization.
- * @const @private
- */
-text.SUPPORT_LINK_BASE_ =
-    'https://support.google.com/chrome/?p=ui_voice_search&hl=';
-
-
-/**
  * Finds the text view elements.
  */
 text.init = function() {
@@ -1061,7 +1048,7 @@
     case RecognitionError.LANGUAGE_NOT_SUPPORTED:
       return speech.messages.languageError;
     default:
-      return '';
+      return speech.messages.otherError;
   }
 };
 
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 3e50a383..6805a14 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -141,6 +141,8 @@
     AddString(translated_strings.get(), "tryAgain",
               IDS_NEW_TAB_VOICE_TRY_AGAIN);
     AddString(translated_strings.get(), "waiting", IDS_NEW_TAB_VOICE_WAITING);
+    AddString(translated_strings.get(), "otherError",
+              IDS_NEW_TAB_VOICE_OTHER_ERROR);
   }
 
   return translated_strings;
diff --git a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc
index 5b389fc..9195e5b 100644
--- a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc
@@ -123,7 +123,7 @@
   auto simulator =
       content::NavigationSimulator::CreateRendererInitiated(url, rfh);
   simulator->Commit();
-  return simulator->GetLastThrottleCheckResult() ==
+  return simulator->GetLastThrottleCheckResult().action() ==
                  content::NavigationThrottle::PROCEED
              ? simulator->GetFinalRenderFrameHost()
              : nullptr;
diff --git a/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
index ba725f4..354e3fda 100644
--- a/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
+++ b/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
@@ -74,7 +74,7 @@
   content::NavigationThrottle::ThrottleCheckResult result =
       ShouldProceed(child_account_service_->IsGoogleAuthenticated());
 
-  if (result == content::NavigationThrottle::DEFER) {
+  if (result.action() == content::NavigationThrottle::DEFER) {
     google_auth_state_subscription_ =
         child_account_service_->ObserveGoogleAuthState(
             base::Bind(&SupervisedUserGoogleAuthNavigationThrottle::
@@ -90,7 +90,7 @@
   content::NavigationThrottle::ThrottleCheckResult result =
       ShouldProceed(authenticated);
 
-  switch (result) {
+  switch (result.action()) {
     case content::NavigationThrottle::PROCEED: {
       google_auth_state_subscription_.reset();
       Resume();
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
index e6207ffa..3eab10a5 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
@@ -159,8 +159,8 @@
   if (got_result)
     behavior_ = SupervisedUserURLFilter::INVALID;
   if (deferred_)
-    return ThrottleCheckResult::DEFER;
-  return ThrottleCheckResult::PROCEED;
+    return NavigationThrottle::DEFER;
+  return NavigationThrottle::PROCEED;
 }
 
 void SupervisedUserNavigationThrottle::ShowInterstitial(
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 4b44dd2..7a14966 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -420,7 +420,7 @@
 // Enables or disables the creation of (legacy) supervised users. Does not
 // affect existing supervised users.
 const base::Feature kSupervisedUserCreation{"SupervisedUserCreation",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if defined(OS_CHROMEOS)
 // Enables or disables chrome://sys-internals.
diff --git a/chrome/test/data/local_ntp/voice_speech_browsertest.js b/chrome/test/data/local_ntp/voice_speech_browsertest.js
index f16dcb2..509c447 100644
--- a/chrome/test/data/local_ntp/voice_speech_browsertest.js
+++ b/chrome/test/data/local_ntp/voice_speech_browsertest.js
@@ -42,6 +42,7 @@
   networkError: 'Network error',
   noTranslation: 'No translation',
   noVoice: 'No voice',
+  otherError: 'Unknown error',
   permissionError: 'Permission error',
   ready: 'Ready',
   tryAgain: 'Try again',
@@ -158,7 +159,7 @@
         };
         this.continuous = false;
         this.interimResults = false;
-        this.maxAlternatives = 0;
+        this.maxAlternatives = 1;
         this.onerror = null;
         this.onnomatch = null;
         this.onend = null;
@@ -178,10 +179,12 @@
  * Tests if the controller has the correct speech recognition settings.
  */
 test.speech.testSpeechRecognitionInitSettings = function() {
+  test.speech.recognitionStubs.reset();
+
   test.speech.initSpeech();
   assertFalse(speech.recognition_.continuous);
   assertEquals('en-ZA', speech.recognition_.lang);
-  assertEquals(4, speech.recognition_.maxAlternatives);
+  assertEquals(1, speech.recognition_.maxAlternatives);
   assert(!!speech.recognition_);
   test.speech.validateInactive();
 };
@@ -230,7 +233,7 @@
  */
 test.speech.testOmniboxFocusWithWorkingView = function() {
   test.speech.initSpeech();
-  speech.start_();
+  speech.start();
 
   assertEquals(speech.State_.STARTED, speech.currentState_);
   assertEquals(1, test.speech.recognitionActiveCount);
@@ -254,7 +257,7 @@
   speech.recognition_ = undefined;
   assertEquals(speech.State_.READY, speech.currentState_);
   assert(!speech.recognition_);
-  speech.toggleStartStop();
+  speech.start();
 
   assertEquals(1, test.speech.recognitionActiveCount);
   assertEquals(1, test.speech.viewActiveCount);
@@ -268,7 +271,7 @@
  */
 test.speech.testHandleAudioStart = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
 
   assertTrue('ready' in test.speech.viewState);
@@ -284,7 +287,7 @@
  */
 test.speech.testHandleSpeechStart = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
 
@@ -307,7 +310,7 @@
   const responseEvent =
       test.speech.createInterimResponse(lowConfidenceText, highConfidenceText);
 
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.recognition_.onresult(responseEvent);
@@ -331,7 +334,7 @@
   const responseEvent =
       test.speech.createFinalResponse(lowConfidenceText, highConfidenceText);
 
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   // Handle a final transcript from the recognition API.
@@ -363,13 +366,13 @@
   const responseEvent =
       test.speech.createInterimResponse(lowConfidenceText, highConfidenceText);
 
-  speech.start_();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   // Handle an interim trancript from the recognition API.
   speech.recognition_.onresult(responseEvent);
   // The user interrupts speech.
-  speech.stop_();
+  speech.stop();
 
   assertFalse(speech.isRecognizing_());
   assertEquals('', speech.interimResult_);
@@ -393,10 +396,10 @@
  */
 test.speech.testInterruptSpeechInputBeforeResult = function() {
   test.speech.initSpeech();
-  speech.start_();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
-  speech.stop_();
+  speech.stop();
 
   test.speech.validateInactive();
 };
@@ -408,7 +411,7 @@
  */
 test.speech.testSpeechRecognitionErrorTimeout = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onerror({error: 'some-error'});
 
   assertFalse(speech.isRecognizing_());
@@ -431,7 +434,7 @@
  */
 test.speech.testNoSpeechInput = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onend(null);
 
@@ -480,7 +483,7 @@
   test.speech.initSpeech();
   assertRecognitionHandlers(true);
 
-  speech.start_();
+  speech.start();
   assertRecognitionHandlers(true);
 
   speech.recognition_.onaudiostart(null);
@@ -497,7 +500,7 @@
   test.speech.validateInactive();
   assertRecognitionHandlers(true);
 
-  speech.start_();
+  speech.start();
   assertRecognitionHandlers(true);
 };
 
@@ -505,7 +508,7 @@
 /**
  * Tests starting and stopping the Speech Recognition API quickly
  * in succession.
- * Motivation: If |speech.start_()| is called too soon after |speech.stop_()|,
+ * Motivation: If |speech.start()| is called too soon after |speech.stop()|,
  * then the recognition interface hasn't yet reset and an error occurs.
  * In this case we need to hard-reset it and reissue the |recognition_.start()|
  * command.
@@ -514,7 +517,7 @@
   test.speech.recognitionStubs.reset();
 
   test.speech.initSpeech();
-  speech.start_();
+  speech.start();
   assertEquals(speech.State_.STARTED, speech.currentState_);
   assertTrue(speech.isRecognizing_());
 
@@ -522,15 +525,15 @@
   assertEquals(speech.State_.AUDIO_RECEIVED, speech.currentState_);
   assertTrue(speech.isRecognizing_());
 
-  speech.stop_();
+  speech.stop();
   assertEquals(speech.State_.READY, speech.currentState_);
   test.speech.validateInactive();
 
-  speech.start_();
+  speech.start();
   assertEquals(speech.State_.STARTED, speech.currentState_);
   assertTrue(speech.isRecognizing_());
 
-  speech.stop_();
+  speech.stop();
   assertEquals(speech.State_.READY, speech.currentState_);
   test.speech.validateInactive();
 };
@@ -572,7 +575,7 @@
  */
 test.speech.testEnterToSubmit = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.finalResult_ = 'test query';
@@ -596,7 +599,7 @@
  */
 test.speech.testClickToSubmit = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.finalResult_ = 'test query';
@@ -680,7 +683,7 @@
  */
 test.speech.testClickToAbort = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.onClick_(
@@ -695,7 +698,7 @@
  */
 test.speech.testClickToRetryWhenStopped = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   // An onend event after onpeechstart forces an error and stops recognition.
@@ -715,7 +718,7 @@
  */
 test.speech.testClickToRetryWhenNotStopped = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.onClick_(
@@ -731,7 +734,7 @@
  */
 test.speech.testNoSpeechInputMatched = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.recognition_.onnomatch(null);
@@ -762,7 +765,7 @@
       test.speech.createInterimResponse(lowConfidenceText, highConfidenceText);
   speech.reset_();
 
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.recognition_.onresult(responseEvent);
@@ -800,7 +803,7 @@
       test.speech.createInterimResponse(lowConfidenceText, highConfidenceText);
   speech.reset_();
 
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.recognition_.onresult(responseEvent);
@@ -823,7 +826,7 @@
  */
 test.speech.testQueryEncoding = function() {
   test.speech.initSpeech();
-  speech.toggleStartStop();
+  speech.start();
   speech.recognition_.onaudiostart(null);
   speech.recognition_.onspeechstart(null);
   speech.finalResult_ = '🔍t&qôr 文字+weird*chär%?s?';
diff --git a/chrome/test/data/local_ntp/voice_text_browsertest.js b/chrome/test/data/local_ntp/voice_text_browsertest.js
index c7684a7..789ab2e 100644
--- a/chrome/test/data/local_ntp/voice_text_browsertest.js
+++ b/chrome/test/data/local_ntp/voice_text_browsertest.js
@@ -48,6 +48,7 @@
     networkError: 'Network error',
     noTranslation: 'No translation',
     noVoice: 'No voice',
+    otherError: 'Unknown error',
     permissionError: 'Permission error',
     ready: 'Ready',
     tryAgain: 'Try again',
diff --git a/chrome/test/data/local_ntp/voice_view_browsertest.js b/chrome/test/data/local_ntp/voice_view_browsertest.js
index 831fb733..eee8a838 100644
--- a/chrome/test/data/local_ntp/voice_view_browsertest.js
+++ b/chrome/test/data/local_ntp/voice_view_browsertest.js
@@ -16,12 +16,13 @@
 
 /**
  * The set of textual strings for different states.
- * @enum {string}
+ * @const
  */
-test.view.Text = {
-  WAITING: 'Waiting...',
+test.view.TEXT = {
+  BLANK: '',
+  ERROR: 'Error',
   SPEAK_NOW: 'Speak now',
-  BLANK: ''
+  WAITING: 'Waiting...'
 };
 
 
@@ -80,20 +81,24 @@
   // Mock text area manipulating functions.
   test.view.stubs.replace(text, 'showInitializingMessage', function() {
     // Ignore the short timeout before showing "Waiting...".
-    test.view.interimText = test.view.Text.WAITING;
-    test.view.finalText = test.view.Text.BLANK;
+    test.view.interimText = test.view.TEXT.WAITING;
+    test.view.finalText = test.view.TEXT.BLANK;
   });
   test.view.stubs.replace(text, 'showReadyMessage', function() {
-    test.view.interimText = test.view.Text.SPEAK_NOW;
-    test.view.finalText = test.view.Text.BLANK;
+    test.view.interimText = test.view.TEXT.SPEAK_NOW;
+    test.view.finalText = test.view.TEXT.BLANK;
+  });
+  test.view.stubs.replace(text, 'showErrorMessage', function() {
+    test.view.interimText = test.view.TEXT.ERROR;
+    test.view.finalText = test.view.TEXT.BLANK;
   });
   test.view.stubs.replace(text, 'updateTextArea', function(texti, textf = '') {
     test.view.interimText = texti;
     test.view.finalText = textf;
   });
   test.view.stubs.replace(text, 'clear', function() {
-    test.view.interimText = test.view.Text.BLANK;
-    test.view.finalText = test.view.Text.BLANK;
+    test.view.interimText = test.view.TEXT.BLANK;
+    test.view.finalText = test.view.TEXT.BLANK;
   });
 
   // Mock level animation state.
@@ -127,8 +132,8 @@
   view.show();
 
   test.view.assertViewActive(
-      /*interim=*/test.view.Text.WAITING,
-      /*final=*/test.view.Text.BLANK,
+      /*interim=*/test.view.TEXT.WAITING,
+      /*final=*/test.view.TEXT.BLANK,
       /*containerClass=*/view.INACTIVE_CLASS_,
       /*levelAnimationActive=*/false);
 };
@@ -143,8 +148,8 @@
   view.show();
 
   test.view.assertViewActive(
-      /*interim=*/test.view.Text.WAITING,
-      /*final=*/test.view.Text.BLANK,
+      /*interim=*/test.view.TEXT.WAITING,
+      /*final=*/test.view.TEXT.BLANK,
       /*containerClass=*/view.INACTIVE_CLASS_,
       /*levelAnimationActive=*/false);
 };
@@ -173,8 +178,8 @@
   view.setReadyForSpeech();
 
   test.view.assertViewActive(
-      /*interim=*/test.view.Text.SPEAK_NOW,
-      /*final=*/test.view.Text.BLANK,
+      /*interim=*/test.view.TEXT.SPEAK_NOW,
+      /*final=*/test.view.TEXT.BLANK,
       /*containerClass=*/view.MICROPHONE_LISTENING_CLASS_,
       /*levelAnimationActive=*/false);
 };
@@ -202,8 +207,8 @@
   view.setReceivingSpeech();
 
   test.view.assertViewActive(
-      /*interim=*/test.view.Text.SPEAK_NOW,
-      /*final=*/test.view.Text.BLANK,
+      /*interim=*/test.view.TEXT.SPEAK_NOW,
+      /*final=*/test.view.TEXT.BLANK,
       /*containerClass=*/view.RECEIVING_SPEECH_CLASS_,
       /*levelAnimationActive=*/true);
 };
@@ -458,8 +463,8 @@
   view.showError(RecognitionError.OTHER);
 
   test.view.assertViewActive(
-      /*interim=*/test.view.Text.BLANK,
-      /*final=*/test.view.Text.BLANK,
+      /*interim=*/test.view.TEXT.ERROR,
+      /*final=*/test.view.TEXT.BLANK,
       /*containerClass=*/view.ERROR_RECEIVED_CLASS_,
       /*levelAnimationActive=*/false);
 };
@@ -477,8 +482,8 @@
   assertFalse(view.isNoMatchShown_);
   assertEquals(view.OVERLAY_HIDDEN_CLASS_, view.background_.className);
 
-  assertEquals(test.view.Text.BLANK, test.view.interimText);
-  assertEquals(test.view.Text.BLANK, test.view.finalText);
+  assertEquals(test.view.TEXT.BLANK, test.view.interimText);
+  assertEquals(test.view.TEXT.BLANK, test.view.finalText);
   assertEquals(view.INACTIVE_CLASS_, view.container_.className);
   assertFalse(test.view.levelAnimationActive);
 };
diff --git a/components/ntp_snippets/remote/proto/ntp_snippets.proto b/components/ntp_snippets/remote/proto/ntp_snippets.proto
index 7aa3641..ffcb538 100644
--- a/components/ntp_snippets/remote/proto/ntp_snippets.proto
+++ b/components/ntp_snippets/remote/proto/ntp_snippets.proto
@@ -22,7 +22,7 @@
   optional int64 publish_date = 5;
   optional int64 expiry_date = 6;
   optional float score = 7;
-  repeated SnippetSourceProto sources = 8;
+  optional SnippetSourceProto source = 8;
   optional bool dismissed = 9;
   optional int32 remote_category_id = 10;
   // The time when the snippet was fetched from the server.
diff --git a/components/ntp_snippets/remote/remote_suggestion.cc b/components/ntp_snippets/remote/remote_suggestion.cc
index 0157646..5569081 100644
--- a/components/ntp_snippets/remote/remote_suggestion.cc
+++ b/components/ntp_snippets/remote/remote_suggestion.cc
@@ -16,39 +16,6 @@
 
 namespace {
 
-struct SnippetSource {
-  SnippetSource(const GURL& url,
-                const std::string& publisher_name,
-                const GURL& amp_url)
-      : url(url), publisher_name(publisher_name), amp_url(amp_url) {}
-  GURL url;
-  std::string publisher_name;
-  GURL amp_url;
-};
-
-const SnippetSource& FindBestSource(const std::vector<SnippetSource>& sources) {
-  // The same article can be hosted by multiple sources, e.g. nytimes.com,
-  // cnn.com, etc. We need to parse the list of sources for this article and
-  // find the best match. In order of preference:
-  //  1) A source that has URL, publisher name, AMP URL
-  //  2) A source that has URL, publisher name
-  //  3) A source that has URL and AMP URL, or URL only (since we won't show
-  //  the snippet to users if the article does not have a publisher name, it
-  //  doesn't matter whether the snippet has the AMP URL or not)
-  int best_source_index = 0;
-  for (size_t i = 0; i < sources.size(); ++i) {
-    const SnippetSource& source = sources[i];
-    if (!source.publisher_name.empty()) {
-      best_source_index = i;
-      if (!source.amp_url.is_empty()) {
-        // This is the best possible source, stop looking.
-        break;
-      }
-    }
-  }
-  return sources[best_source_index];
-}
-
 // dict.Get() specialization for base::Time values
 bool GetTimeValue(const base::DictionaryValue& dict,
                   const std::string& key,
@@ -81,8 +48,6 @@
         kArticlesRemoteId,
     "kArticlesRemoteId has a wrong value?!");
 
-const int kChromeReaderDefaultExpiryTimeMins = 3 * 24 * 60;
-
 RemoteSuggestion::RemoteSuggestion(const std::vector<std::string>& ids,
                                    int remote_category_id)
     : ids_(ids),
@@ -97,128 +62,6 @@
 
 // static
 std::unique_ptr<RemoteSuggestion>
-RemoteSuggestion::CreateFromChromeReaderDictionary(
-    const base::DictionaryValue& dict,
-    const base::Time& fetch_date) {
-  const base::DictionaryValue* content = nullptr;
-  if (!dict.GetDictionary("contentInfo", &content)) {
-    return nullptr;
-  }
-
-  // Need at least a primary id.
-  std::string primary_id;
-  if (!content->GetString("url", &primary_id) || primary_id.empty()) {
-    return nullptr;
-  }
-
-  const base::ListValue* corpus_infos_list = nullptr;
-  if (!content->GetList("sourceCorpusInfo", &corpus_infos_list)) {
-    DLOG(WARNING) << "No sources found for article " << primary_id;
-    return nullptr;
-  }
-
-  std::vector<std::string> ids(1, primary_id);
-  std::vector<SnippetSource> sources;
-  for (const auto& value : *corpus_infos_list) {
-    const base::DictionaryValue* dict_value = nullptr;
-    if (!value.GetAsDictionary(&dict_value)) {
-      DLOG(WARNING) << "Invalid source info for article " << primary_id;
-      continue;
-    }
-
-    std::string corpus_id_str;
-    GURL corpus_id;
-    if (dict_value->GetString("corpusId", &corpus_id_str)) {
-      corpus_id = GURL(corpus_id_str);
-    }
-
-    if (!corpus_id.is_valid()) {
-      // We must at least have a valid source URL.
-      DLOG(WARNING) << "Invalid article url " << corpus_id_str;
-      continue;
-    }
-    const base::DictionaryValue* publisher_data = nullptr;
-    std::string site_title;
-    if (dict_value->GetDictionary("publisherData", &publisher_data)) {
-      if (!publisher_data->GetString("sourceName", &site_title)) {
-        // It's possible but not desirable to have no publisher data.
-        DLOG(WARNING) << "No publisher name for article " << corpus_id_str;
-      }
-    } else {
-      DLOG(WARNING) << "No publisher data for article " << corpus_id_str;
-    }
-
-    std::string amp_url_str;
-    GURL amp_url;
-    // Expected to not have AMP url sometimes.
-    if (dict_value->GetString("ampUrl", &amp_url_str)) {
-      amp_url = GURL(amp_url_str);
-      DLOG_IF(WARNING, !amp_url.is_valid())
-          << "Invalid AMP url " << amp_url_str;
-    }
-    sources.emplace_back(corpus_id, site_title,
-                         amp_url.is_valid() ? amp_url : GURL());
-    // We use the raw string so that we can compare it against other primary
-    // IDs. Parsing the ID as a URL might add a trailing slash (and we don't do
-    // this for the primary ID).
-    ids.push_back(corpus_id_str);
-  }
-  if (sources.empty()) {
-    DLOG(WARNING) << "No sources found for article " << primary_id;
-    return nullptr;
-  }
-
-  std::unique_ptr<RemoteSuggestion> snippet(
-      new RemoteSuggestion(ids, kArticlesRemoteId));
-  snippet->fetch_date_ = fetch_date;
-
-  std::string title;
-  if (content->GetString("title", &title)) {
-    snippet->title_ = title;
-  }
-  std::string salient_image_url;
-  if (content->GetString("thumbnailUrl", &salient_image_url)) {
-    snippet->salient_image_url_ = GURL(salient_image_url);
-  }
-  std::string snippet_str;
-  if (content->GetString("snippet", &snippet_str)) {
-    snippet->snippet_ = snippet_str;
-  }
-  // The creation and expiry timestamps are uint64s which are stored as strings.
-  std::string creation_timestamp_str;
-  if (content->GetString("creationTimestampSec", &creation_timestamp_str)) {
-    snippet->publish_date_ = TimeFromJsonString(creation_timestamp_str);
-  }
-  std::string expiry_timestamp_str;
-  if (content->GetString("expiryTimestampSec", &expiry_timestamp_str)) {
-    snippet->expiry_date_ = TimeFromJsonString(expiry_timestamp_str);
-  }
-
-  // If publish and/or expiry date are missing, fill in reasonable defaults.
-  if (snippet->publish_date_.is_null()) {
-    snippet->publish_date_ = base::Time::Now();
-  }
-  if (snippet->expiry_date_.is_null()) {
-    snippet->expiry_date_ =
-        snippet->publish_date() +
-        base::TimeDelta::FromMinutes(kChromeReaderDefaultExpiryTimeMins);
-  }
-
-  const SnippetSource& source = FindBestSource(sources);
-  snippet->url_ = source.url;
-  snippet->publisher_name_ = source.publisher_name;
-  snippet->amp_url_ = source.amp_url;
-
-  double score;
-  if (dict.GetDouble("score", &score)) {
-    snippet->score_ = score;
-  }
-
-  return snippet;
-}
-
-// static
-std::unique_ptr<RemoteSuggestion>
 RemoteSuggestion::CreateFromContentSuggestionsDictionary(
     const base::DictionaryValue& dict,
     int remote_category_id,
@@ -338,33 +181,25 @@
   snippet->score_ = proto.score();
   snippet->is_dismissed_ = proto.dismissed();
 
-  std::vector<SnippetSource> sources;
-  for (int i = 0; i < proto.sources_size(); ++i) {
-    const SnippetSourceProto& source_proto = proto.sources(i);
-    GURL url(source_proto.url());
-    if (!url.is_valid()) {
-      // We must at least have a valid source URL.
-      DLOG(WARNING) << "Invalid article url " << source_proto.url();
-      continue;
-    }
-    GURL amp_url;
-    if (source_proto.has_amp_url()) {
-      amp_url = GURL(source_proto.amp_url());
-      DLOG_IF(WARNING, !amp_url.is_valid())
-          << "Invalid AMP URL " << source_proto.amp_url();
-    }
-
-    sources.emplace_back(url, source_proto.publisher_name(), amp_url);
-  }
-
-  if (sources.empty()) {
-    DLOG(WARNING) << "No sources found for article " << snippet->id();
+  if (!proto.has_source()) {
+    DLOG(WARNING) << "No source found for article " << snippet->id();
     return nullptr;
   }
-  const SnippetSource& source = FindBestSource(sources);
-  snippet->url_ = source.url;
-  snippet->publisher_name_ = source.publisher_name;
-  snippet->amp_url_ = source.amp_url;
+  GURL url(proto.source().url());
+  if (!url.is_valid()) {
+    // We must at least have a valid source URL.
+    DLOG(WARNING) << "Invalid article url " << proto.source().url();
+    return nullptr;
+  }
+  GURL amp_url;
+  if (proto.source().has_amp_url()) {
+    amp_url = GURL(proto.source().amp_url());
+    DLOG_IF(WARNING, !amp_url.is_valid())
+        << "Invalid AMP URL " << proto.source().amp_url();
+  }
+  snippet->url_ = url;
+  snippet->publisher_name_ = proto.source().publisher_name();
+  snippet->amp_url_ = amp_url;
 
   if (proto.has_fetch_date()) {
     snippet->fetch_date_ = base::Time::FromInternalValue(proto.fetch_date());
@@ -404,7 +239,7 @@
   result.set_dismissed(is_dismissed_);
   result.set_remote_category_id(remote_category_id_);
 
-  SnippetSourceProto* source_proto = result.add_sources();
+  SnippetSourceProto* source_proto = result.mutable_source();
   source_proto->set_url(url_.spec());
   if (!publisher_name_.empty()) {
     source_proto->set_publisher_name(publisher_name_);
@@ -458,24 +293,6 @@
 }
 
 // static
-base::Time RemoteSuggestion::TimeFromJsonString(
-    const std::string& timestamp_str) {
-  int64_t timestamp;
-  if (!base::StringToInt64(timestamp_str, &timestamp)) {
-    // Even if there's an error in the conversion, some garbage data may still
-    // be written to the output var, so reset it.
-    DLOG(WARNING) << "Invalid json timestamp: " << timestamp_str;
-    timestamp = 0;
-  }
-  return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(timestamp);
-}
-
-// static
-std::string RemoteSuggestion::TimeToJsonString(const base::Time& time) {
-  return base::Int64ToString((time - base::Time::UnixEpoch()).InSeconds());
-}
-
-// static
 std::unique_ptr<RemoteSuggestion> RemoteSuggestion::MakeUnique(
     const std::vector<std::string>& ids,
     int remote_category_id) {
diff --git a/components/ntp_snippets/remote/remote_suggestion.h b/components/ntp_snippets/remote/remote_suggestion.h
index 367cd3e..fa1e483 100644
--- a/components/ntp_snippets/remote/remote_suggestion.h
+++ b/components/ntp_snippets/remote/remote_suggestion.h
@@ -23,7 +23,6 @@
 
 // Exposed for tests.
 extern const int kArticlesRemoteId;
-extern const int kChromeReaderDefaultExpiryTimeMins;
 
 class SnippetProto;
 
@@ -35,17 +34,9 @@
 
   ~RemoteSuggestion();
 
-  // Creates a RemoteSuggestion from a dictionary, as returned by Chrome Reader.
-  // Returns a null pointer if the dictionary doesn't correspond to a valid
-  // suggestion. The keys in the dictionary are expected to be the same as the
-  // property name, with exceptions documented in the property comment.
-  static std::unique_ptr<RemoteSuggestion> CreateFromChromeReaderDictionary(
-      const base::DictionaryValue& dict,
-      const base::Time& fetch_date);
-
   // Creates a RemoteSuggestion from a dictionary, as returned by Chrome Content
   // Suggestions. Returns a null pointer if the dictionary doesn't correspond to
-  // a valid suggestion. Maps field names to Chrome Reader field names.
+  // a valid suggestion.
   static std::unique_ptr<RemoteSuggestion>
   CreateFromContentSuggestionsDictionary(const base::DictionaryValue& dict,
                                          int remote_category_id,
@@ -87,13 +78,10 @@
   const std::string& snippet() const { return snippet_; }
 
   // Link to an image representative of the content. Do not fetch this image
-  // directly. If initialized by CreateFromChromeReaderDictionary() the relevant
-  // key is 'thumbnailUrl'
+  // directly.
   const GURL& salient_image_url() const { return salient_image_url_; }
 
-  // When the page pointed by this suggestion was published.  If initialized by
-  // CreateFromChromeReaderDictionary() the relevant key is
-  // 'creationTimestampSec'
+  // When the page pointed by this suggestion was published.
   const base::Time& publish_date() const { return publish_date_; }
 
   // After this expiration date this suggestion should no longer be presented to
@@ -131,10 +119,6 @@
 
   base::Time fetch_date() const { return fetch_date_; }
 
-  // Public for testing.
-  static base::Time TimeFromJsonString(const std::string& timestamp_str);
-  static std::string TimeToJsonString(const base::Time& time);
-
  private:
   RemoteSuggestion(const std::vector<std::string>& ids, int remote_category_id);
 
diff --git a/components/ntp_snippets/remote/remote_suggestion_builder.cc b/components/ntp_snippets/remote/remote_suggestion_builder.cc
index 95d3d02..f552601 100644
--- a/components/ntp_snippets/remote/remote_suggestion_builder.cc
+++ b/components/ntp_snippets/remote/remote_suggestion_builder.cc
@@ -148,7 +148,7 @@
   proto.set_score(score_.value_or(1));
   proto.set_dismissed(is_dismissed_.value_or(false));
   proto.set_remote_category_id(remote_category_id_.value_or(1));
-  auto* source = proto.add_sources();
+  auto* source = proto.mutable_source();
   source->set_url(url_.value_or("http://url.com/"));
   source->set_publisher_name(publisher_name_.value_or("Publisher"));
   source->set_amp_url(amp_url_.value_or("http://amp_url.com/"));
diff --git a/components/ntp_snippets/remote/remote_suggestion_unittest.cc b/components/ntp_snippets/remote/remote_suggestion_unittest.cc
index 6c8d7876..066bfa91 100644
--- a/components/ntp_snippets/remote/remote_suggestion_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestion_unittest.cc
@@ -35,7 +35,7 @@
       *json_dict, kArticlesRemoteId, fetch_date);
 }
 
-TEST(RemoteSuggestionTest, FromChromeContentSuggestionsDictionary) {
+TEST(RemoteSuggestionTest, FromContentSuggestionsDictionary) {
   const std::string kJsonStr =
       "{"
       "  \"ids\" : [\"http://localhost/foobar\"],"
@@ -79,291 +79,6 @@
   EXPECT_EQ(fetch_date, snippet->fetch_date());
 }
 
-std::unique_ptr<RemoteSuggestion> SnippetFromChromeReaderDict(
-    std::unique_ptr<base::DictionaryValue> dict,
-    const base::Time& fetch_date) {
-  if (!dict) {
-    return nullptr;
-  }
-  return RemoteSuggestion::CreateFromChromeReaderDictionary(*dict, fetch_date);
-}
-
-const char kChromeReaderCreationTimestamp[] = "1234567890";
-const char kChromeReaderExpiryTimestamp[] = "2345678901";
-
-// Old form, from chromereader-pa.googleapis.com. Two sources.
-std::unique_ptr<base::DictionaryValue> ChromeReaderSnippetWithTwoSources() {
-  const std::string kJsonStr = base::StringPrintf(
-      "{\n"
-      "  \"contentInfo\": {\n"
-      "    \"url\":                   \"http://url.com\",\n"
-      "    \"title\":                 \"Source 1 Title\",\n"
-      "    \"snippet\":               \"Source 1 Snippet\",\n"
-      "    \"thumbnailUrl\":          \"http://url.com/thumbnail\",\n"
-      "    \"creationTimestampSec\":  \"%s\",\n"
-      "    \"expiryTimestampSec\":    \"%s\",\n"
-      "    \"sourceCorpusInfo\": [{\n"
-      "      \"corpusId\":            \"http://source1.com\",\n"
-      "      \"publisherData\": {\n"
-      "        \"sourceName\":        \"Source 1\"\n"
-      "      },\n"
-      "      \"ampUrl\": \"http://source1.amp.com\"\n"
-      "    }, {\n"
-      "      \"corpusId\":            \"http://source2.com\",\n"
-      "      \"publisherData\": {\n"
-      "        \"sourceName\":        \"Source 2\"\n"
-      "      },\n"
-      "      \"ampUrl\": \"http://source2.amp.com\"\n"
-      "    }]\n"
-      "  },\n"
-      "  \"score\": 5.0\n"
-      "}\n",
-      kChromeReaderCreationTimestamp, kChromeReaderExpiryTimestamp);
-
-  auto json_value = base::JSONReader::Read(kJsonStr);
-  base::DictionaryValue* json_dict;
-  if (!json_value->GetAsDictionary(&json_dict)) {
-    return nullptr;
-  }
-  return json_dict->CreateDeepCopy();
-}
-
-TEST(RemoteSuggestionTest, TestMultipleSources) {
-  auto snippet = SnippetFromChromeReaderDict(
-      ChromeReaderSnippetWithTwoSources(), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  // Expect the first source to be chosen.
-  EXPECT_EQ(snippet->id(), "http://url.com");
-  EXPECT_EQ(snippet->url(), GURL("http://source1.com"));
-  EXPECT_EQ(snippet->publisher_name(), std::string("Source 1"));
-  EXPECT_EQ(snippet->amp_url(), GURL("http://source1.amp.com"));
-}
-
-TEST(RemoteSuggestionTest, TestMultipleIncompleteSources1) {
-  // Set Source 2 to have no AMP url, and Source 1 to have no publisher name
-  // Source 2 should win since we favor publisher name over amp url
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  base::ListValue* sources;
-  ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources));
-  base::DictionaryValue* source;
-  ASSERT_TRUE(sources->GetDictionary(0, &source));
-  source->Remove("publisherData.sourceName", nullptr);
-  ASSERT_TRUE(sources->GetDictionary(1, &source));
-  source->Remove("ampUrl", nullptr);
-
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  EXPECT_EQ(snippet->id(), "http://url.com");
-  EXPECT_EQ(snippet->url(), GURL("http://source2.com"));
-  EXPECT_EQ(snippet->publisher_name(), std::string("Source 2"));
-  EXPECT_EQ(snippet->amp_url(), GURL());
-}
-
-TEST(RemoteSuggestionTest, TestMultipleIncompleteSources2) {
-  // Set Source 1 to have no AMP url, and Source 2 to have no publisher name
-  // Source 1 should win in this case since we prefer publisher name to AMP url
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  base::ListValue* sources;
-  ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources));
-  base::DictionaryValue* source;
-  ASSERT_TRUE(sources->GetDictionary(0, &source));
-  source->Remove("ampUrl", nullptr);
-  ASSERT_TRUE(sources->GetDictionary(1, &source));
-  source->Remove("publisherData.sourceName", nullptr);
-
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  EXPECT_EQ(snippet->id(), "http://url.com");
-  EXPECT_EQ(snippet->url(), GURL("http://source1.com"));
-  EXPECT_EQ(snippet->publisher_name(), std::string("Source 1"));
-  EXPECT_EQ(snippet->amp_url(), GURL());
-}
-
-TEST(RemoteSuggestionTest, TestMultipleIncompleteSources3) {
-  // Set source 1 to have no AMP url and no source, and source 2 to only have
-  // amp url. There should be no snippets since we only add sources we consider
-  // complete
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  base::ListValue* sources;
-  ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources));
-  base::DictionaryValue* source;
-  ASSERT_TRUE(sources->GetDictionary(0, &source));
-  source->Remove("publisherData.sourceName", nullptr);
-  source->Remove("ampUrl", nullptr);
-  ASSERT_TRUE(sources->GetDictionary(1, &source));
-  source->Remove("publisherData.sourceName", nullptr);
-
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-  ASSERT_FALSE(snippet->is_complete());
-}
-
-TEST(RemoteSuggestionTest, ShouldFillInCreation) {
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  ASSERT_TRUE(dict->Remove("contentInfo.creationTimestampSec", nullptr));
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  // Publish date should have been filled with "now" - just make sure it's not
-  // empty and not the test default value.
-  base::Time publish_date = snippet->publish_date();
-  EXPECT_FALSE(publish_date.is_null());
-  EXPECT_NE(publish_date, RemoteSuggestion::TimeFromJsonString(
-                              kChromeReaderCreationTimestamp));
-  // Expiry date should have kept the test default value.
-  base::Time expiry_date = snippet->expiry_date();
-  EXPECT_FALSE(expiry_date.is_null());
-  EXPECT_EQ(expiry_date,
-            RemoteSuggestion::TimeFromJsonString(kChromeReaderExpiryTimestamp));
-}
-
-TEST(RemoteSuggestionTest, ShouldFillInExpiry) {
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  ASSERT_TRUE(dict->Remove("contentInfo.expiryTimestampSec", nullptr));
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  base::Time publish_date = snippet->publish_date();
-  ASSERT_FALSE(publish_date.is_null());
-  // Expiry date should have been filled with creation date + offset.
-  base::Time expiry_date = snippet->expiry_date();
-  EXPECT_FALSE(expiry_date.is_null());
-  EXPECT_EQ(publish_date + base::TimeDelta::FromMinutes(
-                               kChromeReaderDefaultExpiryTimeMins),
-            expiry_date);
-}
-
-TEST(RemoteSuggestionTest, ShouldFillInCreationAndExpiry) {
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  ASSERT_TRUE(dict->Remove("contentInfo.creationTimestampSec", nullptr));
-  ASSERT_TRUE(dict->Remove("contentInfo.expiryTimestampSec", nullptr));
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  // Publish date should have been filled with "now" - just make sure it's not
-  // empty and not the test default value.
-  base::Time publish_date = snippet->publish_date();
-  EXPECT_FALSE(publish_date.is_null());
-  EXPECT_NE(publish_date, RemoteSuggestion::TimeFromJsonString(
-                              kChromeReaderCreationTimestamp));
-  // Expiry date should have been filled with creation date + offset.
-  base::Time expiry_date = snippet->expiry_date();
-  EXPECT_FALSE(expiry_date.is_null());
-  EXPECT_EQ(publish_date + base::TimeDelta::FromMinutes(
-                               kChromeReaderDefaultExpiryTimeMins),
-            expiry_date);
-}
-
-TEST(RemoteSuggestionTest, ShouldNotOverwriteExpiry) {
-  auto dict = ChromeReaderSnippetWithTwoSources();
-  ASSERT_TRUE(dict->Remove("contentInfo.creationTimestampSec", nullptr));
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  // Expiry date should have kept the test default value.
-  base::Time expiry_date = snippet->expiry_date();
-  EXPECT_FALSE(expiry_date.is_null());
-  EXPECT_EQ(expiry_date,
-            RemoteSuggestion::TimeFromJsonString(kChromeReaderExpiryTimestamp));
-}
-
-// Old form, from chromereader-pa.googleapis.com. Three sources.
-std::unique_ptr<base::DictionaryValue> ChromeReaderSnippetWithThreeSources() {
-  const std::string kJsonStr = base::StringPrintf(
-      "{\n"
-      "  \"contentInfo\": {\n"
-      "    \"url\":                   \"http://url.com\",\n"
-      "    \"title\":                 \"Source 1 Title\",\n"
-      "    \"snippet\":               \"Source 1 Snippet\",\n"
-      "    \"thumbnailUrl\":          \"http://url.com/thumbnail\",\n"
-      "    \"creationTimestampSec\":  \"%s\",\n"
-      "    \"expiryTimestampSec\":    \"%s\",\n"
-      "    \"sourceCorpusInfo\": [{\n"
-      "      \"corpusId\":            \"http://source1.com\",\n"
-      "      \"publisherData\": {\n"
-      "        \"sourceName\":        \"Source 1\"\n"
-      "      },\n"
-      "      \"ampUrl\": \"http://source1.amp.com\"\n"
-      "    }, {\n"
-      "      \"corpusId\":            \"http://source2.com\",\n"
-      "      \"publisherData\": {\n"
-      "        \"sourceName\":        \"Source 2\"\n"
-      "      },\n"
-      "      \"ampUrl\": \"http://source2.amp.com\"\n"
-      "    }, {\n"
-      "      \"corpusId\":            \"http://source3.com\",\n"
-      "      \"publisherData\": {\n"
-      "        \"sourceName\":        \"Source 3\"\n"
-      "      },\n"
-      "      \"ampUrl\": \"http://source3.amp.com\"\n"
-      "    }]\n"
-      "  },\n"
-      "  \"score\": 5.0\n"
-      "}\n",
-      kChromeReaderCreationTimestamp, kChromeReaderExpiryTimestamp);
-
-  auto json_value = base::JSONReader::Read(kJsonStr);
-  base::DictionaryValue* json_dict;
-  if (!json_value->GetAsDictionary(&json_dict)) {
-    return nullptr;
-  }
-  return json_dict->CreateDeepCopy();
-}
-
-TEST(RemoteSuggestionTest, TestMultipleCompleteSources1) {
-  // Test 2 complete sources, we should choose the first complete source
-  auto dict = ChromeReaderSnippetWithThreeSources();
-  base::ListValue* sources;
-  ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources));
-  base::DictionaryValue* source;
-  ASSERT_TRUE(sources->GetDictionary(1, &source));
-  source->Remove("publisherData.sourceName", nullptr);
-
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  EXPECT_EQ(snippet->id(), "http://url.com");
-  EXPECT_THAT(snippet->GetAllIDs(),
-              ElementsAre("http://url.com", "http://source1.com",
-                          "http://source2.com", "http://source3.com"));
-  EXPECT_EQ(snippet->url(), GURL("http://source1.com"));
-  EXPECT_EQ(snippet->publisher_name(), std::string("Source 1"));
-  EXPECT_EQ(snippet->amp_url(), GURL("http://source1.amp.com"));
-}
-
-TEST(RemoteSuggestionTest, TestMultipleCompleteSources2) {
-  // Test 2 complete sources, we should choose the first complete source
-  auto dict = ChromeReaderSnippetWithThreeSources();
-  base::ListValue* sources;
-  ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources));
-  base::DictionaryValue* source;
-  ASSERT_TRUE(sources->GetDictionary(0, &source));
-  source->Remove("publisherData.sourceName", nullptr);
-
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  EXPECT_EQ(snippet->id(), "http://url.com");
-  EXPECT_EQ(snippet->url(), GURL("http://source2.com"));
-  EXPECT_EQ(snippet->publisher_name(), std::string("Source 2"));
-  EXPECT_EQ(snippet->amp_url(), GURL("http://source2.amp.com"));
-}
-
-TEST(RemoteSuggestionTest, TestMultipleCompleteSources3) {
-  // Test 3 complete sources, we should choose the first complete source
-  auto dict = ChromeReaderSnippetWithThreeSources();
-  auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time());
-  ASSERT_THAT(snippet, NotNull());
-
-  EXPECT_EQ(snippet->id(), "http://url.com");
-  EXPECT_EQ(snippet->url(), GURL("http://source1.com"));
-  EXPECT_EQ(snippet->publisher_name(), std::string("Source 1"));
-  EXPECT_EQ(snippet->amp_url(), GURL("http://source1.amp.com"));
-}
-
 TEST(RemoteSuggestionTest,
      ShouldSupportMultipleIdsFromContentSuggestionsServer) {
   const std::string kJsonStr =
@@ -401,7 +116,7 @@
   proto.set_remote_category_id(1);
   proto.set_fetch_date(1476364691);
   proto.set_content_type(SnippetProto_ContentType_VIDEO);
-  auto* source = proto.add_sources();
+  auto* source = proto.mutable_source();
   source->set_url("http://cool-suggestions.com/");
   source->set_publisher_name("Great Suggestions Inc.");
   source->set_amp_url("http://cdn.ampproject.org/c/foo/");
@@ -435,7 +150,7 @@
   proto.set_score(0.1f);
   proto.set_dismissed(false);
   proto.set_remote_category_id(1);
-  auto* source = proto.add_sources();
+  auto* source = proto.mutable_source();
   source->set_url("http://cool-suggestions.com/");
   source->set_publisher_name("Great Suggestions Inc.");
   source->set_amp_url("http://cdn.ampproject.org/c/foo/");
@@ -449,7 +164,6 @@
   EXPECT_EQ(snippet->fetch_date(), base::Time());
 }
 
-// New form, from chromecontentsuggestions-pa.googleapis.com.
 std::unique_ptr<base::DictionaryValue> ContentSuggestionSnippet() {
   const std::string kJsonStr =
       "{"
diff --git a/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
index b951f4d6..613fc20 100644
--- a/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
@@ -44,7 +44,7 @@
   SnippetProto proto;
   proto.add_ids("http://localhost");
   proto.set_remote_category_id(1);  // Articles
-  auto* source = proto.add_sources();
+  auto* source = proto.mutable_source();
   source->set_url("http://localhost");
   source->set_publisher_name("Publisher");
   source->set_amp_url("http://amp");
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
index cfcfce2..068e01b8 100644
--- a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
+++ b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
@@ -64,22 +64,6 @@
   }
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestAuthenticated);
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestUnauthenticated);
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestExcludedIds);
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestNoUserClass);
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestWithTwoLanguages);
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestWithUILanguageOnly);
-  FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest,
-                           BuildRequestWithOtherLanguageOnly);
-  friend class ChromeReaderSnippetsFetcherTest;
-
   void FetchSnippetsNonAuthenticated(internal::JsonRequest::Builder builder,
                                      SnippetsAvailableCallback callback);
   void FetchSnippetsAuthenticated(internal::JsonRequest::Builder builder,
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
index 39b8687..c6550993 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -828,8 +828,6 @@
     // from the server. crbug.com/653816
     bool response_includes_article_category = false;
     for (FetchedCategory& fetched_category : *fetched_categories) {
-      // TODO(tschumann): Remove this histogram once we only talk to the content
-      // suggestions cloud backend.
       if (fetched_category.category == articles_category_) {
         UMA_HISTOGRAM_SPARSE_SLOWLY(
             "NewTabPage.Snippets.NumArticlesFetched",
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
index ae50314c..7799f92 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -151,7 +151,7 @@
   snippet_proto.set_publish_date(SerializeTime(GetDefaultCreationTime()));
   snippet_proto.set_expiry_date(SerializeTime(GetDefaultExpirationTime()));
   snippet_proto.set_remote_category_id(1);
-  auto* source = snippet_proto.add_sources();
+  auto* source = snippet_proto.mutable_source();
   source->set_url(url);
   source->set_publisher_name("Publisher");
   source->set_amp_url(url + "amp");
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
index 2db31a5e..27499e7 100644
--- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
@@ -79,7 +79,7 @@
       parent_activation_state_->activation_level == ActivationLevel::DISABLED) {
     DCHECK(navigation_handle()->IsInMainFrame());
     DCHECK(!ruleset_handle_);
-    return content::NavigationThrottle::ThrottleCheckResult::PROCEED;
+    return content::NavigationThrottle::PROCEED;
   }
 
   DCHECK(ruleset_handle_);
@@ -99,7 +99,7 @@
                  weak_ptr_factory_.GetWeakPtr()));
 
   defer_timestamp_ = base::TimeTicks::Now();
-  return content::NavigationThrottle::ThrottleCheckResult::DEFER;
+  return content::NavigationThrottle::DEFER;
 }
 
 const char* ActivationStateComputingNavigationThrottle::GetNameForLogging() {
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
index e904794e..b509103 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -194,36 +194,36 @@
   }
 
   void SimulateStartAndExpectResult(
-      content::NavigationThrottle::ThrottleCheckResult expect_result) {
+      content::NavigationThrottle::ThrottleAction expect_result) {
     navigation_simulator_->Start();
     content::NavigationThrottle::ThrottleCheckResult result =
         navigation_simulator_->GetLastThrottleCheckResult();
     EXPECT_EQ(expect_result, result);
-    if (result != content::NavigationThrottle::PROCEED)
+    if (result.action() != content::NavigationThrottle::PROCEED)
       navigation_simulator_.reset();
   }
 
   void SimulateRedirectAndExpectResult(
       const GURL& new_url,
-      content::NavigationThrottle::ThrottleCheckResult expect_result) {
+      content::NavigationThrottle::ThrottleAction expect_result) {
     navigation_simulator_->Redirect(new_url);
     content::NavigationThrottle::ThrottleCheckResult result =
         navigation_simulator_->GetLastThrottleCheckResult();
     EXPECT_EQ(expect_result, result);
-    if (result != content::NavigationThrottle::PROCEED)
+    if (result.action() != content::NavigationThrottle::PROCEED)
       navigation_simulator_.reset();
   }
 
   // Returns the RenderFrameHost that the navigation commit in.
   content::RenderFrameHost* SimulateCommitAndExpectResult(
-      content::NavigationThrottle::ThrottleCheckResult expect_result) {
+      content::NavigationThrottle::ThrottleAction expect_result) {
     navigation_simulator_->Commit();
     content::NavigationThrottle::ThrottleCheckResult result =
         navigation_simulator_->GetLastThrottleCheckResult();
     EXPECT_EQ(expect_result, result);
 
     auto scoped_simulator = std::move(navigation_simulator_);
-    if (result == content::NavigationThrottle::PROCEED)
+    if (result.action() == content::NavigationThrottle::PROCEED)
       return scoped_simulator->GetFinalRenderFrameHost();
     return nullptr;
   }
@@ -370,12 +370,12 @@
   CreateSubframeWithTestNavigation(
       GURL("https://www.example.com/before-redirect.html"), main_rfh());
   SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
-  content::NavigationThrottle::ThrottleCheckResult expected_result =
+  content::NavigationThrottle::ThrottleAction expected_action =
       content::IsBrowserSideNavigationEnabled()
           ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
           : content::NavigationThrottle::CANCEL;
   SimulateRedirectAndExpectResult(
-      GURL("https://www.example.com/disallowed.html"), expected_result);
+      GURL("https://www.example.com/disallowed.html"), expected_action);
 
   EXPECT_EQ(1, disallowed_notification_count());
 }
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
index 21a5f71a..c436bf7a 100644
--- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
+++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
@@ -63,7 +63,7 @@
 SubframeNavigationFilteringThrottle::WillProcessResponse() {
   DCHECK_NE(load_policy_, LoadPolicy::DISALLOW);
   NotifyLoadPolicy();
-  return content::NavigationThrottle::ThrottleCheckResult::PROCEED;
+  return PROCEED;
 }
 
 const char* SubframeNavigationFilteringThrottle::GetNameForLogging() {
@@ -75,13 +75,13 @@
     ThrottlingStage stage) {
   DCHECK_NE(load_policy_, LoadPolicy::DISALLOW);
   if (load_policy_ == LoadPolicy::WOULD_DISALLOW)
-    return content::NavigationThrottle::ThrottleCheckResult::PROCEED;
+    return PROCEED;
   parent_frame_filter_->GetLoadPolicyForSubdocument(
       navigation_handle()->GetURL(),
       base::Bind(&SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy,
                  weak_ptr_factory_.GetWeakPtr(), stage));
   last_defer_timestamp_ = base::TimeTicks::Now();
-  return content::NavigationThrottle::ThrottleCheckResult::DEFER;
+  return DEFER;
 }
 
 void SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy(
@@ -111,9 +111,7 @@
         content::IsBrowserSideNavigationEnabled() ||
         stage == ThrottlingStage::WillStartRequest;
     CancelDeferredNavigation(
-        block_and_collapse_is_supported
-            ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
-            : content::NavigationThrottle::CANCEL);
+        block_and_collapse_is_supported ? BLOCK_REQUEST_AND_COLLAPSE : CANCEL);
   } else {
     Resume();
   }
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
index 553c5d3..40fad386 100644
--- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
@@ -104,7 +104,7 @@
   }
 
   void SimulateStartAndExpectResult(
-      content::NavigationThrottle::ThrottleCheckResult expect_result) {
+      content::NavigationThrottle::ThrottleAction expect_result) {
     navigation_simulator_->Start();
     EXPECT_EQ(expect_result,
               navigation_simulator_->GetLastThrottleCheckResult());
@@ -112,14 +112,14 @@
 
   void SimulateRedirectAndExpectResult(
       const GURL& new_url,
-      content::NavigationThrottle::ThrottleCheckResult expect_result) {
+      content::NavigationThrottle::ThrottleAction expect_result) {
     navigation_simulator_->Redirect(new_url);
     EXPECT_EQ(expect_result,
               navigation_simulator_->GetLastThrottleCheckResult());
   }
 
   void SimulateCommitAndExpectResult(
-      content::NavigationThrottle::ThrottleCheckResult expect_result) {
+      content::NavigationThrottle::ThrottleAction expect_result) {
     navigation_simulator_->Commit();
     EXPECT_EQ(expect_result,
               navigation_simulator_->GetLastThrottleCheckResult());
@@ -158,7 +158,7 @@
                                       main_rfh());
 
   SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
-  content::NavigationThrottle::ThrottleCheckResult expected_result =
+  content::NavigationThrottle::ThrottleAction expected_result =
       content::IsBrowserSideNavigationEnabled()
           ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
           : content::NavigationThrottle::CANCEL;
@@ -174,7 +174,7 @@
   SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
   SimulateRedirectAndExpectResult(GURL("https://example.test/allowed2.html"),
                                   content::NavigationThrottle::PROCEED);
-  content::NavigationThrottle::ThrottleCheckResult expected_result =
+  content::NavigationThrottle::ThrottleAction expected_result =
       content::IsBrowserSideNavigationEnabled()
           ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
           : content::NavigationThrottle::CANCEL;
@@ -219,7 +219,7 @@
   if (content::IsBrowserSideNavigationEnabled())
     navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
   SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
-  content::NavigationThrottle::ThrottleCheckResult expected_result =
+  content::NavigationThrottle::ThrottleAction expected_result =
       content::IsBrowserSideNavigationEnabled()
           ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE
           : content::NavigationThrottle::CANCEL;
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
index 62c06cb..60d257a 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -119,7 +119,7 @@
 SubresourceFilterSafeBrowsingActivationThrottle::WillRedirectRequest() {
   CheckCurrentUrl();
   DCHECK(!database_client_ || !check_results_.empty());
-  return content::NavigationThrottle::ThrottleCheckResult::PROCEED;
+  return PROCEED;
 }
 
 content::NavigationThrottle::ThrottleCheckResult
@@ -128,12 +128,12 @@
   // No need to defer the navigation if the check already happened.
   if (!database_client_ || check_results_.back().finished) {
     NotifyResult();
-    return content::NavigationThrottle::ThrottleCheckResult::PROCEED;
+    return PROCEED;
   }
   CHECK(!deferring_);
   deferring_ = true;
   defer_time_ = base::TimeTicks::Now();
-  return content::NavigationThrottle::ThrottleCheckResult::DEFER;
+  return DEFER;
 }
 
 const char*
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
index 16bb301..5ee61533 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -255,7 +255,7 @@
     auto simulator = content::NavigationSimulator::CreateRendererInitiated(
         GURL("https://example.test/disallowed.html"), subframe);
     simulator->Commit();
-    return simulator->GetLastThrottleCheckResult() ==
+    return simulator->GetLastThrottleCheckResult().action() ==
                    content::NavigationThrottle::PROCEED
                ? simulator->GetFinalRenderFrameHost()
                : nullptr;
@@ -280,7 +280,7 @@
         content::NavigationSimulator::CreateRendererInitiated(first_url, rfh);
     navigation_simulator_->Start();
     auto result = navigation_simulator_->GetLastThrottleCheckResult();
-    if (result == content::NavigationThrottle::CANCEL)
+    if (result.action() == content::NavigationThrottle::CANCEL)
       navigation_simulator_.reset();
     return result;
   }
@@ -289,7 +289,7 @@
       const GURL& new_url) {
     navigation_simulator_->Redirect(new_url);
     auto result = navigation_simulator_->GetLastThrottleCheckResult();
-    if (result == content::NavigationThrottle::CANCEL)
+    if (result.action() == content::NavigationThrottle::CANCEL)
       navigation_simulator_.reset();
     return result;
   }
diff --git a/components/viz/common/resources/platform_color.h b/components/viz/common/resources/platform_color.h
index 9c0fa1e..5a6caba5 100644
--- a/components/viz/common/resources/platform_color.h
+++ b/components/viz/common/resources/platform_color.h
@@ -60,6 +60,7 @@
       case RED_8:
       case LUMINANCE_F16:
       case RGBA_F16:
+      case R16_EXT:
         NOTREACHED();
         return false;
     }
diff --git a/components/viz/common/resources/platform_color_unittest.cc b/components/viz/common/resources/platform_color_unittest.cc
index f8012176..feab684 100644
--- a/components/viz/common/resources/platform_color_unittest.cc
+++ b/components/viz/common/resources/platform_color_unittest.cc
@@ -33,6 +33,7 @@
       case RED_8:
       case LUMINANCE_F16:
       case RGBA_F16:
+      case R16_EXT:
         break;
     }
   }
diff --git a/components/viz/common/resources/resource_format.h b/components/viz/common/resources/resource_format.h
index 1e90781..265a064cb 100644
--- a/components/viz/common/resources/resource_format.h
+++ b/components/viz/common/resources/resource_format.h
@@ -20,7 +20,8 @@
   RED_8,
   LUMINANCE_F16,
   RGBA_F16,
-  RESOURCE_FORMAT_MAX = RGBA_F16,
+  R16_EXT,
+  RESOURCE_FORMAT_MAX = R16_EXT,
 };
 
 }  // namespace viz
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc
index 4cee8649..161290a 100644
--- a/components/viz/common/resources/resource_format_utils.cc
+++ b/components/viz/common/resources/resource_format_utils.cc
@@ -29,6 +29,7 @@
     case ETC1:
     case RED_8:
     case LUMINANCE_F16:
+    case R16_EXT:
       return kN32_SkColorType;
     case RGBA_F16:
       return kRGBA_F16_SkColorType;
@@ -47,6 +48,7 @@
     case RGBA_4444:
     case RGB_565:
     case LUMINANCE_F16:
+    case R16_EXT:
       return 16;
     case ALPHA_8:
     case LUMINANCE_8:
@@ -72,6 +74,7 @@
       GL_UNSIGNED_BYTE,           // RED_8
       GL_HALF_FLOAT_OES,          // LUMINANCE_F16
       GL_HALF_FLOAT_OES,          // RGBA_F16
+      GL_UNSIGNED_SHORT,          // R16_EXT
   };
   static_assert(arraysize(format_gl_data_type) == (RESOURCE_FORMAT_MAX + 1),
                 "format_gl_data_type does not handle all cases.");
@@ -92,6 +95,7 @@
       GL_RED_EXT,        // RED_8
       GL_LUMINANCE,      // LUMINANCE_F16
       GL_RGBA,           // RGBA_F16
+      GL_R16_EXT,        // R16_EXT
   };
   static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1),
                 "format_gl_data_format does not handle all cases.");
@@ -123,6 +127,7 @@
       GL_LUMINANCE,  // RED_8
       GL_LUMINANCE,  // LUMINANCE_F16
       GL_RGBA,       // RGBA_F16
+      GL_LUMINANCE,  // R16_EXT
   };
   static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1),
                 "format_gl_data_format does not handle all cases.");
@@ -135,6 +140,8 @@
       return gfx::BufferFormat::BGRA_8888;
     case RED_8:
       return gfx::BufferFormat::R_8;
+    case R16_EXT:
+      return gfx::BufferFormat::R_16;
     case RGBA_4444:
       return gfx::BufferFormat::RGBA_4444;
     case RGBA_8888:
@@ -187,6 +194,7 @@
     case ETC1:
     case RED_8:
     case LUMINANCE_F16:
+    case R16_EXT:
       return false;
   }
   NOTREACHED();
diff --git a/components/viz/common/resources/resource_settings.h b/components/viz/common/resources/resource_settings.h
index 31ab9d0..4ace644 100644
--- a/components/viz/common/resources/resource_settings.h
+++ b/components/viz/common/resources/resource_settings.h
@@ -21,6 +21,9 @@
 
   size_t texture_id_allocation_chunk_size = 64;
   bool use_gpu_memory_buffer_resources = false;
+  bool high_bit_for_testing = false;
+  // TODO(riju): Remove after r16 is used without the flag. crbug.com/759456
+  bool use_r16_texture = false;
   BufferToTextureTargetMap buffer_to_texture_target_map;
 };
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 31a250f..aae0db5 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -328,25 +328,12 @@
 MSVC_DISABLE_OPTIMIZE()
 MSVC_PUSH_DISABLE_WARNING(4748)
 
-NOINLINE void ResetThread_DB() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::DB);
-}
-
 NOINLINE void ResetThread_FILE() {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
   BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::FILE);
 }
 
-NOINLINE void ResetThread_FILE_USER_BLOCKING() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  BrowserThreadImpl::StopRedirectionOfThreadID(
-      BrowserThread::FILE_USER_BLOCKING);
-}
-
 #if defined(OS_ANDROID)
 NOINLINE void ResetThread_PROCESS_LAUNCHER(
     std::unique_ptr<BrowserProcessSubThread> thread) {
@@ -362,21 +349,6 @@
 }
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_WIN)
-NOINLINE void ResetThread_CACHE(
-    std::unique_ptr<BrowserProcessSubThread> thread) {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-    thread.reset();
-}
-#else   // defined(OS_WIN)
-NOINLINE void ResetThread_CACHE() {
-  volatile int inhibit_comdat = __LINE__;
-  ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::CACHE);
-}
-#endif  // defined(OS_WIN)
-
 NOINLINE void ResetThread_IO(std::unique_ptr<BrowserProcessSubThread> thread) {
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
@@ -1059,18 +1031,6 @@
         base::TaskShutdownBehavior::BLOCK_SHUTDOWN};
 
     switch (thread_id) {
-      case BrowserThread::DB:
-        TRACE_EVENT_BEGIN1("startup",
-            "BrowserMainLoop::CreateThreads:start",
-            "Thread", "BrowserThread::DB");
-        non_ui_non_io_task_runner_traits = kUserVisibleTraits;
-        break;
-      case BrowserThread::FILE_USER_BLOCKING:
-        TRACE_EVENT_BEGIN1("startup",
-            "BrowserMainLoop::CreateThreads:start",
-            "Thread", "BrowserThread::FILE_USER_BLOCKING");
-        non_ui_non_io_task_runner_traits = kUserBlockingTraits;
-        break;
       case BrowserThread::FILE:
         TRACE_EVENT_BEGIN1("startup",
             "BrowserMainLoop::CreateThreads:start",
@@ -1092,23 +1052,6 @@
         non_ui_non_io_task_runner_traits = kUserBlockingTraits;
 #endif  // defined(OS_ANDROID)
         break;
-      case BrowserThread::CACHE:
-        TRACE_EVENT_BEGIN1("startup",
-            "BrowserMainLoop::CreateThreads:start",
-            "Thread", "BrowserThread::CACHE");
-#if defined(OS_WIN)
-        // TaskScheduler doesn't support async I/O on Windows as CACHE thread is
-        // the only user and this use case is going away in
-        // https://codereview.chromium.org/2216583003/.
-        // TODO(gavinp): Remove this ifdef (and thus enable redirection of the
-        // CACHE thread on Windows) once that CL lands.
-        thread_to_start = &cache_thread_;
-        options = io_message_loop_options;
-        options.timer_slack = base::TIMER_SLACK_MAXIMUM;
-#else  // OS_WIN
-        non_ui_non_io_task_runner_traits = kUserBlockingTraits;
-#endif  // OS_WIN
-        break;
       case BrowserThread::IO:
         TRACE_EVENT_BEGIN1("startup",
             "BrowserMainLoop::CreateThreads:start",
@@ -1306,14 +1249,7 @@
       // - The PROCESS_LAUNCHER thread must be stopped after IO in case
       //   the IO thread posted a task to terminate a process on the
       //   process launcher thread.
-      //
-      // - (Not sure why DB stops last.)
       switch (thread_id) {
-        case BrowserThread::DB: {
-          TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread");
-          ResetThread_DB();
-          break;
-        }
         case BrowserThread::FILE: {
           TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread");
           // Clean up state that lives on or uses the FILE thread before it goes
@@ -1323,12 +1259,6 @@
           ResetThread_FILE();
           break;
         }
-        case BrowserThread::FILE_USER_BLOCKING: {
-          TRACE_EVENT0("shutdown",
-                       "BrowserMainLoop::Subsystem:FileUserBlockingThread");
-          ResetThread_FILE_USER_BLOCKING();
-          break;
-        }
         case BrowserThread::PROCESS_LAUNCHER: {
           TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread");
 #if defined(OS_ANDROID)
@@ -1338,15 +1268,6 @@
 #endif  // defined(OS_ANDROID)
           break;
         }
-        case BrowserThread::CACHE: {
-          TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread");
-#if defined(OS_WIN)
-          ResetThread_CACHE(std::move(cache_thread_));
-#else   // defined(OS_WIN)
-          ResetThread_CACHE();
-#endif  // defined(OS_WIN)
-          break;
-        }
         case BrowserThread::IO: {
           TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread");
           ResetThread_IO(std::move(io_thread_));
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index d341e72d..fa962f29 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -316,13 +316,6 @@
   // On Android, the PROCESS_LAUNCHER thread is handled by Java,
   // |process_launcher_thread_| is merely a proxy to the real message loop.
   std::unique_ptr<BrowserProcessSubThread> process_launcher_thread_;
-#elif defined(OS_WIN)
-  // TaskScheduler doesn't support async I/O on Windows as CACHE thread is
-  // the only user and this use case is going away in
-  // https://codereview.chromium.org/2216583003/.
-  // TODO(gavinp): Remove this (and thus enable redirection of the CACHE thread
-  // on Windows) once that CL lands.
-  std::unique_ptr<BrowserProcessSubThread> cache_thread_;
 #endif
 
   // Members initialized in |BrowserThreadsStarted()| --------------------------
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 8bb84ee..a222c790 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -34,11 +34,8 @@
 // Friendly names for the well-known threads.
 static const char* const g_browser_thread_names[BrowserThread::ID_COUNT] = {
   "",  // UI (name assembled in browser_main.cc).
-  "Chrome_DBThread",  // DB
   "Chrome_FileThread",  // FILE
-  "Chrome_FileUserBlockingThread",  // FILE_USER_BLOCKING
   "Chrome_ProcessLauncherThread",  // PROCESS_LAUNCHER
-  "Chrome_CacheThread",  // CACHE
   "Chrome_IOThread",  // IO
 };
 
@@ -211,11 +208,8 @@
   }
 #endif  // DCHECK_IS_ON()
 
-  if (identifier_ == BrowserThread::DB ||
-      identifier_ == BrowserThread::FILE ||
-      identifier_ == BrowserThread::FILE_USER_BLOCKING ||
-      identifier_ == BrowserThread::PROCESS_LAUNCHER ||
-      identifier_ == BrowserThread::CACHE) {
+  if (identifier_ == BrowserThread::FILE ||
+      identifier_ == BrowserThread::PROCESS_LAUNCHER) {
     // Nesting and task observers are not allowed on redirected threads.
     base::RunLoop::DisallowNestingOnCurrentThread();
     message_loop()->DisallowTaskObservers();
@@ -240,25 +234,12 @@
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::DBThreadRun(base::RunLoop* run_loop) {
-  volatile int line_number = __LINE__;
-  Thread::Run(run_loop);
-  CHECK_GT(line_number, 0);
-}
-
 NOINLINE void BrowserThreadImpl::FileThreadRun(base::RunLoop* run_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(run_loop);
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun(
-    base::RunLoop* run_loop) {
-  volatile int line_number = __LINE__;
-  Thread::Run(run_loop);
-  CHECK_GT(line_number, 0);
-}
-
 NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun(
     base::RunLoop* run_loop) {
   volatile int line_number = __LINE__;
@@ -266,12 +247,6 @@
   CHECK_GT(line_number, 0);
 }
 
-NOINLINE void BrowserThreadImpl::CacheThreadRun(base::RunLoop* run_loop) {
-  volatile int line_number = __LINE__;
-  Thread::Run(run_loop);
-  CHECK_GT(line_number, 0);
-}
-
 NOINLINE void BrowserThreadImpl::IOThreadRun(base::RunLoop* run_loop) {
   volatile int line_number = __LINE__;
   Thread::Run(run_loop);
@@ -298,16 +273,10 @@
   switch (identifier_) {
     case BrowserThread::UI:
       return UIThreadRun(run_loop);
-    case BrowserThread::DB:
-      return DBThreadRun(run_loop);
     case BrowserThread::FILE:
       return FileThreadRun(run_loop);
-    case BrowserThread::FILE_USER_BLOCKING:
-      return FileUserBlockingThreadRun(run_loop);
     case BrowserThread::PROCESS_LAUNCHER:
       return ProcessLauncherThreadRun(run_loop);
-    case BrowserThread::CACHE:
-      return CacheThreadRun(run_loop);
     case BrowserThread::IO:
       return IOThreadRun(run_loop);
     case BrowserThread::ID_COUNT:
diff --git a/content/browser/browser_thread_impl.h b/content/browser/browser_thread_impl.h
index 00681000..050fae4e 100644
--- a/content/browser/browser_thread_impl.h
+++ b/content/browser/browser_thread_impl.h
@@ -78,11 +78,8 @@
   // The following are unique function names that makes it possible to tell
   // the thread id from the callstack alone in crash dumps.
   void UIThreadRun(base::RunLoop* run_loop);
-  void DBThreadRun(base::RunLoop* run_loop);
   void FileThreadRun(base::RunLoop* run_loop);
-  void FileUserBlockingThreadRun(base::RunLoop* run_loop);
   void ProcessLauncherThreadRun(base::RunLoop* run_loop);
-  void CacheThreadRun(base::RunLoop* run_loop);
   void IOThreadRun(base::RunLoop* run_loop);
 
   static bool PostTaskHelper(BrowserThread::ID identifier,
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 2e3951c..20c97cb 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -566,9 +566,9 @@
   NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
     if (network_handler_ && network_handler_->ShouldCancelNavigation(
                                 navigation_handle()->GetGlobalRequestID())) {
-      return ThrottleCheckResult::CANCEL_AND_IGNORE;
+      return CANCEL_AND_IGNORE;
     }
-    return ThrottleCheckResult::PROCEED;
+    return PROCEED;
   }
 
   const char* GetNameForLogging() override {
diff --git a/content/browser/frame_host/form_submission_throttle_browsertest.cc b/content/browser/frame_host/form_submission_throttle_browsertest.cc
index b3aec72..5632154 100644
--- a/content/browser/frame_host/form_submission_throttle_browsertest.cc
+++ b/content/browser/frame_host/form_submission_throttle_browsertest.cc
@@ -33,8 +33,8 @@
   const struct {
     GURL main_page_url;
     GURL form_page_url;
-    NavigationThrottle::ThrottleCheckResult start_expectation;
-    NavigationThrottle::ThrottleCheckResult redirect_expectation;
+    NavigationThrottle::ThrottleAction start_expectation;
+    NavigationThrottle::ThrottleAction redirect_expectation;
   } kTestCases[] = {
       // Form submissions is allowed by default when there is no CSP.
       {
diff --git a/content/browser/frame_host/mixed_content_navigation_throttle.cc b/content/browser/frame_host/mixed_content_navigation_throttle.cc
index d0a7466..fd45a48 100644
--- a/content/browser/frame_host/mixed_content_navigation_throttle.cc
+++ b/content/browser/frame_host/mixed_content_navigation_throttle.cc
@@ -127,26 +127,27 @@
 
 MixedContentNavigationThrottle::~MixedContentNavigationThrottle() {}
 
-ThrottleCheckResult MixedContentNavigationThrottle::WillStartRequest() {
+NavigationThrottle::ThrottleCheckResult
+MixedContentNavigationThrottle::WillStartRequest() {
   bool should_block = ShouldBlockNavigation(false);
-  return should_block ? ThrottleCheckResult::CANCEL
-                      : ThrottleCheckResult::PROCEED;
+  return should_block ? CANCEL : PROCEED;
 }
 
-ThrottleCheckResult MixedContentNavigationThrottle::WillRedirectRequest() {
+NavigationThrottle::ThrottleCheckResult
+MixedContentNavigationThrottle::WillRedirectRequest() {
   // Upon redirects the same checks are to be executed as for requests.
   bool should_block = ShouldBlockNavigation(true);
-  return should_block ? ThrottleCheckResult::CANCEL
-                      : ThrottleCheckResult::PROCEED;
+  return should_block ? CANCEL : PROCEED;
 }
 
-ThrottleCheckResult MixedContentNavigationThrottle::WillProcessResponse() {
+NavigationThrottle::ThrottleCheckResult
+MixedContentNavigationThrottle::WillProcessResponse() {
   // TODO(carlosk): At this point we are about to process the request response.
   // So if we ever need to, here/now it is a good moment to check for the final
   // attained security level of the connection. For instance, does it use an
   // outdated protocol? The implementation should be based off
   // MixedContentChecker::handleCertificateError. See https://crbug.com/576270.
-  return ThrottleCheckResult::PROCEED;
+  return PROCEED;
 }
 
 const char* MixedContentNavigationThrottle::GetNameForLogging() {
diff --git a/content/browser/frame_host/mixed_content_navigation_throttle.h b/content/browser/frame_host/mixed_content_navigation_throttle.h
index c7ca00f7..7cad03b 100644
--- a/content/browser/frame_host/mixed_content_navigation_throttle.h
+++ b/content/browser/frame_host/mixed_content_navigation_throttle.h
@@ -20,8 +20,6 @@
 class FrameTreeNode;
 struct WebPreferences;
 
-using ThrottleCheckResult = NavigationThrottle::ThrottleCheckResult;
-
 // Responsible for browser-process-side mixed content security checks. It is
 // only enabled if PlzNavigate is and checks only for frame-level resource loads
 // (aka navigation loads). Sub-resources fetches are checked in the renderer
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index 2e4d0d9..bec56e0 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -588,7 +588,7 @@
   // Notify each throttle of the request.
   base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
   NavigationThrottle::ThrottleCheckResult result = CheckWillStartRequest();
-  if (result == NavigationThrottle::DEFER) {
+  if (result.action() == NavigationThrottle::DEFER) {
     if (!on_defer_callback_copy.is_null())
       on_defer_callback_copy.Run();
     // DO NOT ADD CODE: the NavigationHandle might have been destroyed during
@@ -597,7 +597,7 @@
   }
 
   TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this,
-                               "StartRequest", "result", result);
+                               "StartRequest", "result", result.action());
   RunCompleteCallback(result);
 }
 
@@ -653,7 +653,7 @@
   // Notify each throttle of the request.
   base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
   NavigationThrottle::ThrottleCheckResult result = CheckWillRedirectRequest();
-  if (result == NavigationThrottle::DEFER) {
+  if (result.action() == NavigationThrottle::DEFER) {
     if (!on_defer_callback_copy.is_null())
       on_defer_callback_copy.Run();
     // DO NOT ADD CODE: the NavigationHandle might have been destroyed during
@@ -662,7 +662,7 @@
   }
 
   TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this,
-                               "RedirectRequest", "result", result);
+                               "RedirectRequest", "result", result.action());
   RunCompleteCallback(result);
 }
 
@@ -696,7 +696,7 @@
   // Notify each throttle of the response.
   base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
   NavigationThrottle::ThrottleCheckResult result = CheckWillProcessResponse();
-  if (result == NavigationThrottle::DEFER) {
+  if (result.action() == NavigationThrottle::DEFER) {
     if (!on_defer_callback_copy.is_null())
       on_defer_callback_copy.Run();
     // DO NOT ADD CODE: the NavigationHandle might have been destroyed during
@@ -709,11 +709,12 @@
   // on its site (after any redirects).
   // Note: if MaybeTransferAndProceed returns false, this means that this
   // NavigationHandle was deleted, so return immediately.
-  if (result == NavigationThrottle::PROCEED && !MaybeTransferAndProceed())
+  if (result.action() == NavigationThrottle::PROCEED &&
+      !MaybeTransferAndProceed())
     return;
 
   TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this,
-                               "ProcessResponse", "result", result);
+                               "ProcessResponse", "result", result.action());
   RunCompleteCallback(result);
 }
 
@@ -867,8 +868,9 @@
     TRACE_EVENT_ASYNC_STEP_INTO0(
         "navigation", "NavigationHandle", this,
         base::StringPrintf("CheckWillStartRequest: %s: %d",
-                           throttles_[i]->GetNameForLogging(), result));
-    switch (result) {
+                           throttles_[i]->GetNameForLogging(),
+                           result.action()));
+    switch (result.action()) {
       case NavigationThrottle::PROCEED:
         continue;
 
@@ -913,8 +915,9 @@
     TRACE_EVENT_ASYNC_STEP_INTO0(
         "navigation", "NavigationHandle", this,
         base::StringPrintf("CheckWillRedirectRequest: %s: %d",
-                           throttles_[i]->GetNameForLogging(), result));
-    switch (result) {
+                           throttles_[i]->GetNameForLogging(),
+                           result.action()));
+    switch (result.action()) {
       case NavigationThrottle::PROCEED:
         continue;
 
@@ -966,8 +969,9 @@
     TRACE_EVENT_ASYNC_STEP_INTO0(
         "navigation", "NavigationHandle", this,
         base::StringPrintf("CheckWillProcessResponse: %s: %d",
-                           throttles_[i]->GetNameForLogging(), result));
-    switch (result) {
+                           throttles_[i]->GetNameForLogging(),
+                           result.action()));
+    switch (result.action()) {
       case NavigationThrottle::PROCEED:
         continue;
 
@@ -1004,7 +1008,7 @@
   base::Closure on_defer_callback_copy = on_defer_callback_for_testing_;
   if (state_ == DEFERRING_START) {
     result = CheckWillStartRequest();
-    if (result == NavigationThrottle::DEFER) {
+    if (result.action() == NavigationThrottle::DEFER) {
       if (!on_defer_callback_copy.is_null())
         on_defer_callback_copy.Run();
       // DO NOT ADD CODE: the NavigationHandle might have been destroyed during
@@ -1013,7 +1017,7 @@
     }
   } else if (state_ == DEFERRING_REDIRECT) {
     result = CheckWillRedirectRequest();
-    if (result == NavigationThrottle::DEFER) {
+    if (result.action() == NavigationThrottle::DEFER) {
       if (!on_defer_callback_copy.is_null())
         on_defer_callback_copy.Run();
       // DO NOT ADD CODE: the NavigationHandle might have been destroyed during
@@ -1022,7 +1026,7 @@
     }
   } else {
     result = CheckWillProcessResponse();
-    if (result == NavigationThrottle::DEFER) {
+    if (result.action() == NavigationThrottle::DEFER) {
       if (!on_defer_callback_copy.is_null())
         on_defer_callback_copy.Run();
       // DO NOT ADD CODE: the NavigationHandle might have been destroyed during
@@ -1036,10 +1040,11 @@
     // redirects).
     // Note: if MaybeTransferAndProceed returns false, this means that this
     // NavigationHandle was deleted, so return immediately.
-    if (result == NavigationThrottle::PROCEED && !MaybeTransferAndProceed())
+    if (result.action() == NavigationThrottle::PROCEED &&
+        !MaybeTransferAndProceed())
       return;
   }
-  DCHECK_NE(NavigationThrottle::DEFER, result);
+  DCHECK_NE(NavigationThrottle::DEFER, result.action());
 
   TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
                                "Resuming");
@@ -1050,14 +1055,14 @@
     NavigationThrottle::ThrottleCheckResult result) {
   DCHECK(state_ == DEFERRING_START || state_ == DEFERRING_REDIRECT ||
          state_ == DEFERRING_RESPONSE);
-  DCHECK(result == NavigationThrottle::CANCEL_AND_IGNORE ||
-         result == NavigationThrottle::CANCEL ||
-         result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
-  DCHECK(result != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE ||
+  DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
+         result.action() == NavigationThrottle::CANCEL ||
+         result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+  DCHECK(result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE ||
          state_ == DEFERRING_START ||
          (state_ == DEFERRING_REDIRECT && IsBrowserSideNavigationEnabled()));
 
-  if (result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE)
+  if (result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE)
     frame_tree_node_->SetCollapsed(true);
 
   TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
@@ -1155,7 +1160,7 @@
 
 void NavigationHandleImpl::RunCompleteCallback(
     NavigationThrottle::ThrottleCheckResult result) {
-  DCHECK(result != NavigationThrottle::DEFER);
+  DCHECK(result.action() != NavigationThrottle::DEFER);
 
   ThrottleChecksFinishedCallback callback = complete_callback_;
   complete_callback_.Reset();
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
index ab2c3778..448c5e2 100644
--- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -39,9 +39,9 @@
  public:
   TestNavigationThrottle(
       NavigationHandle* handle,
-      NavigationThrottle::ThrottleCheckResult will_start_result,
-      NavigationThrottle::ThrottleCheckResult will_redirect_result,
-      NavigationThrottle::ThrottleCheckResult will_process_result,
+      NavigationThrottle::ThrottleAction will_start_result,
+      NavigationThrottle::ThrottleAction will_redirect_result,
+      NavigationThrottle::ThrottleAction will_process_result,
       base::Closure did_call_will_start,
       base::Closure did_call_will_redirect,
       base::Closure did_call_will_process)
@@ -100,9 +100,9 @@
     return will_process_result_;
   }
 
-  NavigationThrottle::ThrottleCheckResult will_start_result_;
-  NavigationThrottle::ThrottleCheckResult will_redirect_result_;
-  NavigationThrottle::ThrottleCheckResult will_process_result_;
+  NavigationThrottle::ThrottleAction will_start_result_;
+  NavigationThrottle::ThrottleAction will_redirect_result_;
+  NavigationThrottle::ThrottleAction will_process_result_;
   base::Closure did_call_will_start_;
   base::Closure did_call_will_redirect_;
   base::Closure did_call_will_process_;
@@ -117,9 +117,9 @@
  public:
   TestNavigationThrottleInstaller(
       WebContents* web_contents,
-      NavigationThrottle::ThrottleCheckResult will_start_result,
-      NavigationThrottle::ThrottleCheckResult will_redirect_result,
-      NavigationThrottle::ThrottleCheckResult will_process_result,
+      NavigationThrottle::ThrottleAction will_start_result,
+      NavigationThrottle::ThrottleAction will_redirect_result,
+      NavigationThrottle::ThrottleAction will_process_result,
       const GURL& expected_start_url = GURL())
       : WebContentsObserver(web_contents),
         will_start_result_(will_start_result),
@@ -156,8 +156,8 @@
   }
 
   void Continue(NavigationThrottle::ThrottleCheckResult result) {
-    ASSERT_NE(NavigationThrottle::DEFER, result);
-    if (result == NavigationThrottle::PROCEED)
+    ASSERT_NE(NavigationThrottle::DEFER, result.action());
+    if (result.action() == NavigationThrottle::PROCEED)
       navigation_throttle()->ResumeNavigation();
     else
       navigation_throttle()->CancelNavigation(result);
@@ -215,9 +215,9 @@
       navigation_throttle_ = nullptr;
   }
 
-  NavigationThrottle::ThrottleCheckResult will_start_result_;
-  NavigationThrottle::ThrottleCheckResult will_redirect_result_;
-  NavigationThrottle::ThrottleCheckResult will_process_result_;
+  NavigationThrottle::ThrottleAction will_start_result_;
+  NavigationThrottle::ThrottleAction will_redirect_result_;
+  NavigationThrottle::ThrottleAction will_process_result_;
   int will_start_called_ = 0;
   int will_redirect_called_ = 0;
   int will_process_called_ = 0;
@@ -241,9 +241,9 @@
  public:
   TestDeferringNavigationThrottleInstaller(
       WebContents* web_contents,
-      NavigationThrottle::ThrottleCheckResult will_start_result,
-      NavigationThrottle::ThrottleCheckResult will_redirect_result,
-      NavigationThrottle::ThrottleCheckResult will_process_result,
+      NavigationThrottle::ThrottleAction will_start_result,
+      NavigationThrottle::ThrottleAction will_redirect_result,
+      NavigationThrottle::ThrottleAction will_process_result,
       GURL expected_start_url = GURL())
       : TestNavigationThrottleInstaller(web_contents,
                                         NavigationThrottle::DEFER,
@@ -271,9 +271,9 @@
   }
 
  private:
-  NavigationThrottle::ThrottleCheckResult will_start_deferred_result_;
-  NavigationThrottle::ThrottleCheckResult will_redirect_deferred_result_;
-  NavigationThrottle::ThrottleCheckResult will_process_deferred_result_;
+  NavigationThrottle::ThrottleAction will_start_deferred_result_;
+  NavigationThrottle::ThrottleAction will_redirect_deferred_result_;
+  NavigationThrottle::ThrottleAction will_process_deferred_result_;
 };
 
 // Records all navigation start URLs from the WebContents.
@@ -749,8 +749,8 @@
   // Exercise both synchronous and deferred throttle check results, and both on
   // WillStartRequest and on WillRedirectRequest.
   const struct {
-    NavigationThrottle::ThrottleCheckResult will_start_result;
-    NavigationThrottle::ThrottleCheckResult will_redirect_result;
+    NavigationThrottle::ThrottleAction will_start_result;
+    NavigationThrottle::ThrottleAction will_redirect_result;
     bool deferred_block;
   } kTestCases[] = {
       {NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc
index 3ffd938..f494483 100644
--- a/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/browser_side_navigation_test_utils.h"
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_render_frame_host.h"
 #include "content/test/test_web_contents.h"
@@ -304,7 +305,7 @@
   std::vector<std::unique_ptr<NavigationThrottle>> GetThrottles(
       NavigationHandle* handle) {
     auto throttle = base::MakeUnique<TestNavigationThrottle>(
-        handle, NavigationThrottle::ThrottleCheckResult::PROCEED);
+        handle, NavigationThrottle::PROCEED);
     std::vector<std::unique_ptr<NavigationThrottle>> vec;
     throttles_inserted_++;
     vec.push_back(std::move(throttle));
@@ -864,6 +865,172 @@
   EXPECT_EQ(0, proceed_throttle->will_process_response_calls());
 }
 
+TEST_F(NavigationHandleImplTest, BlockRequestCustomNetError) {
+  TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle(
+      {NavigationThrottle::BLOCK_REQUEST, net::ERR_BLOCKED_BY_ADMINISTRATOR});
+  EXPECT_EQ(0, blocked_throttle->will_start_calls());
+  EXPECT_EQ(0, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+
+  // Simulate WillRedirectRequest. The request should not be deferred. The
+  // callback should have been called. The second throttle should not have
+  // been notified.
+  SimulateWillStartRequest();
+  EXPECT_FALSE(IsDeferringStart());
+  EXPECT_FALSE(IsDeferringRedirect());
+  EXPECT_FALSE(IsDeferringResponse());
+  EXPECT_TRUE(was_callback_called());
+  EXPECT_TRUE(IsCanceling());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result().action());
+  EXPECT_EQ(net::ERR_BLOCKED_BY_ADMINISTRATOR,
+            callback_result().net_error_code());
+  EXPECT_FALSE(callback_result().error_page_content().has_value());
+  EXPECT_EQ(1, blocked_throttle->will_start_calls());
+  EXPECT_EQ(0, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+}
+
+TEST_F(NavigationHandleImplTest, BlockRequestCustomNetErrorAndErrorHTML) {
+  std::string expected_error_page_content("<html><body>test</body></html>");
+  TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle(
+      {NavigationThrottle::BLOCK_REQUEST, net::ERR_BLOCKED_BY_ADMINISTRATOR,
+       expected_error_page_content});
+  EXPECT_EQ(0, blocked_throttle->will_start_calls());
+  EXPECT_EQ(0, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+
+  // Simulate WillRedirectRequest. The request should not be deferred. The
+  // callback should have been called. The second throttle should not have
+  // been notified.
+  SimulateWillStartRequest();
+  EXPECT_FALSE(IsDeferringStart());
+  EXPECT_FALSE(IsDeferringRedirect());
+  EXPECT_FALSE(IsDeferringResponse());
+  EXPECT_TRUE(was_callback_called());
+  EXPECT_TRUE(IsCanceling());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result());
+  EXPECT_EQ(net::ERR_BLOCKED_BY_ADMINISTRATOR,
+            callback_result().net_error_code());
+  EXPECT_TRUE(callback_result().error_page_content().has_value());
+  EXPECT_EQ(expected_error_page_content,
+            callback_result().error_page_content().value());
+  EXPECT_EQ(1, blocked_throttle->will_start_calls());
+  EXPECT_EQ(0, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+}
+
+TEST_F(NavigationHandleImplTest, BlockRequestCustomNetErrorInRedirect) {
+  // BLOCK_REQUEST on redirect requires PlzNavigate.
+  EnableBrowserSideNavigation();
+  TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle(
+      {NavigationThrottle::BLOCK_REQUEST, net::ERR_FILE_NOT_FOUND});
+  EXPECT_EQ(0, blocked_throttle->will_start_calls());
+  EXPECT_EQ(0, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+
+  // Simulate WillRedirectRequest. The request should not be deferred. The
+  // callback should have been called. The second throttle should not have
+  // been notified.
+  SimulateWillRedirectRequest();
+  EXPECT_FALSE(IsDeferringStart());
+  EXPECT_FALSE(IsDeferringRedirect());
+  EXPECT_FALSE(IsDeferringResponse());
+  EXPECT_TRUE(was_callback_called());
+  EXPECT_TRUE(IsCanceling());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result().action());
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, callback_result().net_error_code());
+  EXPECT_FALSE(callback_result().error_page_content().has_value());
+  EXPECT_EQ(0, blocked_throttle->will_start_calls());
+  EXPECT_EQ(1, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+}
+
+TEST_F(NavigationHandleImplTest,
+       BlockRequestCustomNetErrorAndErrorHTMLInRedirect) {
+  // BLOCK_REQUEST on redirect requires PlzNavigate.
+  EnableBrowserSideNavigation();
+  std::string expected_error_page_content("<html><body>test</body></html>");
+  TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle(
+      {NavigationThrottle::BLOCK_REQUEST, net::ERR_FILE_NOT_FOUND,
+       expected_error_page_content});
+  EXPECT_EQ(0, blocked_throttle->will_start_calls());
+  EXPECT_EQ(0, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+
+  // Simulate WillRedirectRequest. The request should not be deferred. The
+  // callback should have been called. The second throttle should not have
+  // been notified.
+  SimulateWillRedirectRequest();
+  EXPECT_FALSE(IsDeferringStart());
+  EXPECT_FALSE(IsDeferringRedirect());
+  EXPECT_FALSE(IsDeferringResponse());
+  EXPECT_TRUE(was_callback_called());
+  EXPECT_TRUE(IsCanceling());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result());
+  EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result().action());
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, callback_result().net_error_code());
+  EXPECT_TRUE(callback_result().error_page_content().has_value());
+  EXPECT_EQ(expected_error_page_content,
+            callback_result().error_page_content().value());
+  EXPECT_EQ(0, blocked_throttle->will_start_calls());
+  EXPECT_EQ(1, blocked_throttle->will_redirect_calls());
+  EXPECT_EQ(0, blocked_throttle->will_process_response_calls());
+}
+
+TEST_F(NavigationHandleImplTest, BlockResponseCustomNetError) {
+  TestNavigationThrottle* block_throttle = CreateTestNavigationThrottle(
+      {NavigationThrottle::BLOCK_RESPONSE, net::ERR_FILE_VIRUS_INFECTED});
+  EXPECT_EQ(0, block_throttle->will_start_calls());
+  EXPECT_EQ(0, block_throttle->will_redirect_calls());
+  EXPECT_EQ(0, block_throttle->will_process_response_calls());
+  // Simulate WillRedirectRequest. The request should not be deferred. The
+  // callback should have been called. The second throttle should not have
+  // been notified.
+  SimulateWillProcessResponse();
+  EXPECT_FALSE(IsDeferringStart());
+  EXPECT_FALSE(IsDeferringRedirect());
+  EXPECT_FALSE(IsDeferringResponse());
+  EXPECT_TRUE(was_callback_called());
+  EXPECT_TRUE(IsCanceling());
+  EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result());
+  EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result().action());
+  EXPECT_EQ(net::ERR_FILE_VIRUS_INFECTED, callback_result().net_error_code());
+  EXPECT_FALSE(callback_result().error_page_content().has_value());
+  EXPECT_EQ(0, block_throttle->will_start_calls());
+  EXPECT_EQ(0, block_throttle->will_redirect_calls());
+  EXPECT_EQ(1, block_throttle->will_process_response_calls());
+}
+
+TEST_F(NavigationHandleImplTest, BlockResponseCustomNetErrorAndErrorHTML) {
+  std::string expected_error_page_content("<html><body>test</body></html>");
+  TestNavigationThrottle* block_throttle = CreateTestNavigationThrottle(
+      {NavigationThrottle::BLOCK_RESPONSE, net::ERR_FILE_VIRUS_INFECTED,
+       expected_error_page_content});
+  EXPECT_EQ(0, block_throttle->will_start_calls());
+  EXPECT_EQ(0, block_throttle->will_redirect_calls());
+  EXPECT_EQ(0, block_throttle->will_process_response_calls());
+  // Simulate WillRedirectRequest. The request should not be deferred. The
+  // callback should have been called. The second throttle should not have
+  // been notified.
+  SimulateWillProcessResponse();
+  EXPECT_FALSE(IsDeferringStart());
+  EXPECT_FALSE(IsDeferringRedirect());
+  EXPECT_FALSE(IsDeferringResponse());
+  EXPECT_TRUE(was_callback_called());
+  EXPECT_TRUE(IsCanceling());
+  EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result());
+  EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result().action());
+  EXPECT_EQ(net::ERR_FILE_VIRUS_INFECTED, callback_result().net_error_code());
+  EXPECT_TRUE(callback_result().error_page_content().has_value());
+  EXPECT_EQ(expected_error_page_content,
+            callback_result().error_page_content().value());
+  EXPECT_EQ(0, block_throttle->will_start_calls());
+  EXPECT_EQ(0, block_throttle->will_redirect_calls());
+  EXPECT_EQ(1, block_throttle->will_process_response_calls());
+}
+
 // Checks that a NavigationHandle can be safely deleted by teh execution of one
 // of its NavigationThrottle.
 TEST_F(NavigationHandleImplTest, DeletionByNavigationThrottle) {
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index ccc28ea8..d108ff7 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -825,31 +825,32 @@
 
 void NavigationRequest::OnStartChecksComplete(
     NavigationThrottle::ThrottleCheckResult result) {
-  DCHECK(result != NavigationThrottle::DEFER);
-  DCHECK(result != NavigationThrottle::BLOCK_RESPONSE);
+  DCHECK(result.action() != NavigationThrottle::DEFER);
+  DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
 
   if (on_start_checks_complete_closure_)
     on_start_checks_complete_closure_.Run();
   // Abort the request if needed. This will destroy the NavigationRequest.
-  if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
-      result == NavigationThrottle::CANCEL ||
-      result == NavigationThrottle::BLOCK_REQUEST ||
-      result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
+  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
+      result.action() == NavigationThrottle::CANCEL ||
+      result.action() == NavigationThrottle::BLOCK_REQUEST ||
+      result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
     // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
-    int error_code = net::ERR_ABORTED;
-    if (result == NavigationThrottle::BLOCK_REQUEST ||
-        result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
-      error_code = net::ERR_BLOCKED_BY_CLIENT;
-    }
+    DCHECK_EQ((result.action() == NavigationThrottle::CANCEL ||
+               result.action() == NavigationThrottle::CANCEL_AND_IGNORE)
+                  ? net::ERR_ABORTED
+                  : net::ERR_BLOCKED_BY_CLIENT,
+              result.net_error_code());
 
     // If the start checks completed synchronously, which could happen if there
     // is no onbeforeunload handler or if a NavigationThrottle cancelled it,
     // then this could cause reentrancy into NavigationController. So use a
     // PostTask to avoid that.
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::BindOnce(&NavigationRequest::OnRequestFailed,
-                                           weak_factory_.GetWeakPtr(), false,
-                                           error_code, base::nullopt, false));
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&NavigationRequest::OnRequestFailed,
+                       weak_factory_.GetWeakPtr(), false,
+                       result.net_error_code(), base::nullopt, false));
 
     // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
     // destroyed the NavigationRequest.
@@ -937,23 +938,25 @@
 
 void NavigationRequest::OnRedirectChecksComplete(
     NavigationThrottle::ThrottleCheckResult result) {
-  DCHECK(result != NavigationThrottle::DEFER);
-  DCHECK(result != NavigationThrottle::BLOCK_RESPONSE);
+  DCHECK(result.action() != NavigationThrottle::DEFER);
+  DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
 
   // Abort the request if needed. This will destroy the NavigationRequest.
-  if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
-      result == NavigationThrottle::CANCEL) {
+  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
+      result.action() == NavigationThrottle::CANCEL) {
     // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE if needed.
-    OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
+    DCHECK_EQ(net::ERR_ABORTED, result.net_error_code());
+    OnRequestFailed(false, result.net_error_code(), base::nullopt, false);
 
     // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
     // destroyed the NavigationRequest.
     return;
   }
 
-  if (result == NavigationThrottle::BLOCK_REQUEST ||
-      result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
-    OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt, false);
+  if (result.action() == NavigationThrottle::BLOCK_REQUEST ||
+      result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
+    DCHECK_EQ(net::ERR_BLOCKED_BY_CLIENT, result.net_error_code());
+    OnRequestFailed(false, result.net_error_code(), base::nullopt, false);
     // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
     // destroyed the NavigationRequest.
     return;
@@ -964,28 +967,34 @@
 
 void NavigationRequest::OnWillProcessResponseChecksComplete(
     NavigationThrottle::ThrottleCheckResult result) {
-  DCHECK(result != NavigationThrottle::DEFER);
+  DCHECK(result.action() != NavigationThrottle::DEFER);
 
   // If the NavigationThrottles allowed the navigation to continue, have the
   // processing of the response resume in the network stack.
-  if (result == NavigationThrottle::PROCEED)
+  if (result.action() == NavigationThrottle::PROCEED)
     loader_->ProceedWithResponse();
 
   // Abort the request if needed. This includes requests that were blocked by
   // NavigationThrottles and requests that should not commit (e.g. downloads,
   // 204/205s). This will destroy the NavigationRequest.
-  if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
-      result == NavigationThrottle::CANCEL || !response_should_be_rendered_) {
+  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
+      result.action() == NavigationThrottle::CANCEL ||
+      !response_should_be_rendered_) {
+    int net_error = result.net_error_code();
+    if (!response_should_be_rendered_)
+      net_error = net::ERR_ABORTED;
     // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
-    OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false);
+    DCHECK_EQ(net::ERR_ABORTED, net_error);
+    OnRequestFailed(false, net_error, base::nullopt, false);
 
     // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
     // destroyed the NavigationRequest.
     return;
   }
 
-  if (result == NavigationThrottle::BLOCK_RESPONSE) {
-    OnRequestFailed(false, net::ERR_BLOCKED_BY_RESPONSE, base::nullopt, false);
+  if (result.action() == NavigationThrottle::BLOCK_RESPONSE) {
+    DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code());
+    OnRequestFailed(false, result.net_error_code(), base::nullopt, false);
     // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
     // destroyed the NavigationRequest.
     return;
diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc
index 5cfee32..825bae6 100644
--- a/content/browser/loader/navigation_resource_throttle.cc
+++ b/content/browser/loader/navigation_resource_throttle.cc
@@ -48,7 +48,7 @@
 void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
                                NavigationThrottle::ThrottleCheckResult result) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK_NE(result, NavigationThrottle::DEFER);
+  DCHECK_NE(result.action(), NavigationThrottle::DEFER);
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                           base::BindOnce(callback, result));
 }
@@ -344,19 +344,20 @@
 void NavigationResourceThrottle::OnUIChecksPerformed(
     NavigationThrottle::ThrottleCheckResult result) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK_NE(NavigationThrottle::DEFER, result);
+  DCHECK_NE(NavigationThrottle::DEFER, result.action());
   if (in_cross_site_transition_) {
     on_transfer_done_result_ = result;
     return;
   }
 
-  if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
-      result == NavigationThrottle::CANCEL) {
+  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
+      result.action() == NavigationThrottle::CANCEL) {
     Cancel();
-  } else if (result == NavigationThrottle::BLOCK_REQUEST ||
-             result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
+  } else if (result.action() == NavigationThrottle::BLOCK_REQUEST ||
+             result.action() ==
+                 NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
     CancelWithError(net::ERR_BLOCKED_BY_CLIENT);
-  } else if (result == NavigationThrottle::BLOCK_RESPONSE) {
+  } else if (result.action() == NavigationThrottle::BLOCK_RESPONSE) {
     // TODO(mkwst): If we cancel the main frame request with anything other than
     // 'net::ERR_ABORTED', we'll trigger some special behavior that might not be
     // desirable here (non-POSTs will reload the page, while POST has some logic
@@ -389,7 +390,7 @@
 
   // If the results of the checks on the UI thread are known, unblock the
   // navigation. Otherwise, wait until the callback has executed.
-  if (on_transfer_done_result_ != NavigationThrottle::DEFER) {
+  if (on_transfer_done_result_.action() != NavigationThrottle::DEFER) {
     OnUIChecksPerformed(on_transfer_done_result_);
     on_transfer_done_result_ = NavigationThrottle::DEFER;
   }
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index 47bcbfc8..7a27813f 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -68,9 +68,6 @@
     // The main thread in the browser.
     UI,
 
-    // This is the thread that interacts with the database.
-    DB,
-
     // This is the thread that interacts with the file system.
     // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes
     // requiring a background file I/O task runner, i.e.:
@@ -81,23 +78,11 @@
     //         is visible but non-blocking to the user.
     FILE,
 
-    // Used for file system operations that block user interactions.
-    // Responsiveness of this thread affect users.
-    // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes
-    // requiring a user-blocking file I/O task runner, i.e.:
-    //   base::CreateSequencedTaskRunnerWithTraits(
-    //       {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
-    FILE_USER_BLOCKING,
-
     // Used to launch and terminate Chrome processes.
     PROCESS_LAUNCHER,
 
-    // This is the thread to handle slow HTTP cache operations.
-    CACHE,
-
     // This is the thread that processes non-blocking IO, i.e. IPC and network.
-    // Blocking IO should happen on other threads like DB, FILE,
-    // FILE_USER_BLOCKING and CACHE depending on the usage.
+    // Blocking IO should happen in TaskScheduler.
     IO,
 
     // NOTE: do not add new threads here that are only used by a small number of
@@ -321,7 +306,6 @@
   struct DeleteOnUIThread : public DeleteOnThread<UI> { };
   struct DeleteOnIOThread : public DeleteOnThread<IO> { };
   struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
-  struct DeleteOnDBThread : public DeleteOnThread<DB> { };
 
   // Returns an appropriate error message for when DCHECK_CURRENTLY_ON() fails.
   static std::string GetDCheckCurrentlyOnErrorMessage(ID expected);
diff --git a/content/public/browser/navigation_throttle.cc b/content/public/browser/navigation_throttle.cc
index 0e71b15..5b4e358 100644
--- a/content/public/browser/navigation_throttle.cc
+++ b/content/public/browser/navigation_throttle.cc
@@ -8,6 +8,55 @@
 
 namespace content {
 
+namespace {
+
+net::Error DefaultNetErrorCode(NavigationThrottle::ThrottleAction action) {
+  switch (action) {
+    case NavigationThrottle::PROCEED:
+    case NavigationThrottle::DEFER:
+      return net::OK;
+    case NavigationThrottle::CANCEL:
+    case NavigationThrottle::CANCEL_AND_IGNORE:
+      return net::ERR_ABORTED;
+    case NavigationThrottle::BLOCK_REQUEST:
+    case NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE:
+      return net::ERR_BLOCKED_BY_CLIENT;
+    case NavigationThrottle::BLOCK_RESPONSE:
+      return net::ERR_BLOCKED_BY_RESPONSE;
+    default:
+      NOTREACHED();
+      return net::ERR_UNEXPECTED;
+  }
+}
+
+}  // namespace
+
+NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult(
+    NavigationThrottle::ThrottleAction action)
+    : NavigationThrottle::ThrottleCheckResult(action,
+                                              DefaultNetErrorCode(action),
+                                              base::nullopt) {}
+
+NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult(
+    NavigationThrottle::ThrottleAction action,
+    net::Error net_error_code)
+    : NavigationThrottle::ThrottleCheckResult(action,
+                                              net_error_code,
+                                              base::nullopt) {}
+
+NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult(
+    NavigationThrottle::ThrottleAction action,
+    net::Error net_error_code,
+    base::Optional<std::string> error_page_content)
+    : action_(action),
+      net_error_code_(net_error_code),
+      error_page_content_(error_page_content) {}
+
+NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult(
+    const ThrottleCheckResult& other) = default;
+
+NavigationThrottle::ThrottleCheckResult::~ThrottleCheckResult() {}
+
 NavigationThrottle::NavigationThrottle(NavigationHandle* navigation_handle)
     : navigation_handle_(navigation_handle) {}
 
diff --git a/content/public/browser/navigation_throttle.h b/content/public/browser/navigation_throttle.h
index bfc8062..6a77568 100644
--- a/content/public/browser/navigation_throttle.h
+++ b/content/public/browser/navigation_throttle.h
@@ -5,7 +5,9 @@
 #ifndef CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
 #define CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
 
+#include "base/optional.h"
 #include "content/common/content_export.h"
+#include "net/base/net_errors.h"
 
 namespace content {
 class NavigationHandle;
@@ -14,30 +16,30 @@
 // UI thread.
 class CONTENT_EXPORT NavigationThrottle {
  public:
-  // This is returned to the NavigationHandle to allow the navigation to
-  // proceed, or to cancel it.
-  enum ThrottleCheckResult {
+  // Represents what a NavigationThrottle can decide to do to a navigation. Note
+  // that this enum is implicitly convertable to ThrottleCheckResult.
+  enum ThrottleAction {
     // The navigation proceeds uninterrupted.
     PROCEED,
 
     // Defers the navigation until the NavigationThrottle calls
-    // NavigationHandle::Resume or NavigationHandle::CancelDeferredRequest.
-    // If the NavigationHandle is destroyed while the navigation is deferred,
-    // the navigation will be canceled in the network stack.
+    // NavigationHandle::Resume or NavigationHandle::CancelDeferredRequest. If
+    // the NavigationHandle is destroyed while the navigation is deferred, the
+    // navigation will be canceled in the network stack.
     DEFER,
 
     // Cancels the navigation.
     CANCEL,
 
-    // Cancels the navigation and makes the requester of the navigation acts
+    // Cancels the navigation and makes the requester of the navigation act
     // like the request was never made.
     CANCEL_AND_IGNORE,
 
     // Blocks a navigation due to rules asserted before the request is made.
     // This can only be returned from WillStartRequest and also from
     // WillRedirectRequest when PlzNavigate is enabled. This will result in an
-    // error page for net::ERR_BLOCKED_BY_CLIENT being loaded in the frame that
-    // is navigated.
+    // default net_error code of net::ERR_BLOCKED_BY_CLIENT being loaded in
+    // the frame that is navigated.
     BLOCK_REQUEST,
 
     // Blocks a navigation taking place in a subframe, and collapses the frame
@@ -52,6 +54,70 @@
     BLOCK_RESPONSE,
   };
 
+  // ThrottleCheckResult, the return value for NavigationThrottle decision
+  // methods, is a ThrottleAction value with an attached net::Error and an
+  // optional attached error page HTML string.
+  //
+  // ThrottleCheckResult is implicitly convertible from ThrottleAction, allowing
+  // the following examples to work:
+  //
+  //   ThrottleCheckResult WillStartRequest() override {
+  //      // Uses default error for PROCEED (net::OK).
+  //      return PROCEED;
+  //   }
+  //
+  //   ThrottleCheckResult WillStartRequest() override {
+  //      // Uses default error for BLOCK_REQUEST (net::ERR_BLOCKED_BY_CLIENT).
+  //      return BLOCK_REQUEST;
+  //   }
+  //
+  //   ThrottleCheckResult WillStartRequest() override {
+  //      // Identical to previous example (net::ERR_BLOCKED_BY_CLIENT)
+  //      return {BLOCK_REQUEST};
+  //   }
+  //
+  //   ThrottleCheckResult WillStartRequest() override {
+  //      // Uses a custom error code of ERR_FILE_NOT_FOUND.
+  //      return {BLOCK_REQUEST, net::ERR_FILE_NOT_FOUND};
+  //   }
+  //
+  //   ThrottleCheckResult WillStartRequest() override {
+  //      // Uses a custom error code of ERR_FILE_NOT_FOUND and an error page
+  //      string.
+  //      return {BLOCK_REQUEST,
+  //              net::ERR_FILE_NOT_FOUND,
+  //              std::string("<html><body>Could not find.</body></html>")};
+  //   }
+  class CONTENT_EXPORT ThrottleCheckResult {
+   public:
+    // Construct with just a ThrottleAction, using the default net::Error for
+    // that action.
+    ThrottleCheckResult(ThrottleAction action);
+
+    // Construct with an action and error.
+    ThrottleCheckResult(ThrottleAction action, net::Error net_error_code);
+
+    // Construct with an action, error, and error page HTML.
+    ThrottleCheckResult(ThrottleAction action,
+                        net::Error net_error_code,
+                        base::Optional<std::string> error_page_content);
+
+    ThrottleCheckResult(const ThrottleCheckResult& other);
+
+    ~ThrottleCheckResult();
+
+    ThrottleAction action() const { return action_; }
+    net::Error net_error_code() const { return net_error_code_; }
+    base::Optional<std::string> error_page_content() {
+      return error_page_content_;
+    }
+
+   private:
+    ThrottleAction action_;
+    net::Error net_error_code_;
+    base::Optional<std::string> error_page_content_;
+  };
+
   NavigationThrottle(NavigationHandle* navigation_handle);
   virtual ~NavigationThrottle();
 
@@ -111,6 +177,21 @@
   NavigationHandle* navigation_handle_;
 };
 
+#if defined(UNIT_TEST)
+// Test-only operator== to enable assertions like:
+//   EXPECT_EQ(NavigationThrottle::PROCEED, throttle->WillProcessResponse())
+inline bool operator==(NavigationThrottle::ThrottleAction lhs,
+                       const NavigationThrottle::ThrottleCheckResult& rhs) {
+  return lhs == rhs.action();
+}
+// Test-only operator!= to enable assertions like:
+//   EXPECT_NE(NavigationThrottle::PROCEED, throttle->WillProcessResponse())
+inline bool operator!=(NavigationThrottle::ThrottleAction lhs,
+                       const NavigationThrottle::ThrottleCheckResult& rhs) {
+  return lhs != rhs.action();
+}
+#endif
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc
index b579847..f2b69ba 100644
--- a/content/public/test/navigation_simulator.cc
+++ b/content/public/test/navigation_simulator.cc
@@ -203,7 +203,7 @@
   WaitForThrottleChecksComplete();
 
   CHECK_EQ(1, num_did_start_navigation_called_);
-  if (GetLastThrottleCheckResult() == NavigationThrottle::PROCEED) {
+  if (GetLastThrottleCheckResult().action() == NavigationThrottle::PROCEED) {
     CHECK_EQ(1, num_will_start_request_called_);
   } else {
     FailFromThrottleCheck(GetLastThrottleCheckResult());
@@ -259,7 +259,7 @@
 
   WaitForThrottleChecksComplete();
 
-  if (GetLastThrottleCheckResult() == NavigationThrottle::PROCEED) {
+  if (GetLastThrottleCheckResult().action() == NavigationThrottle::PROCEED) {
     CHECK_EQ(previous_num_will_redirect_request_called + 1,
              num_will_redirect_request_called_);
     CHECK_EQ(previous_did_redirect_navigation_called + 1,
@@ -330,7 +330,7 @@
        IsURLHandledByNetworkStack(navigation_url_))) {
     WaitForThrottleChecksComplete();
 
-    if (GetLastThrottleCheckResult() != NavigationThrottle::PROCEED) {
+    if (GetLastThrottleCheckResult().action() != NavigationThrottle::PROCEED) {
       FailFromThrottleCheck(GetLastThrottleCheckResult());
       return;
     }
@@ -849,38 +849,24 @@
 
 void NavigationSimulator::FailFromThrottleCheck(
     NavigationThrottle::ThrottleCheckResult result) {
-  DCHECK_NE(result, NavigationThrottle::PROCEED);
+  DCHECK_NE(NavigationThrottle::PROCEED, result.action());
   state_ = FAILED;
 
   // Special failure logic only needed for non-PlzNavigate case.
   if (IsBrowserSideNavigationEnabled())
     return;
-  int error_code = net::OK;
-  switch (result) {
-    case NavigationThrottle::PROCEED:
-    case NavigationThrottle::DEFER:
-      NOTREACHED();
-      break;
-    case NavigationThrottle::CANCEL:
-    case NavigationThrottle::CANCEL_AND_IGNORE:
-      error_code = net::ERR_ABORTED;
-      break;
-    case NavigationThrottle::BLOCK_REQUEST:
-    case NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE:
-      error_code = net::ERR_BLOCKED_BY_CLIENT;
-      break;
-    case NavigationThrottle::BLOCK_RESPONSE:
-      error_code = net::ERR_BLOCKED_BY_RESPONSE;
-      break;
-  };
+  DCHECK_NE(NavigationThrottle::DEFER, result.action());
+  DCHECK_NE(NavigationThrottle::PROCEED, result.action());
+  DCHECK_NE(net::OK, result.net_error_code());
 
   FrameHostMsg_DidFailProvisionalLoadWithError_Params error_params;
-  error_params.error_code = error_code;
+  error_params.error_code = result.net_error_code();
   error_params.url = navigation_url_;
   render_frame_host_->OnMessageReceived(
       FrameHostMsg_DidFailProvisionalLoadWithError(
           render_frame_host_->GetRoutingID(), error_params));
-  bool should_result_in_error_page = error_code != net::ERR_ABORTED;
+  bool should_result_in_error_page =
+      result.net_error_code() != net::ERR_ABORTED;
   if (!should_result_in_error_page) {
     render_frame_host_->OnMessageReceived(
         FrameHostMsg_DidStopLoading(render_frame_host_->GetRoutingID()));
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc
index 461c80e..864e1b9 100644
--- a/content/public/test/test_browser_thread_bundle.cc
+++ b/content/public/test/test_browser_thread_bundle.cc
@@ -45,16 +45,10 @@
   base::RunLoop().RunUntilIdle();
   io_thread_->Stop();
   base::RunLoop().RunUntilIdle();
-  cache_thread_->Stop();
-  base::RunLoop().RunUntilIdle();
   process_launcher_thread_->Stop();
   base::RunLoop().RunUntilIdle();
-  file_user_blocking_thread_->Stop();
-  base::RunLoop().RunUntilIdle();
   file_thread_->Stop();
   base::RunLoop().RunUntilIdle();
-  db_thread_->Stop();
-  base::RunLoop().RunUntilIdle();
   // This is the point at which we normally shut down the thread pool. So flush
   // it again in case any shutdown tasks have been posted to the pool from the
   // threads above.
@@ -135,14 +129,6 @@
 void TestBrowserThreadBundle::CreateBrowserThreads() {
   CHECK(!threads_created_);
 
-  if (options_ & REAL_DB_THREAD) {
-    db_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::DB);
-    db_thread_->Start();
-  } else {
-    db_thread_ = base::MakeUnique<TestBrowserThread>(
-        BrowserThread::DB, base::MessageLoop::current());
-  }
-
   if (options_ & REAL_FILE_THREAD) {
     file_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::FILE);
     file_thread_->Start();
@@ -151,12 +137,8 @@
         BrowserThread::FILE, base::MessageLoop::current());
   }
 
-  file_user_blocking_thread_ = base::MakeUnique<TestBrowserThread>(
-      BrowserThread::FILE_USER_BLOCKING, base::MessageLoop::current());
   process_launcher_thread_ = base::MakeUnique<TestBrowserThread>(
       BrowserThread::PROCESS_LAUNCHER, base::MessageLoop::current());
-  cache_thread_ = base::MakeUnique<TestBrowserThread>(
-      BrowserThread::CACHE, base::MessageLoop::current());
 
   if (options_ & REAL_IO_THREAD) {
     io_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::IO);
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h
index 079e339..dd33ee53 100644
--- a/content/public/test/test_browser_thread_bundle.h
+++ b/content/public/test/test_browser_thread_bundle.h
@@ -113,10 +113,9 @@
   enum Options {
     DEFAULT = 0,
     IO_MAINLOOP = 1 << 0,
-    REAL_DB_THREAD = 1 << 1,
-    REAL_FILE_THREAD = 1 << 2,
-    REAL_IO_THREAD = 1 << 3,
-    DONT_CREATE_BROWSER_THREADS = 1 << 4,
+    REAL_FILE_THREAD = 1 << 1,
+    REAL_IO_THREAD = 1 << 2,
+    DONT_CREATE_BROWSER_THREADS = 1 << 3,
   };
 
   TestBrowserThreadBundle();
@@ -133,11 +132,8 @@
 
   std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
   std::unique_ptr<TestBrowserThread> ui_thread_;
-  std::unique_ptr<TestBrowserThread> db_thread_;
   std::unique_ptr<TestBrowserThread> file_thread_;
-  std::unique_ptr<TestBrowserThread> file_user_blocking_thread_;
   std::unique_ptr<TestBrowserThread> process_launcher_thread_;
-  std::unique_ptr<TestBrowserThread> cache_thread_;
   std::unique_ptr<TestBrowserThread> io_thread_;
 
   int options_;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 9a176ac3..925475a 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -59,6 +59,7 @@
 #include "content/renderer/input/input_handler_manager.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
+#include "media/base/media_switches.h"
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h"
 #include "third_party/WebKit/public/platform/WebCompositorMutatorClient.h"
@@ -350,6 +351,9 @@
     bool is_threaded) {
   cc::LayerTreeSettings settings;
 
+  settings.resource_settings.use_r16_texture =
+      base::FeatureList::IsEnabled(media::kUseR16Texture);
+
   settings.commit_to_active_tree = !is_threaded;
   settings.is_layer_tree_for_subframe = is_for_subframe;
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index da67b9d5..60bba6f 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6940,11 +6940,14 @@
                                     const WebRect& selection_rect,
                                     bool final_status_update) {
   DCHECK_GE(ordinal, -1);
+  WebRect converted_rect = selection_rect;
+
+  GetRenderWidget()->ConvertViewportToWindow(&converted_rect);
 
   Send(new FrameHostMsg_Find_Reply(routing_id_,
                                    request_id,
                                    match_count,
-                                   selection_rect,
+                                   converted_rect,
                                    ordinal,
                                    final_status_update));
 }
diff --git a/extensions/browser/extension_navigation_throttle.cc b/extensions/browser/extension_navigation_throttle.cc
index 9f14c4d7f..0154a5ad 100644
--- a/extensions/browser/extension_navigation_throttle.cc
+++ b/extensions/browser/extension_navigation_throttle.cc
@@ -191,7 +191,7 @@
 content::NavigationThrottle::ThrottleCheckResult
 ExtensionNavigationThrottle::WillRedirectRequest() {
   ThrottleCheckResult result = WillStartOrRedirectRequest();
-  if (result == BLOCK_REQUEST) {
+  if (result.action() == BLOCK_REQUEST) {
     // TODO(nick): https://crbug.com/695421 means that BLOCK_REQUEST does not
     // work here. Once PlzNavigate is enabled 100%, just return |result|.
     return CANCEL;
diff --git a/ios/chrome/browser/passwords/credential_manager.h b/ios/chrome/browser/passwords/credential_manager.h
index 3b6c288..64dd23e 100644
--- a/ios/chrome/browser/passwords/credential_manager.h
+++ b/ios/chrome/browser/passwords/credential_manager.h
@@ -7,6 +7,10 @@
 
 #include "components/password_manager/core/browser/credential_manager_impl.h"
 
+namespace web {
+class WebState;
+}
+
 namespace credential_manager {
 
 // Owned by PasswordController. It is responsible for registering and handling
@@ -25,7 +29,8 @@
 //     website.
 class CredentialManager {
  public:
-  explicit CredentialManager(password_manager::PasswordManagerClient* client);
+  CredentialManager(password_manager::PasswordManagerClient* client,
+                    web::WebState* web_state);
   ~CredentialManager();
 
  private:
@@ -46,6 +51,7 @@
   void SendStoreResponse(int promise_id);
 
   password_manager::CredentialManagerImpl impl_;
+  web::WebState* web_state_;
 
   DISALLOW_COPY_AND_ASSIGN(CredentialManager);
 };
diff --git a/ios/chrome/browser/passwords/credential_manager.mm b/ios/chrome/browser/passwords/credential_manager.mm
index 3afea52..ea6baa9 100644
--- a/ios/chrome/browser/passwords/credential_manager.mm
+++ b/ios/chrome/browser/passwords/credential_manager.mm
@@ -5,7 +5,10 @@
 #import "ios/chrome/browser/passwords/credential_manager.h"
 
 #import "base/mac/bind_objc_block.h"
+#include "base/strings/utf_string_conversions.h"
 #include "ios/chrome/browser/passwords/credential_manager_util.h"
+#include "ios/chrome/browser/passwords/js_credential_manager.h"
+#import "ios/web/public/web_state/web_state.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -18,46 +21,80 @@
 
 namespace credential_manager {
 
+namespace {
+
+// Script command prefix for CM API calls. Possible commands to be sent from
+// injected JS are 'credentials.get', 'credentials.store' and
+// 'credentials.preventSilentAccess'.
+constexpr char kCommandPrefix[] = "credentials";
+
+}  // namespace
+
 CredentialManager::CredentialManager(
-    password_manager::PasswordManagerClient* client)
-    : impl_(client) {
-  // TODO(crbug.com/435047): Register a script command callback for prefix
-  // "credentials" and HandleScriptCommand method.
+    password_manager::PasswordManagerClient* client,
+    web::WebState* web_state)
+    : impl_(client), web_state_(web_state) {
+  web_state_->AddScriptCommandCallback(
+      base::Bind(&CredentialManager::HandleScriptCommand,
+                 base::Unretained(this)),
+      kCommandPrefix);
 }
 
-CredentialManager::~CredentialManager() {}
+CredentialManager::~CredentialManager() {
+  web_state_->RemoveScriptCommandCallback(kCommandPrefix);
+}
 
 bool CredentialManager::HandleScriptCommand(const base::DictionaryValue& json,
                                             const GURL& origin_url,
                                             bool user_is_interacting) {
-  // TODO(crbug.com/435047): Check if context is secure.
-  std::string command;
-  if (!json.GetString("command", &command)) {
-    DLOG(ERROR) << "RECEIVED BAD json - NO VALID 'command' FIELD";
+  double promise_id_double = -1;
+  // |promiseId| field should be an integer value, but since JavaScript has only
+  // one type for numbers (64-bit float), all numbers in the messages are sent
+  // as doubles.
+  if (!json.GetDouble("promiseId", &promise_id_double)) {
+    DLOG(ERROR) << "Received bad json - no valid 'promiseId' field";
     return false;
   }
+  int promise_id = static_cast<int>(promise_id_double);
 
-  int promise_id;
-  if (!json.GetInteger("promiseId", &promise_id)) {
-    DLOG(ERROR) << "RECEIVED BAD json - NO VALID 'promiseId' FIELD";
+  if (!WebStateContentIsSecureHtml(web_state_)) {
+    RejectPromiseWithInvalidStateError(
+        web_state_, promise_id,
+        base::ASCIIToUTF16(
+            "Credential Manager API called from insecure context"));
+    return true;
+  }
+
+  std::string command;
+  if (!json.GetString("command", &command)) {
+    DLOG(ERROR) << "Received bad json - no valid 'command' field";
     return false;
   }
 
   if (command == "credentials.get") {
     CredentialMediationRequirement mediation;
     if (!ParseMediationRequirement(json, &mediation)) {
-      // TODO(crbug.com/435047): Reject promise with a TypeError.
-      return false;
+      RejectPromiseWithTypeError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16(
+              "CredentialRequestOptions: Invalid 'mediation' value."));
+      return true;
     }
     bool include_passwords;
     if (!ParseIncludePasswords(json, &include_passwords)) {
-      // TODO(crbug.com/435047): Reject promise with a TypeError.
-      return false;
+      RejectPromiseWithTypeError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16(
+              "CredentialRequestOptions: Invalid 'password' value."));
+      return true;
     }
     std::vector<GURL> federations;
     if (!ParseFederations(json, &federations)) {
-      // TODO(crbug.com/435047): Reject promise with a TypeError.
-      return false;
+      RejectPromiseWithTypeError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16(
+              "CredentialRequestOptions: invalid 'providers' value."));
+      return true;
     }
     impl_.Get(mediation, include_passwords, federations,
               base::BindOnce(&CredentialManager::SendGetResponse,
@@ -67,7 +104,11 @@
   if (command == "credentials.store") {
     CredentialInfo credential;
     if (!ParseCredentialDictionary(json, &credential)) {
-      // TODO(crbug.com/435047): Reject promise with a TypeError.
+      // TODO(crbug.com/435047): Refactor ParseCredentialDictionary method to
+      // provide more meaningful error message.
+      RejectPromiseWithTypeError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16("Invalid Credential object."));
       return false;
     }
     impl_.Store(credential,
@@ -87,10 +128,39 @@
 void CredentialManager::SendGetResponse(
     int promise_id,
     CredentialManagerError error,
-    const base::Optional<CredentialInfo>& info) {}
+    const base::Optional<CredentialInfo>& info) {
+  switch (error) {
+    case CredentialManagerError::SUCCESS:
+      ResolvePromiseWithCredentialInfo(web_state_, promise_id, info);
+      break;
+    case CredentialManagerError::DISABLED:
+      RejectPromiseWithInvalidStateError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16("Credential Manager is disabled."));
+      break;
+    case CredentialManagerError::PENDINGREQUEST:
+      RejectPromiseWithInvalidStateError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16("Pending 'get()' request."));
+      break;
+    case CredentialManagerError::PASSWORDSTOREUNAVAILABLE:
+      RejectPromiseWithNotSupportedError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16("Password store is unavailable."));
+      break;
+    case CredentialManagerError::UNKNOWN:
+      RejectPromiseWithNotSupportedError(
+          web_state_, promise_id,
+          base::ASCIIToUTF16("Unknown error has occurred."));
+  }
+}
 
-void CredentialManager::SendPreventSilentAccessResponse(int promise_id) {}
+void CredentialManager::SendPreventSilentAccessResponse(int promise_id) {
+  ResolvePromiseWithUndefined(web_state_, promise_id);
+}
 
-void CredentialManager::SendStoreResponse(int promise_id) {}
+void CredentialManager::SendStoreResponse(int promise_id) {
+  ResolvePromiseWithUndefined(web_state_, promise_id);
+}
 
 }  // namespace credential_manager
diff --git a/ios/chrome/browser/passwords/credential_manager_unittest.mm b/ios/chrome/browser/passwords/credential_manager_unittest.mm
index f3380853..b8022a73 100644
--- a/ios/chrome/browser/passwords/credential_manager_unittest.mm
+++ b/ios/chrome/browser/passwords/credential_manager_unittest.mm
@@ -5,20 +5,38 @@
 #import "ios/chrome/browser/passwords/credential_manager.h"
 
 #include "base/mac/foundation_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/password_manager/core/browser/password_manager.h"
+#include "components/password_manager/core/browser/stub_password_manager_client.h"
+#include "components/password_manager/core/browser/test_password_store.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
 #include "ios/chrome/browser/passwords/credential_manager_util.h"
 #include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h"
 #include "ios/web/public/navigation_item.h"
 #include "ios/web/public/navigation_manager.h"
 #include "ios/web/public/ssl_status.h"
+#import "ios/web/public/test/web_js_test.h"
 #include "ios/web/public/test/web_test_with_web_state.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/test_data_directory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/origin.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+using password_manager::PasswordStore;
+using password_manager::PasswordManager;
+using password_manager::PasswordFormManager;
+using password_manager::TestPasswordStore;
+using testing::_;
+using url::Origin;
+
 namespace credential_manager {
 
 namespace {
@@ -39,14 +57,109 @@
 // SSL certificate to load for testing.
 constexpr char kCertFileName[] = "ok_cert.pem";
 
+// Mocks PasswordManagerClient, used indirectly by CredentialManager.
+class MockPasswordManagerClient
+    : public password_manager::StubPasswordManagerClient {
+ public:
+  MockPasswordManagerClient()
+      : last_committed_url_(kHttpsWebOrigin), password_manager_(this) {
+    store_ = base::MakeRefCounted<TestPasswordStore>();
+    store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
+    prefs_.registry()->RegisterBooleanPref(
+        password_manager::prefs::kCredentialsEnableAutosignin, true);
+    prefs_.registry()->RegisterBooleanPref(
+        password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, true);
+  }
+
+  // PasswordManagerClient:
+  MOCK_METHOD0(OnCredentialManagerUsed, bool());
+
+  // PromptUserTo*Ptr functions allow to both override PromptUserTo* methods
+  // and expect calls.
+  MOCK_METHOD1(PromptUserToSavePasswordPtr, void(PasswordFormManager*));
+  MOCK_METHOD3(PromptUserToChooseCredentialsPtr,
+               bool(const std::vector<autofill::PasswordForm*>& local_forms,
+                    const GURL& origin,
+                    const CredentialsCallback& callback));
+
+  scoped_refptr<TestPasswordStore> password_store() const { return store_; }
+  void set_password_store(scoped_refptr<TestPasswordStore> store) {
+    store_ = store;
+  }
+
+  PasswordFormManager* pending_manager() const { return manager_.get(); }
+
+  void set_current_url(const GURL& current_url) {
+    last_committed_url_ = current_url;
+  }
+
+ private:
+  // PasswordManagerClient:
+  PrefService* GetPrefs() override { return &prefs_; }
+  PasswordStore* GetPasswordStore() const override { return store_.get(); }
+  const PasswordManager* GetPasswordManager() const override {
+    return &password_manager_;
+  }
+  const GURL& GetLastCommittedEntryURL() const override {
+    return last_committed_url_;
+  }
+  // Stores |manager| into |manager_|. Save() should be
+  // called manually in test. To put expectation on this function being called,
+  // use PromptUserToSavePasswordPtr.
+  bool PromptUserToSaveOrUpdatePassword(
+      std::unique_ptr<PasswordFormManager> manager,
+      bool update_password) override;
+  // Mocks choosing a credential by the user. To put expectation on this
+  // function being called, use PromptUserToChooseCredentialsPtr.
+  bool PromptUserToChooseCredentials(
+      std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+      const GURL& origin,
+      const CredentialsCallback& callback) override;
+
+  TestingPrefServiceSimple prefs_;
+  GURL last_committed_url_;
+  PasswordManager password_manager_;
+  std::unique_ptr<PasswordFormManager> manager_;
+  scoped_refptr<TestPasswordStore> store_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient);
+};
+
+bool MockPasswordManagerClient::PromptUserToSaveOrUpdatePassword(
+    std::unique_ptr<PasswordFormManager> manager,
+    bool update_password) {
+  EXPECT_FALSE(update_password);
+  manager_.swap(manager);
+  PromptUserToSavePasswordPtr(manager_.get());
+  return true;
+}
+
+bool MockPasswordManagerClient::PromptUserToChooseCredentials(
+    std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
+    const GURL& origin,
+    const CredentialsCallback& callback) {
+  EXPECT_FALSE(local_forms.empty());
+  const autofill::PasswordForm* form = local_forms[0].get();
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::Bind(callback, base::Owned(new autofill::PasswordForm(*form))));
+  std::vector<autofill::PasswordForm*> raw_forms(local_forms.size());
+  std::transform(local_forms.begin(), local_forms.end(), raw_forms.begin(),
+                 [](const std::unique_ptr<autofill::PasswordForm>& form) {
+                   return form.get();
+                 });
+  PromptUserToChooseCredentialsPtr(raw_forms, origin, callback);
+  return true;
+}
+
 }  // namespace
 
-// TODO(crbug.com/435048): once JSCredentialManager is implemented and used
-// from CredentialManager methods, mock it and write unit tests for
-// CredentialManager methods SendGetResponse, SendStoreResponse and
-// SendPreventSilentAccessResponse.
-class CredentialManagerTest : public web::WebTestWithWebState {
+class CredentialManagerBaseTest
+    : public web::WebJsTest<web::WebTestWithWebState> {
  public:
+  CredentialManagerBaseTest()
+      : web::WebJsTest<web::WebTestWithWebState>(@[ @"credential_manager" ]) {}
+
   void SetUp() override {
     WebTestWithWebState::SetUp();
 
@@ -74,7 +187,559 @@
   }
 };
 
-class WebStateContentIsSecureHtmlTest : public CredentialManagerTest {};
+// Tests CredentialManager class. Tests are performed as follows:
+// 1. CredentialManager is instantiated. In its constructor it registers a
+//     script command callback for 'credentials' prefix.
+// 2. credential_manager.js is injected to the web page.
+// 3. JavaScript code invoking one of exposed API methods is executed.
+// 4. This results in CredentialManager::HandleScriptCommand being called.
+// 5. Wait for background tasks to finish, optionally for returned Promise to be
+//    resolved or rejected.
+// 6. Check values in JavaScript, stored in variables under 'test_*' prefix by
+//    resolver/rejecter functions.
+// 7. Optionally expect PasswordManagerClient methods to be (not) called.
+class CredentialManagerTest : public CredentialManagerBaseTest {
+ public:
+  void SetUp() override {
+    CredentialManagerBaseTest::SetUp();
+
+    client_ = base::MakeUnique<MockPasswordManagerClient>();
+    manager_ = base::MakeUnique<CredentialManager>(client_.get(), web_state());
+
+    // Inject JavaScript and set up secure context.
+    LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin));
+    LoadHtmlAndInject(@"<html></html>");
+    UpdateSslStatus(net::CERT_STATUS_IS_EV, web::SECURITY_STYLE_AUTHENTICATED,
+                    web::SSLStatus::NORMAL_CONTENT);
+
+    ON_CALL(*client_, OnCredentialManagerUsed())
+        .WillByDefault(testing::Return(true));
+
+    password_credential_form_1_.username_value = base::ASCIIToUTF16("id1");
+    password_credential_form_1_.display_name = base::ASCIIToUTF16("Name One");
+    password_credential_form_1_.icon_url = GURL("https://example.com/icon.png");
+    password_credential_form_1_.password_value = base::ASCIIToUTF16("secret1");
+    password_credential_form_1_.origin = GURL(kHttpsWebOrigin);
+    password_credential_form_1_.signon_realm = kHttpsWebOrigin;
+    password_credential_form_1_.scheme = autofill::PasswordForm::SCHEME_HTML;
+
+    password_credential_form_2_.username_value = base::ASCIIToUTF16("id2");
+    password_credential_form_2_.display_name = base::ASCIIToUTF16("Name Two");
+    password_credential_form_2_.icon_url = GURL("https://example.com/icon.png");
+    password_credential_form_2_.password_value = base::ASCIIToUTF16("secret2");
+    password_credential_form_2_.origin = GURL(kHttpsWebOrigin);
+    password_credential_form_2_.signon_realm = kHttpsWebOrigin;
+    password_credential_form_2_.scheme = autofill::PasswordForm::SCHEME_HTML;
+
+    federated_credential_form_.username_value = base::ASCIIToUTF16("id");
+    federated_credential_form_.display_name = base::ASCIIToUTF16("name");
+    federated_credential_form_.icon_url =
+        GURL("https://federation.com/icon.png");
+    federated_credential_form_.federation_origin =
+        Origin(GURL("https://federation.com"));
+    federated_credential_form_.origin = GURL(kHttpsWebOrigin);
+    federated_credential_form_.signon_realm =
+        "federation://www.example.com/www.federation.com";
+    federated_credential_form_.scheme = autofill::PasswordForm::SCHEME_HTML;
+  }
+
+  void TearDown() override {
+    manager_.reset();
+
+    // Shutdown PasswordStore.
+    if (client_->password_store()) {
+      client_->password_store()->ShutdownOnUIThread();
+    }
+
+    CredentialManagerBaseTest::TearDown();
+  }
+
+ protected:
+  std::unique_ptr<MockPasswordManagerClient> client_;
+  std::unique_ptr<CredentialManager> manager_;
+
+  autofill::PasswordForm password_credential_form_1_;
+  autofill::PasswordForm password_credential_form_2_;
+  autofill::PasswordForm federated_credential_form_;
+};
+
+// Tests storing a PasswordCredential.
+TEST_F(CredentialManagerTest, StorePasswordCredential) {
+  // Call API method |store|.
+  ExecuteJavaScript(
+      @"var credential = new PasswordCredential({"
+       "  id: 'id',"
+       "  password: 'pencil',"
+       "  name: 'name',"
+       "  iconURL: 'https://example.com/icon.png'"
+       "});"
+       "navigator.credentials.store(credential).then(function(result) {"
+       "  test_result_ = (result == undefined);"
+       "  test_promise_resolved_ = true;"
+       "});");
+
+  // Wait for the Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Check that Promise was resolved with undefined.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_"));
+
+  // Wait for credential to be stored.
+  WaitForBackgroundTasks();
+  client_->pending_manager()->Save();
+  WaitForBackgroundTasks();
+  EXPECT_FALSE(client_->password_store()->IsEmpty());
+
+  // Get the stored credential and check its fields.
+  TestPasswordStore::PasswordMap passwords =
+      client_->password_store()->stored_passwords();
+  EXPECT_EQ(1u, passwords.size());
+  EXPECT_EQ(1u, passwords[kHttpsWebOrigin].size());
+  autofill::PasswordForm form = passwords[kHttpsWebOrigin][0];
+  EXPECT_EQ(base::ASCIIToUTF16("id"), form.username_value);
+  EXPECT_EQ(base::ASCIIToUTF16("name"), form.display_name);
+  EXPECT_EQ(base::ASCIIToUTF16("pencil"), form.password_value);
+  EXPECT_EQ(GURL("https://example.com/icon.png"), form.icon_url);
+  EXPECT_EQ(GURL(kHttpsWebOrigin), form.origin);
+  EXPECT_EQ(GURL(kHttpsWebOrigin), form.signon_realm);
+}
+
+// Tests storing a FederatedCredential.
+TEST_F(CredentialManagerTest, StoreFederatedCredential) {
+  // Call API method |store|.
+  ExecuteJavaScript(
+      @"var credential = new FederatedCredential({"
+       "  id: 'id',"
+       "  provider: 'https://www.federation.com/',"
+       "  name: 'name',"
+       "  iconURL: 'https://federation.com/icon.png'"
+       "});"
+       "navigator.credentials.store(credential).then(function(result) {"
+       "  test_result_ = (result == undefined);"
+       "  test_promise_resolved_ = true;"
+       "});");
+
+  // Wait for the Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Check that Promise was resolved with undefined.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_"));
+
+  // Wait for credential to be stored.
+  WaitForBackgroundTasks();
+  client_->pending_manager()->Save();
+  WaitForBackgroundTasks();
+  EXPECT_FALSE(client_->password_store()->IsEmpty());
+
+  // Get the stored credential and check its fields.
+  TestPasswordStore::PasswordMap passwords =
+      client_->password_store()->stored_passwords();
+  EXPECT_EQ(1u, passwords.size());
+  std::string federated_origin =
+      "federation://www.example.com/www.federation.com";
+  EXPECT_EQ(1u, passwords[federated_origin].size());
+  autofill::PasswordForm form = passwords[federated_origin][0];
+  EXPECT_EQ(base::ASCIIToUTF16("id"), form.username_value);
+  EXPECT_EQ(base::ASCIIToUTF16("name"), form.display_name);
+  EXPECT_EQ(Origin(GURL("https://www.federation.com")), form.federation_origin);
+  EXPECT_EQ(GURL("https://federation.com/icon.png"), form.icon_url);
+  EXPECT_EQ(GURL("https://www.example.com"), form.origin);
+  EXPECT_EQ(federated_origin, form.signon_realm);
+}
+
+// Tests that storing a credential from insecure context will not happen.
+TEST_F(CredentialManagerTest, TryToStoreCredentialFromInsecureContext) {
+  // Inject JavaScript, set up WebState to have mixed content.
+  LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin));
+  LoadHtmlAndInject(@"<html></html>");
+  UpdateSslStatus(net::CERT_STATUS_IS_EV, web::SECURITY_STYLE_AUTHENTICATED,
+                  web::SSLStatus::DISPLAYED_INSECURE_CONTENT);
+
+  // Expect that user will NOT be prompted to save or update password.
+  EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_)).Times(0);
+
+  // Expect that PasswordManagerClient method used by
+  // CredentialManagerImpl::Store will not be called.
+  EXPECT_CALL(*client_, OnCredentialManagerUsed()).Times(0);
+
+  // Call API method |store|.
+  ExecuteJavaScript(
+      @"var credential = new PasswordCredential({"
+       "  id: 'id',"
+       "  password: 'pencil',"
+       "  name: 'name',"
+       "  iconURL: 'https://example.com/icon.png'"
+       "});"
+       "navigator.credentials.store(credential).catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof DOMException && "
+       "      reason.name == DOMException.INVALID_STATE_ERR);"
+       "  test_promise_rejected_ = true;"
+       "});");
+  WaitForBackgroundTasks();
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+  // Check that Promise was rejected with InvalidStateError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+}
+
+// Tests that Promise will be rejected with TypeError for invalid Credential.
+TEST_F(CredentialManagerTest, RejectOnInvalidCredential) {
+  // Call |store| with invalid Credential: |iconURL| is not a valid URL.
+  ExecuteJavaScript(
+      @"var credential = new PasswordCredential({"
+       "  id: 'id',"
+       "  password: 'pencil',"
+       "  name: 'name',"
+       "  iconURL: 'https://'"
+       "});"
+       "navigator.credentials.store(credential).catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof TypeError);"
+       "  test_promise_rejected_ = true;"
+       "});");
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+
+  // Check that Promise was rejected with TypeError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+}
+
+// Tests retrieving a PasswordCredential.
+TEST_F(CredentialManagerTest, GetPasswordCredential) {
+  // Manually store a PasswordForm in password store.
+  client_->password_store()->AddLogin(password_credential_form_1_);
+
+  // Call API method |get|.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  password: true,"
+       "  mediation: 'silent'"
+       "}).then(function(credential) {"
+       "  test_credential_ = credential; "
+       "  test_promise_resolved_ = true;"
+       "})");
+
+  // Wait for PasswordCredential to be obtained and for Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Check PasswordCredential fields.
+  ASSERT_NSEQ(@"password", ExecuteJavaScript(@"test_credential_.type"));
+  ASSERT_NSEQ(@"id1", ExecuteJavaScript(@"test_credential_.id"));
+  ASSERT_NSEQ(@"Name One", ExecuteJavaScript(@"test_credential_.name"));
+  ASSERT_NSEQ(@"secret1", ExecuteJavaScript(@"test_credential_.password"));
+  ASSERT_NSEQ(@"https://example.com/icon.png",
+              ExecuteJavaScript(@"test_credential_.iconURL"));
+}
+
+// Tests retrieving a FederatedCredential.
+TEST_F(CredentialManagerTest, GetFederatedCredential) {
+  // Manually store a PasswordForm in password store.
+  client_->password_store()->AddLogin(federated_credential_form_);
+
+  // Call API method |get|.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  providers: ['https://federation.com'], "
+       "  mediation: 'silent'"
+       "}).then(function(credential) {"
+       "  test_credential_ = credential;"
+       "  test_promise_resolved_ = true;"
+       "})");
+
+  // Wait for FederatedCredential to be obtained and for Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Check FederatedCredential fields.
+  ASSERT_NSEQ(@"federated", ExecuteJavaScript(@"test_credential_.type"));
+  ASSERT_NSEQ(@"id", ExecuteJavaScript(@"test_credential_.id"));
+  ASSERT_NSEQ(@"name", ExecuteJavaScript(@"test_credential_.name"));
+  ASSERT_NSEQ(@"https://federation.com",
+              ExecuteJavaScript(@"test_credential_.provider"));
+  ASSERT_NSEQ(@"https://federation.com/icon.png",
+              ExecuteJavaScript(@"test_credential_.iconURL"));
+}
+
+// Tests that requesting a credential from insecure context will not happen.
+TEST_F(CredentialManagerTest, TryToGetCredentialFromInsecureContext) {
+  // Set up WebState to have non-cryptographic scheme.
+  LoadHtml(@"<html></html>", GURL(kHttpWebOrigin));
+  LoadHtmlAndInject(@"<html></html>");
+  client_->set_current_url(GURL(kHttpWebOrigin));
+
+  // Expect that PasswordManagerClient method used by
+  // CredentialManagerImpl::Get will not be called.
+  EXPECT_CALL(*client_, OnCredentialManagerUsed()).Times(0);
+
+  // Call API method |get|.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  password: true,"
+       "  mediation: 'required'"
+       "}).catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof DOMException && "
+       "      reason.name == DOMException.INVALID_STATE_ERR);"
+       "  test_promise_rejected_ = true;"
+       "});");
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+  // Check that Promise was rejected with InvalidStateError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+}
+
+// Tests that when Credential is requested with required mediation, a prompt to
+// choose credential will be shown to the user.
+TEST_F(CredentialManagerTest, GetCredentialWithRequiredMediation) {
+  // Manually store a PasswordForm in password store.
+  client_->password_store()->AddLogin(password_credential_form_1_);
+
+  // Expect that user will be prompted to choose credentials.
+  EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _));
+
+  // Call API method |get|.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  password: true,"
+       "  mediation: 'required'"
+       "}).then(function(credential) {"
+       "  test_credential_ = credential; "
+       "  test_promise_resolved_ = true;"
+       "})");
+  // Wait for Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Expect that returned Credential is not null.
+  EXPECT_NSEQ(@"object", ExecuteJavaScript(@"typeof test_credential_"));
+}
+
+// Tests that Promise returned by |navigator.credentials.get| will resolve with
+// |null| if PasswordStore is empty.
+TEST_F(CredentialManagerTest, NullCredentialFromEmptyPasswordStore) {
+  // Call API method |get|.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "    password: true,"
+       "    mediation: 'silent'"
+       "}).then(function(credential) {"
+       "    test_credential_ = credential; "
+       "    test_promise_resolved_ = true;"
+       "})");
+  // Wait for Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Expect that returned Credential is null.
+  EXPECT_NSEQ(NULL, ExecuteJavaScript(@"test_credential_"));
+}
+
+// Tests that if multiple credentials are stored for a website and mediation
+// requirement is set to 'optional', user will be prompted to choose
+// credentials.
+TEST_F(CredentialManagerTest, PromptUserOnMultipleCredentials) {
+  // Manually store two PasswordForms in password store.
+  client_->password_store()->AddLogin(password_credential_form_1_);
+  client_->password_store()->AddLogin(password_credential_form_2_);
+
+  // Expect that user will be prompted to choose credentials.
+  EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _));
+
+  // Call API method |get|.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  password: true, "
+       "  mediation: 'optional'"
+       "}).then(function(credential) {"
+       "  test_credential_ = credential;"
+       "  test_promise_resolved_ = true;"
+       "})");
+  // Wait for Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Expect that returned Credential is not null.
+  EXPECT_NSEQ(@"object", ExecuteJavaScript(@"typeof test_credential_"));
+}
+
+// Tests that Promise returned by |navigator.credentials.get| is rejected with
+// TypeError if |mediation| value is invalid.
+TEST_F(CredentialManagerTest, RejectOnInvalidMediationValue) {
+  // Call API method |get| with invalid |mediation| field.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  password: true,"
+       "  mediation: 'maybe'"
+       "}).catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof TypeError);"
+       "  test_promise_rejected_ = true;"
+       "})");
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+  // Check that Promise was rejected with TypeError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+}
+
+// Tests that Promise returned by |navigator.credentials.get| is rejected with
+// TypeError if |providers| value is invalid.
+TEST_F(CredentialManagerTest, RejectOnInvalidProvidersValue) {
+  // Call API method |get| with invalid |providers| field.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  providers: 'https://exampleprovider.com' /* not a list */"
+       "}).catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof TypeError);"
+       "  test_promise_rejected_ = true;"
+       "})");
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+  // Check that Promise was rejected with TypeError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+}
+
+// Tests that Promise returned by |navigator.credentials.get| is rejected with
+// NotSupportedError if password store is not available.
+TEST_F(CredentialManagerTest, RejectOnPasswordStoreUnavailable) {
+  // Make password store unavailable.
+  client_->password_store()->ShutdownOnUIThread();
+  client_->set_password_store(nullptr);
+
+  // Call API method |get| with correct arguments, set up rejecter to store
+  // reason for failure in |test_*| variables.
+  ExecuteJavaScript(
+      @"navigator.credentials.get({"
+       "  password: true,"
+       "}).catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof DOMException) && "
+       "      (reason.name == DOMException.NOT_SUPPORTED_ERR);"
+       "  test_result_message_ = reason.message;"
+       "  test_promise_rejected_ = true;"
+       "})");
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+
+  // Check that Promise was rejected with NotSupportedError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+
+  // Check that Promise message says "Password store is unavailable."
+  EXPECT_NSEQ(@"Password store is unavailable.",
+              ExecuteJavaScript(@"test_result_message_"));
+}
+
+// Test that calling |preventSilentAccess| from insecure context will not reach
+// CredentialManagerImpl::PreventSilentAccess.
+TEST_F(CredentialManagerTest, TryToPreventSilentAccessFromInsecureContext) {
+  // Inject JavaScript, set up WebState to have non-cryptographic scheme.
+  LoadHtml(@"<html></html>", GURL(kHttpWebOrigin));
+  LoadHtmlAndInject(@"<html></html>");
+  client_->set_current_url(GURL(kHttpWebOrigin));
+
+  // Manually store a PasswordForm in password store.
+  client_->password_store()->AddLogin(password_credential_form_1_);
+
+  // Call API method |preventSilentAccess|.
+  ExecuteJavaScript(
+      @"navigator.credentials.preventSilentAccess().catch(function(reason) {"
+       "  test_result_valid_type_ = (reason instanceof DOMException && "
+       "      reason.name == DOMException.INVALID_STATE_ERR);"
+       "  test_promise_rejected_ = true;"
+       "});");
+
+  // Wait for Promise to be rejected.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]);
+  });
+  // Check that Promise was rejected with InvalidStateError.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_"));
+
+  // Check that credential in password store was not affected by the call.
+  WaitForBackgroundTasks();
+  TestPasswordStore::PasswordMap passwords =
+      client_->password_store()->stored_passwords();
+  EXPECT_EQ(1u, passwords.size());
+  ASSERT_EQ(1u, passwords[kHttpsWebOrigin].size());
+  autofill::PasswordForm form = passwords[kHttpsWebOrigin][0];
+  EXPECT_EQ(false, form.skip_zero_click);
+}
+
+// Tests that after |navigator.credentials.preventSilentAccess| is called, user
+// will be prompted to choose credentials.
+TEST_F(CredentialManagerTest, PreventSilentAccess) {
+  // Manually store two PasswordForms in password store.
+  password_credential_form_1_.skip_zero_click = false;
+  password_credential_form_2_.skip_zero_click = false;
+  client_->password_store()->AddLogin(password_credential_form_1_);
+  client_->password_store()->AddLogin(password_credential_form_2_);
+
+  // Call API method |preventSilentAccess|.
+  ExecuteJavaScript(
+      @"navigator.credentials.preventSilentAccess()"
+       ".then(function(result) {"
+       "  test_result_ = (result == undefined);"
+       "  test_promise_resolved_ = true;"
+       "});");
+
+  // Wait for Promise to be resolved.
+  WaitForCondition(^{
+    return static_cast<bool>(
+        [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]);
+  });
+
+  // Check that Promise was resolved with |undefined|.
+  EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_"));
+
+  // Check that |preventSilentAccess| set a |skip_zero_click| flag on stored
+  // credential.
+  WaitForBackgroundTasks();
+  TestPasswordStore::PasswordMap passwords =
+      client_->password_store()->stored_passwords();
+  std::vector<autofill::PasswordForm> forms = passwords[kHttpsWebOrigin];
+  ASSERT_EQ(2u, forms.size());
+  EXPECT_TRUE(forms[0].skip_zero_click);
+  EXPECT_TRUE(forms[1].skip_zero_click);
+}
+
+class WebStateContentIsSecureHtmlTest : public CredentialManagerBaseTest {};
 
 // Tests that HTTPS websites with valid SSL certificate are recognized as
 // secure.
diff --git a/ios/chrome/browser/passwords/credential_manager_util.mm b/ios/chrome/browser/passwords/credential_manager_util.mm
index a4e0f3c..32f283c 100644
--- a/ios/chrome/browser/passwords/credential_manager_util.mm
+++ b/ios/chrome/browser/passwords/credential_manager_util.mm
@@ -40,20 +40,20 @@
 
 }  // namespace
 
-const char kCredentialIdKey[] = "id";
-const char kCredentialTypeKey[] = "type";
-const char kCredentialNameKey[] = "name";
-const char kCredentialIconKey[] = "iconURL";
-const char kPasswordCredentialPasswordKey[] = "password";
-const char kFederatedCredentialProviderKey[] = "provider";
+const char kCredentialIdKey[] = "_id";
+const char kCredentialTypeKey[] = "_type";
+const char kCredentialNameKey[] = "_name";
+const char kCredentialIconKey[] = "_iconURL";
+const char kPasswordCredentialPasswordKey[] = "_password";
+const char kFederatedCredentialProviderKey[] = "_provider";
 const char kCredentialRequestMediationKey[] = "mediation";
 const char kCredentialRequestPasswordKey[] = "password";
 const char kCredentialRequestProvidersKey[] = "providers";
 const char kMediationRequirementSilent[] = "silent";
 const char kMediationRequirementRequired[] = "required";
 const char kMediationRequirementOptional[] = "optional";
-const char kCredentialTypePassword[] = "PasswordCredential";
-const char kCredentialTypeFederated[] = "FederatedCredential";
+const char kCredentialTypePassword[] = "password";
+const char kCredentialTypeFederated[] = "federated";
 
 bool ParseMediationRequirement(const base::DictionaryValue& json,
                                CredentialMediationRequirement* mediation) {
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
index 8323e9c1c..24c4a5f 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
@@ -31,6 +31,8 @@
 
 @property(readonly, nonatomic) ios::ChromeBrowserState* browserState;
 
+@property(readonly) password_manager::PasswordManager* passwordManager;
+
 @property(readonly, nonatomic) const GURL& lastCommittedURL;
 
 @end
@@ -62,6 +64,7 @@
       std::unique_ptr<password_manager::PasswordFormManager> saved_form_manager)
       override;
   bool IsIncognito() const override;
+  const password_manager::PasswordManager* GetPasswordManager() const override;
   PrefService* GetPrefs() override;
   password_manager::PasswordStore* GetPasswordStore() const override;
   void NotifyUserAutoSignin(
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
index a7860bd1..42629d4 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
@@ -111,6 +111,11 @@
   return (delegate_.browserState)->IsOffTheRecord();
 }
 
+const password_manager::PasswordManager*
+IOSChromePasswordManagerClient::GetPasswordManager() const {
+  return delegate_.passwordManager;
+}
+
 PrefService* IOSChromePasswordManagerClient::GetPrefs() {
   return (delegate_.browserState)->GetPrefs();
 }
diff --git a/ios/chrome/browser/passwords/js_credential_manager.mm b/ios/chrome/browser/passwords/js_credential_manager.mm
index 9d2c77ee..1ff332f 100644
--- a/ios/chrome/browser/passwords/js_credential_manager.mm
+++ b/ios/chrome/browser/passwords/js_credential_manager.mm
@@ -40,7 +40,7 @@
         base::GetQuotedJSONString(info.icon.spec()).c_str(),
         base::GetQuotedJSONString(info.password).c_str());
   }
-  NOTREACHED() << "Invalid CredentialType";
+  /* if (info.type == CREDENTIAL_TYPE_EMPTY) */
   return std::string();
 }
 
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 49ac664..e27eec0 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -66,9 +66,6 @@
 // This is set to YES as soon as the associated WebState is destroyed.
 @property(readonly) BOOL isWebStateDestroyed;
 
-// Accessor for property inside block.
-@property(readonly) PasswordManager* passwordManager;
-
 @end
 
 @interface PasswordController ()<FormSuggestionProvider, PasswordFormFiller>
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
index c8065af..1727942 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h"
 #include "ios/chrome/grit/ios_strings.h"
+#import "ios/third_party/material_components_ios/src/components/AppBar/src/MaterialAppBar.h"
 #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -45,7 +46,8 @@
 
 @interface ReadingListCollectionViewController ()<
     ReadingListCollectionViewItemAccessibilityDelegate,
-    ReadingListDataSink> {
+    ReadingListDataSink,
+    UIGestureRecognizerDelegate> {
   // Toolbar with the actions.
   ReadingListToolbar* _toolbar;
   // Action sheet presenting the subactions of the toolbar.
@@ -199,7 +201,7 @@
       [[UILongPressGestureRecognizer alloc]
           initWithTarget:self
                   action:@selector(handleLongPress:)];
-  longPressRecognizer.numberOfTouchesRequired = 1;
+  longPressRecognizer.delegate = self;
   [self.collectionView addGestureRecognizer:longPressRecognizer];
 }
 
@@ -224,7 +226,7 @@
   [super collectionView:collectionView didDeselectItemAtIndexPath:indexPath];
   if (self.editor.editing) {
     // When deselecting an item, if we are editing, we want to update the
-    // toolbar base on the selected items.
+    // toolbar based on the selected items.
     [self updateToolbarState];
   }
 }
@@ -361,6 +363,16 @@
   }
 }
 
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
+       shouldReceiveTouch:(UITouch*)touch {
+  // Prevent the context menu to be displayed if the long press is done on the
+  // App Bar.
+  CGPoint location = [touch locationInView:self.appBar.navigationBar];
+  return !CGRectContainsPoint(self.appBar.navigationBar.frame, location);
+}
+
 #pragma mark - Private methods
 
 - (void)donePressed {
diff --git a/ios/chrome/browser/web/resources/credential_manager.js b/ios/chrome/browser/web/resources/credential_manager.js
index 700d527..2c0d83d 100644
--- a/ios/chrome/browser/web/resources/credential_manager.js
+++ b/ios/chrome/browser/web/resources/credential_manager.js
@@ -10,10 +10,6 @@
  * the window.navigator.object.
  */
 
-// TODO(crbug.com/435046) This only contains method signatures.
-// Implement the JavaScript API and types according to the spec:
-// https://w3c.github.io/webappsec-credential-management
-
 // TODO(crbug.com/435046) After get, store, preventSilentAccess are
 // implemented app-side, make sure that all tests at
 // https://w3c-test.org/credential-management/idl.https.html
@@ -183,10 +179,10 @@
 
   // Perform following steps:
   // https://w3c.github.io/webappsec-credential-management/#abstract-opdef-create-a-passwordcredential-from-passwordcredentialdata
-  if (!data.id) {
+  if (!data.id || typeof data.id != 'string') {
     throw new TypeError('id must be a non-empty string');
   }
-  if (!data.password) {
+  if (!data.password || typeof data.password != 'string') {
     throw new TypeError('password must be a non-empty string');
   }
   if (data.iconURL && !data.iconURL.startsWith('https://')) {
@@ -260,10 +256,10 @@
  * @constructor
  */
 function FederatedCredential(init) {
-  if (!init.id) {
+  if (!init.id || typeof init.id != 'string') {
     throw new TypeError('id must be a non-empty string');
   }
-  if (!init.provider) {
+  if (!init.provider || typeof init.provider != 'string') {
     throw new TypeError('provider must be a non-empty string');
   }
   if (!init.provider.startsWith('https://') &&
@@ -410,7 +406,10 @@
  * The CredentialCreationOptions dictionary, for more information see
  * https://w3c.github.io/webappsec-credential-management/#credentialcreationoptions-dictionary
  * @dict
- * @typedef {Object}
+ * @typedef {{
+ *     password: ?PasswordCredentialInit,
+ *     federated: ?FederatedCredentialInit
+ * }}
  */
 var CredentialCreationOptions;
 
@@ -474,7 +473,30 @@
  *     of the request.
  */
 CredentialsContainer.prototype.create = function(options) {
-  // TODO(crbug.com/435046) Implement |create| as JS function
+  // According to
+  // https://w3c.github.io/webappsec-credential-management/#abstract-opdef-create-a-credential,
+  // we should also check for secure context. Instead it is done only in
+  // browser-side methods. Since public JS interface is exposed, user can create
+  // a Credential using a constructor anyway.
+  return new Promise(function(resolve, reject) {
+    try {
+      if (options && options.password && !options.federated) {
+        resolve(new PasswordCredential(options.password));
+        return;
+      }
+      if (options && options.federated && !options.password) {
+        resolve(new FederatedCredential(options.federated));
+        return;
+      }
+    } catch (err) {
+      reject(err);
+      return;
+    }
+    reject(Object.create(DOMException.prototype, {
+      name: {value: DOMException.NOT_SUPPORTED_ERR},
+      message: {value: 'Invalid CredentialRequestOptions'}
+    }));
+  });
 };
 
 /**
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 06f94ae..8f0edb9 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -202,11 +202,18 @@
   chromeos::AudioDeviceList devices;
   GetAudioDevices(&devices);
 
-  // At this point, we know we have an ordinary input device, so we look up its
-  // device_name, which identifies which hardware device it belongs to.
   uint64_t device_id = 0;
-  if (!base::StringToUint64(input_device_id, &device_id))
-    return "";
+  if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) {
+    device_id = GetPrimaryActiveInputNode();
+  } else {
+    // At this point, we know we have an ordinary input device id, so we parse
+    // the string for its device_id.
+    if (!base::StringToUint64(input_device_id, &device_id))
+      return "";
+  }
+
+  // Find the device in the device list to get the device name (identifying the
+  // hardware device).
   const chromeos::AudioDevice* input_device =
       GetDeviceFromId(devices, device_id);
   if (!input_device)
@@ -395,12 +402,41 @@
   event->Signal();
 }
 
+uint64_t AudioManagerCras::GetPrimaryActiveInputNode() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  uint64_t device_id = 0;
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    GetPrimaryActiveInputNodeOnMainThread(&device_id, &event);
+  } else {
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AudioManagerCras::GetPrimaryActiveInputNodeOnMainThread,
+                       weak_this_, &device_id, &event));
+  }
+  WaitEventOrShutdown(&event);
+  return device_id;
+}
+
+void AudioManagerCras::GetPrimaryActiveInputNodeOnMainThread(
+    uint64_t* active_input_node_id,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (chromeos::CrasAudioHandler::IsInitialized()) {
+    *active_input_node_id =
+        chromeos::CrasAudioHandler::Get()->GetPrimaryActiveInputNode();
+  }
+  event->Signal();
+}
+
 void AudioManagerCras::GetPrimaryActiveOutputNodeOnMainThread(
     uint64_t* active_output_node_id,
     base::WaitableEvent* event) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   if (chromeos::CrasAudioHandler::IsInitialized()) {
-    chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode();
+    *active_output_node_id =
+        chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode();
   }
   event->Signal();
 }
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h
index 0807037..bf8a3dbf 100644
--- a/media/audio/cras/audio_manager_cras.h
+++ b/media/audio/cras/audio_manager_cras.h
@@ -83,6 +83,9 @@
   void GetAudioDevices(chromeos::AudioDeviceList* devices);
   void GetAudioDevicesOnMainThread(chromeos::AudioDeviceList* devices,
                                    base::WaitableEvent* event);
+  uint64_t GetPrimaryActiveInputNode();
+  void GetPrimaryActiveInputNodeOnMainThread(uint64_t* active_input_node_id,
+                                             base::WaitableEvent* event);
   void GetPrimaryActiveOutputNodeOnMainThread(uint64_t* active_output_node_id,
                                               base::WaitableEvent* event);
   void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 2af246e..efcdc68 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -250,6 +250,10 @@
 const base::Feature kUseNewMediaCache{"use-new-media-cache",
                                       base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Use R16 texture for 9-16 bit channel instead of half-float conversion by CPU.
+const base::Feature kUseR16Texture{"use-r16-texture",
+                                   base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Correct video colors based on output display?
 const base::Feature kVideoColorManagement{"video-color-management",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 2428343..4be332de 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -123,6 +123,7 @@
 MEDIA_EXPORT extern const base::Feature kSupportExperimentalCdmInterface;
 MEDIA_EXPORT extern const base::Feature kUseAndroidOverlay;
 MEDIA_EXPORT extern const base::Feature kUseNewMediaCache;
+MEDIA_EXPORT extern const base::Feature kUseR16Texture;
 MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy;
 MEDIA_EXPORT extern const base::Feature kVideoColorManagement;
 MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideo;
diff --git a/sandbox/win/src/acl.cc b/sandbox/win/src/acl.cc
index f2f5ac4..be1079f8 100644
--- a/sandbox/win/src/acl.cc
+++ b/sandbox/win/src/acl.cc
@@ -48,8 +48,7 @@
   new_access.Trustee.pMultipleTrustee = NULL;
   new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
   new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-  new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(
-                                    const_cast<SID*>(sid.GetPSID()));
+  new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID());
 
   if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
     return false;
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc
index b696a24b..63bc38c 100644
--- a/sandbox/win/src/restricted_token.cc
+++ b/sandbox/win/src/restricted_token.cc
@@ -92,8 +92,7 @@
 
     for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
       deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
-      deny_only_array[i].Sid =
-          const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
+      deny_only_array[i].Sid = sids_for_deny_only_[i].GetPSID();
     }
   }
 
@@ -103,8 +102,7 @@
 
     for (unsigned int i = 0; i < restrict_size; ++i) {
       sids_to_restrict_array[i].Attributes = 0;
-      sids_to_restrict_array[i].Sid =
-          const_cast<SID*>(sids_to_restrict_[i].GetPSID());
+      sids_to_restrict_array[i].Sid = sids_to_restrict_[i].GetPSID();
     }
   }
 
@@ -242,8 +240,8 @@
       bool should_ignore = false;
       if (exceptions) {
         for (unsigned int j = 0; j < exceptions->size(); ++j) {
-          if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
-                          token_groups->Groups[i].Sid)) {
+          if (::EqualSid((*exceptions)[j].GetPSID(),
+                         token_groups->Groups[i].Sid)) {
             should_ignore = true;
             break;
           }
diff --git a/sandbox/win/src/sid.cc b/sandbox/win/src/sid.cc
index 19c645b..5df1acf 100644
--- a/sandbox/win/src/sid.cc
+++ b/sandbox/win/src/sid.cc
@@ -4,23 +4,123 @@
 
 #include "sandbox/win/src/sid.h"
 
+#include <sddl.h>
+
 #include "base/logging.h"
+#include "base/win/windows_version.h"
 
 namespace sandbox {
 
-Sid::Sid(const SID *sid) {
-  ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid));
+namespace {
+
+typedef decltype(
+    ::DeriveCapabilitySidsFromName) DeriveCapabilitySidsFromNameFunc;
+
+class SidArray {
+ public:
+  SidArray() : count_(0), sids_(nullptr) {}
+
+  ~SidArray() {
+    if (sids_) {
+      for (size_t index = 0; index < count_; ++index) {
+        ::LocalFree(sids_[index]);
+      }
+      ::LocalFree(sids_);
+    }
+  }
+
+  DWORD count() { return count_; }
+  PSID* sids() { return sids_; }
+  PDWORD count_ptr() { return &count_; }
+  PSID** sids_ptr() { return &sids_; }
+
+ private:
+  DWORD count_;
+  PSID* sids_;
 };
 
+const wchar_t* WellKnownCapabilityToName(WellKnownCapabilities capability) {
+  switch (capability) {
+    case kInternetClient:
+      return L"internetClient";
+    case kInternetClientServer:
+      return L"internetClientServer";
+    case kRegistryRead:
+      return L"registryRead";
+    case kLpacCryptoServices:
+      return L"lpacCryptoServices";
+    case kEnterpriseAuthentication:
+      return L"enterpriseAuthentication";
+    case kPrivateNetworkClientServer:
+      return L"privateNetworkClientServer";
+    default:
+      return nullptr;
+  }
+}
+
+}  // namespace
+
+Sid::Sid() : sid_() {}
+
+Sid::Sid(PSID sid) : sid_() {
+  ::CopySid(SECURITY_MAX_SID_SIZE, sid_, sid);
+}
+
+Sid::Sid(const SID* sid) : sid_() {
+  ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid));
+}
+
 Sid::Sid(WELL_KNOWN_SID_TYPE type) {
   DWORD size_sid = SECURITY_MAX_SID_SIZE;
-  BOOL result = ::CreateWellKnownSid(type, NULL, sid_, &size_sid);
+  BOOL result = ::CreateWellKnownSid(type, nullptr, sid_, &size_sid);
   DCHECK(result);
   (void)result;
 }
 
-const SID *Sid::GetPSID() const {
-  return reinterpret_cast<SID*>(const_cast<BYTE*>(sid_));
+Sid Sid::FromKnownCapability(WellKnownCapabilities capability) {
+  return Sid::FromNamedCapability(WellKnownCapabilityToName(capability));
+}
+
+Sid Sid::FromNamedCapability(const wchar_t* capability_name) {
+  DeriveCapabilitySidsFromNameFunc* derive_capablity_sids =
+      (DeriveCapabilitySidsFromNameFunc*)GetProcAddress(
+          GetModuleHandle(L"kernelbase"), "DeriveCapabilitySidsFromName");
+  if (!derive_capablity_sids)
+    return Sid();
+
+  if (capability_name == nullptr || ::wcslen(capability_name) == 0)
+    return Sid();
+
+  SidArray capability_group_sids;
+  SidArray capability_sids;
+
+  if (!derive_capablity_sids(capability_name, capability_group_sids.sids_ptr(),
+                             capability_group_sids.count_ptr(),
+                             capability_sids.sids_ptr(),
+                             capability_sids.count_ptr())) {
+    return Sid();
+  }
+
+  if (capability_sids.count() < 1)
+    return Sid();
+
+  return Sid(capability_sids.sids()[0]);
+}
+
+Sid Sid::FromSddlString(const wchar_t* sddl_sid) {
+  PSID converted_sid;
+  if (!::ConvertStringSidToSid(sddl_sid, &converted_sid))
+    return Sid();
+
+  return Sid(converted_sid);
+}
+
+PSID Sid::GetPSID() const {
+  return const_cast<BYTE*>(sid_);
+}
+
+bool Sid::IsValid() const {
+  return !!::IsValidSid(GetPSID());
 }
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/sid.h b/sandbox/win/src/sid.h
index 4656859..c415545 100644
--- a/sandbox/win/src/sid.h
+++ b/sandbox/win/src/sid.h
@@ -9,18 +9,41 @@
 
 namespace sandbox {
 
+enum WellKnownCapabilities {
+  kInternetClient,
+  kInternetClientServer,
+  kRegistryRead,
+  kLpacCryptoServices,
+  kEnterpriseAuthentication,
+  kPrivateNetworkClientServer,
+  kMaxWellKnownCapability
+};
+
 // This class is used to hold and generate SIDS.
 class Sid {
  public:
   // Constructors initializing the object with the SID passed.
   // This is a converting constructor. It is not explicit.
-  Sid(const SID *sid);
+  Sid(PSID sid);
+  Sid(const SID* sid);
   Sid(WELL_KNOWN_SID_TYPE type);
 
+  // Create a Sid from an AppContainer capability name. The name can be
+  // completely arbitrary.
+  static Sid FromNamedCapability(const wchar_t* capability_name);
+  // Create a Sid from a known capability enumeration value.
+  static Sid FromKnownCapability(WellKnownCapabilities capability);
+  // Create a Sid from a SDDL format string, such as S-1-1-0.
+  static Sid FromSddlString(const wchar_t* sddl_sid);
+
   // Returns sid_.
-  const SID *GetPSID() const;
+  PSID GetPSID() const;
+
+  // Gets whether the sid is valid.
+  bool IsValid() const;
 
  private:
+  Sid();
   BYTE sid_[SECURITY_MAX_SID_SIZE];
 };
 
diff --git a/sandbox/win/src/sid_unittest.cc b/sandbox/win/src/sid_unittest.cc
index 76d61e82..b6c2f50 100644
--- a/sandbox/win/src/sid_unittest.cc
+++ b/sandbox/win/src/sid_unittest.cc
@@ -7,65 +7,129 @@
 #define _ATL_NO_EXCEPTIONS
 #include <atlbase.h>
 #include <atlsecurity.h>
+#include <sddl.h>
 
+#include "base/win/windows_version.h"
 #include "sandbox/win/src/sid.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sandbox {
 
-// Calls ::EqualSid. This function exists only to simplify the calls to
-// ::EqualSid by removing the need to cast the input params.
-BOOL EqualSid(const SID *sid1, const SID *sid2) {
-  return ::EqualSid(const_cast<SID*>(sid1), const_cast<SID*>(sid2));
+namespace {
+
+bool EqualSid(const Sid& sid, const ATL::CSid& compare_sid) {
+  if (!sid.IsValid())
+    return false;
+  return !!::EqualSid(sid.GetPSID(), const_cast<SID*>(compare_sid.GetPSID()));
 }
 
-// Tests the creation if a Sid
+bool EqualSid(const Sid& sid, const wchar_t* sddl_sid) {
+  PSID compare_sid;
+  if (!sid.IsValid())
+    return false;
+  if (!::ConvertStringSidToSid(sddl_sid, &compare_sid))
+    return false;
+  bool equal = !!::EqualSid(sid.GetPSID(), compare_sid);
+  ::LocalFree(compare_sid);
+  return equal;
+}
+
+struct CapabilityTestEntry {
+  WellKnownCapabilities capability_;
+  const wchar_t* capability_name_;
+  const wchar_t* sddl_sid_;
+};
+}
+
+// Tests the creation of a Sid.
 TEST(SidTest, Constructors) {
   ATL::CSid sid_world = ATL::Sids::World();
-  SID *sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
+  PSID sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
 
-  // Check the SID* constructor
+  // Check the SID* constructor.
   Sid sid_sid_star(sid_world_pointer);
-  ASSERT_TRUE(EqualSid(sid_world_pointer, sid_sid_star.GetPSID()));
+  ASSERT_TRUE(EqualSid(sid_sid_star, sid_world));
 
-  // Check the copy constructor
+  // Check the copy constructor.
   Sid sid_copy(sid_sid_star);
-  ASSERT_TRUE(EqualSid(sid_world_pointer, sid_copy.GetPSID()));
+  ASSERT_TRUE(EqualSid(sid_copy, sid_world));
+
+  Sid sid_sddl = Sid::FromSddlString(L"S-1-1-0");
+  ASSERT_TRUE(sid_sddl.IsValid());
+  ASSERT_TRUE(EqualSid(sid_sddl, sid_world));
+
+  Sid sid_sddl_invalid = Sid::FromSddlString(L"X-1-1-0");
+  ASSERT_FALSE(sid_sddl_invalid.IsValid());
+
+  Sid sid_sddl_empty = Sid::FromSddlString(L"");
+  ASSERT_FALSE(sid_sddl_empty.IsValid());
 
   // Note that the WELL_KNOWN_SID_TYPE constructor is tested in the GetPSID
-  // test.
+  // test. AppContainer related constructors are tested in AppContainer.
 }
 
 // Tests the method GetPSID
 TEST(SidTest, GetPSID) {
   // Check for non-null result;
-  ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinLocalSid).GetPSID());
-  ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinCreatorOwnerSid).GetPSID());
-  ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinBatchSid).GetPSID());
+  ASSERT_NE(nullptr, Sid(::WinLocalSid).GetPSID());
+  ASSERT_NE(nullptr, Sid(::WinCreatorOwnerSid).GetPSID());
+  ASSERT_NE(nullptr, Sid(::WinBatchSid).GetPSID());
 
-  ASSERT_TRUE(EqualSid(Sid(::WinNullSid).GetPSID(),
-                       ATL::Sids::Null().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinNullSid), ATL::Sids::Null()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinWorldSid).GetPSID(),
-                       ATL::Sids::World().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinWorldSid), ATL::Sids::World()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinDialupSid).GetPSID(),
-                       ATL::Sids::Dialup().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinDialupSid), ATL::Sids::Dialup()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid).GetPSID(),
-                       ATL::Sids::Network().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid), ATL::Sids::Network()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinAdministratorsSid).GetPSID(),
-                       ATL::Sids::Admins().GetPSID()));
+  ASSERT_TRUE(
+      EqualSid(Sid(::WinBuiltinAdministratorsSid), ATL::Sids::Admins()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid).GetPSID(),
-                       ATL::Sids::Users().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid), ATL::Sids::Users()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid).GetPSID(),
-                       ATL::Sids::Guests().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid), ATL::Sids::Guests()));
 
-  ASSERT_TRUE(EqualSid(Sid(::WinProxySid).GetPSID(),
-                       ATL::Sids::Proxy().GetPSID()));
+  ASSERT_TRUE(EqualSid(Sid(::WinProxySid), ATL::Sids::Proxy()));
+}
+
+TEST(SidTest, AppContainer) {
+  const CapabilityTestEntry capabilities[] = {
+      {kInternetClient, L"internetClient", L"S-1-15-3-1"},
+      {kInternetClientServer, L"internetClientServer", L"S-1-15-3-2"},
+      {kRegistryRead, L"registryRead",
+       L"S-1-15-3-1024-1065365936-1281604716-3511738428-"
+       "1654721687-432734479-3232135806-4053264122-3456934681"},
+      {kLpacCryptoServices, L"lpacCryptoServices",
+       L"S-1-15-3-1024-3203351429-2120443784-2872670797-"
+       "1918958302-2829055647-4275794519-765664414-2751773334"},
+      {kEnterpriseAuthentication, L"enterpriseAuthentication", L"S-1-15-3-8"},
+      {kPrivateNetworkClientServer, L"privateNetworkClientServer",
+       L"S-1-15-3-3"}};
+
+  // No support for AppContainer less than Win10 RS2.
+  if (base::win::GetVersion() < base::win::VERSION_WIN10_RS2)
+    return;
+
+  Sid sid_nullptr = Sid::FromNamedCapability(nullptr);
+  EXPECT_FALSE(sid_nullptr.IsValid());
+
+  Sid sid_empty = Sid::FromNamedCapability(L"");
+  EXPECT_FALSE(sid_empty.IsValid());
+
+  WellKnownCapabilities invalid_well_known =
+      static_cast<WellKnownCapabilities>(kMaxWellKnownCapability + 1);
+  Sid sid_invalid_well_known = Sid::FromKnownCapability(invalid_well_known);
+  EXPECT_FALSE(sid_invalid_well_known.IsValid());
+
+  for (auto capability : capabilities) {
+    EXPECT_TRUE(EqualSid(Sid::FromNamedCapability(capability.capability_name_),
+                         capability.sddl_sid_))
+        << "Named Capability: " << capability.sddl_sid_;
+    EXPECT_TRUE(EqualSid(Sid::FromKnownCapability(capability.capability_),
+                         capability.sddl_sid_))
+        << "Known Capability: " << capability.sddl_sid_;
+  }
 }
 
 }  // namespace sandbox
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 3603901e..7974930 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -261,8 +261,6 @@
 crbug.com/591099 animations/interpolation/transform-interpolation-004.html [ Timeout ]
 crbug.com/591099 animations/interpolation/transform-interpolation-005.html [ Timeout ]
 crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Crash Pass Timeout ]
-crbug.com/591099 animations/interpolation/webkit-column-count-interpolation.html [ Failure ]
-crbug.com/591099 animations/interpolation/webkit-column-width-interpolation.html [ Failure ]
 crbug.com/591099 animations/keyframes-rule.html [ Failure Pass ]
 crbug.com/591099 animations/lazy-detached-animation-stop.html [ Failure ]
 crbug.com/591099 animations/play-state.html [ Failure Pass ]
@@ -9287,7 +9285,6 @@
 crbug.com/591099 fast/mediastream/enabled.html [ Failure Pass ]
 crbug.com/591099 fast/mediastream/getusermedia.html [ Failure Pass ]
 crbug.com/591099 fast/mediastream/no-interface-object.html [ Failure Pass ]
-crbug.com/591099 fast/multicol/5-levels-of-nesting-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/abspos-after-break-after.html [ Failure ]
 crbug.com/591099 fast/multicol/abspos-in-overflow-hidden-in-2nd-column.html [ Failure ]
 crbug.com/591099 fast/multicol/abspos-new-width-rebalance.html [ Failure ]
@@ -9357,10 +9354,8 @@
 crbug.com/591099 fast/multicol/composited-with-child-layer-in-next-column.html [ Failure ]
 crbug.com/591099 fast/multicol/composited-with-overflow-in-next-column.html [ Failure Timeout ]
 crbug.com/591099 fast/multicol/constrained-content-height-with-overflow-crash.html [ Failure Pass ]
-crbug.com/591099 fast/multicol/content-change-same-height.html [ Failure ]
 crbug.com/591099 fast/multicol/content-height-zero-crash.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/cssom-view.html [ Failure ]
-crbug.com/591099 fast/multicol/doubly-nested-with-increasing-row-heights-crash.html [ Failure ]
 crbug.com/757767 fast/multicol/doubly-nested-with-insane-child-height-crash.html [ Timeout ]
 crbug.com/757767 fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Timeout ]
 crbug.com/591099 fast/multicol/dynamic/abspos-becomes-spanner.html [ Failure ]
@@ -9486,11 +9481,9 @@
 crbug.com/591099 fast/multicol/hit-test-gap-between-pages.html [ Failure ]
 crbug.com/757767 fast/multicol/huge-column-count.html [ Crash Timeout ]
 crbug.com/591099 fast/multicol/image-inside-nested-blocks-with-border.html [ Failure ]
-crbug.com/591099 fast/multicol/image-loaded-before-layout-assert.html [ Failure ]
 crbug.com/757767 fast/multicol/infinite-height-causing-fractional-row-height-crash.html [ Timeout ]
 crbug.com/757767 fast/multicol/infinitely-tall-content-in-outer-crash.html [ Timeout ]
 crbug.com/591099 fast/multicol/inline-block-baseline.html [ Failure ]
-crbug.com/591099 fast/multicol/inline-children-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/inline-getclientrects.html [ Failure ]
 crbug.com/591099 fast/multicol/inner-multicol-in-second-column.html [ Failure ]
 crbug.com/591099 fast/multicol/inner-multicol-moved-into-continuation.html [ Failure Pass ]
@@ -9517,7 +9510,6 @@
 crbug.com/591099 fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure ]
 crbug.com/591099 fast/multicol/negative-margins-crash.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/nested-3-multicols-fixed-height.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-after-composited-layer-crash.html [ Failure ]
 crbug.com/757767 fast/multicol/nested-and-unbreakable-crash.html [ Timeout ]
 crbug.com/591099 fast/multicol/nested-auto-height-extra-block-inbetween.html [ Failure ]
 crbug.com/591099 fast/multicol/nested-auto-height-short-first-row.html [ Failure ]
@@ -9542,7 +9534,6 @@
 crbug.com/591099 fast/multicol/nested-with-clipped-first-column.html [ Failure ]
 crbug.com/591099 fast/multicol/nested-with-composited-and-multicol-crash.html [ Failure Pass Timeout ]
 crbug.com/591099 fast/multicol/nested-with-forced-breaks-in-eariler-rows.html [ Failure Timeout ]
-crbug.com/591099 fast/multicol/nested-with-line-taller-than-outer.html [ Failure ]
 crbug.com/591099 fast/multicol/nested-with-padding.html [ Failure ]
 crbug.com/591099 fast/multicol/nested-with-single-empty-block.html [ Failure Timeout ]
 crbug.com/591099 fast/multicol/nested-with-single-tall-line.html [ Failure ]
@@ -9652,7 +9643,6 @@
 crbug.com/591099 fast/multicol/span/fill-after-spanner-exact-fit.html [ Failure ]
 crbug.com/591099 fast/multicol/span/fill-after-spanner-extra-height.html [ Failure ]
 crbug.com/591099 fast/multicol/span/float.html [ Failure ]
-crbug.com/591099 fast/multicol/span/foreignObject.html [ Failure ]
 crbug.com/591099 fast/multicol/span/height-decrease.html [ Failure ]
 crbug.com/591099 fast/multicol/span/height-increase.html [ Failure ]
 crbug.com/591099 fast/multicol/span/in-nested-multicol-with-hard-breaks.html [ Failure ]
@@ -9661,7 +9651,6 @@
 crbug.com/591099 fast/multicol/span/inside-abspos-crash.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height-crash.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height.html [ Failure ]
-crbug.com/591099 fast/multicol/span/inside-float-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/span/inside-overflow-hidden-crash.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/span/invalid-span-1.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/span/invalid-spanner-in-abspos.html [ Failure ]
@@ -9722,10 +9711,8 @@
 crbug.com/591099 fast/multicol/textarea-with-placeholder-as-multicol-crash.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/three-inner-rows.html [ Failure Timeout ]
 crbug.com/591099 fast/multicol/transform-inside-opacity.html [ Failure ]
-crbug.com/591099 fast/multicol/triply-nested-with-padding-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/unbreakable-block-too-tall-at-column-start.html [ Failure ]
 crbug.com/591099 fast/multicol/unbreakable-block-too-tall-to-fit.html [ Failure ]
-crbug.com/591099 fast/multicol/unbreakable-content-taller-than-height-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/unforced-break-after-complex-margin-collapsing.html [ Failure ]
 crbug.com/591099 fast/multicol/unsplittable-inline-block.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ]
@@ -14669,10 +14656,8 @@
 crbug.com/591099 printing/page-count-percentage-height.html [ Failure Pass ]
 crbug.com/591099 printing/page-count-relayout-shrink.html [ Failure ]
 crbug.com/591099 printing/page-format-data.html [ Failure Pass ]
-crbug.com/591099 printing/page-height-zero.html [ Failure ]
 crbug.com/591099 printing/page-rule-selection.html [ Failure Pass Timeout ]
 crbug.com/591099 printing/pageNumerForElementById.html [ Failure Pass ]
-crbug.com/591099 printing/pageProperty-with-multicol.html [ Failure ]
 crbug.com/591099 printing/pseudo-class-outside-page.html [ Failure Pass ]
 crbug.com/591099 printing/quirks-percentage-height-body.html [ Failure ]
 crbug.com/591099 printing/quirks-percentage-height.html [ Failure ]
@@ -14687,7 +14672,6 @@
 crbug.com/591099 printing/tfoot-repeats-at-bottom-of-each-page.html [ Failure ]
 crbug.com/591099 printing/thead-repeats-at-top-of-each-page-multiple-tables.html [ Failure ]
 crbug.com/591099 printing/thead-repeats-at-top-of-each-page.html [ Failure ]
-crbug.com/591099 printing/viewport-size-dependant-iframe-with-multicol-crash.html [ Failure ]
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
 crbug.com/591099 scrollbars/basic-scrollbar.html [ Failure ]
 crbug.com/591099 scrollbars/custom-scrollbar-enable-changes-thickness-with-iframe.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests
index 98ff27b..3dcb2eeb 100644
--- a/third_party/WebKit/LayoutTests/NeverFixTests
+++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -288,13 +288,6 @@
 # The revert keyword is not yet supported.
 external/wpt/css/css-cascade-4/revert-val-001.html [ WontFix ]
 
-# WPT subdirectories without owners.
-external/wpt/accelerometer [ WontFix ]
-external/wpt/assumptions [ WontFix ]
-external/wpt/gyroscope [ WontFix ]
-external/wpt/magnetometer [ WontFix ]
-external/wpt/upgrade-insecure-requests [ WontFix ]
-
 # Temporary disabling of most encrypted-media WPT tests while enabling
 # https only. Once the switch is complete (and the WPT tests renamed so they
 # run using https), they can be re-enabled.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index cdc3ed4d..aef1ff8 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -486,22 +486,13 @@
 crbug.com/635619 virtual/layout_ng/fast/block/float/032.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/034.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/035.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/add-float-back-to-anonymous-block.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/assert-when-moving-float.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/assert-when-moving-float-2.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-2.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-3.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-4.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-5.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-6.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/avoiding-float-centered.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/block-with-negative-margin-clears-float.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/br-with-clear-2.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/centered-float-avoidance-complexity.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/checkbox-and-radio-avoid-floats.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/clear-intruding-floats-when-moving-to-inline-parent-3.html [ Failure Crash Pass ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/crash-on-absolute-positioning.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/crash-replaced-display-block.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/element-clears-float-without-clearance.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-at-start-of-clean-lines-that-are-subsequently-dirtied-vertical-rl.html [ Failure ]
@@ -513,10 +504,7 @@
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-inserted-into-clean-line.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-list-changed-before-layout-crash.html [ Crash Pass ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-first-letter.html [ Crash Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling-crash.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling4.html [ Crash Pass ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling5.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/float-on-empty-line.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-on-zero-height-line.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-overflow-hidden-containing-block-width.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/float-reparent-during-detach-crash.html [ Crash Pass ]
@@ -534,7 +522,6 @@
 crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-002.htm [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-003.htm [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-004.htm [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/formatting-context-changes.html [ Failure Crash ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/independent-align-positioning.html [ Failure ]
 crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/intruding-painted-twice.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/line-break-after-white-space-crash.html [ Pass Crash Timeout ]
@@ -549,11 +536,8 @@
 crbug.com/635619 virtual/layout_ng/fast/block/float/overhanging-float-remove-from-fixed-position-block2.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/overlapping-floats-paint-hittest-order-1.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/overlapping-floats-paint-hittest-order-2.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/override-property-float.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/remove-line-above-float-above-line-crash.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-made-inline-crash.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash-2.html [ Failure Crash ]
-crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash.html [ Crash Failure ]
+crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash.html [ Crash Pass ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/shrink-to-avoid-float-complexity.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/shrink-to-fit-width.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/float/trailing-float-with-columns.html [ Crash Failure ]
@@ -565,7 +549,6 @@
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/057.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/103.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/bfc-beside-float-complex-margin-collapsing.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/self-collapsing-block-with-overflow-hidden-and-float-child.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/self-collapsing-cols-creates-block-formatting-context.html [ Failure ]
 
 ### virtual/layout_ng/fast/block/margin-collapse/block-inside-inline
@@ -578,9 +561,6 @@
 ### virtual/layout_ng/fast/block/margin-collapse
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/empty-clear-blocks.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/line-beside-float-complex-margin-collapsing.html [ Failure Crash ]
-crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/self-collapsing-with-floats.html [ Failure ]
-crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/table-beside-float-complex-margin-collapsing.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-container.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-separate-position.html [ Failure ]
 crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-siblings.html [ Failure ]
@@ -1759,6 +1739,8 @@
 crbug.com/751952 virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/budget-api-origin-trial-interfaces.html [ Pass Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/payment-request/change-shipping-option-manual.https.html [ Skip ]
+crbug.com/626703 external/wpt/payment-request/shipping-address-changed-manual.https.html [ Skip ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html [ Failure ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html [ Failure ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/relevant-mutations.html [ Timeout ]
@@ -3663,6 +3645,9 @@
 # Sheriff failures 2017-09-08
 crbug.com/763208 [ Linux ] virtual/mojo-loading/http/tests/devtools/sources/debugger-ui/source-frame-count.html [ Pass Failure ]
 
+crbug.com/763666 [ Linux Win ] external/wpt/assumptions/ahem.html [ Failure ]
+crbug.com/763667 external/wpt/upgrade-insecure-requests/iframe-redirect-upgrade.https.html [ Timeout ]
+
 # Sheriff failures 2017-09-11
 crbug.com/763809 [ Win7 Debug ] fast/multicol/nested-very-tall-inside-short-crash.html [ Pass Failure Timeout ]
 crbug.com/763810 [ Win7 Debug ] virtual/threaded/transitions/transition-end-event-nested.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index ed279db..c2016a8c 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -3,9 +3,8 @@
 # This file acts as a blacklist; directories and files not listed here will
 # automatically be found and imported.
 #
-# We may want to move towards importing but not running directories without
-# owners, in order to make it easier to enable or run them in the future --
-# directories that are imported but not run are listed in NeverFixTests.
+# Directories that are imported but not run are listed in NeverFixTests. This
+# can be used to make it easier to work on getting them running and passing.
 #
 # Further documentation:
 # https://chromium.googlesource.com/chromium/src/+/master/docs/testing/layout_test_expectations.md
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 12819b3..731e1f4 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -3811,6 +3811,12 @@
      {}
     ]
    ],
+   "payment-request/change-shipping-option-manual.https.html": [
+    [
+     "/payment-request/change-shipping-option-manual.https.html",
+     {}
+    ]
+   ],
    "payment-request/payment-response/complete-method-manual.https.html": [
     [
      "/payment-request/payment-response/complete-method-manual.https.html",
@@ -3859,6 +3865,12 @@
      {}
     ]
    ],
+   "payment-request/shipping-address-changed-manual.https.html": [
+    [
+     "/payment-request/shipping-address-changed-manual.https.html",
+     {}
+    ]
+   ],
    "payment-request/updateWith-method-pmi-handling-manual.https.html": [
     [
      "/payment-request/updateWith-method-pmi-handling-manual.https.html",
@@ -92669,6 +92681,11 @@
      {}
     ]
    ],
+   "css/css-ui-3/text-overflow-023-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-ui-3/text-overflow-ref.html": [
     [
      {}
@@ -115334,11 +115351,6 @@
      {}
     ]
    ],
-   "payment-request/interfaces.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "payment-request/payment-request-abort-method.https-expected.txt": [
     [
      {}
@@ -115374,11 +115386,6 @@
      {}
     ]
    ],
-   "performance-timeline/idlharness-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "performance-timeline/performanceobservers.js": [
     [
      {}
@@ -133526,12 +133533,24 @@
      {}
     ]
    ],
+   "XMLHttpRequest/access-control-sandboxed-iframe-allow-origin-null.htm": [
+    [
+     "/XMLHttpRequest/access-control-sandboxed-iframe-allow-origin-null.htm",
+     {}
+    ]
+   ],
    "XMLHttpRequest/access-control-sandboxed-iframe-allow.htm": [
     [
      "/XMLHttpRequest/access-control-sandboxed-iframe-allow.htm",
      {}
     ]
    ],
+   "XMLHttpRequest/access-control-sandboxed-iframe-denied.htm": [
+    [
+     "/XMLHttpRequest/access-control-sandboxed-iframe-denied.htm",
+     {}
+    ]
+   ],
    "XMLHttpRequest/allow-lists-starting-with-comma.htm": [
     [
      "/XMLHttpRequest/allow-lists-starting-with-comma.htm",
@@ -140082,6 +140101,12 @@
      {}
     ]
    ],
+   "css/css-ui-3/text-overflow-023.html": [
+    [
+     "/css/css-ui-3/text-overflow-023.html",
+     {}
+    ]
+   ],
    "css/css-values-3/absolute-length-units-001.html": [
     [
      "/css/css-values-3/absolute-length-units-001.html",
@@ -197621,10 +197646,18 @@
    "9c4a5cf99e43f1315dfd73f543450e4056dcef36",
    "testharness"
   ],
+  "XMLHttpRequest/access-control-sandboxed-iframe-allow-origin-null.htm": [
+   "2b507239c3e3fa6602068d6d92897c5d042a7a0d",
+   "testharness"
+  ],
   "XMLHttpRequest/access-control-sandboxed-iframe-allow.htm": [
    "b1140eacc383af590578319b25ee803ba50c3fee",
    "testharness"
   ],
+  "XMLHttpRequest/access-control-sandboxed-iframe-denied.htm": [
+   "32fcbfa28e93aad6e0040b5b1c9478ce76e7e06e",
+   "testharness"
+  ],
   "XMLHttpRequest/allow-lists-starting-with-comma.htm": [
    "34a8d82f397f35902c73d9ced2f3cf900d04ae53",
    "testharness"
@@ -237665,6 +237698,14 @@
    "095f78700529b34397887722b57b56dd7dd97861",
    "reftest"
   ],
+  "css/css-ui-3/text-overflow-023-expected.txt": [
+   "ca595dbd0053aa0bf73d0922a4de71a035eaec96",
+   "support"
+  ],
+  "css/css-ui-3/text-overflow-023.html": [
+   "4fd38a517e41851216d12db8c6b732d96f76e325",
+   "testharness"
+  ],
   "css/css-ui-3/text-overflow-ref.html": [
    "db55b0b95a7406e9c4f00081b3e2cbe6b07363f7",
    "support"
@@ -254414,7 +254455,7 @@
    "testharness"
   ],
   "hr-time/idlharness-expected.txt": [
-   "f4a7fca22be8e2b8f6b53adb78f55bedcd710b42",
+   "e62291bdf6959ec7d9558211d3dc1ae365b2749d",
    "support"
   ],
   "hr-time/idlharness.html": [
@@ -274418,7 +274459,7 @@
    "support"
   ],
   "navigation-timing/nav2_idlharness-expected.txt": [
-   "8d6b069447dffdb7e215aa7553a8eb049640eefe",
+   "dfc2dd329de01d07ed99872bdb0b14c84359e948",
    "support"
   ],
   "navigation-timing/nav2_idlharness.html": [
@@ -281082,7 +281123,7 @@
    "manual"
   ],
   "payment-request/algorithms-manual.https.html": [
-   "5b603c95f9d356dc4e19888ed779c499acb915eb",
+   "a3d20d112af7ff8d18ddf0b9cb69d121a015f374",
    "manual"
   ],
   "payment-request/allowpaymentrequest/active-document-cross-origin.https.sub.html": [
@@ -281137,6 +281178,10 @@
    "6e4028440fff617d6a0e9abb06625891eb53b28a",
    "testharness"
   ],
+  "payment-request/change-shipping-option-manual.https.html": [
+   "46bc8b2f5512e7d40e46c4fb255f82def0e359d1",
+   "manual"
+  ],
   "payment-request/historical.https-expected.txt": [
    "a98767fbf7d24f102e1546aafe4ed6276c2e79eb",
    "support"
@@ -281145,10 +281190,6 @@
    "6695acdcd1647fdd37702a7f63658dcd50f25596",
    "testharness"
   ],
-  "payment-request/interfaces.https-expected.txt": [
-   "881a5f9ae1b5c21dd9fe47b99c437d41c90e31c0",
-   "support"
-  ],
   "payment-request/interfaces.https.html": [
    "e531c0ceda2fa798e5e6df3c7131e6b80f342884",
    "testharness"
@@ -281273,6 +281314,10 @@
    "cb2d1d6dfb668a40bb0822ce2a097d327bf4dfe7",
    "manual"
   ],
+  "payment-request/shipping-address-changed-manual.https.html": [
+   "a1784f0be2a7861480f663ac789eed67e08ddce8",
+   "manual"
+  ],
   "payment-request/updateWith-method-pmi-handling-manual.https.html": [
    "5e254b412285a6154004aeff98357c6aa55e62c6",
    "manual"
@@ -281289,10 +281334,6 @@
    "9c6b6edf19800a2730de2dfe601a7cd2503cf87d",
    "testharness"
   ],
-  "performance-timeline/idlharness-expected.txt": [
-   "652c9d061afde560a3195a1f75e7c779fc3df032",
-   "support"
-  ],
   "performance-timeline/idlharness.html": [
    "b021a9528875942d44b33c3fc3f4cd643194fad5",
    "testharness"
@@ -294778,7 +294819,7 @@
    "support"
   ],
   "url/interfaces.any-expected.txt": [
-   "59db06e13d086debd8520db45c039f779402df49",
+   "29c69c6078a772a3b88386c7924b5313dbc6176f",
    "support"
   ],
   "url/interfaces.any.js": [
@@ -294786,7 +294827,7 @@
    "testharness"
   ],
   "url/interfaces.any.worker-expected.txt": [
-   "59db06e13d086debd8520db45c039f779402df49",
+   "29c69c6078a772a3b88386c7924b5313dbc6176f",
    "support"
   ],
   "url/setters_tests.json": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt
new file mode 100644
index 0000000..3376ab8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Accelerometer: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Accelerometer: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Accelerometer: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Accelerometer: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+PASS Accelerometer: sensor.start() returns undefined
+PASS Accelerometer: no exception is thrown when calling start() on already started sensor
+PASS Accelerometer: sensor.stop() returns undefined
+PASS Accelerometer: no exception is thrown when calling stop() on already stopped sensor
+PASS Accelerometer: throw a 'SecurityError' when constructing sensor object within iframe
+FAIL Accelerometer: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023-expected.txt
new file mode 100644
index 0000000..71be1ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Checks hit testing on the ellipsis assert_equals: the element targeted by a hit on the ellipsis is the elided inline. expected "target" but got "parent"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023.html
new file mode 100644
index 0000000..ca3f8da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<title>CSS Basic User Interface Test: interacting with the ellipsis</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<link rel="help" href="http://www.w3.org/TR/css3-ui/#text-overflow">
+<meta name="flags" content="ahem dom should">
+<meta name="assert" content="Pointer events on the ellipsis should be dispatched to the elided inline element if there's one, rather than directly to the block.">
+<!-- This is tested indirectly, using elementFromPoint instead of actually triggering a pointer event, because:
+  * Actual pointer events can only be dispatched in an manual test, while elementFromPoint allows for an automated test
+  * These two methods are expected to give the same result
+
+  This indirection and the slight risk of false positive or false negative it introduces
+  is preferable to a manual test which would hardly anyone would ever run.
+-->
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+#parent {
+  position: absolute;
+  top: 0; left: 0;
+  font: 50px / 1  ahem ;
+  overflow: hidden;
+  width: 3em;
+  text-overflow: ellipsis;
+}
+</style>
+<div id=parent>&nbsp;&nbsp;<span id=target>&nbsp;&nbsp;</span></div>
+<script>
+test(
+  function() {
+    var e = document.elementFromPoint(125,25);
+    assert_equals(e.id,"target", "the element targeted by a hit on the ellipsis is the elided inline.");
+  }, "Checks hit testing on the ellipsis");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt
new file mode 100644
index 0000000..3f63e93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Gyroscope: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Gyroscope: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Gyroscope: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Gyroscope: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+PASS Gyroscope: sensor.start() returns undefined
+PASS Gyroscope: no exception is thrown when calling start() on already started sensor
+PASS Gyroscope: sensor.stop() returns undefined
+PASS Gyroscope: no exception is thrown when calling stop() on already stopped sensor
+PASS Gyroscope: throw a 'SecurityError' when constructing sensor object within iframe
+FAIL Gyroscope: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt
index f5beed26..072282c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt
@@ -8,10 +8,10 @@
 PASS Performance interface: existence and properties of interface prototype object's "constructor" property
 PASS Performance interface: operation now()
 PASS Performance interface: operation toJSON()
-FAIL Test default toJSON operation of Performance Illegal invocation
 PASS Performance must be primary interface of window.performance
 PASS Stringification of window.performance
 PASS Performance interface: window.performance must inherit property "now()" with the proper type
 PASS Performance interface: window.performance must inherit property "toJSON()" with the proper type
+FAIL Test default toJSON operation of Performance assert_unreached: property "timing" should not be present in the output of Performance.prototype.toJSON() Reached unreachable code
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt
new file mode 100644
index 0000000..0490c60
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Magnetometer: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Magnetometer: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Magnetometer: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+FAIL Magnetometer: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+PASS Magnetometer: sensor.start() returns undefined
+PASS Magnetometer: no exception is thrown when calling start() on already started sensor
+PASS Magnetometer: sensor.stop() returns undefined
+PASS Magnetometer: no exception is thrown when calling stop() on already stopped sensor
+PASS Magnetometer: throw a 'SecurityError' when constructing sensor object within iframe
+FAIL Magnetometer: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt
index 8c6a4e9..d7761ba0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt
@@ -14,6 +14,6 @@
 PASS PerformanceNavigationTiming interface: attribute loadEventEnd
 PASS PerformanceNavigationTiming interface: attribute type
 PASS PerformanceNavigationTiming interface: attribute redirectCount
-FAIL PerformanceNavigationTiming interface: operation toJSON() undefined PerformanceEntry not found (inherited by PerformanceResourceTiming)
+PASS PerformanceNavigationTiming interface: operation toJSON()
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html
index af4c70ad8..bcb4b23 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html
@@ -65,17 +65,10 @@
   requestShipping: true,
 };
 
-test(() => {
-  const request = new PaymentRequest(
-    methods,
-    detailsNoShippingOptions,
-    options
-  );
-}, "Smoke test");
-
 function testFireEvent(button, details, eventName, expectRequestProps) {
   button.disabled = true;
   promise_test(async t => {
+    new PaymentRequest(methods, detailsNoShippingOptions, options);
     const request = new PaymentRequest(methods, details, options);
     const events = [];
     const p1 = new Promise(resolve => {
@@ -97,12 +90,8 @@
         resolve("listener-2");
       });
     });
-    try {
-      const response = await request.show();
-      response.complete("success");
-    } catch (err) {
-      assert_unreached("Unexpected exception: " + err.message);
-    }
+    const response = await request.show();
+    response.complete("success");
     const [handler, listener1, listener2] = await Promise.all([p1, p2, p3]);
     assert_equals(
       handler,
@@ -164,7 +153,7 @@
   <h2 id="shipping-address-changed-algo">Shipping address changed algorithm</h2>
   <link rel="help" href="https://www.w3.org/TR/payment-request/#shipping-address-changed-algorithm">
   <p>
-    When prompted, please enter or select "web platform test" as recipient, at address "1 wpt street" in "Kabul, Afghanistan", zip/postal code 1001.
+    When prompted, please change or enter a new shipping address and then select Pay.
   </p>
   <ol>
     <li>
@@ -179,7 +168,7 @@
   <h2 id="shipping-option-changed-algo">Shipping option changed algorithm</h2>
   <link rel="help" href="https://w3c.github.io/payment-request/#shipping-option-changed-algorithm">
   <p>
-    When prompted, please select "shipping option 2".
+    Finally, when prompted, please select "shipping option 2" and then select Pay.
   </p>
   <ol>
     <li>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/change-shipping-option-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/change-shipping-option-manual.https.html
new file mode 100644
index 0000000..e9141542
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/change-shipping-option-manual.https.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<meta charset="utf-8">
+<title>Test for PaymentRequest shippingOption attribute</title>
+<link rel="help" href="https://w3c.github.io/payment-request/#shippingoption-attribute">
+<link rel="help" href="https://w3c.github.io/payment-request/#onshippingoptionchange-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({ explicit_done: true, explicit_timeout: true });
+const validMethod = Object.freeze({ supportedMethods: "basic-card" });
+const validMethods = Object.freeze([validMethod]);
+const validAmount = Object.freeze({ currency: "USD", value: "5.00" });
+const validTotal = Object.freeze({
+  label: "label",
+  amount: validAmount,
+});
+const validDetails = Object.freeze({ total: validTotal });
+
+const validShippingOption1 = Object.freeze({
+  id: "valid-1",
+  label: "PICK ME!",
+  amount: validAmount,
+  selected: false,
+});
+
+const validShippingOption2 = Object.freeze({
+  id: "initially-selected",
+  label: "Valid shipping option 2",
+  amount: validAmount,
+  selected: true,
+});
+
+const requestShipping = Object.freeze({
+  requestShipping: true,
+});
+
+function testShippingOptionChanged() {
+  promise_test(async t => {
+    const detailsWithShippingOptions = Object.assign({}, validDetails, {
+      shippingOptions: [validShippingOption1, validShippingOption2],
+    });
+    const request = new PaymentRequest(
+      validMethods,
+      detailsWithShippingOptions,
+      requestShipping
+    );
+    assert_equals(
+      request.shippingOption,
+      "initially-selected",
+      "Must be 'initially-selected', as the selected member is true"
+    );
+    const listenerPromise = new Promise(resolve => {
+      request.addEventListener("shippingoptionchange", () => {
+        resolve(request.shippingOption);
+      });
+    });
+    const handlerPromise = new Promise(resolve => {
+      request.onshippingoptionchange = () => {
+        resolve(request.shippingOption);
+      };
+    });
+    request.show().catch(err => err);
+
+    const results = await Promise.all([listenerPromise, handlerPromise]);
+    assert_true(
+      results.every(result => result === "valid-1"),
+      "Expected valid-1 as the shippingOption"
+    );
+    await request.abort();
+  });
+  done();
+}
+</script>
+
+<h2>PaymentRequest shippingOption attribute</h2>
+<p>
+  When the payment sheet is presented, select "PICK ME!" as the shipping option.
+</p>
+<ol>
+  <li>
+    <button onclick="testShippingOptionChanged()">
+      When the shipping option is manually changed, request.shippingOption represents the user's choice.
+    </button>
+  </li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt
deleted file mode 100644
index aeff47e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-This is a testharness.js-based test.
-PASS PaymentRequest interface: existence and properties of interface object
-PASS PaymentRequest interface object length
-PASS PaymentRequest interface object name
-PASS PaymentRequest interface: existence and properties of interface prototype object
-PASS PaymentRequest interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentRequest interface: operation show()
-PASS PaymentRequest interface: operation abort()
-PASS PaymentRequest interface: operation canMakePayment()
-PASS PaymentRequest interface: attribute id
-PASS PaymentRequest interface: attribute shippingAddress
-PASS PaymentRequest interface: attribute shippingOption
-PASS PaymentRequest interface: attribute shippingType
-PASS PaymentRequest interface: attribute onshippingaddresschange
-PASS PaymentRequest interface: attribute onshippingoptionchange
-PASS PaymentRequest must be primary interface of new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}})
-PASS Stringification of new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}})
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "show()" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "abort()" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "canMakePayment()" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "id" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "shippingAddress" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "shippingOption" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "shippingType" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "onshippingaddresschange" with the proper type
-PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "onshippingoptionchange" with the proper type
-PASS PaymentAddress interface: existence and properties of interface object
-PASS PaymentAddress interface object length
-PASS PaymentAddress interface object name
-PASS PaymentAddress interface: existence and properties of interface prototype object
-PASS PaymentAddress interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentAddress interface: operation toJSON()
-FAIL Test default toJSON operation of PaymentAddress Illegal invocation
-PASS PaymentAddress interface: attribute country
-PASS PaymentAddress interface: attribute addressLine
-PASS PaymentAddress interface: attribute region
-PASS PaymentAddress interface: attribute city
-PASS PaymentAddress interface: attribute dependentLocality
-PASS PaymentAddress interface: attribute postalCode
-PASS PaymentAddress interface: attribute sortingCode
-PASS PaymentAddress interface: attribute languageCode
-PASS PaymentAddress interface: attribute organization
-PASS PaymentAddress interface: attribute recipient
-PASS PaymentAddress interface: attribute phone
-PASS PaymentResponse interface: existence and properties of interface object
-PASS PaymentResponse interface object length
-PASS PaymentResponse interface object name
-PASS PaymentResponse interface: existence and properties of interface prototype object
-PASS PaymentResponse interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentResponse interface: operation toJSON()
-FAIL Test default toJSON operation of PaymentResponse Illegal invocation
-PASS PaymentResponse interface: attribute requestId
-PASS PaymentResponse interface: attribute methodName
-PASS PaymentResponse interface: attribute details
-PASS PaymentResponse interface: attribute shippingAddress
-PASS PaymentResponse interface: attribute shippingOption
-PASS PaymentResponse interface: attribute payerName
-PASS PaymentResponse interface: attribute payerEmail
-PASS PaymentResponse interface: attribute payerPhone
-PASS PaymentResponse interface: operation complete(PaymentComplete)
-PASS PaymentRequestUpdateEvent interface: existence and properties of interface object
-PASS PaymentRequestUpdateEvent interface object length
-PASS PaymentRequestUpdateEvent interface object name
-PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object
-PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentRequestUpdateEvent interface: operation updateWith([object Object])
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/shipping-address-changed-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/shipping-address-changed-manual.https.html
new file mode 100644
index 0000000..787af96b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/shipping-address-changed-manual.https.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<meta charset="utf-8">
+<title>Test for PaymentRequest shippingAddress attribute</title>
+<link rel="help" href="https://w3c.github.io/payment-request/#shippingaddress-attribute">
+<link rel="help" href="https://w3c.github.io/payment-request/#onshippingaddresschange-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({ explicit_done: true, explicit_timeout: true });
+const validMethod = Object.freeze({ supportedMethods: "basic-card" });
+const validMethods = Object.freeze([validMethod]);
+const validAmount = Object.freeze({ currency: "USD", value: "5.00" });
+const validTotal = Object.freeze({
+  label: "label",
+  amount: validAmount,
+});
+const validShippingOption = Object.freeze({
+  id: "valid",
+  label: "Shipping Option",
+  amount: validAmount,
+  selected: false,
+});
+const validDetails = Object.freeze({
+  total: validTotal,
+  shippingOptions: [validShippingOption],
+});
+const requestShipping = Object.freeze({
+  requestShipping: true,
+});
+
+function testShippingAddressChange() {
+  promise_test(async t => {
+    const request = new PaymentRequest(
+      validMethods,
+      validDetails,
+      requestShipping
+    );
+    assert_equals(
+      request.shippingAddress,
+      null,
+      "request.shippingAddress must initially be null"
+    );
+    const listenerPromise = new Promise(resolve => {
+      request.addEventListener("shippingaddresschange", () => {
+        resolve(request.shippingAddress);
+      });
+    });
+    const handlerPromise = new Promise(resolve => {
+      request.onshippingaddresschange = () => {
+        resolve(request.shippingAddress);
+      };
+    });
+    request.show().catch(err => err);
+    const results = await Promise.all([listenerPromise, handlerPromise]);
+    assert_true(
+      results.every(obj => obj instanceof PaymentAddress),
+      "Expected instances of PaymentAddress"
+    );
+    await request.abort();
+  });
+  done();
+}
+
+</script>
+
+<h2>PaymentRequest shippingAddress attribute</h2>
+<p>
+  When the payment sheet is presented, enter or select a shipping address.
+</p>
+<ol>
+  <li>
+    <button onclick="testShippingAddressChange()">
+      When the shipping address is manually changed, request.shippingAddress is a PaymentAddress.
+    </button>
+  </li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness-expected.txt
deleted file mode 100644
index bc8ea6c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness-expected.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-This is a testharness.js-based test.
-PASS Performance interface: operation getEntries(PerformanceEntryFilterOptions)
-PASS Performance interface: operation getEntriesByType(DOMString)
-PASS Performance interface: operation getEntriesByName(DOMString, DOMString)
-PASS Performance interface: window.performance must inherit property "getEntries(PerformanceEntryFilterOptions)" with the proper type
-PASS Performance interface: calling getEntries(PerformanceEntryFilterOptions) on window.performance with too few arguments must throw TypeError
-PASS Performance interface: window.performance must inherit property "getEntriesByType(DOMString)" with the proper type
-PASS Performance interface: calling getEntriesByType(DOMString) on window.performance with too few arguments must throw TypeError
-PASS Performance interface: window.performance must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type
-PASS Performance interface: calling getEntriesByName(DOMString, DOMString) on window.performance with too few arguments must throw TypeError
-PASS PerformanceEntry interface: existence and properties of interface object
-PASS PerformanceEntry interface object length
-PASS PerformanceEntry interface object name
-PASS PerformanceEntry interface: existence and properties of interface prototype object
-PASS PerformanceEntry interface: existence and properties of interface prototype object's "constructor" property
-PASS PerformanceEntry interface: attribute name
-PASS PerformanceEntry interface: attribute entryType
-PASS PerformanceEntry interface: attribute startTime
-PASS PerformanceEntry interface: attribute duration
-FAIL PerformanceEntry interface: operation toJSON() Type DOMHighResTimeStamp not found
-PASS PerformanceObserverEntryList interface: existence and properties of interface object
-PASS PerformanceObserverEntryList interface object length
-PASS PerformanceObserverEntryList interface object name
-PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object
-PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's "constructor" property
-PASS PerformanceObserverEntryList interface: operation getEntries(PerformanceEntryFilterOptions)
-PASS PerformanceObserverEntryList interface: operation getEntriesByType(DOMString)
-PASS PerformanceObserverEntryList interface: operation getEntriesByName(DOMString, DOMString)
-PASS PerformanceObserver interface: existence and properties of interface object
-PASS PerformanceObserver interface object length
-PASS PerformanceObserver interface object name
-PASS PerformanceObserver interface: existence and properties of interface prototype object
-PASS PerformanceObserver interface: existence and properties of interface prototype object's "constructor" property
-PASS PerformanceObserver interface: operation observe(PerformanceObserverInit)
-PASS PerformanceObserver interface: operation disconnect()
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index 5ba69890f..a3bc373b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -332,7 +332,7 @@
      */
 
     var idlType = type.idlType;
-    
+
     if (type.generic == "Promise") { return false; }
 
     //  nullable and annotated types don't need to be handled separately,
@@ -392,9 +392,12 @@
        default:
            var thing = this.members[idlType];
            if (!thing) { throw new Error("Type " + idlType + " not found"); }
-
            if (thing instanceof IdlEnum) { return true; }
 
+           if (thing instanceof IdlTypedef) {
+               return this.is_json_type(thing.idlType);
+           }
+
            //  dictionaries where all of their members are JSON types
            if (thing instanceof IdlDictionary) {
                var stack = thing.get_inheritance_stack();
@@ -407,7 +410,7 @@
                }
                return Array.from(map.values()).every(this.is_json_type, this);
            }
-           
+
            //  interface types that have a toJSON operation declared on themselves or
            //  one of their inherited or consequential interfaces.
            if (thing instanceof IdlInterface) {
@@ -930,7 +933,7 @@
      * and B.get_inheritance_stack() should return [B, C].
      *
      * Note: as dictionary inheritance is expressed identically by the AST,
-     * this works just as well for getting a stack of inherited dictionaries. 
+     * this works just as well for getting a stack of inherited dictionaries.
      */
 
     var stack = [this];
@@ -1788,10 +1791,6 @@
         })),
         "property has wrong .length");
 
-    if (member.is_to_json_regular_operation()) {
-        this.test_to_json_operation(memberHolderObject, member);
-    }
-
     // Make some suitable arguments
     var args = member.arguments.map(function(arg) {
         return create_suitable_object(arg.idlType);
@@ -1854,7 +1853,7 @@
         test(function() {
             var json = memberHolderObject.toJSON();
             map.forEach(function(type, k) {
-                assert_true(k in json, "property " + k + " should be present in the output of " + this.name + ".prototype.toJSON()");
+                assert_true(k in json, "property " + JSON.stringify(k) + " should be present in the output of " + this.name + ".prototype.toJSON()");
                 var descriptor = Object.getOwnPropertyDescriptor(json, k);
                 assert_true(descriptor.writable, "property " + k + " should be writable");
                 assert_true(descriptor.configurable, "property " + k + " should be configurable");
@@ -1863,7 +1862,7 @@
                 delete json[k];
             }, this);
             for (var k in json) {
-                assert_unreached("property " + k + " should not be present in the output of " + this.name + ".prototype.toJSON()");
+                assert_unreached("property " + JSON.stringify(k) + " should not be present in the output of " + this.name + ".prototype.toJSON()");
             }
         }.bind(this), "Test default toJSON operation of " + this.name);
     } else {
@@ -2065,6 +2064,7 @@
         : "object";
 
     this.test_primary_interface_of(desc, obj, exception, expected_typeof);
+
     var current_interface = this;
     while (current_interface)
     {
@@ -2281,6 +2281,10 @@
                 }
             }.bind(this));
         }
+
+        if (member.is_to_json_regular_operation()) {
+            this.test_to_json_operation(obj, member);
+        }
     }
 };
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html
index 57f714b..42f9dd52 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html
@@ -179,6 +179,16 @@
         idl.add_untested_idls('interface Foo : Bar { };');
         assert_throws(new Error(), _ => idl.is_json_type(typeFrom("Foo")));
     }, "should throw for interfaces which inherit from another interface which wasn't added to the IdlArray");
+
+    test(function() {
+        var idl = new IdlArray();
+        assert_true(idl.is_json_type(typedefFrom("typedef double DOMHighResTimeStamp;").idlType));
+    }, 'should return true for typedefs whose source type is a JSON type');
+
+    test(function() {
+        var idl = new IdlArray();
+        assert_false(idl.is_json_type(typedefFrom("typedef DataView DOMHighResTimeStamp;").idlType));
+    }, 'should return false for typedefs whose source type is not a JSON type');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
index b91f3ee..2dd9371 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
@@ -13,11 +13,15 @@
 <script>
     "use strict";
     function wrap(obj) {
-        return {
-            toJSON: function() {
-                return obj;
-            }
+        function F(obj) {
+            this._obj = obj;
         }
+
+        F.prototype.toJSON = function() {
+            return this._obj;
+        }
+
+        return new F(obj);
     }
 
     var i, obj;
@@ -113,21 +117,21 @@
                 "status_string": "FAIL"
             },
             {
-                "message": "assert_unreached: property bar should not be present in the output of C.prototype.toJSON() Reached unreachable code",
+                "message": "assert_unreached: property \"bar\" should not be present in the output of C.prototype.toJSON() Reached unreachable code",
                 "name": "Test default toJSON operation of C",
                 "properties": {},
                 "stack": "(implementation-defined)",
                 "status_string": "FAIL"
             },
             {
-                "message": "assert_true: property foo should be present in the output of D.prototype.toJSON() expected true got false",
+                "message": "assert_true: property \"foo\" should be present in the output of D.prototype.toJSON() expected true got false",
                 "name": "Test default toJSON operation of D",
                 "properties": {},
                 "stack": "(implementation-defined)",
                 "status_string": "FAIL"
             },
             {
-                "message": "assert_unreached: property baz should not be present in the output of E.prototype.toJSON() Reached unreachable code",
+                "message": "assert_unreached: property \"baz\" should not be present in the output of E.prototype.toJSON() Reached unreachable code",
                 "name": "Test default toJSON operation of E",
                 "properties": {},
                 "stack": "(implementation-defined)",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js
index a8484af..2b73527f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js
@@ -1,5 +1,6 @@
 "use strict";
 
+var typedefFrom = interfaceFrom;
 var dictionaryFrom = interfaceFrom;
 function interfaceFrom(i) {
     var idl = new IdlArray();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt
new file mode 100644
index 0000000..ea6241c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt
@@ -0,0 +1,51 @@
+This is a testharness.js-based test.
+FAIL insecure/same-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/same-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/same-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS insecure/same-origin => secure/same-origin image
+PASS insecure/same-origin => secure/same-origin image in <iframe srcdoc>
+PASS insecure/same-origin => secure/same-origin image in <iframe>
+FAIL insecure/same-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/same-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/same-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS insecure/same-origin => secure/cross-origin image
+PASS insecure/same-origin => secure/cross-origin image in <iframe srcdoc>
+PASS insecure/same-origin => secure/cross-origin image in <iframe>
+FAIL secure/same-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/same-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/same-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS secure/same-origin => secure/same-origin image
+PASS secure/same-origin => secure/same-origin image in <iframe srcdoc>
+PASS secure/same-origin => secure/same-origin image in <iframe>
+FAIL secure/same-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/same-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/same-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS secure/same-origin => secure/cross-origin image
+PASS secure/same-origin => secure/cross-origin image in <iframe srcdoc>
+PASS secure/same-origin => secure/cross-origin image in <iframe>
+FAIL insecure/cross-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/cross-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/cross-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS insecure/cross-origin => secure/same-origin image
+PASS insecure/cross-origin => secure/same-origin image in <iframe srcdoc>
+PASS insecure/cross-origin => secure/same-origin image in <iframe>
+FAIL insecure/cross-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/cross-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL insecure/cross-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS insecure/cross-origin => secure/cross-origin image
+PASS insecure/cross-origin => secure/cross-origin image in <iframe srcdoc>
+PASS insecure/cross-origin => secure/cross-origin image in <iframe>
+FAIL secure/cross-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/cross-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/cross-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS secure/cross-origin => secure/same-origin image
+PASS secure/cross-origin => secure/same-origin image in <iframe srcdoc>
+PASS secure/cross-origin => secure/same-origin image in <iframe>
+FAIL secure/cross-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/cross-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+FAIL secure/cross-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
+PASS secure/cross-origin => secure/cross-origin image
+PASS secure/cross-origin => secure/cross-origin image in <iframe srcdoc>
+PASS secure/cross-origin => secure/cross-origin image in <iframe>
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt
index b4b01b2..0540d48 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 74 tests; 72 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 75 tests; 72 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS URL interface: existence and properties of interface object
 PASS URL interface object length
 PASS URL interface object name
@@ -35,6 +35,7 @@
 PASS URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type
 PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type
 FAIL URL interface: new URL("http://foo") must inherit property "toJSON()" with the proper type assert_inherits: property "toJSON" not found in prototype chain
+FAIL Test toJSON operation of URL memberHolderObject.toJSON is not a function
 PASS URLSearchParams interface: existence and properties of interface object
 PASS URLSearchParams interface object length
 PASS URLSearchParams interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt
index b4b01b2..0540d48 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 74 tests; 72 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 75 tests; 72 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS URL interface: existence and properties of interface object
 PASS URL interface object length
 PASS URL interface object name
@@ -35,6 +35,7 @@
 PASS URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type
 PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type
 FAIL URL interface: new URL("http://foo") must inherit property "toJSON()" with the proper type assert_inherits: property "toJSON" not found in prototype chain
+FAIL Test toJSON operation of URL memberHolderObject.toJSON is not a function
 PASS URLSearchParams interface: existence and properties of interface object
 PASS URLSearchParams interface object length
 PASS URLSearchParams interface object name
diff --git a/third_party/WebKit/Source/core/css/StyleElement.cpp b/third_party/WebKit/Source/core/css/StyleElement.cpp
index ac92b62..484203e 100644
--- a/third_party/WebKit/Source/core/css/StyleElement.cpp
+++ b/third_party/WebKit/Source/core/css/StyleElement.cpp
@@ -50,9 +50,11 @@
       registered_as_candidate_(false),
       start_position_(TextPosition::BelowRangePosition()) {
   if (created_by_parser && document &&
-      document->GetScriptableDocumentParser() && !document->IsInDocumentWrite())
+      document->GetScriptableDocumentParser() &&
+      !document->IsInDocumentWrite()) {
     start_position_ =
         document->GetScriptableDocumentParser()->GetTextPosition();
+  }
 }
 
 StyleElement::~StyleElement() {}
@@ -110,9 +112,10 @@
 void StyleElement::ClearSheet(Element& owner_element) {
   DCHECK(sheet_);
 
-  if (sheet_->IsLoading())
+  if (sheet_->IsLoading()) {
     owner_element.GetDocument().GetStyleEngine().RemovePendingSheet(
         owner_element, style_engine_context_);
+  }
 
   sheet_.Release()->ClearOwnerNode();
 }
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.cpp b/third_party/WebKit/Source/core/css/StyleEngine.cpp
index 1e23da0..4f6ad2e6 100644
--- a/third_party/WebKit/Source/core/css/StyleEngine.cpp
+++ b/third_party/WebKit/Source/core/css/StyleEngine.cpp
@@ -100,9 +100,10 @@
 
   StyleSheetCollectionMap::AddResult result =
       style_sheet_collection_map_.insert(&tree_scope, nullptr);
-  if (result.is_new_entry)
+  if (result.is_new_entry) {
     result.stored_value->value =
         new ShadowTreeStyleSheetCollection(ToShadowRoot(tree_scope));
+  }
   return *result.stored_value->value.Get();
 }
 
@@ -607,13 +608,15 @@
 void StyleEngine::CollectScopedStyleFeaturesTo(RuleFeatureSet& features) const {
   HeapHashSet<Member<const StyleSheetContents>>
       visited_shared_style_sheet_contents;
-  if (GetDocument().GetScopedStyleResolver())
+  if (GetDocument().GetScopedStyleResolver()) {
     GetDocument().GetScopedStyleResolver()->CollectFeaturesTo(
         features, visited_shared_style_sheet_contents);
+  }
   for (TreeScope* tree_scope : active_tree_scopes_) {
-    if (ScopedStyleResolver* resolver = tree_scope->GetScopedStyleResolver())
+    if (ScopedStyleResolver* resolver = tree_scope->GetScopedStyleResolver()) {
       resolver->CollectFeaturesTo(features,
                                   visited_shared_style_sheet_contents);
+    }
   }
 }
 
@@ -780,14 +783,16 @@
 
   if (element.HasClass()) {
     const SpaceSplitString& class_names = element.ClassNames();
-    for (size_t i = 0; i < class_names.size(); i++)
+    for (size_t i = 0; i < class_names.size(); i++) {
       features.CollectSiblingInvalidationSetForClass(
           invalidation_lists, element, class_names[i], min_direct_adjacent);
+    }
   }
 
-  for (const Attribute& attribute : element.Attributes())
+  for (const Attribute& attribute : element.Attributes()) {
     features.CollectSiblingInvalidationSetForAttribute(
         invalidation_lists, element, attribute.GetName(), min_direct_adjacent);
+  }
 
   features.CollectUniversalSiblingInvalidationSet(invalidation_lists,
                                                   min_direct_adjacent);
@@ -813,9 +818,11 @@
                                          1);
 
   for (unsigned i = 1; before_element && i <= affected_siblings;
-       i++, before_element = ElementTraversal::PreviousSibling(*before_element))
+       i++, before_element =
+                ElementTraversal::PreviousSibling(*before_element)) {
     ScheduleSiblingInvalidationsForElement(*before_element, *scheduling_parent,
                                            i);
+  }
 }
 
 void StyleEngine::ScheduleInvalidationsForRemovedSibling(
@@ -835,9 +842,11 @@
                                          1);
 
   for (unsigned i = 1; before_element && i <= affected_siblings;
-       i++, before_element = ElementTraversal::PreviousSibling(*before_element))
+       i++, before_element =
+                ElementTraversal::PreviousSibling(*before_element)) {
     ScheduleSiblingInvalidationsForElement(*before_element, *scheduling_parent,
                                            i);
+  }
 }
 
 void StyleEngine::ScheduleNthPseudoInvalidations(ContainerNode& nth_parent) {
@@ -860,18 +869,21 @@
 
   InvalidationLists invalidation_lists;
   for (const auto& rule_set : rule_sets) {
-    if (!id.IsNull())
+    if (!id.IsNull()) {
       rule_set->Features().CollectInvalidationSetsForId(invalidation_lists,
                                                         element, id);
+    }
     if (class_names) {
       unsigned class_name_count = class_names->size();
-      for (size_t i = 0; i < class_name_count; i++)
+      for (size_t i = 0; i < class_name_count; i++) {
         rule_set->Features().CollectInvalidationSetsForClass(
             invalidation_lists, element, (*class_names)[i]);
+      }
     }
-    for (const Attribute& attribute : element.Attributes())
+    for (const Attribute& attribute : element.Attributes()) {
       rule_set->Features().CollectInvalidationSetsForAttribute(
           invalidation_lists, element, attribute.GetName());
+    }
   }
   style_invalidator_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                      element);
@@ -881,9 +893,10 @@
     ContainerNode& node,
     const HeapHashSet<Member<RuleSet>>& rule_sets) {
   InvalidationLists invalidation_lists;
-  for (const auto& rule_set : rule_sets)
+  for (const auto& rule_set : rule_sets) {
     rule_set->Features().CollectTypeRuleInvalidationSet(invalidation_lists,
                                                         node);
+  }
   DCHECK(invalidation_lists.siblings.IsEmpty());
   style_invalidator_.ScheduleInvalidationSetsForNode(invalidation_lists, node);
 
@@ -906,10 +919,11 @@
 
 void StyleEngine::InvalidateSlottedElements(HTMLSlotElement& slot) {
   for (auto& node : slot.GetDistributedNodes()) {
-    if (node->IsElementNode())
+    if (node->IsElementNode()) {
       node->SetNeedsStyleRecalc(kLocalStyleChange,
                                 StyleChangeReasonForTracing::Create(
                                     StyleChangeReason::kStyleSheetChange));
+    }
   }
 }
 
@@ -1163,11 +1177,12 @@
 
 const MediaQueryEvaluator& StyleEngine::EnsureMediaQueryEvaluator() {
   if (!media_query_evaluator_) {
-    if (GetDocument().GetFrame())
+    if (GetDocument().GetFrame()) {
       media_query_evaluator_ =
           new MediaQueryEvaluator(GetDocument().GetFrame());
-    else
+    } else {
       media_query_evaluator_ = new MediaQueryEvaluator("all");
+    }
   }
   return *media_query_evaluator_;
 }
diff --git a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
index 7ea6d68..356cf4e 100644
--- a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
+++ b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
@@ -109,11 +109,12 @@
 
   // If we are looking at a first letter element then we need to find the
   // first letter text layoutObject from the parent node, and not ourselves.
-  if (element.IsFirstLetterPseudoElement())
+  if (element.IsFirstLetterPseudoElement()) {
     parent_layout_object =
         element.ParentOrShadowHostElement()->GetLayoutObject();
-  else
+  } else {
     parent_layout_object = element.GetLayoutObject();
+  }
 
   if (!parent_layout_object ||
       !parent_layout_object->Style()->HasPseudoStyle(kPseudoIdFirstLetter) ||
@@ -240,10 +241,11 @@
   // The text fragment we get our content from is being destroyed. We need
   // to tell our parent element to recalcStyle so we can get cleaned up
   // as well.
-  if (!fragment)
+  if (!fragment) {
     SetNeedsStyleRecalc(
         kLocalStyleChange,
         StyleChangeReasonForTracing::Create(StyleChangeReason::kPseudoClass));
+  }
 
   remaining_text_layout_object_ = fragment;
 }