diff --git a/DEPS b/DEPS
index 782585f..453296bb 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '8289306771381298cf3b87183882cc1f1fef4dc3',
+  'skia_revision': '255607f094dac0f1c075a5b718005e7bd4d03e3d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '65e2bf234545de3acd7f8f1bbda4f0e9094e46f4',
+  'catapult_revision': '2857b6b6c8582e67f9d81360198a1dc9fa561c39',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -214,7 +214,7 @@
     Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'bcaa2585874573d486d94101e883cd2e5dfbca97',
 
   'src/third_party/usrsctp/usrsctplib':
-    Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '76bea922c32b742ecf5c4a0c64dcfb95ab5387c0',
+    Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '2f6478eb8d40f1766a96b5b033ed26c0c2244589',
 
   'src/third_party/libsrtp':
     Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + '1d45b8e599dc2db6ea3ae22dbc94a8c504652423',
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc
index 40dd9a0..147e7aa8 100644
--- a/ash/system/network/network_list.cc
+++ b/ash/system/network/network_list.cc
@@ -114,7 +114,7 @@
   }
 
   virtual void SetIsOn(bool enabled) {
-    toggle_->SetEnabled(true);
+    toggle_->set_accepts_events(true);
     toggle_->SetIsOn(enabled, true);
   }
 
@@ -141,9 +141,10 @@
     DCHECK_EQ(toggle_, sender);
     // In the event of frequent clicks, helps to prevent a toggle button state
     // from becoming inconsistent with the async operation of enabling /
-    // disabling of mobile radio. The toggle will get re-enabled in the next
-    // call to NetworkListView::Update().
-    toggle_->SetEnabled(false);
+    // disabling of mobile radio. The toggle will get unlocked in the next
+    // call to NetworkListView::Update(). Note that we don't disable/enable
+    // because that would clear focus.
+    toggle_->set_accepts_events(false);
     OnToggleToggled(toggle_->is_on());
   }
 
diff --git a/ash/system/tray/tray_details_view.cc b/ash/system/tray/tray_details_view.cc
index 3f154af..1c4c34a 100644
--- a/ash/system/tray/tray_details_view.cc
+++ b/ash/system/tray/tray_details_view.cc
@@ -65,19 +65,21 @@
     PositionHeaderRows();
   }
 
-  void PaintChildren(const ui::PaintContext& context) override {
-    views::View::PaintChildren(context);
+  void PaintChildren(const views::PaintInfo& paint_info) override {
+    views::View::PaintChildren(paint_info);
     bool did_draw_shadow = false;
     // Paint header row separators.
     for (auto& header : headers_)
-      did_draw_shadow = PaintDelineation(header, context) || did_draw_shadow;
+      did_draw_shadow =
+          PaintDelineation(header, paint_info.context()) || did_draw_shadow;
 
     // Draw a shadow at the top of the viewport when scrolled, but only if a
     // header didn't already draw one. Overlap the shadow with the separator
     // that's below the header view so we don't get both a separator and a full
     // shadow.
     if (y() != 0 && !did_draw_shadow)
-      DrawShadow(context, gfx::Rect(0, 0, width(), -y() - kSeparatorWidth));
+      DrawShadow(paint_info.context(),
+                 gfx::Rect(0, 0, width(), -y() - kSeparatorWidth));
   }
 
   void Layout() override {
diff --git a/ash/system/tray/tray_popup_utils.cc b/ash/system/tray/tray_popup_utils.cc
index 0f987e7..ee849f5 100644
--- a/ash/system/tray/tray_popup_utils.cc
+++ b/ash/system/tray/tray_popup_utils.cc
@@ -250,7 +250,6 @@
       (kTrayToggleButtonWidth - toggle_size.width()) / 2;
   toggle->SetBorder(views::CreateEmptyBorder(
       gfx::Insets(vertical_padding, horizontal_padding)));
-  toggle->SetFocusPainter(CreateFocusPainter());
   toggle->SetAccessibleName(l10n_util::GetStringUTF16(accessible_name_id));
   return toggle;
 }
diff --git a/ash/system/update/tray_update.cc b/ash/system/update/tray_update.cc
index bd82e28..73867bb 100644
--- a/ash/system/update/tray_update.cc
+++ b/ash/system/update/tray_update.cc
@@ -188,4 +188,13 @@
   tray_view()->SetVisible(visible);
 }
 
+// static
+void TrayUpdate::ResetForTesting() {
+  update_required_ = false;
+  severity_ = mojom::UpdateSeverity::NONE;
+  factory_reset_required_ = false;
+  update_over_cellular_available_ = false;
+  update_type_ = mojom::UpdateType::SYSTEM;
+}
+
 }  // namespace ash
diff --git a/ash/system/update/tray_update.h b/ash/system/update/tray_update.h
index d730705..ffe3d57 100644
--- a/ash/system/update/tray_update.h
+++ b/ash/system/update/tray_update.h
@@ -47,8 +47,10 @@
   // Expose label information for testing.
   views::Label* GetLabelForTesting();
 
- private:
+  // Resets everything for testing.
+  static void ResetForTesting();
 
+ private:
   class UpdateView;
 
   // Overridden from TrayImageItem.
diff --git a/ash/system/update/tray_update_unittest.cc b/ash/system/update/tray_update_unittest.cc
index 9b36dc6b..43021b6 100644
--- a/ash/system/update/tray_update_unittest.cc
+++ b/ash/system/update/tray_update_unittest.cc
@@ -15,7 +15,20 @@
 
 namespace ash {
 
-using TrayUpdateTest = AshTestBase;
+class TrayUpdateTest : public AshTestBase {
+ public:
+  TrayUpdateTest() = default;
+  ~TrayUpdateTest() override = default;
+
+  // testing::Test:
+  void TearDown() override {
+    AshTestBase::TearDown();
+    TrayUpdate::ResetForTesting();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TrayUpdateTest);
+};
 
 // Tests that the update icon becomes visible when an update becomes
 // available.
@@ -42,6 +55,9 @@
   SystemTray* tray = GetPrimarySystemTray();
   TrayUpdate* tray_update = tray->tray_update();
 
+  // The system starts with no update pending, so the icon isn't visible.
+  EXPECT_FALSE(tray_update->tray_view()->visible());
+
   // Simulate an update.
   Shell::Get()->system_tray_controller()->ShowUpdateIcon(
       mojom::UpdateSeverity::LOW, false, mojom::UpdateType::FLASH);
diff --git a/ash/wm/drag_window_controller.cc b/ash/wm/drag_window_controller.cc
index ea3f62df..b70304a0 100644
--- a/ash/wm/drag_window_controller.cc
+++ b/ash/wm/drag_window_controller.cc
@@ -15,7 +15,9 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
+#include "ui/compositor/compositor.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_tree_owner.h"
 #include "ui/compositor/paint_context.h"
@@ -232,7 +234,8 @@
 }
 
 void DragWindowController::RequestLayerPaintForTest() {
-  ui::PaintContext context(nullptr, 1.0f, gfx::Rect());
+  ui::PaintContext context(nullptr, 1.0f, gfx::Rect(),
+                           window_->GetHost()->compositor()->is_pixel_canvas());
   for (auto& details : drag_windows_) {
     std::vector<ui::Layer*> layers;
     layers.push_back(details->drag_window_->layer());
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index fd889200..a58bcd7 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -130,6 +130,9 @@
     recording_source_->UpdateDisplayItemList(
         picture_layer_inputs_.display_list,
         picture_layer_inputs_.painter_reported_memory_usage);
+    recording_source_->SetRecordingScaleFactor(
+        layer_tree_host()->recording_scale_factor());
+
     SetNeedsPushProperties();
   } else {
     // If this invalidation did not affect the recording source, then it can be
diff --git a/cc/layers/recording_source.cc b/cc/layers/recording_source.cc
index 0177d35..1fa1d7c 100644
--- a/cc/layers/recording_source.cc
+++ b/cc/layers/recording_source.cc
@@ -38,7 +38,8 @@
       is_solid_color_(false),
       clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
       solid_color_(SK_ColorTRANSPARENT),
-      background_color_(SK_ColorTRANSPARENT) {}
+      background_color_(SK_ColorTRANSPARENT),
+      recording_scale_factor_(1.f) {}
 
 RecordingSource::~RecordingSource() {}
 
@@ -140,6 +141,10 @@
   return scoped_refptr<RasterSource>(new RasterSource(this));
 }
 
+void RecordingSource::SetRecordingScaleFactor(float recording_scale_factor) {
+  recording_scale_factor_ = recording_scale_factor;
+}
+
 void RecordingSource::DetermineIfSolidColor() {
   DCHECK(display_list_);
   is_solid_color_ = false;
diff --git a/cc/layers/recording_source.h b/cc/layers/recording_source.h
index 3574086..26edcbc3 100644
--- a/cc/layers/recording_source.h
+++ b/cc/layers/recording_source.h
@@ -51,6 +51,8 @@
 
   void SetNeedsDisplayRect(const gfx::Rect& layer_rect);
 
+  void SetRecordingScaleFactor(float recording_scale_factor);
+
   // These functions are virtual for testing.
   virtual scoped_refptr<RasterSource> CreateRasterSource() const;
 
@@ -68,6 +70,7 @@
   SkColor background_color_;
   scoped_refptr<DisplayItemList> display_list_;
   size_t painter_reported_memory_usage_;
+  float recording_scale_factor_;
 
  private:
   void UpdateInvalidationForNewViewport(const gfx::Rect& old_recorded_viewport,
diff --git a/cc/raster/raster_source.cc b/cc/raster/raster_source.cc
index 3fc5d93..61e6623 100644
--- a/cc/raster/raster_source.cc
+++ b/cc/raster/raster_source.cc
@@ -33,7 +33,8 @@
       size_(other->size_),
       clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
       slow_down_raster_scale_factor_for_debug_(
-          other->slow_down_raster_scale_factor_for_debug_) {}
+          other->slow_down_raster_scale_factor_for_debug_),
+      recording_scale_factor_(other->recording_scale_factor_) {}
 RasterSource::~RasterSource() = default;
 
 void RasterSource::SetupCanvasForRaster(
@@ -46,7 +47,8 @@
   canvas->clipRect(gfx::RectToSkRect(canvas_playback_rect));
   canvas->translate(raster_transform.translation().x(),
                     raster_transform.translation().y());
-  canvas->scale(raster_transform.scale(), raster_transform.scale());
+  canvas->scale(raster_transform.scale() / recording_scale_factor_,
+                raster_transform.scale() / recording_scale_factor_);
 
   if (should_clear_canvas)
     ClearCanvasForPlayback(canvas);
@@ -186,6 +188,7 @@
   TRACE_EVENT0("cc", "RasterSource::PerformSolidColorAnalysis");
 
   layer_rect.Intersect(gfx::Rect(size_));
+  layer_rect = gfx::ScaleToRoundedRect(layer_rect, recording_scale_factor_);
   return display_list_->GetColorIfSolidInRect(layer_rect, color);
 }
 
diff --git a/cc/raster/raster_source.h b/cc/raster/raster_source.h
index 9cce907..a17380a 100644
--- a/cc/raster/raster_source.h
+++ b/cc/raster/raster_source.h
@@ -143,6 +143,7 @@
   const gfx::Size size_;
   const bool clear_canvas_with_debug_color_;
   const int slow_down_raster_scale_factor_for_debug_;
+  const float recording_scale_factor_;
 
  private:
   void RasterCommon(SkCanvas* canvas,
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc
index 2540137..68bbb6e9 100644
--- a/cc/raster/raster_source_unittest.cc
+++ b/cc/raster/raster_source_unittest.cc
@@ -96,6 +96,89 @@
   EXPECT_EQ(solid_color, color);
 }
 
+TEST(RasterSourceTest, AnalyzeIsSolidScaled) {
+  gfx::Size layer_bounds(400, 400);
+  const std::vector<float> recording_scales = {1.25f, 1.33f, 1.5f,  1.6f,
+                                               1.66f, 2.f,   2.25f, 2.5f};
+  for (float recording_scale : recording_scales) {
+    std::unique_ptr<FakeRecordingSource> recording_source =
+        FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
+    recording_source->SetRecordingScaleFactor(recording_scale);
+
+    PaintFlags solid_flags;
+    SkColor solid_color = SkColorSetARGB(255, 12, 23, 34);
+    solid_flags.setColor(solid_color);
+
+    SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67);
+    SkColor color = SK_ColorTRANSPARENT;
+    PaintFlags non_solid_flags;
+    bool is_solid_color = false;
+    non_solid_flags.setColor(non_solid_color);
+
+    recording_source->add_draw_rect_with_flags(
+        gfx::ScaleToEnclosingRect(gfx::Rect(layer_bounds), recording_scale),
+        solid_flags);
+    recording_source->Rerecord();
+
+    scoped_refptr<RasterSource> raster = recording_source->CreateRasterSource();
+
+    // Ensure everything is solid.
+    for (int y = 0; y <= 300; y += 100) {
+      for (int x = 0; x <= 300; x += 100) {
+        gfx::Rect rect(x, y, 100, 100);
+        is_solid_color = raster->PerformSolidColorAnalysis(rect, &color);
+        EXPECT_TRUE(is_solid_color)
+            << rect.ToString() << " recording_scale: " << recording_scale;
+        EXPECT_EQ(solid_color, color)
+            << rect.ToString() << " recording_scale: " << recording_scale;
+      }
+    }
+
+    // Add one non-solid pixel and recreate the raster source.
+    recording_source->add_draw_rect_with_flags(
+        gfx::Rect(std::round(50 * recording_scale),
+                  std::round(50 * recording_scale), 1, 1),
+        non_solid_flags);
+    recording_source->Rerecord();
+    raster = recording_source->CreateRasterSource();
+
+    color = SK_ColorTRANSPARENT;
+    is_solid_color =
+        raster->PerformSolidColorAnalysis(gfx::Rect(0, 0, 100, 100), &color);
+    EXPECT_FALSE(is_solid_color) << " recording_scale: " << recording_scale;
+
+    color = SK_ColorTRANSPARENT;
+    is_solid_color =
+        raster->PerformSolidColorAnalysis(gfx::Rect(0, 0, 51, 51), &color);
+    EXPECT_FALSE(is_solid_color) << " recording_scale: " << recording_scale;
+
+    color = SK_ColorTRANSPARENT;
+    is_solid_color =
+        raster->PerformSolidColorAnalysis(gfx::Rect(51, 0, 100, 100), &color);
+    EXPECT_TRUE(is_solid_color) << " recording_scale: " << recording_scale;
+    EXPECT_EQ(solid_color, color) << " recording_scale: " << recording_scale;
+
+    // Boundaries should be clipped.
+    color = SK_ColorTRANSPARENT;
+    is_solid_color =
+        raster->PerformSolidColorAnalysis(gfx::Rect(350, 0, 100, 100), &color);
+    EXPECT_TRUE(is_solid_color) << " recording_scale: " << recording_scale;
+    EXPECT_EQ(solid_color, color) << " recording_scale: " << recording_scale;
+
+    color = SK_ColorTRANSPARENT;
+    is_solid_color =
+        raster->PerformSolidColorAnalysis(gfx::Rect(0, 350, 100, 100), &color);
+    EXPECT_TRUE(is_solid_color) << " recording_scale: " << recording_scale;
+    EXPECT_EQ(solid_color, color) << " recording_scale: " << recording_scale;
+
+    color = SK_ColorTRANSPARENT;
+    is_solid_color = raster->PerformSolidColorAnalysis(
+        gfx::Rect(350, 350, 100, 100), &color);
+    EXPECT_TRUE(is_solid_color) << " recording_scale: " << recording_scale;
+    EXPECT_EQ(solid_color, color) << " recording_scale: " << recording_scale;
+  }
+}
+
 TEST(RasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) {
   gfx::Size layer_bounds(512, 512);
 
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index bbe3c681..a91a2df 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -1762,60 +1762,19 @@
     resource_ids_to_receive.insert(id2);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_receive);
-  }
 
-  EXPECT_EQ(2u, resource_provider_->num_resources());
-  ResourceProvider::ResourceIdMap resource_map =
-      resource_provider_->GetChildToParentMap(child_id);
-  viz::ResourceId mapped_id1 = resource_map[id1];
-  viz::ResourceId mapped_id2 = resource_map[id2];
-  EXPECT_NE(0u, mapped_id1);
-  EXPECT_NE(0u, mapped_id2);
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
-
-  {
-    // The parent transfers the resources to the grandparent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(mapped_id1);
-    resource_ids_to_transfer.push_back(mapped_id2);
-
-    std::vector<viz::TransferableResource> list;
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
-
-    ASSERT_EQ(2u, list.size());
-    if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
-      EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
-      EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData());
-    }
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
-
-    // Release the resource in the parent. Set no resources as being in use. The
-    // resources are exported so that can't be transferred back yet.
-    viz::ResourceIdSet no_resources;
-    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
-
+    std::vector<viz::ReturnedResource> returned =
+        viz::TransferableResource::ReturnResources(list);
+    child_resource_provider_->ReceiveReturnsFromParent(returned);
     EXPECT_EQ(0u, returned_to_child.size());
     EXPECT_EQ(2u, resource_provider_->num_resources());
 
-    // Return the resources from the grandparent to the parent. They should be
-    // returned to the child then.
-    EXPECT_EQ(2u, list.size());
-    EXPECT_EQ(mapped_id1, list[0].id);
-    EXPECT_EQ(mapped_id2, list[1].id);
-    std::vector<viz::ReturnedResource> returned =
-        viz::TransferableResource::ReturnResources(list);
-    resource_provider_->ReceiveReturnsFromParent(returned);
-
+    // Return the resources from the parent, it should be returned at this
+    // point.
+    viz::ResourceIdSet no_resources;
+    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
+    EXPECT_EQ(2u, returned_to_child.size());
     EXPECT_EQ(0u, resource_provider_->num_resources());
-    ASSERT_EQ(2u, returned_to_child.size());
-    if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
-      EXPECT_TRUE(returned_to_child[0].sync_token.HasData());
-      EXPECT_TRUE(returned_to_child[1].sync_token.HasData());
-    }
-    EXPECT_FALSE(returned_to_child[0].lost);
-    EXPECT_FALSE(returned_to_child[1].lost);
   }
 }
 
@@ -1862,77 +1821,13 @@
     resource_ids_to_receive.insert(id2);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_receive);
-  }
 
-  EXPECT_EQ(2u, resource_provider_->num_resources());
-  ResourceProvider::ResourceIdMap resource_map =
-      resource_provider_->GetChildToParentMap(child_id);
-  viz::ResourceId mapped_id1 = resource_map[id1];
-  viz::ResourceId mapped_id2 = resource_map[id2];
-  EXPECT_NE(0u, mapped_id1);
-  EXPECT_NE(0u, mapped_id2);
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
-  EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
-
-  {
-    // The parent transfers the resources to the grandparent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(mapped_id1);
-    resource_ids_to_transfer.push_back(mapped_id2);
-
-    std::vector<viz::TransferableResource> list;
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
-
-    ASSERT_EQ(2u, list.size());
-    if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
-      EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
-      EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData());
-    }
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
-
-    // Release the resource in the parent. Set no resources as being in use. The
-    // resources are exported so that can't be transferred back yet.
-    viz::ResourceIdSet no_resources;
-    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
-
-    // Destroy the child, the resources should not be returned yet.
     EXPECT_EQ(0u, returned_to_child.size());
     EXPECT_EQ(2u, resource_provider_->num_resources());
-
+    // Destroy the child, the resources should be returned.
     resource_provider_->DestroyChild(child_id);
-
-    EXPECT_EQ(2u, resource_provider_->num_resources());
-    ASSERT_EQ(0u, returned_to_child.size());
-
-    // Return a resource from the grandparent, it should be returned at this
-    // point.
-    EXPECT_EQ(2u, list.size());
-    EXPECT_EQ(mapped_id1, list[0].id);
-    EXPECT_EQ(mapped_id2, list[1].id);
-    std::vector<viz::TransferableResource> return_list;
-    return_list.push_back(list[1]);
-    list.pop_back();
-    std::vector<viz::ReturnedResource> returned =
-        viz::TransferableResource::ReturnResources(return_list);
-    resource_provider_->ReceiveReturnsFromParent(returned);
-
-    EXPECT_EQ(1u, resource_provider_->num_resources());
-    ASSERT_EQ(1u, returned_to_child.size());
-    if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
-      EXPECT_TRUE(returned_to_child[0].sync_token.HasData());
-    }
-    EXPECT_FALSE(returned_to_child[0].lost);
-    returned_to_child.clear();
-
-    // Destroy the parent resource provider. The resource that's left should be
-    // lost at this point, and returned.
-    resource_provider_ = nullptr;
-    ASSERT_EQ(1u, returned_to_child.size());
-    if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
-      EXPECT_TRUE(returned_to_child[0].sync_token.HasData());
-    }
-    EXPECT_TRUE(returned_to_child[0].lost);
+    EXPECT_EQ(2u, returned_to_child.size());
+    EXPECT_EQ(0u, resource_provider_->num_resources());
   }
 }
 
@@ -1989,121 +1884,6 @@
   EXPECT_EQ(0u, child_resource_provider_->num_resources());
 }
 
-TEST_P(ResourceProviderTest, UnuseTransferredResources) {
-  gfx::Size size(1, 1);
-  viz::ResourceFormat format = viz::RGBA_8888;
-  size_t pixel_size = TextureSizeBytes(size, format);
-  ASSERT_EQ(4U, pixel_size);
-
-  viz::ResourceId id = child_resource_provider_->CreateResource(
-      size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format,
-      gfx::ColorSpace());
-  uint8_t data[4] = {1, 2, 3, 4};
-  child_resource_provider_->CopyToResource(id, data, size);
-
-  std::vector<viz::ReturnedResource> returned_to_child;
-  int child_id =
-      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
-  const ResourceProvider::ResourceIdMap& map =
-      resource_provider_->GetChildToParentMap(child_id);
-  {
-    // Transfer some resource to the parent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(id);
-
-    std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
-    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
-    resource_provider_->ReceiveFromChild(child_id, list);
-    viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(id);
-    resource_provider_->DeclareUsedResourcesFromChild(child_id,
-                                                      resource_ids_to_receive);
-  }
-  std::vector<viz::TransferableResource> sent_to_top_level;
-  {
-    // Parent transfers to top-level.
-    ASSERT_TRUE(map.find(id) != map.end());
-    viz::ResourceId parent_id = map.find(id)->second;
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(parent_id);
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                            &sent_to_top_level);
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
-  }
-  {
-    // Stop using resource.
-    viz::ResourceIdSet empty;
-    resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
-    // Resource is not yet returned to the child, since it's in use by the
-    // top-level.
-    EXPECT_TRUE(returned_to_child.empty());
-  }
-  {
-    // Send the resource to the parent again.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(id);
-    std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
-    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
-    resource_provider_->ReceiveFromChild(child_id, list);
-    viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(id);
-    resource_provider_->DeclareUsedResourcesFromChild(child_id,
-                                                      resource_ids_to_receive);
-  }
-  {
-    // Receive returns back from top-level.
-    std::vector<viz::ReturnedResource> returned =
-        viz::TransferableResource::ReturnResources(sent_to_top_level);
-    resource_provider_->ReceiveReturnsFromParent(returned);
-    // Resource is still not yet returned to the child, since it's declared used
-    // in the parent.
-    EXPECT_TRUE(returned_to_child.empty());
-    ASSERT_TRUE(map.find(id) != map.end());
-    viz::ResourceId parent_id = map.find(id)->second;
-    EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
-  }
-  {
-    sent_to_top_level.clear();
-    // Parent transfers again to top-level.
-    ASSERT_TRUE(map.find(id) != map.end());
-    viz::ResourceId parent_id = map.find(id)->second;
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(parent_id);
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                            &sent_to_top_level);
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
-  }
-  {
-    // Receive returns back from top-level.
-    std::vector<viz::ReturnedResource> returned =
-        viz::TransferableResource::ReturnResources(sent_to_top_level);
-    resource_provider_->ReceiveReturnsFromParent(returned);
-    // Resource is still not yet returned to the child, since it's still
-    // declared used in the parent.
-    EXPECT_TRUE(returned_to_child.empty());
-    ASSERT_TRUE(map.find(id) != map.end());
-    viz::ResourceId parent_id = map.find(id)->second;
-    EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
-  }
-  {
-    // Stop using resource.
-    viz::ResourceIdSet empty;
-    resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
-    // Resource should have been returned to the child, since it's no longer in
-    // use by the top-level.
-    ASSERT_EQ(1u, returned_to_child.size());
-    EXPECT_EQ(id, returned_to_child[0].id);
-    EXPECT_EQ(2, returned_to_child[0].count);
-    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
-    returned_to_child.clear();
-    EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
-  }
-}
-
 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
  public:
   static void RunTest(GLenum child_filter, GLenum parent_filter) {
@@ -2306,7 +2086,7 @@
       base::Bind(ReleaseCallback, &release_sync_token, &lost_resource,
                  &main_thread_task_runner);
   viz::ResourceId resource =
-      resource_provider_->CreateResourceFromTextureMailbox(
+      child_resource_provider_->CreateResourceFromTextureMailbox(
           viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D),
           SingleReleaseCallbackImpl::Create(callback));
   EXPECT_EQ(1u, context()->NumTextures());
@@ -2316,7 +2096,8 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(resource);
     std::vector<viz::TransferableResource> list;
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(1u, list.size());
     EXPECT_LE(sync_token.release_count(),
               list[0].mailbox_holder.sync_token.release_count());
@@ -2344,11 +2125,11 @@
     // consistent.
     std::vector<viz::ReturnedResource> returned =
         viz::TransferableResource::ReturnResources(list);
-    resource_provider_->ReceiveReturnsFromParent(returned);
+    child_resource_provider_->ReceiveReturnsFromParent(returned);
     EXPECT_EQ(1u, context()->NumTextures());
     EXPECT_FALSE(release_sync_token.HasData());
 
-    resource_provider_->DeleteResource(resource);
+    child_resource_provider_->DeleteResource(resource);
     EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(),
               release_sync_token.release_count());
     EXPECT_FALSE(lost_resource);
@@ -2360,7 +2141,7 @@
   sync_token = release_sync_token;
   EXPECT_LT(0u, sync_token.release_count());
   release_sync_token.Clear();
-  resource = resource_provider_->CreateResourceFromTextureMailbox(
+  resource = child_resource_provider_->CreateResourceFromTextureMailbox(
       viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D),
       SingleReleaseCallbackImpl::Create(callback));
   EXPECT_EQ(1u, context()->NumTextures());
@@ -2370,7 +2151,8 @@
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
     resource_ids_to_transfer.push_back(resource);
     std::vector<viz::TransferableResource> list;
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
     ASSERT_EQ(1u, list.size());
     EXPECT_LE(sync_token.release_count(),
               list[0].mailbox_holder.sync_token.release_count());
@@ -2395,7 +2177,7 @@
     EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
 
     // Delete the resource, which shouldn't do anything.
-    resource_provider_->DeleteResource(resource);
+    child_resource_provider_->DeleteResource(resource);
     EXPECT_EQ(1u, context()->NumTextures());
     EXPECT_FALSE(release_sync_token.HasData());
 
@@ -2403,7 +2185,7 @@
     // sync points to be consistent.
     std::vector<viz::ReturnedResource> returned =
         viz::TransferableResource::ReturnResources(list);
-    resource_provider_->ReceiveReturnsFromParent(returned);
+    child_resource_provider_->ReceiveReturnsFromParent(returned);
     EXPECT_LE(list[0].mailbox_holder.sync_token.release_count(),
               release_sync_token.release_count());
     EXPECT_FALSE(lost_resource);
@@ -2472,83 +2254,6 @@
             child_resource_provider_->InUseByConsumer(resource));
 }
 
-TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
-  gfx::Size size(1, 1);
-  viz::ResourceFormat format = viz::RGBA_8888;
-  viz::ResourceId resource = child_resource_provider_->CreateResource(
-      size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format,
-      gfx::ColorSpace());
-  child_resource_provider_->AllocateForTesting(resource);
-
-  std::vector<viz::ReturnedResource> returned_to_child;
-  int child_id =
-      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
-  {
-    // Transfer the resource to the parent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(resource);
-    std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
-    EXPECT_EQ(1u, list.size());
-
-    resource_provider_->ReceiveFromChild(child_id, list);
-    viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(resource);
-    resource_provider_->DeclareUsedResourcesFromChild(child_id,
-                                                      resource_ids_to_receive);
-  }
-
-  {
-    ResourceProvider::ResourceIdMap resource_map =
-        resource_provider_->GetChildToParentMap(child_id);
-    viz::ResourceId parent_resource = resource_map[resource];
-    EXPECT_NE(0u, parent_resource);
-
-    // Transfer to a grandparent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(parent_resource);
-    std::vector<viz::TransferableResource> list;
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
-
-    // Receive back a lost resource from the grandparent.
-    EXPECT_EQ(1u, list.size());
-    EXPECT_EQ(parent_resource, list[0].id);
-    std::vector<viz::ReturnedResource> returned =
-        viz::TransferableResource::ReturnResources(list);
-    EXPECT_EQ(1u, returned.size());
-    EXPECT_EQ(parent_resource, returned[0].id);
-    returned[0].lost = true;
-    resource_provider_->ReceiveReturnsFromParent(returned);
-
-    // The resource should be lost.
-    EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
-
-    // Lost resources stay in use in the parent forever.
-    EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
-  }
-
-  {
-    EXPECT_EQ(0u, returned_to_child.size());
-
-    // Transfer resources back from the parent to the child. Set no resources as
-    // being in use.
-    viz::ResourceIdSet no_resources;
-    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
-
-    // Expect the resource to be lost.
-    ASSERT_EQ(1u, returned_to_child.size());
-    EXPECT_TRUE(returned_to_child[0].lost);
-    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
-    returned_to_child.clear();
-  }
-
-  // The resource should be lost.
-  EXPECT_TRUE(child_resource_provider_->IsLost(resource));
-
-  // Lost resources stay in use in the parent forever.
-  EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
-}
 
 TEST_P(ResourceProviderTest, LostMailboxInParent) {
   gpu::SyncToken release_sync_token;
@@ -2603,76 +2308,6 @@
             GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
 }
 
-TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
-  gpu::SyncToken release_sync_token;
-  bool lost_resource = false;
-  bool release_called = false;
-  gpu::SyncToken sync_token;
-  viz::ResourceId resource = CreateChildMailbox(
-      &release_sync_token, &lost_resource, &release_called, &sync_token);
-
-  std::vector<viz::ReturnedResource> returned_to_child;
-  int child_id =
-      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
-  {
-    // Transfer the resource to the parent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(resource);
-    std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
-    EXPECT_EQ(1u, list.size());
-
-    resource_provider_->ReceiveFromChild(child_id, list);
-    viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(resource);
-    resource_provider_->DeclareUsedResourcesFromChild(child_id,
-                                                      resource_ids_to_receive);
-  }
-
-  {
-    ResourceProvider::ResourceIdMap resource_map =
-        resource_provider_->GetChildToParentMap(child_id);
-    viz::ResourceId parent_resource = resource_map[resource];
-    EXPECT_NE(0u, parent_resource);
-
-    // Transfer to a grandparent.
-    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(parent_resource);
-    std::vector<viz::TransferableResource> list;
-    resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
-
-    // Receive back a lost resource from the grandparent.
-    EXPECT_EQ(1u, list.size());
-    EXPECT_EQ(parent_resource, list[0].id);
-    std::vector<viz::ReturnedResource> returned =
-        viz::TransferableResource::ReturnResources(list);
-    EXPECT_EQ(1u, returned.size());
-    EXPECT_EQ(parent_resource, returned[0].id);
-    returned[0].lost = true;
-    resource_provider_->ReceiveReturnsFromParent(returned);
-  }
-
-  {
-    EXPECT_EQ(0u, returned_to_child.size());
-
-    // Transfer resources back from the parent to the child. Set no resources as
-    // being in use.
-    viz::ResourceIdSet no_resources;
-    resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
-
-    // Expect the resource to be lost.
-    ASSERT_EQ(1u, returned_to_child.size());
-    EXPECT_TRUE(returned_to_child[0].lost);
-    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
-    returned_to_child.clear();
-  }
-
-  // Delete the resource in the child. Expect the resource to be lost.
-  child_resource_provider_->DeleteResource(resource);
-  EXPECT_TRUE(lost_resource);
-}
-
 TEST_P(ResourceProviderTest, Shutdown) {
   gpu::SyncToken release_sync_token;
   bool lost_resource = false;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 7c5941a..78865db 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1037,6 +1037,12 @@
   SetNeedsCommit();
 }
 
+void LayerTreeHost::SetRecordingScaleFactor(float recording_scale_factor) {
+  if (recording_scale_factor_ == recording_scale_factor)
+    return;
+  recording_scale_factor_ = recording_scale_factor;
+}
+
 void LayerTreeHost::SetPaintedDeviceScaleFactor(
     float painted_device_scale_factor) {
   if (painted_device_scale_factor_ == painted_device_scale_factor)
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index adfca180..a68f671 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -319,6 +319,8 @@
   void SetDeviceScaleFactor(float device_scale_factor);
   float device_scale_factor() const { return device_scale_factor_; }
 
+  void SetRecordingScaleFactor(float recording_scale_factor);
+
   void SetPaintedDeviceScaleFactor(float painted_device_scale_factor);
   float painted_device_scale_factor() const {
     return painted_device_scale_factor_;
@@ -495,6 +497,8 @@
 
   void RequestBeginMainFrameNotExpected(bool new_state);
 
+  float recording_scale_factor() const { return recording_scale_factor_; }
+
  protected:
   LayerTreeHost(InitParams* params, CompositorMode mode);
 
@@ -602,6 +606,7 @@
 
   float device_scale_factor_ = 1.f;
   float painted_device_scale_factor_ = 1.f;
+  float recording_scale_factor_ = 1.f;
   float page_scale_factor_ = 1.f;
   float min_page_scale_factor_ = 1.f;
   float max_page_scale_factor_ = 1.f;
diff --git a/chrome/VERSION b/chrome/VERSION
index 6396691..cf19862 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=62
 MINOR=0
-BUILD=3175
+BUILD=3176
 PATCH=0
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index a6c10d4..a551ff7 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2158,24 +2158,15 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIES_ALLOW_SITES_RECOMMENDED" desc="The 'allow cookies' label in site settings -- the recommended setting for when sites want to read/write cookie information.">
     Allow sites to save and read cookie data (recommended)
   </message>
-  <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_ALLOW" desc="The 'allow' label for Flash in site settings.">
-    Allow sites to run Flash
-  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_BLOCK" desc="The 'block' label for Flash in site settings.">
     Block sites from running Flash
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_DETECT_IMPORTANT_RECOMMENDED" desc="The 'detect and run important content' label in site settings (with the 'recommended' suffix).">
+    Run only important content (recommended)
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_DETECT_IMPORTANT" desc="The 'detect and run important content' label in site settings.">
     Run only important content
   </message>
-  <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_DETECT_IMPORTANT_SUBTITLE" desc="The 'detect and run important content' subtitle label in site settings.">
-    Detect and run only important Flash content (recommended)
-  </message>
-  <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_ASK_BEFORE_RUNNING" desc="The 'ask before running' label for Flash in site settings.">
-    Ask first
-  </message>
-  <message name="IDS_SETTINGS_SITE_SETTINGS_FLASH_ASK_BEFORE_RUNNING_SUBTITLE" desc="The 'ask before running' subtitle label for Flash in site settings.">
-    Ask before allowing sites to run Flash (recommended)
-  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_ALLOW_RECENTLY_CLOSED_SITES" desc="The allow label for background sync in site settings.">
     Allow recently closed sites to finish sending and receiving data
   </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 051a5bb8..431d650 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2583,6 +2583,9 @@
      flag_descriptions::kTabDetachingInFullscreenDescription, kOsMac,
      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableFullscreenTabDetaching,
                                switches::kDisableFullscreenTabDetaching)},
+    {"enable-content-fullscreen", flag_descriptions::kContentFullscreenName,
+     flag_descriptions::kContentFullscreenDescription, kOsMac,
+     FEATURE_VALUE_TYPE(features::kContentFullscreen)},
     {"enable-fullscreen-toolbar-reveal",
      flag_descriptions::kFullscreenToolbarRevealName,
      flag_descriptions::kFullscreenToolbarRevealDescription, kOsMac,
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index 5680fa3d..af975e0 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -73,8 +73,8 @@
     Profile* profile)
     : profile_(profile),
       scheme_classifier_(profile),
-      search_terms_data_(profile_) {
-}
+      search_terms_data_(profile_),
+      storage_partition_(nullptr) {}
 
 ChromeAutocompleteProviderClient::~ChromeAutocompleteProviderClient() {
 }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 5fa138a..4a1059e 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -521,6 +521,8 @@
         <include name="IDR_PROXY_SETTINGS_HTML" file="resources\chromeos\proxy_settings.html" flattenhtml="true" type="BINDATA" />
         <include name="IDR_CERT_MANAGER_DIALOG_HTML" file="resources\chromeos\certificate_manager_dialog.html" flattenhtml="true" type="BINDATA" />
         <include name="IDR_BLUETOOTH_PAIR_DEVICE_HTML" file="resources\chromeos\bluetooth_pair_device.html" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_BLUETOOTH_DIALOG_HOST_HTML" file="resources\chromeos\bluetooth_dialog_host.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
+        <include name="IDR_BLUETOOTH_DIALOG_HOST_JS" file="resources\chromeos\bluetooth_dialog_host.js" type="chrome_html" />
         <include name="IDR_SIM_UNLOCK_HTML" file="resources\chromeos\sim_unlock.html" flattenhtml="true" type="BINDATA" />
         <include name="IDR_SLOW_HTML" file="resources\chromeos\slow.html" flattenhtml="true" type="BINDATA" />
         <include name="IDR_SLOW_JS" file="resources\chromeos\slow.js" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_renderer_manifest_overlay.json b/chrome/browser/chrome_content_renderer_manifest_overlay.json
index 6ff17bc..bf7d77b 100644
--- a/chrome/browser/chrome_content_renderer_manifest_overlay.json
+++ b/chrome/browser/chrome_content_renderer_manifest_overlay.json
@@ -25,6 +25,7 @@
           "chrome::mojom::InsecureContentRenderer",
           "chrome::mojom::PhishingDetector",
           "chrome::mojom::ThumbnailCapturer",
+          "chrome::mojom::WebUITester",
           "contextual_search::mojom::OverlayPageNotifierService",
           "dom_distiller::mojom::DistillerPageNotifierService",
           "spellcheck::mojom::SpellCheckPanel"
diff --git a/chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.cc b/chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.cc
index 89c3880..e4f52ac 100644
--- a/chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.cc
+++ b/chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.cc
@@ -30,9 +30,9 @@
 
 namespace {
 
-// Default width/height ratio of screen size.
-const int kDefaultWidth = 480;
-const int kDefaultHeight = 280;
+// The width needs to match the width specified in cr_dialog.html :host.
+const int kDefaultWidth = 512;
+const int kDefaultHeight = 400;
 
 }  // namespace
 
@@ -51,8 +51,7 @@
   device_data_.SetBoolean("connected", connected);
 }
 
-BluetoothPairingDialog::~BluetoothPairingDialog() {
-}
+BluetoothPairingDialog::~BluetoothPairingDialog() {}
 
 void BluetoothPairingDialog::ShowInContainer(int container_id) {
   // Dialog must be in a modal window container.
@@ -103,8 +102,7 @@
 }
 
 void BluetoothPairingDialog::GetWebUIMessageHandlers(
-    std::vector<WebUIMessageHandler*>* handlers) const {
-}
+    std::vector<WebUIMessageHandler*>* handlers) const {}
 
 void BluetoothPairingDialog::GetDialogSize(gfx::Size* size) const {
   size->SetSize(kDefaultWidth, kDefaultHeight);
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index ba2c11e..a4aa225 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -107,6 +107,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/grit/chromium_strings.h"
 #include "chromeos/audio/audio_devices_pref_handler_impl.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/cert_loader.h"
@@ -169,10 +170,12 @@
 #include "ui/base/ime/chromeos/ime_keyboard.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/ime/chromeos/input_method_util.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/touch/touch_device.h"
 #include "ui/chromeos/events/event_rewriter_chromeos.h"
 #include "ui/chromeos/events/pref_names.h"
 #include "ui/events/event_utils.h"
+#include "ui/message_center/message_center.h"
 
 #if BUILDFLAG(ENABLE_RLZ)
 #include "components/rlz/rlz_tracker.h"
@@ -787,6 +790,11 @@
     VLOG(1) << "Relaunching browser for user: " << account_id.Serialize()
             << " with hash: " << user_id_hash;
   }
+
+  // Set product name ("Chrome OS" or "Chromium OS") to be used in context
+  // header of new-style notification.
+  message_center::MessageCenter::Get()->SetProductOSName(
+      l10n_util::GetStringUTF16(IDS_PRODUCT_OS_NAME));
 }
 
 class GuestLanguageSetCallbackData {
diff --git a/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc b/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc
index 00a53e86..53bc65ff 100644
--- a/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc
+++ b/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.cc
@@ -16,6 +16,8 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "ui/app_list/search/tokenized_string.h"
+#include "ui/app_list/search/tokenized_string_match.h"
 
 namespace api_launcher_search_provider =
     extensions::api::launcher_search_provider;
@@ -27,11 +29,7 @@
 
 Service::Service(Profile* profile,
                  extensions::ExtensionRegistry* extension_registry)
-    : profile_(profile),
-      extension_registry_(extension_registry),
-      provider_(nullptr),
-      query_id_(0),
-      is_query_running_(false) {
+    : profile_(profile), extension_registry_(extension_registry) {
   extension_registry_->AddObserver(this);
 }
 
@@ -48,6 +46,7 @@
                              const std::string& query,
                              const int max_result) {
   DCHECK(!is_query_running_);
+  query_ = query;
   is_query_running_ = true;
   provider_ = provider;
 
@@ -132,10 +131,21 @@
     const GURL icon_url =
         result.icon_url ? GURL(*result.icon_url.get()) : GURL();
 
+    // Calculate the relevance score by matching the query with the title.
+    // Results with a match score of 0 are discarded. This will also be used to
+    // set the title tags (highlighting which parts of the title matched the
+    // search query).
+    const base::string16 title = base::UTF8ToUTF16(result.title);
+    app_list::TokenizedString tokenized_title(title);
+    app_list::TokenizedStringMatch match;
+    app_list::TokenizedString tokenized_query(base::UTF8ToUTF16(query_));
+    if (!match.Calculate(tokenized_query, tokenized_title))
+      continue;
+
     auto search_result = base::MakeUnique<app_list::LauncherSearchResult>(
         result.item_id, icon_url, relevance, profile_, extension,
         error_reporter->Duplicate());
-    search_result->set_title(base::UTF8ToUTF16(result.title));
+    search_result->UpdateFromMatch(tokenized_title, match);
     search_results.push_back(std::move(search_result));
   }
   provider_->SetSearchResults(extension->id(), std::move(search_results));
diff --git a/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.h b/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.h
index 7a648ac..88a1364 100644
--- a/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.h
+++ b/chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.h
@@ -78,9 +78,10 @@
 
   Profile* const profile_;
   extensions::ExtensionRegistry* extension_registry_;
-  app_list::LauncherSearchProvider* provider_;
-  int query_id_;
-  bool is_query_running_;
+  app_list::LauncherSearchProvider* provider_ = nullptr;
+  int query_id_ = 0;
+  bool is_query_running_ = false;
+  std::string query_;
   std::unique_ptr<std::set<extensions::ExtensionId>>
       cached_listener_extension_ids_;
 
diff --git a/chrome/browser/extensions/external_pref_loader.cc b/chrome/browser/extensions/external_pref_loader.cc
index 4d74878a..338434c5 100644
--- a/chrome/browser/extensions/external_pref_loader.cc
+++ b/chrome/browser/extensions/external_pref_loader.cc
@@ -18,6 +18,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/lazy_task_runner.h"
 #include "build/build_config.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
@@ -26,6 +27,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/browser/browser_thread.h"
+#include "extensions/browser/extension_file_task_runner.h"
 
 using content::BrowserThread;
 
@@ -36,7 +38,7 @@
 
 std::set<base::FilePath> GetPrefsCandidateFilesFromFolder(
       const base::FilePath& external_extension_search_path) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  base::ThreadRestrictions::AssertIOAllowed();
 
   std::set<base::FilePath> external_extension_paths;
 
@@ -144,9 +146,8 @@
       }
     }
   } else {
-    BrowserThread::PostTask(
-        BrowserThread::FILE, FROM_HERE,
-        base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
+    GetExtensionFileTaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
   }
 }
 
@@ -185,15 +186,14 @@
   DCHECK(service);
   service->RemoveObserver(this);
 
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
+  GetExtensionFileTaskRunner()->PostTask(
+      FROM_HERE, base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
 }
 
 void ExternalPrefLoader::LoadOnFileThread() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  base::ThreadRestrictions::AssertIOAllowed();
 
-  std::unique_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
+  auto prefs = base::MakeUnique<base::DictionaryValue>();
 
   // TODO(skerner): Some values of base_path_id_ will cause
   // PathService::Get() to return false, because the path does
@@ -233,7 +233,7 @@
 
 void ExternalPrefLoader::ReadExternalExtensionPrefFile(
     base::DictionaryValue* prefs) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  base::ThreadRestrictions::AssertIOAllowed();
   CHECK(NULL != prefs);
 
   base::FilePath json_file = base_path_.Append(kExternalExtensionJson);
@@ -271,7 +271,7 @@
 
 void ExternalPrefLoader::ReadStandaloneExtensionPrefFiles(
     base::DictionaryValue* prefs) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  base::ThreadRestrictions::AssertIOAllowed();
   CHECK(NULL != prefs);
 
   // First list the potential .json candidates.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f6079926..035a2c0 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2086,6 +2086,12 @@
     "Reveal the toolbar in fullscreen for a short period when the tab strip "
     "has changed.";
 
+const char kContentFullscreenName[] = "Improved Content Fullscreen";
+
+const char kContentFullscreenDescription[] =
+    "Fullscreen content window detaches from main browser window and goes to "
+    "a new space without moving or changing the original browser window.";
+
 const char kTabStripKeyboardFocusName[] = "Tab Strip Keyboard Focus";
 
 const char kTabStripKeyboardFocusDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 18b6e7c..41398f9 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1224,6 +1224,9 @@
 extern const char kFullscreenToolbarRevealName[];
 extern const char kFullscreenToolbarRevealDescription[];
 
+extern const char kContentFullscreenName[];
+extern const char kContentFullscreenDescription[];
+
 extern const char kHostedAppsInWindowsName[];
 extern const char kHostedAppsInWindowsDescription[];
 
diff --git a/chrome/browser/resources/chromeos/bluetooth_dialog_host.html b/chrome/browser/resources/chromeos/bluetooth_dialog_host.html
new file mode 100644
index 0000000..b5c2f31
--- /dev/null
+++ b/chrome/browser/resources/chromeos/bluetooth_dialog_host.html
@@ -0,0 +1,21 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/chromeos/bluetooth_dialog.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+
+<dom-module id="bluetooth-dialog-host">
+  <template>
+    <style>
+      :host {
+        overflow: hidden;
+      }
+    </style>
+
+    <bluetooth-dialog id="deviceDialog"
+        title="[[i18n('bluetoothPairDevicePageTitle')]]"
+        on-close="onDialogClose_"
+        pairing-device="[[pairingDevice_]]">
+    </bluetooth-dialog>
+  </template>
+  <script src="bluetooth_dialog_host.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/bluetooth_dialog_host.js b/chrome/browser/resources/chromeos/bluetooth_dialog_host.js
new file mode 100644
index 0000000..15f208f6
--- /dev/null
+++ b/chrome/browser/resources/chromeos/bluetooth_dialog_host.js
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'bluetooth-dialog-host' is used to host a <bluetooth-dialog> element to
+ * manage bluetooth pairing. The device properties are provided in the
+ * chrome 'dialogArguments' variable. When created (attached) the dialog
+ * connects to the specified device and passes the results to the
+ * bluetooth-dialog element to display.
+ */
+
+Polymer({
+  is: 'bluetooth-dialog-host',
+
+  behaviors: [I18nBehavior],
+
+  properties: {
+    /**
+     * Current Pairing device.
+     * @type {!chrome.bluetooth.Device|undefined}
+     * @private
+     */
+    pairingDevice_: Object,
+  },
+
+  /** @override */
+  attached: function() {
+    var dialogArgs = chrome.getVariableValue('dialogArguments');
+    this.pairingDevice_ =
+        /** @type {!chrome.bluetooth.Device} */ (
+            dialogArgs ? JSON.parse(dialogArgs) : {});
+    this.connect_();
+  },
+
+  /** @private */
+  connect_: function() {
+    this.$.deviceDialog.open();
+    var device = this.pairingDevice_;
+    chrome.bluetoothPrivate.connect(device.address, result => {
+      var dialog = this.$.deviceDialog;
+      dialog.handleError(device, chrome.runtime.lastError, result);
+    });
+  },
+
+  /** @private */
+  onDialogClose_: function() {
+    chrome.send('dialogClose');
+  },
+});
diff --git a/chrome/browser/resources/chromeos/bluetooth_options.js b/chrome/browser/resources/chromeos/bluetooth_options.js
deleted file mode 100644
index 556f544..0000000
--- a/chrome/browser/resources/chromeos/bluetooth_options.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('options', function() {
-  /** @const */ var Page = cr.ui.pageManager.Page;
-
-  /**
-   * Encapsulated handling of the BluetoothOptions calls from
-   * BluetoothOptionsHandler that is registered by the webUI,
-   * ie, BluetoothPairingUI.
-   * @constructor
-   */
-  function BluetoothOptions() {
-    Page.call(this, 'bluetooth', '', 'bluetooth-container');
-  }
-
-  cr.addSingletonGetter(BluetoothOptions);
-
-  BluetoothOptions.prototype = {
-    __proto__: Page.prototype,
-  };
-
-  BluetoothOptions.updateDiscovery = function() {};
-
-  // Export
-  return {BluetoothOptions: BluetoothOptions};
-});
diff --git a/chrome/browser/resources/chromeos/bluetooth_pair_device.css b/chrome/browser/resources/chromeos/bluetooth_pair_device.css
deleted file mode 100644
index 924add0..0000000
--- a/chrome/browser/resources/chromeos/bluetooth_pair_device.css
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-#bluetooth-pairing {
-  border: 0;
-  box-shadow: none;
-}
-
-.overlay {
-  padding: 0;
-}
diff --git a/chrome/browser/resources/chromeos/bluetooth_pair_device.html b/chrome/browser/resources/chromeos/bluetooth_pair_device.html
index 52bfc17d..d977202 100644
--- a/chrome/browser/resources/chromeos/bluetooth_pair_device.html
+++ b/chrome/browser/resources/chromeos/bluetooth_pair_device.html
@@ -1,44 +1,18 @@
 <!doctype html>
 <html i18n-values="dir:textdirection;lang:language">
+
 <head>
-<meta charset="utf-8">
-<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
-<link rel="stylesheet" href="chrome://resources/css/overlay.css">
+  <meta charset="utf-8">
+  <link rel="import" href="chrome://bluetooth-pairing/bluetooth_dialog_host.html">
 
-<link rel="stylesheet" href="../options/options_page.css">
-<link rel="stylesheet" href="../options/chromeos/bluetooth.css">
-<link rel="stylesheet" href="bluetooth_pair_device.css">
-
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/event_tracker.js"></script>
-<script src="chrome://resources/js/cr/event_target.js"></script>
-<script src="chrome://resources/js/cr/ui.js"></script>
-<script src="chrome://resources/js/cr/ui/array_data_model.js"></script>
-<script src="chrome://resources/js/cr/ui/focus_manager.js"></script>
-<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
-<script src="chrome://resources/js/cr/ui/touch_handler.js"></script>
-<script src="chrome://resources/js/load_time_data.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script src="chrome://resources/js/cr/ui/page_manager/page_manager.js"></script>
-<script src="chrome://resources/js/cr/ui/page_manager/page.js"></script>
-<script src="chrome://bluetooth-pairing/strings.js"></script>
-
-<script src="../options/options_page.js"></script>
-<script src="../options/chromeos/bluetooth_pair_device_overlay.js"></script>
-
-<script src="bluetooth_options.js"></script>
-<script src="browser_options.js"></script>
-<script src="bluetooth_pair_device.js"></script>
+  <script src="chrome://resources/js/cr.js"></script>
+  <script src="chrome://resources/js/load_time_data.js"></script>
+  <script src="chrome://resources/js/util.js"></script>
+  <script src="chrome://bluetooth-pairing/strings.js"></script>
 </head>
 
 <body>
-<div id="overlay-container" class="overlay">
-  <include src="../options/chromeos/bluetooth_pair_device_overlay.html">
-</div>
-<div id="page-container">
-  <div id="bluetooth-container"></div>
-</div>
-<div id="searchBox" hidden><input id="search-field" type=text></div>
-<script src="chrome://resources/js/i18n_template.js"></script>
+  <bluetooth-dialog-host></bluetooth-dialog-host>
 </body>
+
 </html>
diff --git a/chrome/browser/resources/chromeos/bluetooth_pair_device.js b/chrome/browser/resources/chromeos/bluetooth_pair_device.js
deleted file mode 100644
index 9c9eaf7..0000000
--- a/chrome/browser/resources/chromeos/bluetooth_pair_device.js
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(dbeam): should these be global like this?
-var Page = cr.ui.pageManager.Page;
-var PageManager = cr.ui.pageManager.PageManager;
-var BluetoothPairing = options.BluetoothPairing;
-
-/** @override */
-PageManager.closeOverlay = function() {
-  chrome.send('dialogClose');
-};
-
-/**
- * Listener for the |beforeunload| event.
- * TODO(dbeam): probably ought to be using addEventListener() instead.
- */
-window.onbeforeunload = function() {
-  PageManager.willClose();
-};
-
-/**
- * Override calls from BluetoothOptionsHandler.
- */
-cr.define('options', function() {
-  function BluetoothOptions() {}
-
-  BluetoothOptions.startDeviceDiscovery = function() {};
-  BluetoothOptions.updateDiscoveryState = function() {};
-  BluetoothOptions.dismissOverlay = function() {
-    PageManager.closeOverlay();
-  };
-
-  return {BluetoothOptions: BluetoothOptions};
-});
-
-/**
- * DOMContentLoaded handler, sets up the page.
- */
-function load() {
-  if (cr.isChromeOS)
-    document.documentElement.setAttribute('os', 'chromeos');
-
-  // Decorate the existing elements in the document.
-  cr.ui.decorate('input[pref][type=checkbox]', options.PrefCheckbox);
-  cr.ui.decorate('input[pref][type=number]', options.PrefNumber);
-  cr.ui.decorate('input[pref][type=radio]', options.PrefRadio);
-  cr.ui.decorate('input[pref][type=range]', options.PrefRange);
-  cr.ui.decorate('select[pref]', options.PrefSelect);
-  cr.ui.decorate('input[pref][type=text]', options.PrefTextField);
-  cr.ui.decorate('input[pref][type=url]', options.PrefTextField);
-
-  // TODO(ivankr): remove when http://crosbug.com/20660 is resolved.
-  var inputs = document.querySelectorAll('input[pref]');
-  for (var i = 0, el; el = inputs[i]; i++) {
-    el.addEventListener('keyup', function(e) {
-      cr.dispatchSimpleEvent(this, 'change');
-    });
-  }
-
-  chrome.send('coreOptionsInitialize');
-
-  var pairingPage = new Page('bluetooth', '', 'bluetooth-container');
-  PageManager.register(pairingPage);
-  PageManager.registerOverlay(BluetoothPairing.getInstance(), pairingPage);
-
-  // Since this UI is used to host a BluetoothPairing dialog we need to add
-  // an onPairing observer. (Normally that would be added in browser_options).
-  chrome.bluetoothPrivate.onPairing.addListener(
-      BluetoothPairing.onBluetoothPairingEvent);
-
-  // Show the BluetoothPairing dialog.
-  var args = JSON.parse(chrome.getVariableValue('dialogArguments'));
-  var device = /** @type {!chrome.bluetooth.Device} */ (args);
-  BluetoothPairing.connect(device, true);
-}
-
-document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
index 0c9805a..531ef49 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -634,7 +634,14 @@
   brailleRoutingCommand_: function(text, position) {
     var actionNodeSpan = null;
     var selectionSpan = null;
-    text.getSpans(position).forEach(function(span) {
+
+    // For a routing key press one cell beyond the last displayed character, use
+    // the node span for the last character. This enables routing selection to
+    // the length of the text, which is valid.
+    var nodePosition = position;
+    if (position == text.length && position > 0)
+      nodePosition--;
+    text.getSpans(nodePosition).forEach(function(span) {
       if (span instanceof Output.SelectionSpan) {
         selectionSpan = span;
       } else if (span instanceof Output.NodeSpan) {
diff --git a/chrome/browser/resources/chromeos/compiled_resources2.gyp b/chrome/browser/resources/chromeos/compiled_resources2.gyp
index c00877f..246baf98 100644
--- a/chrome/browser/resources/chromeos/compiled_resources2.gyp
+++ b/chrome/browser/resources/chromeos/compiled_resources2.gyp
@@ -4,98 +4,15 @@
 {
   'targets': [
     {
-      'target_name': 'bluetooth_pair_device',
-      'variables': {
-        'extra_inputs': [
-          '<!@(python <(CLOSURE_DIR)/build/get_includes.py ../options/options_bundle.js)',
-        ],
-        'script_args': ['--custom_sources', '--custom_includes'],
-        'source_files': [
-          '<(DEPTH)/third_party/jstemplate/util.js',
-          '<(DEPTH)/third_party/jstemplate/jsevalcontext.js',
-          '<(DEPTH)/third_party/jstemplate/jstemplate.js',
-          '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js',
-          '<(DEPTH)/ui/webui/resources/js/action_link.js',
-          '<(DEPTH)/ui/webui/resources/js/cr.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/event_target.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/array_data_model.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/autocomplete_list.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/bubble.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/bubble_button.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/command.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/controlled_indicator.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/focus_manager.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/focus_without_ink.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/list.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/list_item.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/list_selection_controller.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/list_selection_model.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/grid.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/menu.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/menu_item.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/overlay.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/position_util.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/node_utils.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/page_manager/page.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/page_manager/page_manager.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/repeating_button.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/touch_handler.js',
-          '<(DEPTH)/ui/webui/resources/js/cr/ui/tree.js',
-          '<(DEPTH)/ui/webui/resources/js/event_tracker.js',
-          '<(DEPTH)/ui/webui/resources/js/icon.js',
-          '<(DEPTH)/ui/webui/resources/js/load_time_data.js',
-          '<(DEPTH)/ui/webui/resources/js/parse_html_subset.js',
-          '<(DEPTH)/ui/webui/resources/js/promise_resolver.js',
-          '<(DEPTH)/ui/webui/resources/js/util.js',
-          '../chromeos/keyboard/keyboard_utils.js',
-          '<(DEPTH)/ui/webui/resources/js/i18n_behavior.js',
-          '<(DEPTH)/ui/webui/resources/js/web_ui_listener_behavior.js',
-          '../settings/page_visibility.js',
-          '../settings/route.js',
-          '../settings/people_page/easy_unlock_browser_proxy.js',
-          '../settings/people_page/fingerprint_browser_proxy.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/iron-selection-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/iron-selectable-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/iron-multi-selectable-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/iron-menu-behavior-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/iron-menubar-behavior-extracted.js',
-          '<(DEPTH)/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.js',
-          '<(DEPTH)/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js',
-          '../settings/people_page/lock_screen_constants.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/quick_unlock_private.js',
-          '../settings/people_page/lock_state_behavior.js',
-          '../settings/people_page/password_prompt_dialog.js',
-          '<(DEPTH)/ui/webui/resources/js/assert.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-meta/iron-meta-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-inky-focus-behavior-extracted.js',
-          '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button-extracted.js',
-          '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js',
-          '../settings/people_page/lock_screen.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/bluetooth.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/bluetooth_private.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/management.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/metrics_private.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/networking_private.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/chrome_send.js',
-          '<(DEPTH)/third_party/closure_compiler/externs/web_animations.js',
-          '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon_externs.js',
-          '../options/options_bundle.js',
-          # Note: ^ this is just a copy of
-          # ../options/compiled_resources2.gyp:options_bundle#source_files. Most
-          # of this code is deprecated, but please keep in sync if you really
-          # need to change.
-          'bluetooth_pair_device.js',
-        ],
-      },
+      'target_name': 'bluetooth_dialog_host',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+        '<(EXTERNS_GYP):bluetooth',
+        '<(EXTERNS_GYP):bluetooth_private',
+        '<(INTERFACES_GYP):bluetooth_interface',
+        '<(INTERFACES_GYP):bluetooth_private_interface',
+      ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
diff --git a/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.js b/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.js
index 369d5bc8..e19832f9 100644
--- a/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.js
+++ b/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.js
@@ -187,7 +187,7 @@
     this.addClass_('value-prop-loaded');
 
     this.valuePropButtonsDisabled = false;
-    this.$['continue-button'].focus();
+    this.$['next-button'].focus();
   },
 
   /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html
index f4828c2..396a03f5 100644
--- a/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html
+++ b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html
@@ -9,7 +9,8 @@
     <link rel="stylesheet" href="oobe_wait_for_container_ready.css">
     <oobe-dialog id="waitForContainerReadyDialog" role="dialog" hide-shadow
         no-footer android>
-      <iron-icon src="https://www.gstatic.com/opa-chromeos/oobe/images/assistant_logo.png" class="oobe-icon">
+      <iron-icon src="https://www.gstatic.com/opa-chromeos/oobe/images/assistant_logo.png"
+        i18n-values="aria-label:voiceInteractionLogo" class="oobe-icon">
       </iron-icon>
       <div class="header">
         <div class="title" i18n-content="waitForContainerReadyTitle"></div>
diff --git a/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html b/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html
index 7150197..6844a00 100644
--- a/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html
+++ b/chrome/browser/resources/pdf/elements/viewer-error-screen/viewer-error-screen.html
@@ -13,8 +13,7 @@
       <div slot="body">
         [[strings.pageLoadFailed]]
       </div>
-      <div slot="button-container">
-          hidden$="[[!reloadFn]]">
+      <div slot="button-container" hidden$="[[!reloadFn]]">
         <paper-button class="action-button" on-click="reload">
           [[strings.pageReload]]
         </paper-button>
diff --git a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
index fec7261..75c2295 100644
--- a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
+++ b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
@@ -1,8 +1,12 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="google_assistant_browser_proxy.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="../prefs/prefs.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -28,7 +32,7 @@
             on-change="onGoogleAssistantContextEnableChange_">
         </settings-toggle-button>
       </div>
-      <div class="settings-box"
+      <div id="googleAssistantSettings" class="settings-box"
           on-tap="onGoogleAssistantSettingsTapped_" actionable>
         <div class="start">
           $i18n{googleAssistantSettings}
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy.html b/chrome/browser/resources/settings/internet_page/network_proxy.html
index 1db0df7..34427b8 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy.html
+++ b/chrome/browser/resources/settings/internet_page/network_proxy.html
@@ -21,7 +21,7 @@
 <link rel="import" href="../prefs/prefs_behavior.html">
 <link rel="import" href="../settings_vars_css.html">
 <link rel="import" href="internet_shared_css.html">
-link rel="import" href="network_proxy_exclusions.html">
+<link rel="import" href="network_proxy_exclusions.html">
 <link rel="import" href="network_proxy_input.html">
 
 <dom-module id="network-proxy">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 1f816bc..871bd0d 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -376,9 +376,7 @@
         <settings-subpage page-title="$i18n{siteSettingsFlash}">
           <category-default-setting category="{{ContentSettingsTypes.PLUGINS}}"
               toggle-off-label="$i18n{siteSettingsFlashBlock}"
-              toggle-on-label="$i18n{siteSettingsFlashAllow}"
-              sub-option-label="$i18n{siteSettingsFlashAskBefore}"
-              sub-option-secondary="$i18n{siteSettingsFlashAskBeforeSubtitle}">
+              toggle-on-label="$i18n{siteSettingsFlashAskFirstRecommended}">
           </category-default-setting>
 <if expr="chromeos">
           <a class="settings-box inherit-color no-outline" tabindex="-1"
diff --git a/chrome/browser/resources/settings/site_settings/category_default_setting.js b/chrome/browser/resources/settings/site_settings/category_default_setting.js
index c5e6b6b..48b1ca7 100644
--- a/chrome/browser/resources/settings/site_settings/category_default_setting.js
+++ b/chrome/browser/resources/settings/site_settings/category_default_setting.js
@@ -124,14 +124,11 @@
         this.browserProxy.setDefaultValueForContentType(this.category, value);
         break;
       case settings.ContentSettingsTypes.PLUGINS:
-        // This category is tri-state: "Allow", "Block", "Ask before running".
-        var value = settings.ContentSetting.BLOCK;
-        if (this.categoryEnabled) {
-          value = this.subControlParams_.value ?
-              settings.ContentSetting.IMPORTANT_CONTENT :
-              settings.ContentSetting.ALLOW;
-        }
-        this.browserProxy.setDefaultValueForContentType(this.category, value);
+        // "Run important content" vs. "Block".
+        this.browserProxy.setDefaultValueForContentType(
+            this.category,
+            this.categoryEnabled ? settings.ContentSetting.IMPORTANT_CONTENT :
+                                   settings.ContentSetting.BLOCK);
         break;
       default:
         assertNotReached('Invalid category: ' + this.category);
@@ -170,18 +167,8 @@
     this.controlParams_ = /** @type {chrome.settingsPrivate.PrefObject} */ (
         Object.assign({'value': prefValue}, basePref));
 
-    var subPrefValue = false;
-    if (this.category == settings.ContentSettingsTypes.PLUGINS ||
-        this.category == settings.ContentSettingsTypes.COOKIES) {
-      if (this.category == settings.ContentSettingsTypes.PLUGINS &&
-          update.setting == settings.ContentSetting.IMPORTANT_CONTENT) {
-        subPrefValue = true;
-      } else if (
-          this.category == settings.ContentSettingsTypes.COOKIES &&
-          update.setting == settings.ContentSetting.SESSION_ONLY) {
-        subPrefValue = true;
-      }
-    }
+    var subPrefValue = this.category == settings.ContentSettingsTypes.COOKIES &&
+        update.setting == settings.ContentSetting.SESSION_ONLY;
     // The subControlParams_ must be replaced (rather than just value changes)
     // so that observers will be notified of the change.
     this.subControlParams_ = /** @type {chrome.settingsPrivate.PrefObject} */ (
@@ -197,17 +184,8 @@
         .then(defaultValue => {
           this.updateControlParams_(defaultValue);
 
-          // Flash only shows ALLOW or BLOCK descriptions on the toggle.
-          var setting = defaultValue.setting;
-          if (this.category == settings.ContentSettingsTypes.PLUGINS &&
-              setting == settings.ContentSetting.IMPORTANT_CONTENT) {
-            setting = settings.ContentSetting.ALLOW;
-          } else if (
-              this.category == settings.ContentSettingsTypes.COOKIES &&
-              setting == settings.ContentSetting.SESSION_ONLY) {
-            setting = settings.ContentSetting.ALLOW;
-          }
-          var categoryEnabled = setting != settings.ContentSetting.BLOCK;
+          var categoryEnabled =
+              this.computeIsSettingEnabled(defaultValue.setting);
           this.optionLabel_ =
               categoryEnabled ? this.toggleOnLabel : this.toggleOffLabel;
         });
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
index 50ef70e..5b638ea 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -143,9 +143,8 @@
         <div class="secondary" id="flashSecondary">
           [[defaultSettingLabel_(
               default_.plugins,
-              '$i18nPolymer{siteSettingsFlashAllow}',
-              '$i18nPolymer{siteSettingsFlashBlock}',
-              '$i18nPolymer{siteSettingsFlashAskBefore}')]]
+              '$i18nPolymer{siteSettingsFlashAskFirst}',
+              '$i18nPolymer{siteSettingsFlashBlock}')]]
         </div>
       </div>
       <button class="subpage-arrow" is="paper-icon-button-light"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 408313a..fc6562fb 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -215,7 +215,9 @@
     "webui/chrome_web_ui_controller_factory.cc",
     "webui/chrome_web_ui_controller_factory.h",
 
-    # TODO(dbeam): why are all these /chromeos/ files on all platforms?
+    # Chrome OS specific files (filtered out by GN on non chromeos platforms)
+    "webui/chromeos/bluetooth_dialog_localized_strings_provider.cc",
+    "webui/chromeos/bluetooth_dialog_localized_strings_provider.h",
     "webui/chromeos/choose_mobile_network_ui.cc",
     "webui/chromeos/choose_mobile_network_ui.h",
     "webui/chromeos/cryptohome_ui.cc",
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_contents.h b/chrome/browser/ui/app_list/search/answer_card/answer_card_contents.h
index 87ec12a..2e855a54 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_contents.h
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_contents.h
@@ -13,12 +13,6 @@
 class AnswerCardResult;
 }
 
-namespace content {
-class NavigationHandle;
-struct OpenURLParams;
-class WebContents;
-}
-
 namespace gfx {
 class Size;
 }
@@ -41,10 +35,11 @@
     // events in WebContentsDelegate and WebContentsObserver, however,
     // unnecessary parameters are omitted.
     virtual void UpdatePreferredSize(const gfx::Size& pref_size) = 0;
-    virtual content::WebContents* OpenURLFromTab(
-        const content::OpenURLParams& params) = 0;
-    virtual void DidFinishNavigation(
-        content::NavigationHandle* navigation_handle) = 0;
+    virtual void DidFinishNavigation(const GURL& url,
+                                     bool has_error,
+                                     bool has_answer_card,
+                                     const std::string& result_title,
+                                     const std::string& issued_query) = 0;
     virtual void DidStopLoading() = 0;
 
    private:
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
index c2c29ec..ede9eea 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
@@ -17,10 +17,6 @@
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/search_engines/template_url_service.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/page_navigator.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_status_code.h"
 #include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_model.h"
 #include "ui/app_list/search_box_model.h"
@@ -38,10 +34,6 @@
   REQUEST_RESULT_MAX = 5
 };
 
-constexpr char kSearchAnswerHasResult[] = "SearchAnswer-HasResult";
-constexpr char kSearchAnswerIssuedQuery[] = "SearchAnswer-IssuedQuery";
-constexpr char kSearchAnswerTitle[] = "SearchAnswer-Title";
-
 void RecordRequestResult(SearchAnswerRequestResult request_result) {
   UMA_HISTOGRAM_ENUMERATION("SearchAnswer.RequestResult", request_result,
                             SearchAnswerRequestResult::REQUEST_RESULT_MAX);
@@ -116,33 +108,13 @@
   }
 }
 
-content::WebContents* AnswerCardSearchProvider::OpenURLFromTab(
-    const content::OpenURLParams& params) {
-  // Open the user-clicked link in the browser taking into account the requested
-  // disposition.
-  chrome::NavigateParams new_tab_params(profile_, params.url,
-                                        params.transition);
-
-  new_tab_params.disposition = params.disposition;
-
-  if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
-    // When the user asks to open a link as a background tab, we show an
-    // activated window with the new activated tab after the user closes the
-    // launcher. So it's "background" relative to the launcher itself.
-    new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
-    new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW_INACTIVE;
-  }
-
-  chrome::Navigate(&new_tab_params);
-
-  base::RecordAction(base::UserMetricsAction("SearchAnswer_OpenedUrl"));
-
-  return new_tab_params.target_contents;
-}
-
 void AnswerCardSearchProvider::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (navigation_handle->GetURL() != current_request_url_) {
+    const GURL& url,
+    bool has_error,
+    bool has_answer_card,
+    const std::string& result_title,
+    const std::string& issued_query) {
+  if (url != current_request_url_) {
     // TODO(vadimt): Remove this and similar logging once testing is complete if
     // we think this is not useful after release or happens too frequently.
     VLOG(1) << "DidFinishNavigation: Another request started";
@@ -152,29 +124,27 @@
   }
 
   VLOG(1) << "DidFinishNavigation: Latest request completed";
-  if (!navigation_handle->HasCommitted() || navigation_handle->IsErrorPage() ||
-      !navigation_handle->IsInMainFrame()) {
-    LOG(ERROR) << "Failed to navigate: HasCommitted="
-               << navigation_handle->HasCommitted()
-               << ", IsErrorPage=" << navigation_handle->IsErrorPage()
-               << ", IsInMainFrame=" << navigation_handle->IsInMainFrame();
+  if (has_error) {
     RecordRequestResult(
         SearchAnswerRequestResult::REQUEST_RESULT_REQUEST_FAILED);
     return;
   }
 
   if (!features::IsAnswerCardDarkRunEnabled()) {
-    if (!ParseResponseHeaders(navigation_handle->GetResponseHeaders())) {
+    if (!has_answer_card || result_title.empty()) {
       RecordRequestResult(SearchAnswerRequestResult::REQUEST_RESULT_NO_ANSWER);
       return;
     }
+    result_title_ = result_title;
+    if (!issued_query.empty())
+      result_url_ = GetResultUrl(base::UTF8ToUTF16(issued_query));
   } else {
     // In the dark run mode, every other "server response" contains a card.
     dark_run_received_answer_ = !dark_run_received_answer_;
     if (!dark_run_received_answer_)
       return;
     // SearchResult requires a non-empty id. This "url" will never be opened.
-    result_url_ = "some string";
+    result_url_ = "https://www.google.com/?q=something";
   }
 
   received_answer_ = true;
@@ -238,44 +208,6 @@
   SwapResults(&results);
 }
 
-bool AnswerCardSearchProvider::ParseResponseHeaders(
-    const net::HttpResponseHeaders* headers) {
-  if (!headers) {
-    LOG(ERROR) << "Failed to parse response headers: no headers";
-    return false;
-  }
-  if (headers->response_code() != net::HTTP_OK) {
-    LOG(ERROR) << "Failed to parse response headers: response code="
-               << headers->response_code();
-    return false;
-  }
-  if (!headers->HasHeaderValue(kSearchAnswerHasResult, "true")) {
-    LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerHasResult
-               << " header != true";
-    return false;
-  }
-  if (!headers->GetNormalizedHeader(kSearchAnswerTitle, &result_title_)) {
-    LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerTitle
-               << " header is not present";
-    return false;
-  }
-
-  std::string issued_query;
-  // TODO(749320): Make the header mandatory once the production server starts
-  // serving it.
-  if (headers->GetNormalizedHeader(kSearchAnswerIssuedQuery, &issued_query)) {
-    // The header contains the autocompleted query that corresponds to the card
-    // contents. Use it for the open-URL, and for deduplication with the omnibox
-    // search results.
-    result_url_ = GetResultUrl(base::UTF8ToUTF16(issued_query));
-  } else {
-    VLOG(1) << "Warning: " << kSearchAnswerIssuedQuery
-            << " header is not present";
-  }
-
-  return true;
-}
-
 std::string AnswerCardSearchProvider::GetResultUrl(
     const base::string16& query) const {
   return template_url_service_->GetDefaultSearchProvider()
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h
index dc776a6..75b538e9 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h
@@ -22,10 +22,6 @@
 class AppListModel;
 }
 
-namespace net {
-class HttpResponseHeaders;
-}
-
 namespace app_list {
 
 // Search provider for the answer card.
@@ -45,17 +41,17 @@
 
   // AnswerCardContents::Delegate overrides:
   void UpdatePreferredSize(const gfx::Size& pref_size) override;
-  content::WebContents* OpenURLFromTab(
-      const content::OpenURLParams& params) override;
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
+  void DidFinishNavigation(const GURL& url,
+                           bool has_error,
+                           bool has_answer_card,
+                           const std::string& result_title,
+                           const std::string& issued_query) override;
   void DidStopLoading() override;
 
  private:
   bool IsCardSizeOk() const;
   void RecordReceivedAnswerFinalResult();
   void OnResultAvailable(bool is_available);
-  bool ParseResponseHeaders(const net::HttpResponseHeaders* headers);
   // Returns Url to open when the user clicks at the result for |query|.
   std::string GetResultUrl(const base::string16& query) const;
 
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
new file mode 100644
index 0000000..001edf5
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
@@ -0,0 +1,291 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/app_list/app_list_test_util.h"
+#include "chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h"
+#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/search_engines/template_url_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/app_list/app_list_features.h"
+#include "ui/app_list/app_list_model.h"
+#include "ui/app_list/search_result.h"
+#include "ui/views/view.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::ReturnRef;
+
+namespace app_list {
+namespace test {
+
+namespace {
+
+constexpr char kCatCardId[] =
+    "https://www.google.com/search?q=cat&sourceid=chrome&ie=UTF-8";
+constexpr char kCatCardTitle[] = "Cat is a furry beast.";
+
+class MockAnswerCardContents : public AnswerCardContents {
+ public:
+  MockAnswerCardContents() {}
+
+  // AnswerCardContents overrides:
+  MOCK_METHOD1(LoadURL, void(const GURL& url));
+  MOCK_CONST_METHOD0(IsLoading, bool());
+  MOCK_METHOD0(GetView, views::View*());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockAnswerCardContents);
+};
+
+gfx::Size GetMaxValidCardSize() {
+  return gfx::Size(features::AnswerCardMaxWidth(),
+                   features::AnswerCardMaxHeight());
+}
+
+std::unique_ptr<KeyedService> CreateTemplateURLService(
+    content::BrowserContext* context) {
+  return base::MakeUnique<TemplateURLService>(nullptr, 0);
+}
+
+}  // namespace
+
+class AnswerCardSearchProviderTest : public AppListTestBase {
+ public:
+  AnswerCardSearchProviderTest() : field_trial_list_(nullptr) {}
+
+  void TestDidFinishNavigation(bool has_error,
+                               bool has_result,
+                               std::string title,
+                               std::size_t expected_result_count) {
+    EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+    provider()->Start(false, base::UTF8ToUTF16("cat"));
+
+    provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=cat"),
+                                    has_error, has_result, title, "");
+
+    provider()->DidStopLoading();
+    provider()->UpdatePreferredSize(GetMaxValidCardSize());
+
+    EXPECT_EQ(expected_result_count, results().size());
+
+    testing::Mock::VerifyAndClearExpectations(contents());
+  }
+
+  AppListModel* model() const { return model_.get(); }
+
+  const SearchProvider::Results& results() { return provider()->results(); }
+
+  MockAnswerCardContents* contents() const { return contents_; }
+
+  AnswerCardSearchProvider* provider() const { return provider_.get(); }
+
+  views::View* view() { return &view_; }
+
+  // AppListTestBase overrides:
+  void SetUp() override {
+    AppListTestBase::SetUp();
+
+    model_ = base::MakeUnique<app_list::AppListModel>();
+    model_->SetSearchEngineIsGoogle(true);
+
+    controller_ = base::MakeUnique<::test::TestAppListControllerDelegate>();
+
+    // Set up card server URL.
+    std::map<std::string, std::string> params;
+    params["ServerUrl"] = "http://beasts.org/search";
+    base::AssociateFieldTrialParams("TestTrial", "TestGroup", params);
+    scoped_refptr<base::FieldTrial> trial =
+        base::FieldTrialList::CreateFieldTrial("TestTrial", "TestGroup");
+    std::unique_ptr<base::FeatureList> feature_list =
+        base::MakeUnique<base::FeatureList>();
+    feature_list->RegisterFieldTrialOverride(
+        features::kEnableAnswerCard.name,
+        base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
+    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
+
+    contents_ = new MockAnswerCardContents;
+    std::unique_ptr<AnswerCardContents> contents(contents_);
+    TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
+        profile_.get(), CreateTemplateURLService);
+    // Provider will own the MockAnswerCardContents instance.
+    provider_ = base::MakeUnique<AnswerCardSearchProvider>(
+        profile_.get(), model_.get(), nullptr, std::move(contents));
+
+    ON_CALL(*contents_, GetView()).WillByDefault(Return(view()));
+  }
+
+ private:
+  std::unique_ptr<app_list::AppListModel> model_;
+  std::unique_ptr<AnswerCardSearchProvider> provider_;
+  std::unique_ptr<::test::TestAppListControllerDelegate> controller_;
+  MockAnswerCardContents* contents_ = nullptr;  // Unowned.
+  base::FieldTrialList field_trial_list_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+  views::View view_;
+
+  DISALLOW_COPY_AND_ASSIGN(AnswerCardSearchProviderTest);
+};
+
+// Basic event sequence.
+TEST_F(AnswerCardSearchProviderTest, Basic) {
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+  provider()->Start(false, base::UTF8ToUTF16("cat"));
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=cat"), false,
+                                  true, kCatCardTitle, "cat");
+  provider()->DidStopLoading();
+  provider()->UpdatePreferredSize(GetMaxValidCardSize());
+
+  EXPECT_EQ(1UL, results().size());
+  SearchResult* result = results()[0].get();
+  EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+  EXPECT_EQ(kCatCardId, result->id());
+  EXPECT_EQ(1, result->relevance());
+  EXPECT_EQ(view(), result->view());
+  EXPECT_EQ(base::UTF8ToUTF16(kCatCardTitle), result->title());
+}
+
+// Voice queries are ignored.
+TEST_F(AnswerCardSearchProviderTest, VoiceQuery) {
+  EXPECT_CALL(*contents(), LoadURL(_)).Times(0);
+  provider()->Start(true, base::UTF8ToUTF16("cat"));
+}
+
+// Queries to non-Google search engines are ignored.
+TEST_F(AnswerCardSearchProviderTest, NotGoogle) {
+  model()->SetSearchEngineIsGoogle(false);
+  EXPECT_CALL(*contents(), LoadURL(_)).Times(0);
+  provider()->Start(false, base::UTF8ToUTF16("cat"));
+}
+
+// Zero-query is ignored.
+TEST_F(AnswerCardSearchProviderTest, EmptyQuery) {
+  EXPECT_CALL(*contents(), LoadURL(_)).Times(0);
+  provider()->Start(false, base::UTF8ToUTF16(""));
+}
+
+// Two queries, the second produces a card of exactly same size, so
+// UpdatePreferredSize() doesn't come. The second query should still produce a
+// result.
+TEST_F(AnswerCardSearchProviderTest, TwoResultsSameSize) {
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+  provider()->Start(false, base::UTF8ToUTF16("cat"));
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=cat"), false,
+                                  true, kCatCardTitle, "cat");
+  provider()->DidStopLoading();
+  provider()->UpdatePreferredSize(GetMaxValidCardSize());
+
+  EXPECT_EQ(1UL, results().size());
+  SearchResult* result = results()[0].get();
+  EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+  EXPECT_EQ(kCatCardId, result->id());
+  EXPECT_EQ(1, result->relevance());
+  EXPECT_EQ(view(), result->view());
+  EXPECT_EQ(base::UTF8ToUTF16(kCatCardTitle), result->title());
+
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=dog")));
+  provider()->Start(false, base::UTF8ToUTF16("dog"));
+  EXPECT_EQ(0UL, results().size());
+
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=dog"), false,
+                                  true, "Dog is a friendly beast.", "dog");
+  provider()->DidStopLoading();
+  // No UpdatePreferredSize().
+
+  EXPECT_EQ(1UL, results().size());
+  result = results()[0].get();
+  EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+  EXPECT_EQ("https://www.google.com/search?q=dog&sourceid=chrome&ie=UTF-8",
+            result->id());
+  EXPECT_EQ(1, result->relevance());
+  EXPECT_EQ(view(), result->view());
+  EXPECT_EQ(base::UTF8ToUTF16("Dog is a friendly beast."), result->title());
+}
+
+// User enters a query character by character, so that each next query generates
+// a web request while the previous one is still in progress. Only the last
+// query should produce a result.
+TEST_F(AnswerCardSearchProviderTest, InterruptedRequest) {
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=c")));
+  provider()->Start(false, base::UTF8ToUTF16("c"));
+  EXPECT_EQ(0UL, results().size());
+
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=ca")));
+  provider()->Start(false, base::UTF8ToUTF16("ca"));
+  EXPECT_EQ(0UL, results().size());
+
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+  provider()->Start(false, base::UTF8ToUTF16("cat"));
+  EXPECT_EQ(0UL, results().size());
+
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=c"), false,
+                                  true, "Title c", "c");
+  provider()->DidStopLoading();
+  EXPECT_EQ(0UL, results().size());
+
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=ca"), false,
+                                  true, "Title ca", "ca");
+  provider()->DidStopLoading();
+  provider()->UpdatePreferredSize(gfx::Size(1, 1));
+  EXPECT_EQ(0UL, results().size());
+
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=cat"), false,
+                                  true, kCatCardTitle, "cat");
+  provider()->DidStopLoading();
+  provider()->UpdatePreferredSize(GetMaxValidCardSize());
+  EXPECT_EQ(1UL, results().size());
+
+  SearchResult* result = results()[0].get();
+  EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+  EXPECT_EQ(kCatCardId, result->id());
+  EXPECT_EQ(base::UTF8ToUTF16(kCatCardTitle), result->title());
+}
+
+// Due to, for example, JS activity in the card, it can change its size after
+// loading. We should hide the result while its size if larger than the allowed
+// maximum.
+TEST_F(AnswerCardSearchProviderTest, ChangingSize) {
+  EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+  provider()->Start(false, base::UTF8ToUTF16("cat"));
+  provider()->DidFinishNavigation(GURL("http://beasts.org/search?q=cat"), false,
+                                  true, kCatCardTitle, "cat");
+  provider()->UpdatePreferredSize(gfx::Size(features::AnswerCardMaxWidth() + 1,
+                                            features::AnswerCardMaxHeight()));
+  provider()->DidStopLoading();
+  EXPECT_EQ(0UL, results().size());
+
+  provider()->UpdatePreferredSize(GetMaxValidCardSize());
+  EXPECT_EQ(1UL, results().size());
+
+  provider()->UpdatePreferredSize(gfx::Size(
+      features::AnswerCardMaxWidth(), features::AnswerCardMaxHeight() + 1));
+  EXPECT_EQ(0UL, results().size());
+
+  provider()->UpdatePreferredSize(GetMaxValidCardSize());
+  EXPECT_EQ(1UL, results().size());
+}
+
+// Various values for DidFinishNavigation params.
+TEST_F(AnswerCardSearchProviderTest, DidFinishNavigation) {
+  TestDidFinishNavigation(false, true, kCatCardTitle, 1UL);
+  TestDidFinishNavigation(true, true, kCatCardTitle, 0UL);
+  TestDidFinishNavigation(false, false, kCatCardTitle, 0UL);
+  TestDidFinishNavigation(false, true, "", 0UL);
+}
+
+}  // namespace test
+}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
index 34631a1..7f9b1de 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
@@ -7,10 +7,15 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/page_navigator.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences.h"
+#include "net/http/http_status_code.h"
 #include "third_party/WebKit/public/platform/WebMouseEvent.h"
 #include "ui/views/controls/webview/web_contents_set_background_color.h"
 #include "ui/views/controls/webview/webview.h"
@@ -20,6 +25,10 @@
 
 namespace {
 
+constexpr char kSearchAnswerHasResult[] = "SearchAnswer-HasResult";
+constexpr char kSearchAnswerIssuedQuery[] = "SearchAnswer-IssuedQuery";
+constexpr char kSearchAnswerTitle[] = "SearchAnswer-Title";
+
 class SearchAnswerWebView : public views::WebView {
  public:
   explicit SearchAnswerWebView(content::BrowserContext* browser_context)
@@ -50,6 +59,38 @@
   DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebView);
 };
 
+void ParseResponseHeaders(const net::HttpResponseHeaders* headers,
+                          bool* has_answer_card,
+                          std::string* result_title,
+                          std::string* issued_query) {
+  if (!headers) {
+    LOG(ERROR) << "Failed to parse response headers: no headers";
+    return;
+  }
+  if (headers->response_code() != net::HTTP_OK) {
+    LOG(ERROR) << "Failed to parse response headers: response code="
+               << headers->response_code();
+    return;
+  }
+  if (!headers->HasHeaderValue(kSearchAnswerHasResult, "true")) {
+    LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerHasResult
+               << " header != true";
+    return;
+  }
+  if (!headers->GetNormalizedHeader(kSearchAnswerTitle, result_title)) {
+    LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerTitle
+               << " header is not present";
+    return;
+  }
+  if (!headers->GetNormalizedHeader(kSearchAnswerIssuedQuery, issued_query)) {
+    // TODO(749320): Make the header mandatory once the production server
+    // starts serving it.
+    VLOG(1) << "Warning: " << kSearchAnswerIssuedQuery
+            << " header is not present";
+  }
+  *has_answer_card = true;
+}
+
 }  // namespace
 
 AnswerCardWebContents::AnswerCardWebContents(Profile* profile)
@@ -59,7 +100,8 @@
               profile,
               content::SiteInstance::Create(profile)))),
       mouse_event_callback_(base::Bind(&AnswerCardWebContents::HandleMouseEvent,
-                                       base::Unretained(this))) {
+                                       base::Unretained(this))),
+      profile_(profile) {
   content::RendererPreferences* renderer_prefs =
       web_contents_->GetMutableRendererPrefs();
   renderer_prefs->can_accept_load_drops = false;
@@ -117,7 +159,26 @@
   if (!params.user_gesture)
     return WebContentsDelegate::OpenURLFromTab(source, params);
 
-  return delegate()->OpenURLFromTab(params);
+  // Open the user-clicked link in the browser taking into account the requested
+  // disposition.
+  chrome::NavigateParams new_tab_params(profile_, params.url,
+                                        params.transition);
+
+  new_tab_params.disposition = params.disposition;
+
+  if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
+    // When the user asks to open a link as a background tab, we show an
+    // activated window with the new activated tab after the user closes the
+    // launcher. So it's "background" relative to the launcher itself.
+    new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
+    new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW_INACTIVE;
+  }
+
+  chrome::Navigate(&new_tab_params);
+
+  base::RecordAction(base::UserMetricsAction("SearchAnswer_OpenedUrl"));
+
+  return new_tab_params.target_contents;
 }
 
 bool AnswerCardWebContents::HandleContextMenu(
@@ -128,7 +189,25 @@
 
 void AnswerCardWebContents::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  delegate()->DidFinishNavigation(navigation_handle);
+  bool has_answer_card = false;
+  std::string result_title;
+  std::string issued_query;
+
+  const bool has_error = !navigation_handle->HasCommitted() ||
+                         navigation_handle->IsErrorPage() ||
+                         !navigation_handle->IsInMainFrame();
+  if (has_error) {
+    LOG(ERROR) << "Failed to navigate: HasCommitted="
+               << navigation_handle->HasCommitted()
+               << ", IsErrorPage=" << navigation_handle->IsErrorPage()
+               << ", IsInMainFrame=" << navigation_handle->IsInMainFrame();
+  } else {
+    ParseResponseHeaders(navigation_handle->GetResponseHeaders(),
+                         &has_answer_card, &result_title, &issued_query);
+  }
+
+  delegate()->DidFinishNavigation(navigation_handle->GetURL(), has_error,
+                                  has_answer_card, result_title, issued_query);
 }
 
 void AnswerCardWebContents::DidStopLoading() {
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.h b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.h
index ce2909d..ffb6aac 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.h
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.h
@@ -68,6 +68,8 @@
   // Current widget host.
   content::RenderWidgetHost* host_ = nullptr;
 
+  Profile* const profile_;  // Unowned
+
   DISALLOW_COPY_AND_ASSIGN(AnswerCardWebContents);
 };
 
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc
index e07a78e..9c5dbb6b 100644
--- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc
+++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc
@@ -56,6 +56,7 @@
       new LauncherSearchResult(item_id_, discrete_value_relevance_, profile_,
                                extension_, icon_image_loader_);
   duplicated_result->set_title(title());
+  duplicated_result->set_title_tags(title_tags());
   return base::WrapUnique(duplicated_result);
 }
 
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.cc b/chrome/browser/ui/app_list/search/omnibox_result.cc
index c340244c..7163209 100644
--- a/chrome/browser/ui/app_list/search/omnibox_result.cc
+++ b/chrome/browser/ui/app_list/search/omnibox_result.cc
@@ -159,7 +159,8 @@
       list_controller_(list_controller),
       autocomplete_controller_(autocomplete_controller),
       is_voice_query_(is_voice_query),
-      match_(match) {
+      match_(match),
+      is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
   if (match_.search_terms_args && autocomplete_controller_) {
     match_.search_terms_args->from_app_list = true;
     autocomplete_controller_->UpdateMatchDestinationURL(
@@ -213,7 +214,7 @@
   bool is_bookmarked =
       bookmark_model && bookmark_model->IsBookmarked(match_.destination_url);
 
-  if (features::IsFullscreenAppListEnabled()) {
+  if (is_fullscreen_app_list_enabled_) {
     const gfx::VectorIcon& icon =
         is_bookmarked ? kIcBookmarkIcon : TypeToVectorIcon(match_.type);
     SetIcon(
@@ -233,11 +234,17 @@
                                &title_tags);
   set_title_tags(title_tags);
 
-  set_details(match_.description);
-  SearchResult::Tags details_tags;
-  ACMatchClassificationsToTags(match_.description, match_.description_class,
-                               &details_tags);
-  set_details_tags(details_tags);
+  // Do not set details for omnibox non-url search result. This will make
+  // SearchResultView show single line row for omnibox non-url search result.
+  if (!is_fullscreen_app_list_enabled_ ||
+      !AutocompleteMatch::IsSearchType(match_.type)) {
+    set_is_url(true);
+    set_details(match_.description);
+    SearchResult::Tags details_tags;
+    ACMatchClassificationsToTags(match_.description, match_.description_class,
+                                 &details_tags);
+    set_details_tags(details_tags);
+  }
 }
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.h b/chrome/browser/ui/app_list/search/omnibox_result.h
index 849bec9..49b4058 100644
--- a/chrome/browser/ui/app_list/search/omnibox_result.h
+++ b/chrome/browser/ui/app_list/search/omnibox_result.h
@@ -42,6 +42,8 @@
   bool is_voice_query_;
   AutocompleteMatch match_;
 
+  const bool is_fullscreen_app_list_enabled_;
+
   DISALLOW_COPY_AND_ASSIGN(OmniboxResult);
 };
 
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
index 56ae549..7b42e29 100644
--- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
+++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -504,11 +504,11 @@
 }
 
 void CardUnmaskPromptViews::FadeOutView::PaintChildren(
-    const ui::PaintContext& context) {
+    const views::PaintInfo& paint_info) {
   const bool kLcdTextRequiresOpaqueLayer = true;
-  ui::CompositingRecorder recorder(context, alpha_,
+  ui::CompositingRecorder recorder(paint_info.context(), alpha_,
                                    kLcdTextRequiresOpaqueLayer);
-  views::View::PaintChildren(context);
+  views::View::PaintChildren(paint_info);
 }
 
 void CardUnmaskPromptViews::FadeOutView::OnPaint(gfx::Canvas* canvas) {
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
index 51544ce..acd8828f 100644
--- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
+++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
@@ -93,7 +93,7 @@
     ~FadeOutView() override;
 
     // views::View
-    void PaintChildren(const ui::PaintContext& context) override;
+    void PaintChildren(const views::PaintInfo& paint_info) override;
     void OnPaint(gfx::Canvas* canvas) override;
 
     void set_fade_everything(bool fade_everything) {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 0dfe496..b84bd48 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1050,8 +1050,8 @@
   }
 }
 
-void BookmarkBarView::PaintChildren(const ui::PaintContext& context) {
-  View::PaintChildren(context);
+void BookmarkBarView::PaintChildren(const views::PaintInfo& paint_info) {
+  View::PaintChildren(paint_info);
 
   if (drop_info_.get() && drop_info_->valid &&
       drop_info_->location.operation != 0 && drop_info_->location.index != -1 &&
@@ -1082,7 +1082,7 @@
     gfx::Rect indicator_bounds = GetMirroredRect(
         gfx::Rect(x - kDropIndicatorWidth / 2, y, kDropIndicatorWidth, h));
 
-    ui::PaintRecorder recorder(context, size());
+    ui::PaintRecorder recorder(paint_info.context(), size());
     // TODO(sky/glen): make me pretty!
     recorder.canvas()->FillRect(
         indicator_bounds,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
index 4bbbc02..9de863b 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -169,7 +169,7 @@
   void Layout() override;
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
   bool GetDropFormats(
       int* formats,
       std::set<ui::Clipboard::FormatType>* format_types) override;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index c6353be4..c6e215a 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -2005,8 +2005,8 @@
 #endif
 }
 
-void BrowserView::PaintChildren(const ui::PaintContext& context) {
-  views::ClientView::PaintChildren(context);
+void BrowserView::PaintChildren(const views::PaintInfo& paint_info) {
+  views::ClientView::PaintChildren(paint_info);
   // Don't reset the instance before it had a chance to get compositor callback.
   if (!histogram_helper_) {
     histogram_helper_ = BrowserWindowHistogramHelper::
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 411b2d61..b318d5b2 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -434,7 +434,7 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
   void ChildPreferredSizeChanged(View* child) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnThemeChanged() override;
diff --git a/chrome/browser/ui/views/frame/top_container_view.cc b/chrome/browser/ui/views/frame/top_container_view.cc
index 0f9f816..686c73a 100644
--- a/chrome/browser/ui/views/frame/top_container_view.cc
+++ b/chrome/browser/ui/views/frame/top_container_view.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
-#include "ui/compositor/paint_context.h"
+#include "ui/views/paint_info.h"
 
 TopContainerView::TopContainerView(BrowserView* browser_view)
     : browser_view_(browser_view) {
@@ -20,7 +20,7 @@
   return "TopContainerView";
 }
 
-void TopContainerView::PaintChildren(const ui::PaintContext& context) {
+void TopContainerView::PaintChildren(const views::PaintInfo& paint_info) {
   if (browser_view_->immersive_mode_controller()->IsRevealed()) {
     // Top-views depend on parts of the frame (themes, window title, window
     // controls) being painted underneath them. Clip rect has already been set
@@ -28,10 +28,10 @@
     // invalidation info, as we're painting something outside of the normal
     // parent-child relationship, so invalidations are no longer in the correct
     // space to compare.
-    browser_view_->frame()->GetFrameView()->Paint(ui::PaintContext(
-        context, ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
+    browser_view_->frame()->GetFrameView()->Paint(
+        views::PaintInfo::ClonePaintInfo(paint_info));
   }
-  View::PaintChildren(context);
+  View::PaintChildren(paint_info);
 }
 
 void TopContainerView::ChildPreferredSizeChanged(views::View* child) {
diff --git a/chrome/browser/ui/views/frame/top_container_view.h b/chrome/browser/ui/views/frame/top_container_view.h
index 66dfa47..5ffacf8 100644
--- a/chrome/browser/ui/views/frame/top_container_view.h
+++ b/chrome/browser/ui/views/frame/top_container_view.h
@@ -21,7 +21,7 @@
 
   // views::View overrides:
   const char* GetClassName() const override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
   void ChildPreferredSizeChanged(views::View* child) override;
 
  private:
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index 8717a87..22f4cfbd 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -494,9 +494,10 @@
                        g_bottom_shadow.Get().height());
 }
 
-void OmniboxPopupContentsView::PaintChildren(const ui::PaintContext& context) {
+void OmniboxPopupContentsView::PaintChildren(
+    const views::PaintInfo& paint_info) {
   if (base::FeatureList::IsEnabled(omnibox::kUIExperimentNarrowDropdown)) {
-    View::PaintChildren(context);
+    View::PaintChildren(paint_info);
     return;
   }
 
@@ -504,15 +505,15 @@
   contents_bounds.Inset(0, g_top_shadow.Get().height(), 0,
                         g_bottom_shadow.Get().height());
 
-  ui::ClipRecorder clip_recorder(context);
+  ui::ClipRecorder clip_recorder(paint_info.context());
   clip_recorder.ClipRect(contents_bounds);
   {
-    ui::PaintRecorder recorder(context, size());
+    ui::PaintRecorder recorder(paint_info.context(), size());
     SkColor background_color = result_view_at(0)->GetColor(
         OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND);
     recorder.canvas()->DrawColor(background_color);
   }
-  View::PaintChildren(context);
+  View::PaintChildren(paint_info);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
index 96abda7..7d7eea38 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
@@ -94,7 +94,7 @@
   // views::View:
   const char* GetClassName() const override;
   void OnPaint(gfx::Canvas* canvas) override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
 
   // views::ViewTargeterDelegate:
   views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override;
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 52115c8..7ce3a83 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -349,10 +349,10 @@
     SetEnabled(false);
   }
 
-  void PaintChildren(const ui::PaintContext& context) override {
+  void PaintChildren(const views::PaintInfo& paint_info) override {
     {
       // Display any children (the "change photo" overlay) as a circle.
-      ui::ClipRecorder clip_recorder(context);
+      ui::ClipRecorder clip_recorder(paint_info.context());
       gfx::Rect clip_bounds = image()->GetMirroredBounds();
       gfx::Path clip_mask;
       clip_mask.addCircle(
@@ -360,11 +360,11 @@
           clip_bounds.y() + clip_bounds.height() / 2,
           clip_bounds.width() / 2);
       clip_recorder.ClipPathWithAntiAliasing(clip_mask);
-      View::PaintChildren(context);
+      View::PaintChildren(paint_info);
     }
 
     ui::PaintRecorder paint_recorder(
-        context, gfx::Size(kProfileBadgeSize, kProfileBadgeSize));
+        paint_info.context(), gfx::Size(kProfileBadgeSize, kProfileBadgeSize));
     gfx::Canvas* canvas = paint_recorder.canvas();
     if (profile_->IsSupervised()) {
       gfx::Rect bounds(0, 0, kProfileBadgeSize, kProfileBadgeSize);
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 10abdb5..ef7ae9c 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -357,9 +357,8 @@
 }
 
 bool BrowserTabStripController::IsCompatibleWith(TabStrip* other) const {
-  Profile* other_profile =
-      static_cast<BrowserTabStripController*>(other->controller())->profile();
-  return other_profile == profile();
+  Profile* other_profile = other->controller()->GetProfile();
+  return other_profile == GetProfile();
 }
 
 void BrowserTabStripController::CreateNewTab() {
@@ -376,8 +375,9 @@
   // Use autocomplete to clean up the text, going so far as to turn it into
   // a search query if necessary.
   AutocompleteMatch match;
-  AutocompleteClassifierFactory::GetForProfile(profile())->Classify(
-      location, false, false, metrics::OmniboxEventProto::BLANK, &match, NULL);
+  AutocompleteClassifierFactory::GetForProfile(GetProfile())
+      ->Classify(location, false, false, metrics::OmniboxEventProto::BLANK,
+                 &match, NULL);
   if (match.destination_url.is_valid())
     model_->delegate()->AddTabAt(match.destination_url, -1, true);
 }
@@ -432,6 +432,10 @@
       false /* include_app_name */, tabstrip_->GetModelIndexOfTab(tab));
 }
 
+Profile* BrowserTabStripController::GetProfile() const {
+  return model_->profile();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // BrowserTabStripController, TabStripModelObserver implementation:
 
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index d51a2a0..c708952 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -78,6 +78,7 @@
   void CheckFileSupported(const GURL& url) override;
   SkColor GetToolbarTopSeparatorColor() const override;
   base::string16 GetAccessibleTabName(const Tab* tab) const override;
+  Profile* GetProfile() const override;
 
   // TabStripModelObserver implementation:
   void TabInsertedAt(TabStripModel* tab_strip_model,
@@ -119,8 +120,6 @@
                                            TabRendererData* data,
                                            TabStatus tab_status);
 
-  Profile* profile() const { return model_->profile(); }
-
   const TabStrip* tabstrip() const { return tabstrip_; }
 
  private:
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
index d4c0337..e4f291b 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -153,3 +153,7 @@
     const Tab* tab) const {
   return base::string16();
 }
+
+Profile* FakeBaseTabStripController::GetProfile() const {
+  return nullptr;
+}
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
index 28318dfa..50a314a0 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -56,6 +56,7 @@
   void CheckFileSupported(const GURL& url) override;
   SkColor GetToolbarTopSeparatorColor() const override;
   base::string16 GetAccessibleTabName(const Tab* tab) const override;
+  Profile* GetProfile() const override;
 
  private:
   TabStrip* tab_strip_;
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc
index b867042..6e0f6b47 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.cc
+++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -4,8 +4,10 @@
 
 #include "chrome/browser/ui/views/tabs/new_tab_button.h"
 
+#include "build/build_config.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/layout_constants.h"
+#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
 #include "chrome/browser/ui/views/tabs/new_tab_promo.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
@@ -22,6 +24,11 @@
 #include "ui/views/win/hwnd_util.h"
 #endif
 
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h"
+#endif
+
 namespace {
 
 sk_sp<SkDrawLooper> CreateShadowDrawLooper(SkColor color) {
@@ -46,6 +53,7 @@
 NewTabButton::NewTabButton(TabStrip* tab_strip, views::ButtonListener* listener)
     : views::ImageButton(listener),
       tab_strip_(tab_strip),
+      new_tab_promo_(nullptr),
       destroyed_(nullptr),
       new_tab_promo_observer_(this) {
   set_animate_on_state_change(true);
@@ -71,8 +79,8 @@
 
 void NewTabButton::ShowPromo() {
   // Owned by its native widget. Will be destroyed as its widget is destroyed.
-  NewTabPromo* new_tab_promo = NewTabPromo::CreateSelfOwned(GetVisibleBounds());
-  new_tab_promo_observer_.Add(new_tab_promo->GetWidget());
+  new_tab_promo_ = NewTabPromo::Create(GetVisibleBounds());
+  new_tab_promo_observer_.Add(new_tab_promo_->GetWidget());
   NewTabButton::SchedulePaint();
 }
 
@@ -177,6 +185,11 @@
 }
 
 void NewTabButton::OnWidgetDestroying(views::Widget* widget) {
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
+  feature_engagement::NewTabTrackerFactory::GetInstance()
+      ->GetForProfile(tab_strip_->controller()->GetProfile())
+      ->DismissNewTabTracker();
+#endif
   new_tab_promo_observer_.Remove(widget);
   // When the promo widget is destroyed, the NewTabButton needs to be
   // recolored.
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.h b/chrome/browser/ui/views/tabs/new_tab_button.h
index e27ce92..98f61d83 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.h
+++ b/chrome/browser/ui/views/tabs/new_tab_button.h
@@ -41,6 +41,8 @@
   // Shows the NewTabPromo when the NewTabFeatureEngagementTracker calls for it.
   void ShowPromo();
 
+  NewTabPromo* new_tab_promo() { return new_tab_promo_; }
+
  private:
 // views::ImageButton:
 #if defined(OS_WIN)
@@ -81,6 +83,10 @@
   // Tab strip that contains this button.
   TabStrip* tab_strip_;
 
+  // Promotional UI that appears next to the NewTabButton and encourages its
+  // use. Owned by its NativeWidget.
+  NewTabPromo* new_tab_promo_;
+
   // The offset used to paint the background image.
   gfx::Point background_offset_;
 
diff --git a/chrome/browser/ui/views/tabs/new_tab_promo.cc b/chrome/browser/ui/views/tabs/new_tab_promo.cc
index df2b9f3..1ddb923 100644
--- a/chrome/browser/ui/views/tabs/new_tab_promo.cc
+++ b/chrome/browser/ui/views/tabs/new_tab_promo.cc
@@ -33,7 +33,7 @@
 }  // namespace
 
 // static
-NewTabPromo* NewTabPromo::CreateSelfOwned(const gfx::Rect& anchor_rect) {
+NewTabPromo* NewTabPromo::Create(const gfx::Rect& anchor_rect) {
   return new NewTabPromo(anchor_rect);
 }
 
diff --git a/chrome/browser/ui/views/tabs/new_tab_promo.h b/chrome/browser/ui/views/tabs/new_tab_promo.h
index 642fc164..77f3fc2 100644
--- a/chrome/browser/ui/views/tabs/new_tab_promo.h
+++ b/chrome/browser/ui/views/tabs/new_tab_promo.h
@@ -22,8 +22,9 @@
 // when prompted by the NewTabFeatureEngagementTracker.
 class NewTabPromo : public views::BubbleDialogDelegateView {
  public:
-  // Returns a self owned raw pointer to the NewTabButton.
-  static NewTabPromo* CreateSelfOwned(const gfx::Rect& anchor_rect);
+  // Returns a raw pointer to the NewTabButton. This raw pointer is owned by its
+  // NativeWidget.
+  static NewTabPromo* Create(const gfx::Rect& anchor_rect);
 
  private:
   // Constructs NewTabPromo. Anchors the bubble to the NewTabButton.
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 3fb853b..3762681 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1066,7 +1066,7 @@
   DoLayout();
 }
 
-void TabStrip::PaintChildren(const ui::PaintContext& context) {
+void TabStrip::PaintChildren(const views::PaintInfo& paint_info) {
   // The view order doesn't match the paint order (tabs_ contains the tab
   // ordering). Additionally we need to paint the tabs that are closing in
   // |tabs_closing_map_|.
@@ -1079,10 +1079,10 @@
     // We pass false for |lcd_text_requires_opaque_layer| so that background
     // tab titles will get LCD AA.  These are rendered opaquely on an opaque tab
     // background before the layer is composited, so this is safe.
-    ui::CompositingRecorder opacity_recorder(context, GetInactiveAlpha(false),
-                                             false);
+    ui::CompositingRecorder opacity_recorder(paint_info.context(),
+                                             GetInactiveAlpha(false), false);
 
-    PaintClosingTabs(tab_count(), context);
+    PaintClosingTabs(tab_count(), paint_info);
 
     int active_tab_index = -1;
     for (int i = tab_count() - 1; i >= 0; --i) {
@@ -1098,7 +1098,7 @@
       } else if (!tab->IsActive()) {
         if (!tab->IsSelected()) {
           if (!stacked_layout_)
-            tab->Paint(context);
+            tab->Paint(paint_info);
         } else {
           selected_tabs.push_back(tab);
         }
@@ -1106,19 +1106,19 @@
         active_tab = tab;
         active_tab_index = i;
       }
-      PaintClosingTabs(i, context);
+      PaintClosingTabs(i, paint_info);
     }
 
     // Draw from the left and then the right if we're in touch mode.
     if (stacked_layout_ && active_tab_index >= 0) {
       for (int i = 0; i < active_tab_index; ++i) {
         Tab* tab = tab_at(i);
-        tab->Paint(context);
+        tab->Paint(paint_info);
       }
 
       for (int i = tab_count() - 1; i > active_tab_index; --i) {
         Tab* tab = tab_at(i);
-        tab->Paint(context);
+        tab->Paint(paint_info);
       }
     }
   }
@@ -1126,34 +1126,34 @@
   // Now selected but not active. We don't want these dimmed if using native
   // frame, so they're painted after initial pass.
   for (size_t i = 0; i < selected_tabs.size(); ++i)
-    selected_tabs[i]->Paint(context);
+    selected_tabs[i]->Paint(paint_info);
 
   // Next comes the active tab.
   if (active_tab && !is_dragging)
-    active_tab->Paint(context);
+    active_tab->Paint(paint_info);
 
   // Paint the New Tab button.
   if (new_tab_button_->state() == views::CustomButton::STATE_PRESSED) {
-    new_tab_button_->Paint(context);
+    new_tab_button_->Paint(paint_info);
   } else {
     // Match the inactive tab opacity for non-pressed states.  See comments in
     // NewTabButton::PaintFill() for why we don't do this for the pressed state.
     // This call doesn't need to set |lcd_text_requires_opaque_layer| to false
     // because no text will be drawn.
-    ui::CompositingRecorder opacity_recorder(context, GetInactiveAlpha(true),
-                                             true);
-    new_tab_button_->Paint(context);
+    ui::CompositingRecorder opacity_recorder(paint_info.context(),
+                                             GetInactiveAlpha(true), true);
+    new_tab_button_->Paint(paint_info);
   }
 
   // And the dragged tabs.
   for (size_t i = 0; i < tabs_dragging.size(); ++i)
-    tabs_dragging[i]->Paint(context);
+    tabs_dragging[i]->Paint(paint_info);
 
   // If the active tab is being dragged, it goes last.
   if (active_tab && is_dragging)
-    active_tab->Paint(context);
+    active_tab->Paint(paint_info);
 
-  ui::PaintRecorder recorder(context, size());
+  ui::PaintRecorder recorder(paint_info.context(), size());
   gfx::Canvas* canvas = recorder.canvas();
   if (active_tab) {
     canvas->sk_canvas()->clipRect(
@@ -1784,13 +1784,13 @@
   return FindClosingTabResult(tabs_closing_map_.end(), Tabs::iterator());
 }
 
-void TabStrip::PaintClosingTabs(int index, const ui::PaintContext& context) {
+void TabStrip::PaintClosingTabs(int index, const views::PaintInfo& paint_info) {
   if (tabs_closing_map_.find(index) == tabs_closing_map_.end())
     return;
 
   const Tabs& tabs = tabs_closing_map_[index];
   for (Tabs::const_reverse_iterator i(tabs.rbegin()); i != tabs.rend(); ++i)
-    (*i)->Paint(context);
+    (*i)->Paint(paint_info);
 }
 
 void TabStrip::UpdateStackedLayoutFromMouseEvent(views::View* source,
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 7601eaa6..6fc020c7 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -251,7 +251,7 @@
 
   // views::View overrides:
   void Layout() override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
   const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
   // NOTE: the drag and drop methods are invoked from FrameView. This is done
@@ -428,7 +428,7 @@
   FindClosingTabResult FindClosingTab(const Tab* tab);
 
   // Paints all the tabs in |tabs_closing_map_[index]|.
-  void PaintClosingTabs(int index, const ui::PaintContext& context);
+  void PaintClosingTabs(int index, const views::PaintInfo& paint_info);
 
   // Invoked when a mouse event occurs over |source|. Potentially switches the
   // |stacked_layout_|.
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h
index f06590b..ecb8f01e 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
 
 #include "base/strings/string16.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_types.h"
@@ -126,6 +127,9 @@
 
   // Returns the accessible tab name.
   virtual base::string16 GetAccessibleTabName(const Tab* tab) const = 0;
+
+  // Returns the profile associated with the Tabstrip.
+  virtual Profile* GetProfile() const = 0;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc
new file mode 100644
index 0000000..ce64fd4
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc
@@ -0,0 +1,68 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
+
+#include "build/build_config.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+namespace chromeos {
+namespace bluetooth_dialog {
+
+void AddLocalizedStrings(content::WebUIDataSource* html_source) {
+  struct {
+    const char* name;
+    int id;
+  } localized_strings[] = {
+      {"bluetoothAccept", IDS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY},
+      {"bluetoothEnterKey", IDS_SETTINGS_BLUETOOTH_ENTER_KEY},
+      {"bluetoothPair", IDS_SETTINGS_BLUETOOTH_PAIR},
+      {"bluetoothReject", IDS_SETTINGS_BLUETOOTH_REJECT_PASSKEY},
+      {"bluetoothStartConnecting", IDS_SETTINGS_BLUETOOTH_START_CONNECTING},
+      // Device connecting and pairing.
+      // These ids are generated in JS using 'bluetooth_' + a value from
+      // bluetoothPrivate.PairingEventType (see bluetooth_private.idl).
+      // 'keysEntered', and 'requestAuthorization' have no associated message.
+      {"bluetooth_requestPincode", IDS_SETTINGS_BLUETOOTH_REQUEST_PINCODE},
+      {"bluetooth_displayPincode", IDS_SETTINGS_BLUETOOTH_DISPLAY_PINCODE},
+      {"bluetooth_requestPasskey", IDS_SETTINGS_BLUETOOTH_REQUEST_PASSKEY},
+      {"bluetooth_displayPasskey", IDS_SETTINGS_BLUETOOTH_DISPLAY_PASSKEY},
+      {"bluetooth_confirmPasskey", IDS_SETTINGS_BLUETOOTH_CONFIRM_PASSKEY},
+      // These ids are generated in JS using 'bluetooth_connect_' + a value from
+      // bluetoothPrivate.ConnectResultType (see bluetooth_private.idl).
+      {"bluetooth_connect_attributeLengthInvalid",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_ATTRIBUTE_LENGTH_INVALID},
+      {"bluetooth_connect_authCanceled",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_CANCELED},
+      {"bluetooth_connect_authFailed",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_FAILED},
+      {"bluetooth_connect_authRejected",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_REJECTED},
+      {"bluetooth_connect_authTimeout",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_TIMEOUT},
+      {"bluetooth_connect_connectionCongested",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_CONNECTION_CONGESTED},
+      {"bluetooth_connect_failed", IDS_SETTINGS_BLUETOOTH_CONNECT_FAILED},
+      {"bluetooth_connect_inProgress",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_IN_PROGRESS},
+      {"bluetooth_connect_insufficientEncryption",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_INSUFFICIENT_ENCRYPTION},
+      {"bluetooth_connect_offsetInvalid",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_OFFSET_INVALID},
+      {"bluetooth_connect_readNotPermitted",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_READ_NOT_PERMITTED},
+      {"bluetooth_connect_requestNotSupported",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_REQUEST_NOT_SUPPORTED},
+      {"bluetooth_connect_unsupportedDevice",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_UNSUPPORTED_DEVICE},
+      {"bluetooth_connect_writeNotPermitted",
+       IDS_SETTINGS_BLUETOOTH_CONNECT_WRITE_NOT_PERMITTED},
+  };
+  for (const auto& entry : localized_strings)
+    html_source->AddLocalizedString(entry.name, entry.id);
+}
+
+}  // namespace bluetooth_dialog
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h b/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h
new file mode 100644
index 0000000..c85140ca
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_LOCALIZED_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_LOCALIZED_STRINGS_PROVIDER_H_
+
+namespace content {
+class WebUIDataSource;
+}
+
+namespace chromeos {
+namespace bluetooth_dialog {
+
+// Adds the strings needed for network elements to |html_source|. String ids
+// correspond to ids in ui/webui/resources/cr_elements/chromeos/network/.
+void AddLocalizedStrings(content::WebUIDataSource* html_source);
+
+}  // namespace bluetooth_dialog
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.cc b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.cc
index bbd209e..70a41a4d 100644
--- a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.cc
@@ -4,59 +4,55 @@
 
 #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h"
 
-#include "base/memory/ptr_util.h"
-#include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h"
-#include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
+#include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 
-using content::WebContents;
-using content::WebUIMessageHandler;
-
 namespace chromeos {
 
+namespace {
+
+void AddBluetoothStrings(content::WebUIDataSource* html_source) {
+  struct {
+    const char* name;
+    int id;
+  } localized_strings[] = {
+      {"ok", IDS_OK},
+      {"bluetoothPairDevicePageTitle",
+       IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE},
+      {"cancel", IDS_CANCEL},
+      {"close", IDS_CLOSE},
+  };
+  for (const auto& entry : localized_strings)
+    html_source->AddLocalizedString(entry.name, entry.id);
+  chromeos::bluetooth_dialog::AddLocalizedStrings(html_source);
+}
+
+}  // namespace
+
 BluetoothPairingUI::BluetoothPairingUI(content::WebUI* web_ui)
     : WebDialogUI(web_ui) {
-  base::DictionaryValue localized_strings;
-
-  auto core_handler = base::MakeUnique<options::CoreChromeOSOptionsHandler>();
-  core_handler_ = core_handler.get();
-  web_ui->AddMessageHandler(std::move(core_handler));
-  core_handler_->set_handlers_host(this);
-  core_handler_->GetLocalizedValues(&localized_strings);
-
-  auto bluetooth_handler = base::MakeUnique<options::BluetoothOptionsHandler>();
-  bluetooth_handler_ = bluetooth_handler.get();
-  web_ui->AddMessageHandler(std::move(bluetooth_handler));
-  bluetooth_handler_->GetLocalizedValues(&localized_strings);
-
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(chrome::kChromeUIBluetoothPairingHost);
-  source->AddLocalizedStrings(localized_strings);
+
+  AddBluetoothStrings(source);
   source->SetJsonPath("strings.js");
   source->SetDefaultResource(IDR_BLUETOOTH_PAIR_DEVICE_HTML);
   source->DisableContentSecurityPolicy();
 
-  Profile* profile = Profile::FromWebUI(web_ui);
-  content::WebUIDataSource::Add(profile, source);
+  source->AddResourcePath("bluetooth_dialog_host.html",
+                          IDR_BLUETOOTH_DIALOG_HOST_HTML);
+  source->AddResourcePath("bluetooth_dialog_host.js",
+                          IDR_BLUETOOTH_DIALOG_HOST_JS);
+
+  content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
 }
 
-BluetoothPairingUI::~BluetoothPairingUI() {
-  // Uninitialize all registered handlers. The base class owns them and it will
-  // eventually delete them.
-  core_handler_->Uninitialize();
-  bluetooth_handler_->Uninitialize();
-}
-
-void BluetoothPairingUI::InitializeHandlers() {
-  core_handler_->InitializeHandler();
-  bluetooth_handler_->InitializeHandler();
-  core_handler_->InitializePage();
-  bluetooth_handler_->InitializePage();
-}
+BluetoothPairingUI::~BluetoothPairingUI() {}
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h
index 3690918..d49cf57 100644
--- a/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h
+++ b/chrome/browser/ui/webui/chromeos/bluetooth_pairing_ui.h
@@ -6,30 +6,17 @@
 #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_BLUETOOTH_PAIRING_UI_H_
 
 #include "base/macros.h"
-#include "chrome/browser/ui/webui/options/options_ui.h"
 #include "ui/web_dialogs/web_dialog_ui.h"
 
 namespace chromeos {
 
-namespace options {
-class CoreChromeOSOptionsHandler;
-class BluetoothOptionsHandler;
-}
-
 // A WebUI to host bluetooth device pairing web ui.
-class BluetoothPairingUI : public ui::WebDialogUI,
-                           public ::options::OptionsPageUIHandlerHost {
+class BluetoothPairingUI : public ui::WebDialogUI {
  public:
   explicit BluetoothPairingUI(content::WebUI* web_ui);
   ~BluetoothPairingUI() override;
 
  private:
-  // Overridden from OptionsPageUIHandlerHost:
-  void InitializeHandlers() override;
-
-  options::CoreChromeOSOptionsHandler* core_handler_ = nullptr;
-  options::BluetoothOptionsHandler* bluetooth_handler_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(BluetoothPairingUI);
 };
 
diff --git a/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc
index 854a59b..9e73b08 100644
--- a/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc
@@ -45,6 +45,7 @@
                IDS_WAIT_FOR_CONTAINER_READY_TITLE);
   builder->Add("waitForContainerReadyIntroMessage",
                IDS_WAIT_FOR_CONTAINER_READY_INTRO_MESSAGE);
+  builder->Add("voiceInteractionLogo", IDS_VOICE_INTERACTION_LOGO);
 }
 
 void WaitForContainerReadyScreenHandler::Bind(
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 0a39641..88d409c 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
 #include "chromeos/chromeos_switches.h"
@@ -368,7 +369,6 @@
 #if defined(OS_CHROMEOS)
 void AddBluetoothStrings(content::WebUIDataSource* html_source) {
   LocalizedString localized_strings[] = {
-      {"bluetoothAccept", IDS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY},
       {"bluetoothConnected", IDS_SETTINGS_BLUETOOTH_CONNECTED},
       {"bluetoothConnecting", IDS_SETTINGS_BLUETOOTH_CONNECTING},
       {"bluetoothDeviceListPaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED},
@@ -384,54 +384,13 @@
       {"bluetoothNoDevicesFound", IDS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND},
       {"bluetoothNotConnected", IDS_SETTINGS_BLUETOOTH_NOT_CONNECTED},
       {"bluetoothPageTitle", IDS_SETTINGS_BLUETOOTH},
-      {"bluetoothPair", IDS_SETTINGS_BLUETOOTH_PAIR},
       {"bluetoothPairDevicePageTitle",
        IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE},
-      {"bluetoothReject", IDS_SETTINGS_BLUETOOTH_REJECT_PASSKEY},
       {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE},
-      // Device connecting and pairing.
-      {"bluetoothStartConnecting", IDS_SETTINGS_BLUETOOTH_START_CONNECTING},
-      {"bluetoothEnterKey", IDS_SETTINGS_BLUETOOTH_ENTER_KEY},
-      // These ids are generated in JS using 'bluetooth_' + a value from
-      // bluetoothPrivate.PairingEventType (see bluetooth_private.idl).
-      // 'keysEntered', and 'requestAuthorization' have no associated message.
-      {"bluetooth_requestPincode", IDS_SETTINGS_BLUETOOTH_REQUEST_PINCODE},
-      {"bluetooth_displayPincode", IDS_SETTINGS_BLUETOOTH_DISPLAY_PINCODE},
-      {"bluetooth_requestPasskey", IDS_SETTINGS_BLUETOOTH_REQUEST_PASSKEY},
-      {"bluetooth_displayPasskey", IDS_SETTINGS_BLUETOOTH_DISPLAY_PASSKEY},
-      {"bluetooth_confirmPasskey", IDS_SETTINGS_BLUETOOTH_CONFIRM_PASSKEY},
-      // These ids are generated in JS using 'bluetooth_connect_' + a value from
-      // bluetoothPrivate.ConnectResultType (see bluetooth_private.idl).
-      {"bluetooth_connect_attributeLengthInvalid",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_ATTRIBUTE_LENGTH_INVALID},
-      {"bluetooth_connect_authCanceled",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_CANCELED},
-      {"bluetooth_connect_authFailed",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_FAILED},
-      {"bluetooth_connect_authRejected",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_REJECTED},
-      {"bluetooth_connect_authTimeout",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_AUTH_TIMEOUT},
-      {"bluetooth_connect_connectionCongested",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_CONNECTION_CONGESTED},
-      {"bluetooth_connect_failed", IDS_SETTINGS_BLUETOOTH_CONNECT_FAILED},
-      {"bluetooth_connect_inProgress",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_IN_PROGRESS},
-      {"bluetooth_connect_insufficientEncryption",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_INSUFFICIENT_ENCRYPTION},
-      {"bluetooth_connect_offsetInvalid",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_OFFSET_INVALID},
-      {"bluetooth_connect_readNotPermitted",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_READ_NOT_PERMITTED},
-      {"bluetooth_connect_requestNotSupported",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_REQUEST_NOT_SUPPORTED},
-      {"bluetooth_connect_unsupportedDevice",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_UNSUPPORTED_DEVICE},
-      {"bluetooth_connect_writeNotPermitted",
-       IDS_SETTINGS_BLUETOOTH_CONNECT_WRITE_NOT_PERMITTED},
   };
   AddLocalizedStringsBulk(html_source, localized_strings,
                           arraysize(localized_strings));
+  chromeos::bluetooth_dialog::AddLocalizedStrings(html_source);
 }
 #endif
 
@@ -1892,7 +1851,6 @@
      IDS_SETTINGS_SITE_SETTINGS_ASK_BEFORE_SENDING},
     {"siteSettingsAskBeforeSendingRecommended",
      IDS_SETTINGS_SITE_SETTINGS_ASK_BEFORE_SENDING_RECOMMENDED},
-    {"siteSettingsFlashAllow", IDS_SETTINGS_SITE_SETTINGS_FLASH_ALLOW},
     {"siteSettingsFlashBlock", IDS_SETTINGS_SITE_SETTINGS_FLASH_BLOCK},
     {"siteSettingsAllowRecentlyClosedSites",
      IDS_SETTINGS_SITE_SETTINGS_ALLOW_RECENTLY_CLOSED_SITES},
@@ -2024,19 +1982,18 @@
   if (PluginUtils::ShouldPreferHtmlOverPlugins(
           HostContentSettingsMapFactory::GetForProfile(profile))) {
     LocalizedString flash_strings[] = {
-        {"siteSettingsFlashAskBefore",
-         IDS_SETTINGS_SITE_SETTINGS_FLASH_ASK_BEFORE_RUNNING},
-        {"siteSettingsFlashAskBeforeSubtitle",
-         IDS_SETTINGS_SITE_SETTINGS_FLASH_ASK_BEFORE_RUNNING_SUBTITLE},
+        {"siteSettingsFlashAskFirst", IDS_SETTINGS_SITE_SETTINGS_ASK_FIRST},
+        {"siteSettingsFlashAskFirstRecommended",
+         IDS_SETTINGS_SITE_SETTINGS_ASK_FIRST_RECOMMENDED},
     };
     AddLocalizedStringsBulk(html_source, flash_strings,
                             arraysize(flash_strings));
   } else {
     LocalizedString flash_strings[] = {
-        {"siteSettingsFlashAskBefore",
+        {"siteSettingsFlashAskFirst",
          IDS_SETTINGS_SITE_SETTINGS_FLASH_DETECT_IMPORTANT},
-        {"siteSettingsFlashAskBeforeSubtitle",
-         IDS_SETTINGS_SITE_SETTINGS_FLASH_DETECT_IMPORTANT_SUBTITLE},
+        {"siteSettingsFlashAskFirstRecommended",
+         IDS_SETTINGS_SITE_SETTINGS_FLASH_DETECT_IMPORTANT_RECOMMENDED},
     };
     AddLocalizedStringsBulk(html_source, flash_strings,
                             arraysize(flash_strings));
diff --git a/chrome/browser/ui/webui/web_ui_test_handler.cc b/chrome/browser/ui/webui/web_ui_test_handler.cc
index 2b9ae90..35561e4 100644
--- a/chrome/browser/ui/webui/web_ui_test_handler.cc
+++ b/chrome/browser/ui/webui/web_ui_test_handler.cc
@@ -11,6 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/common/render_messages.h"
+#include "chrome/common/web_ui_tester.mojom.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_types.h"
@@ -18,6 +19,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
+#include "content/public/common/associated_interface_provider.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -34,8 +36,10 @@
 void WebUITestHandler::PreloadJavaScript(const base::string16& js_text,
                                          RenderViewHost* preload_host) {
   DCHECK(preload_host);
-  preload_host->Send(new ChromeViewMsg_WebUIJavaScript(
-      preload_host->GetRoutingID(), js_text));
+  chrome::mojom::WebUITesterAssociatedPtr web_ui_tester;
+  preload_host->GetMainFrame()->GetRemoteAssociatedInterfaces()->GetInterface(
+      &web_ui_tester);
+  web_ui_tester->ExecuteWebUIJavaScript(js_text);
 }
 
 void WebUITestHandler::RunJavaScript(const base::string16& js_text) {
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index ceabd84..f329273a 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -703,6 +703,10 @@
     ]
   }
 
+  if (!is_android) {
+    sources += [ "web_ui_tester.mojom" ]
+  }
+
   public_deps = [
     "//components/content_settings/core/common:mojo_bindings",
     "//mojo/common:common_custom_types",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 509775b3..f46bba7 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -5,6 +5,7 @@
 #include "chrome/common/chrome_features.h"
 
 #include "base/command_line.h"
+#include "build/build_config.h"
 #include "chrome/common/chrome_switches.h"
 #include "extensions/features/features.h"
 #include "ppapi/features/features.h"
@@ -137,6 +138,11 @@
     "ConsistentOmniboxGeolocation", base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
+#if defined(OS_MACOSX)
+const base::Feature kContentFullscreen{"ContentFullscreen",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 #if defined(OS_ANDROID)
 // Experiment to extract structured metadata for app indexing.
 const base::Feature kCopylessPaste{"CopylessPaste",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 3dbd63b..5511bd8 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -75,6 +75,10 @@
 extern const base::Feature kConsistentOmniboxGeolocation;
 #endif
 
+#if defined(OS_MACOSX)
+extern const base::Feature kContentFullscreen;
+#endif
+
 #if defined(OS_ANDROID)
 extern const base::Feature kCopylessPaste;
 #endif
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index fdcfdbf..3ab888f 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -114,14 +114,6 @@
 // RenderView messages
 // These are messages sent from the browser to the renderer process.
 
-#if !defined(OS_ANDROID)
-// For WebUI testing, this message requests JavaScript to be executed at a time
-// which is late enough to not be thrown out, and early enough to be before
-// onload events are fired.
-IPC_MESSAGE_ROUTED1(ChromeViewMsg_WebUIJavaScript,
-                    base::string16  /* javascript */)
-#endif
-
 // Tells the render frame to load all blocked plugins with the given identifier.
 IPC_MESSAGE_ROUTED1(ChromeViewMsg_LoadBlockedPlugins,
                     std::string /* identifier */)
diff --git a/chrome/common/web_ui_tester.mojom b/chrome/common/web_ui_tester.mojom
new file mode 100644
index 0000000..7e511de
--- /dev/null
+++ b/chrome/common/web_ui_tester.mojom
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chrome.mojom;
+
+import "mojo/common/string16.mojom";
+
+interface WebUITester {
+  // For WebUI testing, this message requests JavaScript to be executed at a
+  // time which is late enough to not be thrown out, and early enough to be
+  // before onload events are fired.
+  ExecuteWebUIJavaScript(mojo.common.mojom.String16 javascript);
+};
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn
index 0fd816f..c055862 100644
--- a/chrome/installer/linux/BUILD.gn
+++ b/chrome/installer/linux/BUILD.gn
@@ -99,7 +99,7 @@
     "debian/changelog.template",
     "debian/control.template",
     "debian/debian.menu",
-    "debian/expected_deps_x64_jessie",
+    "debian/expected_deps_x64",
     "debian/postinst",
     "debian/postrm",
     "debian/prerm",
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh
index fdf61ef..4c4979f 100755
--- a/chrome/installer/linux/debian/build.sh
+++ b/chrome/installer/linux/debian/build.sh
@@ -235,13 +235,6 @@
 process_opts "$@"
 BUILDDIR=${BUILDDIR:=$(readlink -f "${SCRIPTDIR}/../../../../out/Release")}
 
-if [[ "$(basename ${SYSROOT})" = "debian_jessie_"*"-sysroot" ]]; then
-  TARGET_DISTRO="jessie"
-else
-  echo "Debian package can only be built using the jessie sysroot."
-  exit 1
-fi
-
 source ${BUILDDIR}/installer/common/installer.include
 
 get_version_info
@@ -295,15 +288,15 @@
 
 # Compare the expected dependency list to the generated list.
 BAD_DIFF=0
-if [ -r "$SCRIPTDIR/expected_deps_${TARGETARCH}_${TARGET_DISTRO}" ]; then
-  diff -u "$SCRIPTDIR/expected_deps_${TARGETARCH}_${TARGET_DISTRO}" actual || \
+if [ -r "$SCRIPTDIR/expected_deps_${TARGETARCH}" ]; then
+  diff -u "$SCRIPTDIR/expected_deps_${TARGETARCH}" actual || \
     BAD_DIFF=1
 fi
 if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
   echo
   echo "ERROR: Shared library dependencies changed!"
   echo "If this is intentional, please update:"
-  echo "chrome/installer/linux/debian/expected_deps_x64_jessie"
+  echo "chrome/installer/linux/debian/expected_deps_x64"
   echo
   exit $BAD_DIFF
 fi
diff --git a/chrome/installer/linux/debian/expected_deps_x64_jessie b/chrome/installer/linux/debian/expected_deps_x64
similarity index 100%
rename from chrome/installer/linux/debian/expected_deps_x64_jessie
rename to chrome/installer/linux/debian/expected_deps_x64
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index da45c543..06fbf18f 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -28,6 +28,8 @@
 #include "chrome/renderer/web_apps.h"
 #include "components/translate/content/renderer/translate_helper.h"
 #include "content/public/common/associated_interface_provider.h"
+#include "content/public/common/associated_interface_registry.h"
+#include "content/public/common/bindings_policy.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_view.h"
 #include "extensions/common/constants.h"
@@ -142,6 +144,11 @@
   if (!command_line.HasSwitch(switches::kDisableClientSidePhishingDetection))
     SetClientSidePhishingDetection(true);
 #endif
+#if !defined(OS_ANDROID)
+  render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
+      base::Bind(&ChromeRenderFrameObserver::OnWebUITesterRequest,
+                 base::Unretained(this)));
+#endif
   translate_helper_ = new translate::TranslateHelper(
       render_frame, chrome::ISOLATED_WORLD_ID_TRANSLATE,
       extensions::kExtensionScheme);
@@ -313,6 +320,13 @@
 }
 #endif
 
+#if !defined(OS_ANDROID)
+void ChromeRenderFrameObserver::ExecuteWebUIJavaScript(
+    const base::string16& javascript) {
+  webui_javascript_.push_back(javascript);
+}
+#endif
+
 void ChromeRenderFrameObserver::DidFinishLoad() {
   WebLocalFrame* frame = render_frame()->GetWebFrame();
   // Don't do anything for subframes.
@@ -352,6 +366,15 @@
   base::debug::SetCrashKeyValue(
       crash_keys::kViewCount,
       base::SizeTToString(content::RenderView::GetRenderViewCount()));
+
+#if !defined(OS_ANDROID)
+  if ((render_frame()->GetEnabledBindings() &
+       content::BINDINGS_POLICY_WEB_UI)) {
+    for (const auto& script : webui_javascript_)
+      render_frame()->ExecuteJavaScript(script);
+    webui_javascript_.clear();
+  }
+#endif
 }
 
 void ChromeRenderFrameObserver::CapturePageText(TextCaptureType capture_type) {
@@ -439,6 +462,13 @@
 }
 #endif
 
+#if !defined(OS_ANDROID)
+void ChromeRenderFrameObserver::OnWebUITesterRequest(
+    chrome::mojom::WebUITesterAssociatedRequest request) {
+  web_ui_tester_bindings_.AddBinding(this, std::move(request));
+}
+#endif
+
 void ChromeRenderFrameObserver::OnThumbnailCapturerRequest(
     chrome::mojom::ThumbnailCapturerRequest request) {
   thumbnail_capturer_bindings_.AddBinding(this, std::move(request));
diff --git a/chrome/renderer/chrome_render_frame_observer.h b/chrome/renderer/chrome_render_frame_observer.h
index 5261aaa9..abae87f 100644
--- a/chrome/renderer/chrome_render_frame_observer.h
+++ b/chrome/renderer/chrome_render_frame_observer.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/timer/timer.h"
+#include "build/build_config.h"
 #include "chrome/common/image_context_menu_renderer.mojom.h"
 #include "chrome/common/prerender_types.h"
 #include "chrome/common/thumbnail_capturer.mojom.h"
@@ -18,6 +19,11 @@
 #include "chrome/common/safe_browsing/phishing_detector.mojom.h"
 #endif
 
+#if !defined(OS_ANDROID)
+#include "chrome/common/web_ui_tester.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
+#endif
+
 namespace gfx {
 class Size;
 }
@@ -38,6 +44,9 @@
 #if defined(SAFE_BROWSING_CSD)
       public chrome::mojom::PhishingDetector,
 #endif
+#if !defined(OS_ANDROID)
+      public chrome::mojom::WebUITester,
+#endif
       public chrome::mojom::ThumbnailCapturer {
  public:
   explicit ChromeRenderFrameObserver(content::RenderFrame* render_frame);
@@ -68,6 +77,11 @@
   void SetClientSidePhishingDetection(bool enable_phishing_detection) override;
 #endif
 
+#if !defined(OS_ANDROID)
+  // chrome::mojom::WebUITester:
+  void ExecuteWebUIJavaScript(const base::string16& javascript) override;
+#endif
+
   // chrome::mojom::ThumbnailCapturer:
   void RequestThumbnailForContextNode(
       int32_t thumbnail_min_area_pixels,
@@ -82,6 +96,10 @@
   void OnPhishingDetectorRequest(
       chrome::mojom::PhishingDetectorRequest request);
 #endif
+#if !defined(OS_ANDROID)
+  void OnWebUITesterRequest(
+      chrome::mojom::WebUITesterAssociatedRequest request);
+#endif
   void OnThumbnailCapturerRequest(
       chrome::mojom::ThumbnailCapturerRequest request);
 
@@ -116,6 +134,13 @@
   mojo::BindingSet<chrome::mojom::PhishingDetector> phishing_detector_bindings_;
 #endif
 
+#if !defined(OS_ANDROID)
+  // Save the JavaScript to preload if ExecuteWebUIJavaScript is invoked.
+  std::vector<base::string16> webui_javascript_;
+  mojo::AssociatedBindingSet<chrome::mojom::WebUITester>
+      web_ui_tester_bindings_;
+#endif
+
   mojo::BindingSet<chrome::mojom::ThumbnailCapturer>
       thumbnail_capturer_bindings_;
 
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index 5445f7fb..8317a4c 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -52,9 +52,6 @@
 bool ChromeRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(ChromeRenderViewObserver, message)
-#if !defined(OS_ANDROID)
-    IPC_MESSAGE_HANDLER(ChromeViewMsg_WebUIJavaScript, OnWebUIJavaScript)
-#endif
 #if defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_UpdateBrowserControlsState,
                         OnUpdateBrowserControlsState)
@@ -66,13 +63,6 @@
   return handled;
 }
 
-#if !defined(OS_ANDROID)
-void ChromeRenderViewObserver::OnWebUIJavaScript(
-    const base::string16& javascript) {
-  webui_javascript_.push_back(javascript);
-}
-#endif
-
 #if defined(OS_ANDROID)
 void ChromeRenderViewObserver::OnUpdateBrowserControlsState(
     content::BrowserControlsState constraints,
@@ -95,19 +85,6 @@
     web_cache_impl_->ExecutePendingClearCache();
 }
 
-void ChromeRenderViewObserver::DidCommitProvisionalLoad(
-    blink::WebLocalFrame* frame,
-    bool is_new_navigation) {
-  auto* render_frame = content::RenderFrame::FromWebFrame(frame);
-  if (render_frame->IsMainFrame() &&
-      (render_frame->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) &&
-      !webui_javascript_.empty()) {
-    for (const auto& script : webui_javascript_)
-      render_view()->GetMainRenderFrame()->ExecuteJavaScript(script);
-    webui_javascript_.clear();
-  }
-}
-
 void ChromeRenderViewObserver::OnDestruct() {
   delete this;
 }
diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h
index 5609f10..4adb5772 100644
--- a/chrome/renderer/chrome_render_view_observer.h
+++ b/chrome/renderer/chrome_render_view_observer.h
@@ -35,14 +35,9 @@
  private:
   // RenderViewObserver implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
-  void DidCommitProvisionalLoad(blink::WebLocalFrame* frame,
-                                bool is_new_navigation) override;
   void Navigate(const GURL& url) override;
   void OnDestruct() override;
 
-#if !defined(OS_ANDROID)
-  void OnWebUIJavaScript(const base::string16& javascript);
-#endif
 #if defined(OS_ANDROID)
   void OnUpdateBrowserControlsState(content::BrowserControlsState constraints,
                                     content::BrowserControlsState current,
@@ -53,9 +48,6 @@
   // Determines if a host is in the strict security host set.
   bool IsStrictSecurityHost(const std::string& host);
 
-  // Save the JavaScript to preload if a ViewMsg_WebUIJavaScript is received.
-  std::vector<base::string16> webui_javascript_;
-
   // Owned by ChromeContentRendererClient and outlive us.
   web_cache::WebCacheImpl* web_cache_impl_;
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 50202f6..584cc15 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4971,6 +4971,7 @@
       "../browser/ui/app_list/extension_app_model_builder_unittest.cc",
       "../browser/ui/app_list/profile_loader_unittest.cc",
       "../browser/ui/app_list/search/answer_card/answer_card_result_unittest.cc",
+      "../browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc",
       "../browser/ui/app_list/search/app_search_provider_unittest.cc",
       "../browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc",
       "../browser/ui/app_list/search/history_unittest.cc",
diff --git a/chrome/test/data/webui/settings/category_default_setting_tests.js b/chrome/test/data/webui/settings/category_default_setting_tests.js
index 081221f..74d49a9 100644
--- a/chrome/test/data/webui/settings/category_default_setting_tests.js
+++ b/chrome/test/data/webui/settings/category_default_setting_tests.js
@@ -16,65 +16,6 @@
    */
   var browserProxy = null;
 
-  /**
-   * An example pref where the location category is disabled.
-   * @type {SiteSettingsPref}
-   */
-  var prefsLocationDisabled = {
-    defaults: {
-      geolocation: {
-        setting: 'block',
-      },
-    },
-    exceptions: {
-      geolocation: [],
-    },
-  };
-
-  /**
-   * An example pref where the location category is enabled.
-   * @type {SiteSettingsPref}
-   */
-  var prefsLocationEnabled = {
-    defaults: {
-      geolocation: {
-        setting: 'allow',
-      },
-    },
-    exceptions: {
-      geolocation: [],
-    },
-  };
-
-  /**
-   * An example pref where the Flash category is set on detect mode.
-   */
-  var prefsFlashDetect = {
-    defaults: {
-      plugins: {
-        setting: 'detect_important_content',
-      },
-    },
-    exceptions: {
-      plugins: [],
-    },
-  };
-
-  /**
-   * An example pref where the Cookies category is set to delete when
-   * session ends.
-   */
-  var prefsCookesSessionOnly = {
-    defaults: {
-      cookies: {
-        setting: 'session_only',
-      },
-    },
-    exceptions: {
-      cookies: [],
-    },
-  };
-
   // Initialize a site-settings-category before each test.
   setup(function() {
     browserProxy = new TestSiteSettingsPrefsBrowserProxy();
@@ -93,36 +34,109 @@
         });
   });
 
-  function testCategoryEnabled(testElement, enabled) {
+  // Verifies that the widget works as expected for a given |category|, initial
+  // |prefs|, and given expectations.
+  function testCategoryEnabled(
+      testElement, category, prefs, expectedEnabled,
+      expectedEnabledContentSetting) {
     browserProxy.reset();
-    browserProxy.setPrefs(
-        enabled ? prefsLocationEnabled : prefsLocationDisabled);
+    browserProxy.setPrefs(prefs);
 
-    testElement.category = settings.ContentSettingsTypes.GEOLOCATION;
+    testElement.category = category;
     return browserProxy.whenCalled('getDefaultValueForContentType')
         .then(function(contentType) {
-          assertEquals(settings.ContentSettingsTypes.GEOLOCATION, contentType);
-          assertEquals(enabled, testElement.categoryEnabled);
+          assertEquals(category, contentType);
+          assertEquals(expectedEnabled, testElement.categoryEnabled);
           browserProxy.resetResolver('setDefaultValueForContentType');
           MockInteractions.tap(testElement.$.toggle.$.control);
           return browserProxy.whenCalled('setDefaultValueForContentType');
         })
         .then(function(args) {
-          assertEquals(settings.ContentSettingsTypes.GEOLOCATION, args[0]);
-          assertEquals(
-              enabled ? settings.ContentSetting.BLOCK :
-                        settings.ContentSetting.ASK,
-              args[1]);
-          assertNotEquals(enabled, testElement.categoryEnabled);
+          assertEquals(category, args[0]);
+          var oppositeSetting = expectedEnabled ?
+              settings.ContentSetting.BLOCK :
+              expectedEnabledContentSetting;
+          assertEquals(oppositeSetting, args[1]);
+          assertNotEquals(expectedEnabled, testElement.categoryEnabled);
         });
   }
 
   test('categoryEnabled correctly represents prefs (enabled)', function() {
-    return testCategoryEnabled(testElement, true);
+    /**
+     * An example pref where the location category is enabled.
+     * @type {SiteSettingsPref}
+     */
+    var prefsLocationEnabled = {
+      defaults: {
+        geolocation: {
+          setting: 'allow',
+        },
+      },
+    };
+
+    return testCategoryEnabled(
+        testElement, settings.ContentSettingsTypes.GEOLOCATION,
+        prefsLocationEnabled, true, settings.ContentSetting.ASK);
   });
 
   test('categoryEnabled correctly represents prefs (disabled)', function() {
-    return testCategoryEnabled(testElement, false);
+    /**
+     * An example pref where the location category is disabled.
+     * @type {SiteSettingsPref}
+     */
+    var prefsLocationDisabled = {
+      defaults: {
+        geolocation: {
+          setting: 'block',
+        },
+      },
+    };
+
+    return testCategoryEnabled(
+        testElement, settings.ContentSettingsTypes.GEOLOCATION,
+        prefsLocationDisabled, false, settings.ContentSetting.ASK);
+  });
+
+  test('test Flash content setting in DETECT/ASK setting', function() {
+    var prefsFlash = {
+      defaults: {
+        plugins: {
+          setting: 'detect_important_content',
+        },
+      },
+    };
+
+    return testCategoryEnabled(
+        testElement, settings.ContentSettingsTypes.PLUGINS, prefsFlash, true,
+        settings.ContentSetting.IMPORTANT_CONTENT);
+  });
+
+  test('test Flash content setting in legacy ALLOW setting', function() {
+    var prefsFlash = {
+      defaults: {
+        plugins: {
+          setting: 'allow',
+        },
+      },
+    };
+
+    return testCategoryEnabled(
+        testElement, settings.ContentSettingsTypes.PLUGINS, prefsFlash, true,
+        settings.ContentSetting.IMPORTANT_CONTENT);
+  });
+
+  test('test Flash content setting in BLOCK setting', function() {
+    var prefsFlash = {
+      defaults: {
+        plugins: {
+          setting: 'block',
+        },
+      },
+    };
+
+    return testCategoryEnabled(
+        testElement, settings.ContentSettingsTypes.PLUGINS, prefsFlash, false,
+        settings.ContentSetting.IMPORTANT_CONTENT);
   });
 
   function testTristateCategory(
@@ -229,15 +243,21 @@
         });
   }
 
-  test('test special tri-state Flash category', function() {
-    return testTristateCategory(
-        prefsFlashDetect, settings.ContentSettingsTypes.PLUGINS,
-        settings.ContentSetting.IMPORTANT_CONTENT, '#subOptionToggle');
-  });
-
   test('test special tri-state Cookies category', function() {
+    /**
+     * An example pref where the Cookies category is set to delete when
+     * session ends.
+     */
+    var prefsCookiesSessionOnly = {
+      defaults: {
+        cookies: {
+          setting: 'session_only',
+        },
+      },
+    };
+
     return testTristateCategory(
-        prefsCookesSessionOnly, settings.ContentSettingsTypes.COOKIES,
+        prefsCookiesSessionOnly, settings.ContentSettingsTypes.COOKIES,
         settings.ContentSetting.SESSION_ONLY, '#subOptionToggle');
   });
 });
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 295c997..453bf3a8 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1701,6 +1701,36 @@
   mocha.run();
 });
 
+/**
+ * @constructor
+ * @extends {CrSettingsBrowserTest}
+ */
+function CrSettingsGoogleAssistantPageTest() {}
+
+CrSettingsGoogleAssistantPageTest.prototype = {
+  __proto__: CrSettingsBrowserTest.prototype,
+
+  /** @override */
+  browsePreload:
+      'chrome://md-settings/google_assistant_page/google_assistant_page.html',
+
+  /** @override */
+  commandLineSwitches: [{
+    switchName: 'enable-voice-interaction',
+  }],
+
+  /** @override */
+  extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([
+    ROOT_PATH + 'ui/webui/resources/js/promise_resolver.js',
+    '../test_browser_proxy.js',
+    'google_assistant_page_test.js',
+  ]),
+};
+
+TEST_F('CrSettingsGoogleAssistantPageTest', 'All', function() {
+  mocha.run();
+});
+
 GEN('#endif');
 
 /**
diff --git a/chrome/test/data/webui/settings/google_assistant_page_test.js b/chrome/test/data/webui/settings/google_assistant_page_test.js
new file mode 100644
index 0000000..b2b41b2
--- /dev/null
+++ b/chrome/test/data/webui/settings/google_assistant_page_test.js
@@ -0,0 +1,111 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @implements {settings.GoogleAssistantBrowserProxy}
+ */
+class TestGoogleAssistantBrowserProxy extends TestBrowserProxy {
+  constructor() {
+    super([
+      'setGoogleAssistantEnabled',
+      'setGoogleAssistantContextEnabled',
+      'showGoogleAssistantSettings',
+    ]);
+  }
+
+  /** @override */
+  setGoogleAssistantEnabled(enabled) {
+    this.methodCalled('setGoogleAssistantEnabled', enabled);
+  }
+
+  /** @override */
+  setGoogleAssistantContextEnabled(enabled) {
+    this.methodCalled('setGoogleAssistantContextEnabled', enabled);
+  }
+
+  /** @override */
+  showGoogleAssistantSettings() {
+    this.methodCalled('showGoogleAssistantSettings');
+  }
+}
+
+suite('GoogleAssistantHandler', function() {
+
+  /** @type {SettingsGoogleAssistantPageElement} */
+  var page = null;
+
+  /** @type {?TestGoogleAssistantBrowserProxy} */
+  var browserProxy = null;
+
+  setup(function() {
+    browserProxy = new TestGoogleAssistantBrowserProxy();
+    settings.GoogleAssistantBrowserProxyImpl.instance_ = browserProxy;
+
+    PolymerTest.clearBody();
+
+    var prefElement = document.createElement('settings-prefs');
+    document.body.appendChild(prefElement);
+
+    return CrSettingsPrefs.initialized.then(function() {
+      page = document.createElement('settings-google-assistant-page');
+      page.prefs = prefElement.prefs;
+      document.body.appendChild(page);
+    });
+  });
+
+  teardown(function() {
+    page.remove();
+  });
+
+  test('toggleAssistant', function() {
+    Polymer.dom.flush();
+    var button = page.$$('#googleAssistantEnable');
+    assertTrue(!!button);
+    assertFalse(button.disabled);
+    assertFalse(button.checked);
+
+    // Tap the enable toggle button and ensure the state becomes enabled.
+    MockInteractions.tap(button.$.control);
+    Polymer.dom.flush();
+    assertTrue(button.checked);
+    return browserProxy.whenCalled('setGoogleAssistantEnabled')
+        .then(function(arg) {
+          assertTrue(arg);
+        });
+  });
+
+  test('toggleAssistantContext', function() {
+    var button = page.$$('#googleAssistantContextEnable');
+    assertFalse(!!button);
+    page.setPrefValue('settings.voice_interaction.enabled', true);
+    Polymer.dom.flush();
+    button = page.$$('#googleAssistantContextEnable');
+    assertTrue(!!button);
+    assertFalse(button.disabled);
+    assertFalse(button.checked);
+
+    MockInteractions.tap(button.$.control);
+    Polymer.dom.flush();
+    assertTrue(button.checked);
+    return browserProxy.whenCalled('setGoogleAssistantContextEnabled')
+        .then(function(arg) {
+          assertTrue(arg);
+        });
+    ;
+  });
+
+  test('tapOnAssistantSettings', function() {
+    var button = page.$$('#googleAssistantSettings');
+    assertFalse(!!button);
+    page.setPrefValue('settings.voice_interaction.enabled', true);
+    Polymer.dom.flush();
+    button = page.$$('#googleAssistantSettings');
+    assertTrue(!!button);
+
+    MockInteractions.tap(button);
+    Polymer.dom.flush();
+    return browserProxy.whenCalled('showGoogleAssistantSettings');
+  });
+
+});
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index fb8adec..df91ada4 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -31,6 +31,7 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/class_property.h"
+#include "ui/compositor/compositor.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/path.h"
@@ -50,6 +51,12 @@
 // Application Id set by the client.
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kApplicationIdKey, nullptr);
 
+// Maximum amount of time to wait until the window is resized
+// to match the display's orientation in tablet mode.
+// TODO(oshima): Looks like android is generating unnecessary frames.
+// Fix it on Android side and reduce the timeout.
+constexpr int kRotationLockTimeoutMs = 2500;
+
 // This is a struct for accelerator keys used to close ShellSurfaces.
 const struct Accelerator {
   ui::KeyboardCode keycode;
@@ -196,6 +203,12 @@
   DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget);
 };
 
+Orientation SizeToOrientation(const gfx::Size& size) {
+  DCHECK_NE(size.width(), size.height());
+  return size.width() > size.height() ? Orientation::LANDSCAPE
+                                      : Orientation::PORTRAIT;
+}
+
 }  // namespace
 
 // Helper class used to coalesce a number of changes into one "configure"
@@ -301,6 +314,7 @@
       container_(container) {
   WMHelper::GetInstance()->AddActivationObserver(this);
   WMHelper::GetInstance()->AddDisplayConfigurationObserver(this);
+  display::Screen::GetScreen()->AddObserver(this);
   surface->AddSurfaceObserver(this);
   SetRootSurface(surface);
   host_window()->Show();
@@ -334,6 +348,7 @@
   }
   WMHelper::GetInstance()->RemoveActivationObserver(this);
   WMHelper::GetInstance()->RemoveDisplayConfigurationObserver(this);
+  display::Screen::GetScreen()->RemoveObserver(this);
   if (parent_)
     parent_->RemoveObserver(this);
   if (root_surface())
@@ -462,6 +477,10 @@
 void ShellSurface::SetSystemUiVisibility(bool autohide) {
   TRACE_EVENT1("exo", "ShellSurface::SetSystemUiVisibility", "autohide",
                autohide);
+
+  if (!widget_)
+    CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL);
+
   ash::wm::SetAutoHideShelf(widget_->GetNativeWindow(), autohide);
 }
 
@@ -595,6 +614,12 @@
   pending_geometry_ = geometry;
 }
 
+void ShellSurface::SetOrientation(Orientation orientation) {
+  TRACE_EVENT1("exo", "ShellSurface::SetOrientation", "orientation",
+               orientation == Orientation::PORTRAIT ? "portrait" : "landscape");
+  pending_orientation_ = orientation;
+}
+
 void ShellSurface::SetRectangularShadowEnabled(bool enabled) {
   TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadowEnabled", "enabled",
                enabled);
@@ -770,6 +795,11 @@
       if (container_ == ash::kShellWindowId_SystemModalContainer)
         UpdateSystemModal();
     }
+    orientation_ = pending_orientation_;
+    if (expected_orientation_ == orientation_)
+      compositor_lock_.reset();
+  } else {
+    compositor_lock_.reset();
   }
 }
 
@@ -979,7 +1009,7 @@
 
     // The shadow size may be updated to match the widget. Change it back
     // to the shadow content size.
-    // TODO(oshima): When the arc window reiszing is enabled, we may want to
+    // TODO(oshima): When the window reiszing is enabled, we may want to
     // implement shadow management here instead of using shadow controller.
     UpdateShadow();
 
@@ -1081,6 +1111,38 @@
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// display::DisplayObserver overrides:
+
+void ShellSurface::OnDisplayMetricsChanged(const display::Display& new_display,
+                                           uint32_t changed_metrics) {
+  if (!widget_ || !widget_->IsActive() || bounds_mode_ != BoundsMode::CLIENT ||
+      !WMHelper::GetInstance()->IsTabletModeWindowManagerEnabled()) {
+    return;
+  }
+
+  const display::Screen* screen = display::Screen::GetScreen();
+  display::Display current_display =
+      screen->GetDisplayNearestWindow(widget_->GetNativeWindow());
+  if (current_display.id() != new_display.id() ||
+      !(changed_metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION)) {
+    return;
+  }
+
+  Orientation target_orientation = SizeToOrientation(new_display.size());
+  if (orientation_ == target_orientation)
+    return;
+  expected_orientation_ = target_orientation;
+  EnsureCompositorIsLocked();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ui::CompositorLockClient overrides:
+
+void ShellSurface::CompositorLockTimedOut() {
+  compositor_lock_.reset();
+}
+
 void ShellSurface::OnMouseEvent(ui::MouseEvent* event) {
   if (!resizer_) {
     views::View::OnMouseEvent(event);
@@ -1721,4 +1783,13 @@
   return location;
 }
 
+void ShellSurface::EnsureCompositorIsLocked() {
+  if (!compositor_lock_) {
+    ui::Compositor* compositor =
+      widget_->GetNativeWindow()->layer()->GetCompositor();
+    compositor_lock_ = compositor->GetCompositorLock(
+        this, base::TimeDelta::FromMilliseconds(kRotationLockTimeoutMs));
+  }
+}
+
 }  // namespace exo
diff --git a/components/exo/shell_surface.h b/components/exo/shell_surface.h
index fc96631d..e3739d4d 100644
--- a/components/exo/shell_surface.h
+++ b/components/exo/shell_surface.h
@@ -17,6 +17,8 @@
 #include "components/exo/surface_tree_host.h"
 #include "components/exo/wm_helper.h"
 #include "ui/base/hit_test.h"
+#include "ui/compositor/compositor_lock.h"
+#include "ui/display/display_observer.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d.h"
@@ -35,9 +37,15 @@
 }
 }
 
+namespace ui {
+class CompositorLock;
+}  // namespace ui
+
 namespace exo {
 class Surface;
 
+enum class Orientation { PORTRAIT, LANDSCAPE };
+
 // This class provides functions for treating a surfaces like toplevel,
 // fullscreen or popup widgets, move, resize or maximize them, associate
 // metadata like title and class, etc.
@@ -45,9 +53,11 @@
                      public SurfaceObserver,
                      public views::WidgetDelegate,
                      public views::View,
+                     public display::DisplayObserver,
                      public ash::wm::WindowStateObserver,
                      public WMHelper::ActivationObserver,
-                     public WMHelper::DisplayConfigurationObserver {
+                     public WMHelper::DisplayConfigurationObserver,
+                     NON_EXPORTED_BASE(public ui::CompositorLockClient) {
  public:
   enum class BoundsMode { SHELL, CLIENT, FIXED };
 
@@ -171,6 +181,9 @@
   // for the surface from the user's perspective.
   void SetGeometry(const gfx::Rect& geometry);
 
+  // Set orientation for surface.
+  void SetOrientation(Orientation orientation);
+
   // Enable/disable rectangular shadow that uses the widget bounds as a content
   // bounds.
   void SetRectangularShadowEnabled(bool enabled);
@@ -277,6 +290,13 @@
   // Overridden from ui::AcceleratorTarget:
   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
 
+  // Overridden from display::DisplayObserver:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t changed_metrics) override;
+
+  // Ovrridden ui::CompositorLockClient:
+  void CompositorLockTimedOut() override;
+
   aura::Window* shadow_overlay() { return shadow_overlay_.get(); }
   aura::Window* shadow_underlay() { return shadow_underlay_.get(); }
 
@@ -336,6 +356,10 @@
   // In the coordinate system of the parent root window.
   gfx::Point GetMouseLocation() const;
 
+  // Lock the compositor if it's not already locked, or extends the
+  // lock timeout if it's already locked.
+  void EnsureCompositorIsLocked();
+
   views::Widget* widget_ = nullptr;
   aura::Window* parent_;
   const BoundsMode bounds_mode_;
@@ -376,6 +400,10 @@
   int pending_top_inset_height_ = 0;
   bool shadow_underlay_in_surface_ = true;
   bool pending_shadow_underlay_in_surface_ = true;
+  Orientation pending_orientation_ = Orientation::LANDSCAPE;
+  Orientation orientation_ = Orientation::LANDSCAPE;
+  Orientation expected_orientation_ = Orientation::LANDSCAPE;
+  std::unique_ptr<ui::CompositorLock> compositor_lock_;
   bool system_modal_ = false;
   gfx::ImageSkia icon_;
 
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc
index ab98dd9..04858f14 100644
--- a/components/exo/shell_surface_unittest.cc
+++ b/components/exo/shell_surface_unittest.cc
@@ -11,11 +11,13 @@
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/shell_test_api.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
 #include "ash/wm/workspace_controller_test_api.h"
 #include "base/message_loop/message_loop.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/exo/buffer.h"
 #include "components/exo/display.h"
@@ -27,6 +29,8 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/base/hit_test.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/layer.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/views/widget/widget.h"
@@ -1003,5 +1007,43 @@
   ash::wm::GetWindowState(window)->OnWMEvent(&minimize_event);
 }
 
+TEST_F(ShellSurfaceTest, CompositorLockInRotation) {
+  UpdateDisplay("800x600");
+  const gfx::Size buffer_size(800, 600);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  std::unique_ptr<Surface> surface(new Surface);
+  std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(
+      surface.get(), nullptr, ShellSurface::BoundsMode::CLIENT, gfx::Point(),
+      true, false, ash::kShellWindowId_DefaultContainer));
+  ash::Shell* shell = ash::Shell::Get();
+  shell->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+
+  // Start in maximized.
+  shell_surface->Maximize();
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  gfx::Rect maximum_bounds =
+      display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
+  shell_surface->SetGeometry(maximum_bounds);
+  shell_surface->SetOrientation(Orientation::LANDSCAPE);
+  surface->Commit();
+
+  ui::Compositor* compositor =
+      shell_surface->GetWidget()->GetNativeWindow()->layer()->GetCompositor();
+
+  EXPECT_FALSE(compositor->IsLocked());
+
+  UpdateDisplay("800x600/r");
+
+  EXPECT_TRUE(compositor->IsLocked());
+
+  shell_surface->SetOrientation(Orientation::PORTRAIT);
+  surface->Commit();
+
+  EXPECT_FALSE(compositor->IsLocked());
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index ddaacaa..822682f 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -2047,6 +2047,15 @@
       gfx::Rect(x, y, width, height));
 }
 
+void remote_surface_set_orientation(wl_client* client,
+                                    wl_resource* resource,
+                                    int32_t orientation) {
+  GetUserDataAs<ShellSurface>(resource)->SetOrientation(
+      orientation == ZCR_REMOTE_SURFACE_V1_ORIENTATION_PORTRAIT
+          ? Orientation::PORTRAIT
+          : Orientation::LANDSCAPE);
+}
+
 void remote_surface_set_scale(wl_client* client,
                               wl_resource* resource,
                               wl_fixed_t scale) {
@@ -2221,7 +2230,8 @@
     remote_surface_set_always_on_top,
     remote_surface_unset_always_on_top,
     remote_surface_ack_configure,
-    remote_surface_move};
+    remote_surface_move,
+    remote_surface_set_orientation};
 
 ////////////////////////////////////////////////////////////////////////////////
 // notification_surface_interface:
@@ -2574,7 +2584,7 @@
     remote_shell_destroy, remote_shell_get_remote_surface,
     remote_shell_get_notification_surface};
 
-const uint32_t remote_shell_version = 5;
+const uint32_t remote_shell_version = 6;
 
 void bind_remote_shell(wl_client* client,
                        void* data,
diff --git a/components/safe_browsing/web_ui/resources/safe_browsing.js b/components/safe_browsing/web_ui/resources/safe_browsing.js
index 4bc04309..d6be52b4 100644
--- a/components/safe_browsing/web_ui/resources/safe_browsing.js
+++ b/components/safe_browsing/web_ui/resources/safe_browsing.js
@@ -15,7 +15,7 @@
         addExperiments(experiments));
     cr.sendWithPromise('getPrefs', []).then((prefs) => addPrefs(prefs));
     cr.sendWithPromise('getDatabaseManagerInfo', []).then(
-        (databaseState) => addDatabaseInfo(databaseState));
+        (databaseState) => addDatabaseManagerInfo(databaseState));
   }
 
   function addExperiments(result) {
@@ -26,7 +26,6 @@
       experimentsListFormatted += "<div><b>" + result[i + 1] +
           "</b>: " + result[i] + "</div>";
       }
-
       $('experiments-list').innerHTML = experimentsListFormatted;
   }
 
@@ -42,7 +41,7 @@
   }
 
 
-  function addDatabaseInfo(result) {
+  function addDatabaseManagerInfo(result) {
       var resLength = result.length;
       var preferencesListFormatted = "";
 
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc
index 37ef94e..547222e0 100644
--- a/components/safe_browsing/web_ui/safe_browsing_ui.cc
+++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -31,6 +31,14 @@
 namespace safe_browsing {
 namespace {
 #if SAFE_BROWSING_DB_LOCAL
+
+base::Value UserReadableTimeFromMillisSinceEpoch(int64_t time_in_milliseconds) {
+  base::Time time = base::Time::UnixEpoch() +
+                    base::TimeDelta::FromMilliseconds(time_in_milliseconds);
+  return base::Value(
+      base::UTF16ToASCII(base::TimeFormatShortDateAndTime(time)));
+}
+
 void AddStoreInfo(const DatabaseManagerInfo::DatabaseInfo::StoreInfo store_info,
                   base::ListValue* database_info_list) {
   if (store_info.has_file_size_bytes() && store_info.has_file_name()) {
@@ -44,6 +52,18 @@
     database_info_list->GetList().push_back(
         base::Value(store_info.update_status()));
   }
+  if (store_info.has_last_apply_update_time_millis()) {
+    database_info_list->GetList().push_back(base::Value("Last update time"));
+    database_info_list->GetList().push_back(
+        UserReadableTimeFromMillisSinceEpoch(
+            store_info.last_apply_update_time_millis()));
+  }
+  if (store_info.has_checks_attempted()) {
+    database_info_list->GetList().push_back(
+        base::Value("Number of database checks"));
+    database_info_list->GetList().push_back(
+        base::Value(static_cast<int>(store_info.checks_attempted())));
+  }
 }
 
 void AddDatabaseInfo(const DatabaseManagerInfo::DatabaseInfo database_info,
@@ -72,12 +92,9 @@
   }
   if (update_info.has_last_update_time_millis()) {
     database_info_list->GetList().push_back(base::Value("Last update time"));
-    // Converts time to Base::Time
-    base::Time last_update =
-        base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(
-                                      update_info.last_update_time_millis());
-    database_info_list->GetList().push_back(base::Value(
-        base::UTF16ToASCII(base::TimeFormatShortDateAndTime(last_update))));
+    database_info_list->GetList().push_back(
+        UserReadableTimeFromMillisSinceEpoch(
+            update_info.last_update_time_millis()));
   }
 }
 #endif
diff --git a/components/safe_browsing/web_ui/webui.proto b/components/safe_browsing/web_ui/webui.proto
index 52a9255..bc0e96e7 100644
--- a/components/safe_browsing/web_ui/webui.proto
+++ b/components/safe_browsing/web_ui/webui.proto
@@ -17,8 +17,9 @@
     // Network status code for the last update request sent to SafeBrowsing.
     optional int32 network_status_code = 1;
 
-    // Time when the last update request was sent to SafeBrowsing.
-    optional int64 last_update_time_millis = 2;
+    // The time, since epoch, when the last update request was sent to
+    // SafeBrowsing.
+    optional uint64 last_update_time_millis = 2;
   }
 
   optional UpdateInfo update_info = 1;
@@ -29,7 +30,7 @@
     optional bool update_successful = 1;
 
     // Sum of the store sizes in the database.
-    optional int64 database_size_bytes = 2;
+    optional uint64 database_size_bytes = 2;
 
     // Describes the state of a store in the database.
     message StoreInfo {
@@ -43,6 +44,12 @@
       // store. The values of update_status corresponds to the enum
       // ApplyUpdateResult in V4Store.
       optional int32 update_status = 3;
+
+      // The time, since epoch, of applying the updates to the store.
+      optional uint64 last_apply_update_time_millis = 4;
+
+      // The number of times the store has been queried for a prefix.
+      optional uint32 checks_attempted = 5;
     }
 
     // Information about each of the stores managed by the database.
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc
index b1ab194..e7bce82 100644
--- a/components/safe_browsing_db/v4_store.cc
+++ b/components/safe_browsing_db/v4_store.cc
@@ -375,6 +375,8 @@
   if (apply_update_result == APPLY_UPDATE_SUCCESS) {
     new_store->has_valid_data_ = true;
     new_store->last_apply_update_result_ = apply_update_result;
+    new_store->last_apply_update_time_millis_ = base::Time::Now();
+    new_store->checks_attempted_ = checks_attempted_;
     RecordApplyUpdateTime(metric, TimeTicks::Now() - before, store_path_);
   } else {
     new_store.reset();
@@ -767,6 +769,7 @@
   // full hash. However, if that happens, this method returns any one of them.
   // It does not guarantee which one of those will be returned.
   DCHECK(full_hash.size() == 32u || full_hash.size() == 21u);
+  checks_attempted_++;
   for (const auto& pair : hash_prefix_map_) {
     const PrefixSize& prefix_size = pair.first;
     const HashPrefixes& hash_prefixes = pair.second;
@@ -874,8 +877,12 @@
     const std::string& base_metric) {
   store_info->set_file_name(base_metric + GetUmaSuffixForStore(store_path_));
   store_info->set_file_size_bytes(file_size_);
-
   store_info->set_update_status(static_cast<int>(last_apply_update_result_));
+  store_info->set_checks_attempted(checks_attempted_);
+  if (last_apply_update_time_millis_.ToJavaTime()) {
+    store_info->set_last_apply_update_time_millis(
+        last_apply_update_time_millis_.ToJavaTime());
+  }
 }
 
 }  // namespace safe_browsing
diff --git a/components/safe_browsing_db/v4_store.h b/components/safe_browsing_db/v4_store.h
index e4ca305..3ebd47a 100644
--- a/components/safe_browsing_db/v4_store.h
+++ b/components/safe_browsing_db/v4_store.h
@@ -409,6 +409,9 @@
   // Records the status of the update being applied to the database.
   ApplyUpdateResult last_apply_update_result_ = APPLY_UPDATE_RESULT_MAX;
 
+  // Records the time when the store was last updated.
+  base::Time last_apply_update_time_millis_;
+
   // The checksum value as read from the disk, until it is verified. Once
   // verified, it is cleared.
   std::string expected_checksum_;
@@ -420,6 +423,9 @@
   // a full update.
   bool has_valid_data_;
 
+  // Records the number of times we have looked up the store.
+  size_t checks_attempted_ = 0;
+
   // The state of the store as returned by the PVer4 server in the last applied
   // update response.
   std::string state_;
diff --git a/components/ukm/BUILD.gn b/components/ukm/BUILD.gn
index 6dbee54..eb7723f 100644
--- a/components/ukm/BUILD.gn
+++ b/components/ukm/BUILD.gn
@@ -49,12 +49,14 @@
 
   public_deps = [
     "//base",
+    "//services/metrics/public/cpp:metrics_cpp",
     "//services/metrics/public/interfaces",
   ]
 
   deps = [
     ":ukm",
     "//mojo/public/cpp/bindings",
+    "//services/metrics/public/cpp:metrics_cpp",
   ]
 }
 
diff --git a/components/ukm/ukm_interface.cc b/components/ukm/ukm_interface.cc
index c0eb4de..3cc99a2 100644
--- a/components/ukm/ukm_interface.cc
+++ b/components/ukm/ukm_interface.cc
@@ -8,24 +8,11 @@
 #include "base/memory/ptr_util.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
 #include "url/gurl.h"
 
 namespace ukm {
 
-namespace {
-
-// Map source ids from different instances into unique namespaces, so that
-// clients can create thier own IDs without having them collide.
-// This won't be necessary once we switch to using CoordinationUnitIDs.
-int64_t ConvertSourceId(int64_t source_id, int64_t instance_id) {
-  const int64_t low_bits = (INT64_C(1) << 32) - 1;
-  // Neither ID should get large enough to cause an issue, but explicitly
-  // discard down to 32 bits anyway.
-  return ((instance_id & low_bits) << 32) | (source_id & low_bits);
-}
-
-}  // namespace
-
 UkmInterface::UkmInterface(UkmRecorder* ukm_recorder, int64_t instance_id)
     : ukm_recorder_(ukm_recorder), instance_id_(instance_id) {}
 
@@ -42,13 +29,14 @@
 }
 
 void UkmInterface::AddEntry(mojom::UkmEntryPtr ukm_entry) {
-  ukm_entry->source_id = ConvertSourceId(instance_id_, ukm_entry->source_id);
+  ukm_entry->source_id =
+      ConvertSourceIdFromInstance(instance_id_, ukm_entry->source_id);
   ukm_recorder_->AddEntry(std::move(ukm_entry));
 }
 
 void UkmInterface::UpdateSourceURL(int64_t source_id, const std::string& url) {
-  ukm_recorder_->UpdateSourceURL(ConvertSourceId(instance_id_, source_id),
-                                 GURL(url));
+  ukm_recorder_->UpdateSourceURL(
+      ConvertSourceIdFromInstance(instance_id_, source_id), GURL(url));
 }
 
 }  // namespace ukm
diff --git a/components/ukm/ukm_source.h b/components/ukm/ukm_source.h
index 928144b..307eda3 100644
--- a/components/ukm/ukm_source.h
+++ b/components/ukm/ukm_source.h
@@ -5,19 +5,17 @@
 #ifndef COMPONENTS_UKM_UKM_SOURCE_H_
 #define COMPONENTS_UKM_UKM_SOURCE_H_
 
-#include <stddef.h>
 #include <map>
 
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
 #include "url/gurl.h"
 
 namespace ukm {
 
 class Source;
 
-typedef int64_t SourceId;
-
 // Contains UKM data for a single navigation entry.
 class UkmSource {
  public:
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
index ab5f100..dfb242d 100644
--- a/components/viz/host/host_frame_sink_manager.cc
+++ b/components/viz/host/host_frame_sink_manager.cc
@@ -147,18 +147,17 @@
   // Find the expected embedder for the new surface and assign the temporary
   // reference to it.
   auto iter = frame_sink_data_map_.find(surface_id.frame_sink_id());
-  if (iter != frame_sink_data_map_.end()) {
-    const FrameSinkData& data = iter->second;
+  DCHECK(iter != frame_sink_data_map_.end());
+  const FrameSinkData& data = iter->second;
 
-    // Display roots don't have temporary references to assign.
-    if (data.is_root)
-      return;
+  // Display roots don't have temporary references to assign.
+  if (data.is_root)
+    return;
 
-    if (data.parent.has_value()) {
-      frame_sink_manager_impl_->AssignTemporaryReference(surface_id,
-                                                         data.parent.value());
-      return;
-    }
+  if (data.parent.has_value()) {
+    frame_sink_manager_impl_->AssignTemporaryReference(surface_id,
+                                                       data.parent.value());
+    return;
   }
 
   // We don't have any hierarchy information for what will embed the new
@@ -169,8 +168,12 @@
 void HostFrameSinkManager::OnSurfaceCreated(const SurfaceInfo& surface_info) {
   auto it = frame_sink_data_map_.find(surface_info.id().frame_sink_id());
   // If we've received a bogus or stale SurfaceId from Viz then just ignore it.
-  if (it == frame_sink_data_map_.end())
+  if (it == frame_sink_data_map_.end()) {
+    // We don't have any hierarchy information for what will embed the new
+    // surface, drop the temporary reference.
+    frame_sink_manager_->DropTemporaryReference(surface_info.id());
     return;
+  }
 
   FrameSinkData& frame_sink_data = it->second;
   if (frame_sink_data.client)
diff --git a/components/viz/host/host_frame_sink_manager_unittests.cc b/components/viz/host/host_frame_sink_manager_unittests.cc
index 298beed..b21ba8ab 100644
--- a/components/viz/host/host_frame_sink_manager_unittests.cc
+++ b/components/viz/host/host_frame_sink_manager_unittests.cc
@@ -235,6 +235,47 @@
   GetFrameSinkManagerClient()->OnSurfaceCreated(MakeSurfaceInfo(surface_id));
 }
 
+TEST_F(HostFrameSinkManagerTest, DropTemporaryReferenceForStaleClient) {
+  FakeHostFrameSinkClient client;
+  host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client);
+  auto support_client =
+      CreateCompositorFrameSinkSupport(kClientFrameSinkId, false /* is_root */);
+  EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId));
+
+  host_manager().RegisterFrameSinkId(kParentFrameSinkId, &client);
+  auto support_parent =
+      CreateCompositorFrameSinkSupport(kParentFrameSinkId, true /* is_root */);
+  EXPECT_TRUE(FrameSinkDataExists(kParentFrameSinkId));
+
+  // Register should call through to FrameSinkManagerImpl.
+  EXPECT_CALL(manager_impl(), RegisterFrameSinkHierarchy(kParentFrameSinkId,
+                                                         kClientFrameSinkId));
+  host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId,
+                                            kClientFrameSinkId);
+
+  const SurfaceId client_surface_id = MakeSurfaceId(kClientFrameSinkId, 1);
+  EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id))
+      .Times(0);
+  EXPECT_CALL(manager_impl(), AssignTemporaryReference(client_surface_id, _))
+      .Times(1);
+  GetFrameSinkManagerClient()->OnSurfaceCreated(
+      MakeSurfaceInfo(client_surface_id));
+  testing::Mock::VerifyAndClearExpectations(&manager_impl());
+
+  // Invaidating the client should cause the next SurfaceId to be dropped.
+  support_client.reset();
+  host_manager().InvalidateFrameSinkId(kClientFrameSinkId);
+
+  const SurfaceId client_surface_id2 = MakeSurfaceId(kClientFrameSinkId, 2);
+  EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id2))
+      .Times(1);
+  GetFrameSinkManagerClient()->OnSurfaceCreated(
+      MakeSurfaceInfo(client_surface_id2));
+
+  support_parent.reset();
+  host_manager().InvalidateFrameSinkId(kParentFrameSinkId);
+}
+
 TEST_F(HostFrameSinkManagerTest, DisplayRootTemporaryReference) {
   const SurfaceId surface_id = MakeSurfaceId(kParentFrameSinkId, 1);
   auto support = CreateCompositorFrameSinkSupport(surface_id.frame_sink_id(),
diff --git a/components/viz/service/surfaces/surface_manager.cc b/components/viz/service/surfaces/surface_manager.cc
index b3a8281..f56ba6b 100644
--- a/components/viz/service/surfaces/surface_manager.cc
+++ b/components/viz/service/surfaces/surface_manager.cc
@@ -194,10 +194,11 @@
 
 void SurfaceManager::DropTemporaryReference(const SurfaceId& surface_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
 
-  if (!HasTemporaryReference(surface_id))
+  if (lifetime_type_ != LifetimeType::REFERENCES ||
+      !HasTemporaryReference(surface_id)) {
     return;
+  }
 
   RemoveTemporaryReference(surface_id, false);
 }
diff --git a/components/web_contents_delegate_android/validation_message_bubble_android.cc b/components/web_contents_delegate_android/validation_message_bubble_android.cc
index 2f15a5e5..edfb81d0 100644
--- a/components/web_contents_delegate_android/validation_message_bubble_android.cc
+++ b/components/web_contents_delegate_android/validation_message_bubble_android.cc
@@ -14,13 +14,6 @@
 using base::android::ConvertUTF16ToJavaString;
 
 namespace {
-
-gfx::Rect ScaleToRoundedRect(const gfx::Rect& rect, float scale) {
-  gfx::RectF scaledRect(rect);
-  scaledRect.Scale(scale);
-  return ToNearestRect(scaledRect);
-}
-
 gfx::Size ScaleToRoundedSize(const gfx::SizeF& size, float scale) {
   return gfx::ToRoundedSize(gfx::ScaleSize(size, scale));
 }
@@ -55,7 +48,9 @@
 
   // Convert to physical unit before passing to Java.
   float scale = view->GetDipScale() * view->page_scale();
-  gfx::Rect anchor = ScaleToRoundedRect(anchor_in_screen, scale);
+  gfx::RectF anchor_f = gfx::RectF(anchor_in_screen);
+  anchor_f.Scale(scale);
+  gfx::Rect anchor = ToNearestRect(anchor_f);
   gfx::Size viewport = ScaleToRoundedSize(view->viewport_size(), scale);
 
   JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/content/browser/android/app_web_message_port.cc b/content/browser/android/app_web_message_port.cc
index 07fea5e..6925705 100644
--- a/content/browser/android/app_web_message_port.cc
+++ b/content/browser/android/app_web_message_port.cc
@@ -61,9 +61,10 @@
     const base::android::JavaParamRef<jobject>& jcaller,
     const base::android::JavaParamRef<jstring>& jmessage,
     const base::android::JavaParamRef<jobjectArray>& jports) {
-  port_.PostMessage(
-      EncodeStringMessage(base::android::ConvertJavaStringToUTF16(jmessage)),
-      UnwrapJavaArray(env, jports));
+  std::vector<uint8_t> encoded_message =
+      EncodeStringMessage(base::android::ConvertJavaStringToUTF16(jmessage));
+  port_.PostMessage(encoded_message.data(), encoded_message.size(),
+                    UnwrapJavaArray(env, jports));
 }
 
 jboolean AppWebMessagePort::DispatchNextMessage(
@@ -78,7 +79,7 @@
           env, org_chromium_content_browser_AppWebMessagePort_clazz(env),
           "<init>", "()V");
 
-  base::string16 encoded_message;
+  std::vector<uint8_t> encoded_message;
   std::vector<MessagePort> ports;
   if (!port_.GetMessage(&encoded_message, &ports))
     return false;
diff --git a/content/browser/android/string_message_codec.cc b/content/browser/android/string_message_codec.cc
index b2bae5dd..5303ac43 100644
--- a/content/browser/android/string_message_codec.cc
+++ b/content/browser/android/string_message_codec.cc
@@ -81,7 +81,7 @@
 
 } // namespace
 
-base::string16 EncodeStringMessage(const base::string16& data) {
+std::vector<uint8_t> EncodeStringMessage(const base::string16& data) {
   std::vector<uint8_t> buffer;
   WriteUint8(kVersionTag, &buffer);
   WriteUint32(kVersion, &buffer);
@@ -100,20 +100,13 @@
     WriteBytes(reinterpret_cast<const char*>(data.data()), num_bytes, &buffer);
   }
 
-  base::string16 result;
-  size_t result_num_bytes = (buffer.size() + 1) & ~1;
-  result.resize(result_num_bytes / 2);
-  uint8_t* destination = reinterpret_cast<uint8_t*>(&result[0]);
-  memcpy(destination, &buffer[0], buffer.size());
-  return result;
+  return buffer;
 }
 
-bool DecodeStringMessage(const base::string16& encoded_data,
+bool DecodeStringMessage(const std::vector<uint8_t>& encoded_data,
                          base::string16* result) {
-  size_t num_bytes = encoded_data.size() * 2;
-
-  const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&encoded_data[0]);
-  const uint8_t* end = ptr + num_bytes;
+  const uint8_t* ptr = encoded_data.data();
+  const uint8_t* end = ptr + encoded_data.size();
   uint8_t tag;
 
   // Discard any leading version and padding tags.
diff --git a/content/browser/android/string_message_codec.h b/content/browser/android/string_message_codec.h
index 94f18c2d..a613f05 100644
--- a/content/browser/android/string_message_codec.h
+++ b/content/browser/android/string_message_codec.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_ANDROID_STRING_MESSAGE_CODEC_H_
 #define CONTENT_BROWSER_ANDROID_STRING_MESSAGE_CODEC_H_
 
+#include <vector>
 #include "base/strings/string16.h"
 #include "content/common/content_export.h"
 
@@ -20,10 +21,12 @@
 // handle string messages and this serialization format is static, as it is a
 // format we currently persist to disk via IndexedDB.
 
-CONTENT_EXPORT base::string16 EncodeStringMessage(const base::string16& data);
+CONTENT_EXPORT std::vector<uint8_t> EncodeStringMessage(
+    const base::string16& data);
 
-CONTENT_EXPORT bool DecodeStringMessage(const base::string16& encoded_data,
-                                        base::string16* result);
+CONTENT_EXPORT bool DecodeStringMessage(
+    const std::vector<uint8_t>& encoded_data,
+    base::string16* result);
 
 }  // namespace content
 
diff --git a/content/browser/android/string_message_codec_unittest.cc b/content/browser/android/string_message_codec_unittest.cc
index fc3e2c3..00a85ba0 100644
--- a/content/browser/android/string_message_codec_unittest.cc
+++ b/content/browser/android/string_message_codec_unittest.cc
@@ -12,7 +12,7 @@
 namespace content {
 namespace {
 
-base::string16 DecodeWithV8(const base::string16& encoded) {
+base::string16 DecodeWithV8(const std::vector<uint8_t>& encoded) {
   base::test::ScopedAsyncTaskScheduler task_scheduler;
   base::string16 result;
 
@@ -26,10 +26,7 @@
 
     v8::Local<v8::Context> context = v8::Context::New(isolate);
 
-    v8::ValueDeserializer deserializer(
-        isolate,
-        reinterpret_cast<const uint8_t*>(encoded.data()),
-        encoded.size() * sizeof(base::char16));
+    v8::ValueDeserializer deserializer(isolate, encoded.data(), encoded.size());
     deserializer.SetSupportsLegacyWireFormat(true);
 
     EXPECT_TRUE(deserializer.ReadHeader(context).ToChecked());
@@ -47,9 +44,9 @@
   return result;
 }
 
-base::string16 EncodeWithV8(const base::string16& message) {
+std::vector<uint8_t> EncodeWithV8(const base::string16& message) {
   base::test::ScopedAsyncTaskScheduler task_scheduler;
-  base::string16 result;
+  std::vector<uint8_t> result;
 
   v8::Isolate::CreateParams params;
   params.array_buffer_allocator =
@@ -72,11 +69,7 @@
     EXPECT_TRUE(serializer.WriteValue(context, message_as_value).ToChecked());
 
     std::pair<uint8_t*, size_t> buffer = serializer.Release();
-
-    size_t result_num_bytes = (buffer.second + 1) & ~1;
-    result.resize(result_num_bytes / 2);
-    memcpy(reinterpret_cast<uint8_t*>(&result[0]), buffer.first, buffer.second);
-
+    result = std::vector<uint8_t>(buffer.first, buffer.first + buffer.second);
     free(buffer.first);
   }
   isolate->Dispose();
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc
index 1d2bc41..9da4a8e 100644
--- a/content/browser/compositor/reflector_impl_unittest.cc
+++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -143,7 +143,8 @@
     compositor_.reset(new ui::Compositor(
         context_factory_private->AllocateFrameSinkId(), context_factory,
         context_factory_private, compositor_task_runner_.get(),
-        false /* enable_surface_synchronization */));
+        false /* enable_surface_synchronization */,
+        false /* enable_pixel_canvas */));
     compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
 
     auto context_provider = cc::TestContextProvider::Create();
diff --git a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
index 522efa0..9cf29d5f 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
+++ b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
@@ -104,7 +104,8 @@
   compositor_.reset(new ui::Compositor(
       context_factory_private->AllocateFrameSinkId(), context_factory,
       context_factory_private, message_loop_.task_runner().get(),
-      false /* enable_surface_synchronization */));
+      false /* enable_surface_synchronization */,
+      false /* enable_pixel_canvas */));
   compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
 }
 
diff --git a/content/browser/compositor/software_output_device_ozone_unittest.cc b/content/browser/compositor/software_output_device_ozone_unittest.cc
index af3e1574..2b34384e 100644
--- a/content/browser/compositor/software_output_device_ozone_unittest.cc
+++ b/content/browser/compositor/software_output_device_ozone_unittest.cc
@@ -96,7 +96,8 @@
   compositor_.reset(
       new ui::Compositor(viz::FrameSinkId(1, 1), context_factory, nullptr,
                          base::ThreadTaskRunnerHandle::Get(),
-                         false /* enable_surface_synchronization */));
+                         false /* enable_surface_synchronization */,
+                         false /* enable_pixel_canvas */));
   compositor_->SetAcceleratedWidget(window_delegate_.GetAcceleratedWidget());
   compositor_->SetScaleAndSize(1.0f, size);
 
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index c134de6..8a7eb98f 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -104,7 +104,8 @@
                   content::GetContextFactory(),
                   content::GetContextFactoryPrivate(),
                   ui::WindowResizeHelperMac::Get()->task_runner(),
-                  false /* enable_surface_synchronization */) {
+                  false /* enable_surface_synchronization */,
+                  false /* enable_pixel_canvas */) {
   compositor_.SetAcceleratedWidget(
       accelerated_widget_mac_->accelerated_widget());
   Suspend();
diff --git a/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc b/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
index cdf3bc48..5f6382b7 100644
--- a/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
+++ b/content/browser/service_worker/foreign_fetch_request_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "base/test/simple_test_clock.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -50,6 +51,10 @@
 
 const char* kValidUrl = "https://valid.example.com/foo/bar";
 
+// This timestamp is set to a time after the expiry timestamp of the expired
+// tokens in this test, but before the expiry timestamp of the valid ones.
+double kNowTimestamp = 1500000000;
+
 void EmptyCallback() {}
 
 }  // namespace
@@ -79,6 +84,12 @@
                                         kVersionId, context()->AsWeakPtr());
     version_->set_foreign_fetch_scopes({kScope});
 
+    // Fix the time for testing to kNowTimestamp
+    std::unique_ptr<base::SimpleTestClock> clock =
+        base::MakeUnique<base::SimpleTestClock>();
+    clock->SetNow(base::Time::FromDoubleT(kNowTimestamp));
+    version_->SetClockForTesting(std::move(clock));
+
     context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
     base::RunLoop().RunUntilIdle();
 
diff --git a/content/browser/service_worker/link_header_support.cc b/content/browser/service_worker/link_header_support.cc
index 32ce577..9f1fe471 100644
--- a/content/browser/service_worker/link_header_support.cc
+++ b/content/browser/service_worker/link_header_support.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/time/time.h"
 #include "components/link_header_util/link_header_util.h"
 #include "content/browser/loader/resource_message_filter.h"
 #include "content/browser/loader/resource_request_info_impl.h"
@@ -42,7 +43,8 @@
 
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableExperimentalWebPlatformFeatures) &&
-      !TrialTokenValidator::RequestEnablesFeature(request, "ForeignFetch")) {
+      !TrialTokenValidator::RequestEnablesFeature(request, "ForeignFetch",
+                                                  base::Time::Now())) {
     // TODO(mek): Log attempt to use without having correct token?
     return;
   }
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 7741575..3f1df99 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
 #include "base/time/default_tick_clock.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/child_process_security_policy_impl.h"
@@ -290,7 +291,8 @@
       site_for_uma_(ServiceWorkerMetrics::SiteFromURL(scope_)),
       context_(context),
       script_cache_map_(this, context),
-      tick_clock_(base::WrapUnique(new base::DefaultTickClock)),
+      tick_clock_(base::MakeUnique<base::DefaultTickClock>()),
+      clock_(base::MakeUnique<base::DefaultClock>()),
       ping_controller_(new PingController(this)),
       weak_factory_(this) {
   DCHECK_NE(kInvalidServiceWorkerVersionId, version_id);
@@ -552,7 +554,7 @@
       << " can only be dispatched to an active worker: " << status();
 
   int request_id = pending_requests_.Add(base::MakeUnique<PendingRequest>(
-      error_callback, base::Time::Now(), tick_clock_->NowTicks(), event_type));
+      error_callback, clock_->Now(), tick_clock_->NowTicks(), event_type));
   TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::Request",
                            pending_requests_.Lookup(request_id), "Request id",
                            request_id, "Event type",
@@ -622,7 +624,7 @@
   if (iter != external_request_uuid_to_request_id_.end()) {
     int request_id = iter->second;
     external_request_uuid_to_request_id_.erase(iter);
-    return FinishRequest(request_id, true, base::Time::Now());
+    return FinishRequest(request_id, true, clock_->Now());
   }
 
   // It is possible that the request was cancelled or timed out before and we
@@ -743,8 +745,8 @@
 
 void ServiceWorkerVersion::SetValidOriginTrialTokens(
     const TrialTokenValidator::FeatureToTokensMap& tokens) {
-  origin_trial_tokens_ =
-      TrialTokenValidator::GetValidTokens(url::Origin(scope()), tokens);
+  origin_trial_tokens_ = TrialTokenValidator::GetValidTokens(
+      url::Origin(scope()), tokens, clock_->Now());
 }
 
 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
@@ -796,7 +798,7 @@
   //     wasn't set in the entry.
   if (!origin_trial_tokens_) {
     origin_trial_tokens_ = TrialTokenValidator::GetValidTokensFromHeaders(
-        url::Origin(scope()), http_info.headers.get());
+        url::Origin(scope()), http_info.headers.get(), clock_->Now());
   }
 
   for (auto& observer : listeners_)
@@ -812,6 +814,11 @@
   tick_clock_ = std::move(tick_clock);
 }
 
+void ServiceWorkerVersion::SetClockForTesting(
+    std::unique_ptr<base::Clock> clock) {
+  clock_ = std::move(clock);
+}
+
 const net::HttpResponseInfo*
 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
   return main_script_http_info_.get();
@@ -1799,7 +1806,7 @@
   if (!registration || registration->active_version() != this)
     return;
   base::TimeDelta time_since_last_check =
-      base::Time::Now() - registration->last_update_check();
+      clock_->Now() - registration->last_update_check();
   if (time_since_last_check > kServiceWorkerScriptMaxCacheAge)
     RestartTick(&stale_time_);
 }
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 57be8c2..4c455a9 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -25,6 +25,7 @@
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/clock.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -392,6 +393,9 @@
   // Used to allow tests to change time for testing.
   void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
 
+  // Used to allow tests to change wall clock for testing.
+  void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+
   // Returns true if the service worker has work to do: it has pending
   // requests, in-progress streaming URLRequestJobs, or pending start callbacks.
   bool HasWork() const;
@@ -794,6 +798,9 @@
   // The clock used to vend tick time.
   std::unique_ptr<base::TickClock> tick_clock_;
 
+  // The clock used for actual (wall clock) time
+  std::unique_ptr<base::Clock> clock_;
+
   std::unique_ptr<PingController> ping_controller_;
 
   // Used for recording worker activities (e.g., a ratio of handled events)
diff --git a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index 8becd58..261e9e3 100644
--- a/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -111,7 +111,12 @@
 static const unsigned long long kDocumentIDs[] = {200, 201, 202};
 static const int kRenderFrameRouteIDs[] = {300, 301, 302};
 
-void BlockingReadFromMessagePort(MessagePort port, base::string16* message) {
+std::vector<uint8_t> StringPieceToVector(base::StringPiece s) {
+  return std::vector<uint8_t>(s.begin(), s.end());
+}
+
+void BlockingReadFromMessagePort(MessagePort port,
+                                 std::vector<uint8_t>* message) {
   base::RunLoop run_loop;
   port.SetCallback(run_loop.QuitClosure());
   run_loop.Run();
@@ -381,10 +386,11 @@
                               std::set<uint32_t>());
 
   // Verify that |worker_msg_port| corresponds to |connector->local_port()|.
-  base::string16 expected_message(base::ASCIIToUTF16("test1"));
-  connector->local_port().PostMessage(expected_message,
+  std::vector<uint8_t> expected_message(StringPieceToVector("test1"));
+  connector->local_port().PostMessage(expected_message.data(),
+                                      expected_message.size(),
                                       std::vector<MessagePort>());
-  base::string16 received_message;
+  std::vector<uint8_t> received_message;
   BlockingReadFromMessagePort(worker_msg_port, &received_message);
   EXPECT_EQ(expected_message, received_message);
 
@@ -472,10 +478,11 @@
                               std::set<uint32_t>());
 
   // Verify that |worker_msg_port1| corresponds to |connector0->local_port()|.
-  base::string16 expected_message1(base::ASCIIToUTF16("test1"));
-  connector0->local_port().PostMessage(expected_message1,
+  std::vector<uint8_t> expected_message1(StringPieceToVector("test1"));
+  connector0->local_port().PostMessage(expected_message1.data(),
+                                       expected_message1.size(),
                                        std::vector<MessagePort>());
-  base::string16 received_message1;
+  std::vector<uint8_t> received_message1;
   BlockingReadFromMessagePort(worker_msg_port1, &received_message1);
   EXPECT_EQ(expected_message1, received_message1);
 
@@ -544,10 +551,11 @@
                               {feature1, feature2});
 
   // Verify that |worker_msg_port2| corresponds to |connector1->local_port()|.
-  base::string16 expected_message2(base::ASCIIToUTF16("test2"));
-  connector1->local_port().PostMessage(expected_message2,
+  std::vector<uint8_t> expected_message2(StringPieceToVector("test2"));
+  connector1->local_port().PostMessage(expected_message2.data(),
+                                       expected_message2.size(),
                                        std::vector<MessagePort>());
-  base::string16 received_message2;
+  std::vector<uint8_t> received_message2;
   BlockingReadFromMessagePort(worker_msg_port2, &received_message2);
   EXPECT_EQ(expected_message2, received_message2);
 
diff --git a/content/child/webmessageportchannel_impl.cc b/content/child/webmessageportchannel_impl.cc
index 9f420ef..80c42fd6 100644
--- a/content/child/webmessageportchannel_impl.cc
+++ b/content/child/webmessageportchannel_impl.cc
@@ -96,7 +96,8 @@
 }
 
 void WebMessagePortChannelImpl::PostMessage(
-    const WebString& encoded_message,
+    const uint8_t* encoded_message,
+    size_t encoded_message_size,
     WebMessagePortChannelArray channels) {
   std::vector<MessagePort> ports;
   if (!channels.IsEmpty()) {
@@ -106,18 +107,18 @@
           ReleaseMessagePort();
     }
   }
-  port_.PostMessage(encoded_message.Utf16(), std::move(ports));
+  port_.PostMessage(encoded_message, encoded_message_size, std::move(ports));
 }
 
 bool WebMessagePortChannelImpl::TryGetMessage(
-    WebString* encoded_message,
+    blink::WebVector<uint8_t>* encoded_message,
     WebMessagePortChannelArray& channels) {
-  base::string16 buffer;
+  std::vector<uint8_t> buffer;
   std::vector<MessagePort> ports;
   if (!port_.GetMessage(&buffer, &ports))
     return false;
 
-  *encoded_message = WebString::FromUTF16(buffer);
+  *encoded_message = std::move(buffer);
 
   if (!ports.empty()) {
     channels = WebMessagePortChannelArray(ports.size());
diff --git a/content/child/webmessageportchannel_impl.h b/content/child/webmessageportchannel_impl.h
index 28091a3..5b5ab76 100644
--- a/content/child/webmessageportchannel_impl.h
+++ b/content/child/webmessageportchannel_impl.h
@@ -42,9 +42,10 @@
 
   // WebMessagePortChannel implementation.
   void SetClient(blink::WebMessagePortChannelClient* client) override;
-  void PostMessage(const blink::WebString& encoded_message,
+  void PostMessage(const uint8_t* encoded_message,
+                   size_t encoded_message_size,
                    blink::WebMessagePortChannelArray channels) override;
-  bool TryGetMessage(blink::WebString* encoded_message,
+  bool TryGetMessage(blink::WebVector<uint8_t>* encoded_message,
                      blink::WebMessagePortChannelArray& channels) override;
 
   MessagePort port_;
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 9805472..dc5090f 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -233,6 +233,10 @@
     "media/video_capture.h",
     "message_port.cc",
     "message_port.h",
+    "message_port_message.cc",
+    "message_port_message.h",
+    "message_port_message_struct_traits.cc",
+    "message_port_message_struct_traits.h",
     "navigation_gesture.h",
     "navigation_params.cc",
     "navigation_params.h",
diff --git a/content/common/message_port.cc b/content/common/message_port.cc
index b90ac41e..75f51b9 100644
--- a/content/common/message_port.cc
+++ b/content/common/message_port.cc
@@ -8,6 +8,7 @@
 #include "base/logging.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/common/message_port.mojom.h"
+#include "content/common/message_port_message_struct_traits.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 
 namespace content {
@@ -44,28 +45,27 @@
   return handles;
 }
 
-void MessagePort::PostMessage(const base::string16& encoded_message,
+void MessagePort::PostMessage(const uint8_t* encoded_message,
+                              size_t encoded_message_size,
                               std::vector<MessagePort> ports) {
   DCHECK(state_->handle().is_valid());
 
-  uint32_t num_bytes = encoded_message.size() * sizeof(base::char16);
-
   // NOTE: It is OK to ignore the return value of mojo::WriteMessageNew here.
   // HTML MessagePorts have no way of reporting when the peer is gone.
 
-  mojom::MessagePortMessagePtr msg = mojom::MessagePortMessage::New();
-  msg->encoded_message.resize(num_bytes);
-  std::memcpy(msg->encoded_message.data(), encoded_message.data(), num_bytes);
-  msg->ports.resize(ports.size());
+  MessagePortMessage msg;
+  msg.encoded_message =
+      mojo::ConstCArray<uint8_t>(encoded_message_size, encoded_message);
+  msg.ports.resize(ports.size());
   for (size_t i = 0; i < ports.size(); ++i)
-    msg->ports[i] = ports[i].ReleaseHandle();
+    msg.ports[i] = ports[i].ReleaseHandle();
   mojo::Message mojo_message =
       mojom::MessagePortMessage::SerializeAsMessage(&msg);
   mojo::WriteMessageNew(state_->handle().get(), mojo_message.TakeMojoMessage(),
                         MOJO_WRITE_MESSAGE_FLAG_NONE);
 }
 
-bool MessagePort::GetMessage(base::string16* encoded_message,
+bool MessagePort::GetMessage(std::vector<uint8_t>* encoded_message,
                              std::vector<MessagePort>* ports) {
   DCHECK(state_->handle().is_valid());
   mojo::ScopedMessageHandle message_handle;
@@ -75,19 +75,16 @@
     return false;
 
   mojo::Message message(std::move(message_handle));
-  mojom::MessagePortMessagePtr msg;
+  MessagePortMessage msg;
   bool success = mojom::MessagePortMessage::DeserializeFromMessage(
       std::move(message), &msg);
-  if (!success || !msg)
+  if (!success)
     return false;
 
-  DCHECK_EQ(0u, msg->encoded_message.size() % sizeof(base::char16));
-  encoded_message->resize(msg->encoded_message.size() / sizeof(base::char16));
-  std::memcpy(&encoded_message->at(0), msg->encoded_message.data(),
-              msg->encoded_message.size());
-  ports->resize(msg->ports.size());
+  *encoded_message = std::move(msg.owned_encoded_message);
+  ports->resize(msg.ports.size());
   for (size_t i = 0; i < ports->size(); ++i)
-    ports->at(i) = MessagePort(std::move(msg->ports[i]));
+    ports->at(i) = MessagePort(std::move(msg.ports[i]));
 
   return true;
 }
diff --git a/content/common/message_port.h b/content/common/message_port.h
index 31f6c16f..2ed695f 100644
--- a/content/common/message_port.h
+++ b/content/common/message_port.h
@@ -10,7 +10,6 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/strings/string16.h"
 #include "base/synchronization/lock.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -61,12 +60,13 @@
 
   // Sends an encoded message (along with ports to transfer) to this port's
   // peer.
-  void PostMessage(const base::string16& encoded_message,
+  void PostMessage(const uint8_t* encoded_message,
+                   size_t encoded_message_size,
                    std::vector<MessagePort> ports);
 
   // Get the next available encoded message if any. Returns true if a message
   // was read.
-  bool GetMessage(base::string16* encoded_message,
+  bool GetMessage(std::vector<uint8_t>* encoded_message,
                   std::vector<MessagePort>* ports);
 
   // This callback will be invoked on a background thread when messages are
diff --git a/content/common/message_port_message.cc b/content/common/message_port_message.cc
new file mode 100644
index 0000000..facde6f8
--- /dev/null
+++ b/content/common/message_port_message.cc
@@ -0,0 +1,12 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/message_port_message.h"
+
+namespace content {
+
+MessagePortMessage::MessagePortMessage() = default;
+MessagePortMessage::~MessagePortMessage() = default;
+
+}  // namespace content
diff --git a/content/common/message_port_message.h b/content/common/message_port_message.h
new file mode 100644
index 0000000..c65764e
--- /dev/null
+++ b/content/common/message_port_message.h
@@ -0,0 +1,34 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_MESSAGE_PORT_MESSAGE_H_
+#define CONTENT_COMMON_MESSAGE_PORT_MESSAGE_H_
+
+#include <vector>
+#include "mojo/public/cpp/bindings/array_traits_carray.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace content {
+
+// This struct represents messages as they are posted over a message port. This
+// type can be serialized as a content::mojom::MessagePortMessage struct.
+struct MessagePortMessage {
+  MessagePortMessage();
+  ~MessagePortMessage();
+
+  // To reduce copies when serializing |encoded_message| does not have to point
+  // to |owned_encoded_message|. The serialization code completely ignores the
+  // |owned_encoded_message| and just serializes whatever |encoded_message|
+  // points to. When deserializing |owned_encoded_message| is set to the data
+  // and |encoded_message| is set to point to |owned_encoded_message|.
+  mojo::ConstCArray<uint8_t> encoded_message;
+  std::vector<uint8_t> owned_encoded_message;
+
+  // Any ports being transfered as part of this message.
+  std::vector<mojo::ScopedMessagePipeHandle> ports;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_MESSAGE_PORT_MESSAGE_H_
diff --git a/content/common/message_port_message_struct_traits.cc b/content/common/message_port_message_struct_traits.cc
new file mode 100644
index 0000000..adbe333
--- /dev/null
+++ b/content/common/message_port_message_struct_traits.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/message_port_message_struct_traits.h"
+
+namespace mojo {
+
+bool StructTraits<content::mojom::MessagePortMessage::DataView,
+                  content::MessagePortMessage>::
+    Read(content::mojom::MessagePortMessage::DataView data,
+         content::MessagePortMessage* out) {
+  if (!data.ReadEncodedMessage(&out->owned_encoded_message) ||
+      !data.ReadPorts(&out->ports))
+    return false;
+
+  out->encoded_message = mojo::ConstCArray<uint8_t>(
+      out->owned_encoded_message.size(), out->owned_encoded_message.data());
+  return true;
+}
+
+}  // namespace mojo
diff --git a/content/common/message_port_message_struct_traits.h b/content/common/message_port_message_struct_traits.h
new file mode 100644
index 0000000..3a6bb97
--- /dev/null
+++ b/content/common/message_port_message_struct_traits.h
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_MESSAGE_PORT_MESSAGE_STRUCT_TRAITS_H_
+#define CONTENT_COMMON_MESSAGE_PORT_MESSAGE_STRUCT_TRAITS_H_
+
+#include "content/common/message_port.mojom.h"
+#include "content/common/message_port_message.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<content::mojom::MessagePortMessage::DataView,
+                    content::MessagePortMessage> {
+  static ConstCArray<uint8_t> encoded_message(
+      content::MessagePortMessage& input) {
+    return input.encoded_message;
+  }
+
+  static std::vector<mojo::ScopedMessagePipeHandle>& ports(
+      content::MessagePortMessage& input) {
+    return input.ports;
+  }
+
+  static bool Read(content::mojom::MessagePortMessage::DataView data,
+                   content::MessagePortMessage* out);
+};
+
+}  // namespace mojo
+
+#endif  // CONTENT_COMMON_MESSAGE_PORT_MESSAGE_STRUCT_TRAITS_H_
diff --git a/content/common/origin_trials/trial_token_validator.cc b/content/common/origin_trials/trial_token_validator.cc
index bb1c232..3412ed9 100644
--- a/content/common/origin_trials/trial_token_validator.cc
+++ b/content/common/origin_trials/trial_token_validator.cc
@@ -21,7 +21,8 @@
 blink::WebOriginTrialTokenStatus TrialTokenValidator::ValidateToken(
     const std::string& token,
     const url::Origin& origin,
-    std::string* feature_name) {
+    std::string* feature_name,
+    base::Time current_time) {
   ContentClient* content_client = GetContentClient();
   const OriginTrialPolicy* origin_trial_policy =
       content_client->GetOriginTrialPolicy();
@@ -40,7 +41,7 @@
   if (status != blink::WebOriginTrialTokenStatus::kSuccess)
     return status;
 
-  status = trial_token->IsValid(origin, base::Time::Now());
+  status = trial_token->IsValid(origin, current_time);
   if (status != blink::WebOriginTrialTokenStatus::kSuccess)
     return status;
 
@@ -54,19 +55,20 @@
   return blink::WebOriginTrialTokenStatus::kSuccess;
 }
 
-bool TrialTokenValidator::RequestEnablesFeature(
-    const net::URLRequest* request,
-    base::StringPiece feature_name) {
+bool TrialTokenValidator::RequestEnablesFeature(const net::URLRequest* request,
+                                                base::StringPiece feature_name,
+                                                base::Time current_time) {
   // TODO(mek): Possibly cache the features that are availble for request in
   // UserData associated with the request.
   return RequestEnablesFeature(request->url(), request->response_headers(),
-                               feature_name);
+                               feature_name, current_time);
 }
 
 bool TrialTokenValidator::RequestEnablesFeature(
     const GURL& request_url,
     const net::HttpResponseHeaders* response_headers,
-    base::StringPiece feature_name) {
+    base::StringPiece feature_name,
+    base::Time current_time) {
   if (!base::FeatureList::IsEnabled(features::kOriginTrials))
     return false;
 
@@ -79,7 +81,7 @@
   while (response_headers->EnumerateHeader(&iter, "Origin-Trial", &token)) {
     std::string token_feature;
     // TODO(mek): Log the validation errors to histograms?
-    if (ValidateToken(token, origin, &token_feature) ==
+    if (ValidateToken(token, origin, &token_feature, current_time) ==
         blink::WebOriginTrialTokenStatus::kSuccess)
       if (token_feature == feature_name)
         return true;
@@ -90,7 +92,8 @@
 std::unique_ptr<TrialTokenValidator::FeatureToTokensMap>
 TrialTokenValidator::GetValidTokensFromHeaders(
     const url::Origin& origin,
-    const net::HttpResponseHeaders* headers) {
+    const net::HttpResponseHeaders* headers,
+    base::Time current_time) {
   std::unique_ptr<FeatureToTokensMap> tokens(
       base::MakeUnique<FeatureToTokensMap>());
   if (!base::FeatureList::IsEnabled(features::kOriginTrials))
@@ -103,7 +106,8 @@
   std::string token;
   while (headers->EnumerateHeader(&iter, "Origin-Trial", &token)) {
     std::string token_feature;
-    if (TrialTokenValidator::ValidateToken(token, origin, &token_feature) ==
+    if (TrialTokenValidator::ValidateToken(token, origin, &token_feature,
+                                           current_time) ==
         blink::WebOriginTrialTokenStatus::kSuccess) {
       (*tokens)[token_feature].push_back(token);
     }
@@ -113,7 +117,8 @@
 
 std::unique_ptr<TrialTokenValidator::FeatureToTokensMap>
 TrialTokenValidator::GetValidTokens(const url::Origin& origin,
-                                    const FeatureToTokensMap& tokens) {
+                                    const FeatureToTokensMap& tokens,
+                                    base::Time current_time) {
   std::unique_ptr<FeatureToTokensMap> out_tokens(
       base::MakeUnique<FeatureToTokensMap>());
   if (!base::FeatureList::IsEnabled(features::kOriginTrials))
@@ -125,7 +130,8 @@
   for (const auto& feature : tokens) {
     for (const std::string& token : feature.second) {
       std::string token_feature;
-      if (TrialTokenValidator::ValidateToken(token, origin, &token_feature) ==
+      if (TrialTokenValidator::ValidateToken(token, origin, &token_feature,
+                                             current_time) ==
           blink::WebOriginTrialTokenStatus::kSuccess) {
         DCHECK_EQ(token_feature, feature.first);
         (*out_tokens)[feature.first].push_back(token);
diff --git a/content/common/origin_trials/trial_token_validator.h b/content/common/origin_trials/trial_token_validator.h
index 9a8cce9..f5afb87 100644
--- a/content/common/origin_trials/trial_token_validator.h
+++ b/content/common/origin_trials/trial_token_validator.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 #include "base/strings/string_piece.h"
+#include "base/time/time.h"
 #include "content/common/content_export.h"
 #include "url/origin.h"
 
@@ -35,26 +36,31 @@
 CONTENT_EXPORT blink::WebOriginTrialTokenStatus ValidateToken(
     const std::string& token,
     const url::Origin& origin,
-    std::string* feature_name);
+    std::string* feature_name,
+    base::Time current_time);
 
 CONTENT_EXPORT bool RequestEnablesFeature(const net::URLRequest* request,
-                                          base::StringPiece feature_name);
+                                          base::StringPiece feature_name,
+                                          base::Time current_time);
 
 CONTENT_EXPORT bool RequestEnablesFeature(
     const GURL& request_url,
     const net::HttpResponseHeaders* response_headers,
-    base::StringPiece feature_name);
+    base::StringPiece feature_name,
+    base::Time current_time);
 
 // Returns all valid tokens in |headers|.
 CONTENT_EXPORT std::unique_ptr<FeatureToTokensMap> GetValidTokensFromHeaders(
     const url::Origin& origin,
-    const net::HttpResponseHeaders* headers);
+    const net::HttpResponseHeaders* headers,
+    base::Time current_time);
 
 // Returns all valid tokens in |tokens|. This method is used to re-validate
 // previously stored tokens.
 CONTENT_EXPORT std::unique_ptr<FeatureToTokensMap> GetValidTokens(
     const url::Origin& origin,
-    const FeatureToTokensMap& tokens);
+    const FeatureToTokensMap& tokens,
+    base::Time current_time);
 
 }  // namespace TrialTokenValidator
 
diff --git a/content/common/origin_trials/trial_token_validator_unittest.cc b/content/common/origin_trials/trial_token_validator_unittest.cc
index e49f02e3..830f580 100644
--- a/content/common/origin_trials/trial_token_validator_unittest.cc
+++ b/content/common/origin_trials/trial_token_validator_unittest.cc
@@ -112,11 +112,9 @@
     "YW1wbGUuY29tOjgwIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6"
     "IDIwMDAwMDAwMDB9";
 
-// These timestamps should be in the past and future, respectively. Sanity
-// checks within the tests assert that that is true, to guard against poorly-set
-// system clocks. (And against the inevitable march of time past the year 2033)
-double kPastTimestamp = 1000000000;
-double kFutureTimestamp = 2000000000;
+// This timestamp is set to a time after the expiry timestamp of kExpiredToken,
+// but before the expiry timestamp of kValidToken.
+double kNowTimestamp = 1500000000;
 
 class TestOriginTrialPolicy : public OriginTrialPolicy {
  public:
@@ -190,15 +188,6 @@
 
   ~TrialTokenValidatorTest() override { SetContentClient(nullptr); }
 
-  void SetUp() override {
-    // Ensure that the system clock is set to a date that the matches the test
-    // expectations. If this fails, either the clock on the test device is
-    // incorrect, or the actual date is after 2033-05-18, and the tokens need to
-    // be regenerated.
-    ASSERT_GT(base::Time::Now(), base::Time::FromDoubleT(kPastTimestamp));
-    ASSERT_LT(base::Time::Now(), base::Time::FromDoubleT(kFutureTimestamp));
-  }
-
   void SetPublicKey(const uint8_t* key) {
     test_content_client_.SetOriginTrialPublicKey(key);
   }
@@ -211,6 +200,8 @@
     test_content_client_.DisableToken(token_signature);
   }
 
+  base::Time Now() { return base::Time::FromDoubleT(kNowTimestamp); }
+
   const url::Origin appropriate_origin_;
   const url::Origin inappropriate_origin_;
   const url::Origin insecure_origin_;
@@ -224,17 +215,11 @@
   TestContentClient test_content_client_;
 };
 
-// Flaky on Android swarming bots: crbug.com/672294
-#if defined(OS_ANDROID)
-#define MAYBE_ValidateValidToken DISABLED_ValidateValidToken
-#else
-#define MAYBE_ValidateValidToken ValidateValidToken
-#endif
-TEST_F(TrialTokenValidatorTest, MAYBE_ValidateValidToken) {
+TEST_F(TrialTokenValidatorTest, ValidateValidToken) {
   std::string feature;
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess,
-            TrialTokenValidator::ValidateToken(kSampleToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kSampleToken, appropriate_origin_, &feature, Now()));
   EXPECT_EQ(kAppropriateFeatureName, feature);
 }
 
@@ -242,60 +227,54 @@
   std::string feature;
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kWrongOrigin,
             TrialTokenValidator::ValidateToken(
-                kSampleToken, inappropriate_origin_, &feature));
+                kSampleToken, inappropriate_origin_, &feature, Now()));
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kWrongOrigin,
             TrialTokenValidator::ValidateToken(kSampleToken, insecure_origin_,
-                                               &feature));
+                                               &feature, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidateInvalidSignature) {
   std::string feature;
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kInvalidSignature,
-            TrialTokenValidator::ValidateToken(kInvalidSignatureToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kInvalidSignatureToken, appropriate_origin_, &feature, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidateUnparsableToken) {
   std::string feature;
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kMalformed,
-            TrialTokenValidator::ValidateToken(kUnparsableToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kUnparsableToken, appropriate_origin_, &feature, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidateExpiredToken) {
   std::string feature;
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kExpired,
-            TrialTokenValidator::ValidateToken(kExpiredToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kExpiredToken, appropriate_origin_, &feature, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) {
   std::string feature;
   SetPublicKey(kTestPublicKey2);
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kInvalidSignature,
-            TrialTokenValidator::ValidateToken(kSampleToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kSampleToken, appropriate_origin_, &feature, Now()));
 }
 
-// Flaky on Android swarming bots: crbug.com/672294
-#if defined(OS_ANDROID)
-#define MAYBE_ValidatorRespectsDisabledFeatures DISABLED_ValidatorRespectsDisabledFeatures
-#else
-#define MAYBE_ValidatorRespectsDisabledFeatures ValidatorRespectsDisabledFeatures
-#endif
-TEST_F(TrialTokenValidatorTest, MAYBE_ValidatorRespectsDisabledFeatures) {
+TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledFeatures) {
   std::string feature;
   // Disable an irrelevant feature; token should still validate
   DisableFeature(kInappropriateFeatureName);
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess,
-            TrialTokenValidator::ValidateToken(kSampleToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kSampleToken, appropriate_origin_, &feature, Now()));
   EXPECT_EQ(kAppropriateFeatureName, feature);
   // Disable the token's feature; it should no longer be valid
   DisableFeature(kAppropriateFeatureName);
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kFeatureDisabled,
-            TrialTokenValidator::ValidateToken(kSampleToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kSampleToken, appropriate_origin_, &feature, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledTokens) {
@@ -303,80 +282,63 @@
   // Disable an irrelevant token; token should still validate
   DisableToken(expired_token_signature_);
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kSuccess,
-            TrialTokenValidator::ValidateToken(kSampleToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kSampleToken, appropriate_origin_, &feature, Now()));
   EXPECT_EQ(kAppropriateFeatureName, feature);
   // Disable the token; it should no longer be valid
   DisableToken(valid_token_signature_);
   EXPECT_EQ(blink::WebOriginTrialTokenStatus::kTokenDisabled,
-            TrialTokenValidator::ValidateToken(kSampleToken,
-                                               appropriate_origin_, &feature));
+            TrialTokenValidator::ValidateToken(
+                kSampleToken, appropriate_origin_, &feature, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidateRequestInsecure) {
   response_headers_->AddHeader(std::string("Origin-Trial: ") +
                                kInsecureOriginToken);
   EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature(
-      GURL(kInsecureOrigin), response_headers_.get(), kAppropriateFeatureName));
+      GURL(kInsecureOrigin), response_headers_.get(), kAppropriateFeatureName,
+      Now()));
 }
 
-// Flaky on Android swarming bots: crbug.com/672294
-#if defined(OS_ANDROID)
-#define MAYBE_ValidateRequestValidToken DISABLED_ValidateRequestValidToken
-#else
-#define MAYBE_ValidateRequestValidToken ValidateRequestValidToken
-#endif
-TEST_F(TrialTokenValidatorTest, MAYBE_ValidateRequestValidToken) {
+TEST_F(TrialTokenValidatorTest, ValidateRequestValidToken) {
   response_headers_->AddHeader(std::string("Origin-Trial: ") + kSampleToken);
   EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kAppropriateOrigin), response_headers_.get(),
-      kAppropriateFeatureName));
+      kAppropriateFeatureName, Now()));
 }
 
 TEST_F(TrialTokenValidatorTest, ValidateRequestNoTokens) {
   EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kAppropriateOrigin), response_headers_.get(),
-      kAppropriateFeatureName));
+      kAppropriateFeatureName, Now()));
 }
 
-// Flaky on Android swarming bots: crbug.com/672294
-#if defined(OS_ANDROID)
-#define MAYBE_ValidateRequestMultipleHeaders DISABLED_ValidateRequestMultipleHeaders
-#else
-#define MAYBE_ValidateRequestMultipleHeaders ValidateRequestMultipleHeaders
-#endif
-TEST_F(TrialTokenValidatorTest, MAYBE_ValidateRequestMultipleHeaders) {
+TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaders) {
   response_headers_->AddHeader(std::string("Origin-Trial: ") + kSampleToken);
   response_headers_->AddHeader(std::string("Origin-Trial: ") + kExpiredToken);
   EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kAppropriateOrigin), response_headers_.get(),
-      kAppropriateFeatureName));
+      kAppropriateFeatureName, Now()));
   EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kAppropriateOrigin), response_headers_.get(),
-      kInappropriateFeatureName));
+      kInappropriateFeatureName, Now()));
   EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kInappropriateOrigin), response_headers_.get(),
-      kAppropriateFeatureName));
+      kAppropriateFeatureName, Now()));
 }
 
-// Flaky on Android swarming bots: crbug.com/672294
-#if defined(OS_ANDROID)
-#define MAYBE_ValidateRequestMultipleHeaderValues DISABLED_ValidateRequestMultipleHeaderValues
-#else
-#define MAYBE_ValidateRequestMultipleHeaderValues ValidateRequestMultipleHeaderValues
-#endif
-TEST_F(TrialTokenValidatorTest, MAYBE_ValidateRequestMultipleHeaderValues) {
+TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaderValues) {
   response_headers_->AddHeader(std::string("Origin-Trial: ") + kExpiredToken +
                                ", " + kSampleToken);
   EXPECT_TRUE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kAppropriateOrigin), response_headers_.get(),
-      kAppropriateFeatureName));
+      kAppropriateFeatureName, Now()));
   EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kAppropriateOrigin), response_headers_.get(),
-      kInappropriateFeatureName));
+      kInappropriateFeatureName, Now()));
   EXPECT_FALSE(TrialTokenValidator::RequestEnablesFeature(
       GURL(kInappropriateOrigin), response_headers_.get(),
-      kAppropriateFeatureName));
+      kAppropriateFeatureName, Now()));
 }
 
 }  // namespace content
diff --git a/content/renderer/origin_trials/web_trial_token_validator_impl.cc b/content/renderer/origin_trials/web_trial_token_validator_impl.cc
index e34dee6..ca9fdf2 100644
--- a/content/renderer/origin_trials/web_trial_token_validator_impl.cc
+++ b/content/renderer/origin_trials/web_trial_token_validator_impl.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/origin_trials/web_trial_token_validator_impl.h"
 
+#include "base/time/time.h"
 #include "content/common/origin_trials/trial_token_validator.h"
 #include "third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h"
 
@@ -17,8 +18,8 @@
     const blink::WebSecurityOrigin& origin,
     blink::WebString* feature_name) {
   std::string feature;
-  blink::WebOriginTrialTokenStatus status =
-      TrialTokenValidator::ValidateToken(token.Utf8(), origin, &feature);
+  blink::WebOriginTrialTokenStatus status = TrialTokenValidator::ValidateToken(
+      token.Utf8(), origin, &feature, base::Time::Now());
   if (status == blink::WebOriginTrialTokenStatus::kSuccess)
     *feature_name = blink::WebString::FromUTF8(feature);
   return status;
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index cfa432d..4fddd69 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -196,6 +196,8 @@
         ['win', 'amd', 'passthrough', 'd3d11'], bug=685232)
 
     # Win / NVIDIA / Passthrough command decoder / D3D11
+    self.Flaky('conformance/extensions/oes-texture-half-float-with-video.html',
+        ['win7', 'nvidia', 'passthrough', 'd3d11', 'debug'], bug=751849)
     self.Flaky('conformance/programs/program-test.html',
         ['win', 'nvidia', 'passthrough', 'd3d11'], bug=737016)
 
diff --git a/device/serial/serial_device_enumerator_linux.cc b/device/serial/serial_device_enumerator_linux.cc
index 010cf78..100f7dd 100644
--- a/device/serial/serial_device_enumerator_linux.cc
+++ b/device/serial/serial_device_enumerator_linux.cc
@@ -68,7 +68,7 @@
         udev_device_get_property_value(device.get(), kHostPathKey);
     const char* bus = udev_device_get_property_value(device.get(), kHostBusKey);
     if (path != NULL && bus != NULL) {
-      mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
+      auto info = mojom::SerialDeviceInfo::New();
       info->path = path;
 
       const char* vendor_id =
diff --git a/device/serial/serial_device_enumerator_mac.cc b/device/serial/serial_device_enumerator_mac.cc
index 3d1b4fa..333da5b 100644
--- a/device/serial/serial_device_enumerator_mac.cc
+++ b/device/serial/serial_device_enumerator_mac.cc
@@ -119,7 +119,7 @@
   base::mac::ScopedIOObject<io_iterator_t> scoped_it(it);
   base::mac::ScopedIOObject<io_service_t> scoped_device;
   while (scoped_device.reset(IOIteratorNext(scoped_it.get())), scoped_device) {
-    mojom::SerialDeviceInfoPtr callout_info(mojom::SerialDeviceInfo::New());
+    auto callout_info = mojom::SerialDeviceInfo::New();
 
     uint16_t vendorId;
     if (GetUInt16Property(scoped_device.get(), CFSTR(kUSBVendorID),
@@ -192,7 +192,7 @@
     std::set<std::string>::const_iterator i = valid_patterns.begin();
     for (; i != valid_patterns.end(); ++i) {
       if (base::MatchPattern(next_device, *i)) {
-        mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
+        auto info = mojom::SerialDeviceInfo::New();
         info->path = next_device;
         devices.push_back(std::move(info));
         break;
diff --git a/device/serial/serial_device_enumerator_win.cc b/device/serial/serial_device_enumerator_win.cc
index b8aa470..ef617fa 100644
--- a/device/serial/serial_device_enumerator_win.cc
+++ b/device/serial/serial_device_enumerator_win.cc
@@ -109,7 +109,7 @@
       // serial device. If the COM can't be found, ignore the device.
       continue;
 
-    mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
+    auto info = mojom::SerialDeviceInfo::New();
     info->path = com_port;
 
     std::string display_name;
@@ -145,7 +145,7 @@
       HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
   std::vector<mojom::SerialDeviceInfoPtr> devices;
   for (; iter_key.Valid(); ++iter_key) {
-    mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
+    auto info = mojom::SerialDeviceInfo::New();
     info->path = base::UTF16ToASCII(iter_key.Value());
     devices.push_back(std::move(info));
   }
diff --git a/device/serial/serial_io_handler_posix.cc b/device/serial/serial_io_handler_posix.cc
index a7d77de..eca131f 100644
--- a/device/serial/serial_io_handler_posix.cc
+++ b/device/serial/serial_io_handler_posix.cc
@@ -411,8 +411,7 @@
     return mojom::SerialDeviceControlSignalsPtr();
   }
 
-  mojom::SerialDeviceControlSignalsPtr signals(
-      mojom::SerialDeviceControlSignals::New());
+  auto signals = mojom::SerialDeviceControlSignals::New();
   signals->dcd = (status & TIOCM_CAR) != 0;
   signals->cts = (status & TIOCM_CTS) != 0;
   signals->dsr = (status & TIOCM_DSR) != 0;
@@ -464,7 +463,7 @@
     return mojom::SerialConnectionInfoPtr();
   }
 
-  mojom::SerialConnectionInfoPtr info(mojom::SerialConnectionInfo::New());
+  auto info = mojom::SerialConnectionInfo::New();
 #if defined(OS_LINUX)
   // Linux forces c_ospeed to contain the correct value, which is nice.
   info->bitrate = config.c_ospeed;
diff --git a/device/serial/serial_io_handler_win.cc b/device/serial/serial_io_handler_win.cc
index 359ffc3..3384a8e8 100644
--- a/device/serial/serial_io_handler_win.cc
+++ b/device/serial/serial_io_handler_win.cc
@@ -466,8 +466,7 @@
     return mojom::SerialDeviceControlSignalsPtr();
   }
 
-  mojom::SerialDeviceControlSignalsPtr signals(
-      mojom::SerialDeviceControlSignals::New());
+  auto signals = mojom::SerialDeviceControlSignals::New();
   signals->dcd = (status & MS_RLSD_ON) != 0;
   signals->cts = (status & MS_CTS_ON) != 0;
   signals->dsr = (status & MS_DSR_ON) != 0;
@@ -501,7 +500,7 @@
     VPLOG(1) << "Failed to get serial port info";
     return mojom::SerialConnectionInfoPtr();
   }
-  mojom::SerialConnectionInfoPtr info(mojom::SerialConnectionInfo::New());
+  auto info = mojom::SerialConnectionInfo::New();
   info->bitrate = SpeedConstantToBitrate(config.BaudRate);
   info->data_bits = DataBitsConstantToEnum(config.ByteSize);
   info->parity_bit = ParityBitConstantToEnum(config.Parity);
diff --git a/device/serial/test_serial_io_handler.cc b/device/serial/test_serial_io_handler.cc
index 3007b46a..4c7585e 100644
--- a/device/serial/test_serial_io_handler.cc
+++ b/device/serial/test_serial_io_handler.cc
@@ -80,14 +80,13 @@
 
 mojom::SerialDeviceControlSignalsPtr TestSerialIoHandler::GetControlSignals()
     const {
-  mojom::SerialDeviceControlSignalsPtr signals(
-      mojom::SerialDeviceControlSignals::New());
+  auto signals = mojom::SerialDeviceControlSignals::New();
   *signals = device_control_signals_;
   return signals;
 }
 
 mojom::SerialConnectionInfoPtr TestSerialIoHandler::GetPortInfo() const {
-  mojom::SerialConnectionInfoPtr info(mojom::SerialConnectionInfo::New());
+  auto info = mojom::SerialConnectionInfo::New();
   *info = info_;
   return info;
 }
diff --git a/extensions/shell/installer/linux/BUILD.gn b/extensions/shell/installer/linux/BUILD.gn
index 77211396..1a05bfc 100644
--- a/extensions/shell/installer/linux/BUILD.gn
+++ b/extensions/shell/installer/linux/BUILD.gn
@@ -71,7 +71,7 @@
     "//chrome/installer/linux/debian/changelog.template",
     "//chrome/installer/linux/debian/control.template",
     "debian/build.sh",
-    "debian/expected_deps_x64_jessie",
+    "debian/expected_deps_x64",
     "debian/postinst",
     "debian/postrm",
   ]
diff --git a/extensions/shell/installer/linux/debian/build.sh b/extensions/shell/installer/linux/debian/build.sh
index 331d9ad4..f0ab21b 100755
--- a/extensions/shell/installer/linux/debian/build.sh
+++ b/extensions/shell/installer/linux/debian/build.sh
@@ -226,13 +226,6 @@
 process_opts "$@"
 BUILDDIR=${BUILDDIR:=$(readlink -f "${SCRIPTDIR}/../../../../out/Release")}
 
-if [[ "$(basename ${SYSROOT})" = "debian_jessie_"*"-sysroot" ]]; then
-  TARGET_DISTRO="jessie"
-else
-  echo "Debian package can only be built using the jessie sysroot."
-  exit 1
-fi
-
 source ${BUILDDIR}/app_shell_installer/common/installer.include
 
 get_version_info
@@ -286,7 +279,7 @@
 
 # Compare the expected dependency list to the generated list.
 BAD_DIFF=0
-diff -u "$SCRIPTDIR/expected_deps_${TARGETARCH}_${TARGET_DISTRO}" actual || \
+diff -u "$SCRIPTDIR/expected_deps_${TARGETARCH}" actual || \
   BAD_DIFF=1
 if [ $BAD_DIFF -ne 0 ] && [ -z "${IGNORE_DEPS_CHANGES:-}" ]; then
   echo
diff --git a/extensions/shell/installer/linux/debian/expected_deps_x64_jessie b/extensions/shell/installer/linux/debian/expected_deps_x64
similarity index 100%
rename from extensions/shell/installer/linux/debian/expected_deps_x64_jessie
rename to extensions/shell/installer/linux/debian/expected_deps_x64
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn
index c415cfe0..c7d94eb 100644
--- a/media/test/BUILD.gn
+++ b/media/test/BUILD.gn
@@ -167,5 +167,5 @@
     "close_fd_mask=1",
   ]
 
-  seed_corpus = "media/test/data/"
+  seed_corpus = "//media/test/data/"
 }
diff --git a/mojo/public/cpp/bindings/array_traits_carray.h b/mojo/public/cpp/bindings/array_traits_carray.h
index 3ff694b..3a9bd8c1 100644
--- a/mojo/public/cpp/bindings/array_traits_carray.h
+++ b/mojo/public/cpp/bindings/array_traits_carray.h
@@ -5,6 +5,7 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_
 
+#include <cstddef>
 #include "mojo/public/cpp/bindings/array_traits.h"
 
 namespace mojo {
diff --git a/net/BUILD.gn b/net/BUILD.gn
index fd433ab..3c3dc66 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1041,6 +1041,8 @@
       "ntlm/ntlm_buffer_reader.h",
       "ntlm/ntlm_buffer_writer.cc",
       "ntlm/ntlm_buffer_writer.h",
+      "ntlm/ntlm_client.cc",
+      "ntlm/ntlm_client.h",
       "ntlm/ntlm_constants.h",
       "proxy/dhcp_proxy_script_adapter_fetcher_win.cc",
       "proxy/dhcp_proxy_script_adapter_fetcher_win.h",
@@ -1797,6 +1799,8 @@
         "ntlm/ntlm_buffer_reader.h",
         "ntlm/ntlm_buffer_writer.cc",
         "ntlm/ntlm_buffer_writer.h",
+        "ntlm/ntlm_client.cc",
+        "ntlm/ntlm_client.h",
         "ntlm/ntlm_constants.h",
       ]
     }
@@ -4895,6 +4899,7 @@
     "ntlm/des_unittest.cc",
     "ntlm/ntlm_buffer_reader_unittest.cc",
     "ntlm/ntlm_buffer_writer_unittest.cc",
+    "ntlm/ntlm_client_unittest.cc",
     "ntlm/ntlm_test_data.h",
     "ntlm/ntlm_unittest.cc",
     "proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc",
@@ -5313,6 +5318,7 @@
       "ntlm/des_unittest.cc",
       "ntlm/ntlm_buffer_reader_unittest.cc",
       "ntlm/ntlm_buffer_writer_unittest.cc",
+      "ntlm/ntlm_client_unittest.cc",
       "ntlm/ntlm_test_data.h",
       "ntlm/ntlm_unittest.cc",
     ]
@@ -5875,6 +5881,21 @@
   dict = "data/fuzzer_dictionaries/net_http_stream_parser_fuzzer.dict"
 }
 
+fuzzer_test("net_ntlm_ntlm_client_fuzzer") {
+  sources = [
+    "ntlm/ntlm_client_fuzzer.cc",
+  ]
+  deps = [
+    ":net_fuzzer_test_support",
+    ":test_support",
+    "//base",
+    "//net",
+    "//net:net_unittests",
+  ]
+  dict = "data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict"
+  seed_corpus = "data/fuzzer_data/ntlm_client_fuzzer/"
+}
+
 if (!disable_brotli_filter) {
   fuzzer_test("net_brotli_source_stream_fuzzer") {
     sources = [
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_spec_4_2_2_3.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_spec_4_2_2_3.bin
new file mode 100644
index 0000000..e698a39
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_spec_4_2_2_3.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_too_short.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_too_short.bin
new file mode 100644
index 0000000..373e40b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/challenge_too_short.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0001.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0001.bin
new file mode 100644
index 0000000..5fbd821
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0001.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0002.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0002.bin
new file mode 100644
index 0000000..f4ba5237
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0002.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0003.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0003.bin
new file mode 100644
index 0000000..d660270e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0003.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0004.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0004.bin
new file mode 100644
index 0000000..47536b9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0004.bin
@@ -0,0 +1 @@
+NTLMTLM
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0005.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0005.bin
new file mode 100644
index 0000000..7473331
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0005.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0006.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0006.bin
new file mode 100644
index 0000000..59b8622
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0006.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0007.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0007.bin
new file mode 100644
index 0000000..41f9091
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0007.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0008.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0008.bin
new file mode 100644
index 0000000..b606083
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0008.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0009.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0009.bin
new file mode 100644
index 0000000..0b611b6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0009.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0010.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0010.bin
new file mode 100644
index 0000000..81328cc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0010.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0011.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0011.bin
new file mode 100644
index 0000000..c1e5459
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0011.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0012.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0012.bin
new file mode 100644
index 0000000..10b29fc2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0012.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0013.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0013.bin
new file mode 100644
index 0000000..9d8690a8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0013.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0014.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0014.bin
new file mode 100644
index 0000000..4973fb20
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0014.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0015.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0015.bin
new file mode 100644
index 0000000..e8a58405a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0015.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0016.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0016.bin
new file mode 100644
index 0000000..621e80e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0016.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0017.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0017.bin
new file mode 100644
index 0000000..c462bd9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0017.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0018.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0018.bin
new file mode 100644
index 0000000..b67afe0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0018.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0019.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0019.bin
new file mode 100644
index 0000000..bab5e6e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0019.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0020.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0020.bin
new file mode 100644
index 0000000..a30cc54
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0020.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0021.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0021.bin
new file mode 100644
index 0000000..d1c8e05
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0021.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0022.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0022.bin
new file mode 100644
index 0000000..f28fc3d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0022.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0023.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0023.bin
new file mode 100644
index 0000000..f1f4bb4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0023.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0024.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0024.bin
new file mode 100644
index 0000000..a0672f4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0024.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0025.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0025.bin
new file mode 100644
index 0000000..fe0425e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0025.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0026.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0026.bin
new file mode 100644
index 0000000..f8a9023
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0026.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0027.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0027.bin
new file mode 100644
index 0000000..3b00f011
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0027.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0028.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0028.bin
new file mode 100644
index 0000000..614ce50
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0028.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0029.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0029.bin
new file mode 100644
index 0000000..377e0f6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0029.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0030.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0030.bin
new file mode 100644
index 0000000..2104a07
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0030.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0031.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0031.bin
new file mode 100644
index 0000000..7060f5a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0031.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0032.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0032.bin
new file mode 100644
index 0000000..34f14d9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0032.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0033.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0033.bin
new file mode 100644
index 0000000..7020361a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0033.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0034.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0034.bin
new file mode 100644
index 0000000..d9c78d1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0034.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0035.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0035.bin
new file mode 100644
index 0000000..0d390d83
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0035.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0036.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0036.bin
new file mode 100644
index 0000000..8a45436
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0036.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0037.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0037.bin
new file mode 100644
index 0000000..69b0a13
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0037.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0038.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0038.bin
new file mode 100644
index 0000000..af76586
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0038.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0039.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0039.bin
new file mode 100644
index 0000000..8e9671c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0039.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0040.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0040.bin
new file mode 100644
index 0000000..b273002
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0040.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0041.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0041.bin
new file mode 100644
index 0000000..51dfba6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0041.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0042.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0042.bin
new file mode 100644
index 0000000..6e6e09e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0042.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0043.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0043.bin
new file mode 100644
index 0000000..530b0ce2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0043.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0044.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0044.bin
new file mode 100644
index 0000000..5cd8c83
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0044.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0045.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0045.bin
new file mode 100644
index 0000000..03af3a5a9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0045.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0046.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0046.bin
new file mode 100644
index 0000000..8410149
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0046.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0047.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0047.bin
new file mode 100644
index 0000000..926d80a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0047.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0048.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0048.bin
new file mode 100644
index 0000000..13577d2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0048.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0049.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0049.bin
new file mode 100644
index 0000000..4771d6c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0049.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0050.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0050.bin
new file mode 100644
index 0000000..fb65c29c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0050.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0051.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0051.bin
new file mode 100644
index 0000000..8217b184
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0051.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0052.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0052.bin
new file mode 100644
index 0000000..ece8b30
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0052.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0053.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0053.bin
new file mode 100644
index 0000000..699dd92
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0053.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0054.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0054.bin
new file mode 100644
index 0000000..38e4308
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0054.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0055.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0055.bin
new file mode 100644
index 0000000..cbc53af
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0055.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0056.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0056.bin
new file mode 100644
index 0000000..f221f8f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0056.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0057.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0057.bin
new file mode 100644
index 0000000..512f14e38
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0057.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0058.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0058.bin
new file mode 100644
index 0000000..9e1d0a0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0058.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0059.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0059.bin
new file mode 100644
index 0000000..caece732
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0059.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0060.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0060.bin
new file mode 100644
index 0000000..9debe5f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0060.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0061.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0061.bin
new file mode 100644
index 0000000..280e506
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0061.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0062.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0062.bin
new file mode 100644
index 0000000..845c743c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0062.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0063.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0063.bin
new file mode 100644
index 0000000..725e684
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0063.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0064.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0064.bin
new file mode 100644
index 0000000..ba17f74
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0064.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0065.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0065.bin
new file mode 100644
index 0000000..3456bc1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0065.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0066.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0066.bin
new file mode 100644
index 0000000..cc59ed3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0066.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0067.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0067.bin
new file mode 100644
index 0000000..bf33a20
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0067.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0068.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0068.bin
new file mode 100644
index 0000000..6c4f277
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0068.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0069.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0069.bin
new file mode 100644
index 0000000..ee77d1b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0069.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0070.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0070.bin
new file mode 100644
index 0000000..46ca637
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0070.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0071.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0071.bin
new file mode 100644
index 0000000..c2d975c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0071.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0072.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0072.bin
new file mode 100644
index 0000000..e4dde45
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0072.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0073.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0073.bin
new file mode 100644
index 0000000..91f3030
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0073.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0074.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0074.bin
new file mode 100644
index 0000000..7c5957a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0074.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0075.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0075.bin
new file mode 100644
index 0000000..88dd3bf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0075.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0076.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0076.bin
new file mode 100644
index 0000000..86a30c0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0076.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0077.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0077.bin
new file mode 100644
index 0000000..9efe98e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0077.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0078.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0078.bin
new file mode 100644
index 0000000..750b9aa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0078.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0079.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0079.bin
new file mode 100644
index 0000000..ab9857d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0079.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0080.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0080.bin
new file mode 100644
index 0000000..924ee6b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0080.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0081.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0081.bin
new file mode 100644
index 0000000..0ff800ef
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0081.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0082.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0082.bin
new file mode 100644
index 0000000..00bd3be
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0082.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0083.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0083.bin
new file mode 100644
index 0000000..c425134
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0083.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0084.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0084.bin
new file mode 100644
index 0000000..0e67c2c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0084.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0085.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0085.bin
new file mode 100644
index 0000000..3706e12
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0085.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0086.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0086.bin
new file mode 100644
index 0000000..adf3728
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0086.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0087.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0087.bin
new file mode 100644
index 0000000..0d68d69
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0087.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0088.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0088.bin
new file mode 100644
index 0000000..26c582d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0088.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0089.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0089.bin
new file mode 100644
index 0000000..7f9ab4e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0089.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0090.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0090.bin
new file mode 100644
index 0000000..f79a15d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0090.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0091.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0091.bin
new file mode 100644
index 0000000..28c50a5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0091.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0092.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0092.bin
new file mode 100644
index 0000000..f3cae66
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0092.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0093.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0093.bin
new file mode 100644
index 0000000..8242183
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0093.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0094.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0094.bin
new file mode 100644
index 0000000..deabfc2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0094.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0095.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0095.bin
new file mode 100644
index 0000000..fd15789
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0095.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0096.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0096.bin
new file mode 100644
index 0000000..fa7bbeb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0096.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0097.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0097.bin
new file mode 100644
index 0000000..2cf1abb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0097.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0098.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0098.bin
new file mode 100644
index 0000000..00ac7a3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0098.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0099.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0099.bin
new file mode 100644
index 0000000..330d7cf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0099.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0100.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0100.bin
new file mode 100644
index 0000000..bca0c582
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0100.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0101.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0101.bin
new file mode 100644
index 0000000..6b44f59
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0101.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0102.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0102.bin
new file mode 100644
index 0000000..5b628fe1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0102.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0103.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0103.bin
new file mode 100644
index 0000000..7999eb7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0103.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0104.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0104.bin
new file mode 100644
index 0000000..66f711e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0104.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0105.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0105.bin
new file mode 100644
index 0000000..6e164b5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0105.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0106.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0106.bin
new file mode 100644
index 0000000..83d22c21
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0106.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0107.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0107.bin
new file mode 100644
index 0000000..d7a1bd9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0107.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0108.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0108.bin
new file mode 100644
index 0000000..7381ba6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0108.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0109.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0109.bin
new file mode 100644
index 0000000..a69095c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0109.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0110.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0110.bin
new file mode 100644
index 0000000..88f9980
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0110.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0111.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0111.bin
new file mode 100644
index 0000000..1003e284
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0111.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0112.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0112.bin
new file mode 100644
index 0000000..0e62a66
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0112.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0113.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0113.bin
new file mode 100644
index 0000000..38ae0fb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0113.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0114.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0114.bin
new file mode 100644
index 0000000..a506e02
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0114.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0115.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0115.bin
new file mode 100644
index 0000000..91a4aa8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0115.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0116.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0116.bin
new file mode 100644
index 0000000..09efefa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0116.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0117.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0117.bin
new file mode 100644
index 0000000..af1652c3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0117.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0118.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0118.bin
new file mode 100644
index 0000000..a0874e3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0118.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0119.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0119.bin
new file mode 100644
index 0000000..4a018dd8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0119.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0120.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0120.bin
new file mode 100644
index 0000000..b6be5c2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0120.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0121.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0121.bin
new file mode 100644
index 0000000..8bb62ee
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0121.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0122.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0122.bin
new file mode 100644
index 0000000..272dc16
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0122.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0123.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0123.bin
new file mode 100644
index 0000000..04508d64
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0123.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0124.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0124.bin
new file mode 100644
index 0000000..4530dd4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0124.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0125.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0125.bin
new file mode 100644
index 0000000..3c8dbb50
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0125.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0126.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0126.bin
new file mode 100644
index 0000000..98754153
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0126.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0127.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0127.bin
new file mode 100644
index 0000000..c1496ce
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0127.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0128.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0128.bin
new file mode 100644
index 0000000..fcd602de
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0128.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0129.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0129.bin
new file mode 100644
index 0000000..6a93485
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0129.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0130.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0130.bin
new file mode 100644
index 0000000..11e4731
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0130.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0131.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0131.bin
new file mode 100644
index 0000000..59b9e48
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0131.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0132.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0132.bin
new file mode 100644
index 0000000..77eef11
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0132.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0133.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0133.bin
new file mode 100644
index 0000000..3a18b53
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0133.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0134.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0134.bin
new file mode 100644
index 0000000..4de9ffa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0134.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0135.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0135.bin
new file mode 100644
index 0000000..345ee99
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0135.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0136.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0136.bin
new file mode 100644
index 0000000..0673656
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0136.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0137.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0137.bin
new file mode 100644
index 0000000..ee10d17
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0137.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0138.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0138.bin
new file mode 100644
index 0000000..0582d75
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0138.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0139.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0139.bin
new file mode 100644
index 0000000..a97ba95
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0139.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0140.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0140.bin
new file mode 100644
index 0000000..e665e49
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0140.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0141.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0141.bin
new file mode 100644
index 0000000..cc12b12
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0141.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0142.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0142.bin
new file mode 100644
index 0000000..e302b08
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0142.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0143.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0143.bin
new file mode 100644
index 0000000..d80571b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0143.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0144.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0144.bin
new file mode 100644
index 0000000..4421a7a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0144.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0145.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0145.bin
new file mode 100644
index 0000000..c1ee371d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0145.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0146.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0146.bin
new file mode 100644
index 0000000..13b34ec5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0146.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0147.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0147.bin
new file mode 100644
index 0000000..ab07749
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0147.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0148.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0148.bin
new file mode 100644
index 0000000..8c66a052
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0148.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0149.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0149.bin
new file mode 100644
index 0000000..5c5302f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0149.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0150.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0150.bin
new file mode 100644
index 0000000..6ba161ab
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0150.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0151.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0151.bin
new file mode 100644
index 0000000..3818c137
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0151.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0152.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0152.bin
new file mode 100644
index 0000000..39fd63d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0152.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0153.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0153.bin
new file mode 100644
index 0000000..2d27dde4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0153.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0154.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0154.bin
new file mode 100644
index 0000000..7454103
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0154.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0155.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0155.bin
new file mode 100644
index 0000000..c0add9e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0155.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0156.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0156.bin
new file mode 100644
index 0000000..6b85869
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0156.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0157.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0157.bin
new file mode 100644
index 0000000..c777eef8
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0157.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0158.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0158.bin
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0158.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0159.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0159.bin
new file mode 100644
index 0000000..8e0b967
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0159.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0160.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0160.bin
new file mode 100644
index 0000000..5faf34c6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0160.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0161.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0161.bin
new file mode 100644
index 0000000..931ca76
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0161.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0162.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0162.bin
new file mode 100644
index 0000000..43d8d4e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0162.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0163.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0163.bin
new file mode 100644
index 0000000..9fc7abe0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0163.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0164.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0164.bin
new file mode 100644
index 0000000..3ed4d46
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0164.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0165.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0165.bin
new file mode 100644
index 0000000..aa1b137
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0165.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0166.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0166.bin
new file mode 100644
index 0000000..e9e2746
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0166.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0167.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0167.bin
new file mode 100644
index 0000000..bc57d7fa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0167.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0168.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0168.bin
new file mode 100644
index 0000000..db6143d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0168.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0169.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0169.bin
new file mode 100644
index 0000000..f7e2f37
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0169.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0170.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0170.bin
new file mode 100644
index 0000000..afa5fcb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0170.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0171.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0171.bin
new file mode 100644
index 0000000..1bc1469
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0171.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0172.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0172.bin
new file mode 100644
index 0000000..77589fd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0172.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0173.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0173.bin
new file mode 100644
index 0000000..341e1294
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0173.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0174.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0174.bin
new file mode 100644
index 0000000..f600051
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0174.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0175.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0175.bin
new file mode 100644
index 0000000..cb85e40
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0175.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0176.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0176.bin
new file mode 100644
index 0000000..4757964
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0176.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0177.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0177.bin
new file mode 100644
index 0000000..c61395e7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0177.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0178.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0178.bin
new file mode 100644
index 0000000..244324df
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0178.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0179.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0179.bin
new file mode 100644
index 0000000..76fafad
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0179.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0180.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0180.bin
new file mode 100644
index 0000000..f607889
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0180.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0181.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0181.bin
new file mode 100644
index 0000000..97eeb3d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0181.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0182.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0182.bin
new file mode 100644
index 0000000..420ecf17
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0182.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0183.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0183.bin
new file mode 100644
index 0000000..3d64a16
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0183.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0184.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0184.bin
new file mode 100644
index 0000000..6c6e27e2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0184.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0185.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0185.bin
new file mode 100644
index 0000000..18aff61dc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0185.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0186.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0186.bin
new file mode 100644
index 0000000..5565fae
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0186.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0187.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0187.bin
new file mode 100644
index 0000000..8b4d50f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0187.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0188.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0188.bin
new file mode 100644
index 0000000..1116e15
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0188.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0189.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0189.bin
new file mode 100644
index 0000000..c8e21bd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0189.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0190.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0190.bin
new file mode 100644
index 0000000..cb8ba0ec
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0190.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0191.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0191.bin
new file mode 100644
index 0000000..f28fcca
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0191.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0192.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0192.bin
new file mode 100644
index 0000000..ff9b900
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0192.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0193.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0193.bin
new file mode 100644
index 0000000..71b3783
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0193.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0194.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0194.bin
new file mode 100644
index 0000000..8d9d867e
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0194.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0195.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0195.bin
new file mode 100644
index 0000000..2a35617
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0195.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0196.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0196.bin
new file mode 100644
index 0000000..a021ead
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0196.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0197.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0197.bin
new file mode 100644
index 0000000..bfdc2c3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0197.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0198.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0198.bin
new file mode 100644
index 0000000..4538d31
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0198.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0199.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0199.bin
new file mode 100644
index 0000000..2b32f8a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0199.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0200.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0200.bin
new file mode 100644
index 0000000..eb21f6bf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0200.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0201.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0201.bin
new file mode 100644
index 0000000..3ee1496
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0201.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0202.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0202.bin
new file mode 100644
index 0000000..359c465
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0202.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0203.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0203.bin
new file mode 100644
index 0000000..8ed1725
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0203.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0204.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0204.bin
new file mode 100644
index 0000000..f8b0ec2
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0204.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0205.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0205.bin
new file mode 100644
index 0000000..dce527ae
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0205.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0206.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0206.bin
new file mode 100644
index 0000000..a048fff
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0206.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0207.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0207.bin
new file mode 100644
index 0000000..9be79a5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0207.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0208.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0208.bin
new file mode 100644
index 0000000..d887e8f1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0208.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0209.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0209.bin
new file mode 100644
index 0000000..cc4e2f1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0209.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0210.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0210.bin
new file mode 100644
index 0000000..054d8cb
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0210.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0211.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0211.bin
new file mode 100644
index 0000000..099130d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0211.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0212.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0212.bin
new file mode 100644
index 0000000..aaf4a625
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0212.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0213.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0213.bin
new file mode 100644
index 0000000..96252735
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0213.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0214.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0214.bin
new file mode 100644
index 0000000..57a2115
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0214.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0215.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0215.bin
new file mode 100644
index 0000000..0699fa3d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0215.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0216.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0216.bin
new file mode 100644
index 0000000..62fca99
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0216.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0217.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0217.bin
new file mode 100644
index 0000000..0149eae1
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0217.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0218.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0218.bin
new file mode 100644
index 0000000..2a3a155
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0218.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0219.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0219.bin
new file mode 100644
index 0000000..0fe6457
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0219.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0220.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0220.bin
new file mode 100644
index 0000000..010f53b5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0220.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0221.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0221.bin
new file mode 100644
index 0000000..aead929
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0221.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0222.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0222.bin
new file mode 100644
index 0000000..7090ef3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0222.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0223.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0223.bin
new file mode 100644
index 0000000..c06942a9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0223.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0224.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0224.bin
new file mode 100644
index 0000000..d2f52926
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0224.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0225.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0225.bin
new file mode 100644
index 0000000..11084fa
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0225.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0226.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0226.bin
new file mode 100644
index 0000000..67d166ae
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0226.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0227.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0227.bin
new file mode 100644
index 0000000..b19336f5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0227.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0228.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0228.bin
new file mode 100644
index 0000000..cf6d673
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0228.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0229.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0229.bin
new file mode 100644
index 0000000..10a4faf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0229.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0230.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0230.bin
new file mode 100644
index 0000000..3d10e15
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0230.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0231.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0231.bin
new file mode 100644
index 0000000..0ac57fb4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0231.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0232.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0232.bin
new file mode 100644
index 0000000..dbd466440
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0232.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0233.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0233.bin
new file mode 100644
index 0000000..32ba27d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0233.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0234.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0234.bin
new file mode 100644
index 0000000..6e3bb081
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0234.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0235.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0235.bin
new file mode 100644
index 0000000..70b881d5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0235.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0236.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0236.bin
new file mode 100644
index 0000000..0f3333f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0236.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0237.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0237.bin
new file mode 100644
index 0000000..2b4ae31c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0237.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0238.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0238.bin
new file mode 100644
index 0000000..23060649
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0238.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0239.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0239.bin
new file mode 100644
index 0000000..18f4ac7d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0239.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0240.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0240.bin
new file mode 100644
index 0000000..4f8e3ae
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0240.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0241.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0241.bin
new file mode 100644
index 0000000..7e68a9d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0241.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0242.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0242.bin
new file mode 100644
index 0000000..f12dd875
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0242.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0243.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0243.bin
new file mode 100644
index 0000000..ca613df
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0243.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0244.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0244.bin
new file mode 100644
index 0000000..4dfa10d0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0244.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0245.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0245.bin
new file mode 100644
index 0000000..28f7803
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0245.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0246.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0246.bin
new file mode 100644
index 0000000..ed9c8ec
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0246.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0247.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0247.bin
new file mode 100644
index 0000000..a6e37a05
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0247.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0248.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0248.bin
new file mode 100644
index 0000000..084d44d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0248.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0249.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0249.bin
new file mode 100644
index 0000000..5c6d187c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0249.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0250.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0250.bin
new file mode 100644
index 0000000..558758d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0250.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0251.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0251.bin
new file mode 100644
index 0000000..8ace642
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0251.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0252.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0252.bin
new file mode 100644
index 0000000..9976ddd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0252.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0253.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0253.bin
new file mode 100644
index 0000000..1c8b94f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0253.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0254.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0254.bin
new file mode 100644
index 0000000..11e7b415f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0254.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0255.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0255.bin
new file mode 100644
index 0000000..b19711d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0255.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0256.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0256.bin
new file mode 100644
index 0000000..e2835ff
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0256.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0257.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0257.bin
new file mode 100644
index 0000000..4a8b194c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0257.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0258.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0258.bin
new file mode 100644
index 0000000..373e3104
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0258.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0259.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0259.bin
new file mode 100644
index 0000000..508a701
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0259.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0260.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0260.bin
new file mode 100644
index 0000000..7c1692b
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0260.bin
@@ -0,0 +1 @@
+NááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááááTLMTLM
\ No newline at end of file
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0261.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0261.bin
new file mode 100644
index 0000000..188eb32
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0261.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0262.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0262.bin
new file mode 100644
index 0000000..aa8587d02
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0262.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0263.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0263.bin
new file mode 100644
index 0000000..46418dc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0263.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0264.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0264.bin
new file mode 100644
index 0000000..50a9ba2c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0264.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0265.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0265.bin
new file mode 100644
index 0000000..8a2dbbd4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0265.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0266.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0266.bin
new file mode 100644
index 0000000..e0c66139
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0266.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0267.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0267.bin
new file mode 100644
index 0000000..e62d1d5
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0267.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0268.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0268.bin
new file mode 100644
index 0000000..b9c13fcd7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0268.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0269.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0269.bin
new file mode 100644
index 0000000..8fc96c1c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0269.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0270.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0270.bin
new file mode 100644
index 0000000..2777fb3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0270.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0271.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0271.bin
new file mode 100644
index 0000000..508f0344
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0271.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0272.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0272.bin
new file mode 100644
index 0000000..ba3d348
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0272.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0273.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0273.bin
new file mode 100644
index 0000000..f3b6d04
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0273.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0274.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0274.bin
new file mode 100644
index 0000000..03ebbda7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0274.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0275.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0275.bin
new file mode 100644
index 0000000..f9518471
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0275.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0276.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0276.bin
new file mode 100644
index 0000000..e8d6d96cd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0276.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0277.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0277.bin
new file mode 100644
index 0000000..a20d91d
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0277.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0278.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0278.bin
new file mode 100644
index 0000000..fe5a9732
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0278.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0279.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0279.bin
new file mode 100644
index 0000000..acbac321
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0279.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0280.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0280.bin
new file mode 100644
index 0000000..c5ec44a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0280.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0281.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0281.bin
new file mode 100644
index 0000000..76d5cb773
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0281.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0282.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0282.bin
new file mode 100644
index 0000000..06228e9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0282.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0283.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0283.bin
new file mode 100644
index 0000000..71e55dd
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0283.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0284.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0284.bin
new file mode 100644
index 0000000..495629f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0284.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0285.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0285.bin
new file mode 100644
index 0000000..3caf33c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0285.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0286.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0286.bin
new file mode 100644
index 0000000..d251b2a
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0286.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0287.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0287.bin
new file mode 100644
index 0000000..6f6a5f1f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0287.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0288.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0288.bin
new file mode 100644
index 0000000..07bed6b4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0288.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0289.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0289.bin
new file mode 100644
index 0000000..b6ccccf
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0289.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0290.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0290.bin
new file mode 100644
index 0000000..487c5e4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0290.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0291.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0291.bin
new file mode 100644
index 0000000..2e0cb65
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0291.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0292.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0292.bin
new file mode 100644
index 0000000..687ae92
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0292.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0293.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0293.bin
new file mode 100644
index 0000000..b3433a7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0293.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0294.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0294.bin
new file mode 100644
index 0000000..b70f5b9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0294.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0295.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0295.bin
new file mode 100644
index 0000000..bad3311
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0295.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0296.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0296.bin
new file mode 100644
index 0000000..cacebbe
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0296.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0297.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0297.bin
new file mode 100644
index 0000000..ca7c259
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0297.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0298.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0298.bin
new file mode 100644
index 0000000..68decb3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0298.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0299.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0299.bin
new file mode 100644
index 0000000..5668a23ab
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0299.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0300.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0300.bin
new file mode 100644
index 0000000..4227ca4
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0300.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0301.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0301.bin
new file mode 100644
index 0000000..8c05a65
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0301.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0302.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0302.bin
new file mode 100644
index 0000000..b3719eb3
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0302.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0303.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0303.bin
new file mode 100644
index 0000000..5746787
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0303.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0304.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0304.bin
new file mode 100644
index 0000000..28c4a85
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0304.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0305.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0305.bin
new file mode 100644
index 0000000..f9cd719
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/generated_challenge_0305.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge.bin
new file mode 100644
index 0000000..bbe0118f
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_ss.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_ss.bin
new file mode 100644
index 0000000..e3cb357
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_ss.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_unicode.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_unicode.bin
new file mode 100644
index 0000000..f7398628
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_no_unicode.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow.bin
new file mode 100644
index 0000000..568c63c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow2.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow2.bin
new file mode 100644
index 0000000..ad4fea0
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_len_overflow2.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_offset_overflow.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_offset_overflow.bin
new file mode 100644
index 0000000..338099c
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_target_name_offset_overflow.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_with_target_name.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_with_target_name.bin
new file mode 100644
index 0000000..24b02fc
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_with_target_name.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_message_type.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_message_type.bin
new file mode 100644
index 0000000..2ec29f6
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_message_type.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_signature.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_signature.bin
new file mode 100644
index 0000000..67ad5ee7
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_wrong_signature.bin
Binary files differ
diff --git a/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_zero_target_name_offset.bin b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_zero_target_name_offset.bin
new file mode 100644
index 0000000..5e832b9
--- /dev/null
+++ b/net/data/fuzzer_data/ntlm_client_fuzzer/min_challenge_zero_target_name_offset.bin
Binary files differ
diff --git a/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict b/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict
new file mode 100644
index 0000000..93b46b43
--- /dev/null
+++ b/net/data/fuzzer_dictionaries/net_ntlm_ntlm_client_fuzzer.dict
@@ -0,0 +1,36 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Signature
+"NTLMSSP\x00"
+
+# Message Types
+"\x01\x00\x00\x00"
+"\x02\x00\x00\x00"
+"\x03\x00\x00\x00"
+
+# Common Target Name offset
+"\x20\x00\x00\x00"
+
+# Useful security buffer lengths to match "Server"
+"\x06\x00"
+"\x0c\x00"
+
+# Common\interesting flag values
+"\x07\x82\x08\x00"
+"\x06\x82\x08\x00"
+"\x07\x82\x00\x00"
+"\x06\x82\x00\x00"
+"\x01\x00\x08\x00"
+"\x02\x00\x08\x00"
+"\x03\x00\x08\x00"
+"\x01\x00\x00\x00"
+"\x02\x00\x00\x00"
+"\x03\x00\x00\x00"
+"\x08\x00"
+"\x00\x00"
+
+# Target Names
+"Server"
+"S\x00e\x00r\x00v\x00e\x00r\x00"
\ No newline at end of file
diff --git a/net/ntlm/ntlm_client.cc b/net/ntlm/ntlm_client.cc
new file mode 100644
index 0000000..a2b8f54
--- /dev/null
+++ b/net/ntlm/ntlm_client.cc
@@ -0,0 +1,253 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/ntlm/ntlm_client.h"
+
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "net/ntlm/ntlm.h"
+#include "net/ntlm/ntlm_buffer_reader.h"
+#include "net/ntlm/ntlm_buffer_writer.h"
+
+namespace net {
+namespace ntlm {
+
+namespace {
+// Parses the challenge message and returns the |challenge_flags| and
+// |server_challenge| into the supplied buffer.
+// |server_challenge| must contain at least 8 bytes.
+bool ParseChallengeMessage(const Buffer& challenge_message,
+                           NegotiateFlags* challenge_flags,
+                           uint8_t* server_challenge) {
+  NtlmBufferReader challenge_reader(challenge_message);
+
+  return challenge_reader.MatchMessageHeader(MessageType::kChallenge) &&
+         challenge_reader.SkipSecurityBufferWithValidation() &&
+         challenge_reader.ReadFlags(challenge_flags) &&
+         challenge_reader.ReadBytes(server_challenge, kChallengeLen);
+}
+
+bool WriteAuthenticateMessage(NtlmBufferWriter* authenticate_writer,
+                              SecurityBuffer lm_payload,
+                              SecurityBuffer ntlm_payload,
+                              SecurityBuffer domain_payload,
+                              SecurityBuffer username_payload,
+                              SecurityBuffer hostname_payload,
+                              NegotiateFlags authenticate_flags) {
+  return authenticate_writer->WriteMessageHeader(MessageType::kAuthenticate) &&
+         authenticate_writer->WriteSecurityBuffer(lm_payload) &&
+         authenticate_writer->WriteSecurityBuffer(ntlm_payload) &&
+         authenticate_writer->WriteSecurityBuffer(domain_payload) &&
+         authenticate_writer->WriteSecurityBuffer(username_payload) &&
+         authenticate_writer->WriteSecurityBuffer(hostname_payload) &&
+         authenticate_writer->WriteSecurityBuffer(
+             SecurityBuffer(kAuthenticateHeaderLenV1, 0)) &&
+         authenticate_writer->WriteFlags(authenticate_flags);
+}
+
+bool WriteResponsePayloads(NtlmBufferWriter* authenticate_writer,
+                           const uint8_t* lm_response,
+                           size_t lm_response_len,
+                           const uint8_t* ntlm_response,
+                           size_t ntlm_response_len) {
+  return authenticate_writer->WriteBytes(lm_response, lm_response_len) &&
+         authenticate_writer->WriteBytes(ntlm_response, ntlm_response_len);
+}
+
+bool WriteStringPayloads(NtlmBufferWriter* authenticate_writer,
+                         bool is_unicode,
+                         const base::string16& domain,
+                         const base::string16& username,
+                         const std::string& hostname) {
+  if (is_unicode) {
+    return authenticate_writer->WriteUtf16String(domain) &&
+           authenticate_writer->WriteUtf16String(username) &&
+           authenticate_writer->WriteUtf8AsUtf16String(hostname);
+  } else {
+    return authenticate_writer->WriteUtf16AsUtf8String(domain) &&
+           authenticate_writer->WriteUtf16AsUtf8String(username) &&
+           authenticate_writer->WriteUtf8String(hostname);
+  }
+}
+
+// Returns the size in bytes of a string16 depending whether unicode
+// was negotiated.
+size_t GetStringPayloadLength(const base::string16& str, bool is_unicode) {
+  if (is_unicode)
+    return str.length() * 2;
+
+  // When |WriteUtf16AsUtf8String| is called with a |base::string16|, the string
+  // is converted to UTF8. Do the conversion to ensure that the character
+  // count is correct.
+  return base::UTF16ToUTF8(str).length();
+}
+
+// Returns the size in bytes of a std::string depending whether unicode
+// was negotiated.
+size_t GetStringPayloadLength(const std::string& str, bool is_unicode) {
+  if (!is_unicode)
+    return str.length();
+
+  return base::UTF8ToUTF16(str).length() * 2;
+}
+
+}  // namespace
+
+NtlmClient::NtlmClient() : negotiate_flags_(kNegotiateMessageFlags) {
+  // Just generate the negotiate message once and hold on to it. It never
+  // changes and in a NTLMv2 it's used as an input
+  // to the Message Integrity Check in the Authenticate message.
+  GenerateNegotiateMessage();
+}
+
+NtlmClient::~NtlmClient() {}
+
+Buffer NtlmClient::GetNegotiateMessage() const {
+  return negotiate_message_;
+}
+
+void NtlmClient::GenerateNegotiateMessage() {
+  NtlmBufferWriter writer(kNegotiateMessageLen);
+  bool result =
+      writer.WriteMessageHeader(MessageType::kNegotiate) &&
+      writer.WriteFlags(negotiate_flags_) &&
+      writer.WriteSecurityBuffer(SecurityBuffer(kNegotiateMessageLen, 0)) &&
+      writer.WriteSecurityBuffer(SecurityBuffer(kNegotiateMessageLen, 0)) &&
+      writer.IsEndOfBuffer();
+
+  DCHECK(result);
+
+  negotiate_message_ = writer.Pass();
+}
+
+Buffer NtlmClient::GenerateAuthenticateMessage(
+    const base::string16& domain,
+    const base::string16& username,
+    const base::string16& password,
+    const std::string& hostname,
+    const uint8_t* client_challenge,
+    const Buffer& server_challenge_message) const {
+  // Limit the size of strings that are accepted. As an absolute limit any
+  // field represented by a |SecurityBuffer| or |AvPair| must be less than
+  // UINT16_MAX bytes long. The strings are restricted to the maximum sizes
+  // without regard to encoding. As such this isn't intended to restrict all
+  // invalid inputs, only to allow all possible valid inputs.
+  //
+  // |domain| and |hostname| can be no longer than 255 characters.
+  // |username| can be no longer than 104 characters. See [1].
+  // |password| can be no longer than 256 characters. See [2].
+  //
+  // [1] - https://technet.microsoft.com/en-us/library/bb726984.aspx
+  // [2] - https://technet.microsoft.com/en-us/library/cc512606.aspx
+  if (hostname.length() > kMaxFqdnLen || domain.length() > kMaxFqdnLen ||
+      username.length() > kMaxUsernameLen ||
+      password.length() > kMaxPasswordLen)
+    return Buffer();
+
+  NegotiateFlags challenge_flags;
+  uint8_t server_challenge[kChallengeLen];
+
+  // Read the flags and the server's random challenge from the challenge
+  // message.
+  if (!ParseChallengeMessage(server_challenge_message, &challenge_flags,
+                             server_challenge)) {
+    return Buffer();
+  }
+
+  // Calculate the responses for the authenticate message.
+  uint8_t lm_response[kResponseLenV1];
+  uint8_t ntlm_response[kResponseLenV1];
+
+  // Always use extended session security even if the server tries to downgrade.
+  NegotiateFlags authenticate_flags = (challenge_flags & negotiate_flags_) |
+                                      NegotiateFlags::kExtendedSessionSecurity;
+
+  // Generate the LM and NTLM responses.
+  GenerateResponsesV1WithSessionSecurity(
+      password, server_challenge, client_challenge, lm_response, ntlm_response);
+
+  // Calculate all the payload lengths and offsets.
+  bool is_unicode = (authenticate_flags & NegotiateFlags::kUnicode) ==
+                    NegotiateFlags::kUnicode;
+
+  SecurityBuffer lm_info;
+  SecurityBuffer ntlm_info;
+  SecurityBuffer domain_info;
+  SecurityBuffer username_info;
+  SecurityBuffer hostname_info;
+  size_t authenticate_message_len;
+  CalculatePayloadLayout(is_unicode, domain, username, hostname, &lm_info,
+                         &ntlm_info, &domain_info, &username_info,
+                         &hostname_info, &authenticate_message_len);
+
+  NtlmBufferWriter authenticate_writer(authenticate_message_len);
+  bool writer_result = WriteAuthenticateMessage(
+      &authenticate_writer, lm_info, ntlm_info, domain_info, username_info,
+      hostname_info, authenticate_flags);
+  DCHECK(writer_result);
+  DCHECK_EQ(authenticate_writer.GetCursor(), GetAuthenticateHeaderLength());
+
+  writer_result =
+      WriteResponsePayloads(&authenticate_writer, lm_response, lm_info.length,
+                            ntlm_response, ntlm_info.length);
+  DCHECK(writer_result);
+  DCHECK_EQ(authenticate_writer.GetCursor(), domain_info.offset);
+
+  writer_result = WriteStringPayloads(&authenticate_writer, is_unicode, domain,
+                                      username, hostname);
+  DCHECK(writer_result);
+  DCHECK(authenticate_writer.IsEndOfBuffer());
+  DCHECK_EQ(authenticate_message_len, authenticate_writer.GetLength());
+
+  return authenticate_writer.Pass();
+}
+
+void NtlmClient::CalculatePayloadLayout(
+    bool is_unicode,
+    const base::string16& domain,
+    const base::string16& username,
+    const std::string& hostname,
+    SecurityBuffer* lm_info,
+    SecurityBuffer* ntlm_info,
+    SecurityBuffer* domain_info,
+    SecurityBuffer* username_info,
+    SecurityBuffer* hostname_info,
+    size_t* authenticate_message_len) const {
+  size_t upto = GetAuthenticateHeaderLength();
+
+  lm_info->offset = upto;
+  lm_info->length = kResponseLenV1;
+  upto += lm_info->length;
+
+  ntlm_info->offset = upto;
+  ntlm_info->length = GetNtlmResponseLength();
+  upto += ntlm_info->length;
+
+  domain_info->offset = upto;
+  domain_info->length = GetStringPayloadLength(domain, is_unicode);
+  upto += domain_info->length;
+
+  username_info->offset = upto;
+  username_info->length = GetStringPayloadLength(username, is_unicode);
+  upto += username_info->length;
+
+  hostname_info->offset = upto;
+  hostname_info->length = GetStringPayloadLength(hostname, is_unicode);
+  upto += hostname_info->length;
+
+  *authenticate_message_len = upto;
+}
+
+size_t NtlmClient::GetAuthenticateHeaderLength() const {
+  return kAuthenticateHeaderLenV1;
+}
+
+size_t NtlmClient::GetNtlmResponseLength() const {
+  return kResponseLenV1;
+}
+
+}  // namespace ntlm
+}  // namespace net
\ No newline at end of file
diff --git a/net/ntlm/ntlm_client.h b/net/ntlm/ntlm_client.h
new file mode 100644
index 0000000..94dd8c9
--- /dev/null
+++ b/net/ntlm/ntlm_client.h
@@ -0,0 +1,93 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
+// Specification version 28.0 [1]. Additional NTLM reference [2].
+//
+// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
+// [2] http://davenport.sourceforge.net/ntlm.html
+
+#ifndef NET_BASE_NTLM_CLIENT_H_
+#define NET_BASE_NTLM_CLIENT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/ntlm/ntlm_constants.h"
+
+namespace net {
+namespace ntlm {
+
+// Provides an implementation of an NTLMv1 Client.
+//
+// The implementation supports NTLMv1 with extended session security (NTLM2).
+class NET_EXPORT_PRIVATE NtlmClient {
+ public:
+  NtlmClient();
+  ~NtlmClient();
+
+  // Returns a |Buffer| containing the Negotiate message.
+  Buffer GetNegotiateMessage() const;
+
+  // Returns a |Buffer| containing the Authenticate message. If the method
+  // fails an empty |Buffer| is returned.
+  //
+  // |hostname| can be a short NetBIOS name or an FQDN, however the server will
+  // only inspect this field if the default domain policy is to restrict NTLM.
+  // In this case the hostname will be compared to a whitelist stored in this
+  // group policy [1].
+  // |client_challenge| must contain 8 bytes of random data.
+  // |server_challenge_message| is the full content of the challenge message
+  // sent by the server.
+  //
+  // [1] - https://technet.microsoft.com/en-us/library/jj852267(v=ws.11).aspx
+  Buffer GenerateAuthenticateMessage(
+      const base::string16& domain,
+      const base::string16& username,
+      const base::string16& password,
+      const std::string& hostname,
+      const uint8_t* client_challenge,
+      const Buffer& server_challenge_message) const;
+
+ private:
+  // Calculates the lengths and offset for all the payloads in the message.
+  void CalculatePayloadLayout(bool is_unicode,
+                              const base::string16& domain,
+                              const base::string16& username,
+                              const std::string& hostname,
+                              SecurityBuffer* lm_info,
+                              SecurityBuffer* ntlm_info,
+                              SecurityBuffer* domain_info,
+                              SecurityBuffer* username_info,
+                              SecurityBuffer* hostname_info,
+                              size_t* authenticate_message_len) const;
+
+  // Returns the length of the header part of the Authenticate message.
+  // NOTE: When NTLMv2 support is added this is no longer a fixed value.
+  size_t GetAuthenticateHeaderLength() const;
+
+  // Returns the length of the NTLM response.
+  // NOTE: When NTLMv2 support is added this is no longer a fixed value.
+  size_t GetNtlmResponseLength() const;
+
+  // Generates the negotiate message (which is always the same) into
+  // |negotiate_message_|.
+  void GenerateNegotiateMessage();
+
+  NegotiateFlags negotiate_flags_;
+  Buffer negotiate_message_;
+
+  DISALLOW_COPY_AND_ASSIGN(NtlmClient);
+};
+
+}  // namespace ntlm
+}  // namespace net
+
+#endif  // NET_BASE_NTLM_CLIENT_H_
\ No newline at end of file
diff --git a/net/ntlm/ntlm_client_fuzzer.cc b/net/ntlm/ntlm_client_fuzzer.cc
new file mode 100644
index 0000000..e937f69
--- /dev/null
+++ b/net/ntlm/ntlm_client_fuzzer.cc
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/test/fuzzed_data_provider.h"
+#include "net/ntlm/ntlm_client.h"
+#include "net/ntlm/ntlm_test_data.h"
+
+base::string16 ConsumeRandomLengthString16(
+    base::FuzzedDataProvider& data_provider,
+    size_t max_chars) {
+  std::string bytes = data_provider.ConsumeRandomLengthString(max_chars * 2);
+  return base::string16(reinterpret_cast<const base::char16*>(bytes.data()),
+                        bytes.size() / 2);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  net::ntlm::NtlmClient client;
+
+  // Generate the input strings and challenge message. The strings will have a
+  // maximum length 1 character longer than the maximum that |NtlmClient| will
+  // accept to allow exploring the error cases.
+  base::FuzzedDataProvider fdp(data, size);
+  base::string16 domain =
+      ConsumeRandomLengthString16(fdp, net::ntlm::kMaxFqdnLen + 1);
+  base::string16 username =
+      ConsumeRandomLengthString16(fdp, net::ntlm::kMaxUsernameLen + 1);
+  base::string16 password =
+      ConsumeRandomLengthString16(fdp, net::ntlm::kMaxPasswordLen + 1);
+  std::string hostname =
+      fdp.ConsumeRandomLengthString(net::ntlm::kMaxFqdnLen + 1);
+  std::string challenge_msg_bytes = fdp.ConsumeRemainingBytes();
+
+  client.GenerateAuthenticateMessage(
+      domain, username, password, hostname, net::ntlm::test::kClientChallenge,
+      net::ntlm::Buffer(
+          reinterpret_cast<const uint8_t*>(challenge_msg_bytes.data()),
+          challenge_msg_bytes.size()));
+  return 0;
+}
\ No newline at end of file
diff --git a/net/ntlm/ntlm_client_unittest.cc b/net/ntlm/ntlm_client_unittest.cc
new file mode 100644
index 0000000..b67c35c
--- /dev/null
+++ b/net/ntlm/ntlm_client_unittest.cc
@@ -0,0 +1,369 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/ntlm/ntlm_client.h"
+
+#include <string>
+
+#include "build/build_config.h"
+#include "net/ntlm/ntlm.h"
+#include "net/ntlm/ntlm_buffer_reader.h"
+#include "net/ntlm/ntlm_buffer_writer.h"
+#include "net/ntlm/ntlm_test_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace ntlm {
+
+namespace {
+
+Buffer GenerateAuthMsg(const NtlmClient& client, const Buffer& challenge_msg) {
+  return client.GenerateAuthenticateMessage(
+      test::kNtlmDomain, test::kUser, test::kPassword, test::kHostnameAscii,
+      test::kClientChallenge, challenge_msg);
+}
+
+Buffer GenerateAuthMsg(const NtlmClient& client,
+                       const uint8_t* challenge_msg,
+                       size_t challenge_msg_len) {
+  return GenerateAuthMsg(client, Buffer(challenge_msg, challenge_msg_len));
+}
+
+Buffer GenerateAuthMsg(const NtlmClient& client,
+                       const NtlmBufferWriter& challenge_writer) {
+  return GenerateAuthMsg(client, challenge_writer.GetBuffer());
+}
+
+bool GetAuthMsgResult(const NtlmClient& client,
+                      const NtlmBufferWriter& challenge_writer) {
+  return !GenerateAuthMsg(client, challenge_writer).empty();
+}
+
+bool ReadBytesPayload(NtlmBufferReader* reader, uint8_t* buffer, size_t len) {
+  SecurityBuffer sec_buf;
+  return reader->ReadSecurityBuffer(&sec_buf) && (sec_buf.length == len) &&
+         reader->ReadBytesFrom(sec_buf, buffer);
+}
+
+// Reads bytes from a payload and assigns them to a string. This makes
+// no assumptions about the underlying encoding.
+bool ReadStringPayload(NtlmBufferReader* reader, std::string* str) {
+  SecurityBuffer sec_buf;
+  if (!reader->ReadSecurityBuffer(&sec_buf))
+    return false;
+
+  std::unique_ptr<uint8_t[]> raw(new uint8_t[sec_buf.length]);
+  if (!reader->ReadBytesFrom(sec_buf, raw.get()))
+    return false;
+
+  str->assign(reinterpret_cast<const char*>(raw.get()), sec_buf.length);
+  return true;
+}
+
+// Reads bytes from a payload and assigns them to a string16. This makes
+// no assumptions about the underlying encoding. This will fail if there
+// are an odd number of bytes in the payload.
+bool ReadString16Payload(NtlmBufferReader* reader, base::string16* str) {
+  SecurityBuffer sec_buf;
+  if (!reader->ReadSecurityBuffer(&sec_buf) || (sec_buf.length % 2 != 0))
+    return false;
+
+  std::unique_ptr<uint8_t[]> raw(new uint8_t[sec_buf.length]);
+  if (!reader->ReadBytesFrom(sec_buf, raw.get()))
+    return false;
+
+#if defined(ARCH_CPU_BIG_ENDIAN)
+  for (size_t i = 0; i < sec_buf.length; i += 2) {
+    std::swap(raw.get()[i], raw.get()[i + 1]);
+  }
+#endif
+
+  str->assign(reinterpret_cast<const base::char16*>(raw.get()),
+              sec_buf.length / 2);
+  return true;
+}
+
+}  // namespace
+
+TEST(NtlmClientTest, VerifyNegotiateMessageV1) {
+  NtlmClient client;
+
+  Buffer result = client.GetNegotiateMessage();
+
+  ASSERT_EQ(kNegotiateMessageLen, result.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedNegotiateMsg, result.data(),
+                      kNegotiateMessageLen));
+}
+
+TEST(NtlmClientTest, MinimalStructurallyValidChallenge) {
+  NtlmClient client;
+
+  NtlmBufferWriter writer(kMinChallengeHeaderLen);
+  ASSERT_TRUE(
+      writer.WriteBytes(test::kMinChallengeMessage, kMinChallengeHeaderLen));
+
+  ASSERT_TRUE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, MinimalStructurallyValidChallengeZeroOffset) {
+  NtlmClient client;
+
+  // The spec (2.2.1.2) states that the length SHOULD be 0 and the offset
+  // SHOULD be where the payload would be if it was present. This is the
+  // expected response from a compliant server when no target name is sent.
+  // In reality the offset should always be ignored if the length is zero.
+  // Also implementations often just write zeros.
+  uint8_t raw[kMinChallengeHeaderLen];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the default valid message to overwrite the offset to zero.
+  ASSERT_NE(0x00, raw[16]);
+  raw[16] = 0x00;
+
+  NtlmBufferWriter writer(kMinChallengeHeaderLen);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+
+  ASSERT_TRUE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, ChallengeMsgTooShort) {
+  NtlmClient client;
+
+  // Fail because the minimum size valid message is 32 bytes.
+  NtlmBufferWriter writer(kMinChallengeHeaderLen - 1);
+  ASSERT_TRUE(writer.WriteBytes(test::kMinChallengeMessage,
+                                kMinChallengeHeaderLen - 1));
+  ASSERT_FALSE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, ChallengeMsgNoSig) {
+  NtlmClient client;
+
+  // Fail because the first 8 bytes don't match "NTLMSSP\0"
+  uint8_t raw[kMinChallengeHeaderLen];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the default valid message to overwrite the last byte of the
+  // signature.
+  ASSERT_NE(0xff, raw[7]);
+  raw[7] = 0xff;
+  NtlmBufferWriter writer(kMinChallengeHeaderLen);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+  ASSERT_FALSE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, ChallengeMsgWrongMessageType) {
+  NtlmClient client;
+
+  // Fail because the message type should be MessageType::kChallenge
+  // (0x00000002)
+  uint8_t raw[kMinChallengeHeaderLen];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the message type.
+  ASSERT_NE(0x03, raw[8]);
+  raw[8] = 0x03;
+
+  NtlmBufferWriter writer(kMinChallengeHeaderLen);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+
+  ASSERT_FALSE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, ChallengeWithNoTargetName) {
+  NtlmClient client;
+
+  // The spec (2.2.1.2) states that the length SHOULD be 0 and the offset
+  // SHOULD be where the payload would be if it was present. This is the
+  // expected response from a compliant server when no target name is sent.
+  // In reality the offset should always be ignored if the length is zero.
+  // Also implementations often just write zeros.
+  uint8_t raw[kMinChallengeHeaderLen];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the default valid message to overwrite the offset to zero.
+  ASSERT_NE(0x00, raw[16]);
+  raw[16] = 0x00;
+
+  NtlmBufferWriter writer(kMinChallengeHeaderLen);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+
+  ASSERT_TRUE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, Type2MessageWithTargetName) {
+  NtlmClient client;
+
+  // One extra byte is provided for target name.
+  uint8_t raw[kMinChallengeHeaderLen + 1];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the default valid message to indicate 1 byte is present in the
+  // target name payload.
+  ASSERT_NE(0x01, raw[12]);
+  ASSERT_EQ(0x00, raw[13]);
+  ASSERT_NE(0x01, raw[14]);
+  ASSERT_EQ(0x00, raw[15]);
+  raw[12] = 0x01;
+  raw[14] = 0x01;
+  // Put something in the target name.
+  ASSERT_NE('Z', raw[32]);
+  raw[32] = 'Z';
+
+  NtlmBufferWriter writer(kChallengeHeaderLen + 1);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+
+  ASSERT_TRUE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, NoTargetNameOverflowFromOffset) {
+  NtlmClient client;
+
+  uint8_t raw[kMinChallengeHeaderLen];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the default valid message to claim that the target name field is 1
+  // byte long overrunning the end of the message message.
+  ASSERT_NE(0x01, raw[12]);
+  ASSERT_EQ(0x00, raw[13]);
+  ASSERT_NE(0x01, raw[14]);
+  ASSERT_EQ(0x00, raw[15]);
+  raw[12] = 0x01;
+  raw[14] = 0x01;
+
+  NtlmBufferWriter writer(kMinChallengeHeaderLen);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+
+  // The above malformed message could cause an implementation to read outside
+  // the message buffer because the offset is past the end of the message.
+  // Verify it gets rejected.
+  ASSERT_FALSE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, NoTargetNameOverflowFromLength) {
+  NtlmClient client;
+
+  // Message has 1 extra byte of space after the header for the target name.
+  // One extra byte is provided for target name.
+  uint8_t raw[kMinChallengeHeaderLen + 1];
+  memcpy(raw, test::kMinChallengeMessage, kMinChallengeHeaderLen);
+  // Modify the default valid message to indicate 2 bytes are present in the
+  // target name payload (however there is only space for 1).
+  ASSERT_NE(0x02, raw[12]);
+  ASSERT_EQ(0x00, raw[13]);
+  ASSERT_NE(0x02, raw[14]);
+  ASSERT_EQ(0x00, raw[15]);
+  raw[12] = 0x02;
+  raw[14] = 0x02;
+  // Put something in the target name.
+  ASSERT_NE('Z', raw[32]);
+  raw[32] = 'Z';
+
+  NtlmBufferWriter writer(kMinChallengeHeaderLen + 1);
+  ASSERT_TRUE(writer.WriteBytes(raw, arraysize(raw)));
+
+  // The above malformed message could cause an implementation
+  // to read outside the message buffer because the length is
+  // longer than available space. Verify it gets rejected.
+  ASSERT_FALSE(GetAuthMsgResult(client, writer));
+}
+
+TEST(NtlmClientTest, Type3UnicodeWithSessionSecuritySpecTest) {
+  NtlmClient client;
+
+  Buffer result = GenerateAuthMsg(client, test::kChallengeMsgV1,
+                                  arraysize(test::kChallengeMsgV1));
+
+  ASSERT_FALSE(result.empty());
+  ASSERT_EQ(arraysize(test::kExpectedAuthenticateMsgV1), result.size());
+  ASSERT_EQ(0, memcmp(test::kExpectedAuthenticateMsgV1, result.data(),
+                      result.size()));
+}
+
+TEST(NtlmClientTest, Type3WithoutUnicode) {
+  NtlmClient client;
+
+  Buffer result = GenerateAuthMsg(client, test::kMinChallengeMessageNoUnicode,
+                                  kMinChallengeHeaderLen);
+  ASSERT_FALSE(result.empty());
+
+  NtlmBufferReader reader(result);
+  ASSERT_TRUE(reader.MatchMessageHeader(MessageType::kAuthenticate));
+
+  // Read the LM and NTLM Response Payloads.
+  uint8_t actual_lm_response[kResponseLenV1];
+  uint8_t actual_ntlm_response[kResponseLenV1];
+
+  ASSERT_TRUE(ReadBytesPayload(&reader, actual_lm_response, kResponseLenV1));
+  ASSERT_TRUE(ReadBytesPayload(&reader, actual_ntlm_response, kResponseLenV1));
+
+  ASSERT_EQ(0, memcmp(test::kExpectedLmResponseWithV1SS, actual_lm_response,
+                      kResponseLenV1));
+  ASSERT_EQ(0, memcmp(test::kExpectedNtlmResponseWithV1SS, actual_ntlm_response,
+                      kResponseLenV1));
+
+  std::string domain;
+  std::string username;
+  std::string hostname;
+  ASSERT_TRUE(ReadStringPayload(&reader, &domain));
+  ASSERT_EQ(test::kNtlmDomainAscii, domain);
+  ASSERT_TRUE(ReadStringPayload(&reader, &username));
+  ASSERT_EQ(test::kUserAscii, username);
+  ASSERT_TRUE(ReadStringPayload(&reader, &hostname));
+  ASSERT_EQ(test::kHostnameAscii, hostname);
+
+  // The session key is not used in HTTP. Since NTLMSSP_NEGOTIATE_KEY_EXCH
+  // was not sent this is empty.
+  ASSERT_TRUE(reader.MatchEmptySecurityBuffer());
+
+  // Verify the unicode flag is not set and OEM flag is.
+  NegotiateFlags flags;
+  ASSERT_TRUE(reader.ReadFlags(&flags));
+  ASSERT_EQ(NegotiateFlags::kNone, flags & NegotiateFlags::kUnicode);
+  ASSERT_EQ(NegotiateFlags::kOem, flags & NegotiateFlags::kOem);
+}
+
+TEST(NtlmClientTest, ClientDoesNotDowngradeSessionSecurity) {
+  NtlmClient client;
+
+  Buffer result = GenerateAuthMsg(client, test::kMinChallengeMessageNoSS,
+                                  kMinChallengeHeaderLen);
+  ASSERT_FALSE(result.empty());
+
+  NtlmBufferReader reader(result);
+  ASSERT_TRUE(reader.MatchMessageHeader(MessageType::kAuthenticate));
+
+  // Read the LM and NTLM Response Payloads.
+  uint8_t actual_lm_response[kResponseLenV1];
+  uint8_t actual_ntlm_response[kResponseLenV1];
+
+  ASSERT_TRUE(ReadBytesPayload(&reader, actual_lm_response, kResponseLenV1));
+  ASSERT_TRUE(ReadBytesPayload(&reader, actual_ntlm_response, kResponseLenV1));
+
+  // The important part of this test is that even though the
+  // server told the client to drop session security. The client
+  // DID NOT drop it.
+  ASSERT_EQ(0, memcmp(test::kExpectedLmResponseWithV1SS, actual_lm_response,
+                      kResponseLenV1));
+  ASSERT_EQ(0, memcmp(test::kExpectedNtlmResponseWithV1SS, actual_ntlm_response,
+                      kResponseLenV1));
+
+  base::string16 domain;
+  base::string16 username;
+  base::string16 hostname;
+  ASSERT_TRUE(ReadString16Payload(&reader, &domain));
+  ASSERT_EQ(test::kNtlmDomain, domain);
+  ASSERT_TRUE(ReadString16Payload(&reader, &username));
+  ASSERT_EQ(test::kUser, username);
+  ASSERT_TRUE(ReadString16Payload(&reader, &hostname));
+  ASSERT_EQ(test::kHostname, hostname);
+
+  // The session key is not used in HTTP. Since NTLMSSP_NEGOTIATE_KEY_EXCH
+  // was not sent this is empty.
+  ASSERT_TRUE(reader.MatchEmptySecurityBuffer());
+
+  // Verify the unicode and session security flag is set.
+  NegotiateFlags flags;
+  ASSERT_TRUE(reader.ReadFlags(&flags));
+  ASSERT_EQ(NegotiateFlags::kUnicode, flags & NegotiateFlags::kUnicode);
+  ASSERT_EQ(NegotiateFlags::kExtendedSessionSecurity,
+            flags & NegotiateFlags::kExtendedSessionSecurity);
+}
+
+}  // namespace ntlm
+}  // namespace net
diff --git a/net/ntlm/ntlm_constants.h b/net/ntlm/ntlm_constants.h
index 53f69a6..cebba53 100644
--- a/net/ntlm/ntlm_constants.h
+++ b/net/ntlm/ntlm_constants.h
@@ -38,7 +38,7 @@
 };
 
 // There are 3 types of messages in NTLM. The message type is a field in
-// every NTLM message header.
+// every NTLM message header. See [MS-NLMP] Section 2.2.
 enum class MessageType : uint32_t {
   kNegotiate = 0x01,
   kChallenge = 0x02,
@@ -78,10 +78,15 @@
 static constexpr size_t kSecurityBufferLen =
     (2 * sizeof(uint16_t)) + sizeof(uint32_t);
 static constexpr size_t kNegotiateMessageLen = 32;
+static constexpr size_t kMinChallengeHeaderLen = 32;
 static constexpr size_t kChallengeHeaderLen = 32;
 static constexpr size_t kResponseLenV1 = 24;
 static constexpr size_t kChallengeLen = 8;
 static constexpr size_t kNtlmHashLen = 16;
+static constexpr size_t kAuthenticateHeaderLenV1 = 64;
+static constexpr size_t kMaxFqdnLen = 255;
+static constexpr size_t kMaxUsernameLen = 104;
+static constexpr size_t kMaxPasswordLen = 256;
 
 static constexpr NegotiateFlags kNegotiateMessageFlags =
     NegotiateFlags::kUnicode | NegotiateFlags::kOem |
diff --git a/net/ntlm/ntlm_test_data.h b/net/ntlm/ntlm_test_data.h
index 2a9913b7..faabae92 100644
--- a/net/ntlm/ntlm_test_data.h
+++ b/net/ntlm/ntlm_test_data.h
@@ -35,6 +35,15 @@
 constexpr uint8_t kClientChallenge[kChallengeLen] = {0xaa, 0xaa, 0xaa, 0xaa,
                                                      0xaa, 0xaa, 0xaa, 0xaa};
 
+// Test input defined in [MS-NLMP] Section 4.2.3.3.
+constexpr uint8_t kChallengeMsgV1[] = {
+    0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
+    0x0c, 0x00, 0x0c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x33, 0x82, 0x0a, 0x82,
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x06, 0x00, 0x70, 0x17, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x65, 0x00,
+    0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00};
+
 // A minimal challenge message for tests. For NTLMv1 this implementation only
 // reads the smallest required version of the message (32 bytes). Some
 // servers may still send messages this small. The only relevant flags
@@ -54,6 +63,20 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x82,
     0x08, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
 
+// The same message as |kMinChallengeMessage| but with the
+// NTLMSSP_NEGOTIATE_UNICODE flag cleared.
+constexpr uint8_t kMinChallengeMessageNoUnicode[kChallengeHeaderLen] = {
+    'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x02, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x82,
+    0x08, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
+
+// The same message as |kMinChallengeMessage| but with the
+// NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag cleared.
+constexpr uint8_t kMinChallengeMessageNoSS[kChallengeHeaderLen] = {
+    'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x02, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x82,
+    0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
+
 // Test result value for NTOWFv1() defined in [MS-NLMP] Section 4.2.2.1.2.
 constexpr uint8_t kExpectedNtlmHashV1[kNtlmHashLen] = {
     0xa4, 0xf4, 0x9c, 0x40, 0x65, 0x10, 0xbd, 0xca,
@@ -74,6 +97,80 @@
     0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
+// Expected negotiate message from this implementation.
+// [0-7]    - "NTLMSSP\0"                       (Signature)
+// [9-11]   - |MessageType::NEGOTIATE|          (Message Type = 0x00000001)
+// [12-15]  - |NEGOTIATE_MESSAGE_FLAGS|         (Flags = 0x00088207)
+// [16-23]  - |SecBuf(kNegotiateMessageLen, 0)|(Domain)
+// [24-32]  - |SecBuf(kNegotiateMessageLen, 0)|(Workstation)
+//
+// NOTE: Message does not include Version field. Since
+// NTLMSSP_NEGOTIATE_VERSION is never sent, it is not required, and the server
+// won't try to read it. The field is currently omitted for test compatibility
+// with the existing implementation. When NTLMv2 is implemented this field
+// will be present for both NTLMv1 and NTLMv2, however it will always be set to
+// all zeros. The version field is only used for debugging and only defines
+// a mapping to Windows operating systems.
+//
+// Similarly both Domain and Workstation fields are are not strictly required
+// either (though are included here) since neither
+// NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED nor
+// NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED are ever sent. A compliant server
+// should never read past the 16th byte in this message.
+//
+// See [MS-NLMP] Section 2.2.2.5 for more detail on flags and 2.2.2.1 for the
+// Negotiate message in general.
+constexpr uint8_t kExpectedNegotiateMsg[kNegotiateMessageLen] = {
+    'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x01, 0x00, 0x00,
+    0x00, 0x07, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
+
+// Expected V1 Authenticate message from this implementation when sent
+// |kChallengeMsgV1| as the challenge.
+//
+// [0-7]    - "NTLMSSP\0"                         (Signature)
+// [9-11]   - |MessageType::kAuthenticate|        (Message Type = 0x00000003)
+// [12-19]  - |SecBuf(64, RESPONSE_V1_LEN)|       (LM Response)
+// [20-27]  - |SecBuf(88, RESPONSE_V1_LEN)|       (NTLM Response)
+// [28-35]  - |SecBuf(112, 12)|                   (Target Name = L"Domain")
+// [36-43]  - |SecBuf(124, 8)|                    (User = L"User")
+// [44-51]  - |SecBuf(132, 16)|                   (Workstation = L"COMPUTER")
+// [52-59]  - |SecBuf(64, 0)|                     (Session Key (empty))
+// [60-63]  - 0x00088203                          (Flags)
+// [64-87]  - |EXPECTED_V1_WITH_SS_LM_RESPONSE|   (LM Response Payload)
+// [88-111] - |EXPECTED_V1_WITH_SS_NTLM_RESPONSE| (NTLM Response Payload)
+// [112-123]- L"Domain"                           (Target Name Payload)
+// [124-132]- L"User"                             (User Payload)
+// [132-147]- L"COMPUTER"                         (Workstation Payload)
+//
+// NOTE: This is not identical to the message in [MS-NLMP] Section 4.2.2.3 for
+// several reasons.
+//
+// 1) The flags are different because this implementation does not support
+// the flags related to version, key exchange, signing and sealing. These
+// flags are not relevant to implementing the NTLM scheme in HTTP.
+// 2) Since key exchange is not required nor supported, the session base key
+// payload is not required nor present.
+// 3) The specification allows payloads to be in any order. This (and the
+// prior) implementation uses a different payload order than the example.
+// 4) The version field is Windows specific and there is no provision for
+// non-Windows OS information. This message does not include a version field.
+constexpr uint8_t kExpectedAuthenticateMsgV1[] = {
+    'N',  'T',  'L',  'M',  'S',  'S',  'P',  '\0', 0x03, 0x00, 0x00, 0x00,
+    0x18, 0x00, 0x18, 0x00, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00,
+    0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x70, 0x00, 0x00, 0x00,
+    0x08, 0x00, 0x08, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
+    0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+    0x03, 0x82, 0x08, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x75, 0x37, 0xf8, 0x03, 0xae, 0x36, 0x71, 0x28,
+    0xca, 0x45, 0x82, 0x04, 0xbd, 0xe7, 0xca, 0xf8, 0x1e, 0x97, 0xed, 0x26,
+    0x83, 0x26, 0x72, 0x32, 'D',  0x00, 'o',  0x00, 'm',  0x00, 'a',  0x00,
+    'i',  0x00, 'n',  0x00, 'U',  0x00, 's',  0x00, 'e',  0x00, 'r',  0x00,
+    'C',  0x00, 'O',  0x00, 'M',  0x00, 'P',  0x00, 'U',  0x00, 'T',  0x00,
+    'E',  0x00, 'R',  0x00,
+};
+
 }  // namespace test
 }  // namespace ntlm
 }  // namespace net
diff --git a/net/ntlm/ntlm_unittest.cc b/net/ntlm/ntlm_unittest.cc
index 6c40d16a..6a2ce032 100644
--- a/net/ntlm/ntlm_unittest.cc
+++ b/net/ntlm/ntlm_unittest.cc
@@ -13,6 +13,9 @@
 
 #include "net/ntlm/ntlm.h"
 
+#include <string>
+
+#include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "net/ntlm/ntlm_test_data.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -117,4 +120,4 @@
 }
 
 }  // namespace ntlm
-}  // namespace net
\ No newline at end of file
+}  // namespace net
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index a0083e2..59ee750 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -137,6 +137,8 @@
     "dns_blackhole_checker.h",
     "evaluate_capability.cc",
     "evaluate_capability.h",
+    "file_transfer_message_handler_factory.cc",
+    "file_transfer_message_handler_factory.h",
     "forward_process_stats_agent.cc",
     "forward_process_stats_agent.h",
     "gcd_rest_client.cc",
@@ -536,16 +538,20 @@
   }
 
   if (enable_me2me_host) {
-    sources += [
-      "evaluate_capability_unittest.cc",
-    ]
+    sources += [ "evaluate_capability_unittest.cc" ]
 
     if (is_win) {
-      data_deps = [ "//remoting/host/win:remoting_me2me_host" ]
+      data_deps = [
+        "//remoting/host/win:remoting_me2me_host",
+      ]
     } else if (is_mac) {
-      data_deps = [ "//remoting/host/mac:remoting_me2me_host" ]
+      data_deps = [
+        "//remoting/host/mac:remoting_me2me_host",
+      ]
     } else {
-      data_deps = [ ":remoting_me2me_host" ]
+      data_deps = [
+        ":remoting_me2me_host",
+      ]
     }
   }
 }
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index 93d6440f..d29cb12e 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -25,6 +25,7 @@
 #include "remoting/proto/control.pb.h"
 #include "remoting/proto/event.pb.h"
 #include "remoting/protocol/audio_stream.h"
+#include "remoting/protocol/capability_names.h"
 #include "remoting/protocol/client_stub.h"
 #include "remoting/protocol/clipboard_thread_proxy.h"
 #include "remoting/protocol/pairing_registry.h"
@@ -181,6 +182,13 @@
   extension_manager_->OnNegotiatedCapabilities(
       connection_->client_stub(), capabilities_);
 
+  if (HasCapability(capabilities_, protocol::kFileTransferCapability)) {
+    data_channel_manager_.RegisterCreateHandlerCallback(
+        kFileTransferDataChannelPrefix,
+        base::Bind(&FileTransferMessageHandlerFactory::CreateDataChannelHandler,
+                   base::Unretained(&file_transfer_message_handler_factory_)));
+  }
+
   VLOG(1) << "Client capabilities: " << *client_capabilities_;
 
   desktop_environment_->SetCapabilities(capabilities_);
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h
index c439355b..93216c7 100644
--- a/remoting/host/client_session.h
+++ b/remoting/host/client_session.h
@@ -19,6 +19,7 @@
 #include "remoting/host/client_session_control.h"
 #include "remoting/host/client_session_details.h"
 #include "remoting/host/desktop_environment_options.h"
+#include "remoting/host/file_transfer_message_handler_factory.h"
 #include "remoting/host/host_experiment_session_plugin.h"
 #include "remoting/host/host_extension_session_manager.h"
 #include "remoting/host/remote_input_filter.h"
@@ -240,6 +241,9 @@
   // Used to dispatch new data channels to factory methods.
   protocol::DataChannelManager data_channel_manager_;
 
+  // Used to handle file transfer data channels.
+  FileTransferMessageHandlerFactory file_transfer_message_handler_factory_;
+
   // Set to true if the client was authenticated successfully.
   bool is_authenticated_ = false;
 
diff --git a/remoting/host/file_transfer_message_handler_factory.cc b/remoting/host/file_transfer_message_handler_factory.cc
new file mode 100644
index 0000000..c14ccabe
--- /dev/null
+++ b/remoting/host/file_transfer_message_handler_factory.cc
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/file_transfer_message_handler_factory.h"
+
+namespace remoting {
+
+FileTransferMessageHandlerFactory::FileTransferMessageHandlerFactory() =
+    default;
+FileTransferMessageHandlerFactory::~FileTransferMessageHandlerFactory() =
+    default;
+
+void FileTransferMessageHandlerFactory::CreateDataChannelHandler(
+    const std::string& channel_name,
+    std::unique_ptr<protocol::MessagePipe> pipe) {
+  // TODO(jarhar): Implement FileTransferMessageHandler and pass pipe to it.
+}
+
+}  // namespace remoting
diff --git a/remoting/host/file_transfer_message_handler_factory.h b/remoting/host/file_transfer_message_handler_factory.h
new file mode 100644
index 0000000..db9dec0
--- /dev/null
+++ b/remoting/host/file_transfer_message_handler_factory.h
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_FILE_TRANSFER_MESSAGE_HANDLER_FACTORY_H_
+#define REMOTING_HOST_FILE_TRANSFER_MESSAGE_HANDLER_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "remoting/protocol/message_pipe.h"
+
+namespace remoting {
+
+constexpr char kFileTransferDataChannelPrefix[] = "filetransfer-";
+
+class FileTransferMessageHandlerFactory final {
+ public:
+  FileTransferMessageHandlerFactory();
+  ~FileTransferMessageHandlerFactory();
+
+  void CreateDataChannelHandler(const std::string& channel_name,
+                                std::unique_ptr<protocol::MessagePipe> pipe);
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_HOST_FILE_TRANSFER_MESSAGE_HANDLER_FACTORY_H_
diff --git a/remoting/host/me2me_desktop_environment.cc b/remoting/host/me2me_desktop_environment.cc
index 23d4da02..0c6e2ba9 100644
--- a/remoting/host/me2me_desktop_environment.cc
+++ b/remoting/host/me2me_desktop_environment.cc
@@ -56,6 +56,14 @@
     capabilities += " ";
     capabilities += protocol::kTouchEventsCapability;
   }
+
+// TODO(jarhar): Replace this ifdef with settings in DesktopEnvironmentOptions,
+//               and then a chrome policy.
+#ifdef CHROME_REMOTE_DESKTOP_FILE_TRANSFER_ENABLED
+  capabilities += " ";
+  capabilities += protocol::kFileTransferCapability;
+#endif
+
   return capabilities;
 }
 
diff --git a/remoting/protocol/capability_names.h b/remoting/protocol/capability_names.h
index 63eb0d74..beae4a8 100644
--- a/remoting/protocol/capability_names.h
+++ b/remoting/protocol/capability_names.h
@@ -14,6 +14,8 @@
 const char kSendInitialResolution[] = "sendInitialResolution";
 const char kRateLimitResizeRequests[] = "rateLimitResizeRequests";
 
+const char kFileTransferCapability[] = "fileTransfer";
+
 }  // namespace protocol
 }  // namespace remoting
 
diff --git a/services/metrics/public/cpp/BUILD.gn b/services/metrics/public/cpp/BUILD.gn
index ae37892..9a0fadf 100644
--- a/services/metrics/public/cpp/BUILD.gn
+++ b/services/metrics/public/cpp/BUILD.gn
@@ -15,6 +15,8 @@
     "ukm_entry_builder_base.h",
     "ukm_recorder.cc",
     "ukm_recorder.h",
+    "ukm_source_id.cc",
+    "ukm_source_id.h",
   ]
 
   defines = [ "METRICS_IMPLEMENTATION" ]
diff --git a/services/metrics/public/cpp/ukm_entry_builder.h b/services/metrics/public/cpp/ukm_entry_builder.h
index c2250b4..1e96952 100644
--- a/services/metrics/public/cpp/ukm_entry_builder.h
+++ b/services/metrics/public/cpp/ukm_entry_builder.h
@@ -9,12 +9,11 @@
 
 #include "base/macros.h"
 #include "services/metrics/public/cpp/metrics_export.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/metrics/public/interfaces/ukm_interface.mojom.h"
 
 namespace ukm {
 
-typedef int64_t SourceId;
-
 // The builder that builds UkmEntry and adds it to UkmRecorder.
 // The example usage is:
 //
diff --git a/services/metrics/public/cpp/ukm_recorder.cc b/services/metrics/public/cpp/ukm_recorder.cc
index 0e8b2f6..53ae8c72c 100644
--- a/services/metrics/public/cpp/ukm_recorder.cc
+++ b/services/metrics/public/cpp/ukm_recorder.cc
@@ -4,7 +4,6 @@
 
 #include "services/metrics/public/cpp/ukm_recorder.h"
 
-#include "base/atomic_sequence_num.h"
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
@@ -33,8 +32,7 @@
 
 // static
 ukm::SourceId UkmRecorder::GetNewSourceID() {
-  static base::AtomicSequenceNumber seq;
-  return static_cast<ukm::SourceId>(seq.GetNext());
+  return AssignNewSourceId();
 }
 
 std::unique_ptr<UkmEntryBuilder> UkmRecorder::GetEntryBuilder(
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h
index fb653e19..97ecf32 100644
--- a/services/metrics/public/cpp/ukm_recorder.h
+++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -5,8 +5,6 @@
 #ifndef SERVICES_METRICS_PUBLIC_CPP_UKM_RECORDER_H_
 #define SERVICES_METRICS_PUBLIC_CPP_UKM_RECORDER_H_
 
-#include <stddef.h>
-
 #include <memory>
 
 #include "base/callback.h"
@@ -15,6 +13,7 @@
 #include "base/threading/thread_checker.h"
 #include "services/metrics/public/cpp/metrics_export.h"
 #include "services/metrics/public/cpp/ukm_entry_builder.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/metrics/public/interfaces/ukm_interface.mojom.h"
 #include "url/gurl.h"
 
@@ -76,8 +75,6 @@
 // This feature controls whether UkmService should be created.
 METRICS_EXPORT extern const base::Feature kUkmFeature;
 
-typedef int64_t SourceId;
-
 // Interface for recording UKM
 class METRICS_EXPORT UkmRecorder {
  public:
diff --git a/services/metrics/public/cpp/ukm_source_id.cc b/services/metrics/public/cpp/ukm_source_id.cc
new file mode 100644
index 0000000..a2ffb19
--- /dev/null
+++ b/services/metrics/public/cpp/ukm_source_id.cc
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/metrics/public/cpp/ukm_source_id.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/logging.h"
+
+namespace ukm {
+
+namespace {
+
+const int64_t kLowBitsMask = (INT64_C(1) << 32) - 1;
+const int64_t kNumTypeBits = 2;
+const int64_t kTypeMask = (INT64_C(1) << kNumTypeBits) - 1;
+
+}  // namespace
+
+SourceId AssignNewSourceId() {
+  static base::AtomicSequenceNumber seq;
+  return ConvertToSourceId(seq.GetNext() + 1, SourceIdType::UKM);
+}
+
+SourceId ConvertToSourceId(int64_t other_id, SourceIdType id_type) {
+  const int64_t type_bits = static_cast<int64_t>(id_type);
+  DCHECK_EQ(type_bits, type_bits & kTypeMask);
+  // Stores the the type ID in the low bits of the source id, and shift the rest
+  // of the ID to make room.  This could cause the original ID to overflow, but
+  // that should be rare enough that it won't matter for UKM's purposes.
+  return (other_id << kNumTypeBits) | type_bits;
+}
+
+SourceId ConvertSourceIdFromInstance(int64_t instance_id, int64_t source_id) {
+  // Only convert source IDs from Create().
+  if ((kTypeMask & source_id) != static_cast<int64_t>(SourceIdType::UKM))
+    return source_id;
+
+  // Neither ID should get large enough to cause an issue, but explicitly
+  // discard down to 32 bits anyway.
+  return ((instance_id & kLowBitsMask) << 32) | (source_id & kLowBitsMask);
+}
+
+}  // namespace ukm
diff --git a/services/metrics/public/cpp/ukm_source_id.h b/services/metrics/public/cpp/ukm_source_id.h
new file mode 100644
index 0000000..1300add
--- /dev/null
+++ b/services/metrics/public/cpp/ukm_source_id.h
@@ -0,0 +1,34 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_METRICS_PUBLIC_CPP_UKM_SOURCE_ID_H_
+#define SERVICES_METRICS_PUBLIC_CPP_UKM_SOURCE_ID_H_
+
+#include <stdint.h>
+
+#include "services/metrics/public/cpp/metrics_export.h"
+
+namespace ukm {
+
+typedef int64_t SourceId;
+
+enum class SourceIdType : int64_t {
+  UKM = 0,
+  NAVIGATION_ID = 1,
+};
+
+// Get a new source ID, which is unique for the duration of a browser session.
+METRICS_EXPORT SourceId AssignNewSourceId();
+
+// Utility for converting other unique ids to source ids.
+METRICS_EXPORT SourceId ConvertToSourceId(int64_t other_id,
+                                          SourceIdType id_type);
+
+// Convert source ids from another process.
+METRICS_EXPORT SourceId ConvertSourceIdFromInstance(int64_t instance_id,
+                                                    int64_t source_id);
+
+}  // namespace ukm
+
+#endif  // SERVICES_METRICS_PUBLIC_CPP_UKM_SOURCE_ID_H_
diff --git a/services/ui/service.cc b/services/ui/service.cc
index 60a3932..e1efc27 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -149,6 +149,8 @@
                                                 : nullptr) {}
 
 Service::~Service() {
+  in_destructor_ = true;
+
   // Destroy |window_server_| first, since it depends on |event_source_|.
   // WindowServer (or more correctly its Displays) may have state that needs to
   // be destroyed before GpuState as well.
@@ -359,9 +361,13 @@
 }
 
 void Service::OnNoMoreDisplays() {
-  // We may get here from the destructor, in which case there is no messageloop.
-  if (base::RunLoop::IsRunningOnCurrentThread())
-    base::RunLoop::QuitCurrentWhenIdleDeprecated();
+  // We may get here from the destructor. Don't try to use RequestQuit() when
+  // that happens as ServiceContext DCHECKs in this case.
+  if (in_destructor_)
+    return;
+
+  DCHECK(context());
+  context()->RequestQuit();
 }
 
 bool Service::IsTestConfig() const {
diff --git a/services/ui/service.h b/services/ui/service.h
index 1cb7c2a..7826b4a0 100644
--- a/services/ui/service.h
+++ b/services/ui/service.h
@@ -226,6 +226,8 @@
   // Set to true in StartDisplayInit().
   bool is_gpu_ready_ = false;
 
+  bool in_destructor_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(Service);
 };
 
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter
index 15101cf9a..fb9ef61 100644
--- a/testing/buildbot/filters/fuchsia.base_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -75,9 +75,12 @@
 -VerifyPathControlledByUserTest.Symlinks
 -VerifyPathControlledByUserTest.WriteBitChecks
 
-# CancelableSyncSocket tests fail: http://crbug.com/741783
+# CancelableSyncSocket tests fail: https://crbug.com/741783
 -CancelableSyncSocket*
 
+# Likely flake cause identified, disabled pending fix: https://crbug.com/751748.
+-MemoryDumpSchedulerTest.*
+
 # These tests are occasionally flaking. See https://crbug.com/738275. Please be
 # pretty confident you've fixed their rarely-flakiness before re-enabling.
 -AllModes/TaskSchedulerSingleThreadTaskRunnerManagerCommonTest.*
diff --git a/testing/scripts/run_telemetry_benchmark_as_googletest.py b/testing/scripts/run_telemetry_benchmark_as_googletest.py
index cd776916..109a5b9 100755
--- a/testing/scripts/run_telemetry_benchmark_as_googletest.py
+++ b/testing/scripts/run_telemetry_benchmark_as_googletest.py
@@ -79,15 +79,14 @@
       with open(chart_tempfile_name) as f:
         chartresults = json.load(f)
 
-    # test-results.json is the file name output by telemetry when the
-    # json-test-results format is included
-    tempfile_name = os.path.join(tempfile_dir, 'test-results.json')
-    with open(tempfile_name) as f:
-      json_test_results = json.load(f)
-
-    # Determine if this was a disabled benchmark that was run
+    # Skip if this was a disabled benchmark that was run
     if (not chartjson_results_present or
        (chartjson_results_present and chartresults.get('enabled', True))):
+      # test-results.json is the file name output by telemetry when the
+      # json-test-results format is included
+      tempfile_name = os.path.join(tempfile_dir, 'test-results.json')
+      with open(tempfile_name) as f:
+        json_test_results = json.load(f)
       num_failures = json_test_results['num_failures_by_type'].get('FAIL', 0)
       valid = bool(rc == 0 or num_failures != 0)
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index ec16f06..50f17b65 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -3088,3 +3088,7 @@
 crbug.com/749738 [ Win7 Debug ] virtual/mojo-loading/http/tests/devtools/console/console-format-es6-2.js [ Timeout ]
 crbug.com/749965 [ Win7 Debug ] media/controls/controls-video-keynav.html [ Failure ]
 crbug.com/750310 [ Win7 Debug ] virtual/off-main-thread-fetch/http/tests/inspector/network/network-blocked-reason.html [ Timeout ]
+
+# Sheriff failures 2017-08-03
+crbug.com/751906 [ Linux Debug ] http/tests/devtools/console/console-correct-suggestions.js [ Timeout Pass ]
+crbug.com/751906 [ Linux Debug ] virtual/mojo-loading/http/tests/devtools/console/console-correct-suggestions.js [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-actions.html b/third_party/WebKit/LayoutTests/accessibility/aom-actions.html
new file mode 100644
index 0000000..d22de17
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-actions.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML>
+<script src="../resources/gc.js"></script>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<!--
+
+Accessibility Object Model
+Explainer: https://github.com/WICG/aom/blob/gh-pages/explainer.md
+Spec: https://wicg.github.io/aom/spec/
+
+-->
+<script>
+test(function(t) {
+    assert_true(internals.runtimeFlags.accessibilityObjectModelEnabled);
+}, "Make sure that Accessibility Object Model is enabled");
+</script>
+
+<button id="target1">Target</button>
+
+<script>
+test(function(t) {
+  var target1 = document.getElementById("target1");
+  var axTarget1 = accessibilityController.accessibleElementById("target1");
+
+  var success = false;
+  target1.accessibleNode.onaccessibleclick = function() {
+    success = true;
+  };
+  axTarget1.press();
+
+  assert_true(success);
+}, "AccessibleNode.onaccessibleclick");
+</script>
+
+<button id="target2">Target</button>
+
+<script>
+test(function(t) {
+  var target2 = document.getElementById("target2");
+  var axTarget2 = accessibilityController.accessibleElementById("target2");
+
+  var success = false;
+  target2.accessibleNode.addEventListener("accessibleclick", function() {
+    success = true;
+  }, false);
+  axTarget2.press();
+
+  assert_true(success);
+}, "AccessibleNode.addEventListener('accessibleclick')");
+</script>
+
+<button id="target3a">Target without preventDefault</button>
+<button id="target3b">Target with preventDefault</button>
+
+<script>
+test(function(t) {
+  var target3a = document.getElementById("target3a");
+  var target3b = document.getElementById("target3b");
+  var axTarget3a = accessibilityController.accessibleElementById("target3a");
+  var axTarget3b = accessibilityController.accessibleElementById("target3b");
+
+  // Without preventDefault, the AOM event listener gets called
+  // first, and then the DOM event listener.
+  var calledAOMForTargetA = false;
+  target3a.accessibleNode.onaccessibleclick = function() {
+    calledAOMForTargetA = true;
+  };
+  var calledDOMForTargetA = false;
+  target3a.addEventListener("click", function() {
+    calledDOMForTargetA = true;
+  }, false);
+  axTarget3a.press();
+
+  assert_true(calledAOMForTargetA, "called AOM for target A");
+  assert_true(calledDOMForTargetA, "called DOM for target A");
+
+  // With preventDefault, the AOM event listener gets called only.
+  var calledAOMForTargetB = false;
+  target3b.accessibleNode.onaccessibleclick = function(evt) {
+    calledAOMForTargetB = true;
+    evt.preventDefault();
+  };
+  var calledDOMForTargetB = false;
+  target3b.addEventListener("click", function() {
+    calledDOMForTargetB = true;
+  }, false);
+  axTarget3b.press();
+
+  assert_true(calledAOMForTargetB, "called AOM for target B");
+  assert_false(calledDOMForTargetB, "called DOM for target B");
+}, "AOM events preventDefault");
+</script>
+
+<p id="p4">
+  <button id="target4">Target</button>
+</p>
+
+<script>
+test(function(t) {
+  var p4 = document.getElementById("p4");
+  var axTarget4 = accessibilityController.accessibleElementById("target4");
+
+  var success = false;
+  p4.accessibleNode.onaccessibleclick = function() {
+    success = true;
+  };
+  axTarget4.press();
+
+  assert_true(success);
+}, "AOM events bubble");
+</script>
+
+<section id="section5">
+  <ul id="ul5">
+    <li id="li5">
+      <button id="target5">Target</button>
+    </li>
+  </ul>
+</section>
+
+<script>
+test(function(t) {
+  var section5 = document.getElementById("section5");
+  var ul5 = document.getElementById("ul5");
+  var li5 = document.getElementById("li5");
+  var target5 = document.getElementById("target5");
+
+  var axTarget5 = accessibilityController.accessibleElementById("target5");
+
+  var seq = [];
+
+  section5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM capture SECTION");
+  }, true);
+  section5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM bubble SECTION");
+  }, false);
+  section5.addEventListener("click", function() {
+    seq.push("DOM capture SECTION");
+  }, true);
+  section5.addEventListener("click", function() {
+    seq.push("DOM bubble SECTION");
+  }, false);
+  ul5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM capture UL");
+  }, true);
+  ul5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM bubble UL");
+  }, false);
+  li5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM capture LI");
+  }, true);
+  li5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM bubble LI");
+  }, false);
+  target5.accessibleNode.addEventListener("accessibleclick", function() {
+    seq.push("AOM main event listener BUTTON");
+  }, false);
+  target5.addEventListener("click", function() {
+    seq.push("DOM main event listener BUTTON");
+  }, false);
+
+  axTarget5.press();
+
+  assert_equals(seq.join(", "),
+                "AOM capture SECTION, " +
+                "AOM capture UL, " +
+                "AOM capture LI, " +
+                "AOM main event listener BUTTON, " +
+                "AOM bubble LI, " +
+                "AOM bubble UL, " +
+                "AOM bubble SECTION, " +
+                "DOM capture SECTION, " +
+                "DOM main event listener BUTTON, " +
+                "DOM bubble SECTION");
+2
+}, "AOM event capturing and bubbling");
+</script>
+
+<ul id="ul6a" aria-owns="li6b">
+  <li id="li6a">Item A</li>
+</ul>
+<ul id="ul6b">
+  <li id="li6b">Item B</li>
+</ul>
+</section>
+
+<script>
+test(function(t) {
+  var ul6a = document.getElementById("ul6a");
+  var ul6b = document.getElementById("ul6b");
+  var li6b = document.getElementById("li6b");
+
+  var axLI6B = accessibilityController.accessibleElementById("li6b");
+
+  var ul6a_got_event = false;
+  var ul6b_got_event = false;
+
+  ul6a.accessibleNode.addEventListener("accessibleclick", function() {
+    ul6a_got_event = true;
+  }, false);
+  ul6b.accessibleNode.addEventListener("accessibleclick", function() {
+    ul6b_got_event = true;
+  }, false);
+
+  axLI6B.press();
+  assert_true(ul6a_got_event);
+  assert_false(ul6b_got_event);
+}, "AOM event bubbling respects aria-owns over DOM parent chain");
+</script>
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-boolean-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-boolean-properties.html
index 5a9f875..32ace158c 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-boolean-properties.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-boolean-properties.html
@@ -6,7 +6,7 @@
 <!--
 
 Accessibility Object Model
-Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+Explainer: https://github.com/WICG/aom/blob/gh-pages/explainer.md
 Spec: https://wicg.github.io/aom/spec/
 
 -->
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-float-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-float-properties.html
index 8699d8b..d8a19d2 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-float-properties.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-float-properties.html
@@ -6,7 +6,7 @@
 <!--
 
 Accessibility Object Model
-Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+Explainer: https://github.com/WICG/aom/blob/gh-pages/explainer.md
 Spec: https://wicg.github.io/aom/spec/
 
 -->
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-int-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-int-properties.html
index ec49d0a1..4d8d5b0 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-int-properties.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-int-properties.html
@@ -6,7 +6,7 @@
 <!--
 
 Accessibility Object Model
-Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+Explainer: https://github.com/WICG/aom/blob/gh-pages/explainer.md
 Spec: https://wicg.github.io/aom/spec/
 
 -->
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-relation-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-relation-properties.html
index f9396af..8278a06 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-relation-properties.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-relation-properties.html
@@ -6,7 +6,7 @@
 <!--
 
 Accessibility Object Model
-Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+Explainer: https://github.com/WICG/aom/blob/gh-pages/explainer.md
 Spec: https://wicg.github.io/aom/spec/
 
 -->
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html
index 10b9346..b9f6746 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html
@@ -6,7 +6,7 @@
 <!--
 
 Accessibility Object Model
-Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+Explainer: https://github.com/WICG/aom/blob/gh-pages/explainer.md
 Spec: https://wicg.github.io/aom/spec/
 
 -->
diff --git a/third_party/WebKit/LayoutTests/accessibility/aria-grid-readonly-propagation.html b/third_party/WebKit/LayoutTests/accessibility/aria-grid-readonly-propagation.html
new file mode 100644
index 0000000..0f0b1c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/accessibility/aria-grid-readonly-propagation.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<div role="grid" id="grid-readonly-undefined">
+  <div role="row">
+    <div id="cell-undef-undef" role="gridcell">X</div>
+    <div id="cell-undef-true" role="gridcell" aria-readonly="true">X</div>
+    <div id="cell-undef-false" role="gridcell" aria-readonly="false">X</div>
+  </div>
+</div>
+
+<div role="grid" id="grid-readonly-true" aria-readonly="true">
+  <div role="row">
+    <div id="cell-true-undef" role="gridcell">X</div>
+    <div id="cell-true-false" role="gridcell" aria-readonly="false">X</div>
+  </div>
+</div>
+
+<div role="grid" id="grid-readonly-false" aria-readonly="false">
+  <div role="row">
+    <div id="cell-false-undef" role="gridcell">X</div>
+    <div id="cell-false-true" role="gridcell" aria-readonly="true">X</div>
+  </div>
+</div>
+
+<div role="treegrid" id="treegrid-readonly-true" aria-readonly="true">
+  <div role="row">
+    <div id="treegrid-cell-true-undef" role="gridcell">X</div>
+  </div>
+</div>
+
+<script>
+function axElementById(id) {
+    return accessibilityController.accessibleElementById(id);
+}
+
+test(function(t) {
+    var cell = axElementById("cell-undef-undef");
+    assert_equals(cell.restriction, "none");
+}, "readonly=false on cell where readonly is undefined on grid+cell");
+
+test(function(t) {
+    var cell = axElementById("cell-undef-true");
+    assert_equals(cell.restriction, "readOnly");
+}, "readonly=true on a cell");
+
+test(function(t) {
+    var cell = axElementById("cell-undef-false");
+    assert_equals(cell.restriction, "none");
+}, "readonly=false on a cell");
+
+test(function(t) {
+    var cell = axElementById("cell-true-undef");
+    assert_equals(cell.restriction, "readOnly");
+}, "Propagation of readonly=true from grid to cells");
+
+test(function(t) {
+    var cell = axElementById("cell-true-false");
+    assert_equals(cell.restriction, "none");
+}, "Cell readonly=false overrides propagation of grid readonly=true");
+
+test(function(t) {
+    var cell = axElementById("cell-false-undef");
+    assert_equals(cell.restriction, "none");
+}, "Propagation of readonly=false from grid to cells");
+
+test(function(t) {
+    var cell = axElementById("cell-false-true");
+    assert_equals(cell.restriction, "readOnly");
+}, "Cell readonly=true overrides propagation of grid readonly=false");
+
+test(function(t) {
+    var cell = axElementById("treegrid-cell-true-undef");
+    assert_equals(cell.restriction, "readOnly");
+}, "Propagation of readonly=true in a readonly treegrid");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-edge-expected.png
index c00d66e..68c804b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-iframe-expected.png
index 2cb42ce..5e7c78b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 9f41d32..2cd7341 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 65ed7b0..8f52b84 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 2e75ded..02e3fa85 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 2e75ded..02e3fa85 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-edge-expected.png
index 1d1e420b..74f21ec 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-iframe-expected.png
index 2a1910ac..66f9c6a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 875361621d..e56382b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index fe1944b..fa18d194 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-edge-expected.png
index 9fc57c43..f6f1add 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-iframe-expected.png
index f3cf0f315..bc0154d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 73cd371..3158a377 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 12a0d4fa..6f50c13 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-edge-expected.png
index 98661bdf..a095e3599 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-iframe-expected.png
index 80b81aef..5d8bcbcd 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 5f3e91ab..f7df505 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index c5144c1f..9167dc7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-edge-expected.png
index 9fc57c43..f6f1add 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-iframe-expected.png
index f3cf0f315..bc0154d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 73cd371..3158a377 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index e0fc7fad..e3502c5 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-edge-expected.png
index d023e24..9684800 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-iframe-expected.png
index efd08bfc..0b16c3e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index add5d5f3..fa2b51e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index f747e75..57ce195 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-edge-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-edge-expected.png
index 0f3f456..eff64b9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-iframe-expected.png
index 5814476c..9c71554d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 1fa0100..146c1573 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index e371ade..3e57418d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index f2953f4..0ae6029f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index f2953f4..0ae6029f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index fc70038..81be9d35 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -14,7 +14,7 @@
     getter y
     getter z
     method constructor
-interface AccessibleNode
+interface AccessibleNode : EventTarget
     attribute @@toStringTag
     getter activeDescendant
     getter atomic
@@ -43,6 +43,7 @@
     getter modal
     getter multiline
     getter multiselectable
+    getter onaccessibleclick
     getter orientation
     getter owns
     getter placeholder
@@ -91,6 +92,7 @@
     setter modal
     setter multiline
     setter multiselectable
+    setter onaccessibleclick
     setter orientation
     setter owns
     setter placeholder
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index db17cec7..0fe0ae3 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -14,7 +14,7 @@
     getter y
     getter z
     method constructor
-interface AccessibleNode
+interface AccessibleNode : EventTarget
     attribute @@toStringTag
     getter activeDescendant
     getter atomic
@@ -43,6 +43,7 @@
     getter modal
     getter multiline
     getter multiselectable
+    getter onaccessibleclick
     getter orientation
     getter owns
     getter placeholder
@@ -91,6 +92,7 @@
     setter modal
     setter multiline
     setter multiselectable
+    setter onaccessibleclick
     setter orientation
     setter owns
     setter placeholder
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp
index 867567c..eac23bcb 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ErrorHandler.cpp
@@ -78,16 +78,10 @@
       v8::Integer::New(GetIsolate(), error_event->colno()), error};
   v8::TryCatch try_catch(GetIsolate());
   try_catch.SetVerbose(true);
-  v8::MaybeLocal<v8::Value> result;
-  if (ExecutionContext::From(script_state)->IsWorkerGlobalScope()) {
-    result = V8ScriptRunner::CallFunction(
-        call_function, ExecutionContext::From(script_state), this_value,
-        WTF_ARRAY_LENGTH(parameters), parameters, GetIsolate());
-  } else {
-    result = V8ScriptRunner::CallFunction(
-        call_function, ExecutionContext::From(script_state), this_value,
-        WTF_ARRAY_LENGTH(parameters), parameters, GetIsolate());
-  }
+
+  v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallFunction(
+      call_function, ExecutionContext::From(script_state), this_value,
+      WTF_ARRAY_LENGTH(parameters), parameters, GetIsolate());
   v8::Local<v8::Value> return_value;
   if (!result.ToLocal(&return_value))
     return v8::Null(GetIsolate());
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValue.cpp
index 50536ed0..812013fb 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValue.cpp
@@ -203,7 +203,8 @@
 }
 
 static void SwapWiredDataIfNeeded(uint8_t* buffer, size_t buffer_size) {
-  DCHECK(!(buffer_size % sizeof(UChar)));
+  if (buffer_size % sizeof(UChar))
+    return;
 
   if (!IsByteSwappedWiredData(buffer, buffer_size))
     return;
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
index e4ed1c8..2baedd4 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
@@ -38,10 +38,12 @@
  public:
   // WebMessagePortChannel
   void SetClient(WebMessagePortChannelClient* client) override {}
-  void PostMessage(const WebString&, WebMessagePortChannelArray) {
+  void PostMessage(const uint8_t*, size_t, WebMessagePortChannelArray) {
     NOTIMPLEMENTED();
   }
-  bool TryGetMessage(WebString*, WebMessagePortChannelArray&) { return false; }
+  bool TryGetMessage(WebVector<uint8_t>*, WebMessagePortChannelArray&) {
+    return false;
+  }
 };
 
 }  // namespace
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
index 6b9587f2..df64b61 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
@@ -874,10 +874,12 @@
  public:
   // WebMessagePortChannel
   void SetClient(WebMessagePortChannelClient* client) override {}
-  void PostMessage(const WebString&, WebMessagePortChannelArray) {
+  void PostMessage(const uint8_t*, size_t, WebMessagePortChannelArray) {
     NOTIMPLEMENTED();
   }
-  bool TryGetMessage(WebString*, WebMessagePortChannelArray&) { return false; }
+  bool TryGetMessage(WebVector<uint8_t>*, WebMessagePortChannelArray&) {
+    return false;
+  }
 };
 
 MessagePort* MakeMessagePort(
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
index 724181b7..127184a 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
@@ -1004,6 +1004,14 @@
   return false;
 }
 
+const AtomicString& AccessibleNode::InterfaceName() const {
+  return EventTargetNames::AccessibleNode;
+}
+
+ExecutionContext* AccessibleNode::GetExecutionContext() const {
+  return element_->GetExecutionContext();
+}
+
 void AccessibleNode::SetStringProperty(AOMStringProperty property,
                                        const AtomicString& value) {
   for (auto& item : string_properties_) {
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.h b/third_party/WebKit/Source/core/dom/AccessibleNode.h
index 65800d1..238c303c 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.h
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.h
@@ -7,6 +7,7 @@
 
 #include "core/CoreExport.h"
 #include "core/dom/QualifiedName.h"
+#include "core/events/EventTarget.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/wtf/HashMap.h"
 #include "platform/wtf/HashSet.h"
@@ -104,9 +105,7 @@
 // Accessibility Object Model node
 // Explainer: https://github.com/WICG/aom/blob/master/explainer.md
 // Spec: https://wicg.github.io/aom/spec/
-class CORE_EXPORT AccessibleNode
-    : public GarbageCollectedFinalized<AccessibleNode>,
-      public ScriptWrappable {
+class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -328,6 +327,12 @@
   AtomicString valueText() const;
   void setValueText(const AtomicString&);
 
+  // EventTarget
+  const AtomicString& InterfaceName() const override;
+  ExecutionContext* GetExecutionContext() const override;
+
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibleclick);
+
   DECLARE_VIRTUAL_TRACE();
 
  protected:
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.idl b/third_party/WebKit/Source/core/dom/AccessibleNode.idl
index e9909ab..1de11290 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.idl
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.idl
@@ -7,7 +7,7 @@
 // Spec: https://wicg.github.io/aom/spec/
 [
     RuntimeEnabled=AccessibilityObjectModel
-] interface AccessibleNode {
+ ] interface AccessibleNode : EventTarget {
     attribute AccessibleNode? activeDescendant;
     attribute boolean? atomic;
     attribute DOMString? autocomplete;
@@ -55,4 +55,6 @@
     attribute double? valueMin;
     attribute double? valueNow;
     attribute DOMString? valueText;
+
+    attribute EventHandler onaccessibleclick;
 };
diff --git a/third_party/WebKit/Source/core/dom/MessagePort.cpp b/third_party/WebKit/Source/core/dom/MessagePort.cpp
index 3f80707..e83fef2 100644
--- a/third_party/WebKit/Source/core/dom/MessagePort.cpp
+++ b/third_party/WebKit/Source/core/dom/MessagePort.cpp
@@ -81,10 +81,12 @@
   if (exception_state.HadException())
     return;
 
-  WebString message_string = message->ToWireString();
+  StringView wire_data = message->GetWireData();
   WebMessagePortChannelArray web_channels =
       ToWebMessagePortChannelArray(std::move(channels));
-  entangled_channel_->PostMessage(message_string, std::move(web_channels));
+  entangled_channel_->PostMessage(
+      reinterpret_cast<const uint8_t*>(wire_data.Characters8()),
+      wire_data.length(), std::move(web_channels));
 }
 
 // static
@@ -161,9 +163,9 @@
 static bool TryGetMessageFrom(WebMessagePortChannel& web_channel,
                               RefPtr<SerializedScriptValue>& message,
                               MessagePortChannelArray& channels) {
-  WebString message_string;
+  WebVector<uint8_t> message_data;
   WebMessagePortChannelArray web_channels;
-  if (!web_channel.TryGetMessage(&message_string, web_channels))
+  if (!web_channel.TryGetMessage(&message_data, web_channels))
     return false;
 
   if (web_channels.size()) {
@@ -171,7 +173,8 @@
     for (size_t i = 0; i < web_channels.size(); ++i)
       channels[i] = std::move(web_channels[i]);
   }
-  message = SerializedScriptValue::Create(message_string);
+  message = SerializedScriptValue::Create(
+      reinterpret_cast<const char*>(message_data.Data()), message_data.size());
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index a670b4f..5f1e46c 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -562,15 +562,14 @@
     visibility = HandleVisibility::kVisible;
   }
 
-  const VisibleSelectionInFlatTree& adjusted_selection =
+  const SelectionInFlatTree& adjusted_selection =
       append_trailing_whitespace == AppendTrailingWhitespace::kShouldAppend
-          ? new_selection.AppendTrailingWhitespace()
-          : new_selection;
+          ? AdjustSelectionWithTrailingWhitespace(new_selection.AsSelection())
+          : new_selection.AsSelection();
 
   return UpdateSelectionForMouseDownDispatchingSelectStart(
       inner_node,
-      ExpandSelectionToRespectUserSelectAll(inner_node,
-                                            adjusted_selection.AsSelection()),
+      ExpandSelectionToRespectUserSelectAll(inner_node, adjusted_selection),
       TextGranularity::kWord, visibility);
 }
 
@@ -608,14 +607,13 @@
   const PositionInFlatTree end(container_node, marker->EndOffset());
   const VisibleSelectionInFlatTree& new_selection = CreateVisibleSelection(
       SelectionInFlatTree::Builder().Collapse(start).Extend(end).Build());
-  const VisibleSelectionInFlatTree& adjusted_selection =
+  const SelectionInFlatTree& adjusted_selection =
       append_trailing_whitespace == AppendTrailingWhitespace::kShouldAppend
-          ? new_selection.AppendTrailingWhitespace()
-          : new_selection;
+          ? AdjustSelectionWithTrailingWhitespace(new_selection.AsSelection())
+          : new_selection.AsSelection();
   UpdateSelectionForMouseDownDispatchingSelectStart(
       inner_node,
-      ExpandSelectionToRespectUserSelectAll(inner_node,
-                                            adjusted_selection.AsSelection()),
+      ExpandSelectionToRespectUserSelectAll(inner_node, adjusted_selection),
       TextGranularity::kWord, HandleVisibility::kNotVisible);
 }
 
@@ -806,11 +804,7 @@
     original_base_in_flat_tree_ = PositionInFlatTreeWithAffinity();
   }
 
-  builder.SetIsHandleVisible(handle_visibility == HandleVisibility::kVisible)
-      .SetIsDirectional(frame_->GetEditor()
-                            .Behavior()
-                            .ShouldConsiderSelectionAsDirectional() ||
-                        new_selection.IsDirectional());
+  builder.SetIsHandleVisible(handle_visibility == HandleVisibility::kVisible);
   const SelectionInFlatTree& selection_in_flat_tree = builder.Build();
   if (Selection().ComputeVisibleSelectionInFlatTree() ==
           CreateVisibleSelection(selection_in_flat_tree) &&
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 0978c235..960a44c4 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -210,22 +210,30 @@
   return NormalizeRange(EphemeralRangeTemplate<Strategy>(Start(), End()));
 }
 
-template <typename Strategy>
-VisibleSelectionTemplate<Strategy>
-VisibleSelectionTemplate<Strategy>::AppendTrailingWhitespace() const {
-  if (IsNone())
-    return *this;
-  if (!IsRange())
-    return *this;
-  const PositionTemplate<Strategy>& new_end = SkipWhitespace(End());
-  if (End() == new_end)
-    return *this;
-  VisibleSelectionTemplate<Strategy> result = *this;
-  if (base_is_first_)
-    result.extent_ = new_end;
-  else
-    result.base_ = new_end;
-  return result;
+// TODO(editing-dev): We should move |AdjustSelectionWithTrailingWhitespace()|
+// to "SelectionController.cpp" as file local function.
+SelectionInFlatTree AdjustSelectionWithTrailingWhitespace(
+    const SelectionInFlatTree& selection) {
+  if (selection.IsNone())
+    return selection;
+  if (!selection.IsRange())
+    return selection;
+  const bool base_is_first =
+      selection.Base() == selection.ComputeStartPosition();
+  const PositionInFlatTree& end =
+      base_is_first ? selection.Extent() : selection.Base();
+  DCHECK_EQ(end, selection.ComputeEndPosition());
+  const PositionInFlatTree& new_end = SkipWhitespace(end);
+  if (end == new_end)
+    return selection;
+  if (base_is_first) {
+    return SelectionInFlatTree::Builder(selection)
+        .SetBaseAndExtent(selection.Base(), new_end)
+        .Build();
+  }
+  return SelectionInFlatTree::Builder(selection)
+      .SetBaseAndExtent(new_end, selection.Extent())
+      .Build();
 }
 
 template <typename Strategy>
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.h b/third_party/WebKit/Source/core/editing/VisibleSelection.h
index 3aedf54..7bc94a2 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.h
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.h
@@ -106,8 +106,6 @@
   bool IsBaseFirst() const { return base_is_first_; }
   bool IsDirectional() const { return is_directional_; }
 
-  VisibleSelectionTemplate<Strategy> AppendTrailingWhitespace() const;
-
   // TODO(yosin) Most callers probably don't want these functions, but
   // are using them for historical reasons. |toNormalizedEphemeralRange()|
   // contracts the range around text, and moves the caret most backward
@@ -199,6 +197,11 @@
     const PositionInFlatTreeWithAffinity&,
     TextGranularity);
 
+// TODO(editing-dev): We should move |AdjustSelectionWithTrailingWhitespace()|
+// to "SelectionController.cpp" as file local function.
+CORE_EXPORT SelectionInFlatTree
+AdjustSelectionWithTrailingWhitespace(const SelectionInFlatTree&);
+
 }  // namespace blink
 
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp b/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
index 1d90f7c1..9d43cef 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
@@ -71,8 +71,9 @@
       granularity);
 }
 
+// TODO(editing-dev): We should move this test to "SelectionControllerTest.cpp"
 // For http://crbug.com/700368
-TEST_F(VisibleSelectionTest, appendTrailingWhitespaceWithAfterAnchor) {
+TEST_F(VisibleSelectionTest, AdjustSelectionWithTrailingWhitespace) {
   SetBodyContent(
       "<input type=checkbox>"
       "<div style='user-select:none'>abc</div>");
@@ -82,16 +83,19 @@
   // TODO(editing-dev): We should remove above comment once we fix [1].
   // [1] http://crbug.com/701657 double-click on user-select:none should not
   // compute selection.
-  const VisibleSelection selection = CreateVisibleSelectionWithGranularity(
-      SelectionInDOMTree::Builder()
-          .Collapse(Position::BeforeNode(*input))
-          .Extend(Position::AfterNode(*input))
-          .Build(),
-      TextGranularity::kWord);
-  const VisibleSelection result = selection.AppendTrailingWhitespace();
+  const VisibleSelectionInFlatTree& selection =
+      CreateVisibleSelectionWithGranularity(
+          SelectionInFlatTree::Builder()
+              .Collapse(PositionInFlatTree::BeforeNode(*input))
+              .Extend(PositionInFlatTree::AfterNode(*input))
+              .Build(),
+          TextGranularity::kWord);
+  const SelectionInFlatTree& result =
+      AdjustSelectionWithTrailingWhitespace(selection.AsSelection());
 
-  EXPECT_EQ(Position::BeforeNode(*input), result.Start());
-  EXPECT_EQ(Position::AfterNode(*input), result.End());
+  EXPECT_EQ(PositionInFlatTree::BeforeNode(*input),
+            result.ComputeStartPosition());
+  EXPECT_EQ(PositionInFlatTree::AfterNode(*input), result.ComputeEndPosition());
 }
 
 TEST_F(VisibleSelectionTest, expandUsingGranularity) {
diff --git a/third_party/WebKit/Source/core/events/EventTargetFactory.json5 b/third_party/WebKit/Source/core/events/EventTargetFactory.json5
index fe22a3cc..5fc15f07 100644
--- a/third_party/WebKit/Source/core/events/EventTargetFactory.json5
+++ b/third_party/WebKit/Source/core/events/EventTargetFactory.json5
@@ -9,6 +9,7 @@
     "core/clipboard/Clipboard",
     "core/css/FontFaceSet",
     "core/css/MediaQueryList",
+    "core/dom/AccessibleNode",
     "core/dom/BroadcastChannel",
     "core/dom/MessagePort",
     "core/dom/Node",
diff --git a/third_party/WebKit/Source/core/events/EventTypeNames.json5 b/third_party/WebKit/Source/core/events/EventTypeNames.json5
index a79b8b75..b78ea3d9 100644
--- a/third_party/WebKit/Source/core/events/EventTypeNames.json5
+++ b/third_party/WebKit/Source/core/events/EventTypeNames.json5
@@ -17,6 +17,7 @@
     "DOMSubtreeModified",
     "abort",
     "abortpayment",
+    "accessibleclick",
     "activate",
     "active",
     "addsourcebuffer",
diff --git a/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css b/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css
index 0c8f0d1..4394cccf 100644
--- a/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css
+++ b/third_party/WebKit/Source/core/html/forms/resources/validation_bubble.css
@@ -13,7 +13,6 @@
   box-sizing: border-box;
   display: inline-block;
   font-family: system-ui;
-  font-size: 16px;
   max-width: 50%;
   opacity: 0;
   position: absolute;
@@ -22,19 +21,33 @@
 
 #container.shown-initially {
   /* If scaleY is smaller than 0.2, an assertion failure occurs in Skia. */
-  transform: scaleY(0.2);
+  transform: scale(0.96, 0.96);
 }
 
 #container.shown-fully {
   opacity: 1.0;
-  transform: scaleY(1);
-  transition: opacity 0.3s, transform 0.3s;
+  transform: scale(1, 1);
+  transition: opacity 466.67ms cubic-bezier(0.4, 0, 0.2, 1), transform 1166.67ms cubic-bezier(0.2, 0, 0, 1);
 }
 
 #container.hiding {
   opacity: 0;
   /* See ValidationMessageClientImpl::HideValidationMessage too */
-  transition: opacity 0.6s;
+  transition: opacity 133.33ms cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+#container.shown-initially -webkit-any(#icon, #main-message, #sub-message) {
+  opacity: 0;
+}
+
+#container.shown-fully -webkit-any(#icon, #main-message, #sub-message) {
+  opacity: 1;
+  transition: opacity 700ms cubic-bezier(0.3, 0, 0.1, 1);
+}
+
+#container.hiding -webkit-any(#icon, #main-message, #sub-message) {
+  opacity: 0;
+  transition: opacity 116.67ms cubic-bezier(0.4, 0, 0.2, 1);
 }
 
 #bubble-body {
@@ -115,7 +128,7 @@
 }
 
 #main-message {
-  font-size: 16px;
+  font-size: 14px;
   grid-row: 1;
   grid-column: 2;
   margin-top: 3px;
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index d128ca0..cf2e930 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -491,6 +491,10 @@
     ]
   }
 
+  if (is_fuchsia) {
+    sources += [ "LayoutThemeFuchsia.cpp" ]
+  }
+
   configs += [
     # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
     "//build/config/compiler:no_size_t_to_int_warning",
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeFuchsia.cpp b/third_party/WebKit/Source/core/layout/LayoutThemeFuchsia.cpp
new file mode 100644
index 0000000..b6087d45
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeFuchsia.cpp
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/layout/LayoutThemeDefault.h"
+
+namespace blink {
+namespace {
+
+// Fuchsia is headless-only for now, so no native themes are applied.
+// TODO(fuchsia): Implement this when we enable the UI. (crbug.com/750946)
+class LayoutThemeFuchsia : public LayoutThemeDefault {
+ public:
+  static RefPtr<LayoutTheme> Create() {
+    return AdoptRef(new LayoutThemeFuchsia());
+  }
+};
+
+}  // namespace
+
+LayoutTheme& LayoutTheme::NativeTheme() {
+  DEFINE_STATIC_REF(LayoutTheme, layout_theme, (LayoutThemeFuchsia::Create()));
+  return *layout_theme;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp
index 5b22a24..ebd4b46 100644
--- a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp
+++ b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp
@@ -132,7 +132,7 @@
       this, &ValidationMessageClientImpl::Reset);
   // This should be equal to or larger than transition duration of
   // #container.hiding in validation_bubble.css.
-  const double kHidingAnimationDuration = 0.6;
+  const double kHidingAnimationDuration = 0.13333;
   timer_->StartOneShot(kHidingAnimationDuration, BLINK_FROM_HERE);
 }
 
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
index da9f848..7dc76e4 100644
--- a/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
+++ b/third_party/WebKit/Source/core/page/ValidationMessageOverlayDelegate.cpp
@@ -158,8 +158,15 @@
                                       kForceSynchronousLoad)));
 
   Element& container = GetElementById("container");
-  if (LayoutTestSupport::IsRunningLayoutTest())
+  if (LayoutTestSupport::IsRunningLayoutTest()) {
     container.SetInlineStyleProperty(CSSPropertyTransition, "none");
+    GetElementById("icon").SetInlineStyleProperty(CSSPropertyTransition,
+                                                  "none");
+    GetElementById("main-message")
+        .SetInlineStyleProperty(CSSPropertyTransition, "none");
+    GetElementById("sub-message")
+        .SetInlineStyleProperty(CSSPropertyTransition, "none");
+  }
   // Get the size to decide position later.
   FrameView().UpdateAllLifecyclePhases();
   bubble_size_ = container.VisibleBoundsInVisualViewport().Size();
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
index 823fd72a..d500c14 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
@@ -5,7 +5,9 @@
 #include "core/paint/BoxPaintInvalidator.h"
 
 #include "core/HTMLNames.h"
+#include "core/frame/FrameTestHelpers.h"
 #include "core/frame/LocalFrameView.h"
+#include "core/html/HTMLFrameOwnerElement.h"
 #include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutView.h"
 #include "core/paint/PaintInvalidator.h"
@@ -115,6 +117,33 @@
 
 INSTANTIATE_TEST_CASE_P(All, BoxPaintInvalidatorTest, ::testing::Bool());
 
+TEST_P(BoxPaintInvalidatorTest, SlowMapToVisualRectInAncestorSpaceLayoutView) {
+  SetBodyInnerHTML(
+      "<!doctype html>"
+      "<style>"
+      "#parent {"
+      "    display: inline-block;"
+      "    width: 300px;"
+      "    height: 300px;"
+      "    margin-top: 200px;"
+      "    filter: blur(3px);"  // Forces the slow path in
+                                // SlowMapToVisualRectInAncestorSpace.
+      "    border: 1px solid rebeccapurple;"
+      "}"
+      "</style>"
+      "<div id=parent>"
+      "  <iframe id='target' src='data:text/html,<body style='background: "
+      "blue;'></body>'></iframe>"
+      "</div>");
+
+  auto& target = *GetDocument().getElementById("target");
+  EXPECT_RECT_EQ(IntRect(2, 202, 318, 168),
+                 EnclosingIntRect(ToHTMLFrameOwnerElement(target)
+                                      .contentDocument()
+                                      ->GetLayoutView()
+                                      ->VisualRect()));
+}
+
 TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
   ScopedSlimmingPaintV2ForTest spv2(true);
 
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
index 9e56498..971ab59 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
@@ -38,9 +38,9 @@
   if (object.IsLayoutView()) {
     ToLayoutView(object).MapToVisualRectInAncestorSpace(
         &ancestor, result, kInputIsInFrameCoordinates, kDefaultVisualRectFlags);
+  } else {
+    object.MapToVisualRectInAncestorSpace(&ancestor, result);
   }
-
-  object.MapToVisualRectInAncestorSpace(&ancestor, result);
   return result;
 }
 
diff --git a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp
index 21fe2a9..d3e2c12 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp
@@ -134,4 +134,22 @@
   return kCellRole;
 }
 
+AXRestriction AXARIAGridCell::Restriction() const {
+  const AXRestriction cell_restriction = AXLayoutObject::Restriction();
+  // Specified gridcell restriction or local ARIA markup takes precedence.
+  if (cell_restriction != kNone || HasAttribute(HTMLNames::aria_readonlyAttr) ||
+      HasAttribute(HTMLNames::aria_disabledAttr))
+    return cell_restriction;
+
+  // Gridcell does not have it's own ARIA input restriction, so
+  // fall back on parent grid's readonly state.
+  // See ARIA specification regarding grid/treegrid and readonly.
+  const AXObject* container = ParentTable();
+  const bool is_in_readonly_grid = container &&
+                                   (container->RoleValue() == kGridRole ||
+                                    container->RoleValue() == kTreeGridRole) &&
+                                   container->Restriction() == kReadOnly;
+  return is_in_readonly_grid ? kReadOnly : kNone;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h
index 28aa170..67cf5ac 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h
@@ -50,6 +50,7 @@
   // fills in the start location and column span of cell
   void ColumnIndexRange(std::pair<unsigned, unsigned>& column_range) override;
   AccessibilityRole ScanToDecideHeaderRole() final;
+  AXRestriction Restriction() const final;
   bool CanSetSelectedAttribute() const final {
     return Restriction() != kDisabled;
   }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
index 75b23e29..7d938e6 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -1306,6 +1306,7 @@
     case kCellRole:
     case kCheckBoxRole:
     case kColorWellRole:
+    case kColumnHeaderRole:
     case kComboBoxRole:
     case kDateRole:
     case kDateTimeRole:
@@ -1317,12 +1318,14 @@
     case kMenuItemRadioRole:
     case kPopUpButtonRole:
     case kRadioGroupRole:
+    case kRowHeaderRole:
     case kSearchBoxRole:
     case kSliderRole:
     case kSpinButtonRole:
     case kSwitchRole:
     case kTextFieldRole:
     case kToggleButtonRole:
+    case kTreeGridRole:
       return true;
     default:
       break;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index 1c30b7ce..9a1e1b1 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -822,6 +822,77 @@
   return 0;
 }
 
+bool AXObject::DispatchEventToAOMEventListeners(Event& event,
+                                                Element* target_element) {
+  HeapVector<Member<AccessibleNode>> event_path;
+  for (AXObject* ancestor = this; ancestor;
+       ancestor = ancestor->ParentObject()) {
+    Element* ancestor_element = ancestor->GetElement();
+    if (!ancestor_element)
+      continue;
+
+    AccessibleNode* ancestor_accessible_node =
+        ancestor_element->ExistingAccessibleNode();
+    if (!ancestor_accessible_node)
+      continue;
+
+    event_path.push_back(ancestor_accessible_node);
+  }
+
+  // Short-circuit: if there are no AccessibleNodes attached anywhere
+  // in the ancestry of this node, exit.
+  if (!event_path.size())
+    return false;
+
+  // Since we now know the AOM is being used in this document, get the
+  // AccessibleNode for the target element and create it if necessary -
+  // otherwise we wouldn't be able to set the event target. However note
+  // that if it didn't previously exist it won't be part of the event path.
+  if (!target_element)
+    target_element = GetElement();
+  AccessibleNode* target = nullptr;
+  if (target_element) {
+    target = target_element->accessibleNode();
+    event.SetTarget(target);
+  }
+
+  // Capturing phase.
+  event.SetEventPhase(Event::kCapturingPhase);
+  for (int i = static_cast<int>(event_path.size()) - 1; i >= 0; i--) {
+    // Don't call capturing event listeners on the target. Note that
+    // the target may not necessarily be in the event path which is why
+    // we check here.
+    if (event_path[i] == target)
+      break;
+
+    event.SetCurrentTarget(event_path[i]);
+    event_path[i]->FireEventListeners(&event);
+    if (event.PropagationStopped())
+      return true;
+  }
+
+  // Targeting phase.
+  event.SetEventPhase(Event::kAtTarget);
+  event.SetCurrentTarget(event_path[0]);
+  event_path[0]->FireEventListeners(&event);
+  if (event.PropagationStopped())
+    return true;
+
+  // Bubbling phase.
+  event.SetEventPhase(Event::kBubblingPhase);
+  for (size_t i = 1; i < event_path.size(); i++) {
+    event.SetCurrentTarget(event_path[i]);
+    event_path[i]->FireEventListeners(&event);
+    if (event.PropagationStopped())
+      return true;
+  }
+
+  if (event.defaultPrevented())
+    return true;
+
+  return false;
+}
+
 bool AXObject::IsDescendantOfDisabledNode() const {
   UpdateCachedAttributeValuesIfNeeded();
   return cached_is_descendant_of_disabled_node_;
@@ -1714,6 +1785,10 @@
 // Modify or take an action on an object.
 //
 
+bool AXObject::PerformDefaultAction() {
+  return Press();
+}
+
 bool AXObject::Press() {
   Document* document = GetDocument();
   if (!document)
@@ -1722,6 +1797,10 @@
   UserGestureIndicator gesture_indicator(
       UserGestureToken::Create(document, UserGestureToken::kNewGesture));
   Element* action_elem = ActionElement();
+  Event* event = Event::CreateCancelable(EventTypeNames::accessibleclick);
+  if (DispatchEventToAOMEventListeners(*event, action_elem))
+    return true;
+
   if (action_elem) {
     action_elem->AccessKeyAction(true);
     return true;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h
index 306d608..0ebb7b0d 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -771,7 +771,7 @@
   // Modify or take an action on an object.
   virtual void Increment() {}
   virtual void Decrement() {}
-  bool PerformDefaultAction() { return Press(); }
+  bool PerformDefaultAction();
   virtual bool Press();
   // Make this object visible by scrolling as many nested scrollable views as
   // needed.
@@ -862,6 +862,9 @@
 
   const AXObject* InertRoot() const;
 
+  // Returns true if the event was handled.
+  bool DispatchEventToAOMEventListeners(Event&, Element*);
+
   mutable Member<AXObject> parent_;
 
   // The following cached attribute values (the ones starting with m_cached*)
diff --git a/third_party/WebKit/public/platform/WebMessagePortChannel.h b/third_party/WebKit/public/platform/WebMessagePortChannel.h
index 8c01ef8..9ed5762d 100644
--- a/third_party/WebKit/public/platform/WebMessagePortChannel.h
+++ b/third_party/WebKit/public/platform/WebMessagePortChannel.h
@@ -39,7 +39,6 @@
 
 class WebMessagePortChannelClient;
 class WebMessagePortChannel;
-class WebString;
 
 using WebMessagePortChannelArray =
     WebVector<std::unique_ptr<WebMessagePortChannel>>;
@@ -51,8 +50,11 @@
   virtual void SetClient(WebMessagePortChannelClient*) = 0;
   // Callee receives ownership of the passed vector.
   // FIXME: Blob refs should be passed to maintain ref counts. crbug.com/351753
-  virtual void PostMessage(const WebString&, WebMessagePortChannelArray) = 0;
-  virtual bool TryGetMessage(WebString*, WebMessagePortChannelArray&) = 0;
+  virtual void PostMessage(const uint8_t*,
+                           size_t,
+                           WebMessagePortChannelArray) = 0;
+  virtual bool TryGetMessage(WebVector<uint8_t>*,
+                             WebMessagePortChannelArray&) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebVector.h b/third_party/WebKit/public/platform/WebVector.h
index 6fa6056..600928b7 100644
--- a/third_party/WebKit/public/platform/WebVector.h
+++ b/third_party/WebKit/public/platform/WebVector.h
@@ -81,6 +81,8 @@
 
   WebVector(WebVector<T>&& other) { Swap(other); }
 
+  WebVector(std::vector<T>&& other) : data_(std::move(other)) {}
+
   WebVector& operator=(const WebVector& other) {
     if (this != &other)
       Assign(other);
@@ -100,6 +102,11 @@
     return *this;
   }
 
+  WebVector<T>& operator=(std::vector<T>&& other) {
+    data_ = std::move(other);
+    return *this;
+  }
+
   template <typename C>
   void Assign(const C& other) {
     data_.assign(other.begin(), other.end());
diff --git a/third_party/usrsctp/BUILD.gn b/third_party/usrsctp/BUILD.gn
index e505d33..5e6c244 100644
--- a/third_party/usrsctp/BUILD.gn
+++ b/third_party/usrsctp/BUILD.gn
@@ -9,6 +9,12 @@
     "usrsctplib/usrsctplib",
     "usrsctplib/usrsctplib/netinet",
   ]
+  if (is_clang && llvm_force_head_revision) {
+    cflags = [
+      # TODO(hans): https://crbug.com/749197
+      "-Wno-pragma-pack",
+    ]
+  }
 }
 
 config("usrsctp_warnings") {
diff --git a/third_party/usrsctp/README.chromium b/third_party/usrsctp/README.chromium
index b903242..598a214 100644
--- a/third_party/usrsctp/README.chromium
+++ b/third_party/usrsctp/README.chromium
@@ -1,8 +1,8 @@
 Name: usrsctp
 URL: http://github.com/sctplab/usrsctp
 Version: 0
-Date: Jul 28, 2017
-Revision: 76bea922c32b742ecf5c4a0c64dcfb95ab5387c0
+Date: Jul 25, 2016
+Revision: 9a3e5465e9d96d8a7f78f1e996412d6235d7a359
 License: New BSD
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h
index 59d7428..80ea2a77 100644
--- a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h
+++ b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h
@@ -442,6 +442,26 @@
 };
 #endif /* ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_ENUM */
 
+#ifndef ZCR_REMOTE_SURFACE_V1_ORIENTATION_ENUM
+#define ZCR_REMOTE_SURFACE_V1_ORIENTATION_ENUM
+/**
+ * @ingroup iface_zcr_remote_surface_v1
+ * window orientation
+ *
+ * The orientation of the window.
+ */
+enum zcr_remote_surface_v1_orientation {
+	/**
+	 * portrait
+	 */
+	ZCR_REMOTE_SURFACE_V1_ORIENTATION_PORTRAIT = 1,
+	/**
+	 * landscape
+	 */
+	ZCR_REMOTE_SURFACE_V1_ORIENTATION_LANDSCAPE = 2,
+};
+#endif /* ZCR_REMOTE_SURFACE_V1_ORIENTATION_ENUM */
+
 /**
  * @ingroup iface_zcr_remote_surface_v1
  * @struct zcr_remote_surface_v1_listener
@@ -539,6 +559,7 @@
 #define ZCR_REMOTE_SURFACE_V1_UNSET_ALWAYS_ON_TOP 21
 #define ZCR_REMOTE_SURFACE_V1_ACK_CONFIGURE 22
 #define ZCR_REMOTE_SURFACE_V1_MOVE 23
+#define ZCR_REMOTE_SURFACE_V1_SET_ORIENTATION 24
 
 /**
  * @ingroup iface_zcr_remote_surface_v1
@@ -649,6 +670,10 @@
  * @ingroup iface_zcr_remote_surface_v1
  */
 #define ZCR_REMOTE_SURFACE_V1_MOVE_SINCE_VERSION 5
+/**
+ * @ingroup iface_zcr_remote_surface_v1
+ */
+#define ZCR_REMOTE_SURFACE_V1_SET_ORIENTATION_SINCE_VERSION 6
 
 /** @ingroup iface_zcr_remote_surface_v1 */
 static inline void
@@ -1076,6 +1101,18 @@
 			 ZCR_REMOTE_SURFACE_V1_MOVE);
 }
 
+/**
+ * @ingroup iface_zcr_remote_surface_v1
+ *
+ * Set an orientation for the surface.
+ */
+static inline void
+zcr_remote_surface_v1_set_orientation(struct zcr_remote_surface_v1 *zcr_remote_surface_v1, int32_t orientation)
+{
+	wl_proxy_marshal((struct wl_proxy *) zcr_remote_surface_v1,
+			 ZCR_REMOTE_SURFACE_V1_SET_ORIENTATION, orientation);
+}
+
 #define ZCR_NOTIFICATION_SURFACE_V1_DESTROY 0
 
 
diff --git a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h
index 544f49d4..9b980dc 100644
--- a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h
+++ b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h
@@ -383,6 +383,26 @@
 };
 #endif /* ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_ENUM */
 
+#ifndef ZCR_REMOTE_SURFACE_V1_ORIENTATION_ENUM
+#define ZCR_REMOTE_SURFACE_V1_ORIENTATION_ENUM
+/**
+ * @ingroup iface_zcr_remote_surface_v1
+ * window orientation
+ *
+ * The orientation of the window.
+ */
+enum zcr_remote_surface_v1_orientation {
+	/**
+	 * portrait
+	 */
+	ZCR_REMOTE_SURFACE_V1_ORIENTATION_PORTRAIT = 1,
+	/**
+	 * landscape
+	 */
+	ZCR_REMOTE_SURFACE_V1_ORIENTATION_LANDSCAPE = 2,
+};
+#endif /* ZCR_REMOTE_SURFACE_V1_ORIENTATION_ENUM */
+
 /**
  * @ingroup iface_zcr_remote_surface_v1
  * @struct zcr_remote_surface_v1_interface
@@ -712,6 +732,15 @@
 	 */
 	void (*move)(struct wl_client *client,
 		     struct wl_resource *resource);
+	/**
+	 * set orientation
+	 *
+	 * Set an orientation for the surface.
+	 * @since 6
+	 */
+	void (*set_orientation)(struct wl_client *client,
+				struct wl_resource *resource,
+				int32_t orientation);
 };
 
 #define ZCR_REMOTE_SURFACE_V1_CLOSE 0
@@ -827,6 +856,10 @@
  * @ingroup iface_zcr_remote_surface_v1
  */
 #define ZCR_REMOTE_SURFACE_V1_MOVE_SINCE_VERSION 5
+/**
+ * @ingroup iface_zcr_remote_surface_v1
+ */
+#define ZCR_REMOTE_SURFACE_V1_SET_ORIENTATION_SINCE_VERSION 6
 
 /**
  * @ingroup iface_zcr_remote_surface_v1
diff --git a/third_party/wayland-protocols/protocol/remote-shell-protocol.c b/third_party/wayland-protocols/protocol/remote-shell-protocol.c
index 49695d8..690940e8 100644
--- a/third_party/wayland-protocols/protocol/remote-shell-protocol.c
+++ b/third_party/wayland-protocols/protocol/remote-shell-protocol.c
@@ -69,7 +69,7 @@
 };
 
 WL_EXPORT const struct wl_interface zcr_remote_shell_v1_interface = {
-	"zcr_remote_shell_v1", 5,
+	"zcr_remote_shell_v1", 6,
 	3, zcr_remote_shell_v1_requests,
 	4, zcr_remote_shell_v1_events,
 };
@@ -99,6 +99,7 @@
 	{ "unset_always_on_top", "4", types + 0 },
 	{ "ack_configure", "5u", types + 0 },
 	{ "move", "5", types + 0 },
+	{ "set_orientation", "6i", types + 0 },
 };
 
 static const struct wl_message zcr_remote_surface_v1_events[] = {
@@ -108,8 +109,8 @@
 };
 
 WL_EXPORT const struct wl_interface zcr_remote_surface_v1_interface = {
-	"zcr_remote_surface_v1", 5,
-	24, zcr_remote_surface_v1_requests,
+	"zcr_remote_surface_v1", 6,
+	25, zcr_remote_surface_v1_requests,
 	3, zcr_remote_surface_v1_events,
 };
 
diff --git a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
index 1c6c71e7..fb5a37b 100644
--- a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
+++ b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
@@ -38,7 +38,7 @@
     reset.
   </description>
 
-  <interface name="zcr_remote_shell_v1" version="5">
+  <interface name="zcr_remote_shell_v1" version="6">
     <description summary="remote_shell">
       The global interface that allows clients to turn a wl_surface into a
       "real window" which is remotely managed but can be stacked, activated
@@ -171,7 +171,7 @@
     </event>
   </interface>
 
-  <interface name="zcr_remote_surface_v1" version="5">
+  <interface name="zcr_remote_surface_v1" version="6">
     <description summary="A desktop window">
       An interface that may be implemented by a wl_surface, for
       implementations that provide a desktop-style user interface
@@ -196,6 +196,14 @@
       <entry name="autohide_sticky" value="3" summary="system ui autohides and is sticky"/>
     </enum>
 
+    <enum name="orientation">
+      <description summary="window orientation">
+         The orientation of the window.
+      </description>
+      <entry name="portrait" value="1" summary="portrait"/>
+      <entry name="landscape" value="2" summary="landscape"/>
+    </enum>
+
     <request name="destroy" type="destructor">
       <description summary="Destroy the remote_surface">
 	Unmap and destroy the window. The window will be effectively
@@ -533,6 +541,15 @@
       </description>
     </request>
 
+    <!-- Version 6 additions -->
+
+    <request name="set_orientation" since="6">
+      <description summary="set orientation">
+	Set an orientation for the surface.
+      </description>
+      <arg name="orientation" type="int"/>
+    </request>
+
   </interface>
 
   <interface name="zcr_notification_surface_v1" version="1">
diff --git a/tools/checkteamtags/checkteamtags.py b/tools/checkteamtags/checkteamtags.py
index 40df48a..c12166fe 100755
--- a/tools/checkteamtags/checkteamtags.py
+++ b/tools/checkteamtags/checkteamtags.py
@@ -75,6 +75,10 @@
   for dir_name, tags in current_mappings.iteritems():
     team = tags.get('team')
     component = tags.get('component')
+    os_tag = tags.get('os')
+    if os_tag:
+      component = '%s(%s)' % (component, os)
+
     if component:
       new_dir_to_component[dir_name] = component
     if team:
@@ -92,7 +96,7 @@
     team_details = []
     for team in teams:
       offending_dirs = [d for d in team_to_dir[team]
-                        if new_dir_to_component[d] == component]
+                        if new_dir_to_component.get(d) == component]
       team_details.append('%(team)s is used in %(paths)s' % {
           'team': team,
           'paths': ', '.join(offending_dirs),
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b9045aa..51c93ae 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -22888,6 +22888,7 @@
   <int value="-1319688939" label="ignore-gpu-blacklist"/>
   <int value="-1310737697" label="MaterialDesignSettings:enabled"/>
   <int value="-1302904242" label="enable-navigation-tracing"/>
+  <int value="-1294050129" label="ContentFullscreen:disabled"/>
   <int value="-1289678848" label="SystemDownloadManager:enabled"/>
   <int value="-1285021473" label="save-page-as-mhtml"/>
   <int value="-1284637134" label="pull-to-refresh"/>
@@ -23070,6 +23071,7 @@
   <int value="-714710496" label="VideoFullscreenOrientationLock:disabled"/>
   <int value="-711890895" label="enable-website-settings-manager"/>
   <int value="-709058455" label="ui-slow-animations"/>
+  <int value="-702477233" label="ContentFullscreen:enabled"/>
   <int value="-699767107" label="enable-sync-app-list"/>
   <int value="-697751423" label="disable-quickoffice-component-app"/>
   <int value="-684900739" label="disable-merge-key-char-events"/>
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc
index 5770c95..80d62e83 100644
--- a/ui/app_list/app_list_constants.cc
+++ b/ui/app_list/app_list_constants.cc
@@ -61,6 +61,7 @@
 const float kFolderBubbleOffsetY = 1;
 
 const SkColor kCardBackgroundColor = SK_ColorWHITE;
+const SkColor kCardBackgroundColorFullscreen = SkColorSetRGB(0xFA, 0xFA, 0xFC);
 
 // Duration in milliseconds for page transition.
 const int kPageTransitionDurationInMs = 180;
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h
index de71454..d4cf5ed8 100644
--- a/ui/app_list/app_list_constants.h
+++ b/ui/app_list/app_list_constants.h
@@ -60,6 +60,7 @@
 APP_LIST_EXPORT extern const float kFolderBubbleOffsetY;
 
 APP_LIST_EXPORT extern const SkColor kCardBackgroundColor;
+APP_LIST_EXPORT extern const SkColor kCardBackgroundColorFullscreen;
 
 APP_LIST_EXPORT extern const int kPageTransitionDurationInMs;
 APP_LIST_EXPORT extern const int kOverscrollPageTransitionDurationMs;
diff --git a/ui/app_list/presenter/app_list_presenter_impl.cc b/ui/app_list/presenter/app_list_presenter_impl.cc
index 14d140b..cde82c6 100644
--- a/ui/app_list/presenter/app_list_presenter_impl.cc
+++ b/ui/app_list/presenter/app_list_presenter_impl.cc
@@ -24,6 +24,12 @@
 // Duration for show/hide animation in milliseconds.
 constexpr int kAnimationDurationMs = 200;
 
+// Duration for hide animation for the fullscreen app list in milliseconds.
+constexpr int kAnimationDurationMsFullscreen = 300;
+
+// Offset for the hide animation for the fullscreen app list in DIPs.
+constexpr int kHideAnimationOffset = 400;
+
 // The maximum shift in pixels when over-scroll happens.
 constexpr int kMaxOverScrollShift = 48;
 
@@ -180,23 +186,29 @@
   views::Widget* widget = view_->GetWidget();
   ui::Layer* layer = GetLayer(widget);
   layer->GetAnimator()->StopAnimating();
-
   gfx::Rect target_bounds = widget->GetWindowBoundsInScreen();
-  gfx::Vector2d offset = presenter_delegate_->GetVisibilityAnimationOffset(
-      widget->GetNativeView()->GetRootWindow());
-  if (is_visible_) {
-    gfx::Rect start_bounds = gfx::Rect(target_bounds);
-    start_bounds.Offset(offset);
-    widget->SetBounds(start_bounds);
+  ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
+
+  if (is_fullscreen_app_list_enabled_) {
+    // Set up the hide animation for the app list.
+    target_bounds.Offset(gfx::Vector2d(0, kHideAnimationOffset));
+    animation.SetTransitionDuration(
+        base::TimeDelta::FromMilliseconds(kAnimationDurationMsFullscreen));
   } else {
-    target_bounds.Offset(offset);
+    gfx::Vector2d offset = presenter_delegate_->GetVisibilityAnimationOffset(
+        widget->GetNativeView()->GetRootWindow());
+    if (is_visible_) {
+      gfx::Rect start_bounds = gfx::Rect(target_bounds);
+      start_bounds.Offset(offset);
+      widget->SetBounds(start_bounds);
+    } else {
+      target_bounds.Offset(offset);
+    }
+    animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
+        is_visible_ ? 0 : kAnimationDurationMs));
   }
 
-  ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
-  animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
-      is_visible_ ? 0 : kAnimationDurationMs));
   animation.AddObserver(this);
-
   layer->SetOpacity(is_visible_ ? 1.0 : 0.0);
   widget->SetBounds(target_bounds);
 }
diff --git a/ui/app_list/search_result.h b/ui/app_list/search_result.h
index 092945f..cd167806 100644
--- a/ui/app_list/search_result.h
+++ b/ui/app_list/search_result.h
@@ -64,10 +64,10 @@
     // Similar to ACMatchClassification::Style, the style values are not
     // mutually exclusive.
     enum Style {
-      NONE  = 0,
-      URL   = 1 << 0,
+      NONE = 0,
+      URL = 1 << 0,
       MATCH = 1 << 1,
-      DIM   = 1 << 2,
+      DIM = 1 << 2,
     };
 
     Tag(int styles, size_t start, size_t end)
@@ -154,9 +154,7 @@
     distance_from_origin_ = distance;
   }
 
-  const Actions& actions() const {
-    return actions_;
-  }
+  const Actions& actions() const { return actions_; }
   void SetActions(const Actions& sets);
 
   // Whether the result can be automatically selected by a voice query.
@@ -170,6 +168,9 @@
   int percent_downloaded() const { return percent_downloaded_; }
   void SetPercentDownloaded(int percent_downloaded);
 
+  bool is_url() const { return is_url_; }
+  void set_is_url(bool is_url) { is_url_ = is_url; }
+
   // Returns the dimension at which this result's icon should be displayed.
   int GetPreferredIconDimension() const;
 
@@ -255,6 +256,10 @@
   bool is_installing_ = false;
   int percent_downloaded_ = 0;
 
+  // Indicates whether result is an omnibox url result. Set by OmniboxResult
+  // subclass.
+  bool is_url_ = false;
+
   base::ObserverList<SearchResultObserver> observers_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchResult);
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index d0dbc50..51d2b1c 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -426,11 +426,14 @@
   const display::Display display_nearest_view = GetDisplayNearestView();
   const gfx::Rect display_work_area_bounds = display_nearest_view.work_area();
   const int bottom_of_screen = display_nearest_view.size().height();
-
+  // todo(crbug.com/750664): Modify animations and bounds of the launcher
+  // in side shelf mode.
   gfx::Rect app_list_overlay_view_bounds(
       display_work_area_bounds.x(),
-      bottom_of_screen,  // Set the widget at the bottom of the screen so it can
-                         // animate up when shown.
+      bottom_of_screen -
+          kShelfSize,  // Set the widget height to the shelf height to replace
+                       // the shelf background on show animation with no
+                       // flicker.
       display_work_area_bounds.width(),
       display_work_area_bounds.height() + kShelfSize);
 
@@ -848,17 +851,16 @@
     }
   }
 
+  StartAnimationForState(new_state_override);
   switch (new_state_override) {
     case PEEKING: {
       switch (app_list_state_) {
         case HALF:
         case FULLSCREEN_ALL_APPS:
-          StartAnimationForState(new_state_override);
           app_list_main_view_->contents_view()->SetActiveState(
               AppListModel::STATE_START);
           break;
         case PEEKING: {
-          StartAnimationForState(new_state_override);
           app_list_main_view_->contents_view()->SetActiveState(
               AppListModel::STATE_START);
           break;
@@ -871,21 +873,8 @@
       break;
     }
     case HALF:
-      switch (app_list_state_) {
-        case PEEKING:
-        case HALF: {
-          StartAnimationForState(new_state_override);
-          break;
-        }
-        case FULLSCREEN_SEARCH:
-        case FULLSCREEN_ALL_APPS:
-        case CLOSED:
-          NOTREACHED();
-          break;
-      }
       break;
     case FULLSCREEN_ALL_APPS: {
-      StartAnimationForState(new_state_override);
       AppsContainerView* apps_container_view =
           app_list_main_view_->contents_view()->apps_container_view();
 
@@ -897,7 +886,6 @@
       break;
     }
     case FULLSCREEN_SEARCH:
-      StartAnimationForState(new_state_override);
       break;
     case CLOSED:
       app_list_main_view_->Close();
@@ -918,6 +906,8 @@
     case HALF:
       target_state_y = display_height - kHalfAppListHeight;
       break;
+    case CLOSED:
+      return;
     default:
       break;
   }
@@ -925,17 +915,19 @@
   gfx::Rect target_bounds = fullscreen_widget_->GetWindowBoundsInScreen();
   target_bounds.set_y(target_state_y);
 
-  std::unique_ptr<ui::LayerAnimationElement> animation_element =
+  std::unique_ptr<ui::LayerAnimationElement> bounds_animation_element =
       ui::LayerAnimationElement::CreateBoundsElement(
           target_bounds,
           base::TimeDelta::FromMilliseconds(kAppListAnimationDurationMs));
-  animation_element->set_tween_type(gfx::Tween::EASE_OUT);
+
+  bounds_animation_element->set_tween_type(gfx::Tween::EASE_OUT);
 
   ui::LayerAnimator* animator = fullscreen_widget_->GetLayer()->GetAnimator();
   animator->set_preemption_strategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+  animator->StopAnimating();
   animator->ScheduleAnimation(
-      new ui::LayerAnimationSequence(std::move(animation_element)));
+      new ui::LayerAnimationSequence(std::move(bounds_animation_element)));
 }
 
 void AppListView::SetStateFromSearchBoxView(bool search_box_is_empty) {
diff --git a/ui/app_list/views/page_switcher_vertical.cc b/ui/app_list/views/page_switcher_vertical.cc
index 518898f..6282e5f 100644
--- a/ui/app_list/views/page_switcher_vertical.cc
+++ b/ui/app_list/views/page_switcher_vertical.cc
@@ -72,11 +72,6 @@
   }
 
  protected:
-  bool IsTriggerableEvent(const ui::Event& event) override {
-    return event.IsMouseEvent() &&
-           (triggerable_event_flags() & event.flags()) != 0;
-  }
-
   std::unique_ptr<views::InkDrop> CreateInkDrop() override {
     std::unique_ptr<views::InkDropImpl> ink_drop =
         CustomButton::CreateDefaultInkDropImpl();
diff --git a/ui/app_list/views/search_result_answer_card_view.cc b/ui/app_list/views/search_result_answer_card_view.cc
index b75b6e8..078ad75 100644
--- a/ui/app_list/views/search_result_answer_card_view.cc
+++ b/ui/app_list/views/search_result_answer_card_view.cc
@@ -79,6 +79,15 @@
 
   void StateChanged(ButtonState old_state) override { UpdateBackgroundColor(); }
 
+  bool OnKeyPressed(const ui::KeyEvent& event) override {
+    if (event.key_code() == ui::VKEY_SPACE) {
+      // Shouldn't eat Space; we want Space to go to the search box.
+      return false;
+    }
+
+    return CustomButton::OnKeyPressed(event);
+  }
+
   // views::ButtonListener overrides:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override {
     DCHECK(sender == this);
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc
index 1d1210f..2f3c99c 100644
--- a/ui/app_list/views/search_result_page_view.cc
+++ b/ui/app_list/views/search_result_page_view.cc
@@ -58,6 +58,9 @@
           GetShadowForZHeight(kSearchResultZHeight)));
       content_view->SetBackground(
           views::CreateSolidBackground(kCardBackgroundColor));
+    } else {
+      content_view->SetBackground(
+          views::CreateSolidBackground(kCardBackgroundColorFullscreen));
     }
     SetLayoutManager(new views::FillLayout());
     AddChildView(content_view);
@@ -95,6 +98,8 @@
     flags.setColor(color_);
     canvas->DrawRoundRect(bounds, corner_radius_, flags);
 
+    if (bounds.height() <= kSearchBoxHeight)
+      return;
     // Draw a separator between SearchBoxView and SearchResultPageView.
     bounds.set_y(kSearchBoxHeight);
     bounds.set_height(kSeparatorThickness);
@@ -182,8 +187,7 @@
   SetLayoutManager(new views::FillLayout);
 }
 
-SearchResultPageView::~SearchResultPageView() {
-}
+SearchResultPageView::~SearchResultPageView() = default;
 
 void SearchResultPageView::SetSelection(bool select) {
   if (select)
diff --git a/ui/app_list/views/search_result_tile_item_list_view.cc b/ui/app_list/views/search_result_tile_item_list_view.cc
index 35dd2a1..ae8d31b 100644
--- a/ui/app_list/views/search_result_tile_item_list_view.cc
+++ b/ui/app_list/views/search_result_tile_item_list_view.cc
@@ -46,7 +46,8 @@
     AppListViewDelegate* view_delegate)
     : search_box_(search_box),
       is_play_store_app_search_enabled_(
-          features::IsPlayStoreAppSearchEnabled()) {
+          features::IsPlayStoreAppSearchEnabled()),
+      is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
   if (is_play_store_app_search_enabled_) {
     SetLayoutManager(new views::BoxLayout(
         views::BoxLayout::kHorizontal,
@@ -65,7 +66,9 @@
 
       SearchResultTileItemView* tile_item =
           new SearchResultTileItemView(this, view_delegate);
-      tile_item->SetParentBackgroundColor(kCardBackgroundColor);
+      tile_item->SetParentBackgroundColor(is_fullscreen_app_list_enabled_
+                                              ? kCardBackgroundColorFullscreen
+                                              : kCardBackgroundColor);
       tile_views_.push_back(tile_item);
       AddChildView(tile_item);
     }
@@ -76,7 +79,9 @@
     for (size_t i = 0; i < kNumSearchResultTiles; ++i) {
       SearchResultTileItemView* tile_item =
           new SearchResultTileItemView(this, view_delegate);
-      tile_item->SetParentBackgroundColor(kCardBackgroundColor);
+      tile_item->SetParentBackgroundColor(is_fullscreen_app_list_enabled_
+                                              ? kCardBackgroundColorFullscreen
+                                              : kCardBackgroundColor);
       tile_item->SetBorder(
           views::CreateEmptyBorder(kTopBottomPadding, 0, kTopBottomPadding, 0));
       tile_views_.push_back(tile_item);
@@ -85,8 +90,7 @@
   }
 }
 
-SearchResultTileItemListView::~SearchResultTileItemListView() {
-}
+SearchResultTileItemListView::~SearchResultTileItemListView() = default;
 
 void SearchResultTileItemListView::OnContainerSelected(
     bool from_bottom,
diff --git a/ui/app_list/views/search_result_tile_item_list_view.h b/ui/app_list/views/search_result_tile_item_list_view.h
index 4ad4c601..7055d57 100644
--- a/ui/app_list/views/search_result_tile_item_list_view.h
+++ b/ui/app_list/views/search_result_tile_item_list_view.h
@@ -48,9 +48,10 @@
 
   views::Textfield* search_box_;  // Owned by the views hierarchy.
 
-  // Whether the Play Store app search feature is enabled.
   const bool is_play_store_app_search_enabled_;
 
+  const bool is_fullscreen_app_list_enabled_;
+
   DISALLOW_COPY_AND_ASSIGN(SearchResultTileItemListView);
 };
 
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc
index 68f30fb..aa742b2 100644
--- a/ui/app_list/views/search_result_view.cc
+++ b/ui/app_list/views/search_result_view.cc
@@ -36,11 +36,19 @@
 constexpr int kTextTrailPadding = 16;
 constexpr int kSeparatorPadding = 62;
 constexpr int kBorderSize = 1;
-constexpr SkColor kSeparatorColor = SkColorSetARGBMacro(0xFF, 0xE1, 0xE1, 0xE1);
-
 // Extra margin at the right of the rightmost action icon.
 constexpr int kActionButtonRightMargin = 8;
 
+constexpr SkColor kSeparatorColor = SkColorSetARGBMacro(0xFF, 0xE1, 0xE1, 0xE1);
+// Matched text color, #000 87%.
+constexpr SkColor kMatchedTextColor =
+    SkColorSetARGBMacro(0xDE, 0x00, 0x00, 0x00);
+// Default text color, #000 54%.
+constexpr SkColor kDefaultTextColor =
+    SkColorSetARGBMacro(0x8A, 0x00, 0x00, 0x00);
+// URL color.
+constexpr SkColor kUrlColor = SkColorSetARGBMacro(0xFF, 0x33, 0x67, 0xD6);
+
 int GetIconViewWidth() {
   if (!features::IsFullscreenAppListEnabled())
     return kListIconSize + kIconLeftPadding + kIconRightPadding;
@@ -48,7 +56,7 @@
 }
 
 // Creates a RenderText of given |text| and |styles|. Caller takes ownership
-// of returned RenderText.
+// of returned RenderText. Used for bubble launcher.
 gfx::RenderText* CreateRenderText(const base::string16& text,
                                   const SearchResult::Tags& tags) {
   gfx::RenderText* render_text = gfx::RenderText::CreateInstance();
@@ -79,8 +87,6 @@
 
 SearchResultView::SearchResultView(SearchResultListView* list_view)
     : views::CustomButton(this),
-      result_(NULL),
-      is_last_result_(false),
       list_view_(list_view),
       icon_(new views::ImageView),
       badge_icon_(new views::ImageView),
@@ -132,8 +138,12 @@
   if (!result_ || result_->title().empty()) {
     title_text_.reset();
   } else {
-    title_text_.reset(
-        CreateRenderText(result_->title(), result_->title_tags()));
+    if (!is_fullscreen_app_list_enabled_) {
+      title_text_.reset(
+          CreateRenderText(result_->title(), result_->title_tags()));
+    } else {
+      CreateTitleRenderText();
+    }
   }
 
   UpdateAccessibleName();
@@ -143,8 +153,12 @@
   if (!result_ || result_->details().empty()) {
     details_text_.reset();
   } else {
-    details_text_.reset(
-        CreateRenderText(result_->details(), result_->details_tags()));
+    if (!is_fullscreen_app_list_enabled_) {
+      details_text_.reset(
+          CreateRenderText(result_->details(), result_->details_tags()));
+    } else {
+      CreateDetailsRenderText();
+    }
   }
 
   UpdateAccessibleName();
@@ -166,6 +180,45 @@
   SetAccessibleName(ComputeAccessibleName());
 }
 
+void SearchResultView::CreateTitleRenderText() {
+  DCHECK(is_fullscreen_app_list_enabled_);
+  std::unique_ptr<gfx::RenderText> render_text(
+      gfx::RenderText::CreateInstance());
+  // When result title is url, set title text using details.
+  render_text->SetText(result_->is_url() ? result_->details()
+                                         : result_->title());
+  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+  render_text->SetFontList(
+      rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(2));
+  // Empty details indicate omnibox non-url search type. When true, the matched
+  // tag indicates proposed query. When false, the matched tag indicates typed
+  // search query.
+  const bool is_omnibox_search = result_->details().empty();
+  render_text->SetColor(is_omnibox_search ? kDefaultTextColor
+                                          : kMatchedTextColor);
+  const SearchResult::Tags& tags =
+      result_->is_url() ? result_->details_tags() : result_->title_tags();
+  for (const auto& tag : tags) {
+    if (tag.styles & SearchResult::Tag::MATCH)
+      render_text->ApplyColor(
+          is_omnibox_search ? kMatchedTextColor : kDefaultTextColor, tag.range);
+  }
+  title_text_ = std::move(render_text);
+}
+
+void SearchResultView::CreateDetailsRenderText() {
+  DCHECK(is_fullscreen_app_list_enabled_);
+  std::unique_ptr<gfx::RenderText> render_text(
+      gfx::RenderText::CreateInstance());
+  // When result title is url, set it to details text.
+  render_text->SetText(result_->is_url() ? result_->title()
+                                         : result_->details());
+  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+  render_text->SetFontList(rb.GetFontList(ui::ResourceBundle::BaseFont));
+  render_text->SetColor(result_->is_url() ? kUrlColor : kDefaultTextColor);
+  details_text_ = std::move(render_text);
+}
+
 const char* SearchResultView::GetClassName() const {
   return kViewClassName;
 }
@@ -272,7 +325,9 @@
   const bool selected = list_view_->IsResultViewSelected(this);
   const bool hover = state() == STATE_HOVERED || state() == STATE_PRESSED;
 
-  canvas->FillRect(content_rect, kCardBackgroundColor);
+  canvas->FillRect(content_rect, is_fullscreen_app_list_enabled_
+                                     ? kCardBackgroundColorFullscreen
+                                     : kCardBackgroundColor);
 
   // Possibly call FillRect a second time (these colours are partially
   // transparent, so the previous FillRect is not redundant).
@@ -312,7 +367,7 @@
                          title_text_->GetStringSize().height());
     gfx::Size details_size(text_bounds.width(),
                            details_text_->GetStringSize().height());
-    int total_height = title_size.height() + +details_size.height();
+    int total_height = title_size.height() + details_size.height();
     int y = text_bounds.y() + (text_bounds.height() - total_height) / 2;
 
     title_text_->SetDisplayRect(
diff --git a/ui/app_list/views/search_result_view.h b/ui/app_list/views/search_result_view.h
index f09cc30a..c1b5358c 100644
--- a/ui/app_list/views/search_result_view.h
+++ b/ui/app_list/views/search_result_view.h
@@ -74,6 +74,10 @@
   void UpdateDetailsText();
   void UpdateAccessibleName();
 
+  // Creates title/details render text.
+  void CreateTitleRenderText();
+  void CreateDetailsRenderText();
+
   // views::View overrides:
   const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
@@ -105,9 +109,9 @@
   // SearchResultActionsViewDelegate overrides:
   void OnSearchResultActionActivated(size_t index, int event_flags) override;
 
-  SearchResult* result_;  // Owned by AppListModel::SearchResults.
+  SearchResult* result_ = nullptr;  // Owned by AppListModel::SearchResults.
 
-  bool is_last_result_;
+  bool is_last_result_ = false;
 
   // Parent list view. Owned by views hierarchy.
   SearchResultListView* list_view_;
diff --git a/ui/arc/notification/arc_notification_content_view.cc b/ui/arc/notification/arc_notification_content_view.cc
index cde53d5..6b0c5d1 100644
--- a/ui/arc/notification/arc_notification_content_view.cc
+++ b/ui/arc/notification/arc_notification_content_view.cc
@@ -324,7 +324,7 @@
     surface_->GetContentWindow()->RemoveObserver(this);
     surface_->GetWindow()->RemovePreTargetHandler(event_forwarder_.get());
 
-    if (surface_->IsAttached()) {
+    if (surface_->GetAttachedHost() == this) {
       DCHECK_EQ(this, surface_->GetAttachedHost());
       surface_->Detach();
     }
@@ -338,8 +338,16 @@
     surface_->GetContentWindow()->AddObserver(this);
     surface_->GetWindow()->AddPreTargetHandler(event_forwarder_.get());
 
-    if (GetWidget())
+    if (GetWidget()) {
+      // Force to detach the surface.
+      if (surface_->IsAttached()) {
+        // The attached host must not be this. Since if it is, this should
+        // already be detached above.
+        DCHECK_NE(this, surface_->GetAttachedHost());
+        surface_->Detach();
+      }
       AttachSurface();
+    }
   }
 }
 
diff --git a/ui/arc/notification/arc_notification_content_view_unittest.cc b/ui/arc/notification/arc_notification_content_view_unittest.cc
index 8b62bf0..3394b01 100644
--- a/ui/arc/notification/arc_notification_content_view_unittest.cc
+++ b/ui/arc/notification/arc_notification_content_view_unittest.cc
@@ -247,6 +247,7 @@
     DummyEvent dummy_event;
     auto* control_buttons_view =
         GetArcNotificationContentView()->control_buttons_view_;
+    ASSERT_TRUE(control_buttons_view);
     message_center::PaddedButton* close_button =
         control_buttons_view->close_button();
     ASSERT_NE(nullptr, close_button);
@@ -257,18 +258,31 @@
       const message_center::Notification& notification) {
     DCHECK(!notification_view_);
 
-    notification_view_.reset(static_cast<ArcNotificationView*>(
-        message_center::MessageViewFactory::Create(controller(), notification,
-                                                   true)));
-    notification_view_->set_owned_by_client();
+    auto result = CreateNotificationView(notification);
+    notification_view_ = std::move(result.first);
+    wrapper_widget_ = std::move(result.second);
+    wrapper_widget_->Show();
+  }
+
+  std::pair<std::unique_ptr<ArcNotificationView>,
+            std::unique_ptr<views::Widget>>
+  CreateNotificationView(const message_center::Notification& notification) {
+    std::unique_ptr<ArcNotificationView> notification_view(
+        static_cast<ArcNotificationView*>(
+            message_center::MessageViewFactory::Create(controller(),
+                                                       notification, true)));
+    notification_view->set_owned_by_client();
     views::Widget::InitParams params(
         CreateParams(views::Widget::InitParams::TYPE_POPUP));
 
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-    wrapper_widget_ = base::MakeUnique<views::Widget>();
-    wrapper_widget_->Init(params);
-    wrapper_widget_->SetContentsView(notification_view_.get());
-    wrapper_widget_->SetSize(notification_view_->GetPreferredSize());
+    auto wrapper_widget = base::MakeUnique<views::Widget>();
+    wrapper_widget->Init(params);
+    wrapper_widget->SetContentsView(notification_view.get());
+    wrapper_widget->SetSize(notification_view->GetPreferredSize());
+
+    return std::make_pair(std::move(notification_view),
+                          std::move(wrapper_widget));
   }
 
   void CloseNotificationView() {
@@ -397,4 +411,59 @@
   CloseNotificationView();
 }
 
+TEST_F(ArcNotificationContentViewTest, ReuseAndCloseSurfaceBeforeClosing) {
+  std::string notification_key("notification id");
+
+  auto notification_item =
+      base::MakeUnique<MockArcNotificationItem>(notification_key);
+  message_center::Notification notification =
+      CreateNotification(notification_item.get());
+
+  surface_manager()->PrepareSurface(notification_key);
+
+  // Create the first view.
+  auto result = CreateNotificationView(notification);
+  auto notification_view = std::move(result.first);
+  auto wrapper_widget = std::move(result.second);
+  wrapper_widget->Show();
+
+  // Create the second view.
+  CreateAndShowNotificationView(notification);
+  // Close second view.
+  CloseNotificationView();
+
+  // Close the first view.
+  wrapper_widget->Close();
+  wrapper_widget.reset();
+  notification_view.reset();
+}
+
+TEST_F(ArcNotificationContentViewTest, ReuseSurfaceBeforeClosing) {
+  std::string notification_key("notification id");
+
+  auto notification_item =
+      base::MakeUnique<MockArcNotificationItem>(notification_key);
+  message_center::Notification notification =
+      CreateNotification(notification_item.get());
+
+  surface_manager()->PrepareSurface(notification_key);
+
+  // Create the first view.
+  auto result = CreateNotificationView(notification);
+  auto notification_view = std::move(result.first);
+  auto wrapper_widget = std::move(result.second);
+  wrapper_widget->Show();
+
+  // Create the second view.
+  CreateAndShowNotificationView(notification);
+
+  // Close the first view.
+  wrapper_widget->Close();
+  wrapper_widget.reset();
+  notification_view.reset();
+
+  // Close second view.
+  CloseNotificationView();
+}
+
 }  // namespace arc
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index d9ecc09..a1f8630 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -20,6 +20,7 @@
 #include "ui/base/ime/input_method_factory.h"
 #include "ui/base/layout.h"
 #include "ui/base/view_prop.h"
+#include "ui/compositor/compositor_switches.h"
 #include "ui/compositor/dip_util.h"
 #include "ui/compositor/layer.h"
 #include "ui/display/display.h"
@@ -270,7 +271,8 @@
           ? frame_sink_id
           : context_factory_private->AllocateFrameSinkId(),
       context_factory, context_factory_private,
-      base::ThreadTaskRunnerHandle::Get(), enable_surface_synchronization));
+      base::ThreadTaskRunnerHandle::Get(), enable_surface_synchronization,
+      ui::IsPixelCanvasRecordingEnabled()));
   if (!dispatcher()) {
     window()->Init(ui::LAYER_NOT_DRAWN);
     window()->set_host(this);
diff --git a/ui/compositor/canvas_painter.cc b/ui/compositor/canvas_painter.cc
index a12e85a..864d8b03 100644
--- a/ui/compositor/canvas_painter.cc
+++ b/ui/compositor/canvas_painter.cc
@@ -11,13 +11,17 @@
 CanvasPainter::CanvasPainter(SkBitmap* output,
                              const gfx::Size& paint_size,
                              float raster_scale,
-                             SkColor clear_color)
+                             SkColor clear_color,
+                             bool is_pixel_canvas)
     : output_(output),
       paint_size_(paint_size),
       raster_scale_(raster_scale),
       clear_color_(clear_color),
       list_(new cc::DisplayItemList),
-      context_(list_.get(), raster_scale, gfx::Rect(paint_size_)) {}
+      context_(list_.get(),
+               raster_scale,
+               gfx::Rect(paint_size_),
+               is_pixel_canvas) {}
 
 CanvasPainter::~CanvasPainter() {
   gfx::Size pixel_size = gfx::ScaleToCeiledSize(paint_size_, raster_scale_);
diff --git a/ui/compositor/canvas_painter.h b/ui/compositor/canvas_painter.h
index 1db206f..da44d7bb 100644
--- a/ui/compositor/canvas_painter.h
+++ b/ui/compositor/canvas_painter.h
@@ -29,7 +29,8 @@
   CanvasPainter(SkBitmap* output,
                 const gfx::Size& paint_size,
                 float raster_scale,
-                SkColor clear_color);
+                SkColor clear_color,
+                bool is_pixel_canvas);
   ~CanvasPainter();
 
   const PaintContext& context() const { return context_; }
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index f0c8888..bc61e1d6 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -60,6 +60,7 @@
                        ui::ContextFactoryPrivate* context_factory_private,
                        scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                        bool enable_surface_synchronization,
+                       bool enable_pixel_canvas,
                        bool external_begin_frames_enabled)
     : context_factory_(context_factory),
       context_factory_private_(context_factory_private),
@@ -70,6 +71,7 @@
       layer_animator_collection_(this),
       scheduled_timeout_(base::TimeTicks()),
       allow_locks_to_extend_timeout_(false),
+      is_pixel_canvas_(enable_pixel_canvas),
       weak_ptr_factory_(this),
       lock_timeout_weak_ptr_factory_(this) {
   if (context_factory_private) {
@@ -334,6 +336,8 @@
   if (device_scale_factor_ != scale) {
     device_scale_factor_ = scale;
     host_->SetDeviceScaleFactor(scale);
+    if (is_pixel_canvas())
+      host_->SetRecordingScaleFactor(scale);
     if (root_layer_)
       root_layer_->OnDeviceScaleFactorChanged(scale);
   }
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 92ed6841..573e654 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -194,6 +194,7 @@
              ui::ContextFactoryPrivate* context_factory_private,
              scoped_refptr<base::SingleThreadTaskRunner> task_runner,
              bool enable_surface_synchronization,
+             bool enable_pixel_canvas,
              bool external_begin_frames_enabled = false);
   ~Compositor() override;
 
@@ -405,6 +406,9 @@
     allow_locks_to_extend_timeout_ = allowed;
   }
 
+  // If true, all paint commands are recorded at pixel size instead of DIP.
+  bool is_pixel_canvas() const { return is_pixel_canvas_; }
+
  private:
   friend class base::RefCounted<Compositor>;
 
@@ -469,6 +473,8 @@
   base::TimeTicks scheduled_timeout_;
   // If true, the |scheduled_timeout_| might be recalculated and extended.
   bool allow_locks_to_extend_timeout_;
+  // If true, all paint commands are recorded at pixel size instead of DIP.
+  const bool is_pixel_canvas_;
 
   base::WeakPtrFactory<Compositor> weak_ptr_factory_;
   base::WeakPtrFactory<Compositor> lock_timeout_weak_ptr_factory_;
diff --git a/ui/compositor/compositor_switches.cc b/ui/compositor/compositor_switches.cc
index 991aba5..4833b4f 100644
--- a/ui/compositor/compositor_switches.cc
+++ b/ui/compositor/compositor_switches.cc
@@ -32,6 +32,11 @@
 
 const char kUISlowAnimations[] = "ui-slow-animations";
 
+// If enabled, all draw commands recorded on canvas are done in pixel aligned
+// measurements. This also enables scaling of all elements in views and layers
+// to be done via corner points. See https://goo.gl/Dqig5s
+const char kEnablePixelCanvasRecording[] = "enable-pixel-canvas-recording";
+
 }  // namespace switches
 
 namespace ui {
@@ -42,4 +47,11 @@
   return command_line.HasSwitch(switches::kUIEnableZeroCopy);
 }
 
+bool IsPixelCanvasRecordingEnabled() {
+  static const bool is_pixel_canvas_recording_enabled =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnablePixelCanvasRecording);
+  return is_pixel_canvas_recording_enabled;
+}
+
 }  // namespace ui
diff --git a/ui/compositor/compositor_switches.h b/ui/compositor/compositor_switches.h
index 54fc33542..9f669a4 100644
--- a/ui/compositor/compositor_switches.h
+++ b/ui/compositor/compositor_switches.h
@@ -17,6 +17,7 @@
 COMPOSITOR_EXPORT extern const char kUIEnableZeroCopy[];
 COMPOSITOR_EXPORT extern const char kUIShowPaintRects[];
 COMPOSITOR_EXPORT extern const char kUISlowAnimations[];
+COMPOSITOR_EXPORT extern const char kEnablePixelCanvasRecording[];
 
 }  // namespace switches
 
@@ -24,6 +25,8 @@
 
 bool IsUIZeroCopyEnabled();
 
+bool COMPOSITOR_EXPORT IsPixelCanvasRecordingEnabled();
+
 }  // namespace ui
 
 #endif  // UI_COMPOSITOR_COMPOSITOR_SWITCHES_H_
diff --git a/ui/compositor/compositor_unittest.cc b/ui/compositor/compositor_unittest.cc
index 4378ec9..4284504b 100644
--- a/ui/compositor/compositor_unittest.cc
+++ b/ui/compositor/compositor_unittest.cc
@@ -40,7 +40,8 @@
     compositor_.reset(new ui::Compositor(
         context_factory_private->AllocateFrameSinkId(), context_factory,
         context_factory_private, CreateTaskRunner(),
-        false /* enable_surface_synchronization */));
+        false /* enable_surface_synchronization */,
+        false /* enable_pixel_canvas */));
     compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
   }
 
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 6f2ac6c5..d436259 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -40,6 +40,10 @@
 namespace {
 
 const ui::Layer* GetRoot(const ui::Layer* layer) {
+  // Parent walk cannot be done on a layer that is being used as a mask. Get the
+  // layer to which this layer is a mask of.
+  if (layer->layer_mask_back_link())
+    layer = layer->layer_mask_back_link();
   while (layer->parent())
     layer = layer->parent();
   return layer;
@@ -315,7 +319,7 @@
   Compositor* compositor = GetCompositor();
 
   if (animator_) {
-    if (compositor)
+    if (compositor && !layer_mask_back_link())
       animator_->DetachLayerAndTimeline(compositor);
     animator_->SetDelegate(nullptr);
   }
@@ -324,7 +328,7 @@
 
   if (animator_) {
     animator_->SetDelegate(this);
-    if (compositor)
+    if (compositor && !layer_mask_back_link())
       animator_->AttachLayerAndTimeline(compositor);
   }
 }
@@ -943,8 +947,9 @@
   paint_region_.Clear();
   auto display_list = make_scoped_refptr(new cc::DisplayItemList);
   if (delegate_) {
-    delegate_->OnPaintLayer(
-        PaintContext(display_list.get(), device_scale_factor_, invalidation));
+    delegate_->OnPaintLayer(PaintContext(display_list.get(),
+                                         device_scale_factor_, invalidation,
+                                         GetCompositor()->is_pixel_canvas()));
   }
   display_list->Finalize();
   // TODO(domlaskowski): Move mirror invalidation to Layer::SchedulePaint.
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index b84e2fc..3aa0427 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -424,6 +424,11 @@
   // surface even if layer is invisible is not a problem.
   void SetCacheRenderSurface(bool cache_render_surface);
 
+  // The back link from the mask layer to it's associated masked layer.
+  // We keep this reference for the case that if the mask layer gets deleted
+  // while attached to the main layer before the main layer is deleted.
+  const Layer* layer_mask_back_link() const { return layer_mask_back_link_; }
+
  private:
   friend class LayerOwner;
   class LayerMirror;
diff --git a/ui/compositor/layer_owner_unittest.cc b/ui/compositor/layer_owner_unittest.cc
index 94992e0..3c1a65d6 100644
--- a/ui/compositor/layer_owner_unittest.cc
+++ b/ui/compositor/layer_owner_unittest.cc
@@ -81,7 +81,8 @@
   compositor_.reset(
       new ui::Compositor(context_factory_private->AllocateFrameSinkId(),
                          context_factory, context_factory_private, task_runner,
-                         false /* enable_surface_synchronization */));
+                         false /* enable_surface_synchronization */,
+                         false /* enable_pixel_canvas */));
   compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
 }
 
diff --git a/ui/compositor/paint_context.cc b/ui/compositor/paint_context.cc
index b2b4fac5..48e2e9d 100644
--- a/ui/compositor/paint_context.cc
+++ b/ui/compositor/paint_context.cc
@@ -10,10 +10,14 @@
 
 PaintContext::PaintContext(cc::DisplayItemList* list,
                            float device_scale_factor,
-                           const gfx::Rect& invalidation)
+                           const gfx::Rect& invalidation,
+                           bool is_pixel_canvas)
     : list_(list),
       device_scale_factor_(device_scale_factor),
-      invalidation_(invalidation) {
+      invalidation_(gfx::ScaleToRoundedRect(
+          invalidation,
+          is_pixel_canvas ? device_scale_factor_ : 1.f)),
+      is_pixel_canvas_(is_pixel_canvas) {
 #if DCHECK_IS_ON()
   root_visited_ = nullptr;
   inside_paint_recorder_ = false;
@@ -25,7 +29,8 @@
     : list_(other.list_),
       device_scale_factor_(other.device_scale_factor_),
       invalidation_(other.invalidation_),
-      offset_(other.offset_ + offset) {
+      offset_(other.offset_ + offset),
+      is_pixel_canvas_(other.is_pixel_canvas_) {
 #if DCHECK_IS_ON()
   root_visited_ = other.root_visited_;
   inside_paint_recorder_ = other.inside_paint_recorder_;
@@ -37,7 +42,8 @@
     : list_(other.list_),
       device_scale_factor_(other.device_scale_factor_),
       invalidation_(),
-      offset_(other.offset_) {
+      offset_(other.offset_),
+      is_pixel_canvas_(other.is_pixel_canvas_) {
 #if DCHECK_IS_ON()
   root_visited_ = other.root_visited_;
   inside_paint_recorder_ = other.inside_paint_recorder_;
diff --git a/ui/compositor/paint_context.h b/ui/compositor/paint_context.h
index bc17c50f..96385275 100644
--- a/ui/compositor/paint_context.h
+++ b/ui/compositor/paint_context.h
@@ -29,7 +29,8 @@
   // |invalidation|.
   PaintContext(cc::DisplayItemList* list,
                float device_scale_factor,
-               const gfx::Rect& invalidation);
+               const gfx::Rect& invalidation,
+               bool is_pixel_canvas);
 
   // Clone a PaintContext with an additional |offset|.
   PaintContext(const PaintContext& other, const gfx::Vector2d& offset);
@@ -46,6 +47,13 @@
   // invalid.
   bool CanCheckInvalid() const { return !invalidation_.IsEmpty(); }
 
+  // The device scale of the frame being painted.
+  float device_scale_factor() const { return device_scale_factor_; }
+
+  // Returns true if the paint commands are recorded at pixel size instead of
+  // DIP.
+  bool is_pixel_canvas() const { return is_pixel_canvas_; }
+
   // When true, the |bounds| touches an invalidated area, so should be
   // re-painted. When false, re-painting can be skipped. Bounds should be in
   // the local space with offsets up to the painting root in the PaintContext.
@@ -94,6 +102,8 @@
   // Offset from the PaintContext to the space of the paint root and the
   // |invalidation_|.
   gfx::Vector2d offset_;
+  // If enabled, the paint commands are recorded at pixel size.
+  const bool is_pixel_canvas_;
 
 #if DCHECK_IS_ON()
   // Used to verify that the |invalidation_| is only used to compare against
diff --git a/ui/compositor/paint_recorder.cc b/ui/compositor/paint_recorder.cc
index ddf9f1b..f85d3cb 100644
--- a/ui/compositor/paint_recorder.cc
+++ b/ui/compositor/paint_recorder.cc
@@ -21,6 +21,8 @@
 // to the |context|'s PaintOpBuffer.
 PaintRecorder::PaintRecorder(const PaintContext& context,
                              const gfx::Size& recording_size,
+                             float recording_scale_x,
+                             float recording_scale_y,
                              PaintCache* cache)
     : context_(context),
       local_list_(cache ? base::MakeRefCounted<cc::DisplayItemList>(
@@ -38,19 +40,34 @@
   }
 
 #if DCHECK_IS_ON()
-  DCHECK(!context.inside_paint_recorder_);
-  context.inside_paint_recorder_ = true;
+  DCHECK(!context_.inside_paint_recorder_);
+  context_.inside_paint_recorder_ = true;
 #endif
+  if (context_.is_pixel_canvas()) {
+    canvas()->Save();
+    canvas()->Scale(recording_scale_x, recording_scale_y);
+  }
 }
 
+// TODO(malaykeshav): The scaling of recording size needs to be handled case
+// by case and the decision to perform the scale should be moved to the caller.
 PaintRecorder::PaintRecorder(const PaintContext& context,
                              const gfx::Size& recording_size)
-    : PaintRecorder(context, recording_size, nullptr) {}
+    : PaintRecorder(
+          context,
+          gfx::ScaleToRoundedSize(
+              recording_size,
+              context.is_pixel_canvas() ? context.device_scale_factor_ : 1.f),
+          context.device_scale_factor_,
+          context.device_scale_factor_,
+          nullptr) {}
 
 PaintRecorder::~PaintRecorder() {
 #if DCHECK_IS_ON()
   context_.inside_paint_recorder_ = false;
 #endif
+  if (context_.is_pixel_canvas())
+    canvas()->Restore();
   // If using cache, append what we've saved there to the PaintContext.
   // Otherwise, the content is already stored in the PaintContext, and we can
   // just close it.
diff --git a/ui/compositor/paint_recorder.h b/ui/compositor/paint_recorder.h
index ffe090a..609d6f0 100644
--- a/ui/compositor/paint_recorder.h
+++ b/ui/compositor/paint_recorder.h
@@ -32,6 +32,8 @@
   // PaintRecorder is in use. Canvas is bounded by |recording_size|.
   PaintRecorder(const PaintContext& context,
                 const gfx::Size& recording_size,
+                float recording_scale_x,
+                float recording_scale_y,
                 PaintCache* cache);
   PaintRecorder(const PaintContext& context, const gfx::Size& recording_size);
   ~PaintRecorder();
diff --git a/ui/compositor/test/test_compositor_host_android.cc b/ui/compositor/test/test_compositor_host_android.cc
index 3fd1bffe..1670706 100644
--- a/ui/compositor/test/test_compositor_host_android.cc
+++ b/ui/compositor/test/test_compositor_host_android.cc
@@ -23,7 +23,8 @@
     compositor_.reset(new ui::Compositor(
         context_factory_private->AllocateFrameSinkId(), context_factory,
         context_factory_private, base::ThreadTaskRunnerHandle::Get(),
-        false /* enable_surface_synchronization */));
+        false /* enable_surface_synchronization */,
+        false /* enable_pixel_canvas */));
     // TODO(sievers): Support onscreen here.
     compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
     compositor_->SetScaleAndSize(1.0f,
diff --git a/ui/compositor/test/test_compositor_host_mac.mm b/ui/compositor/test/test_compositor_host_mac.mm
index ee4f6c6..722edc6 100644
--- a/ui/compositor/test/test_compositor_host_mac.mm
+++ b/ui/compositor/test/test_compositor_host_mac.mm
@@ -112,7 +112,8 @@
                   context_factory,
                   context_factory_private,
                   base::ThreadTaskRunnerHandle::Get(),
-                  false /* enable_surface_synchronization */),
+                  false /* enable_surface_synchronization */,
+                  false /* enable_pixel_canvas */),
       window_(nil) {}
 
 TestCompositorHostMac::~TestCompositorHostMac() {
diff --git a/ui/compositor/test/test_compositor_host_ozone.cc b/ui/compositor/test/test_compositor_host_ozone.cc
index 97d33af..1659d933 100644
--- a/ui/compositor/test/test_compositor_host_ozone.cc
+++ b/ui/compositor/test/test_compositor_host_ozone.cc
@@ -84,7 +84,8 @@
                   context_factory,
                   context_factory_private,
                   base::ThreadTaskRunnerHandle::Get(),
-                  false /* enable_surface_synchronization */) {}
+                  false /* enable_surface_synchronization */,
+                  false /* enable_pixel_canvas */) {}
 
 TestCompositorHostOzone::~TestCompositorHostOzone() {}
 
diff --git a/ui/compositor/test/test_compositor_host_win.cc b/ui/compositor/test/test_compositor_host_win.cc
index cbf1d4830..c2e90b0 100644
--- a/ui/compositor/test/test_compositor_host_win.cc
+++ b/ui/compositor/test/test_compositor_host_win.cc
@@ -24,7 +24,8 @@
     compositor_.reset(new ui::Compositor(
         context_factory_private->AllocateFrameSinkId(), context_factory,
         context_factory_private, base::ThreadTaskRunnerHandle::Get(),
-        false /* enable_surface_synchronization */));
+        false /* enable_surface_synchronization */,
+        false /* enable_pixel_canvas */));
     compositor_->SetAcceleratedWidget(hwnd());
     compositor_->SetScaleAndSize(1.0f, GetSize());
   }
diff --git a/ui/compositor/test/test_compositor_host_x11.cc b/ui/compositor/test/test_compositor_host_x11.cc
index d8a6e907..87cce6c 100644
--- a/ui/compositor/test/test_compositor_host_x11.cc
+++ b/ui/compositor/test/test_compositor_host_x11.cc
@@ -58,7 +58,8 @@
                   context_factory_,
                   context_factory_private_,
                   base::ThreadTaskRunnerHandle::Get(),
-                  false /* enable_surface_synchronization */) {}
+                  false /* enable_surface_synchronization */,
+                  false /* enable_pixel_canvas */) {}
 
 TestCompositorHostX11::~TestCompositorHostX11() {}
 
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 91bf6ca2..877a2ba 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -92,6 +92,7 @@
     "image/image_family.h",
     "image/image_ios.mm",
     "image/image_mac.mm",
+    "image/image_platform.h",
     "image/image_png_rep.cc",
     "image/image_png_rep.h",
     "image/image_skia.cc",
@@ -204,6 +205,7 @@
       "canvas_skia_paint.h",
       "image/canvas_image_source.cc",
       "image/canvas_image_source.h",
+      "image/image_generic.cc",
       "image/image_skia_operations.cc",
       "image/image_skia_operations.h",
       "paint_throbber.cc",
diff --git a/ui/gfx/geometry/rect.h b/ui/gfx/geometry/rect.h
index 4e914b8..c33d4a7 100644
--- a/ui/gfx/geometry/rect.h
+++ b/ui/gfx/geometry/rect.h
@@ -340,6 +340,41 @@
   return ScaleToEnclosedRect(rect, scale, scale);
 }
 
+// Scales |rect| by scaling its four corner points. If the corner points lie on
+// non-integral coordinate after scaling, their values are rounded to the
+// nearest integer.
+// This is helpful during layout when relative positions of multiple gfx::Rect
+// in a given coordinate space needs to be same after scaling as it was before
+// scaling. ie. this gives a lossless relative positioning of rects.
+inline Rect ScaleToRoundedRect(const Rect& rect, float x_scale, float y_scale) {
+  if (x_scale == 1.f && y_scale == 1.f)
+    return rect;
+
+  DCHECK(
+      base::IsValueInRangeForNumericType<int>(std::round(rect.x() * x_scale)));
+  DCHECK(
+      base::IsValueInRangeForNumericType<int>(std::round(rect.y() * y_scale)));
+  DCHECK(base::IsValueInRangeForNumericType<int>(
+      std::round(rect.right() * x_scale)));
+  DCHECK(base::IsValueInRangeForNumericType<int>(
+      std::round(rect.bottom() * y_scale)));
+
+  int x = static_cast<int>(std::round(rect.x() * x_scale));
+  int y = static_cast<int>(std::round(rect.y() * y_scale));
+  int r = rect.width() == 0
+              ? x
+              : static_cast<int>(std::round(rect.right() * x_scale));
+  int b = rect.height() == 0
+              ? y
+              : static_cast<int>(std::round(rect.bottom() * y_scale));
+
+  return Rect(x, y, r - x, b - y);
+}
+
+inline Rect ScaleToRoundedRect(const Rect& rect, float scale) {
+  return ScaleToRoundedRect(rect, scale, scale);
+}
+
 // This is declared here for use in gtest-based unit tests but is defined in
 // the //ui/gfx:test_support target. Depend on that to use this in your unit
 // test. This should not be used in production code - call ToString() instead.
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index 567bdd2..7b4d93cf 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -5,8 +5,8 @@
 #include "ui/gfx/image/image.h"
 
 #include <algorithm>
-#include <set>
 #include <utility>
+#include <vector>
 
 #include "base/logging.h"
 #include "base/macros.h"
@@ -14,13 +14,9 @@
 #include "build/build_config.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_platform.h"
 #include "ui/gfx/image/image_png_rep.h"
 #include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_source.h"
-
-#if !defined(OS_IOS)
-#include "ui/gfx/codec/png_codec.h"
-#endif
 
 #if defined(OS_IOS)
 #include "base/mac/foundation_util.h"
@@ -42,135 +38,6 @@
 
 namespace internal {
 
-#if defined(OS_IOS)
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
-    UIImage* uiimage);
-// Caller takes ownership of the returned UIImage.
-UIImage* CreateUIImageFromPNG(
-    const std::vector<ImagePNGRep>& image_png_reps);
-gfx::Size UIImageSize(UIImage* image);
-#elif defined(OS_MACOSX)
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
-    NSImage* nsimage);
-// Caller takes ownership of the returned NSImage.
-NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
-                        CGColorSpaceRef color_space);
-gfx::Size NSImageSize(NSImage* image);
-#endif // defined(OS_MACOSX)
-
-#if defined(OS_IOS)
-ImageSkia* ImageSkiaFromPNG(
-    const std::vector<ImagePNGRep>& image_png_reps);
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
-    const ImageSkia* skia);
-#else
-// Returns a 16x16 red image to visually show error in decoding PNG.
-// Caller takes ownership of returned ImageSkia.
-ImageSkia* GetErrorImageSkia() {
-  SkBitmap bitmap;
-  bitmap.allocN32Pixels(16, 16);
-  bitmap.eraseARGB(0xff, 0xff, 0, 0);
-  return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
-}
-
-class PNGImageSource : public ImageSkiaSource {
- public:
-  PNGImageSource() {}
-  ~PNGImageSource() override {}
-
-  ImageSkiaRep GetImageForScale(float scale) override {
-    if (image_skia_reps_.empty())
-      return ImageSkiaRep();
-
-    const ImageSkiaRep* rep = NULL;
-    // gfx::ImageSkia passes one of the resource scale factors. The source
-    // should return:
-    // 1) The ImageSkiaRep with the highest scale if all available
-    // scales are smaller than |scale|.
-    // 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
-    for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
-         iter != image_skia_reps_.end(); ++iter) {
-      if ((*iter).scale() == scale)
-        return (*iter);
-      if (!rep || rep->scale() < (*iter).scale())
-        rep = &(*iter);
-      if (rep->scale() >= scale)
-        break;
-    }
-    return rep ? *rep : ImageSkiaRep();
-  }
-
-  const gfx::Size size() const {
-    return size_;
-  }
-
-  bool AddPNGData(const ImagePNGRep& png_rep) {
-    const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
-    if (rep.is_null())
-      return false;
-    if (size_.IsEmpty())
-      size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
-    image_skia_reps_.insert(rep);
-    return true;
-  }
-
-  static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
-    scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
-    CHECK(raw_data.get());
-    SkBitmap bitmap;
-    if (!PNGCodec::Decode(raw_data->front(), raw_data->size(),
-                               &bitmap)) {
-      LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
-      return ImageSkiaRep();
-    }
-    return ImageSkiaRep(bitmap, png_rep.scale);
-  }
-
- private:
-  struct Compare {
-    bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
-      return rep1.scale() < rep2.scale();
-    }
-  };
-
-  typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
-  ImageSkiaRepSet image_skia_reps_;
-  gfx::Size size_;
-
-  DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
-};
-
-ImageSkia* ImageSkiaFromPNG(
-    const std::vector<ImagePNGRep>& image_png_reps) {
-  if (image_png_reps.empty())
-    return GetErrorImageSkia();
-  std::unique_ptr<PNGImageSource> image_source(new PNGImageSource);
-
-  for (size_t i = 0; i < image_png_reps.size(); ++i) {
-    if (!image_source->AddPNGData(image_png_reps[i]))
-      return GetErrorImageSkia();
-  }
-  const gfx::Size& size = image_source->size();
-  DCHECK(!size.IsEmpty());
-  if (size.IsEmpty())
-    return GetErrorImageSkia();
-  return new ImageSkia(image_source.release(), size);
-}
-
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
-    const ImageSkia* image_skia) {
-  ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
-
-  scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
-  if (image_skia_rep.scale() != 1.0f ||
-      !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
-          &png_bytes->data())) {
-    return NULL;
-  }
-  return png_bytes;
-}
-#endif
-
 class ImageRepPNG;
 class ImageRepSkia;
 class ImageRepCocoa;
diff --git a/ui/gfx/image/image_generic.cc b/ui/gfx/image/image_generic.cc
new file mode 100644
index 0000000..9a87078c
--- /dev/null
+++ b/ui/gfx/image/image_generic.cc
@@ -0,0 +1,122 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/image/image_platform.h"
+
+#include <set>
+
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image_skia_source.h"
+
+namespace gfx {
+namespace internal {
+
+namespace {
+
+// Returns a 16x16 red image to visually show error in decoding PNG.
+// Caller takes ownership of returned ImageSkia.
+ImageSkia* GetErrorImageSkia() {
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(16, 16);
+  bitmap.eraseARGB(0xff, 0xff, 0, 0);
+  return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
+}
+
+class PNGImageSource : public ImageSkiaSource {
+ public:
+  PNGImageSource() {}
+  ~PNGImageSource() override {}
+
+  ImageSkiaRep GetImageForScale(float scale) override {
+    if (image_skia_reps_.empty())
+      return ImageSkiaRep();
+
+    const ImageSkiaRep* rep = NULL;
+    // gfx::ImageSkia passes one of the resource scale factors. The source
+    // should return:
+    // 1) The ImageSkiaRep with the highest scale if all available
+    // scales are smaller than |scale|.
+    // 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
+    for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
+         iter != image_skia_reps_.end(); ++iter) {
+      if ((*iter).scale() == scale)
+        return (*iter);
+      if (!rep || rep->scale() < (*iter).scale())
+        rep = &(*iter);
+      if (rep->scale() >= scale)
+        break;
+    }
+    return rep ? *rep : ImageSkiaRep();
+  }
+
+  const gfx::Size size() const { return size_; }
+
+  bool AddPNGData(const ImagePNGRep& png_rep) {
+    const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
+    if (rep.is_null())
+      return false;
+    if (size_.IsEmpty())
+      size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
+    image_skia_reps_.insert(rep);
+    return true;
+  }
+
+  static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
+    scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
+    CHECK(raw_data.get());
+    SkBitmap bitmap;
+    if (!PNGCodec::Decode(raw_data->front(), raw_data->size(), &bitmap)) {
+      LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
+      return ImageSkiaRep();
+    }
+    return ImageSkiaRep(bitmap, png_rep.scale);
+  }
+
+ private:
+  struct Compare {
+    bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
+      return rep1.scale() < rep2.scale();
+    }
+  };
+
+  typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
+  ImageSkiaRepSet image_skia_reps_;
+  gfx::Size size_;
+
+  DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
+};
+
+}  // namespace
+
+ImageSkia* ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps) {
+  if (image_png_reps.empty())
+    return GetErrorImageSkia();
+  std::unique_ptr<PNGImageSource> image_source(new PNGImageSource);
+
+  for (size_t i = 0; i < image_png_reps.size(); ++i) {
+    if (!image_source->AddPNGData(image_png_reps[i]))
+      return GetErrorImageSkia();
+  }
+  const gfx::Size& size = image_source->size();
+  DCHECK(!size.IsEmpty());
+  if (size.IsEmpty())
+    return GetErrorImageSkia();
+  return new ImageSkia(image_source.release(), size);
+}
+
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
+    const ImageSkia* image_skia) {
+  ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
+
+  scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
+  if (image_skia_rep.scale() != 1.0f ||
+      !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
+                                    &png_bytes->data())) {
+    return NULL;
+  }
+  return png_bytes;
+}
+
+}  // namespace internal
+}  // namespace gfx
diff --git a/ui/gfx/image/image_ios.mm b/ui/gfx/image/image_ios.mm
index 9520f32..e1c644d 100644
--- a/ui/gfx/image/image_ios.mm
+++ b/ui/gfx/image/image_ios.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_platform.h"
 
 #include <stddef.h>
 #import <UIKit/UIKit.h>
diff --git a/ui/gfx/image/image_mac.mm b/ui/gfx/image/image_mac.mm
index 6358a36..bce7986 100644
--- a/ui/gfx/image/image_mac.mm
+++ b/ui/gfx/image/image_mac.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_platform.h"
 
 #import <AppKit/AppKit.h>
 #include <stddef.h>
diff --git a/ui/gfx/image/image_platform.h b/ui/gfx/image/image_platform.h
new file mode 100644
index 0000000..ca49cbe
--- /dev/null
+++ b/ui/gfx/image/image_platform.h
@@ -0,0 +1,57 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file declares platform-specific helper functions in gfx::internal for
+// use by image.cc.
+//
+// The functions are implemented in image_generic.cc (all platforms other than
+// iOS), image_ios.mm and image_mac.mm.
+
+#ifndef UI_GFX_IMAGE_IMAGE_PLATFORM_H_
+#define UI_GFX_IMAGE_IMAGE_PLATFORM_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_png_rep.h"
+#include "ui/gfx/image/image_skia.h"
+
+#if defined(OS_IOS)
+#include "base/mac/foundation_util.h"
+#include "ui/gfx/image/image_skia_util_ios.h"
+#elif defined(OS_MACOSX)
+#include "base/mac/foundation_util.h"
+#include "base/mac/mac_util.h"
+#include "ui/gfx/image/image_skia_util_mac.h"
+#endif
+
+namespace gfx {
+namespace internal {
+
+#if defined(OS_IOS)
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
+    UIImage* uiimage);
+// Caller takes ownership of the returned UIImage.
+UIImage* CreateUIImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps);
+gfx::Size UIImageSize(UIImage* image);
+#elif defined(OS_MACOSX)
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
+    NSImage* nsimage);
+// Caller takes ownership of the returned NSImage.
+NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
+                        CGColorSpaceRef color_space);
+gfx::Size NSImageSize(NSImage* image);
+#endif  // defined(OS_MACOSX)
+
+ImageSkia* ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps);
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
+    const ImageSkia* image_skia);
+
+}  // namespace internal
+}  // namespace gfx
+
+#endif  // UI_GFX_IMAGE_IMAGE_PLATFORM_H_
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn
index 96cfede..dded329 100644
--- a/ui/message_center/BUILD.gn
+++ b/ui/message_center/BUILD.gn
@@ -28,6 +28,7 @@
   deps = [
     "//base",
     "//ui/base",
+    "//ui/strings",
     "//url",
   ]
 
@@ -47,7 +48,6 @@
       "//ui/gfx/geometry",
       "//ui/native_theme",
       "//ui/resources",
-      "//ui/strings",
     ]
 
     configs += [
diff --git a/ui/message_center/fake_message_center.cc b/ui/message_center/fake_message_center.cc
index 1900b0e6..b1e67185 100644
--- a/ui/message_center/fake_message_center.cc
+++ b/ui/message_center/fake_message_center.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ui/message_center/fake_message_center.h"
+#include "base/strings/string_util.h"
 #include "ui/message_center/notification_list.h"
 
 namespace message_center {
@@ -142,6 +143,13 @@
 
 void FakeMessageCenter::PausePopupTimers() {}
 
+const base::string16& FakeMessageCenter::GetProductOSName() const {
+  return base::EmptyString16();
+}
+
+void FakeMessageCenter::SetProductOSName(
+    const base::string16& product_os_name) {}
+
 void FakeMessageCenter::DisableTimersForTest() {}
 
 void FakeMessageCenter::EnableChangeQueueForTest(bool enabled) {}
diff --git a/ui/message_center/fake_message_center.h b/ui/message_center/fake_message_center.h
index 7a8766a..c489f67 100644
--- a/ui/message_center/fake_message_center.h
+++ b/ui/message_center/fake_message_center.h
@@ -68,6 +68,8 @@
   bool IsMessageCenterVisible() const override;
   void RestartPopupTimers() override;
   void PausePopupTimers() override;
+  const base::string16& GetProductOSName() const override;
+  void SetProductOSName(const base::string16& product_os_name) override;
 
  protected:
   void DisableTimersForTest() override;
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h
index 55697cb..2eebf0ff 100644
--- a/ui/message_center/message_center.h
+++ b/ui/message_center/message_center.h
@@ -193,6 +193,11 @@
   // example, after the mouse leaves the popup.)
   virtual void RestartPopupTimers() = 0;
 
+  // "Chromium OS" or "Chrome OS" in the current locale.
+  // Return empty string if not on these platforms.
+  virtual const base::string16& GetProductOSName() const = 0;
+  virtual void SetProductOSName(const base::string16& product_os_name) = 0;
+
  protected:
   friend class ::DownloadNotification;
   friend class ::DownloadNotificationTestBase;
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index c4396746..e2369ca 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -15,6 +15,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/observer_list.h"
 #include "base/stl_util.h"
+#include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "ui/message_center/message_center_style.h"
 #include "ui/message_center/message_center_switches.h"
@@ -943,6 +944,15 @@
     popup_timers_controller_->PauseAll();
 }
 
+const base::string16& MessageCenterImpl::GetProductOSName() const {
+  return product_os_name_;
+}
+
+void MessageCenterImpl::SetProductOSName(
+    const base::string16& product_os_name) {
+  product_os_name_ = product_os_name;
+}
+
 void MessageCenterImpl::DisableTimersForTest() {
   popup_timers_controller_.reset();
 }
diff --git a/ui/message_center/message_center_impl.h b/ui/message_center/message_center_impl.h
index 3dd9c7f..ea4348a3 100644
--- a/ui/message_center/message_center_impl.h
+++ b/ui/message_center/message_center_impl.h
@@ -84,6 +84,8 @@
   void EnterQuietModeWithExpire(const base::TimeDelta& expires_in) override;
   void RestartPopupTimers() override;
   void PausePopupTimers() override;
+  const base::string16& GetProductOSName() const override;
+  void SetProductOSName(const base::string16& product_os_name) override;
   void ForceNotificationFlush(const std::string& id) override;
 
   // NotificationBlocker::Observer overrides:
@@ -137,6 +139,8 @@
   // center is visible.
   std::unique_ptr<internal::ChangeQueue> notification_queue_;
 
+  base::string16 product_os_name_;
+
   DISALLOW_COPY_AND_ASSIGN(MessageCenterImpl);
 };
 
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h
index be5acf24..15102b9 100644
--- a/ui/message_center/message_center_style.h
+++ b/ui/message_center/message_center_style.h
@@ -9,6 +9,7 @@
 
 #include "build/build_config.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/message_center/message_center_export.h"
 
@@ -100,6 +101,15 @@
 const SkColor kControlButtonBackgroundColor =
     SkColorSetA(SK_ColorWHITE, 0.9 * 0xff);
 
+// Accent colors of system notifications.
+const SkColor kSystemNotificationColorNormal = SkColorSetRGB(0x33, 0x67, 0xd6);
+const SkColor kSystemNotificationColorWarning = SkColorSetRGB(0xea, 0x61, 0x0);
+const SkColor kSystemNotificationColorCriticalWarning =
+    SkColorSetRGB(0xc5, 0x39, 0x29);
+
+// Default accent color of notifications that are not generated by system.
+const SkColor kNotificationDefaultAccentColor = gfx::kChromeIconGrey;
+
 // Limits.
 
 // Given the size of an image, returns the size of the properly scaled-up image
diff --git a/ui/message_center/notification.cc b/ui/message_center/notification.cc
index c7a7389..1d5a222 100644
--- a/ui/message_center/notification.cc
+++ b/ui/message_center/notification.cc
@@ -5,8 +5,15 @@
 #include "ui/message_center/notification.h"
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/vector_icon_types.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_style.h"
 #include "ui/message_center/notification_delegate.h"
 #include "ui/message_center/notification_types.h"
+#include "ui/strings/grit/ui_strings.h"
 
 namespace message_center {
 
@@ -54,7 +61,9 @@
       vibration_pattern(other.vibration_pattern),
       renotify(other.renotify),
       silent(other.silent),
-      accessible_name(other.accessible_name) {}
+      accessible_name(other.accessible_name),
+      accent_color(other.accent_color) {
+}
 
 RichNotificationData::~RichNotificationData() = default;
 
@@ -170,14 +179,58 @@
     const gfx::Image& icon,
     const std::string& system_component_id,
     const base::Closure& click_callback) {
-  std::unique_ptr<Notification> notification(new Notification(
+  std::unique_ptr<Notification> notification = CreateSystemNotification(
       NOTIFICATION_TYPE_SIMPLE, notification_id, title, message, icon,
       base::string16() /* display_source */, GURL(),
       NotifierId(NotifierId::SYSTEM_COMPONENT, system_component_id),
       RichNotificationData(),
-      new HandleNotificationClickedDelegate(click_callback)));
+      new HandleNotificationClickedDelegate(click_callback), gfx::kNoneIcon,
+      SystemNotificationWarningLevel::CRITICAL_WARNING);
   notification->SetSystemPriority();
   return notification;
 }
 
+// static
+std::unique_ptr<Notification> Notification::CreateSystemNotification(
+    NotificationType type,
+    const std::string& id,
+    const base::string16& title,
+    const base::string16& message,
+    const gfx::Image& icon,
+    const base::string16& display_source,
+    const GURL& origin_url,
+    const NotifierId& notifier_id,
+    const RichNotificationData& optional_fields,
+    scoped_refptr<NotificationDelegate> delegate,
+    const gfx::VectorIcon& small_image,
+    SystemNotificationWarningLevel color_type) {
+  SkColor color = message_center::kSystemNotificationColorNormal;
+  switch (color_type) {
+    case SystemNotificationWarningLevel::NORMAL:
+      color = message_center::kSystemNotificationColorNormal;
+      break;
+    case SystemNotificationWarningLevel::WARNING:
+      color = message_center::kSystemNotificationColorWarning;
+      break;
+    case SystemNotificationWarningLevel::CRITICAL_WARNING:
+      color = message_center::kSystemNotificationColorCriticalWarning;
+      break;
+  }
+  base::string16 display_source_or_default = display_source;
+  if (display_source_or_default.empty()) {
+    display_source_or_default = l10n_util::GetStringFUTF16(
+        IDS_MESSAGE_CENTER_NOTIFICATION_CHROMEOS_SYSTEM,
+        MessageCenter::Get()->GetProductOSName());
+  }
+  std::unique_ptr<Notification> notification = base::MakeUnique<Notification>(
+      type, id, title, message, icon, display_source_or_default, origin_url,
+      notifier_id, optional_fields, delegate);
+  notification->set_accent_color(color);
+  notification->set_small_image(
+      small_image.is_empty()
+          ? gfx::Image()
+          : gfx::Image(gfx::CreateVectorIcon(small_image, color)));
+  return notification;
+}
+
 }  // namespace message_center
diff --git a/ui/message_center/notification.h b/ui/message_center/notification.h
index d08a48a8..8101cad 100644
--- a/ui/message_center/notification.h
+++ b/ui/message_center/notification.h
@@ -15,13 +15,19 @@
 #include "base/time/time.h"
 #include "base/values.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"  // nogncheck
+#include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image.h"
+#include "ui/gfx/skia_util.h"
 #include "ui/message_center/message_center_export.h"
 #include "ui/message_center/notification_delegate.h"
 #include "ui/message_center/notification_types.h"
 #include "ui/message_center/notifier_settings.h"
 #include "url/gurl.h"
 
+namespace gfx {
+struct VectorIcon;
+}  // namespace gfx
+
 namespace message_center {
 
 namespace mojom {
@@ -45,6 +51,8 @@
   TEXT
 };
 
+enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING };
+
 // Represents a button to be shown as part of a notification.
 struct MESSAGE_CENTER_EXPORT ButtonInfo {
   explicit ButtonInfo(const base::string16& title);
@@ -141,6 +149,12 @@
 
   // An accessible description of the notification's contents.
   base::string16 accessible_name;
+
+  // Unified theme color used in new style notification.
+  // Usually, it should not be set directly.
+  // For system notification, CreateSystemNotification with
+  // SystemNotificationWarningLevel should be used.
+  SkColor accent_color = SK_ColorTRANSPARENT;
 };
 
 class MESSAGE_CENTER_EXPORT Notification {
@@ -345,6 +359,11 @@
     return optional_fields_.accessible_name;
   }
 
+  SkColor accent_color() const { return optional_fields_.accent_color; }
+  void set_accent_color(SkColor accent_color) {
+    optional_fields_.accent_color = accent_color;
+  }
+
   NotificationDelegate* delegate() const { return delegate_.get(); }
 
   const RichNotificationData& rich_notification_data() const {
@@ -364,6 +383,13 @@
 
   // Helper method to create a simple system notification. |click_callback|
   // will be invoked when the notification is clicked.
+  //
+  // It should only be used for critical notification, as SetSystemPriority and
+  // CRITICAL_WARNING color are set inside, which means the notification would
+  // not go away without user interaction.
+  //
+  // TODO(tetsui): Add a function parameter |small_image| of gfx::VectorIcon, so
+  // display source of critical system notification is illustrated by icon.
   static std::unique_ptr<Notification> CreateSystemNotification(
       const std::string& notification_id,
       const base::string16& title,
@@ -372,6 +398,25 @@
       const std::string& system_component_id,
       const base::Closure& click_callback);
 
+  // Factory method to create all kinds of notifications generated by system,
+  // from normal priority ones to critical priority ones.
+  // |small_image| is a small icon show on the upper left header to illustrate
+  // |display_source| of the notification.
+  // One specified in the |optional_fields| is overridden.
+  static std::unique_ptr<Notification> CreateSystemNotification(
+      NotificationType type,
+      const std::string& id,
+      const base::string16& title,
+      const base::string16& message,
+      const gfx::Image& icon,
+      const base::string16& display_source,
+      const GURL& origin_url,
+      const NotifierId& notifier_id,
+      const RichNotificationData& optional_fields,
+      scoped_refptr<NotificationDelegate> delegate,
+      const gfx::VectorIcon& small_image,
+      SystemNotificationWarningLevel color_type);
+
  protected:
   // The type of notification we'd like displayed.
   NotificationType type_;
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc
index ed32903..5084cdc 100644
--- a/ui/message_center/views/message_list_view.cc
+++ b/ui/message_center/views/message_list_view.cc
@@ -177,12 +177,12 @@
   return height + GetInsets().height();
 }
 
-void MessageListView::PaintChildren(const ui::PaintContext& context) {
+void MessageListView::PaintChildren(const views::PaintInfo& paint_info) {
   // Paint in the inversed order. Otherwise upper notification may be
   // hidden by the lower one.
   for (int i = child_count() - 1; i >= 0; --i) {
     if (!child_at(i)->layer())
-      child_at(i)->Paint(context);
+      child_at(i)->Paint(paint_info);
   }
 }
 
diff --git a/ui/message_center/views/message_list_view.h b/ui/message_center/views/message_list_view.h
index b12f80f6..a2232fa0 100644
--- a/ui/message_center/views/message_list_view.h
+++ b/ui/message_center/views/message_list_view.h
@@ -63,7 +63,7 @@
   void Layout() override;
   gfx::Size CalculatePreferredSize() const override;
   int GetHeightForWidth(int width) const override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
   void ReorderChildLayers(ui::Layer* parent_layer) override;
 
   // Overridden from views::BoundsAnimatorObserver.
diff --git a/ui/message_center/views/notification_header_view.cc b/ui/message_center/views/notification_header_view.cc
index a43e6eaa..5a26331 100644
--- a/ui/message_center/views/notification_header_view.cc
+++ b/ui/message_center/views/notification_header_view.cc
@@ -68,8 +68,6 @@
 };
 
 ExpandButton::ExpandButton() {
-  SetImage(gfx::CreateVectorIcon(kNotificationExpandMoreIcon, kExpandIconSize,
-                                 gfx::kChromeIconGrey));
   focus_painter_ = views::Painter::CreateSolidFocusPainter(
       kFocusBorderColor, gfx::Insets(1, 2, 2, 2));
   SetFocusBehavior(FocusBehavior::ALWAYS);
@@ -159,6 +157,7 @@
   app_name_view_ = new views::Label(base::string16());
   app_name_view_->SetFontList(font_list);
   app_name_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  app_name_view_->SetEnabledColor(accent_color_);
   app_info_container->AddChildView(app_name_view_);
 
   // Summary text divider
@@ -193,6 +192,7 @@
 
   // Expand button view
   expand_button_ = new ExpandButton();
+  SetExpanded(is_expanded_);
   app_info_container->AddChildView(expand_button_);
 
   // Spacer between left-aligned views and right-aligned views
@@ -224,6 +224,10 @@
   app_icon_view_->SetImage(img);
 }
 
+void NotificationHeaderView::ClearAppIcon() {
+  app_icon_view_->SetImage(gfx::CreateVectorIcon(kProductIcon, accent_color_));
+}
+
 void NotificationHeaderView::SetAppName(const base::string16& name) {
   app_name_view_->SetText(name);
 }
@@ -277,10 +281,10 @@
 }
 
 void NotificationHeaderView::SetExpanded(bool expanded) {
-  expand_button_->SetImage(
-      gfx::CreateVectorIcon(
-          expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon,
-          kExpandIconSize, gfx::kChromeIconGrey));
+  is_expanded_ = expanded;
+  expand_button_->SetImage(gfx::CreateVectorIcon(
+      expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon,
+      kExpandIconSize, accent_color_));
 }
 
 void NotificationHeaderView::SetSettingsButtonEnabled(bool enabled) {
@@ -304,6 +308,12 @@
   }
 }
 
+void NotificationHeaderView::SetAccentColor(SkColor color) {
+  accent_color_ = color;
+  app_name_view_->SetEnabledColor(accent_color_);
+  SetExpanded(is_expanded_);
+}
+
 bool NotificationHeaderView::IsExpandButtonEnabled() {
   return expand_button_->visible();
 }
diff --git a/ui/message_center/views/notification_header_view.h b/ui/message_center/views/notification_header_view.h
index 2471c67a..d196eb5a 100644
--- a/ui/message_center/views/notification_header_view.h
+++ b/ui/message_center/views/notification_header_view.h
@@ -6,6 +6,7 @@
 #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_HEADER_VIEW_H_
 
 #include "base/macros.h"
+#include "ui/message_center/message_center_style.h"
 #include "ui/message_center/views/padded_button.h"
 #include "ui/views/controls/button/custom_button.h"
 
@@ -30,6 +31,10 @@
   void SetSettingsButtonEnabled(bool enabled);
   void SetCloseButtonEnabled(bool enabled);
   void SetControlButtonsVisible(bool visible);
+  // Set the unified theme color used among the app icon, app name, and expand
+  // button.
+  void SetAccentColor(SkColor color);
+  void ClearAppIcon();
   void ClearProgress();
   void ClearOverflowIndicator();
   void ClearTimestamp();
@@ -53,6 +58,8 @@
   // Update visibility for both |summary_text_view_| and |timestamp_view_|.
   void UpdateSummaryTextVisibility();
 
+  SkColor accent_color_ = message_center::kNotificationDefaultAccentColor;
+
   views::Label* app_name_view_ = nullptr;
   views::Label* summary_text_divider_ = nullptr;
   views::Label* summary_text_view_ = nullptr;
@@ -69,6 +76,7 @@
   bool has_progress_ = false;
   bool has_overflow_indicator_ = false;
   bool has_timestamp_ = false;
+  bool is_expanded_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(NotificationHeaderView);
 };
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc
index 3251a9ba1..37a6d2e 100644
--- a/ui/message_center/views/notification_view_md.cc
+++ b/ui/message_center/views/notification_view_md.cc
@@ -12,7 +12,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/text_elider.h"
@@ -56,10 +55,6 @@
 constexpr gfx::Size kActionButtonMinSize(88, 32);
 constexpr gfx::Size kIconViewSize(30, 30);
 
-// Foreground of small icon image.
-constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE;
-// Background of small icon image.
-const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43);
 // Background of inline actions area.
 const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee);
 // Base ink drop color of action buttons.
@@ -83,37 +78,6 @@
     message_center::kNotificationWidth - kIconViewSize.width() -
     kContentRowPadding.left() - kContentRowPadding.right();
 
-const gfx::ImageSkia CreateSolidColorImage(int width,
-                                           int height,
-                                           SkColor color) {
-  SkBitmap bitmap;
-  bitmap.allocN32Pixels(width, height);
-  bitmap.eraseColor(color);
-  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
-}
-
-// Take the alpha channel of icon, mask it with the foreground,
-// then add the masked foreground on top of the background
-const gfx::ImageSkia GetMaskedIcon(const gfx::ImageSkia& icon) {
-  int width = icon.width();
-  int height = icon.height();
-
-  // Background color grey
-  const gfx::ImageSkia background = CreateSolidColorImage(
-      width, height, message_center::kSmallImageBackgroundColor);
-  // Foreground color white
-  const gfx::ImageSkia foreground =
-      CreateSolidColorImage(width, height, message_center::kSmallImageColor);
-  const gfx::ImageSkia masked_small_image =
-      gfx::ImageSkiaOperations::CreateMaskedImage(foreground, icon);
-  return gfx::ImageSkiaOperations::CreateSuperimposedImage(background,
-                                                           masked_small_image);
-}
-
-const gfx::ImageSkia GetProductIcon() {
-  return gfx::CreateVectorIcon(kProductIcon, kSmallImageColor);
-}
-
 // ItemView ////////////////////////////////////////////////////////////////////
 
 // ItemViews are responsible for drawing each list notification item's title and
@@ -504,6 +468,10 @@
 void NotificationViewMD::CreateOrUpdateContextTitleView(
     const Notification& notification) {
   header_row_->SetAppName(notification.display_source());
+  header_row_->SetAccentColor(
+      notification.accent_color() == SK_ColorTRANSPARENT
+          ? message_center::kNotificationDefaultAccentColor
+          : notification.accent_color());
   header_row_->SetTimestamp(notification.timestamp());
 }
 
@@ -687,11 +655,10 @@
 
 void NotificationViewMD::CreateOrUpdateSmallIconView(
     const Notification& notification) {
-  gfx::ImageSkia icon =
-      notification.small_image().IsEmpty()
-          ? GetProductIcon()
-          : GetMaskedIcon(notification.small_image().AsImageSkia());
-  header_row_->SetAppIcon(icon);
+  if (notification.small_image().IsEmpty())
+    header_row_->ClearAppIcon();
+  else
+    header_row_->SetAppIcon(notification.small_image().AsImageSkia());
 }
 
 void NotificationViewMD::CreateOrUpdateImageView(
@@ -760,6 +727,12 @@
       action_buttons_[i]->SchedulePaint();
       action_buttons_[i]->Layout();
     }
+
+    // Change action button color to the accent color.
+    action_buttons_[i]->SetEnabledTextColors(notification.accent_color() ==
+                                                     SK_ColorTRANSPARENT
+                                                 ? kActionButtonTextColor
+                                                 : notification.accent_color());
   }
 
   // Inherit mouse hover state when action button views reset.
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 76de06b..7dd2ae12 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -185,6 +185,7 @@
     "native_cursor.h",
     "native_theme_delegate.h",
     "painter.h",
+    "paint_info.h",
     "pointer_watcher.h",
     "rect_based_targeting_utils.h",
     "repeat_controller.h",
@@ -364,6 +365,7 @@
     "mouse_watcher.cc",
     "mouse_watcher_view_host.cc",
     "native_cursor_mac.mm",
+    "paint_info.cc",
     "painter.cc",
     "rect_based_targeting_utils.cc",
     "repeat_controller.cc",
@@ -897,6 +899,7 @@
     "controls/button/label_button_label_unittest.cc",
     "controls/button/label_button_unittest.cc",
     "controls/button/menu_button_unittest.cc",
+    "controls/button/radio_button_unittest.cc",
     "controls/button/toggle_button_unittest.cc",
     "controls/combobox/combobox_unittest.cc",
     "controls/label_unittest.cc",
@@ -930,6 +933,7 @@
     "layout/box_layout_unittest.cc",
     "layout/fill_layout_unittest.cc",
     "layout/grid_layout_unittest.cc",
+    "paint_info_unittest.cc",
     "rect_based_targeting_utils_unittest.cc",
     "test/widget_test_unittest.cc",
     "view_model_unittest.cc",
diff --git a/ui/views/DEPS b/ui/views/DEPS
index ee24327..edc6d257 100644
--- a/ui/views/DEPS
+++ b/ui/views/DEPS
@@ -36,5 +36,8 @@
   ],
   "views_test_suite\.cc": [
     "+gpu/ipc/service",
+  ],
+  "paint_info_unittest\.cc": [
+    "+cc/base",
   ]
 }
diff --git a/ui/views/animation/square_ink_drop_ripple.cc b/ui/views/animation/square_ink_drop_ripple.cc
index 7dd72be..fffc856 100644
--- a/ui/views/animation/square_ink_drop_ripple.cc
+++ b/ui/views/animation/square_ink_drop_ripple.cc
@@ -238,6 +238,8 @@
       }
       break;
     case InkDropState::ACTION_PENDING:
+      if (old_ink_drop_state == new_ink_drop_state)
+        return;
       DCHECK_EQ(InkDropState::HIDDEN, old_ink_drop_state)
           << " old_ink_drop_state=" << ToString(old_ink_drop_state);
       AnimateToOpacity(visible_opacity_,
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index 23546f49..e1658e0 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -14,7 +14,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/paint_context.h"
 #include "ui/compositor/paint_recorder.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -31,6 +30,7 @@
 #include "ui/views/controls/image_view.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/layout_provider.h"
+#include "ui/views/paint_info.h"
 #include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -404,10 +404,14 @@
   // Border comes after children.
 }
 
-void BubbleFrameView::PaintChildren(const ui::PaintContext& context) {
-  NonClientFrameView::PaintChildren(context);
+void BubbleFrameView::PaintChildren(const PaintInfo& paint_info) {
+  NonClientFrameView::PaintChildren(paint_info);
 
-  ui::PaintRecorder recorder(context, size());
+  ui::PaintCache paint_cache;
+  ui::PaintRecorder recorder(
+      paint_info.context(), paint_info.paint_recording_size(),
+      paint_info.paint_recording_scale_x(),
+      paint_info.paint_recording_scale_y(), &paint_cache);
   OnPaintBorder(recorder.canvas());
 }
 
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h
index 015cc5f..e6e9e2f 100644
--- a/ui/views/bubble/bubble_frame_view.h
+++ b/ui/views/bubble/bubble_frame_view.h
@@ -60,7 +60,7 @@
   gfx::Size GetMaximumSize() const override;
   void Layout() override;
   void OnPaint(gfx::Canvas* canvas) override;
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const PaintInfo& paint_info) override;
   void OnThemeChanged() override;
   void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
   void ViewHierarchyChanged(
diff --git a/ui/views/button_drag_utils.cc b/ui/views/button_drag_utils.cc
index 064a133..c898239 100644
--- a/ui/views/button_drag_utils.cc
+++ b/ui/views/button_drag_utils.cc
@@ -18,6 +18,7 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/drag_utils.h"
+#include "ui/views/paint_info.h"
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
 
@@ -83,7 +84,11 @@
   SkBitmap bitmap;
   float raster_scale = ScaleFactorForDragFromWidget(&widget);
   SkColor color = SK_ColorTRANSPARENT;
-  button.Paint(ui::CanvasPainter(&bitmap, size, raster_scale, color).context());
+  button.Paint(views::PaintInfo::CreateRootPaintInfo(
+      ui::CanvasPainter(&bitmap, size, raster_scale, color,
+                        widget.GetCompositor()->is_pixel_canvas())
+          .context(),
+      size));
   gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, raster_scale));
   data->provider().SetDragImage(image, press_point);
 }
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm
index b4a4de30..e4d1ee9 100644
--- a/ui/views/cocoa/bridged_native_widget.mm
+++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -1275,7 +1275,8 @@
   compositor_.reset(new ui::Compositor(
       context_factory_private->AllocateFrameSinkId(), context_factory,
       context_factory_private, GetCompositorTaskRunner(),
-      false /* enable_surface_synchronization */));
+      false /* enable_surface_synchronization */,
+      false /* enable_pixel_canvas */));
   compositor_->SetAcceleratedWidget(compositor_widget_->accelerated_widget());
   compositor_widget_->SetNSView(this);
 }
diff --git a/ui/views/controls/button/radio_button_unittest.cc b/ui/views/controls/button/radio_button_unittest.cc
new file mode 100644
index 0000000..c68b6ad
--- /dev/null
+++ b/ui/views/controls/button/radio_button_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/button/radio_button.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace {
+// Group ID of the test radio buttons.
+constexpr int kGroup = 1;
+}  // namespace
+
+namespace views {
+
+class RadioButtonTest : public ViewsTestBase {
+ public:
+  RadioButtonTest() : button_container_(nullptr) {}
+
+  void SetUp() override {
+    ViewsTestBase::SetUp();
+
+    // Create a Widget so the radio buttons can find their group siblings.
+    widget_ = base::MakeUnique<Widget>();
+    Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+    params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    widget_->Init(params);
+    widget_->Show();
+
+    button_container_ = new View();
+    widget_->SetContentsView(button_container_);
+  }
+
+  void TearDown() override {
+    button_container_ = nullptr;
+    widget_.reset();
+    ViewsTestBase::TearDown();
+  }
+
+ protected:
+  View& button_container() { return *button_container_; }
+
+ private:
+  View* button_container_;
+  std::unique_ptr<Widget> widget_;
+
+  DISALLOW_COPY_AND_ASSIGN(RadioButtonTest);
+};
+
+TEST_F(RadioButtonTest, Basics) {
+  RadioButton* button1 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+  button_container().AddChildView(button1);
+  RadioButton* button2 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+  button_container().AddChildView(button2);
+
+  button1->SetChecked(true);
+  EXPECT_TRUE(button1->checked());
+  EXPECT_FALSE(button2->checked());
+
+  button2->SetChecked(true);
+  EXPECT_FALSE(button1->checked());
+  EXPECT_TRUE(button2->checked());
+}
+
+TEST_F(RadioButtonTest, Focus) {
+  RadioButton* button1 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+  button_container().AddChildView(button1);
+  RadioButton* button2 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+  button_container().AddChildView(button2);
+
+  // Tabbing through only focuses the checked button.
+  button1->SetChecked(true);
+  auto* focus_manager = button_container().GetFocusManager();
+  ui::KeyEvent pressed_tab(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE);
+  focus_manager->OnKeyEvent(pressed_tab);
+  EXPECT_EQ(button1, focus_manager->GetFocusedView());
+  focus_manager->OnKeyEvent(pressed_tab);
+  EXPECT_EQ(button1, focus_manager->GetFocusedView());
+
+  // The checked button can be moved using arrow keys.
+  focus_manager->OnKeyEvent(
+      ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE));
+  EXPECT_EQ(button2, focus_manager->GetFocusedView());
+  EXPECT_FALSE(button1->checked());
+  EXPECT_TRUE(button2->checked());
+
+  focus_manager->OnKeyEvent(
+      ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE));
+  EXPECT_EQ(button1, focus_manager->GetFocusedView());
+  EXPECT_TRUE(button1->checked());
+  EXPECT_FALSE(button2->checked());
+}
+
+}  // namespace views
diff --git a/ui/views/controls/button/toggle_button.cc b/ui/views/controls/button/toggle_button.cc
index 5585524..4e024ae 100644
--- a/ui/views/controls/button/toggle_button.cc
+++ b/ui/views/controls/button/toggle_button.cc
@@ -111,8 +111,6 @@
 
 ToggleButton::ToggleButton(ButtonListener* listener)
     : CustomButton(listener),
-      is_on_(false),
-      slide_animation_(this),
       thumb_view_(new ThumbView()) {
   slide_animation_.SetSlideDuration(80 /* ms */);
   slide_animation_.SetTweenType(gfx::Tween::LINEAR);
@@ -185,6 +183,10 @@
   return kViewClassName;
 }
 
+bool ToggleButton::CanAcceptEvent(const ui::Event& event) {
+  return accepts_events_ && CustomButton::CanAcceptEvent(event);
+}
+
 void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   UpdateThumb();
 }
@@ -202,9 +204,32 @@
   node_data->AddIntAttribute(ui::AX_ATTR_CHECKED_STATE, checked_state);
 }
 
+void ToggleButton::OnFocus() {
+  CustomButton::OnFocus();
+  AnimateInkDrop(views::InkDropState::ACTION_PENDING, nullptr);
+}
+
+void ToggleButton::OnBlur() {
+  CustomButton::OnBlur();
+
+  // The ink drop may have already gone away if the user clicked after focusing.
+  if (GetInkDrop()->GetTargetInkDropState() ==
+      views::InkDropState::ACTION_PENDING) {
+    AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, nullptr);
+  }
+}
+
 void ToggleButton::NotifyClick(const ui::Event& event) {
   SetIsOn(!is_on(), true);
-  CustomButton::NotifyClick(event);
+
+  // Skip over CustomButton::NotifyClick, to customize the ink drop animation.
+  // Leave the ripple in place when the button is activated via the keyboard.
+  if (!event.IsKeyEvent()) {
+    AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
+                   ui::LocatedEvent::FromIfValid(&event));
+  }
+
+  Button::NotifyClick(event);
 }
 
 void ToggleButton::PaintButtonContents(gfx::Canvas* canvas) {
@@ -247,7 +272,7 @@
 }
 
 SkColor ToggleButton::GetInkDropBaseColor() const {
-  return GetTrackColor(is_on());
+  return GetTrackColor(is_on() || HasFocus());
 }
 
 void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
diff --git a/ui/views/controls/button/toggle_button.h b/ui/views/controls/button/toggle_button.h
index 7b35688..d337486 100644
--- a/ui/views/controls/button/toggle_button.h
+++ b/ui/views/controls/button/toggle_button.h
@@ -23,6 +23,10 @@
   void SetIsOn(bool is_on, bool animate);
   bool is_on() const { return is_on_; }
 
+  void set_accepts_events(bool accepts_events) {
+    accepts_events_ = accepts_events;
+  }
+
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
 
@@ -43,9 +47,12 @@
 
   // views::View:
   const char* GetClassName() const override;
+  bool CanAcceptEvent(const ui::Event& event) override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
   void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+  void OnFocus() override;
+  void OnBlur() override;
 
   // CustomButton:
   void NotifyClick(const ui::Event& event) override;
@@ -59,10 +66,14 @@
   // gfx::AnimationDelegate:
   void AnimationProgressed(const gfx::Animation* animation) override;
 
-  bool is_on_;
-  gfx::SlideAnimation slide_animation_;
+  bool is_on_ = false;
+  gfx::SlideAnimation slide_animation_{this};
   ThumbView* thumb_view_;
 
+  // When false, this button won't accept input. Different from View::SetEnabled
+  // in that the view retains focus when this is false but not when disabled.
+  bool accepts_events_ = true;
+
   DISALLOW_COPY_AND_ASSIGN(ToggleButton);
 };
 
diff --git a/ui/views/controls/button/toggle_button_unittest.cc b/ui/views/controls/button/toggle_button_unittest.cc
index 8ea3f03..e0a6e2e 100644
--- a/ui/views/controls/button/toggle_button_unittest.cc
+++ b/ui/views/controls/button/toggle_button_unittest.cc
@@ -9,6 +9,7 @@
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_utils.h"
+#include "ui/events/test/event_generator.h"
 #include "ui/views/style/platform_style.h"
 #include "ui/views/test/views_test_base.h"
 
@@ -25,6 +26,8 @@
     SetInkDropMode(InkDropMode::OFF);
   }
 
+  using View::Focus;
+
  protected:
   // ToggleButton:
   void AddInkDropLayer(ui::Layer* ink_drop_layer) override {
@@ -54,7 +57,8 @@
     // Create a widget so that the ToggleButton can query the hover state
     // correctly.
     widget_.reset(new Widget);
-    Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+    Widget::InitParams params =
+        CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     params.bounds = gfx::Rect(0, 0, 650, 650);
     widget_->Init(params);
@@ -100,4 +104,53 @@
   EXPECT_EQ(0, counter());
 }
 
+// Make sure nothing bad happens when the widget is destroyed while the
+// ToggleButton has focus (and is showing a ripple).
+TEST_F(ToggleButtonTest, ShutdownWithFocus) {
+  button()->RequestFocus();
+  if (PlatformStyle::kUseRipples)
+    EXPECT_EQ(1, counter());
+  else
+    EXPECT_EQ(0, counter());
+}
+
+// Verify that ToggleButton::accepts_events_ works as expected.
+TEST_F(ToggleButtonTest, AcceptEvents) {
+  EXPECT_FALSE(button()->is_on());
+  ui::test::EventGenerator generator(widget()->GetNativeWindow());
+
+  // Clicking toggles.
+  generator.ClickLeftButton();
+  EXPECT_TRUE(button()->is_on());
+  generator.ClickLeftButton();
+  EXPECT_FALSE(button()->is_on());
+
+  // Spacebar toggles.
+  button()->RequestFocus();
+  generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+  generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+  EXPECT_TRUE(button()->is_on());
+  generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+  generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+  EXPECT_FALSE(button()->is_on());
+
+  // Spacebar and clicking do nothing when not accepting events, but focus is
+  // not affected.
+  button()->set_accepts_events(false);
+  EXPECT_TRUE(button()->HasFocus());
+  generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+  generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+  EXPECT_FALSE(button()->is_on());
+  generator.ClickLeftButton();
+  EXPECT_FALSE(button()->is_on());
+
+  // Re-enable events and clicking and spacebar resume working.
+  button()->set_accepts_events(true);
+  generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+  generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+  EXPECT_TRUE(button()->is_on());
+  generator.ClickLeftButton();
+  EXPECT_FALSE(button()->is_on());
+}
+
 }  // namespace views
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index b2cf18f..3dab5c8 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -56,7 +56,10 @@
   void SimulatePaint() {
     SkBitmap bitmap;
     SkColor color = SK_ColorTRANSPARENT;
-    Paint(ui::CanvasPainter(&bitmap, bounds().size(), 1.f, color).context());
+    Paint(PaintInfo::CreateRootPaintInfo(
+        ui::CanvasPainter(&bitmap, bounds().size(), 1.f, color, false)
+            .context(),
+        bounds().size()));
   }
 
   // View:
diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc
index 77795b9..8dc2bd9 100644
--- a/ui/views/controls/menu/submenu_view.cc
+++ b/ui/views/controls/menu/submenu_view.cc
@@ -191,8 +191,8 @@
   node_data->AddState(ui::AX_STATE_VERTICAL);
 }
 
-void SubmenuView::PaintChildren(const ui::PaintContext& context) {
-  View::PaintChildren(context);
+void SubmenuView::PaintChildren(const PaintInfo& paint_info) {
+  View::PaintChildren(paint_info);
 
   bool paint_drop_indicator = false;
   if (drop_item_) {
@@ -210,7 +210,7 @@
 
   if (paint_drop_indicator) {
     gfx::Rect bounds = CalculateDropIndicatorBounds(drop_item_, drop_position_);
-    ui::PaintRecorder recorder(context, size());
+    ui::PaintRecorder recorder(paint_info.context(), size());
     recorder.canvas()->FillRect(bounds, kDropIndicatorColor);
   }
 }
diff --git a/ui/views/controls/menu/submenu_view.h b/ui/views/controls/menu/submenu_view.h
index 6bfacac..c3b3e11 100644
--- a/ui/views/controls/menu/submenu_view.h
+++ b/ui/views/controls/menu/submenu_view.h
@@ -69,7 +69,7 @@
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   // Painting.
-  void PaintChildren(const ui::PaintContext& context) override;
+  void PaintChildren(const PaintInfo& paint_info) override;
 
   // Drag and drop methods. These are forwarded to the MenuController.
   bool GetDropFormats(
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc
index eaa903c..8af93e64 100644
--- a/ui/views/controls/slider.cc
+++ b/ui/views/controls/slider.cc
@@ -20,7 +20,6 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/native_theme/native_theme.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
@@ -184,21 +183,6 @@
       VALUE_CHANGED_BY_USER);
 }
 
-void Slider::OnPaintFocus(gfx::Canvas* canvas) {
-  if (!HasFocus())
-    return;
-
-  // TODO(estade): make this a glow effect instead: crbug.com/658783
-  gfx::Rect focus_bounds = GetLocalBounds();
-  focus_bounds.Inset(gfx::Insets(1));
-  canvas->DrawSolidFocusRect(
-      gfx::RectF(focus_bounds),
-      SkColorSetA(GetNativeTheme()->GetSystemColor(
-                      ui::NativeTheme::kColorId_FocusedBorderColor),
-                  0x99),
-      2);
-}
-
 void Slider::OnSliderDragStarted() {
   SetHighlighted(true);
   if (listener_)
@@ -321,8 +305,6 @@
   canvas->DrawCircle(
       thumb_center,
       is_active_ ? kThumbRadius : (kThumbRadius - kThumbStroke / 2), flags);
-
-  OnPaintFocus(canvas);
 }
 
 void Slider::OnFocus() {
diff --git a/ui/views/controls/slider.h b/ui/views/controls/slider.h
index f2dace0..096b1401 100644
--- a/ui/views/controls/slider.h
+++ b/ui/views/controls/slider.h
@@ -87,8 +87,6 @@
   // Moves the button to the specified point and updates the value accordingly.
   void MoveButtonTo(const gfx::Point& point);
 
-  void OnPaintFocus(gfx::Canvas* canvas);
-
   // Notify the listener_, if not NULL, that dragging started.
   void OnSliderDragStarted();
 
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 5c562f17..422b4f1e 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1115,8 +1115,11 @@
   if (!ui::XVisualManager::GetInstance()->ArgbVisualAvailable())
     color = GetBackgroundColor();
 #endif
-  label.Paint(
-      ui::CanvasPainter(&bitmap, label.size(), raster_scale, color).context());
+  label.Paint(PaintInfo::CreateRootPaintInfo(
+      ui::CanvasPainter(&bitmap, label.size(), raster_scale, color,
+                        GetWidget()->GetCompositor()->is_pixel_canvas())
+          .context(),
+      label.size()));
   const gfx::Vector2d kOffset(-15, 0);
   gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, raster_scale));
   data->provider().SetDragImage(image, kOffset);
diff --git a/ui/views/paint_info.cc b/ui/views/paint_info.cc
new file mode 100644
index 0000000..79be8d4
--- /dev/null
+++ b/ui/views/paint_info.cc
@@ -0,0 +1,127 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/paint_info.h"
+
+namespace views {
+
+// static
+PaintInfo PaintInfo::CreateRootPaintInfo(const ui::PaintContext& root_context,
+                                         const gfx::Size& size) {
+  return PaintInfo(root_context, size);
+}
+
+//  static
+PaintInfo PaintInfo::CreateChildPaintInfo(const PaintInfo& parent_paint_info,
+                                          const gfx::Rect& bounds,
+                                          const gfx::Size& parent_size,
+                                          ScaleType scale_type) {
+  return PaintInfo(parent_paint_info, bounds, parent_size, scale_type);
+}
+
+// static
+PaintInfo PaintInfo::ClonePaintInfo(const PaintInfo& parent_paint_info) {
+  return PaintInfo(parent_paint_info,
+                   ui::PaintContext::CLONE_WITHOUT_INVALIDATION);
+}
+
+PaintInfo::PaintInfo(const PaintInfo& other,
+                     ui::PaintContext::CloneWithoutInvalidation c)
+    : paint_recording_scale_x_(other.paint_recording_scale_x_),
+      paint_recording_scale_y_(other.paint_recording_scale_y_),
+      paint_recording_bounds_(other.paint_recording_bounds_),
+      offset_from_parent_(other.offset_from_parent_),
+      context_(other.context(), c),
+      root_context_(nullptr) {}
+
+PaintInfo::~PaintInfo() {}
+
+bool PaintInfo::IsPixelCanvas() const {
+  return context().is_pixel_canvas();
+}
+
+PaintInfo::PaintInfo(const PaintInfo& other)
+    : paint_recording_scale_x_(other.paint_recording_scale_x_),
+      paint_recording_scale_y_(other.paint_recording_scale_y_),
+      paint_recording_bounds_(other.paint_recording_bounds_),
+      offset_from_parent_(other.offset_from_parent_),
+      context_(other.context(), gfx::Vector2d()),
+      root_context_(nullptr) {}
+
+PaintInfo::PaintInfo(const ui::PaintContext& root_context,
+                     const gfx::Size& size)
+    : paint_recording_scale_x_(root_context.is_pixel_canvas()
+                                   ? root_context.device_scale_factor()
+                                   : 1.f),
+      paint_recording_scale_y_(paint_recording_scale_x_),
+      paint_recording_bounds_(
+          gfx::ScaleToRoundedRect(gfx::Rect(size), paint_recording_scale_x_)),
+      context_(root_context, gfx::Vector2d()),
+      root_context_(&root_context) {}
+
+PaintInfo::PaintInfo(const PaintInfo& parent_paint_info,
+                     const gfx::Rect& bounds,
+                     const gfx::Size& parent_size,
+                     ScaleType scale_type)
+    : paint_recording_scale_x_(1.f),
+      paint_recording_scale_y_(1.f),
+      paint_recording_bounds_(
+          parent_paint_info.GetSnappedRecordingBounds(parent_size, bounds)),
+      offset_from_parent_(
+          paint_recording_bounds_.OffsetFromOrigin() -
+          parent_paint_info.paint_recording_bounds_.OffsetFromOrigin()),
+      context_(parent_paint_info.context(), offset_from_parent_),
+      root_context_(nullptr) {
+  if (IsPixelCanvas()) {
+    if (scale_type == ScaleType::kScaleToScaleFactor) {
+      paint_recording_scale_x_ = paint_recording_scale_y_ =
+          context().device_scale_factor();
+    } else if (scale_type == ScaleType::kScaleToFit) {
+      if (bounds.size().width() > 0) {
+        paint_recording_scale_x_ =
+            static_cast<float>(paint_recording_bounds_.width()) /
+            static_cast<float>(bounds.size().width());
+      }
+      if (bounds.size().height() > 0) {
+        paint_recording_scale_y_ =
+            static_cast<float>(paint_recording_bounds_.height()) /
+            static_cast<float>(bounds.size().height());
+      }
+    }
+  }
+}
+
+gfx::Rect PaintInfo::GetSnappedRecordingBounds(
+    const gfx::Size& parent_size,
+    const gfx::Rect& child_bounds) const {
+  if (!IsPixelCanvas())
+    return (child_bounds + paint_recording_bounds_.OffsetFromOrigin());
+
+  const gfx::Vector2d& child_origin = child_bounds.OffsetFromOrigin();
+
+  int right = child_origin.x() + child_bounds.width();
+  int bottom = child_origin.y() + child_bounds.height();
+
+  int new_x = std::round(child_origin.x() * context().device_scale_factor());
+  int new_y = std::round(child_origin.y() * context().device_scale_factor());
+
+  int new_right;
+  int new_bottom;
+
+  if (right == parent_size.width())
+    new_right = paint_recording_bounds_.width();
+  else
+    new_right = std::round(right * context().device_scale_factor());
+
+  if (bottom == parent_size.height())
+    new_bottom = paint_recording_bounds_.height();
+  else
+    new_bottom = std::round(bottom * context().device_scale_factor());
+
+  return gfx::Rect(new_x + paint_recording_bounds_.x(),
+                   new_y + paint_recording_bounds_.y(), new_right - new_x,
+                   new_bottom - new_y);
+}
+
+}  // namespace views
diff --git a/ui/views/paint_info.h b/ui/views/paint_info.h
new file mode 100644
index 0000000..8545f04
--- /dev/null
+++ b/ui/views/paint_info.h
@@ -0,0 +1,119 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_PAINT_INFO_H_
+#define UI_VIEWS_PAINT_INFO_H_
+
+#include "ui/compositor/paint_context.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+// This class manages the context required during View::Paint(). It is
+// responsible for setting the paint recording size and the paint recording
+// scale factors for an individual View.
+// Each PaintInfo instance has paint recording offset relative to a root
+// PaintInfo.
+// All coordinates are in paint recording space. If pixel canvas is enabled this
+// essentially becomes pixel coordinate space.
+class VIEWS_EXPORT PaintInfo {
+ public:
+  enum class ScaleType {
+    // Scale the recordings by the default dsf. Use this if you don't want any
+    // form of distortion during scaling.
+    kScaleToScaleFactor = 0,
+
+    // Scale the recordings based on the effective dsf. This may lead to minor
+    // distortion during scaling due to edge snapping.
+    kScaleToFit
+  };
+
+  // Instantiates a root PaintInfo. This should only be initialized at the Paint
+  // root, ie., a layer or the root of a widget.
+  static PaintInfo CreateRootPaintInfo(const ui::PaintContext& root_context,
+                                       const gfx::Size& size);
+
+  // Instantiate a child PaintInfo instance. All bounds for this object are
+  // relative to its root PaintInfo.
+  static PaintInfo CreateChildPaintInfo(const PaintInfo& parent_paint_info,
+                                        const gfx::Rect& bounds,
+                                        const gfx::Size& parent_size,
+                                        ScaleType scale_type);
+
+  // Clones a given paint info, |other|, without the invalidation from its
+  // PaintContext.
+  static PaintInfo ClonePaintInfo(const PaintInfo& other);
+
+  PaintInfo(const PaintInfo& other);
+  ~PaintInfo();
+
+  // Returns true if all paint commands are recorded at pixel size.
+  bool IsPixelCanvas() const;
+
+  const ui::PaintContext& context() const {
+    return root_context_ ? *root_context_ : context_;
+  }
+
+  gfx::Vector2d offset_from_root() const {
+    return paint_recording_bounds_.OffsetFromOrigin();
+  }
+
+  const gfx::Vector2d& offset_from_parent() const {
+    return offset_from_parent_;
+  }
+
+  float paint_recording_scale_x() const { return paint_recording_scale_x_; }
+
+  float paint_recording_scale_y() const { return paint_recording_scale_y_; }
+
+  const gfx::Size& paint_recording_size() const {
+    return paint_recording_bounds_.size();
+  }
+
+  const gfx::Rect& paint_recording_bounds() const {
+    return paint_recording_bounds_;
+  }
+
+ private:
+  friend class PaintInfoTest;
+
+  PaintInfo(const ui::PaintContext& root_context, const gfx::Size& size);
+  PaintInfo(const PaintInfo& parent_paint_info,
+            const gfx::Rect& bounds,
+            const gfx::Size& parent_size,
+            ScaleType scale_type);
+  PaintInfo(const PaintInfo& other,
+            ui::PaintContext::CloneWithoutInvalidation c);
+
+  // Scales the |child_bounds| to its recording bounds based on the
+  // |context.device_scale_factor()|. The recording bounds are snapped to the
+  // parent's right and/or bottom edge if required.
+  // If pixel canvas is disabled, this function returns |child_bounds| as is.
+  gfx::Rect GetSnappedRecordingBounds(const gfx::Size& parent_size,
+                                      const gfx::Rect& child_bounds) const;
+
+  // The scale at which the paint commands are recorded at. Due to the decimal
+  // rounding and snapping to edges during the scale operation, the effective
+  // paint recording scale may end up being slightly different between the x and
+  // y axis.
+  float paint_recording_scale_x_;
+  float paint_recording_scale_y_;
+
+  // Paint Recording bounds of the view. The offset is relative to the root
+  // PaintInfo.
+  const gfx::Rect paint_recording_bounds_;
+
+  // Offset relative to the parent view's paint recording bounds. Returns 0
+  // offset if this is the root.
+  gfx::Vector2d offset_from_parent_;
+
+  // Compositor PaintContext associated with the view this object belongs to.
+  ui::PaintContext context_;
+  const ui::PaintContext* root_context_;
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_PAINT_INFO_H_
diff --git a/ui/views/paint_info_unittest.cc b/ui/views/paint_info_unittest.cc
new file mode 100644
index 0000000..6b4d4e6
--- /dev/null
+++ b/ui/views/paint_info_unittest.cc
@@ -0,0 +1,246 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/paint_info.h"
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "cc/base/region.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/compositor/paint_context.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace views {
+namespace {
+
+using PaintInfos = std::vector<std::unique_ptr<PaintInfo>>;
+
+// Device scale factors
+constexpr float DSF100 = 1.f;
+constexpr float DSF125 = 1.25f;
+constexpr float DSF150 = 1.5f;
+constexpr float DSF160 = 1.6f;
+constexpr float DSF166 = 1.66f;
+
+const std::vector<float> kDsfList = {DSF100, DSF125, DSF150, DSF160, DSF166};
+
+constexpr gfx::Size kLayerSize(123, 456);
+
+//  ___________
+// |     1     |
+// |___________|
+// | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5)
+// |___|___|___|
+// |   7   | 8 | <-- 6 (encapsulates 7 and 8)
+// |_______|___|
+//
+// |r_0| encapsulates 1, 2 and 6.
+const gfx::Rect r_0(kLayerSize);
+
+constexpr gfx::Rect r_1(0, 0, 123, 152);
+
+constexpr gfx::Rect r_2(0, 152, 123, 152);
+constexpr gfx::Rect r_3(0, 0, 41, 152);
+constexpr gfx::Rect r_4(41, 0, 41, 152);
+constexpr gfx::Rect r_5(82, 0, 41, 152);
+
+constexpr gfx::Rect r_6(0, 304, 123, 152);
+constexpr gfx::Rect r_7(0, 0, 82, 152);
+constexpr gfx::Rect r_8(82, 0, 41, 152);
+
+// Verifies that the child recording bounds completely cover the parent
+// recording bounds.
+void VerifyChildBoundsCoversParent(const PaintInfo* parent_paint_info,
+                                   const std::vector<PaintInfo*>& info_list) {
+  cc::Region remaining(gfx::Rect(parent_paint_info->paint_recording_size()));
+  int times_empty = 0;
+  for (auto* const paint_info : info_list) {
+    const gfx::Rect& child_recording_bounds =
+        paint_info->paint_recording_bounds() -
+        parent_paint_info->paint_recording_bounds().OffsetFromOrigin();
+    EXPECT_TRUE(remaining.Contains(child_recording_bounds))
+        << "Remaining: " << remaining.ToString()
+        << " paint recording bounds: " << child_recording_bounds.ToString();
+    remaining.Subtract(child_recording_bounds);
+    times_empty += remaining.IsEmpty();
+  }
+  EXPECT_EQ(times_empty, 1);
+}
+
+void VerifyPixelCanvasCornerScaling(const PaintInfos& info_list) {
+  // child 1, child 2 and child 6 should completely cover child 0.
+  std::vector<PaintInfo*> child_info_list;
+  child_info_list.push_back(info_list[1].get());
+  child_info_list.push_back(info_list[2].get());
+  child_info_list.push_back(info_list[6].get());
+  VerifyChildBoundsCoversParent(info_list[0].get(), child_info_list);
+  child_info_list.clear();
+
+  // Child 3,4 and 5 should completely cover child 2.
+  child_info_list.push_back(info_list[3].get());
+  child_info_list.push_back(info_list[4].get());
+  child_info_list.push_back(info_list[5].get());
+  VerifyChildBoundsCoversParent(info_list[2].get(), child_info_list);
+  child_info_list.clear();
+
+  // Child 7 and 8 should completely cover child 6.
+  child_info_list.push_back(info_list[7].get());
+  child_info_list.push_back(info_list[8].get());
+  VerifyChildBoundsCoversParent(info_list[6].get(), child_info_list);
+  child_info_list.clear();
+}
+
+void VerifyPixelSizesAreSameAsDIPSize(const PaintInfos& info_list) {
+  EXPECT_EQ(info_list[0]->paint_recording_size(), r_0.size());
+
+  EXPECT_EQ(info_list[1]->paint_recording_size(), r_1.size());
+
+  EXPECT_EQ(info_list[2]->paint_recording_size(), r_2.size());
+  EXPECT_EQ(info_list[3]->paint_recording_size(), r_3.size());
+  EXPECT_EQ(info_list[4]->paint_recording_size(), r_4.size());
+  EXPECT_EQ(info_list[5]->paint_recording_size(), r_5.size());
+
+  EXPECT_EQ(info_list[6]->paint_recording_size(), r_6.size());
+  EXPECT_EQ(info_list[7]->paint_recording_size(), r_7.size());
+  EXPECT_EQ(info_list[8]->paint_recording_size(), r_8.size());
+}
+
+}  // namespace
+
+class PaintInfoTest : public ::testing::Test {
+ public:
+  PaintInfoTest() {}
+
+  ~PaintInfoTest() override {}
+
+  //  ___________
+  // |     1     |
+  // |___________|
+  // | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5)
+  // |___|___|___|
+  // |   7   | 8 | <-- 6 (encapsulates 7 and 8)
+  // |_______|___|
+  //
+  // |r_0| encapsulates 1, 2 and 6.
+  //
+  // Returns the following arrangement of paint recording bounds for the given
+  // |dsf|
+  PaintInfos GetPaintInfoSetup(const ui::PaintContext& context) {
+    PaintInfos info_list(9);
+
+    info_list[0].reset(new PaintInfo(context, kLayerSize));
+
+    info_list[1].reset(new PaintInfo(*info_list[0], r_1, r_0.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+
+    info_list[2].reset(new PaintInfo(*info_list[0], r_2, r_0.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+    info_list[3].reset(new PaintInfo(*info_list[2], r_3, r_2.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+    info_list[4].reset(new PaintInfo(*info_list[2], r_4, r_2.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+    info_list[5].reset(new PaintInfo(*info_list[2], r_5, r_2.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+
+    info_list[6].reset(new PaintInfo(*info_list[0], r_6, r_0.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+    info_list[7].reset(new PaintInfo(*info_list[6], r_7, r_6.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+    info_list[8].reset(new PaintInfo(*info_list[6], r_8, r_6.size(),
+                                     PaintInfo::ScaleType::kScaleToFit));
+
+    return info_list;
+  }
+
+  void VerifyInvalidationRects(float dsf, bool pixel_canvas_enabled) {
+    std::vector<gfx::Rect> invalidation_rects = {
+        gfx::Rect(0, 0, 123, 41),     // Intersects with 0 & 1.
+        gfx::Rect(0, 76, 60, 152),    // Intersects 0, 1, 2, 3 & 4.
+        gfx::Rect(41, 152, 41, 152),  // Intersects with 0, 2 & 4.
+        gfx::Rect(80, 320, 4, 4),     // Intersects with 0, 6, 7 & 8.
+        gfx::Rect(40, 151, 43, 154),  // Intersects all
+        gfx::Rect(82, 304, 1, 1),     // Intersects with 0, 6 & 8.
+        gfx::Rect(81, 303, 2, 2)      // Intersects with 0, 2, 4, 5, 6, 7, 8
+    };
+
+    std::vector<std::vector<int>> repaint_indices = {
+        std::vector<int>{0, 1},
+        std::vector<int>{0, 1, 2, 3, 4},
+        std::vector<int>{0, 2, 4},
+        std::vector<int>{0, 6, 7, 8},
+        std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8},
+        std::vector<int>{0, 6, 8},
+        std::vector<int>{0, 2, 4, 5, 6, 7, 8}};
+
+    PaintInfos info_list;
+
+    EXPECT_EQ(repaint_indices.size(), invalidation_rects.size());
+    for (size_t i = 0; i < invalidation_rects.size(); i++) {
+      ui::PaintContext context(nullptr, dsf, invalidation_rects[i],
+                               pixel_canvas_enabled);
+      info_list = GetPaintInfoSetup(context);
+      for (size_t j = 0; j < repaint_indices[i].size(); j++) {
+        EXPECT_TRUE(
+            info_list[repaint_indices[i][j]]->context().IsRectInvalid(gfx::Rect(
+                info_list[repaint_indices[i][j]]->paint_recording_size())));
+      }
+      info_list.clear();
+    }
+  }
+};
+
+TEST_F(PaintInfoTest, CornerScalingPixelCanvasEnabled) {
+  PaintInfos info_list;
+  for (float dsf : kDsfList) {
+    ui::PaintContext context(nullptr, dsf, gfx::Rect(), true);
+    info_list = GetPaintInfoSetup(context);
+    VerifyPixelCanvasCornerScaling(info_list);
+    info_list.clear();
+  }
+
+  // More accurate testing for 1.25 dsf
+  ui::PaintContext context(nullptr, DSF125, gfx::Rect(), true);
+  info_list = GetPaintInfoSetup(context);
+  VerifyPixelCanvasCornerScaling(info_list);
+  EXPECT_EQ(info_list[0]->paint_recording_size(), gfx::Size(154, 570));
+
+  EXPECT_EQ(info_list[1]->paint_recording_size(), gfx::Size(154, 190));
+
+  EXPECT_EQ(info_list[2]->paint_recording_bounds(),
+            gfx::Rect(0, 190, 154, 190));
+  EXPECT_EQ(info_list[3]->paint_recording_size(), gfx::Size(51, 190));
+  EXPECT_EQ(info_list[4]->paint_recording_bounds(),
+            gfx::Rect(51, 190, 52, 190));
+  EXPECT_EQ(info_list[5]->paint_recording_bounds(),
+            gfx::Rect(103, 190, 51, 190));
+
+  EXPECT_EQ(info_list[6]->paint_recording_bounds(),
+            gfx::Rect(0, 380, 154, 190));
+  EXPECT_EQ(info_list[7]->paint_recording_size(), gfx::Size(103, 190));
+  EXPECT_EQ(info_list[8]->paint_recording_bounds(),
+            gfx::Rect(103, 380, 51, 190));
+}
+
+TEST_F(PaintInfoTest, ScalingWithPixelCanvasDisabled) {
+  for (float dsf : kDsfList) {
+    ui::PaintContext context(nullptr, dsf, gfx::Rect(), false);
+    PaintInfos info_list = GetPaintInfoSetup(context);
+    VerifyPixelCanvasCornerScaling(info_list);
+    VerifyPixelSizesAreSameAsDIPSize(info_list);
+    info_list.clear();
+  }
+}
+
+TEST_F(PaintInfoTest, Invalidation) {
+  for (float dsf : kDsfList) {
+    VerifyInvalidationRects(dsf, false);
+    VerifyInvalidationRects(dsf, true);
+  }
+}
+
+}  // namespace views
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 7738915..72cdf76 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -845,36 +845,46 @@
   }
 }
 
-void View::Paint(const ui::PaintContext& parent_context) {
+void View::Paint(const PaintInfo& parent_paint_info) {
   if (!ShouldPaint())
     return;
 
-  ui::PaintContext context(parent_context, GetPaintContextOffset());
+  const gfx::Rect& parent_bounds = !parent()
+                                       ? GetPaintRecordingBounds()
+                                       : parent()->GetPaintRecordingBounds();
 
+  PaintInfo paint_info = PaintInfo::CreateChildPaintInfo(
+      parent_paint_info, GetPaintRecordingBounds(), parent_bounds.size(),
+      GetPaintScaleType());
+
+  const ui::PaintContext& context = paint_info.context();
   bool is_invalidated = true;
-  if (context.CanCheckInvalid()) {
+  if (paint_info.context().CanCheckInvalid()) {
 #if DCHECK_IS_ON()
-    gfx::Vector2d offset;
-    context.Visited(this);
-    View* view = this;
-    while (view->parent() && !view->layer()) {
-      DCHECK(view->GetTransform().IsIdentity());
-      offset += view->GetMirroredPosition().OffsetFromOrigin();
-      view = view->parent();
+    if (!context.is_pixel_canvas()) {
+      gfx::Vector2d offset;
+      context.Visited(this);
+      View* view = this;
+      while (view->parent() && !view->layer()) {
+        DCHECK(view->GetTransform().IsIdentity());
+        offset += view->GetMirroredPosition().OffsetFromOrigin();
+        view = view->parent();
+      }
+      // The offset in the PaintContext should be the offset up to the paint
+      // root, which we compute and verify here.
+      DCHECK_EQ(context.PaintOffset().x(), offset.x());
+      DCHECK_EQ(context.PaintOffset().y(), offset.y());
+      // The above loop will stop when |view| is the paint root, which should be
+      // the root of the current paint walk, as verified by storing the root in
+      // the PaintContext.
+      DCHECK_EQ(context.RootVisited(), view);
     }
-    // The offset in the PaintContext should be the offset up to the paint root,
-    // which we compute and verify here.
-    DCHECK_EQ(context.PaintOffset().x(), offset.x());
-    DCHECK_EQ(context.PaintOffset().y(), offset.y());
-    // The above loop will stop when |view| is the paint root, which should be
-    // the root of the current paint walk, as verified by storing the root in
-    // the PaintContext.
-    DCHECK_EQ(context.RootVisited(), view);
 #endif
 
     // If the View wasn't invalidated, don't waste time painting it, the output
     // would be culled.
-    is_invalidated = context.IsRectInvalid(GetLocalBounds());
+    is_invalidated =
+        context.IsRectInvalid(gfx::Rect(paint_info.paint_recording_size()));
   }
 
   TRACE_EVENT1("views", "View::Paint", "class", GetClassName());
@@ -883,29 +893,44 @@
   // rather than relative to its parent.
   // TODO(danakj): Rework clip and transform recorder usage here to use
   // std::optional once we can do so.
-  ui::ClipRecorder clip_recorder(parent_context);
+  ui::ClipRecorder clip_recorder(parent_paint_info.context());
   if (!layer()) {
     // Set the clip rect to the bounds of this View, or |clip_path_| if it's
     // been set. Note that the X (or left) position we pass to ClipRect takes
     // into consideration whether or not the View uses a right-to-left layout so
     // that we paint the View in its mirrored position if need be.
     if (clip_path_.isEmpty()) {
-      clip_recorder.ClipRect(GetMirroredBounds());
+      clip_recorder.ClipRect(gfx::Rect(paint_info.paint_recording_size()) +
+                             paint_info.offset_from_parent());
     } else {
       gfx::Path clip_path_in_parent = clip_path_;
-      clip_path_in_parent.offset(GetMirroredX(), y());
+
+      // Transform |clip_path_| from local space to parent recording space.
+      gfx::Transform to_parent_recording_space;
+
+      to_parent_recording_space.Scale(
+          SkFloatToScalar(paint_info.paint_recording_scale_x()),
+          SkFloatToScalar(paint_info.paint_recording_scale_y()));
+      to_parent_recording_space.Translate(paint_info.offset_from_parent());
+
+      clip_path_in_parent.transform(to_parent_recording_space.matrix());
       clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent);
     }
   }
 
   ui::TransformRecorder transform_recorder(context);
-  SetupTransformRecorderForPainting(&transform_recorder);
+  SetupTransformRecorderForPainting(paint_info.offset_from_parent(),
+                                    &transform_recorder);
 
   // Note that the cache is not aware of the offset of the view
   // relative to the parent since painting is always done relative to
   // the top left of the individual view.
-  if (is_invalidated || !paint_cache_.UseCache(context, size())) {
-    ui::PaintRecorder recorder(context, size(), &paint_cache_);
+  if (is_invalidated ||
+      !paint_cache_.UseCache(context, paint_info.paint_recording_size())) {
+    ui::PaintRecorder recorder(context, paint_info.paint_recording_size(),
+                               paint_info.paint_recording_scale_x(),
+                               paint_info.paint_recording_scale_y(),
+                               &paint_cache_);
     gfx::Canvas* canvas = recorder.canvas();
     gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width(),
                                            flip_canvas_on_paint_for_rtl_ui_);
@@ -915,7 +940,7 @@
   }
 
   // View::Paint() recursion over the subtree.
-  PaintChildren(context);
+  PaintChildren(paint_info);
 }
 
 void View::SetBackground(std::unique_ptr<Background> b) {
@@ -1543,9 +1568,9 @@
 
 // Painting --------------------------------------------------------------------
 
-void View::PaintChildren(const ui::PaintContext& context) {
+void View::PaintChildren(const PaintInfo& paint_info) {
   TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName());
-  RecursivePaintHelper(&View::Paint, context);
+  RecursivePaintHelper(&View::Paint, paint_info);
 }
 
 void View::OnPaint(gfx::Canvas* canvas) {
@@ -1817,6 +1842,10 @@
   return kDefaultVerticalDragThreshold;
 }
 
+PaintInfo::ScaleType View::GetPaintScaleType() const {
+  return PaintInfo::ScaleType::kScaleToFit;
+}
+
 // Debugging -------------------------------------------------------------------
 
 #if !defined(NDEBUG)
@@ -1969,14 +1998,16 @@
   return visible_ && !size().IsEmpty();
 }
 
-gfx::Vector2d View::GetPaintContextOffset() const {
-  // If the View has a layer() then it is a paint root. Otherwise, we need to
-  // add the offset from the parent into the total offset from the paint root.
+gfx::Rect View::GetPaintRecordingBounds() const {
+  // If the View has a layer() then it is a paint root and no offset information
+  // is needed. Otherwise, we need bounds that includes an offset from the
+  // parent to add to the total offset from the paint root.
   DCHECK(layer() || parent() || origin() == gfx::Point());
-  return layer() ? gfx::Vector2d() : GetMirroredPosition().OffsetFromOrigin();
+  return layer() ? GetLocalBounds() : GetMirroredBounds();
 }
 
 void View::SetupTransformRecorderForPainting(
+    const gfx::Vector2d& offset_from_parent,
     ui::TransformRecorder* recorder) const {
   // If the view is backed by a layer, it should paint with itself as the origin
   // rather than relative to its parent.
@@ -1986,42 +2017,54 @@
   // Translate the graphics such that 0,0 corresponds to where this View is
   // located relative to its parent.
   gfx::Transform transform_from_parent;
-  gfx::Vector2d offset_from_parent = GetMirroredPosition().OffsetFromOrigin();
   transform_from_parent.Translate(offset_from_parent.x(),
                                   offset_from_parent.y());
-  transform_from_parent.PreconcatTransform(GetTransform());
   recorder->Transform(transform_from_parent);
 }
 
-void View::RecursivePaintHelper(void (View::*func)(const ui::PaintContext&),
-                                const ui::PaintContext& context) {
+void View::RecursivePaintHelper(void (View::*func)(const PaintInfo&),
+                                const PaintInfo& info) {
   View::Views children = GetChildrenInZOrder();
   DCHECK_EQ(child_count(), static_cast<int>(children.size()));
   for (auto* child : children) {
     if (!child->layer())
-      (child->*func)(context);
+      (child->*func)(info);
   }
 }
 
 void View::PaintFromPaintRoot(const ui::PaintContext& parent_context) {
-  Paint(parent_context);
+  PaintInfo paint_info = PaintInfo::CreateRootPaintInfo(
+      parent_context, layer() ? layer()->size() : size());
+  Paint(paint_info);
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDrawViewBoundsRects))
-    PaintDebugRects(parent_context);
+    PaintDebugRects(paint_info);
 }
 
-void View::PaintDebugRects(const ui::PaintContext& parent_context) {
+void View::PaintDebugRects(const PaintInfo& parent_paint_info) {
   if (!ShouldPaint())
     return;
 
-  ui::PaintContext context(parent_context, GetPaintContextOffset());
-  ui::TransformRecorder transform_recorder(context);
-  SetupTransformRecorderForPainting(&transform_recorder);
+  const gfx::Rect& parent_bounds = (layer() || !parent())
+                                       ? GetPaintRecordingBounds()
+                                       : parent()->GetPaintRecordingBounds();
+  PaintInfo paint_info = PaintInfo::CreateChildPaintInfo(
+      parent_paint_info, GetPaintRecordingBounds(), parent_bounds.size(),
+      GetPaintScaleType());
 
-  RecursivePaintHelper(&View::PaintDebugRects, context);
+  const ui::PaintContext& context = paint_info.context();
+
+  ui::TransformRecorder transform_recorder(context);
+  SetupTransformRecorderForPainting(paint_info.offset_from_parent(),
+                                    &transform_recorder);
+
+  RecursivePaintHelper(&View::PaintDebugRects, paint_info);
 
   // Draw outline rects for debugging.
-  ui::PaintRecorder recorder(context, size());
+  ui::PaintRecorder recorder(context, paint_info.paint_recording_size(),
+                             paint_info.paint_recording_scale_x(),
+                             paint_info.paint_recording_scale_y(),
+                             &paint_cache_);
   gfx::Canvas* canvas = recorder.canvas();
   const float scale = canvas->UndoDeviceScaleFactor();
   gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale));
diff --git a/ui/views/view.h b/ui/views/view.h
index 120cb40..5f6f8335 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -37,6 +37,7 @@
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/path.h"
+#include "ui/views/paint_info.h"
 #include "ui/views/view_targeter.h"
 #include "ui/views/views_export.h"
 
@@ -543,7 +544,7 @@
   // for View coordinates and language direction as required, allows the View
   // to paint itself via the various OnPaint*() event handlers and then paints
   // the hierarchy beneath it.
-  void Paint(const ui::PaintContext& parent_context);
+  void Paint(const PaintInfo& parent_paint_info);
 
   // The background object may be null.
   void SetBackground(std::unique_ptr<Background> b);
@@ -1152,7 +1153,7 @@
 
   // Responsible for calling Paint() on child Views. Override to control the
   // order child Views are painted.
-  virtual void PaintChildren(const ui::PaintContext& context);
+  virtual void PaintChildren(const PaintInfo& info);
 
   // Override to provide rendering in any part of the View's bounds. Typically
   // this is the "contents" of the view. If you override this method you will
@@ -1167,6 +1168,13 @@
   // Override to paint a border not specified by SetBorder().
   virtual void OnPaintBorder(gfx::Canvas* canvas);
 
+  // Returns the type of scaling to be done for this View. Override this to
+  // change the default scaling type from |kScaleToFit|. You would want to
+  // override this for a view and return |kScaleToScaleFactor| in cases where
+  // scaling should cause no distortion. Such as in the case of an image or
+  // an icon.
+  virtual PaintInfo::ScaleType GetPaintScaleType() const;
+
   // Accelerated painting ------------------------------------------------------
 
   // Returns the offset from this view to the nearest ancestor with a layer. If
@@ -1291,6 +1299,10 @@
   friend class ViewLayerTest;
   friend class Widget;
 
+  FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithMovedViewUsesCache);
+  FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithMovedViewUsesCacheInRTL);
+  FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithUnknownInvalidation);
+
   // Painting  -----------------------------------------------------------------
 
   enum SchedulePaintType {
@@ -1314,17 +1326,19 @@
   // during painting.
   bool ShouldPaint() const;
 
-  // Returns the offset that should be used when constructing the paint context
+  // Returns the bounds that should be used when constructing the |PaintInfo|
   // for this view.
-  gfx::Vector2d GetPaintContextOffset() const;
+  gfx::Rect GetPaintRecordingBounds() const;
 
   // Adjusts the transform of |recorder| in advance of painting.
-  void SetupTransformRecorderForPainting(ui::TransformRecorder* recorder) const;
+  void SetupTransformRecorderForPainting(
+      const gfx::Vector2d& offset_from_parent,
+      ui::TransformRecorder* recorder) const;
 
   // Recursively calls the painting method |func| on all non-layered children,
   // in Z order.
-  void RecursivePaintHelper(void (View::*func)(const ui::PaintContext&),
-                            const ui::PaintContext& context);
+  void RecursivePaintHelper(void (View::*func)(const PaintInfo&),
+                            const PaintInfo& info);
 
   // Invokes Paint() and, if necessary, PaintDebugRects().  Should be called
   // only on the root of a widget/layer.  PaintDebugRects() is invoked as a
@@ -1335,7 +1349,7 @@
   // Draws a semitransparent rect to indicate the bounds of this view.
   // Recursively does the same for all children.  Invoked only with
   // --draw-view-bounds-rects.
-  void PaintDebugRects(const ui::PaintContext& parent_context);
+  void PaintDebugRects(const PaintInfo& paint_info);
 
   // Tree operations -----------------------------------------------------------
 
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index 1dbb59e..d1eb371 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -40,6 +40,7 @@
 #include "ui/views/controls/native/native_view_host.h"
 #include "ui/views/controls/scroll_view.h"
 #include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/paint_info.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/view_observer.h"
 #include "ui/views/widget/native_widget.h"
@@ -527,7 +528,9 @@
   // Paint "everything".
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      first_paint.size()));
 
   // The empty view has nothing to paint so it doesn't try build a cache, nor do
   // its children which would be clipped by its (empty) self.
@@ -548,8 +551,8 @@
   gfx::Rect pixel_rect = gfx::Rect(1, 1);
   float device_scale_factor = 1.f;
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
   EXPECT_TRUE(v1->did_paint_);
   v1->Reset();
   // The visual rects for (clip, drawing, transform) should be in layer space.
@@ -564,15 +567,15 @@
 
   // If invalidation doesn't intersect v1, we paint with the cache.
   list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
   EXPECT_FALSE(v1->did_paint_);
   v1->Reset();
 
   // If invalidation does intersect v1, we don't paint with the cache.
   list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, v1->bounds()));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, v1->bounds(), false));
   EXPECT_TRUE(v1->did_paint_);
   v1->Reset();
 
@@ -580,8 +583,8 @@
   // intersect v1.
   list = base::MakeRefCounted<cc::DisplayItemList>();
   v1->SetX(9);
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
   EXPECT_FALSE(v1->did_paint_);
   v1->Reset();
   item_index = 3;
@@ -597,8 +600,8 @@
   // invalidation.
   list = base::MakeRefCounted<cc::DisplayItemList>();
   v1->SetX(8);
-  root_view->Paint(ui::PaintContext(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect),
+  root_view->PaintFromPaintRoot(ui::PaintContext(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false),
       ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
   EXPECT_TRUE(v1->did_paint_);
   v1->Reset();
@@ -625,8 +628,8 @@
   gfx::Rect pixel_rect = gfx::Rect(1, 1);
   float device_scale_factor = 1.f;
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
   EXPECT_TRUE(v1->did_paint_);
   v1->Reset();
   // The visual rects for (clip, drawing, transform) should be in layer space.
@@ -642,15 +645,15 @@
 
   // If invalidation doesn't intersect v1, we paint with the cache.
   list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
   EXPECT_FALSE(v1->did_paint_);
   v1->Reset();
 
   // If invalidation does intersect v1, we don't paint with the cache.
   list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, v1->bounds()));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, v1->bounds(), false));
   EXPECT_TRUE(v1->did_paint_);
   v1->Reset();
 
@@ -658,8 +661,8 @@
   // intersect v1.
   list = base::MakeRefCounted<cc::DisplayItemList>();
   v1->SetX(9);
-  root_view->Paint(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
   EXPECT_FALSE(v1->did_paint_);
   v1->Reset();
   item_index = 3;
@@ -676,8 +679,8 @@
   // invalidation.
   list = base::MakeRefCounted<cc::DisplayItemList>();
   v1->SetX(8);
-  root_view->Paint(ui::PaintContext(
-      ui::PaintContext(list.get(), device_scale_factor, pixel_rect),
+  root_view->PaintFromPaintRoot(ui::PaintContext(
+      ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false),
       ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
   EXPECT_TRUE(v1->did_paint_);
   v1->Reset();
@@ -708,7 +711,8 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), 1.f, first_paint, false));
   v1->Reset();
   v2->Reset();
 
@@ -719,13 +723,14 @@
   // With a known invalidation, v1 and v2 are not painted.
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(list.get(), 1.f, paint_area, false));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 
   // With unknown invalidation, v1 and v2 are painted.
-  root_view->Paint(
-      ui::PaintContext(ui::PaintContext(list.get(), 1.f, paint_area),
+  root_view->PaintFromPaintRoot(
+      ui::PaintContext(ui::PaintContext(list.get(), 1.f, paint_area, false),
                        ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
@@ -747,7 +752,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -757,7 +764,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -790,7 +798,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -800,7 +810,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -821,7 +832,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -831,7 +844,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -864,7 +878,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -874,7 +890,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -895,7 +912,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -905,7 +924,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -938,7 +958,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -948,7 +970,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -969,7 +992,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -979,7 +1004,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -1012,7 +1038,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -1022,7 +1050,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -1043,7 +1072,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -1054,7 +1085,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 
@@ -1065,7 +1097,8 @@
   v2->Reset();
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 }
@@ -1098,7 +1131,9 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false),
+      root_view->size()));
   v1->Reset();
   v2->Reset();
 
@@ -1109,7 +1144,8 @@
 
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_TRUE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
 
@@ -1120,7 +1156,8 @@
   v2->Reset();
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_FALSE(v2->did_paint_);
-  root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+  root_view->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
   EXPECT_FALSE(v1->did_paint_);
   EXPECT_TRUE(v2->did_paint_);
 }
@@ -1142,7 +1179,8 @@
   // invalidation.
   gfx::Rect first_paint(1, 1);
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  v1->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+  v1->Paint(PaintInfo::CreateRootPaintInfo(
+      ui::PaintContext(list.get(), 1.f, first_paint, false), v1->size()));
   v1->Reset();
   v2->Reset();
 
@@ -1152,7 +1190,9 @@
     auto list = base::MakeRefCounted<cc::DisplayItemList>();
 
     // The promoted views are not painted as they are separate paint roots.
-    root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+    root_view->Paint(PaintInfo::CreateRootPaintInfo(
+        ui::PaintContext(list.get(), 1.f, paint_area, false),
+        root_view->size()));
     EXPECT_FALSE(v1->did_paint_);
     EXPECT_FALSE(v2->did_paint_);
   }
@@ -1164,7 +1204,8 @@
 
     // The |v1| view is painted. If it used its offset incorrect, it would think
     // its at (10,11) instead of at (0,0) since it is the paint root.
-    v1->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+    v1->Paint(PaintInfo::CreateRootPaintInfo(
+        ui::PaintContext(list.get(), 1.f, paint_area, false), v1->size()));
     EXPECT_TRUE(v1->did_paint_);
     EXPECT_FALSE(v2->did_paint_);
   }
@@ -1178,7 +1219,8 @@
 
     // The |v2| view is painted also. If it used its offset incorrect, it would
     // think its at (13,15) instead of at (3,4) since |v1| is the paint root.
-    v1->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+    v1->Paint(PaintInfo::CreateRootPaintInfo(
+        ui::PaintContext(list.get(), 1.f, paint_area, false), v1->size()));
     EXPECT_TRUE(v1->did_paint_);
     EXPECT_TRUE(v2->did_paint_);
   }
@@ -1221,9 +1263,9 @@
   EXPECT_EQ(gfx::Rect(0, 1000, 100, 100), v1->GetVisibleBounds());
 
   auto list = base::MakeRefCounted<cc::DisplayItemList>();
-  ui::PaintContext context(list.get(), 1.f, gfx::Rect());
+  ui::PaintContext context(list.get(), 1.f, gfx::Rect(), false);
 
-  v1->Paint(context);
+  v1->Paint(PaintInfo::CreateRootPaintInfo(context, gfx::Size()));
   EXPECT_TRUE(v1->did_paint_);
 
   // Check that the canvas produced by |v1| for paint contains all of |v1|'s