diff --git a/DEPS b/DEPS
index 567719e..837e66f 100644
--- a/DEPS
+++ b/DEPS
@@ -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': '7ef761733d291aabe77a456fe91083a966aa3caa',
+  'catapult_revision': '1b305da0d509f4122732296a8581fd8ff48dc4c7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/ash/touch/touch_uma.cc b/ash/touch/touch_uma.cc
index 7ca2f5f..c3f66dac 100644
--- a/ash/touch/touch_uma.cc
+++ b/ash/touch/touch_uma.cc
@@ -24,14 +24,6 @@
 namespace {
 
 struct WindowTouchDetails {
-  // Move and start times of the touch points. The key is the touch-id.
-  std::map<int, base::TimeTicks> last_move_time_;
-  std::map<int, base::TimeTicks> last_start_time_;
-
-  // The first and last positions of the touch points.
-  std::map<int, gfx::Point> start_touch_position_;
-  std::map<int, gfx::Point> last_touch_position_;
-
   // Last time-stamp of the last touch-end event.
   base::TimeTicks last_release_time_;
 
@@ -86,8 +78,6 @@
                                 event.pointer_details().radius_y)),
       1, 500, 100);
 
-  UpdateTouchState(event);
-
   WindowTouchDetails* details = target->GetProperty(kWindowTouchDetails);
   if (!details) {
     details = new WindowTouchDetails;
@@ -122,14 +112,9 @@
       "Ash.TouchPositionY", position.y() / bucket_size_y, 1,
       kBucketCountForLocation, kBucketCountForLocation + 1);
 
-  const int touch_pointer_id = event.pointer_details().id;
   if (event.type() == ui::ET_TOUCH_PRESSED) {
     WmShell::Get()->RecordUserMetricsAction(UMA_TOUCHSCREEN_TAP_DOWN);
 
-    details->last_start_time_[touch_pointer_id] = event.time_stamp();
-    details->start_touch_position_[touch_pointer_id] = event.root_location();
-    details->last_touch_position_[touch_pointer_id] = event.location();
-
     if (details->last_release_time_.ToInternalValue()) {
       // Measuring the interval between a touch-release and the next
       // touch-start is probably less useful when doing multi-touch (e.g.
@@ -142,89 +127,15 @@
                                    gap.InMilliseconds());
       }
     }
-
-    // Record the number of touch-points currently active for the window.
-    const int kMaxTouchPoints = 10;
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.ActiveTouchPoints",
-                                details->last_start_time_.size(), 1,
-                                kMaxTouchPoints, kMaxTouchPoints + 1);
   } else if (event.type() == ui::ET_TOUCH_RELEASED) {
-    if (details->last_start_time_.count(touch_pointer_id)) {
-      base::TimeDelta duration =
-          event.time_stamp() - details->last_start_time_[touch_pointer_id];
-      // Look for touches that were [almost] stationary for a long time.
-      const double kLongStationaryTouchDuration = 10;
-      const int kLongStationaryTouchDistanceSquared = 100;
-      if (duration.InSecondsF() > kLongStationaryTouchDuration) {
-        gfx::Vector2d distance =
-            event.root_location() -
-            details->start_touch_position_[touch_pointer_id];
-        if (distance.LengthSquared() < kLongStationaryTouchDistanceSquared) {
-          UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.StationaryTouchDuration",
-                                      duration.InSeconds(),
-                                      kLongStationaryTouchDuration, 1000, 20);
-        }
-      }
-    }
-    details->last_start_time_.erase(touch_pointer_id);
-    details->last_move_time_.erase(touch_pointer_id);
-    details->start_touch_position_.erase(touch_pointer_id);
-    details->last_touch_position_.erase(touch_pointer_id);
     details->last_release_time_ = event.time_stamp();
-  } else if (event.type() == ui::ET_TOUCH_MOVED) {
-    int distance = 0;
-    if (details->last_touch_position_.count(touch_pointer_id)) {
-      gfx::Point lastpos = details->last_touch_position_[touch_pointer_id];
-      distance =
-          std::abs(lastpos.x() - event.x()) + std::abs(lastpos.y() - event.y());
-    }
-
-    if (details->last_move_time_.count(touch_pointer_id)) {
-      base::TimeDelta move_delay =
-          event.time_stamp() - details->last_move_time_[touch_pointer_id];
-      UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchMoveInterval",
-                                  move_delay.InMilliseconds(), 1, 50, 25);
-    }
-
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchMoveSteps", distance, 1, 1000, 50);
-
-    details->last_move_time_[touch_pointer_id] = event.time_stamp();
-    details->last_touch_position_[touch_pointer_id] = event.location();
   }
 }
 
-TouchUMA::TouchUMA()
-    : is_single_finger_gesture_(false),
-      touch_in_progress_(false),
-      burst_length_(0) {}
+TouchUMA::TouchUMA() {}
 
 TouchUMA::~TouchUMA() {}
 
-void TouchUMA::UpdateTouchState(const ui::TouchEvent& event) {
-  if (event.type() == ui::ET_TOUCH_PRESSED) {
-    if (!touch_in_progress_) {
-      is_single_finger_gesture_ = true;
-      base::TimeDelta difference = event.time_stamp() - last_touch_down_time_;
-      if (difference > base::TimeDelta::FromMilliseconds(250)) {
-        if (burst_length_) {
-          UMA_HISTOGRAM_COUNTS_100("Ash.TouchStartBurst",
-                                   std::min(burst_length_, 100));
-        }
-        burst_length_ = 1;
-      } else {
-        ++burst_length_;
-      }
-    } else {
-      is_single_finger_gesture_ = false;
-    }
-    touch_in_progress_ = true;
-    last_touch_down_time_ = event.time_stamp();
-  } else if (event.type() == ui::ET_TOUCH_RELEASED) {
-    if (!aura::Env::GetInstance()->is_touch_down())
-      touch_in_progress_ = false;
-  }
-}
-
 GestureActionType TouchUMA::FindGestureActionType(
     aura::Window* window,
     const ui::GestureEvent& event) {
diff --git a/ash/touch/touch_uma.h b/ash/touch/touch_uma.h
index c9bdd8b..480cb3de 100644
--- a/ash/touch/touch_uma.h
+++ b/ash/touch/touch_uma.h
@@ -22,7 +22,7 @@
 namespace ash {
 
 // Records some touch/gesture event specific details (e.g. what gestures are
-// targetted to which components etc.)
+// targeted to which components etc.)
 class ASH_EXPORT TouchUMA {
  public:
   // Returns the singleton instance.
@@ -38,15 +38,9 @@
   TouchUMA();
   ~TouchUMA();
 
-  void UpdateTouchState(const ui::TouchEvent& event);
   GestureActionType FindGestureActionType(aura::Window* window,
                                           const ui::GestureEvent& event);
 
-  bool is_single_finger_gesture_;
-  // These are used to measure the number of touch-start events we receive in a
-  // quick succession, regardless of the target window.
-  bool touch_in_progress_;
-  int burst_length_;
   base::TimeTicks last_touch_down_time_;
 
   DISALLOW_COPY_AND_ASSIGN(TouchUMA);
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h
index b740e66..42e97e4 100644
--- a/cc/ipc/cc_param_traits_macros.h
+++ b/cc/ipc/cc_param_traits_macros.h
@@ -197,6 +197,7 @@
   IPC_STRUCT_TRAITS_MEMBER(selection)
   IPC_STRUCT_TRAITS_MEMBER(latency_info)
   IPC_STRUCT_TRAITS_MEMBER(referenced_surfaces)
+  IPC_STRUCT_TRAITS_MEMBER(content_source_id)
 IPC_STRUCT_TRAITS_END()
 
 #endif  // CC_IPC_CC_PARAM_TRAITS_MACROS_H_
diff --git a/cc/ipc/compositor_frame_metadata.mojom b/cc/ipc/compositor_frame_metadata.mojom
index 2634925..74deb837 100644
--- a/cc/ipc/compositor_frame_metadata.mojom
+++ b/cc/ipc/compositor_frame_metadata.mojom
@@ -31,4 +31,5 @@
   array<ui.mojom.LatencyInfo> latency_info;
   array<SurfaceId> referenced_surfaces;
   bool can_activate_before_dependencies;
+  uint32 content_source_id;
 };
diff --git a/cc/ipc/compositor_frame_metadata_struct_traits.cc b/cc/ipc/compositor_frame_metadata_struct_traits.cc
index e64f6727..cdef417 100644
--- a/cc/ipc/compositor_frame_metadata_struct_traits.cc
+++ b/cc/ipc/compositor_frame_metadata_struct_traits.cc
@@ -36,6 +36,7 @@
   out->top_controls_shown_ratio = data.top_controls_shown_ratio();
   out->bottom_controls_height = data.bottom_controls_height();
   out->bottom_controls_shown_ratio = data.bottom_controls_shown_ratio();
+  out->content_source_id = data.content_source_id();
 
   out->root_background_color = data.root_background_color();
   out->can_activate_before_dependencies =
diff --git a/cc/ipc/compositor_frame_metadata_struct_traits.h b/cc/ipc/compositor_frame_metadata_struct_traits.h
index 381edb3f..c58ba45b 100644
--- a/cc/ipc/compositor_frame_metadata_struct_traits.h
+++ b/cc/ipc/compositor_frame_metadata_struct_traits.h
@@ -111,6 +111,11 @@
     return metadata.can_activate_before_dependencies;
   }
 
+  static uint32_t content_source_id(
+      const cc::CompositorFrameMetadata& metadata) {
+    return metadata.content_source_id;
+  }
+
   static bool Read(cc::mojom::CompositorFrameMetadataDataView data,
                    cc::CompositorFrameMetadata* out);
 };
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc
index 8088ac9..5647cb51 100644
--- a/cc/ipc/struct_traits_unittest.cc
+++ b/cc/ipc/struct_traits_unittest.cc
@@ -240,6 +240,7 @@
   const gfx::Vector2dF root_scroll_offset(1234.5f, 6789.1f);
   const float page_scale_factor = 1337.5f;
   const gfx::SizeF scrollable_viewport_size(1337.7f, 1234.5f);
+  const uint32_t content_source_id = 3;
 
   CompositorFrame input;
   input.metadata.device_scale_factor = device_scale_factor;
@@ -248,6 +249,7 @@
   input.metadata.scrollable_viewport_size = scrollable_viewport_size;
   input.render_pass_list.push_back(std::move(render_pass));
   input.resource_list.push_back(resource);
+  input.metadata.content_source_id = content_source_id;
 
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
   CompositorFrame output;
@@ -257,6 +259,7 @@
   EXPECT_EQ(root_scroll_offset, output.metadata.root_scroll_offset);
   EXPECT_EQ(page_scale_factor, output.metadata.page_scale_factor);
   EXPECT_EQ(scrollable_viewport_size, output.metadata.scrollable_viewport_size);
+  EXPECT_EQ(content_source_id, output.metadata.content_source_id);
 
   ASSERT_EQ(1u, output.resource_list.size());
   TransferableResource out_resource = output.resource_list[0];
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h
index e383e50..59023b43 100644
--- a/cc/output/compositor_frame_metadata.h
+++ b/cc/output/compositor_frame_metadata.h
@@ -82,6 +82,12 @@
   // dependencies have been resolved.
   bool can_activate_before_dependencies = true;
 
+  // This is a value that allows the browser to associate compositor frames
+  // with the content that they represent -- typically top-level page loads.
+  // TODO(kenrb, fsamuel): This should eventually by SurfaceID, when they
+  // become available in all renderer processes. See https://crbug.com/695579.
+  uint32_t content_source_id;
+
  private:
   CompositorFrameMetadata(const CompositorFrameMetadata& other);
   CompositorFrameMetadata operator=(const CompositorFrameMetadata&) = delete;
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 59d711d1..32222128 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -1480,7 +1480,8 @@
 }
 
 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
-  gfx::Size viewport_size(1, 1);
+  gfx::Size viewport_size(30, 30);  // Don't translate out of the viewport.
+  gfx::Size quad_size(3, 3);
   int root_pass_id = 1;
   RenderPass* root_pass;
 
@@ -1491,7 +1492,7 @@
   root_pass = AddRenderPass(&render_passes_in_draw_order_, root_pass_id,
                             gfx::Rect(viewport_size), gfx::Transform(),
                             FilterOperations());
-  AddTransformedQuad(root_pass, gfx::Rect(viewport_size), SK_ColorYELLOW,
+  AddTransformedQuad(root_pass, gfx::Rect(quad_size), SK_ColorYELLOW,
                      pixel_aligned_transform_causing_aa);
 
   renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 4ad7918..942d593 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -104,6 +104,7 @@
       debug_state_(settings_.initial_debug_state),
       id_(s_layer_tree_host_sequence_number.GetNext() + 1),
       task_graph_runner_(params->task_graph_runner),
+      content_source_id_(0),
       event_listener_properties_(),
       mutator_host_(params->mutator_host) {
   DCHECK(task_graph_runner_);
@@ -972,6 +973,13 @@
       this, [](Layer* layer) { layer->SetNeedsDisplay(); });
 }
 
+void LayerTreeHost::SetContentSourceId(uint32_t id) {
+  if (content_source_id_ == id)
+    return;
+  content_source_id_ = id;
+  SetNeedsCommit();
+}
+
 void LayerTreeHost::RegisterLayer(Layer* layer) {
   DCHECK(!LayerById(layer->id()));
   DCHECK(!in_paint_layer_contents_);
@@ -1142,6 +1150,8 @@
 
   tree_impl->SetDeviceColorSpace(device_color_space_);
 
+  tree_impl->set_content_source_id(content_source_id_);
+
   if (pending_page_scale_animation_) {
     tree_impl->SetPendingPageScaleAnimation(
         std::move(pending_page_scale_animation_));
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 809ffb6..9a5deabf 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -309,6 +309,9 @@
     return painted_device_scale_factor_;
   }
 
+  void SetContentSourceId(uint32_t);
+  uint32_t content_source_id() const { return content_source_id_; }
+
   void SetDeviceColorSpace(const gfx::ColorSpace& device_color_space);
   const gfx::ColorSpace& device_color_space() const {
     return device_color_space_;
@@ -570,6 +573,8 @@
   float max_page_scale_factor_ = 1.f;
   gfx::ColorSpace device_color_space_;
 
+  uint32_t content_source_id_;
+
   SkColor background_color_ = SK_ColorWHITE;
   bool has_transparent_background_ = false;
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 26208cb4..15d72e6e 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1581,6 +1581,7 @@
   metadata.bottom_controls_shown_ratio =
       browser_controls_offset_manager_->BottomControlsShownRatio();
   metadata.root_background_color = active_tree_->background_color();
+  metadata.content_source_id = active_tree_->content_source_id();
 
   active_tree_->GetViewportSelection(&metadata.selection);
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index eaf3c475..1f2059cb 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -7010,5 +7010,32 @@
 
 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSubmitFrameResources);
 
+// Ensure that content_source_id is propagated to the frame's metadata.
+class LayerTreeHostTestContentSourceId : public LayerTreeHostTest {
+ protected:
+  void BeginTest() override {
+    layer_tree_host()->SetContentSourceId(5);
+    PostSetNeedsCommitToMainThread();
+  }
+
+  DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+                                   LayerTreeHostImpl::FrameData* frame_data,
+                                   DrawResult draw_result) override {
+    EXPECT_EQ(DRAW_SUCCESS, draw_result);
+    EXPECT_EQ(5U, host_impl->active_tree()->content_source_id());
+    return draw_result;
+  }
+
+  void DisplayReceivedCompositorFrameOnThread(
+      const CompositorFrame& frame) override {
+    EXPECT_EQ(5U, frame.metadata.content_source_id);
+    EndTest();
+  }
+
+  void AfterTest() override {}
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContentSourceId);
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 9096698..f694b09 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -73,6 +73,7 @@
       max_page_scale_factor_(0),
       device_scale_factor_(1.f),
       painted_device_scale_factor_(1.f),
+      content_source_id_(0),
       elastic_overscroll_(elastic_overscroll),
       layers_(new OwnedLayerImplList),
       viewport_size_invalid_(false),
@@ -487,6 +488,8 @@
   target_tree->SetDeviceColorSpace(device_color_space_);
   target_tree->elastic_overscroll()->PushPendingToActive();
 
+  target_tree->set_content_source_id(content_source_id());
+
   target_tree->pending_page_scale_animation_ =
       std::move(pending_page_scale_animation_);
 
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 09cd850f..02c6e99 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -229,6 +229,9 @@
     return painted_device_scale_factor_;
   }
 
+  void set_content_source_id(uint32_t id) { content_source_id_ = id; }
+  uint32_t content_source_id() { return content_source_id_; }
+
   void SetDeviceColorSpace(const gfx::ColorSpace& device_color_space);
   const gfx::ColorSpace& device_color_space() const {
     return device_color_space_;
@@ -495,6 +498,8 @@
   float painted_device_scale_factor_;
   gfx::ColorSpace device_color_space_;
 
+  uint32_t content_source_id_;
+
   scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_;
 
   std::unique_ptr<OwnedLayerImplList> layers_;
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 299a156..746d757b 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -584,6 +584,12 @@
             android:excludeFromRecents="true">
         </activity>
 
+        <activity android:name="org.chromium.chrome.browser.childaccounts.ResetDataActivity"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar"
+            android:exported="true"
+            android:excludeFromRecents="true">
+        </activity>
+
         <!-- This activity is used to restart the main Chrome process.  Should never be exported. -->
         <activity android:name="org.chromium.chrome.browser.BrowserRestartActivity"
             android:launchMode="singleInstance"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java
new file mode 100644
index 0000000..0de3a79
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java
@@ -0,0 +1,79 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.childaccounts;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+
+import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
+
+/**
+ * An activity that allows whitelisted applications to reset all data in Chrome, as part of
+ * child account management.
+ */
+public class ResetDataActivity extends Activity {
+    /**
+     * The calling activity is not authorized. This activity is only available to Google-signed
+     * applications.
+     */
+    private static final int RESULT_ERROR_UNAUTHORIZED = Activity.RESULT_FIRST_USER;
+
+    /**
+     * Resetting data is not supported.
+     */
+    private static final int RESULT_ERROR_NOT_SUPPORTED = Activity.RESULT_FIRST_USER + 1;
+
+    /**
+     * There was an error resetting data.
+     */
+    private static final int RESULT_ERROR_COULD_NOT_RESET_DATA = Activity.RESULT_FIRST_USER + 2;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (!authenticateSender()) {
+            returnResult(RESULT_ERROR_UNAUTHORIZED);
+            return;
+        }
+
+        // If resetting data is not supported, immediately return an error.
+        if (!supportsResetData()) {
+            returnResult(RESULT_ERROR_NOT_SUPPORTED);
+            return;
+        }
+
+        boolean success = resetData();
+
+        // We should only land here if resetting data was not successful, as otherwise the process
+        // will be killed.
+        assert !success;
+        returnResult(RESULT_ERROR_COULD_NOT_RESET_DATA);
+    }
+
+    private boolean authenticateSender() {
+        return ExternalAuthUtils.getInstance().isGoogleSigned(this, getCallingPackage());
+    }
+
+    private boolean supportsResetData() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+    }
+
+    @TargetApi(Build.VERSION_CODES.KITKAT)
+    private boolean resetData() {
+        assert supportsResetData();
+        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+        return am.clearApplicationUserData();
+    }
+
+    private void returnResult(int resultCode) {
+        setResult(resultCode);
+        finish();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index c566a2a..453e85c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -540,6 +540,9 @@
             }
         }
 
+        // Update snap scrolling for the fakebox.
+        mRecyclerView.setContainsLocationBar(mManager.isLocationBarShownInNTP());
+
         updateTileGridPlaceholderVisibility();
 
         onUrlFocusAnimationChanged();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java
index cafe093..9e9c8cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java
@@ -14,7 +14,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.chrome.browser.childaccounts.ChildAccountService;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.signin.AccountManagerHelper;
 import org.chromium.components.signin.ChromeSigninController;
@@ -146,11 +145,9 @@
         }
         String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope;
 
-        boolean handleUserRecoverableErrors = ChildAccountService.isChildAccount();
-
         AccountManagerHelper accountManagerHelper = AccountManagerHelper.get(context);
-        accountManagerHelper.getAuthToken(account, oauth2Scope, handleUserRecoverableErrors,
-                new AccountManagerHelper.GetAuthTokenCallback() {
+        accountManagerHelper.getAuthToken(
+                account, oauth2Scope, new AccountManagerHelper.GetAuthTokenCallback() {
                     @Override
                     public void tokenAvailable(String token) {
                         nativeOAuth2TokenFetched(token, false, nativeCallback);
@@ -173,9 +170,7 @@
     public static void getOAuth2AccessToken(Context context, Account account, String scope,
             AccountManagerHelper.GetAuthTokenCallback callback) {
         String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope;
-        boolean handleUserRecoverableErrors = ChildAccountService.isChildAccount();
-        AccountManagerHelper.get(context).getAuthToken(
-                account, oauth2Scope, handleUserRecoverableErrors, callback);
+        AccountManagerHelper.get(context).getAuthToken(account, oauth2Scope, callback);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
index 9313d08..594b8f45 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -174,6 +174,11 @@
                 protected void onPostExecute(Void result) {
                     String renamedAccount = getNewSignedInAccountName(mContext);
                     if (renamedAccount == null) {
+                        // SigninManager.signOut() uses the same code path as a user-triggered
+                        // signout, which can be prohibited in some cases (e.g. child accounts).
+                        // Here we have to sign out though to ensure account consistency,
+                        // so override the flag.
+                        mSigninManager.prohibitSignout(false);
                         mSigninManager.signOut();
                     } else {
                         validateAccountSettings(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index 15d00d2..623205c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -560,6 +560,10 @@
         nativeClearLastSignedInUser(mNativeSigninManagerAndroid);
     }
 
+    public void prohibitSignout(boolean prohibitSignout) {
+        nativeProhibitSignout(mNativeSigninManagerAndroid, prohibitSignout);
+    }
+
     /**
      * Aborts the current sign in.
      *
@@ -685,4 +689,6 @@
     private native void nativeClearLastSignedInUser(long nativeSigninManagerAndroid);
     private native void nativeLogInSignedInUser(long nativeSigninManagerAndroid);
     private native boolean nativeIsSignedInOnNative(long nativeSigninManagerAndroid);
+    private native void nativeProhibitSignout(
+            long nativeSigninManagerAndroid, boolean prohibitSignout);
 }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 27084cd..2a4d2fbd 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -126,6 +126,7 @@
   "java/src/org/chromium/chrome/browser/childaccounts/ChildAccountFeedbackReporter.java",
   "java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java",
   "java/src/org/chromium/chrome/browser/childaccounts/ExternalFeedbackReporter.java",
+  "java/src/org/chromium/chrome/browser/childaccounts/ResetDataActivity.java",
   "java/src/org/chromium/chrome/browser/compositor/CompositorView.java",
   "java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java",
   "java/src/org/chromium/chrome/browser/compositor/Invalidator.java",
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index b8d4da8..ff3571d6 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -164,6 +164,8 @@
 
 void SigninManagerAndroid::SignOut(JNIEnv* env,
                                    const JavaParamRef<jobject>& obj) {
+  // TODO(bauerb): This is not only called for a user-triggered signout.
+  // We should pass the reason in here from Java.
   SigninManagerFactory::GetForProfile(profile_)
       ->SignOut(signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS,
                 signin_metrics::SignoutDelete::IGNORE_METRIC);
@@ -284,6 +286,13 @@
   return SigninManagerFactory::GetForProfile(profile_)->IsAuthenticated();
 }
 
+void SigninManagerAndroid::ProhibitSignout(JNIEnv* env,
+                                           const JavaParamRef<jobject>& obj,
+                                           jboolean prohibit_signout) {
+  SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(
+      prohibit_signout);
+}
+
 void SigninManagerAndroid::GoogleSigninFailed(
     const GoogleServiceAuthError& error) {}
 
diff --git a/chrome/browser/android/signin/signin_manager_android.h b/chrome/browser/android/signin/signin_manager_android.h
index ea7f1ecd..7bf556b 100644
--- a/chrome/browser/android/signin/signin_manager_android.h
+++ b/chrome/browser/android/signin/signin_manager_android.h
@@ -78,6 +78,10 @@
   jboolean IsSignedInOnNative(JNIEnv* env,
                               const base::android::JavaParamRef<jobject>& obj);
 
+  void ProhibitSignout(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj,
+                       jboolean prohibit_signout);
+
   // SigninManagerBase::Observer implementation.
   void GoogleSigninFailed(const GoogleServiceAuthError& error) override;
   void GoogleSigninSucceeded(const std::string& account_id,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
index 8264bcad..6c8b936 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.cc
@@ -16,7 +16,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h"
-#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "url/gurl.h"
 
@@ -75,6 +74,9 @@
 
 ArcDocumentsProviderRoot::~ArcDocumentsProviderRoot() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (observer_wrapper_)
+    file_system_operation_runner_util::RemoveObserverOnIOThread(
+        std::move(observer_wrapper_));
 }
 
 void ArcDocumentsProviderRoot::GetFileInfo(
@@ -95,6 +97,44 @@
                        weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
+void ArcDocumentsProviderRoot::AddWatcher(
+    const base::FilePath& path,
+    const WatcherCallback& watcher_callback,
+    const StatusCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (path_to_watcher_id_.count(path)) {
+    callback.Run(base::File::FILE_ERROR_FAILED);
+    return;
+  }
+  ResolveToDocumentId(
+      path,
+      base::Bind(&ArcDocumentsProviderRoot::AddWatcherWithDocumentId,
+                 weak_ptr_factory_.GetWeakPtr(), path, watcher_callback,
+                 callback));
+}
+
+void ArcDocumentsProviderRoot::RemoveWatcher(const base::FilePath& path,
+                                             const StatusCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  auto iter = path_to_watcher_id_.find(path);
+  if (iter == path_to_watcher_id_.end()) {
+    callback.Run(base::File::FILE_ERROR_FAILED);
+    return;
+  }
+  int64_t watcher_id = iter->second;
+  path_to_watcher_id_.erase(iter);
+  if (watcher_id < 0) {
+    // This is an orphan watcher. Just remove an entry from
+    // |path_to_watcher_id_| and return success.
+    callback.Run(base::File::FILE_OK);
+    return;
+  }
+  file_system_operation_runner_util::RemoveWatcherOnIOThread(
+      watcher_id,
+      base::Bind(&ArcDocumentsProviderRoot::OnWatcherRemoved,
+                 weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
 void ArcDocumentsProviderRoot::ResolveToContentUrl(
     const base::FilePath& path,
     const ResolveToContentUrlCallback& callback) {
@@ -105,9 +145,17 @@
                  weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
+void ArcDocumentsProviderRoot::OnWatchersCleared() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  // Mark all watchers orphan.
+  for (auto& entry : path_to_watcher_id_)
+    entry.second = -1;
+}
+
 void ArcDocumentsProviderRoot::GetFileInfoWithDocumentId(
     const GetFileInfoCallback& callback,
     const std::string& document_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (document_id.empty()) {
     callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info());
     return;
@@ -182,6 +230,62 @@
   callback.Run(base::File::FILE_OK, entry_list, false /* has_more */);
 }
 
+void ArcDocumentsProviderRoot::AddWatcherWithDocumentId(
+    const base::FilePath& path,
+    const WatcherCallback& watcher_callback,
+    const StatusCallback& callback,
+    const std::string& document_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (document_id.empty()) {
+    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    return;
+  }
+  // Start observing ArcFileSystemOperationRunner if we have not.
+  if (!observer_wrapper_) {
+    observer_wrapper_ =
+        new file_system_operation_runner_util::ObserverIOThreadWrapper(this);
+    file_system_operation_runner_util::AddObserverOnIOThread(observer_wrapper_);
+  }
+  file_system_operation_runner_util::AddWatcherOnIOThread(
+      authority_, document_id, watcher_callback,
+      base::Bind(&ArcDocumentsProviderRoot::OnWatcherAdded,
+                 weak_ptr_factory_.GetWeakPtr(), path, callback));
+}
+
+void ArcDocumentsProviderRoot::OnWatcherAdded(const base::FilePath& path,
+                                              const StatusCallback& callback,
+                                              int64_t watcher_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (watcher_id < 0) {
+    callback.Run(base::File::FILE_ERROR_FAILED);
+    return;
+  }
+  if (path_to_watcher_id_.count(path)) {
+    // Multiple watchers have been installed on the same file path in a race.
+    // Following the contract of WatcherManager, we reject all except the first.
+    file_system_operation_runner_util::RemoveWatcherOnIOThread(
+        watcher_id,
+        base::Bind(&ArcDocumentsProviderRoot::OnWatcherAddedButRemoved,
+                   weak_ptr_factory_.GetWeakPtr(), callback));
+    return;
+  }
+  path_to_watcher_id_.insert(std::make_pair(path, watcher_id));
+  callback.Run(base::File::FILE_OK);
+}
+
+void ArcDocumentsProviderRoot::OnWatcherAddedButRemoved(
+    const StatusCallback& callback,
+    bool success) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  callback.Run(base::File::FILE_ERROR_FAILED);
+}
+
+void ArcDocumentsProviderRoot::OnWatcherRemoved(const StatusCallback& callback,
+                                                bool success) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  callback.Run(success ? base::File::FILE_OK : base::File::FILE_ERROR_FAILED);
+}
+
 void ArcDocumentsProviderRoot::ResolveToContentUrlWithDocumentId(
     const ResolveToContentUrlCallback& callback,
     const std::string& document_id) {
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h
index fd8f880..d2afb37 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_
 #define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_ROOT_H_
 
+#include <stdint.h>
+
 #include <map>
 #include <string>
 #include <vector>
@@ -12,10 +14,14 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h"
 #include "components/arc/common/file_system.mojom.h"
 #include "storage/browser/fileapi/async_file_util.h"
+#include "storage/browser/fileapi/watcher_manager.h"
 
 class GURL;
 
@@ -26,16 +32,19 @@
 // All methods must be called on the IO thread.
 // If this object is deleted while there are in-flight operations, callbacks
 // for those operations will be never called.
-class ArcDocumentsProviderRoot {
+class ArcDocumentsProviderRoot : public ArcFileSystemOperationRunner::Observer {
  public:
   using GetFileInfoCallback = storage::AsyncFileUtil::GetFileInfoCallback;
   using ReadDirectoryCallback = storage::AsyncFileUtil::ReadDirectoryCallback;
+  using ChangeType = storage::WatcherManager::ChangeType;
+  using WatcherCallback = base::Callback<void(ChangeType type)>;
+  using StatusCallback = base::Callback<void(base::File::Error error)>;
   using ResolveToContentUrlCallback =
       base::Callback<void(const GURL& content_url)>;
 
   ArcDocumentsProviderRoot(const std::string& authority,
                            const std::string& root_document_id);
-  ~ArcDocumentsProviderRoot();
+  ~ArcDocumentsProviderRoot() override;
 
   // Queries information of a file just like AsyncFileUtil.GetFileInfo().
   void GetFileInfo(const base::FilePath& path,
@@ -46,6 +55,56 @@
   void ReadDirectory(const base::FilePath& path,
                      const ReadDirectoryCallback& callback);
 
+  // Installs a document watcher.
+  //
+  // It is not allowed to install multiple watchers at the same file path;
+  // if attempted, duplicated requests will fail.
+  //
+  // Currently, watchers can be installed only on directories, and only
+  // directory content changes are notified. The result of installing a watcher
+  // to a non-directory in unspecified.
+  //
+  // NOTES ABOUT CORRECTNESS AND CONSISTENCY:
+  //
+  // Document watchers are not always correct and they may miss some updates or
+  // even notify incorrect update events for several reasons, such as:
+  //
+  //   - Directory moves: Currently a watcher will misbehave if the watched
+  //     directory is moved to another location. This is acceptable for now
+  //     since we whitelist MediaDocumentsProvider only.
+  //   - Duplicated file name handling in this class: The same reason as
+  //     directory moves. This may happen even with MediaDocumentsProvider,
+  //     but the chance will not be very high.
+  //   - File system operation races: For example, an watcher can be installed
+  //     to a non-directory in a race condition.
+  //   - Broken DocumentsProviders: For example, we get no notification if a
+  //     document provider does not call setNotificationUri().
+  //
+  // However, consistency of installed watchers is guaranteed. That is, after
+  // a watcher is installed on a file path X, an attempt to uninstall a watcher
+  // at X will always succeed.
+  //
+  // Unfortunately it is too difficult (or maybe theoretically impossible) to
+  // implement a perfect Android document watcher which never misses document
+  // updates. So the current implementation gives up correctness, but instead
+  // focuses on following two goals:
+  //
+  //   1. Keep the implementation simple, rather than trying hard to catch
+  //      race conditions or minor cases. Even if we return wrong results, the
+  //      worst consequence is just that users do not see the latest contents
+  //      until they refresh UI.
+  //
+  //   2. Keep consistency of installed watchers so that the caller can avoid
+  //      dangling watchers.
+  void AddWatcher(const base::FilePath& path,
+                  const WatcherCallback& watcher_callback,
+                  const StatusCallback& callback);
+
+  // Uninstalls a document watcher.
+  // See the documentation of AddWatcher() above.
+  void RemoveWatcher(const base::FilePath& path,
+                     const StatusCallback& callback);
+
   // Resolves a file path into a content:// URL pointing to the file
   // on DocumentsProvider. Returns URL that can be passed to
   // ArcContentFileSystemFileSystemReader to read the content.
@@ -53,6 +112,9 @@
   void ResolveToContentUrl(const base::FilePath& path,
                            const ResolveToContentUrlCallback& callback);
 
+  // ArcFileSystemOperationRunner::Observer overrides:
+  void OnWatchersCleared() override;
+
  private:
   // Thin representation of a document in documents provider.
   struct ThinDocument {
@@ -82,6 +144,17 @@
       base::File::Error error,
       NameToThinDocumentMap mapping);
 
+  void AddWatcherWithDocumentId(const base::FilePath& path,
+                                const WatcherCallback& watcher_callback,
+                                const StatusCallback& callback,
+                                const std::string& document_id);
+  void OnWatcherAdded(const base::FilePath& path,
+                      const StatusCallback& callback,
+                      int64_t watcher_id);
+  void OnWatcherAddedButRemoved(const StatusCallback& callback, bool success);
+
+  void OnWatcherRemoved(const StatusCallback& callback, bool success);
+
   void ResolveToContentUrlWithDocumentId(
       const ResolveToContentUrlCallback& callback,
       const std::string& document_id);
@@ -110,6 +183,25 @@
 
   const std::string authority_;
   const std::string root_document_id_;
+
+  // Map from a file path to a watcher ID.
+  //
+  // A watcher can be "orphan" when watchers are cleared as notified by
+  // OnWatchersCleared() callback. Such watchers are still tracked here,
+  // but they are not known by the remote service, so they are represented
+  // by the invalid watcher ID (-1).
+  //
+  // Note that we do not use a document ID as a key here to guarantee that
+  // a watch installed by AddWatcher() can be always identified in
+  // RemoveWatcher() with the same file path specified.
+  // See the documentation of AddWatcher() for more details.
+  std::map<base::FilePath, int64_t> path_to_watcher_id_;
+
+  // Can be null if this instance is not observing ArcFileSystemOperationRunner.
+  // Observation is started on the first call of AddWatcher().
+  scoped_refptr<file_system_operation_runner_util::ObserverIOThreadWrapper>
+      observer_wrapper_;
+
   base::WeakPtrFactory<ArcDocumentsProviderRoot> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderRoot);
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc
index 7919b209..df9f467 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc
@@ -16,12 +16,14 @@
 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
+#include "components/arc/common/file_system.mojom.h"
 #include "components/arc/test/fake_file_system_instance.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "storage/common/fileapi/directory_entry.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+using ChangeType = arc::ArcDocumentsProviderRoot::ChangeType;
 using storage::DirectoryEntry;
 using Document = arc::FakeFileSystemInstance::Document;
 using EntryList = storage::AsyncFileUtil::EntryList;
@@ -120,6 +122,10 @@
     arc_service_manager_->arc_bridge_service()->file_system()->SetInstance(
         &fake_file_system_);
 
+    // Run the message loop until FileSystemInstance::Init() is called.
+    base::RunLoop().RunUntilIdle();
+    ASSERT_TRUE(fake_file_system_.InitCalled());
+
     root_ = base::MakeUnique<ArcDocumentsProviderRoot>(kAuthority,
                                                        kRootSpec.document_id);
   }
@@ -287,6 +293,92 @@
   run_loop.Run();
 }
 
+TEST_F(ArcDocumentsProviderRootTest, WatchChanged) {
+  int num_called = 0;
+  auto watcher_callback = base::Bind(
+      [](int* num_called, ChangeType type) {
+        EXPECT_EQ(ChangeType::CHANGED, type);
+        ++(*num_called);
+      },
+      &num_called);
+
+  {
+    base::RunLoop run_loop;
+    root_->AddWatcher(base::FilePath(FILE_PATH_LITERAL("dir")),
+                      watcher_callback,
+                      base::Bind(
+                          [](base::RunLoop* run_loop, base::File::Error error) {
+                            EXPECT_EQ(base::File::FILE_OK, error);
+                            run_loop->Quit();
+                          },
+                          &run_loop));
+    run_loop.Run();
+  }
+
+  EXPECT_EQ(0, num_called);
+  fake_file_system_.TriggerWatchers(kAuthority, kDirSpec.document_id,
+                                    mojom::ChangeType::CHANGED);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1, num_called);
+
+  {
+    base::RunLoop run_loop;
+    root_->RemoveWatcher(
+        base::FilePath(FILE_PATH_LITERAL("dir")),
+        base::Bind(
+            [](base::RunLoop* run_loop, base::File::Error error) {
+              EXPECT_EQ(base::File::FILE_OK, error);
+              run_loop->Quit();
+            },
+            &run_loop));
+    run_loop.Run();
+  }
+}
+
+TEST_F(ArcDocumentsProviderRootTest, WatchDeleted) {
+  int num_called = 0;
+  auto watcher_callback = base::Bind(
+      [](int* num_called, ChangeType type) {
+        EXPECT_EQ(ChangeType::DELETED, type);
+        ++(*num_called);
+      },
+      &num_called);
+
+  {
+    base::RunLoop run_loop;
+    root_->AddWatcher(base::FilePath(FILE_PATH_LITERAL("dir")),
+                      watcher_callback,
+                      base::Bind(
+                          [](base::RunLoop* run_loop, base::File::Error error) {
+                            EXPECT_EQ(base::File::FILE_OK, error);
+                            run_loop->Quit();
+                          },
+                          &run_loop));
+    run_loop.Run();
+  }
+
+  EXPECT_EQ(0, num_called);
+  fake_file_system_.TriggerWatchers(kAuthority, kDirSpec.document_id,
+                                    mojom::ChangeType::DELETED);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1, num_called);
+
+  // Even if the watched file was deleted, the watcher is still alive and we
+  // should clean it up.
+  {
+    base::RunLoop run_loop;
+    root_->RemoveWatcher(
+        base::FilePath(FILE_PATH_LITERAL("dir")),
+        base::Bind(
+            [](base::RunLoop* run_loop, base::File::Error error) {
+              EXPECT_EQ(base::File::FILE_OK, error);
+              run_loop->Quit();
+            },
+            &run_loop));
+    run_loop.Run();
+  }
+}
+
 TEST_F(ArcDocumentsProviderRootTest, ResolveToContentUrl) {
   base::RunLoop run_loop;
   root_->ResolveToContentUrl(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
index 9e914c1..85c094ae 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
@@ -18,6 +20,23 @@
 
 namespace arc {
 
+namespace {
+
+// TODO(nya): Use typemaps.
+ArcFileSystemOperationRunner::ChangeType FromMojoChangeType(
+    mojom::ChangeType type) {
+  switch (type) {
+    case mojom::ChangeType::CHANGED:
+      return ArcFileSystemOperationRunner::ChangeType::CHANGED;
+    case mojom::ChangeType::DELETED:
+      return ArcFileSystemOperationRunner::ChangeType::DELETED;
+  }
+  NOTREACHED();
+  return ArcFileSystemOperationRunner::ChangeType::CHANGED;
+}
+
+}  // namespace
+
 // static
 const char ArcFileSystemOperationRunner::kArcServiceName[] =
     "arc::ArcFileSystemOperationRunner";
@@ -42,30 +61,46 @@
 ArcFileSystemOperationRunner::ArcFileSystemOperationRunner(
     ArcBridgeService* bridge_service,
     const Profile* profile,
-    bool observe_events)
+    bool set_should_defer_by_events)
     : ArcService(bridge_service),
       profile_(profile),
-      observe_events_(observe_events),
+      set_should_defer_by_events_(set_should_defer_by_events),
+      binding_(this),
       weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  if (observe_events_) {
-    ArcSessionManager::Get()->AddObserver(this);
-    arc_bridge_service()->file_system()->AddObserver(this);
-    OnStateChanged();
-  }
+  // We need to observe FileSystemInstance even in unit tests to call Init().
+  arc_bridge_service()->file_system()->AddObserver(this);
+
+  // ArcSessionManager may not exist in unit tests.
+  auto* arc_session_manager = ArcSessionManager::Get();
+  if (arc_session_manager)
+    arc_session_manager->AddObserver(this);
+
+  OnStateChanged();
 }
 
 ArcFileSystemOperationRunner::~ArcFileSystemOperationRunner() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  if (observe_events_) {
-    ArcSessionManager::Get()->RemoveObserver(this);
-    arc_bridge_service()->file_system()->RemoveObserver(this);
-  }
+  auto* arc_session_manager = ArcSessionManager::Get();
+  if (arc_session_manager)
+    arc_session_manager->RemoveObserver(this);
+
+  arc_bridge_service()->file_system()->RemoveObserver(this);
   // On destruction, deferred operations are discarded.
 }
 
+void ArcFileSystemOperationRunner::AddObserver(Observer* observer) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  observer_list_.AddObserver(observer);
+}
+
+void ArcFileSystemOperationRunner::RemoveObserver(Observer* observer) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  observer_list_.RemoveObserver(observer);
+}
+
 void ArcFileSystemOperationRunner::GetFileSize(
     const GURL& url,
     const GetFileSizeCallback& callback) {
@@ -150,6 +185,78 @@
                                           callback);
 }
 
+void ArcFileSystemOperationRunner::AddWatcher(
+    const std::string& authority,
+    const std::string& document_id,
+    const WatcherCallback& watcher_callback,
+    const AddWatcherCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (should_defer_) {
+    deferred_operations_.emplace_back(
+        base::Bind(&ArcFileSystemOperationRunner::AddWatcher,
+                   weak_ptr_factory_.GetWeakPtr(), authority, document_id,
+                   watcher_callback, callback));
+    return;
+  }
+  auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
+      arc_bridge_service()->file_system(), AddWatcher);
+  if (!file_system_instance) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  base::Bind(callback, -1));
+    return;
+  }
+  file_system_instance->AddWatcher(
+      authority, document_id,
+      base::Bind(&ArcFileSystemOperationRunner::OnWatcherAdded,
+                 weak_ptr_factory_.GetWeakPtr(), watcher_callback, callback));
+}
+
+void ArcFileSystemOperationRunner::RemoveWatcher(
+    int64_t watcher_id,
+    const RemoveWatcherCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // RemoveWatcher() is never deferred since watchers do not persist across
+  // container reboots.
+  if (should_defer_) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  base::Bind(callback, false));
+    return;
+  }
+
+  // Unregister from |watcher_callbacks_| now because we will do it even if
+  // the remote method fails anyway. This is an implementation detail, so
+  // users must not assume registered callbacks are immediately invalidated.
+  auto iter = watcher_callbacks_.find(watcher_id);
+  if (iter == watcher_callbacks_.end()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  base::Bind(callback, false));
+    return;
+  }
+  watcher_callbacks_.erase(iter);
+
+  auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
+      arc_bridge_service()->file_system(), AddWatcher);
+  if (!file_system_instance) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  base::Bind(callback, false));
+    return;
+  }
+  file_system_instance->RemoveWatcher(watcher_id, callback);
+}
+
+void ArcFileSystemOperationRunner::OnDocumentChanged(int64_t watcher_id,
+                                                     mojom::ChangeType type) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto iter = watcher_callbacks_.find(watcher_id);
+  if (iter == watcher_callbacks_.end()) {
+    // This may happen in a race condition with documents changes and
+    // RemoveWatcher().
+    return;
+  }
+  WatcherCallback watcher_callback = iter->second;
+  watcher_callback.Run(FromMojoChangeType(type));
+}
+
 void ArcFileSystemOperationRunner::OnArcPlayStoreEnabledChanged(bool enabled) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   OnStateChanged();
@@ -157,18 +264,46 @@
 
 void ArcFileSystemOperationRunner::OnInstanceReady() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* file_system_instance =
+      ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service()->file_system(), Init);
+  if (file_system_instance)
+    file_system_instance->Init(binding_.CreateInterfacePtrAndBind());
   OnStateChanged();
 }
 
 void ArcFileSystemOperationRunner::OnInstanceClosed() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // ArcFileSystemService and watchers are gone.
+  watcher_callbacks_.clear();
+  for (auto& observer : observer_list_)
+    observer.OnWatchersCleared();
   OnStateChanged();
 }
 
+void ArcFileSystemOperationRunner::OnWatcherAdded(
+    const WatcherCallback& watcher_callback,
+    const AddWatcherCallback& callback,
+    int64_t watcher_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (watcher_id < 0) {
+    callback.Run(-1);
+    return;
+  }
+  if (watcher_callbacks_.count(watcher_id)) {
+    NOTREACHED();
+    callback.Run(-1);
+    return;
+  }
+  watcher_callbacks_.insert(std::make_pair(watcher_id, watcher_callback));
+  callback.Run(watcher_id);
+}
+
 void ArcFileSystemOperationRunner::OnStateChanged() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  SetShouldDefer(IsArcPlayStoreEnabledForProfile(profile_) &&
-                 !arc_bridge_service()->file_system()->has_instance());
+  if (set_should_defer_by_events_) {
+    SetShouldDefer(IsArcPlayStoreEnabledForProfile(profile_) &&
+                   !arc_bridge_service()->file_system()->has_instance());
+  }
 }
 
 void ArcFileSystemOperationRunner::SetShouldDefer(bool should_defer) {
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
index 65dcf5d..0e5bd29 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
@@ -5,6 +5,9 @@
 #ifndef CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_FILE_SYSTEM_OPERATION_RUNNER_H_
 #define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_FILE_SYSTEM_OPERATION_RUNNER_H_
 
+#include <stdint.h>
+
+#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -12,10 +15,13 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "components/arc/arc_service.h"
 #include "components/arc/common/file_system.mojom.h"
 #include "components/arc/instance_holder.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "storage/browser/fileapi/watcher_manager.h"
 
 namespace arc {
 
@@ -44,6 +50,7 @@
 // All member functions must be called on the UI thread.
 class ArcFileSystemOperationRunner
     : public ArcService,
+      public mojom::FileSystemHost,
       public ArcSessionManager::Observer,
       public InstanceHolder<mojom::FileSystemInstance>::Observer {
  public:
@@ -53,6 +60,22 @@
   using GetDocumentCallback = mojom::FileSystemInstance::GetDocumentCallback;
   using GetChildDocumentsCallback =
       mojom::FileSystemInstance::GetChildDocumentsCallback;
+  using AddWatcherCallback = base::Callback<void(int64_t watcher_id)>;
+  using RemoveWatcherCallback = base::Callback<void(bool success)>;
+  using ChangeType = storage::WatcherManager::ChangeType;
+  using WatcherCallback = base::Callback<void(ChangeType type)>;
+
+  class Observer {
+   public:
+    // Called when the installed watchers are invalidated.
+    // This can happen when Android system restarts, for example.
+    // After this event is fired, watcher IDs issued before the event can be
+    // reused.
+    virtual void OnWatchersCleared() = 0;
+
+   protected:
+    virtual ~Observer() = default;
+  };
 
   // For supporting ArcServiceManager::GetService<T>().
   static const char kArcServiceName[];
@@ -70,6 +93,10 @@
                                const Profile* profile);
   ~ArcFileSystemOperationRunner() override;
 
+  // Adds or removes observers.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
   // Runs file system operations. See file_system.mojom for documentation.
   void GetFileSize(const GURL& url, const GetFileSizeCallback& callback);
   void OpenFileToRead(const GURL& url, const OpenFileToReadCallback& callback);
@@ -79,6 +106,14 @@
   void GetChildDocuments(const std::string& authority,
                          const std::string& parent_document_id,
                          const GetChildDocumentsCallback& callback);
+  void AddWatcher(const std::string& authority,
+                  const std::string& document_id,
+                  const WatcherCallback& watcher_callback,
+                  const AddWatcherCallback& callback);
+  void RemoveWatcher(int64_t watcher_id, const RemoveWatcherCallback& callback);
+
+  // FileSystemHost overrides:
+  void OnDocumentChanged(int64_t watcher_id, mojom::ChangeType type) override;
 
   // ArcSessionManager::Observer overrides:
   void OnArcPlayStoreEnabledChanged(bool enabled) override;
@@ -92,7 +127,11 @@
 
   ArcFileSystemOperationRunner(ArcBridgeService* bridge_service,
                                const Profile* profile,
-                               bool observe_events);
+                               bool set_should_defer_by_events);
+
+  void OnWatcherAdded(const WatcherCallback& watcher_callback,
+                      const AddWatcherCallback& callback,
+                      int64_t watcher_id);
 
   // Called whenever ARC states related to |should_defer_| are changed.
   void OnStateChanged();
@@ -106,9 +145,9 @@
   // unit tests.
   const Profile* const profile_;
 
-  // Indicates if this instance should register observers to receive events.
+  // Indicates if this instance should enable/disable deferring by events.
   // Usually true, but set to false in unit tests.
-  const bool observe_events_;
+  bool set_should_defer_by_events_;
 
   // Set to true if operations should be deferred at this moment.
   // The default is set to false so that operations are not deferred in
@@ -118,6 +157,13 @@
   // List of deferred operations.
   std::vector<base::Closure> deferred_operations_;
 
+  // Map from a watcher ID to a watcher callback.
+  std::map<int64_t, WatcherCallback> watcher_callbacks_;
+
+  base::ObserverList<Observer> observer_list_;
+
+  mojo::Binding<mojom::FileSystemHost> binding_;
+
   base::WeakPtrFactory<ArcFileSystemOperationRunner> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcFileSystemOperationRunner);
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
index da694f0..0d04ab3 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
@@ -41,6 +41,11 @@
     arc_service_manager_->AddService(
         ArcFileSystemOperationRunner::CreateForTesting(
             arc_service_manager_->arc_bridge_service()));
+
+    // Run the message loop until FileSystemInstance::Init() is called.
+    base::RunLoop().RunUntilIdle();
+    ASSERT_TRUE(file_system_instance_.InitCalled());
+
     runner_ = arc_service_manager_->GetService<ArcFileSystemOperationRunner>();
   }
 
@@ -50,6 +55,41 @@
     runner_->SetShouldDefer(should_defer);
   }
 
+  // Calls all functions implemented by ArcFileSystemOperationRunner.
+  void CallAllFunctions(int* counter) {
+    // Following functions are deferred.
+    runner_->AddWatcher(
+        kAuthority, kDocumentId,
+        base::Bind([](ArcFileSystemOperationRunner::ChangeType type) {}),
+        base::Bind([](int* counter, int64_t watcher_id) { ++*counter; },
+                   counter));
+    runner_->GetChildDocuments(
+        kAuthority, kDocumentId,
+        base::Bind(
+            [](int* counter,
+               base::Optional<std::vector<mojom::DocumentPtr>> documents) {
+              ++*counter;
+            },
+            counter));
+    runner_->GetDocument(
+        kAuthority, kDocumentId,
+        base::Bind(
+            [](int* counter, mojom::DocumentPtr document) { ++*counter; },
+            counter));
+    runner_->GetFileSize(
+        GURL(kUrl),
+        base::Bind([](int* counter, int64_t size) { ++*counter; }, counter));
+    runner_->OpenFileToRead(
+        GURL(kUrl),
+        base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; },
+                   counter));
+
+    // RemoveWatcher() is never deferred.
+    runner_->RemoveWatcher(
+        123,
+        base::Bind([](int* counter, bool success) { ++*counter; }, counter));
+  }
+
   content::TestBrowserThreadBundle thread_bundle_;
   FakeFileSystemInstance file_system_instance_;
   std::unique_ptr<ArcServiceManager> arc_service_manager_;
@@ -63,87 +103,33 @@
 TEST_F(ArcFileSystemOperationRunnerTest, RunImmediately) {
   int counter = 0;
   CallSetShouldDefer(false);
-  runner_->GetChildDocuments(
-      kAuthority, kDocumentId,
-      base::Bind(
-          [](int* counter,
-             base::Optional<std::vector<mojom::DocumentPtr>> documents) {
-            ++*counter;
-          },
-          &counter));
-  runner_->GetDocument(
-      kAuthority, kDocumentId,
-      base::Bind([](int* counter, mojom::DocumentPtr document) { ++*counter; },
-                 &counter));
-  runner_->GetFileSize(
-      GURL(kUrl),
-      base::Bind([](int* counter, int64_t size) { ++*counter; }, &counter));
-  runner_->OpenFileToRead(
-      GURL(kUrl),
-      base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; },
-                 &counter));
+  CallAllFunctions(&counter);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(4, counter);
+  EXPECT_EQ(6, counter);
 }
 
 TEST_F(ArcFileSystemOperationRunnerTest, DeferAndRun) {
   int counter = 0;
   CallSetShouldDefer(true);
-  runner_->GetChildDocuments(
-      kAuthority, kDocumentId,
-      base::Bind(
-          [](int* counter,
-             base::Optional<std::vector<mojom::DocumentPtr>> documents) {
-            ++*counter;
-          },
-          &counter));
-  runner_->GetDocument(
-      kAuthority, kDocumentId,
-      base::Bind([](int* counter, mojom::DocumentPtr document) { ++*counter; },
-                 &counter));
-  runner_->GetFileSize(
-      GURL(kUrl),
-      base::Bind([](int* counter, int64_t size) { ++*counter; }, &counter));
-  runner_->OpenFileToRead(
-      GURL(kUrl),
-      base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; },
-                 &counter));
+  CallAllFunctions(&counter);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, counter);
+  EXPECT_EQ(1, counter);
 
   CallSetShouldDefer(false);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(4, counter);
+  EXPECT_EQ(6, counter);
 }
 
 TEST_F(ArcFileSystemOperationRunnerTest, DeferAndDiscard) {
   int counter = 0;
   CallSetShouldDefer(true);
-  runner_->GetChildDocuments(
-      kAuthority, kDocumentId,
-      base::Bind(
-          [](int* counter,
-             base::Optional<std::vector<mojom::DocumentPtr>> documents) {
-            ++*counter;
-          },
-          &counter));
-  runner_->GetDocument(
-      kAuthority, kDocumentId,
-      base::Bind([](int* counter, mojom::DocumentPtr document) { ++*counter; },
-                 &counter));
-  runner_->GetFileSize(
-      GURL(kUrl),
-      base::Bind([](int* counter, int64_t size) { ++*counter; }, &counter));
-  runner_->OpenFileToRead(
-      GURL(kUrl),
-      base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; },
-                 &counter));
+  CallAllFunctions(&counter);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, counter);
+  EXPECT_EQ(1, counter);
 
   arc_service_manager_.reset();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, counter);
+  EXPECT_EQ(1, counter);
 }
 
 TEST_F(ArcFileSystemOperationRunnerTest, FileInstanceUnavailable) {
@@ -152,27 +138,9 @@
 
   int counter = 0;
   CallSetShouldDefer(false);
-  runner_->GetChildDocuments(
-      kAuthority, kDocumentId,
-      base::Bind(
-          [](int* counter,
-             base::Optional<std::vector<mojom::DocumentPtr>> documents) {
-            ++*counter;
-          },
-          &counter));
-  runner_->GetDocument(
-      kAuthority, kDocumentId,
-      base::Bind([](int* counter, mojom::DocumentPtr document) { ++*counter; },
-                 &counter));
-  runner_->GetFileSize(
-      GURL(kUrl),
-      base::Bind([](int* counter, int64_t size) { ++*counter; }, &counter));
-  runner_->OpenFileToRead(
-      GURL(kUrl),
-      base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; },
-                 &counter));
+  CallAllFunctions(&counter);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(4, counter);
+  EXPECT_EQ(6, counter);
 }
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
index 8f6fd07..4cbb0b5 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
@@ -7,7 +7,6 @@
 #include <utility>
 #include <vector>
 
-#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
 #include "components/arc/arc_service_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "url/gurl.h"
@@ -34,8 +33,8 @@
   auto* runner =
       ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
   if (!runner) {
-    LOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
-               << "File system operations are dropped.";
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
     callback.Run(-1);
     return;
   }
@@ -48,8 +47,8 @@
   auto* runner =
       ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
   if (!runner) {
-    LOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
-               << "File system operations are dropped.";
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
     callback.Run(mojo::ScopedHandle());
     return;
   }
@@ -63,8 +62,8 @@
   auto* runner =
       ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
   if (!runner) {
-    LOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
-               << "File system operations are dropped.";
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
     callback.Run(mojom::DocumentPtr());
     return;
   }
@@ -78,16 +77,95 @@
   auto* runner =
       ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
   if (!runner) {
-    LOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
-               << "File system operations are dropped.";
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
     callback.Run(base::nullopt);
     return;
   }
   runner->GetChildDocuments(authority, parent_document_id, callback);
 }
 
+void AddWatcherOnUIThread(const std::string& authority,
+                          const std::string& document_id,
+                          const WatcherCallback& watcher_callback,
+                          const AddWatcherCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* runner =
+      ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
+  if (!runner) {
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
+    callback.Run(-1);
+    return;
+  }
+  runner->AddWatcher(authority, document_id, watcher_callback, callback);
+}
+
+void RemoveWatcherOnUIThread(int64_t watcher_id,
+                             const RemoveWatcherCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* runner =
+      ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
+  if (!runner) {
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
+    callback.Run(false);
+    return;
+  }
+  runner->RemoveWatcher(watcher_id, callback);
+}
+
+void AddObserverOnUIThread(scoped_refptr<ObserverIOThreadWrapper> observer) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* runner =
+      ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
+  if (!runner) {
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
+    return;
+  }
+  runner->AddObserver(observer.get());
+}
+
+void RemoveObserverOnUIThread(scoped_refptr<ObserverIOThreadWrapper> observer) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* runner =
+      ArcServiceManager::GetGlobalService<ArcFileSystemOperationRunner>();
+  if (!runner) {
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
+    return;
+  }
+  runner->RemoveObserver(observer.get());
+}
+
 }  // namespace
 
+ObserverIOThreadWrapper::ObserverIOThreadWrapper(
+    ArcFileSystemOperationRunner::Observer* underlying_observer)
+    : underlying_observer_(underlying_observer) {}
+
+ObserverIOThreadWrapper::~ObserverIOThreadWrapper() = default;
+
+void ObserverIOThreadWrapper::Disable() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  disabled_ = true;
+}
+
+void ObserverIOThreadWrapper::OnWatchersCleared() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&ObserverIOThreadWrapper::OnWatchersClearedOnIOThread, this));
+}
+
+void ObserverIOThreadWrapper::OnWatchersClearedOnIOThread() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (disabled_)
+    return;
+  underlying_observer_->OnWatchersCleared();
+}
+
 void GetFileSizeOnIOThread(const GURL& url,
                            const GetFileSizeCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -129,6 +207,44 @@
               callback)));
 }
 
+void AddWatcherOnIOThread(const std::string& authority,
+                          const std::string& document_id,
+                          const WatcherCallback& watcher_callback,
+                          const AddWatcherCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(
+          &AddWatcherOnUIThread, authority, document_id,
+          base::Bind(&PostToIOThread<ArcFileSystemOperationRunner::ChangeType>,
+                     watcher_callback),
+          base::Bind(&PostToIOThread<int64_t>, callback)));
+}
+
+void RemoveWatcherOnIOThread(int64_t watcher_id,
+                             const RemoveWatcherCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&RemoveWatcherOnUIThread, watcher_id,
+                 base::Bind(&PostToIOThread<bool>, callback)));
+}
+
+void AddObserverOnIOThread(scoped_refptr<ObserverIOThreadWrapper> observer) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(&AddObserverOnUIThread, observer));
+}
+
+void RemoveObserverOnIOThread(scoped_refptr<ObserverIOThreadWrapper> observer) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  // Disable the observer now to guarantee the underlying observer is never
+  // called after this function returns.
+  observer->Disable();
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(&RemoveObserverOnUIThread, observer));
+}
+
 }  // namespace file_system_operation_runner_util
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
index 98740fa..b21c3da 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
@@ -7,22 +7,62 @@
 
 #include <string>
 
-#include "components/arc/common/file_system.mojom.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
 
 class GURL;
 
 namespace arc {
+
 namespace file_system_operation_runner_util {
 
-using GetFileSizeCallback = mojom::FileSystemInstance::GetFileSizeCallback;
+using GetFileSizeCallback = ArcFileSystemOperationRunner::GetFileSizeCallback;
 using OpenFileToReadCallback =
-    mojom::FileSystemInstance::OpenFileToReadCallback;
-using GetDocumentCallback = mojom::FileSystemInstance::GetDocumentCallback;
+    ArcFileSystemOperationRunner::OpenFileToReadCallback;
+using GetDocumentCallback = ArcFileSystemOperationRunner::GetDocumentCallback;
 using GetChildDocumentsCallback =
-    mojom::FileSystemInstance::GetChildDocumentsCallback;
+    ArcFileSystemOperationRunner::GetChildDocumentsCallback;
+using AddWatcherCallback = ArcFileSystemOperationRunner::AddWatcherCallback;
+using RemoveWatcherCallback =
+    ArcFileSystemOperationRunner::RemoveWatcherCallback;
+using WatcherCallback = ArcFileSystemOperationRunner::WatcherCallback;
+
+// Wraps an ArcFileSystemOperationRunner::Observer so it is called on the IO
+// thread.
+class ObserverIOThreadWrapper
+    : public base::RefCountedThreadSafe<ObserverIOThreadWrapper>,
+      public ArcFileSystemOperationRunner::Observer {
+ public:
+  explicit ObserverIOThreadWrapper(
+      ArcFileSystemOperationRunner::Observer* underlying_observer);
+
+  // Disables the observer. After calling this function, the underlying observer
+  // will never be called.
+  // This function should be called on the IO thread.
+  void Disable();
+
+  // ArcFileSystemOperationRunner::Observer overrides:
+  void OnWatchersCleared() override;
+
+ private:
+  friend class base::RefCountedThreadSafe<ObserverIOThreadWrapper>;
+
+  ~ObserverIOThreadWrapper() override;
+
+  void OnWatchersClearedOnIOThread();
+
+  ArcFileSystemOperationRunner::Observer* const underlying_observer_;
+
+  // If set to true, |observer_| will not be called. This variable should be
+  // accessed only on the IO thread.
+  bool disabled_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(ObserverIOThreadWrapper);
+};
 
 // Utility functions to post a task to run ArcFileSystemOperationRunner methods.
-// These functions must be called on the IO thread.
+// These functions must be called on the IO thread. Callbacks and observers will
+// be called on the IO thread.
 void GetFileSizeOnIOThread(const GURL& url,
                            const GetFileSizeCallback& callback);
 void OpenFileToReadOnIOThread(const GURL& url,
@@ -33,6 +73,14 @@
 void GetChildDocumentsOnIOThread(const std::string& authority,
                                  const std::string& parent_document_id,
                                  const GetChildDocumentsCallback& callback);
+void AddWatcherOnIOThread(const std::string& authority,
+                          const std::string& document_id,
+                          const WatcherCallback& watcher_callback,
+                          const AddWatcherCallback& callback);
+void RemoveWatcherOnIOThread(int64_t watcher_id,
+                             const RemoveWatcherCallback& callback);
+void AddObserverOnIOThread(scoped_refptr<ObserverIOThreadWrapper> observer);
+void RemoveObserverOnIOThread(scoped_refptr<ObserverIOThreadWrapper> observer);
 
 }  // namespace file_system_operation_runner_util
 }  // namespace arc
diff --git a/chrome/browser/chromeos/input_method/input_method_persistence.cc b/chrome/browser/chromeos/input_method/input_method_persistence.cc
index 0c0e5891..3ebd98e7 100644
--- a/chrome/browser/chromeos/input_method/input_method_persistence.cc
+++ b/chrome/browser/chromeos/input_method/input_method_persistence.cc
@@ -27,44 +27,44 @@
         language_prefs::kPreferredKeyboardLayout, input_method);
 }
 
-static void SetUserLRUInputMethodPreference(const std::string& username,
-                                            const std::string& input_method,
-                                            PrefService* local_state) {
+static void SetUserLastInputMethodPreference(const std::string& username,
+                                             const std::string& input_method,
+                                             PrefService* local_state) {
   if (!username.empty() && !local_state->ReadOnly()) {
     bool update_succeed = false;
     {
       // Updater may have side-effects, therefore we do not replace
       // entry while updater exists.
-      DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
-      base::DictionaryValue* const users_lru_input_methods = updater.Get();
-      if (users_lru_input_methods) {
-        users_lru_input_methods->SetStringWithoutPathExpansion(username,
-                                                               input_method);
+      DictionaryPrefUpdate updater(local_state, prefs::kUsersLastInputMethod);
+      base::DictionaryValue* const users_last_input_methods = updater.Get();
+      if (users_last_input_methods) {
+        users_last_input_methods->SetStringWithoutPathExpansion(username,
+                                                                input_method);
         update_succeed = true;
       }
     }
     if (!update_succeed) {
-      // Somehow key kUsersLRUInputMethod has value of invalid type.
+      // Somehow key kUsersLastInputMethod has value of invalid type.
       // Replace and retry.
-      local_state->Set(prefs::kUsersLRUInputMethod, base::DictionaryValue());
+      local_state->Set(prefs::kUsersLastInputMethod, base::DictionaryValue());
 
-      DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
-      base::DictionaryValue* const users_lru_input_methods = updater.Get();
-      if (users_lru_input_methods) {
-        users_lru_input_methods->SetStringWithoutPathExpansion(username,
-                                                               input_method);
+      DictionaryPrefUpdate updater(local_state, prefs::kUsersLastInputMethod);
+      base::DictionaryValue* const users_last_input_methods = updater.Get();
+      if (users_last_input_methods) {
+        users_last_input_methods->SetStringWithoutPathExpansion(username,
+                                                                input_method);
         update_succeed = true;
       }
     }
     if (!update_succeed) {
-      DVLOG(1) << "Failed to replace local_state.kUsersLRUInputMethod: '"
-               << prefs::kUsersLRUInputMethod << "' for '" << username << "'";
+      DVLOG(1) << "Failed to replace local_state.kUsersLastInputMethod: '"
+               << prefs::kUsersLastInputMethod << "' for '" << username << "'";
     }
   }
 }
 
-// Update user LRU keyboard layout for login screen
-static void SetUserLRUInputMethod(
+// Update user Last keyboard layout for login screen
+static void SetUserLastInputMethod(
     const std::string& input_method,
     const chromeos::input_method::InputMethodManager* const manager,
     Profile* profile) {
@@ -78,8 +78,8 @@
 
   PrefService* const local_state = g_browser_process->local_state();
 
-  SetUserLRUInputMethodPreference(
-      profile->GetProfileUserName(), input_method, local_state);
+  SetUserLastInputMethodPreference(profile->GetProfileUserName(), input_method,
+                                   local_state);
 }
 
 void PersistUserInputMethod(const std::string& input_method,
@@ -93,7 +93,7 @@
     user_prefs = profile->GetPrefs();
   if (!user_prefs)
     return;
-  SetUserLRUInputMethod(input_method, manager, profile);
+  SetUserLastInputMethod(input_method, manager, profile);
 
   const std::string current_input_method_on_pref =
       user_prefs->GetString(prefs::kLanguageCurrentInputMethod);
@@ -153,10 +153,11 @@
   ui_session_ = new_ui_session;
 }
 
-void SetUserLRUInputMethodPreferenceForTesting(const std::string& username,
-                                               const std::string& input_method,
-                                               PrefService* const local_state) {
-  SetUserLRUInputMethodPreference(username, input_method, local_state);
+void SetUserLastInputMethodPreferenceForTesting(
+    const std::string& username,
+    const std::string& input_method,
+    PrefService* const local_state) {
+  SetUserLastInputMethodPreference(username, input_method, local_state);
 }
 
 }  // namespace input_method
diff --git a/chrome/browser/chromeos/input_method/input_method_persistence.h b/chrome/browser/chromeos/input_method/input_method_persistence.h
index 2693d97..090a7ec 100644
--- a/chrome/browser/chromeos/input_method/input_method_persistence.h
+++ b/chrome/browser/chromeos/input_method/input_method_persistence.h
@@ -42,9 +42,9 @@
   DISALLOW_COPY_AND_ASSIGN(InputMethodPersistence);
 };
 
-void SetUserLRUInputMethodPreferenceForTesting(const std::string& username,
-                                               const std::string& input_method,
-                                               PrefService* local_state);
+void SetUserLastInputMethodPreferenceForTesting(const std::string& username,
+                                                const std::string& input_method,
+                                                PrefService* local_state);
 
 }  // namespace input_method
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
index 3e5b8d1..2fc7f66 100644
--- a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
@@ -103,12 +103,12 @@
 
   // Should be called from PRE_ test so that local_state is saved to disk, and
   // reloaded in the main test.
-  void InitUserLRUInputMethod() {
+  void InitUserLastInputMethod() {
     PrefService* local_state = g_browser_process->local_state();
 
-    input_method::SetUserLRUInputMethodPreferenceForTesting(
+    input_method::SetUserLastInputMethodPreferenceForTesting(
         kTestUser1, user_input_methods[0], local_state);
-    input_method::SetUserLRUInputMethodPreferenceForTesting(
+    input_method::SetUserLastInputMethodPreferenceForTesting(
         kTestUser2, user_input_methods[1], local_state);
   }
 
@@ -141,7 +141,7 @@
   RegisterUser(kTestUser1);
   RegisterUser(kTestUser2);
 
-  InitUserLRUInputMethod();
+  InitUserLastInputMethod();
 
   StartupUtils::MarkOobeCompleted();
 }
@@ -204,14 +204,14 @@
 
   // Should be called from PRE_ test so that local_state is saved to disk, and
   // reloaded in the main test.
-  void InitUserLRUInputMethod() {
+  void InitUserLastInputMethod() {
     PrefService* local_state = g_browser_process->local_state();
 
-    input_method::SetUserLRUInputMethodPreferenceForTesting(
+    input_method::SetUserLastInputMethodPreferenceForTesting(
         kTestUser1, user_input_methods[0], local_state);
-    input_method::SetUserLRUInputMethodPreferenceForTesting(
+    input_method::SetUserLastInputMethodPreferenceForTesting(
         kTestUser2, user_input_methods[1], local_state);
-    input_method::SetUserLRUInputMethodPreferenceForTesting(
+    input_method::SetUserLastInputMethodPreferenceForTesting(
         kTestUser3, user_input_methods[2], local_state);
 
     local_state->SetString(language_prefs::kPreferredKeyboardLayout,
@@ -243,7 +243,7 @@
   RegisterUser(kTestUser2);
   RegisterUser(kTestUser3);
 
-  InitUserLRUInputMethod();
+  InitUserLastInputMethod();
 
   StartupUtils::MarkOobeCompleted();
 }
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index eda7c36..41aca8d6 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -53,6 +53,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/common/chrome_constants.h"
@@ -325,6 +326,16 @@
   client_callback.Run(incognito ? profile->GetOffTheRecordProfile() : profile);
 }
 
+#if !defined(OS_ANDROID)
+// Helper function for ScheduleForcedEphemeralProfileForDeletion.
+bool IsProfileEphemeral(ProfileAttributesStorage* storage,
+                        const base::FilePath& profile_dir) {
+  ProfileAttributesEntry* entry = nullptr;
+  return storage->GetProfileAttributesWithPath(profile_dir, &entry) &&
+         entry->IsEphemeral();
+}
+#endif
+
 }  // namespace
 
 ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
@@ -1665,8 +1676,8 @@
     // Do nothing if the profile is already being deleted.
   } else if (profile->GetPrefs()->GetBoolean(prefs::kForceEphemeralProfiles)) {
     // Delete if the profile is an ephemeral profile.
-    g_browser_process->profile_manager()->ScheduleProfileForDeletion(
-        path, ProfileManager::CreateCallback());
+    g_browser_process->profile_manager()
+        ->ScheduleForcedEphemeralProfileForDeletion(path);
   } else {
 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
     // Gather statistics and store into ProfileInfoCache. For incognito profile
@@ -1725,6 +1736,37 @@
   if (!original_callback.is_null())
     original_callback.Run(loaded_profile, status);
 }
+
+void ProfileManager::ScheduleForcedEphemeralProfileForDeletion(
+    const base::FilePath& profile_dir) {
+  DCHECK_EQ(0u, chrome::GetBrowserCount(GetProfileByPath(profile_dir)));
+  DCHECK(IsProfileEphemeral(&GetProfileAttributesStorage(), profile_dir));
+
+  // Search for latest active profile, already loaded preferably.
+  bool found_entry_loaded = false;
+  ProfileAttributesEntry* found_entry = nullptr;
+  ProfileAttributesStorage& storage = GetProfileAttributesStorage();
+  for (ProfileAttributesEntry* entry : storage.GetAllProfilesAttributes()) {
+    // Skip all profiles forbidden to rollback.
+    base::FilePath entry_path = entry->GetPath();
+    if (entry_path == profile_dir ||
+        entry_path == GetGuestProfilePath() ||
+        entry->IsLegacySupervised() ||
+        IsProfileDirectoryMarkedForDeletion(entry_path))
+      continue;
+    // Check if |entry| preferable over |found_entry|.
+    bool entry_loaded = !!GetProfileByPath(entry_path);
+    if (!found_entry || (!found_entry_loaded && entry_loaded) ||
+        found_entry->GetActiveTime() < entry->GetActiveTime()) {
+      found_entry = entry;
+      found_entry_loaded = entry_loaded;
+    }
+  }
+
+  const base::FilePath new_active_profile_dir =
+      found_entry ? found_entry->GetPath() : GenerateNextProfileDirectoryPath();
+  FinishDeletingProfile(profile_dir, new_active_profile_dir);
+}
 #endif  // !defined(OS_ANDROID)
 
 ProfileManagerWithoutInit::ProfileManagerWithoutInit(
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 6554312..385f9c3 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -383,6 +383,11 @@
       const CreateCallback& original_callback,
       Profile* loaded_profile,
       Profile::CreateStatus status);
+
+  // Schedules the forced ephemeral profile at the given path to be deleted on
+  // shutdown. New profiles will not be created.
+  void ScheduleForcedEphemeralProfileForDeletion(
+      const base::FilePath& profile_dir);
 #endif  // !defined(OS_ANDROID)
 
   // Object to cache various information about profiles. Contains information
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index 58ff171..b68675b 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -178,6 +178,21 @@
     return profile_manager->GetProfile(path);
   }
 
+  // Helper function to set profile ephemeral at prefs and attributes storage.
+  void SetProfileEphemeral(Profile* profile) {
+    profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true);
+
+    // Update IsEphemeral in attributes storage, normally it happened via
+    // kForceEphemeralProfiles pref change event routed to
+    // ProfileImpl::UpdateIsEphemeralInStorage().
+    ProfileAttributesEntry* entry;
+    ProfileAttributesStorage& storage =
+        g_browser_process->profile_manager()->GetProfileAttributesStorage();
+    EXPECT_TRUE(
+        storage.GetProfileAttributesWithPath(profile->GetPath(), &entry));
+    entry->SetIsEphemeral(true);
+  }
+
 #if defined(OS_CHROMEOS)
   // Helper function to register an user with id |user_id| and create profile
   // with a correct path.
@@ -878,7 +893,7 @@
   TestingProfile* profile =
       static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path));
   ASSERT_TRUE(profile);
-  profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true);
+  SetProfileEphemeral(profile);
 
   // Here the last used profile is still the "Default" profile.
   Profile* last_used_profile = profile_manager->GetLastUsedProfile();
@@ -918,8 +933,7 @@
   TestingProfile* ephemeral_profile1 =
       static_cast<TestingProfile*>(profile_manager->GetProfile(dest_path2));
   ASSERT_TRUE(ephemeral_profile1);
-  ephemeral_profile1->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles,
-                                             true);
+  SetProfileEphemeral(ephemeral_profile1);
 
   // Add second ephemeral profile but don't mark it as such yet.
   TestingProfile* ephemeral_profile2 =
@@ -947,8 +961,7 @@
   EXPECT_EQ(ephemeral_profile2, last_opened_profiles[1]);
 
   // Mark the second profile ephemeral.
-  ephemeral_profile2->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles,
-                                             true);
+  SetProfileEphemeral(ephemeral_profile2);
 
   // Simulate a shutdown.
   content::NotificationService::current()->Notify(
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index be7c809d..5998a85a 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -246,6 +246,10 @@
   SetIsChildAccount(info.is_child_account);
 }
 
+void ChildAccountService::OnAccountRemoved(const AccountInfo& info) {
+  SetIsChildAccount(false);
+}
+
 void ChildAccountService::OnGetFamilyMembersSuccess(
     const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
   bool hoh_found = false;
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.h b/chrome/browser/supervised_user/child_accounts/child_account_service.h
index d6feb08..dfd5c03f 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.h
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.h
@@ -65,6 +65,7 @@
 
   // AccountTrackerService::Observer implementation.
   void OnAccountUpdated(const AccountInfo& info) override;
+  void OnAccountRemoved(const AccountInfo& info) override;
 
   // FamilyInfoFetcher::Consumer implementation.
   void OnGetFamilyMembersSuccess(
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 1c5bf8e..13c9224 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -880,7 +880,7 @@
   } else {
     std::vector<std::string> input_methods =
         imm->GetInputMethodUtil()->GetHardwareLoginInputMethodIds();
-    const std::string owner_im = SigninScreenHandler::GetUserLRUInputMethod(
+    const std::string owner_im = SigninScreenHandler::GetUserLastInputMethod(
         user_manager::UserManager::Get()->GetOwnerAccountId().GetUserEmail());
     const std::string system_im = g_browser_process->local_state()->GetString(
         language_prefs::kPreferredKeyboardLayout);
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 3e90662..06367218 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -204,16 +204,16 @@
   if (!chromeos::input_method::InputMethodManager::Get()->IsLoginKeyboard(
           user_input_method)) {
     LOG(WARNING) << "SetUserInputMethod('" << username
-                 << "'): stored user LRU input method '" << user_input_method
+                 << "'): stored user last input method '" << user_input_method
                  << "' is no longer Full Latin Keyboard Language"
                  << " (entry dropped). Use hardware default instead.";
 
     PrefService* const local_state = g_browser_process->local_state();
-    DictionaryPrefUpdate updater(local_state, prefs::kUsersLRUInputMethod);
+    DictionaryPrefUpdate updater(local_state, prefs::kUsersLastInputMethod);
 
-    base::DictionaryValue* const users_lru_input_methods = updater.Get();
-    if (users_lru_input_methods != nullptr) {
-      users_lru_input_methods->SetStringWithoutPathExpansion(username, "");
+    base::DictionaryValue* const users_last_input_methods = updater.Get();
+    if (users_last_input_methods != nullptr) {
+      users_last_input_methods->SetStringWithoutPathExpansion(username, "");
     }
     return false;
   }
@@ -363,23 +363,23 @@
 }
 
 // static
-std::string SigninScreenHandler::GetUserLRUInputMethod(
+std::string SigninScreenHandler::GetUserLastInputMethod(
     const std::string& username) {
   PrefService* const local_state = g_browser_process->local_state();
-  const base::DictionaryValue* users_lru_input_methods =
-      local_state->GetDictionary(prefs::kUsersLRUInputMethod);
+  const base::DictionaryValue* users_last_input_methods =
+      local_state->GetDictionary(prefs::kUsersLastInputMethod);
 
-  if (!users_lru_input_methods) {
-    DLOG(WARNING) << "GetUserLRUInputMethod('" << username
-                  << "'): no kUsersLRUInputMethod";
+  if (!users_last_input_methods) {
+    DLOG(WARNING) << "GetUserLastInputMethod('" << username
+                  << "'): no kUsersLastInputMethod";
     return std::string();
   }
 
   std::string input_method;
 
-  if (!users_lru_input_methods->GetStringWithoutPathExpansion(username,
-                                                              &input_method)) {
-    DVLOG(0) << "GetUserLRUInputMethod('" << username
+  if (!users_last_input_methods->GetStringWithoutPathExpansion(username,
+                                                               &input_method)) {
+    DVLOG(0) << "GetUserLastInputMethod('" << username
              << "'): no input method for this user";
     return std::string();
   }
@@ -394,14 +394,14 @@
     input_method::InputMethodManager::State* ime_state) {
   bool succeed = false;
 
-  const std::string input_method = GetUserLRUInputMethod(username);
+  const std::string input_method = GetUserLastInputMethod(username);
 
   EnforcePolicyInputMethods(input_method);
 
   if (!input_method.empty())
     succeed = SetUserInputMethodImpl(username, input_method, ime_state);
 
-  // This is also a case when LRU layout is set only for a few local users,
+  // This is also a case when last layout is set only for a few local users,
   // thus others need to be switched to default locale.
   // Otherwise they will end up using another user's locale to log in.
   if (!succeed) {
@@ -982,7 +982,7 @@
 }
 
 void SigninScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(prefs::kUsersLRUInputMethod);
+  registry->RegisterDictionaryPref(prefs::kUsersLastInputMethod);
 }
 
 void SigninScreenHandler::OnCurrentScreenChanged(OobeScreen current_screen,
@@ -1619,7 +1619,7 @@
 void SigninScreenHandler::OnAllowedInputMethodsChanged() {
   if (focused_pod_account_id_) {
     std::string user_input_method =
-        GetUserLRUInputMethod(focused_pod_account_id_->GetUserEmail());
+        GetUserLastInputMethod(focused_pod_account_id_->GetUserEmail());
     EnforcePolicyInputMethods(user_input_method);
   } else {
     EnforcePolicyInputMethods(std::string());
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 57d1043d..861ac63 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -235,10 +235,10 @@
       JSCallsContainer* js_calls_container);
   ~SigninScreenHandler() override;
 
-  static std::string GetUserLRUInputMethod(const std::string& username);
+  static std::string GetUserLastInputMethod(const std::string& username);
 
   // Update current input method (namely keyboard layout) in the given IME state
-  // to LRU by this user.
+  // to last input method used by this user.
   static void SetUserInputMethod(
       const std::string& username,
       input_method::InputMethodManager::State* ime_state);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index f4a36c0..3327c59 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1871,9 +1871,10 @@
 // How many times HID detection OOBE dialog was shown.
 const char kTimesHIDDialogShown[] = "HIDDialog.shown_how_many_times";
 
-// Dictionary of per-user Least Recently Used input method (used at login
-// screen).
-const char kUsersLRUInputMethod[] = "UsersLRUInputMethod";
+// Dictionary of per-user last input method (used at login screen). Note that
+// the pref name is UsersLRUInputMethods for compatibility with previous
+// versions.
+const char kUsersLastInputMethod[] = "UsersLRUInputMethod";
 
 // A dictionary pref of the echo offer check flag. It sets offer info when
 // an offer is checked.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index af128bc..771afb8 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -666,7 +666,7 @@
 extern const char kDeviceEnrollmentCanExit[];
 extern const char kDeviceDMToken[];
 extern const char kTimesHIDDialogShown[];
-extern const char kUsersLRUInputMethod[];
+extern const char kUsersLastInputMethod[];
 extern const char kEchoCheckedOffers[];
 extern const char kCachedMultiProfileUserBehavior[];
 extern const char kInitialLocale[];
diff --git a/components/cronet/android/cert/cert_verifier_cache_serializer.cc b/components/cronet/android/cert/cert_verifier_cache_serializer.cc
index c6c1513..e0c4b9a 100644
--- a/components/cronet/android/cert/cert_verifier_cache_serializer.cc
+++ b/components/cronet/android/cert/cert_verifier_cache_serializer.cc
@@ -55,7 +55,7 @@
   certificate->add_cert_numbers(cert_number);
   const net::X509Certificate::X509Certificate::OSCertHandles&
       intermediate_ca_certs = cert->GetIntermediateCertificates();
-  for (const auto& intermediate : intermediate_ca_certs) {
+  for (auto* const intermediate : intermediate_ca_certs) {
     if (!SerializeCertHandle(intermediate, serialized_certs, &cert_number))
       return false;
     certificate->add_cert_numbers(cert_number);
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index a74342c..dda9ce4 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -799,7 +799,7 @@
   }
 
   // Iterate through PKP configuration for every host.
-  for (const auto& pkp : config->pkp_list) {
+  for (auto* const pkp : config->pkp_list) {
     // Add the host pinning.
     context_->transport_security_state()->AddHPKP(
         pkp->host, pkp->expiration_date, pkp->include_subdomains,
diff --git a/components/doodle/doodle_service.cc b/components/doodle/doodle_service.cc
index c5cb9137..463d768 100644
--- a/components/doodle/doodle_service.cc
+++ b/components/doodle/doodle_service.cc
@@ -11,9 +11,11 @@
 
 namespace doodle {
 
-DoodleService::DoodleService(std::unique_ptr<DoodleFetcher> fetcher)
-    : fetcher_(std::move(fetcher)) {
+DoodleService::DoodleService(std::unique_ptr<DoodleFetcher> fetcher,
+                             std::unique_ptr<base::OneShotTimer> expiry_timer)
+    : fetcher_(std::move(fetcher)), expiry_timer_(std::move(expiry_timer)) {
   DCHECK(fetcher_);
+  DCHECK(expiry_timer_);
 }
 
 DoodleService::~DoodleService() = default;
@@ -35,15 +37,39 @@
     DoodleState state,
     base::TimeDelta time_to_live,
     const base::Optional<DoodleConfig>& doodle_config) {
-  // If nothing changed, then there's nothing to do. Note that this checks both
-  // for existence changes as well as changes of the configs themselves.
-  if (cached_config_ == doodle_config) {
-    // TODO(treib): Once we support expiry, update the time to live here.
-    return;
+  // Handle the case where the new config is already expired.
+  bool expired = time_to_live <= base::TimeDelta();
+  const base::Optional<DoodleConfig>& new_config =
+      expired ? base::nullopt : doodle_config;
+
+  // If the config changed, update our cache and notify observers.
+  // Note that this checks both for existence changes as well as changes of the
+  // configs themselves.
+  if (cached_config_ != new_config) {
+    cached_config_ = new_config;
+    for (auto& observer : observers_) {
+      observer.OnDoodleConfigUpdated(cached_config_);
+    }
   }
 
-  // Update the cache and notify observers.
-  cached_config_ = doodle_config;
+  // Even if the configs are identical, the time-to-live might have changed.
+  UpdateTimeToLive(time_to_live);
+}
+
+void DoodleService::UpdateTimeToLive(base::TimeDelta time_to_live) {
+  // (Re-)schedule the cache expiry.
+  if (cached_config_.has_value()) {
+    expiry_timer_->Start(
+        FROM_HERE, time_to_live,
+        base::Bind(&DoodleService::DoodleExpired, base::Unretained(this)));
+  } else {
+    expiry_timer_->Stop();
+  }
+}
+
+void DoodleService::DoodleExpired() {
+  DCHECK(cached_config_.has_value());
+  cached_config_.reset();
   for (auto& observer : observers_) {
     observer.OnDoodleConfigUpdated(cached_config_);
   }
diff --git a/components/doodle/doodle_service.h b/components/doodle/doodle_service.h
index f1265e7..8913fbf14 100644
--- a/components/doodle/doodle_service.h
+++ b/components/doodle/doodle_service.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/optional.h"
+#include "base/timer/timer.h"
 #include "components/doodle/doodle_fetcher.h"
 #include "components/doodle/doodle_types.h"
 
@@ -26,7 +27,9 @@
     virtual void OnDoodleConfigUpdated(const base::Optional<DoodleConfig>&) = 0;
   };
 
-  DoodleService(std::unique_ptr<DoodleFetcher> fetcher);
+  // Both |fetcher| and |expiry_timer| must be non-null.
+  DoodleService(std::unique_ptr<DoodleFetcher> fetcher,
+                std::unique_ptr<base::OneShotTimer> expiry_timer);
   ~DoodleService();
 
   // Returns the current (cached) config, if any.
@@ -46,13 +49,21 @@
   void Refresh();
 
  private:
+  // Callback for the fetcher.
   void DoodleFetched(DoodleState state,
                      base::TimeDelta time_to_live,
                      const base::Optional<DoodleConfig>& doodle_config);
 
+  void UpdateTimeToLive(base::TimeDelta time_to_live);
+
+  // Callback for the expiry timer.
+  void DoodleExpired();
+
   // The fetcher for getting fresh DoodleConfigs from the network.
   std::unique_ptr<DoodleFetcher> fetcher_;
 
+  std::unique_ptr<base::OneShotTimer> expiry_timer_;
+
   // The result of the last network fetch.
   base::Optional<DoodleConfig> cached_config_;
 
diff --git a/components/doodle/doodle_service_unittest.cc b/components/doodle/doodle_service_unittest.cc
index 41ebe7d5a..cc875008 100644
--- a/components/doodle/doodle_service_unittest.cc
+++ b/components/doodle/doodle_service_unittest.cc
@@ -10,6 +10,10 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -55,18 +59,41 @@
 
 class DoodleServiceTest : public testing::Test {
  public:
-  DoodleServiceTest() : fetcher_(nullptr) {
+  DoodleServiceTest()
+      : fetcher_(nullptr),
+        task_runner_(new base::TestMockTimeTaskRunner()),
+        task_runner_handle_(task_runner_),
+        tick_clock_(task_runner_->GetMockTickClock()),
+        expiry_timer_(nullptr) {
+    task_runner_->FastForwardBy(base::TimeDelta::FromHours(12345));
+
+    auto expiry_timer = base::MakeUnique<base::OneShotTimer>(tick_clock_.get());
+    expiry_timer->SetTaskRunner(task_runner_);
+    expiry_timer_ = expiry_timer.get();
+
     auto fetcher = base::MakeUnique<FakeDoodleFetcher>();
     fetcher_ = fetcher.get();
-    service_ = base::MakeUnique<DoodleService>(std::move(fetcher));
+
+    service_ = base::MakeUnique<DoodleService>(std::move(fetcher),
+                                               std::move(expiry_timer));
   }
 
   DoodleService* service() { return service_.get(); }
   FakeDoodleFetcher* fetcher() { return fetcher_; }
 
+  base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
+
  private:
-  std::unique_ptr<DoodleService> service_;
+  // Weak, owned by the service.
   FakeDoodleFetcher* fetcher_;
+
+  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+  base::ThreadTaskRunnerHandle task_runner_handle_;
+  std::unique_ptr<base::TickClock> tick_clock_;
+  // Weak, owned by the service.
+  base::OneShotTimer* expiry_timer_;
+
+  std::unique_ptr<DoodleService> service_;
 };
 
 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) {
@@ -177,7 +204,7 @@
   service()->RemoveObserver(&observer);
 }
 
-TEST_F(DoodleServiceTest, DoesNotCallObserverWhenConfigEquivalent) {
+TEST_F(DoodleServiceTest, DoesNotCallObserverIfConfigEquivalent) {
   // Load some doodle config.
   service()->Refresh();
   DoodleConfig config;
@@ -204,4 +231,63 @@
   service()->RemoveObserver(&observer);
 }
 
+TEST_F(DoodleServiceTest, CallsObserverWhenConfigExpires) {
+  // Load some doodle config.
+  service()->Refresh();
+  DoodleConfig config;
+  config.doodle_type = DoodleType::SIMPLE;
+  fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
+                               base::TimeDelta::FromHours(1), config);
+  ASSERT_THAT(service()->config(), Eq(config));
+
+  // Make sure the task arrived at the timer's task runner.
+  ASSERT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u));
+  EXPECT_THAT(task_runner()->NextPendingTaskDelay(),
+              Eq(base::TimeDelta::FromHours(1)));
+
+  // Register an observer.
+  StrictMock<MockDoodleObserver> observer;
+  service()->AddObserver(&observer);
+
+  // Fast-forward time so that the expiry task will run. The observer should get
+  // notified that there's no config anymore.
+  EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt)));
+  task_runner()->FastForwardBy(base::TimeDelta::FromHours(1));
+
+  // Remove the observer before the service gets destroyed.
+  service()->RemoveObserver(&observer);
+}
+
+TEST_F(DoodleServiceTest, DisregardsAlreadyExpiredConfigs) {
+  StrictMock<MockDoodleObserver> observer;
+  service()->AddObserver(&observer);
+
+  ASSERT_THAT(service()->config(), Eq(base::nullopt));
+
+  // Load an already-expired config. This should have no effect; in particular
+  // no call to the observer.
+  service()->Refresh();
+  DoodleConfig config;
+  config.doodle_type = DoodleType::SIMPLE;
+  fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
+                               base::TimeDelta::FromSeconds(0), config);
+  EXPECT_THAT(service()->config(), Eq(base::nullopt));
+
+  // Load a doodle config as usual. Nothing to see here.
+  service()->Refresh();
+  EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config)));
+  fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
+                               base::TimeDelta::FromHours(1), config);
+  ASSERT_THAT(service()->config(), Eq(config));
+
+  // Now load an expired config again. The cached one should go away.
+  service()->Refresh();
+  EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt)));
+  fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
+                               base::TimeDelta::FromSeconds(0), config);
+
+  // Remove the observer before the service gets destroyed.
+  service()->RemoveObserver(&observer);
+}
+
 }  // namespace doodle
diff --git a/components/exo/display_unittest.cc b/components/exo/display_unittest.cc
index a9a4f0e..81792d8 100644
--- a/components/exo/display_unittest.cc
+++ b/components/exo/display_unittest.cc
@@ -13,7 +13,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(USE_OZONE)
-#include "ui/ozone/public/native_pixmap.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 #endif
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 800ccb4..4f7c845 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -419,11 +419,6 @@
     LOG(WARNING) << "Download of popular sites failed";
     return;
   }
-
-  for (const PopularSites::Site& popular_site : popular_sites_->sites()) {
-    // Ignore callback; these icons will be seen on the *next* NTP.
-    icon_cacher_->StartFetch(popular_site, base::Closure(), base::Closure());
-  }
 }
 
 void MostVisitedSites::OnIconMadeAvailable(const GURL& site_url) {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 3b5378a..84c9694 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -9596,7 +9596,7 @@
       'tags': [],
       'desc': '''Configures which keyboard layouts are allowed on the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> sign-in screen.
 
-      If this policy is set to a list of input method identifiers, the given input methods will be available on the sign-in screen. The first given input method will be preselected. While a user pod is focused on the sign-in screen, the user's least recently used input method will be available in addition to the input methods given by this policy.  If this policy is not set, the input methods on the sign-in screen will be derived from the locale in which the sign-in screen is displayed.  Values which are not valid input method identifiers will be ignored.''',
+      If this policy is set to a list of input method identifiers, the given input methods will be available on the sign-in screen. The first given input method will be preselected. While a user pod is focused on the sign-in screen, the user's last used input method will be available in addition to the input methods given by this policy. If this policy is not set, the input methods on the sign-in screen will be derived from the locale in which the sign-in screen is displayed. Values which are not valid input method identifiers will be ignored.''',
     },
   ],
   'messages': {
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
index d5934eb..3c41ad0 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
@@ -29,9 +29,8 @@
     /**
      * Get an auth token. This should only be called on a background thread.
      *
-     * @param account        The {@link Account} for which the auth token is requested.
+     * @param account The {@link Account} for which the auth token is requested.
      * @param authTokenScope The scope of the authToken being requested.
-     *
      * @return The auth token fetched from the authenticator.
      * @throws AuthException Indicates a failure in fetching the auth token perhaps due to a
      * transient error or when user intervention is required (like confirming the credentials)
@@ -40,22 +39,6 @@
     String getAuthToken(Account account, String authTokenScope) throws AuthException;
 
     /**
-     * Get an auth token. If there is a user-recoverable auth error, immediately attempt to resolve
-     * it by launching the intent associated with it.
-     * This should only be called on a background thread.
-     *
-     * @param account        The {@link Account} for which the auth token is requested.
-     * @param authTokenScope The scope of the authToken being requested.
-     *
-     * @return The auth token fetched from the authenticator.
-     * @throws AuthException Indicates a failure in fetching the auth token perhaps due to a
-     *         transient error or when user intervention is required (like confirming the
-     *         credentials) which is expressed as an {@link Intent} to the handler.
-     */
-    String getAuthTokenAndFixUserRecoverableErrorIfNeeded(Account account, String authTokenScope)
-            throws AuthException;
-
-    /**
      * @param authToken The auth token to invalidate.
      * @throws AuthException Indicates a failure clearing the auth token; can be transient.
      */
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
index dc02c903..0d71fa4 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
@@ -14,7 +14,6 @@
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.net.NetworkChangeNotifier;
-import org.chromium.net.NetworkChangeNotifier.ConnectionTypeObserver;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -292,23 +291,15 @@
      * Gets the auth token and returns the response asynchronously.
      * This should be called when we have a foreground activity that needs an auth token.
      * If encountered an IO error, it will attempt to retry when the network is back.
-     * If {@code handleUserRecoverableErrors} is true, attempt to immediately resolve
-     * user-recoverable errors. This should only be used if getting the auth token is absolutely
-     * necessary for the browser to function.
      *
      * - Assumes that the account is a valid account.
      */
     public void getAuthToken(final Account account, final String authTokenType,
-            final boolean handleUserRecoverableErrors, final GetAuthTokenCallback callback) {
+            final GetAuthTokenCallback callback) {
         ConnectionRetry.runAuthTask(new AuthTask<String>() {
             @Override
             public String run() throws AuthException {
-                if (handleUserRecoverableErrors) {
-                    return mAccountManager.getAuthTokenAndFixUserRecoverableErrorIfNeeded(
-                            account, authTokenType);
-                } else {
-                    return mAccountManager.getAuthToken(account, authTokenType);
-                }
+                return mAccountManager.getAuthToken(account, authTokenType);
             }
             @Override
             public void onSuccess(String token) {
@@ -329,7 +320,7 @@
     public void getNewAuthToken(Account account, String authToken, String authTokenType,
             GetAuthTokenCallback callback) {
         invalidateAuthToken(authToken);
-        getAuthToken(account, authTokenType, false /* handleUserRecoverableErrors */, callback);
+        getAuthToken(account, authTokenType, callback);
     }
 
     /**
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
index 68f74069..2700cf05 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
@@ -14,7 +14,6 @@
 import android.accounts.OperationCanceledException;
 import android.app.Activity;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -24,7 +23,6 @@
 import com.google.android.gms.auth.GoogleAuthException;
 import com.google.android.gms.auth.GoogleAuthUtil;
 import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
-import com.google.android.gms.auth.UserRecoverableAuthException;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
@@ -38,8 +36,8 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Default implementation of {@link AccountManagerDelegate} which delegates all calls to the Android
- * account manager.
+ * Default implementation of {@link AccountManagerDelegate} which delegates all calls to the
+ * Android account manager.
  */
 @MainDex
 public class SystemAccountManagerDelegate implements AccountManagerDelegate {
@@ -87,26 +85,8 @@
             return GoogleAuthUtil.getTokenWithNotification(
                     mApplicationContext, account, authTokenScope, null);
         } catch (GoogleAuthException ex) {
-            // TODO(bauerb): Investigate integrating the callback with ConnectionRetry.
-            throw new AuthException(false /* isTransientError */, ex);
-        } catch (IOException ex) {
-            throw new AuthException(true /* isTransientError */, ex);
-        }
-    }
-
-    @Override
-    public String getAuthTokenAndFixUserRecoverableErrorIfNeeded(
-            Account account, String authTokenScope) throws AuthException {
-        assert !ThreadUtils.runningOnUiThread();
-        assert AccountManagerHelper.GOOGLE_ACCOUNT_TYPE.equals(account.type);
-        try {
-            return GoogleAuthUtil.getToken(mApplicationContext, account, authTokenScope, null);
-        } catch (UserRecoverableAuthException ex) {
-            Intent intent = ex.getIntent();
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mApplicationContext.startActivity(intent);
-            throw new AuthException(false /* isTransientError */, ex);
-        } catch (GoogleAuthException ex) {
+            // This case includes a UserRecoverableNotifiedException, but most clients will have
+            // their own retry mechanism anyway.
             // TODO(bauerb): Investigate integrating the callback with ConnectionRetry.
             throw new AuthException(false /* isTransientError */, ex);
         } catch (IOException ex) {
@@ -162,8 +142,8 @@
 
     /**
      * Records a histogram value for how long time an action has taken using
-     * {@link RecordHistogram#recordTimesHistogram(String, long, TimeUnit))} iff the browser process
-     * has been initialized.
+     * {@link RecordHistogram#recordTimesHistogram(String, long, TimeUnit))} iff the browser
+     * process has been initialized.
      *
      * @param histogramName the name of the histogram.
      * @param elapsedMs the elapsed time in milliseconds.
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/MockAccountManager.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/MockAccountManager.java
index e9b6932..6aa4198 100644
--- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/MockAccountManager.java
+++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/MockAccountManager.java
@@ -159,12 +159,6 @@
     }
 
     @Override
-    public String getAuthTokenAndFixUserRecoverableErrorIfNeeded(
-            Account account, String authTokenScope) {
-        return getAuthToken(account, authTokenScope);
-    }
-
-    @Override
     public void invalidateAuthToken(String authToken) {
         if (authToken == null) {
             throw new IllegalArgumentException("AuthToken can not be null");
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index ff676db..419beed 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1305,7 +1305,7 @@
   if (frame_tree_node_->IsMainFrame() && GetView() &&
       !validated_params.was_within_same_page) {
     RenderWidgetHostImpl::From(GetView()->GetRenderWidgetHost())
-        ->StartNewContentRenderingTimeout();
+        ->StartNewContentRenderingTimeout(validated_params.content_source_id);
   }
 }
 
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
index f809926..e8d38e0 100644
--- a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
+++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -225,63 +225,6 @@
           original_component, gpu_swap_begin_component);
     }
   }
-
-  // TODO(miletus): Add validation for making sure the following components
-  // are present and their event times are legit.
-  LatencyInfo::LatencyComponent rendering_scheduled_component;
-  bool rendering_scheduled_on_main = latency.FindLatency(
-      ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT,
-      0, &rendering_scheduled_component);
-
-  if (!rendering_scheduled_on_main) {
-    if (!latency.FindLatency(
-            ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT,
-            0, &rendering_scheduled_component))
-      return;
-  }
-
-  if (rendering_scheduled_on_main) {
-    UMA_HISTOGRAM_SCROLL_LATENCY_LONG(
-        "Event.Latency.ScrollUpdate.TouchToHandled_Main",
-        original_component, rendering_scheduled_component);
-  } else {
-    UMA_HISTOGRAM_SCROLL_LATENCY_LONG(
-        "Event.Latency.ScrollUpdate.TouchToHandled_Impl",
-        original_component, rendering_scheduled_component);
-  }
-
-  LatencyInfo::LatencyComponent renderer_swap_component;
-  if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
-                           0, &renderer_swap_component))
-    return;
-
-  if (rendering_scheduled_on_main) {
-    UMA_HISTOGRAM_SCROLL_LATENCY_LONG(
-        "Event.Latency.ScrollUpdate.HandledToRendererSwap_Main",
-        rendering_scheduled_component, renderer_swap_component);
-  } else {
-    UMA_HISTOGRAM_SCROLL_LATENCY_LONG(
-        "Event.Latency.ScrollUpdate.HandledToRendererSwap_Impl",
-        rendering_scheduled_component, renderer_swap_component);
-  }
-
-  LatencyInfo::LatencyComponent browser_received_swap_component;
-  if (!latency.FindLatency(
-          ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT,
-          0, &browser_received_swap_component))
-    return;
-
-  UMA_HISTOGRAM_SCROLL_LATENCY_SHORT(
-      "Event.Latency.ScrollUpdate.RendererSwapToBrowserNotified",
-      renderer_swap_component, browser_received_swap_component);
-
-  UMA_HISTOGRAM_SCROLL_LATENCY_LONG(
-      "Event.Latency.ScrollUpdate.BrowserNotifiedToBeforeGpuSwap",
-      browser_received_swap_component, gpu_swap_begin_component);
-
-  UMA_HISTOGRAM_SCROLL_LATENCY_SHORT("Event.Latency.ScrollUpdate.GpuSwap",
-                                     gpu_swap_begin_component,
-                                     gpu_swap_end_component);
 }
 
 void ComputeTouchAndWheelScrollLatencyHistograms(
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
index c7c1017..3423483 100644
--- a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
+++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -434,23 +434,6 @@
           HistogramSizeEq("Event.Latency.TouchToScrollUpdateSwapBegin_"
                           "IsRunningNavigationHintTask",
                           is_running_navigation_hint_task ? 1 : 0));
-      EXPECT_TRUE(
-          HistogramSizeEq("Event.Latency.ScrollUpdate.TouchToHandled_Main",
-                          rendering_on_main ? 1 : 0));
-      EXPECT_TRUE(
-          HistogramSizeEq("Event.Latency.ScrollUpdate.TouchToHandled_Impl",
-                          rendering_on_main ? 0 : 1));
-      EXPECT_TRUE(HistogramSizeEq(
-          "Event.Latency.ScrollUpdate.HandledToRendererSwap_Main",
-          rendering_on_main ? 1 : 0));
-      EXPECT_TRUE(HistogramSizeEq(
-          "Event.Latency.ScrollUpdate.HandledToRendererSwap_Impl",
-          rendering_on_main ? 0 : 1));
-      EXPECT_TRUE(HistogramSizeEq(
-          "Event.Latency.ScrollUpdate.RendererSwapToBrowserNotified", 1));
-      EXPECT_TRUE(HistogramSizeEq(
-          "Event.Latency.ScrollUpdate.BrowserNotifiedToBeforeGpuSwap", 1));
-      EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 1));
       EXPECT_TRUE(HistogramSizeEq(
           "Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin2", 1));
 
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 15b8995..4afec65e 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -294,6 +294,7 @@
       last_event_type_(blink::WebInputEvent::Undefined),
       new_content_rendering_delay_(
           base::TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
+      current_content_source_id_(0),
       weak_factory_(this) {
   CHECK(delegate_);
   CHECK_NE(MSG_ROUTING_NONE, routing_id_);
@@ -985,7 +986,9 @@
   RendererIsResponsive();
 }
 
-void RenderWidgetHostImpl::StartNewContentRenderingTimeout() {
+void RenderWidgetHostImpl::StartNewContentRenderingTimeout(
+    uint32_t next_source_id) {
+  current_content_source_id_ = next_source_id;
   // It is possible for a compositor frame to arrive before the browser is
   // notified about the page being committed, in which case no timer is
   // necessary.
@@ -1829,7 +1832,13 @@
   if (touch_emulator_)
     touch_emulator_->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
 
-  if (view_) {
+  // Ignore this frame if its content has already been unloaded. Source ID
+  // is always zero for an OOPIF because we are only concerned with displaying
+  // stale graphics on top-level frames. We accept frames that have a source ID
+  // greater than |current_content_source_id_| because in some cases the first
+  // compositor frame can arrive before the navigation commit message that
+  // updates that value.
+  if (view_ && frame.metadata.content_source_id >= current_content_source_id_) {
     view_->OnSwapCompositorFrame(compositor_frame_sink_id, std::move(frame));
     view_->DidReceiveRendererFrame();
   } else {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index b6aa99ec..11dddf1 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -325,8 +325,10 @@
   void StopHangMonitorTimeout();
 
   // Starts the rendering timeout, which will clear displayed graphics if
-  // a new compositor frame is not received before it expires.
-  void StartNewContentRenderingTimeout();
+  // a new compositor frame is not received before it expires. This also causes
+  // any new compositor frames received with content_source_id less than
+  // |next_source_id| to be discarded.
+  void StartNewContentRenderingTimeout(uint32_t next_source_id);
 
   // Notification that a new compositor frame has been generated following
   // a page load. This stops |new_content_rendering_timeout_|, or prevents
@@ -889,6 +891,14 @@
   // renderer process before clearing any previously displayed content.
   base::TimeDelta new_content_rendering_delay_;
 
+  // This identifier tags compositor frames according to the page load with
+  // which they are associated, to prevent an unloaded web page from being
+  // drawn after a navigation to a new page has already committed. This is
+  // a no-op for non-top-level RenderWidgets, as that should always be zero.
+  // TODO(kenrb, fsamuel): We should use SurfaceIDs for this purpose when they
+  // are available in the renderer process. See https://crbug.com/695579.
+  uint32_t current_content_source_id_;
+
 #if defined(OS_MACOSX)
   std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;
 #endif
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 439ffcc..7b74276 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -1242,7 +1242,7 @@
       base::TimeDelta::FromMicroseconds(10));
 
   // Test immediate start and stop, ensuring that the timeout doesn't fire.
-  host_->StartNewContentRenderingTimeout();
+  host_->StartNewContentRenderingTimeout(0);
   host_->OnFirstPaintAfterLoad();
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
@@ -1254,7 +1254,7 @@
   // Test that the timer doesn't fire if it receives a stop before
   // a start.
   host_->OnFirstPaintAfterLoad();
-  host_->StartNewContentRenderingTimeout();
+  host_->StartNewContentRenderingTimeout(0);
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
       TimeDelta::FromMicroseconds(20));
@@ -1263,7 +1263,7 @@
   EXPECT_FALSE(host_->new_content_rendering_timeout_fired());
 
   // Test with a long delay to ensure that it does fire this time.
-  host_->StartNewContentRenderingTimeout();
+  host_->StartNewContentRenderingTimeout(0);
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
       TimeDelta::FromMicroseconds(20));
@@ -1271,6 +1271,39 @@
   EXPECT_TRUE(host_->new_content_rendering_timeout_fired());
 }
 
+// This tests that a compositor frame received with a stale content source ID
+// in its metadata is properly discarded.
+TEST_F(RenderWidgetHostTest, SwapCompositorFrameWithBadSourceId) {
+  host_->StartNewContentRenderingTimeout(100);
+  host_->OnFirstPaintAfterLoad();
+
+  // First swap a frame with an invalid ID.
+  cc::CompositorFrame frame;
+  frame.metadata.content_source_id = 99;
+  host_->OnMessageReceived(ViewHostMsg_SwapCompositorFrame(
+      0, 0, frame, std::vector<IPC::Message>()));
+  EXPECT_FALSE(
+      static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
+  static_cast<TestView*>(host_->GetView())->reset_did_swap_compositor_frame();
+
+  // Test with a valid content ID as a control.
+  frame.metadata.content_source_id = 100;
+  host_->OnMessageReceived(ViewHostMsg_SwapCompositorFrame(
+      0, 0, frame, std::vector<IPC::Message>()));
+  EXPECT_TRUE(
+      static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
+  static_cast<TestView*>(host_->GetView())->reset_did_swap_compositor_frame();
+
+  // We also accept frames with higher content IDs, to cover the case where
+  // the browser process receives a compositor frame for a new page before
+  // the corresponding DidCommitProvisionalLoad (it's a race).
+  frame.metadata.content_source_id = 101;
+  host_->OnMessageReceived(ViewHostMsg_SwapCompositorFrame(
+      0, 0, frame, std::vector<IPC::Message>()));
+  EXPECT_TRUE(
+      static_cast<TestView*>(host_->GetView())->did_swap_compositor_frame());
+}
+
 TEST_F(RenderWidgetHostTest, TouchEmulator) {
   simulated_event_time_delta_seconds_ = 0.1;
   // Immediately ack all touches instead of sending them to the renderer.
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 774d9cb..5ef2e7b 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -304,6 +304,11 @@
   // in BeginNavigationParams.
   IPC_STRUCT_MEMBER(GURL, searchable_form_url)
   IPC_STRUCT_MEMBER(std::string, searchable_form_encoding)
+
+  // This is a non-decreasing value that the browser process can use to
+  // identify and discard compositor frames that correspond to now-unloaded
+  // web content.
+  IPC_STRUCT_MEMBER(uint32_t, content_source_id)
 IPC_STRUCT_END()
 
 IPC_STRUCT_BEGIN(FrameMsg_PostMessage_Params)
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 8852de8..f6803022 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -544,12 +544,6 @@
       "media/aec_dump_message_filter.h",
       "media/audio_repetition_detector.cc",
       "media/audio_repetition_detector.h",
-      "media/capturefromelement/canvas_capture_handler.cc",
-      "media/capturefromelement/canvas_capture_handler.h",
-      "media/capturefromelement/html_audio_element_capturer_source.cc",
-      "media/capturefromelement/html_audio_element_capturer_source.h",
-      "media/capturefromelement/html_video_element_capturer_source.cc",
-      "media/capturefromelement/html_video_element_capturer_source.h",
       "media/external_media_stream_audio_source.cc",
       "media/external_media_stream_audio_source.h",
       "media/gpu/rtc_video_decoder.cc",
@@ -668,6 +662,12 @@
       "media/webrtc_logging.h",
       "media/webrtc_uma_histograms.cc",
       "media/webrtc_uma_histograms.h",
+      "media_capture_from_element/canvas_capture_handler.cc",
+      "media_capture_from_element/canvas_capture_handler.h",
+      "media_capture_from_element/html_audio_element_capturer_source.cc",
+      "media_capture_from_element/html_audio_element_capturer_source.h",
+      "media_capture_from_element/html_video_element_capturer_source.cc",
+      "media_capture_from_element/html_video_element_capturer_source.h",
       "media_recorder/audio_track_recorder.cc",
       "media_recorder/audio_track_recorder.h",
       "media_recorder/media_recorder_handler.cc",
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index f1c6a7b5..ec1b8579 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -1130,4 +1130,8 @@
   is_for_oopif_ = is_for_oopif;
 }
 
+void RenderWidgetCompositor::SetContentSourceId(uint32_t id) {
+  layer_tree_host_->SetContentSourceId(id);
+}
+
 }  // namespace content
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h
index 99cfc21..2367818 100644
--- a/content/renderer/gpu/render_widget_compositor.h
+++ b/content/renderer/gpu/render_widget_compositor.h
@@ -113,6 +113,7 @@
   void SetPaintedDeviceScaleFactor(float device_scale);
   void SetDeviceColorSpace(const gfx::ColorSpace& color_space);
   void SetIsForOopif(bool is_for_oopif);
+  void SetContentSourceId(uint32_t);
 
   // WebLayerTreeView implementation.
   cc::FrameSinkId getFrameSinkId() override;
diff --git a/content/renderer/media_capture_from_element/DEPS b/content/renderer/media_capture_from_element/DEPS
new file mode 100644
index 0000000..54f5844e
--- /dev/null
+++ b/content/renderer/media_capture_from_element/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/libyuv",
+]
diff --git a/content/renderer/media/capturefromelement/OWNERS b/content/renderer/media_capture_from_element/OWNERS
similarity index 100%
rename from content/renderer/media/capturefromelement/OWNERS
rename to content/renderer/media_capture_from_element/OWNERS
diff --git a/content/renderer/media/capturefromelement/canvas_capture_handler.cc b/content/renderer/media_capture_from_element/canvas_capture_handler.cc
similarity index 98%
rename from content/renderer/media/capturefromelement/canvas_capture_handler.cc
rename to content/renderer/media_capture_from_element/canvas_capture_handler.cc
index b462e73..92737980 100644
--- a/content/renderer/media/capturefromelement/canvas_capture_handler.cc
+++ b/content/renderer/media_capture_from_element/canvas_capture_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/capturefromelement/canvas_capture_handler.h"
+#include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
 
 #include <utility>
 
diff --git a/content/renderer/media/capturefromelement/canvas_capture_handler.h b/content/renderer/media_capture_from_element/canvas_capture_handler.h
similarity index 94%
rename from content/renderer/media/capturefromelement/canvas_capture_handler.h
rename to content/renderer/media_capture_from_element/canvas_capture_handler.h
index 9a0cb4b..b99d71a3 100644
--- a/content/renderer/media/capturefromelement/canvas_capture_handler.h
+++ b/content/renderer/media_capture_from_element/canvas_capture_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_CANVAS_CAPTURE_HANDLER_H_
-#define CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_CANVAS_CAPTURE_HANDLER_H_
+#ifndef CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_
+#define CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -106,4 +106,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_CANVAS_CAPTURE_HANDLER_H_
+#endif  // CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_
diff --git a/content/renderer/media/capturefromelement/canvas_capture_handler_unittest.cc b/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
similarity index 98%
rename from content/renderer/media/capturefromelement/canvas_capture_handler_unittest.cc
rename to content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
index 5a592893..165e425 100644
--- a/content/renderer/media/capturefromelement/canvas_capture_handler_unittest.cc
+++ b/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/child/child_process.h"
-#include "content/renderer/media/capturefromelement/canvas_capture_handler.h"
 #include "content/renderer/media/media_stream_video_capturer_source.h"
+#include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
 #include "media/base/limits.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/renderer/media/capturefromelement/html_audio_element_capturer_source.cc b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
similarity index 96%
rename from content/renderer/media/capturefromelement/html_audio_element_capturer_source.cc
rename to content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
index ea23efdd..e88b06d8 100644
--- a/content/renderer/media/capturefromelement/html_audio_element_capturer_source.cc
+++ b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/capturefromelement/html_audio_element_capturer_source.h"
+#include "content/renderer/media_capture_from_element/html_audio_element_capturer_source.h"
 
 #include "base/threading/thread_task_runner_handle.h"
 #include "media/base/audio_parameters.h"
diff --git a/content/renderer/media/capturefromelement/html_audio_element_capturer_source.h b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.h
similarity index 86%
rename from content/renderer/media/capturefromelement/html_audio_element_capturer_source.h
rename to content/renderer/media_capture_from_element/html_audio_element_capturer_source.h
index 9fe33c6..351e18e 100644
--- a/content/renderer/media/capturefromelement/html_audio_element_capturer_source.h
+++ b/content/renderer/media_capture_from_element/html_audio_element_capturer_source.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
-#define CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
+#ifndef CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
+#define CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
@@ -60,4 +60,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
+#endif  // CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_AUDIO_ELEMENT_CAPTURER_SOURCE_H_
diff --git a/content/renderer/media/capturefromelement/html_audio_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
similarity index 98%
rename from content/renderer/media/capturefromelement/html_audio_element_capturer_source_unittest.cc
rename to content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
index 0ef426f..ce3a94d8a5 100644
--- a/content/renderer/media/capturefromelement/html_audio_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc
@@ -6,8 +6,8 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/public/renderer/media_stream_audio_sink.h"
-#include "content/renderer/media/capturefromelement/html_audio_element_capturer_source.h"
 #include "content/renderer/media/media_stream_audio_track.h"
+#include "content/renderer/media_capture_from_element/html_audio_element_capturer_source.h"
 #include "media/audio/null_audio_sink.h"
 #include "media/base/audio_parameters.h"
 #include "media/base/fake_audio_render_callback.h"
diff --git a/content/renderer/media/capturefromelement/html_video_element_capturer_source.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
similarity index 98%
rename from content/renderer/media/capturefromelement/html_video_element_capturer_source.cc
rename to content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
index cecd54ef..896bda8 100644
--- a/content/renderer/media/capturefromelement/html_video_element_capturer_source.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/renderer/media/capturefromelement/html_video_element_capturer_source.h"
+#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
 
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
diff --git a/content/renderer/media/capturefromelement/html_video_element_capturer_source.h b/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
similarity index 91%
rename from content/renderer/media/capturefromelement/html_video_element_capturer_source.h
rename to content/renderer/media_capture_from_element/html_video_element_capturer_source.h
index e13c42e..4621b2f 100644
--- a/content/renderer/media/capturefromelement/html_video_element_capturer_source.h
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
-#define CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
+#ifndef CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
+#define CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
@@ -84,4 +84,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_RENDERER_MEDIA_CAPTUREFROMELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
+#endif  // CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_HTML_VIDEO_ELEMENT_CAPTURER_SOURCE_H_
diff --git a/content/renderer/media/capturefromelement/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
similarity index 98%
rename from content/renderer/media/capturefromelement/html_video_element_capturer_source_unittest.cc
rename to content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
index d054be7..16e92a4 100644
--- a/content/renderer/media/capturefromelement/html_video_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "content/renderer/media/capturefromelement/html_video_element_capturer_source.h"
+#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
 #include "media/base/limits.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 4af9b671..20e835f6 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3607,6 +3607,7 @@
   // For new page navigations, the browser process needs to be notified of the
   // first paint of that page, so it can cancel the timer that waits for it.
   if (is_main_frame_ && !navigation_state->WasWithinSamePage()) {
+    GetRenderWidget()->IncrementContentSourceId();
     render_view_->QueueMessage(
         new ViewHostMsg_DidFirstPaintAfterLoad(render_view_->routing_id_),
         MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
@@ -4879,6 +4880,8 @@
   // corresponding FrameNavigationEntry.
   params.page_state = SingleHistoryItemToPageState(item);
 
+  params.content_source_id = GetRenderWidget()->GetContentSourceId();
+
   params.method = request.httpMethod().latin1();
   if (params.method == "POST")
     params.post_id = ExtractPostId(item);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index f5f43f0..6a4442fa 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -378,6 +378,7 @@
       focused_pepper_plugin_(nullptr),
       time_to_first_active_paint_recorded_(true),
       was_shown_time_(base::TimeTicks::Now()),
+      current_content_source_id_(0),
       weak_ptr_factory_(this) {
   DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
   if (!swapped_out)
@@ -1286,6 +1287,7 @@
   compositor_->setViewportSize(physical_backing_size_);
   OnDeviceScaleFactorChanged();
   compositor_->SetDeviceColorSpace(screen_info_.icc_profile.GetColorSpace());
+  compositor_->SetContentSourceId(current_content_source_id_);
   // For background pages and certain tests, we don't want to trigger
   // CompositorFrameSink creation.
   if (compositor_never_visible_ || !RenderThreadImpl::current())
@@ -2300,6 +2302,15 @@
                                      possible_drag_event_info_));
 }
 
+uint32_t RenderWidget::GetContentSourceId() {
+  return current_content_source_id_;
+}
+
+void RenderWidget::IncrementContentSourceId() {
+  if (compositor_)
+    compositor_->SetContentSourceId(++current_content_source_id_);
+}
+
 blink::WebWidget* RenderWidget::GetWebWidget() const {
   return webwidget_internal_;
 }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index e808bcc2..e43cd4d 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -414,6 +414,9 @@
   virtual void TransferActiveWheelFlingAnimation(
       const blink::WebActiveWheelFlingParameters& params) {}
 
+  uint32_t GetContentSourceId();
+  void IncrementContentSourceId();
+
  protected:
   // Friend RefCounted so that the dtor can be non-public. Using this class
   // without ref-counting is an error.
@@ -847,6 +850,19 @@
   bool time_to_first_active_paint_recorded_;
   base::TimeTicks was_shown_time_;
 
+  // This is initialized to zero and is incremented on each non-same-page
+  // navigation commit by RenderFrameImpl. At that time it is sent to the
+  // compositor so that it can tag compositor frames, and RenderFrameImpl is
+  // responsible for sending it to the browser process to be used to match
+  // each compositor frame to the most recent page navigation before it was
+  // generated.
+  // This only applies to main frames, and is not touched for subframe
+  // RenderWidgets, where there is no concern around displaying unloaded
+  // content.
+  // TODO(kenrb, fsamuel): This should be removed when SurfaceIDs can be used
+  // to replace it. See https://crbug.com/695579.
+  uint32_t current_content_source_id_;
+
   base::WeakPtrFactory<RenderWidget> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidget);
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index ed2baee5..175cc09 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -56,12 +56,12 @@
 #include "content/renderer/gamepad_shared_memory_reader.h"
 #include "content/renderer/media/audio_decoder.h"
 #include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/capturefromelement/canvas_capture_handler.h"
-#include "content/renderer/media/capturefromelement/html_audio_element_capturer_source.h"
-#include "content/renderer/media/capturefromelement/html_video_element_capturer_source.h"
 #include "content/renderer/media/image_capture_frame_grabber.h"
 #include "content/renderer/media/renderer_webaudiodevice_impl.h"
 #include "content/renderer/media/renderer_webmidiaccessor_impl.h"
+#include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
+#include "content/renderer/media_capture_from_element/html_audio_element_capturer_source.h"
+#include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h"
 #include "content/renderer/media_recorder/media_recorder_handler.h"
 #include "content/renderer/mojo/blink_interface_provider_impl.h"
 #include "content/renderer/render_thread_impl.h"
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 7cb5934..ccdc8d7 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1575,9 +1575,6 @@
       "../browser/webrtc/webrtc_eventlog_host_unittest.cc",
       "../browser/webrtc/webrtc_internals_unittest.cc",
       "../renderer/media/audio_repetition_detector_unittest.cc",
-      "../renderer/media/capturefromelement/canvas_capture_handler_unittest.cc",
-      "../renderer/media/capturefromelement/html_audio_element_capturer_source_unittest.cc",
-      "../renderer/media/capturefromelement/html_video_element_capturer_source_unittest.cc",
       "../renderer/media/gpu/rtc_video_decoder_unittest.cc",
       "../renderer/media/gpu/rtc_video_encoder_unittest.cc",
       "../renderer/media/media_devices_event_dispatcher_unittest.cc",
@@ -1614,6 +1611,9 @@
       "../renderer/media/webrtc_audio_renderer_unittest.cc",
       "../renderer/media/webrtc_local_audio_source_provider_unittest.cc",
       "../renderer/media/webrtc_uma_histograms_unittest.cc",
+      "../renderer/media_capture_from_element/canvas_capture_handler_unittest.cc",
+      "../renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc",
+      "../renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc",
       "../renderer/media_recorder/audio_track_recorder_unittest.cc",
       "../renderer/media_recorder/media_recorder_handler_unittest.cc",
       "../renderer/media_recorder/video_track_recorder_unittest.cc",
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index 252a22d..6a9a4f58 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -111,6 +111,7 @@
   bool is_showing() const { return is_showing_; }
   bool is_occluded() const { return is_occluded_; }
   bool did_swap_compositor_frame() const { return did_swap_compositor_frame_; }
+  void reset_did_swap_compositor_frame() { did_swap_compositor_frame_ = false; }
 
  protected:
   RenderWidgetHostImpl* rwh_;
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 04415d9..7cca2165 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -170,6 +170,7 @@
       "//device/usb:test_support",
       "//device/usb/mojo",
       "//device/usb/public/interfaces",
+      "//net:test_support",
     ]
   }
 
diff --git a/device/test/DEPS b/device/test/DEPS
index b4a8f734..ad987c5 100644
--- a/device/test/DEPS
+++ b/device/test/DEPS
@@ -2,5 +2,6 @@
   "+mojo/edk/embedder",
   "+net/base",
   "+net/proxy",
+  "+net/traffic_annotation",
   "+net/url_request",
 ]
diff --git a/device/test/usb_test_gadget_impl.cc b/device/test/usb_test_gadget_impl.cc
index ddb79c4..4c1c479 100644
--- a/device/test/usb_test_gadget_impl.cc
+++ b/device/test/usb_test_gadget_impl.cc
@@ -34,6 +34,7 @@
 #include "device/usb/usb_service.h"
 #include "net/base/escape.h"
 #include "net/proxy/proxy_service.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context.h"
@@ -130,8 +131,8 @@
     const GURL& url,
     net::URLFetcher::RequestType request_type,
     net::URLFetcherDelegate* delegate) {
-  std::unique_ptr<net::URLFetcher> url_fetcher =
-      net::URLFetcher::Create(url, request_type, delegate);
+  std::unique_ptr<net::URLFetcher> url_fetcher = net::URLFetcher::Create(
+      url, request_type, delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
 
   url_fetcher->SetRequestContext(request_context_getter.get());
 
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc b/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc
index e85f23be..4d03ea6 100644
--- a/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc
+++ b/gpu/ipc/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc
@@ -9,8 +9,8 @@
 #include "base/memory/ptr_util.h"
 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/public/client_native_pixmap_factory.h"
-#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.cc b/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.cc
index 8b266b8..78ba19e 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.cc
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.cc
@@ -4,10 +4,10 @@
 
 #include "gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.h"
 
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/gl/gl_image_ozone_native_pixmap.h"
 #include "ui/ozone/public/client_native_pixmap.h"
 #include "ui/ozone/public/client_native_pixmap_factory.h"
-#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.h b/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.h
index 45be752..de5ee21 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.h
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_ozone_native_pixmap.h
@@ -14,7 +14,7 @@
 #include "gpu/command_buffer/service/image_factory.h"
 #include "gpu/gpu_export.h"
 #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
-#include "ui/ozone/public/native_pixmap.h"
+#include "ui/gfx/native_pixmap.h"
 
 namespace gl {
 class GLImage;
diff --git a/media/gpu/vaapi_drm_picture.cc b/media/gpu/vaapi_drm_picture.cc
index c61d12ce..dbfb96a 100644
--- a/media/gpu/vaapi_drm_picture.cc
+++ b/media/gpu/vaapi_drm_picture.cc
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "media/gpu/vaapi_drm_picture.h"
+
 #include "base/file_descriptor_posix.h"
 #include "media/gpu/va_surface.h"
-#include "media/gpu/vaapi_drm_picture.h"
 #include "media/gpu/vaapi_wrapper.h"
 #include "third_party/libva/va/drm/va_drm.h"
 #include "third_party/libva/va/va.h"
 #include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/scoped_binders.h"
 #include "ui/ozone/gl/gl_image_ozone_native_pixmap.h"
-#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc
index cb1bed9..aab37255 100644
--- a/media/gpu/video_decode_accelerator_unittest.cc
+++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -85,7 +85,7 @@
 #endif  // OS_WIN
 
 #if defined(USE_OZONE)
-#include "ui/ozone/public/native_pixmap.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/public/ozone_gpu_test_helper.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 5334ba8..63e6426 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -4481,6 +4481,7 @@
     "quic/core/quic_versions_test.cc",
     "quic/core/quic_write_blocked_list_test.cc",
     "quic/core/spdy_utils_test.cc",
+    "quic/platform/api/quic_endian_test.cc",
     "quic/platform/api/quic_estimate_memory_usage.h",
     "quic/platform/api/quic_hostname_utils_test.cc",
     "quic/platform/api/quic_lru_cache_test.cc",
diff --git a/net/quic/platform/api/quic_endian.h b/net/quic/platform/api/quic_endian.h
index ae58b8b2..adf5c52 100644
--- a/net/quic/platform/api/quic_endian.h
+++ b/net/quic/platform/api/quic_endian.h
@@ -13,6 +13,7 @@
 // to/from host order (can be either little or big endian depending on the
 // platform).
 class QuicEndian {
+ public:
   // Convert |x| from host order (can be either little or big endian depending
   // on the platform) to network order (big endian).
   static uint16_t HostToNet16(uint16_t x) {
@@ -36,6 +37,11 @@
   static uint64_t NetToHost64(uint64_t x) {
     return QuicEndianImpl::NetToHost64(x);
   }
+
+  // Returns true if current host order is little endian.
+  static bool HostIsLittleEndian() {
+    return QuicEndianImpl::HostIsLittleEndian();
+  }
 };
 
 }  // namespace net
diff --git a/net/quic/platform/api/quic_endian_test.cc b/net/quic/platform/api/quic_endian_test.cc
new file mode 100644
index 0000000..5b63dd9
--- /dev/null
+++ b/net/quic/platform/api/quic_endian_test.cc
@@ -0,0 +1,49 @@
+// 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/quic/platform/api/quic_endian.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+namespace {
+
+const uint16_t k16BitTestData = 0xaabb;
+const uint16_t k16BitSwappedTestData = 0xbbaa;
+const uint32_t k32BitTestData = 0xaabbccdd;
+const uint32_t k32BitSwappedTestData = 0xddccbbaa;
+const uint64_t k64BitTestData = 0xaabbccdd44332211;
+const uint64_t k64BitSwappedTestData = 0x11223344ddccbbaa;
+
+TEST(QuicEndianTest, HostToNet) {
+  if (QuicEndian::HostIsLittleEndian()) {
+    EXPECT_EQ(k16BitSwappedTestData, QuicEndian::HostToNet16(k16BitTestData));
+    EXPECT_EQ(k32BitSwappedTestData, QuicEndian::HostToNet32(k32BitTestData));
+    EXPECT_EQ(k64BitSwappedTestData, QuicEndian::HostToNet64(k64BitTestData));
+  } else {
+    EXPECT_EQ(k16BitTestData, QuicEndian::HostToNet16(k16BitTestData));
+    EXPECT_EQ(k32BitTestData, QuicEndian::HostToNet32(k32BitTestData));
+    EXPECT_EQ(k64BitTestData, QuicEndian::HostToNet64(k64BitTestData));
+  }
+}
+
+TEST(QuicEndianTest, NetToHost) {
+  if (QuicEndian::HostIsLittleEndian()) {
+    EXPECT_EQ(k16BitTestData, QuicEndian::NetToHost16(k16BitSwappedTestData));
+    EXPECT_EQ(k32BitTestData, QuicEndian::NetToHost32(k32BitSwappedTestData));
+    EXPECT_EQ(k64BitTestData, QuicEndian::NetToHost64(k64BitSwappedTestData));
+  } else {
+    EXPECT_EQ(k16BitSwappedTestData,
+              QuicEndian::NetToHost16(k16BitSwappedTestData));
+    EXPECT_EQ(k32BitSwappedTestData,
+              QuicEndian::NetToHost32(k32BitSwappedTestData));
+    EXPECT_EQ(k64BitSwappedTestData,
+              QuicEndian::NetToHost64(k64BitSwappedTestData));
+  }
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace net
diff --git a/net/quic/platform/impl/quic_endian_impl.h b/net/quic/platform/impl/quic_endian_impl.h
index 4bcb3bb2..d4adfcd 100644
--- a/net/quic/platform/impl/quic_endian_impl.h
+++ b/net/quic/platform/impl/quic_endian_impl.h
@@ -13,15 +13,24 @@
  public:
   // Convert |x| from host order (can be either little or big endian depending
   // on the platform) to network order (big endian).
-  static uint16_t HostToNet16(uint16_t x) { return HostToNet16(x); }
-  static uint32_t HostToNet32(uint32_t x) { return HostToNet32(x); }
-  static uint64_t HostToNet64(uint64_t x) { return HostToNet64(x); }
+  static uint16_t HostToNet16(uint16_t x) { return base::HostToNet16(x); }
+  static uint32_t HostToNet32(uint32_t x) { return base::HostToNet32(x); }
+  static uint64_t HostToNet64(uint64_t x) { return base::HostToNet64(x); }
 
   // Convert |x| from network order (big endian) to host order (can be either
   // little or big endian depending on the platform).
-  static uint16_t NetToHost16(uint16_t x) { return NetToHost16(x); }
-  static uint32_t NetToHost32(uint32_t x) { return NetToHost32(x); }
-  static uint64_t NetToHost64(uint64_t x) { return NetToHost64(x); }
+  static uint16_t NetToHost16(uint16_t x) { return base::NetToHost16(x); }
+  static uint32_t NetToHost32(uint32_t x) { return base::NetToHost32(x); }
+  static uint64_t NetToHost64(uint64_t x) { return base::NetToHost64(x); }
+
+  // Returns true if current host order is little endian.
+  static bool HostIsLittleEndian() {
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+    return true;
+#else
+    return false;
+#endif
+  }
 };
 
 }  // namespace net
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/echo-content.php b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/echo-content.php
new file mode 100644
index 0000000..7e851dd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/echo-content.php
@@ -0,0 +1,4 @@
+<?php
+header('Content-Type: text/plain');
+echo file_get_contents('php://input');
+?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/send-entity-body-basic.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/send-entity-body-basic.html
new file mode 100644
index 0000000..e176b35
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/send-entity-body-basic.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+  <head>
+    <title>XMLHttpRequest: send() - data argument</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="/following::ol/li[4]" />
+  </head>
+  <body>
+    <div id="log"></div>
+    <script>
+      // Taken from http://w3c-test.org/XMLHttpRequest/send-entity-body-basic.htm
+
+      function request(input, output) {
+        test(function() {
+          var client = new XMLHttpRequest()
+          client.open("POST", "resources/echo-content.php", false)
+          client.send(input)
+          assert_equals(client.responseText, output)
+        }, document.title + " (" + output + ")")
+      }
+      request(1, "1")
+      request(10000000, "10000000")
+      request([2,2], "2,2")
+      request(false, "false")
+      request("A\0A", "A\0A")
+      request(new URLSearchParams([[1, 2], [3, 4]]), "1=2&3=4")
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/send-entity-body-charset.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/send-entity-body-charset.html
new file mode 100644
index 0000000..4b803086
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/send-entity-body-charset.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+  <head>
+    <title>XMLHttpRequest: send() - data argument</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="/following::ol/li[4]" />
+  </head>
+  <body>
+    <div id="log"></div>
+    <script>
+      function requestCharset(input, charset, contentType) {
+        test(function() {
+          var client = new XMLHttpRequest();
+          client.open("POST", "print-content-type.cgi", false);
+          if (contentType)
+            client.setRequestHeader("Content-Type", contentType);
+          client.send(input);
+          assert_true(client.responseText.indexOf("charset=" + charset) >= 0);
+        }, document.title + " (" + input + " requested with charset=" + charset + ")")
+      }
+      requestCharset(1, "UTF-8");
+      requestCharset(1, "UTF-8", "application/javascript;charset=us-ascii");
+      requestCharset(new URLSearchParams([[1, 2], [3, 4]]), "UTF-8");
+      requestCharset(new URLSearchParams([[1, 2], [3, 4]]), "UTF-8", "text/javascript;charset=us-ascii");
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/track/captions-webvtt/tc017-line-position-bad.vtt b/third_party/WebKit/LayoutTests/media/track/captions-webvtt/tc017-line-position-bad.vtt
index 9eff499..3d521757 100644
--- a/third_party/WebKit/LayoutTests/media/track/captions-webvtt/tc017-line-position-bad.vtt
+++ b/third_party/WebKit/LayoutTests/media/track/captions-webvtt/tc017-line-position-bad.vtt
@@ -7,11 +7,6 @@
 Negative percentages are not allowed.
 Line position is ignored.
 
-00:00:15.500 --> 00:00:30.500 line:0.5
-Bear is Coming!!!!!
-Fractions of lines are not allowed.
-Line position is ignored.
-
 2
 00:00:31.000 --> 00:00:45.500 line:+50%
 I said Bear is coming!!!!
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/001-expected.txt b/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/001-expected.txt
new file mode 100644
index 0000000..e611ba2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/001-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+PASS WebVTT parser tests, settings-vertical.vtt 
+PASS WebVTT parser tests, settings-size.vtt 
+PASS WebVTT parser tests, settings-position.vtt 
+PASS WebVTT parser tests, settings-multiple.vtt 
+FAIL WebVTT parser tests, settings-line.vtt assert_equals: line (cue 10) expected 1e+34 but got 9.999999790214768e+33
+PASS WebVTT parser tests, settings-align.vtt 
+PASS WebVTT parser tests, signature-bom.vtt 
+PASS WebVTT parser tests, signature-space.vtt 
+PASS WebVTT parser tests, signature-space-no-newline.vtt 
+PASS WebVTT parser tests, signature-tab.vtt 
+PASS WebVTT parser tests, signature-tab-no-newline.vtt 
+PASS WebVTT parser tests, signature-timings.vtt 
+PASS WebVTT parser tests, signature-two-boms.vtt 
+PASS WebVTT parser tests, signature-lowercase.vtt 
+PASS WebVTT parser tests, signature-too-short.vtt 
+PASS WebVTT parser tests, signature-websrt.vtt 
+PASS WebVTT parser tests, signature-formfeed.vtt 
+PASS WebVTT parser tests, signature-null.vtt 
+PASS WebVTT parser tests, signature-no-newline.vtt 
+PASS WebVTT parser tests, no-signature.vtt 
+PASS WebVTT parser tests, nulls.vtt 
+PASS WebVTT parser tests, header-garbage.vtt 
+PASS WebVTT parser tests, header-timings.vtt 
+PASS WebVTT parser tests, header-space.vtt 
+PASS WebVTT parser tests, header-tab.vtt 
+PASS WebVTT parser tests, ids.vtt 
+PASS WebVTT parser tests, arrows.vtt 
+PASS WebVTT parser tests, space-chars.vtt 
+PASS WebVTT parser tests, timings-garbage.vtt 
+PASS WebVTT parser tests, timings-too-short.vtt 
+PASS WebVTT parser tests, timings-too-long.vtt 
+PASS WebVTT parser tests, newlines.vtt 
+PASS WebVTT parser tests, omitted-hours.vtt 
+PASS WebVTT parser tests, timings-60.vtt 
+PASS WebVTT parser tests, timings-negative.vtt 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/support/settings-line.vtt b/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/support/settings-line.vtt
index 7d49fce..54b3b14 100644
--- a/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/support/settings-line.vtt
+++ b/third_party/WebKit/LayoutTests/media/track/opera/track/webvtt/parsing/support/settings-line.vtt
@@ -22,13 +22,13 @@
 {"line":65536}
 
 00:00:00.000 --> 00:00:01.000 line:4294967296
-{"line":2147483648}
+{"line":4294967296}
 
 00:00:00.000 --> 00:00:01.000 line:18446744073709552000
-{"line":2147483648}
+{"line":18446744073709552000}
 
 00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000
-{"line":2147483648}
+{"line":10000000000000000000000000000000000}
 
 00:00:00.000 --> 00:00:01.000 line:65536%
 {}
@@ -43,10 +43,10 @@
 {}
 
 00:00:00.000 --> 00:00:01.000 line:1.5
-{}
+{"line":1.5}
 
 00:00:00.000 --> 00:00:01.000 line:-50.5
-{}
+{"line":-50.5}
 
 00:00:00.000 --> 00:00:01.000 line:0%
 {"snapToLines":false, "line":0}
diff --git a/third_party/WebKit/LayoutTests/media/track/track-webvtt-tc017-line-position.html b/third_party/WebKit/LayoutTests/media/track/track-webvtt-tc017-line-position.html
index 2e77b93..8594214a 100644
--- a/third_party/WebKit/LayoutTests/media/track/track-webvtt-tc017-line-position.html
+++ b/third_party/WebKit/LayoutTests/media/track/track-webvtt-tc017-line-position.html
@@ -49,11 +49,10 @@
             { line : "auto", snapToLines : true },
             { line : "auto", snapToLines : true },
             { line : "auto", snapToLines : true },
-            { line : "auto", snapToLines : true },
             { line : "auto", snapToLines : true }
         ];
 
         assert_cues_match(video.textTracks[index].cues, expected);
     }
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-repaint.html b/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-repaint.html
index d0185bc6..d12c6bd 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-repaint.html
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-repaint.html
@@ -1,30 +1,31 @@
 <!DOCTYPE html>
 <style>
-    ::selection {
+    #t1::selection {
         background-color: transparent;
         color: red
     }
     .green::selection {
-        color: green
+        color: green !important
     }
 </style>
-<span id="t1">This text should be green.</span>
+<span id="t1">This text </span><span id="t2">should be green.</span>
 <script>
     if (window.testRunner)
         testRunner.waitUntilDone();
 
-    function setSelection(textNode) {
+    function setSelection(startNode, endNode) {
         window.getSelection().removeAllRanges();
         var range = document.createRange();
-        range.setStart(textNode, 0);
-        range.setEnd(textNode, textNode.data.length);
+        range.setStart(startNode, 0);
+        range.setEnd(endNode, endNode.data.length);
         window.getSelection().addRange(range);
     }
 
-    setSelection(t1.firstChild);
+    setSelection(t1.firstChild, t2.firstChild);
     requestAnimationFrame(() =>
         requestAnimationFrame(() => {
             t1.className = "green";
+            t2.className = "green";
             if (window.testRunner)
                 testRunner.notifyDone();
         }));
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index b4c5075..8856cdc 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -156,8 +156,8 @@
   "$bindings_core_v8_output_dir/AddEventListenerOptionsOrBoolean.h",
   "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferView.cpp",
   "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferView.h",
-  "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData.cpp",
-  "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData.h",
+  "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams.cpp",
+  "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams.h",
   "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferViewOrBlobOrUSVString.cpp",
   "$bindings_core_v8_output_dir/ArrayBufferOrArrayBufferViewOrBlobOrUSVString.h",
   "$bindings_core_v8_output_dir/CSSStyleValueOrCSSStyleValueSequence.cpp",
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_web_module_api_test.py b/third_party/WebKit/Source/bindings/scripts/code_generator_web_agent_api_test.py
similarity index 100%
rename from third_party/WebKit/Source/bindings/scripts/code_generator_web_module_api_test.py
rename to third_party/WebKit/Source/bindings/scripts/code_generator_web_agent_api_test.py
diff --git a/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm.py b/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm.py
index cda46c2b..7f2803c 100644
--- a/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm.py
+++ b/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm.py
@@ -14,7 +14,43 @@
     return ((k, list(g)) for k, g in itertools.groupby(list_to_sort, key))
 
 
-def effective_overload_set(F):  # pylint: disable=invalid-name
+class OverloadSetAdapter(object):
+    """Base class for the second effective_overload_set argument. Python is
+       a type-lax language, so this is mostly documentation of the expected
+       interface."""
+
+    def arguments(self, operation):
+        """Given an operation, return the list of its arguments."""
+        raise NotImplementedError
+
+    def type(self, argument):
+        """Given an argument, return its type."""
+        raise NotImplementedError
+
+    def is_optional(self, argument):
+        """Given an argument, return whether it is optional."""
+        raise NotImplementedError
+
+    def is_variadic(self, argument):
+        """"Given an argument, return whether it is variadic."""
+        raise NotImplementedError
+
+
+class MethodContextAdapter(OverloadSetAdapter):
+    def arguments(self, operation):
+        return operation['arguments']
+
+    def type(self, argument):
+        return argument['idl_type_object']
+
+    def is_optional(self, argument):
+        return argument['is_optional']
+
+    def is_variadic(self, argument):
+        return argument['is_variadic']
+
+
+def effective_overload_set(F, adapter):  # pylint: disable=invalid-name
     """Returns the effective overload set of an overloaded function.
 
     An effective overload set is the set of overloaded functions + signatures
@@ -45,6 +81,7 @@
 
     Arguments:
         F: list of overloads for a given callable name.
+        value_reader: an OverloadSetValueReader instance.
 
     Returns:
         S: list of tuples of the form (callable, type list, optionality list).
@@ -64,21 +101,22 @@
 
     # 5. For each operation, extended attribute or callback function X in F:
     for X in F:  # X is the "callable". pylint: disable=invalid-name
-        arguments = X['arguments']  # pylint: disable=invalid-name
+        arguments = adapter.arguments(X)  # pylint: disable=invalid-name
         # 1. Let n be the number of arguments X is declared to take.
         n = len(arguments)  # pylint: disable=invalid-name
         # 2. Let t0..n−1 be a list of types, where ti is the type of X’s
         # argument at index i.
         # (“type list”)
-        t = tuple(argument['idl_type_object']  # pylint: disable=invalid-name
+        t = tuple(adapter.type(argument)  # pylint: disable=invalid-name
                   for argument in arguments)
         # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic”
         # if X’s argument at index i is a final, variadic argument, “optional”
         # if the argument is optional, and “required” otherwise.
         # (“optionality list”)
         # (We’re just using a boolean for optional/variadic vs. required.)
-        o = tuple(argument['is_optional']  # pylint: disable=invalid-name
-                  or argument['is_variadic'] for argument in arguments)
+        o = tuple(adapter.is_optional(argument)  # pylint: disable=invalid-name
+                  or adapter.is_variadic(argument)
+                  for argument in arguments)
         # 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
         S.append((X, t, o))
         # 5. If X is declared to be variadic, then:
@@ -99,7 +137,7 @@
         # 8. If n > 0 and all arguments of X are optional, then add to S the
         # tuple <X, (), ()> (where “()” represents the empty list).
         if n > 0 and all(oi for oi in o):
-            S.append((X, [], []))
+            S.append((X, (), ()))
     # 6. The effective overload set is S.
     return S
 
@@ -110,7 +148,8 @@
         # (callable, type list, optionality list)
         return len(entry[1])
 
-    effective_overloads = effective_overload_set(overloads)
+    effective_overloads = effective_overload_set(overloads,
+                                                 MethodContextAdapter())
     return list(sort_and_groupby(effective_overloads, type_list_length))
 
 
diff --git a/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm_test.py b/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm_test.py
new file mode 100644
index 0000000..8a25711
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/scripts/overload_set_algorithm_test.py
@@ -0,0 +1,54 @@
+# 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.
+
+# pylint: disable=import-error,print-statement,relative-import,protected-access
+
+"""Unit tests for overload_set_algorithm.py."""
+
+import unittest
+
+from overload_set_algorithm import effective_overload_set
+from overload_set_algorithm import MethodContextAdapter
+
+
+class MethodContextAdapterTest(unittest.TestCase):
+    def test_simple(self):
+        adapter = MethodContextAdapter()
+        self.assertEqual(adapter.arguments({'arguments': 'foo'}), 'foo')
+        self.assertEqual(adapter.type({'idl_type_object': 'bar'}), 'bar')
+        self.assertEqual(adapter.is_optional({'is_optional': 'baz'}), 'baz')
+        self.assertEqual(adapter.is_variadic({'is_variadic': 'qux'}), 'qux')
+
+
+class EffectiveOverloadSetTest(unittest.TestCase):
+    def test_example_in_comments(self):
+        operation_list = [
+            {'arguments': [{'idl_type_object': 'long',  # f1(optional long x)
+                            'is_optional': True,
+                            'is_variadic': False}]},
+            {'arguments': [{'idl_type_object': 'DOMString',  # f2(DOMString s)
+                            'is_optional': False,
+                            'is_variadic': False}]},
+        ]
+
+        overload_set = [
+            ({'arguments': [{'idl_type_object': 'long',  # f1(long)
+                             'is_optional': True,
+                             'is_variadic': False}]},
+             ('long',),
+             (True,)),
+            ({'arguments': [{'idl_type_object': 'long',  # f1()
+                             'is_optional': True,
+                             'is_variadic': False}]},
+             (),
+             ()),
+            ({'arguments': [{'idl_type_object': 'DOMString',  # f2(DOMString)
+                             'is_optional': False,
+                             'is_variadic': False}]},
+             ('DOMString',),
+             (False,))]
+
+        self.assertEqual(
+            effective_overload_set(operation_list, MethodContextAdapter()),
+            overload_set)
diff --git a/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp b/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp
index ec2b0ea6..17a9100 100644
--- a/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp
+++ b/third_party/WebKit/Source/core/html/track/vtt/VTTCue.cpp
@@ -983,23 +983,38 @@
         //    If parse a percentage string from linepos doesn't fail, let
         //    number be the returned percentage, otherwise jump to the step
         //    labeled next setting.
-        bool isPercentage = scanPercentage(input, number);
-        if (!isPercentage) {
+        bool isPercentage = input.scanPercentage(number);
+        if (isPercentage) {
+          if (isInvalidPercentage(number))
+            break;
+        } else {
           // Otherwise
           //
           // 1. If linepos contains any characters other than U+002D
-          //    HYPHEN-MINUS characters (-) and ASCII digits, then jump to
-          //    the step labeled next setting.
-          // 2. If any character in linepos other than the first character is
-          //    a U+002D HYPHEN-MINUS character (-), then jump to the step
+          //    HYPHEN-MINUS characters (-), ASCII digits, and U+002E DOT
+          //    character (.), then jump to the step labeled next setting.
+          //
+          // 2. If any character in linepos other than the first character is a
+          //    U+002D HYPHEN-MINUS character (-), then jump to the step
           //    labeled next setting.
+          //
+          // 3. If there are more than one U+002E DOT characters (.), then jump
+          //    to the step labeled next setting.
+          //
+          // 4. If there is a U+002E DOT character (.) and the character before
+          //    or the character after is not an ASCII digit, or if the U+002E
+          //    DOT character (.) is the first or the last character, then jump
+          //    to the step labeled next setting.
+          //
+          // 5. Interpret linepos as a (potentially signed) real number, and
+          //    let number be that number.
           bool isNegative = input.scan('-');
-          int intLinePosition;
-          if (!input.scanDigits(intLinePosition))
+          if (!input.scanFloat(number))
             break;
-          // 3. Interpret linepos as a (potentially signed) integer, and let
-          //    number be that number.
-          number = isNegative ? -intLinePosition : intLinePosition;
+          // Negate number if it was preceded by a hyphen-minus - unless it's
+          // zero.
+          if (isNegative && number)
+            number = -number;
         }
         if (!input.isAt(valueRun.end()))
           break;
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 6a2b51a6..eaf1313 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1405,8 +1405,7 @@
   if (!isSelectable())
     return Color::transparent;
 
-  if (RefPtr<ComputedStyle> pseudoStyle =
-          getUncachedPseudoStyleFromParentOrShadowHost())
+  if (RefPtr<ComputedStyle> pseudoStyle = getUncachedSelectionStyle())
     return resolveColor(*pseudoStyle, CSSPropertyBackgroundColor)
         .blendWithWhite();
   return frame()->selection().isFocusedAndActive()
@@ -1422,8 +1421,7 @@
   if (!isSelectable() || (globalPaintFlags & GlobalPaintSelectionOnly))
     return resolveColor(colorProperty);
 
-  if (RefPtr<ComputedStyle> pseudoStyle =
-          getUncachedPseudoStyleFromParentOrShadowHost())
+  if (RefPtr<ComputedStyle> pseudoStyle = getUncachedSelectionStyle())
     return resolveColor(*pseudoStyle, colorProperty);
   if (!LayoutTheme::theme().supportsSelectionForegroundColors())
     return resolveColor(colorProperty);
@@ -3090,11 +3088,15 @@
       element, pseudoStyleRequest, parentStyle, parentStyle);
 }
 
-PassRefPtr<ComputedStyle>
-LayoutObject::getUncachedPseudoStyleFromParentOrShadowHost() const {
+PassRefPtr<ComputedStyle> LayoutObject::getUncachedSelectionStyle() const {
   if (!node())
     return nullptr;
 
+  // In Blink, ::selection only applies to direct children of the element on
+  // which ::selection is matched. In order to be able to style ::selection
+  // inside elements implemented with a UA shadow tree, like input::selection,
+  // we calculate ::selection style on the shadow host for elements inside the
+  // UA shadow.
   if (ShadowRoot* root = node()->containingShadowRoot()) {
     if (root->type() == ShadowRootType::UserAgent) {
       if (Element* shadowHost = node()->ownerShadowHost()) {
@@ -3104,7 +3106,20 @@
     }
   }
 
-  return getUncachedPseudoStyle(PseudoStyleRequest(PseudoIdSelection));
+  // If we request ::selection style for LayoutText, query ::selection style on
+  // the parent element instead, as that is the node for which ::selection
+  // matches.
+  const LayoutObject* selectionLayoutObject = this;
+  Element* element = Traversal<Element>::firstAncestorOrSelf(*node());
+  if (!element)
+    return nullptr;
+  if (element != node()) {
+    selectionLayoutObject = element->layoutObject();
+    if (!selectionLayoutObject)
+      return nullptr;
+  }
+  return selectionLayoutObject->getUncachedPseudoStyle(
+      PseudoStyleRequest(PseudoIdSelection));
 }
 
 void LayoutObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index 3a2b86f..0272622 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -429,10 +429,9 @@
   void addAbsoluteRectForLayer(IntRect& result);
   bool requiresAnonymousTableWrappers(const LayoutObject*) const;
 
-  // Gets pseudoStyle from Shadow host(in case of input elements)
-  // or from Parent element.
-  PassRefPtr<ComputedStyle> getUncachedPseudoStyleFromParentOrShadowHost()
-      const;
+  // Gets ::selection pseudo style from Shadow host(in case of input elements)
+  // or from parent element.
+  PassRefPtr<ComputedStyle> getUncachedSelectionStyle() const;
 
  public:
 #ifndef NDEBUG
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index eae72e1..c74d9e94 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -23,7 +23,8 @@
 
 #include "core/xmlhttprequest/XMLHttpRequest.h"
 
-#include "bindings/core/v8/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData.h"
+#include <memory>
+#include "bindings/core/v8/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams.h"
 #include "bindings/core/v8/ArrayBufferOrArrayBufferViewOrBlobOrUSVString.h"
 #include "bindings/core/v8/DOMWrapperWorld.h"
 #include "bindings/core/v8/ExceptionState.h"
@@ -37,6 +38,7 @@
 #include "core/dom/DocumentParser.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/dom/URLSearchParams.h"
 #include "core/dom/XMLDocument.h"
 #include "core/editing/serializers/Serialization.h"
 #include "core/events/Event.h"
@@ -81,7 +83,6 @@
 #include "wtf/AutoReset.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/text/CString.h"
-#include <memory>
 
 namespace blink {
 
@@ -704,7 +705,8 @@
 }
 
 void XMLHttpRequest::send(
-    const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData& body,
+    const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams&
+        body,
     ExceptionState& exceptionState) {
   probe::willSendXMLHttpOrFetchNetworkRequest(getExecutionContext(), url());
 
@@ -738,6 +740,11 @@
     return;
   }
 
+  if (body.isURLSearchParams()) {
+    send(body.getAsURLSearchParams(), exceptionState);
+    return;
+  }
+
   DCHECK(body.isString());
   send(body.getAsString(), exceptionState);
 }
@@ -784,17 +791,9 @@
   RefPtr<EncodedFormData> httpBody;
 
   if (!body.isNull() && areMethodAndURLValidForSend()) {
-    String contentType = getRequestHeader(HTTPNames::Content_Type);
-    if (contentType.isEmpty()) {
-      setRequestHeaderInternal(HTTPNames::Content_Type,
-                               "text/plain;charset=UTF-8");
-    } else {
-      replaceCharsetInMediaType(contentType, "UTF-8");
-      m_requestHeaders.set(HTTPNames::Content_Type, AtomicString(contentType));
-    }
-
     httpBody = EncodedFormData::create(
         UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
+    updateContentTypeAndCharset("text/plain;charset=UTF-8", "UTF-8");
   }
 
   createRequest(std::move(httpBody), exceptionState);
@@ -846,6 +845,8 @@
   if (areMethodAndURLValidForSend()) {
     httpBody = body->encodeMultiPartFormData();
 
+    // TODO (sof): override any author-provided charset= in the
+    // content type value to UTF-8 ?
     if (getRequestHeader(HTTPNames::Content_Type).isEmpty()) {
       AtomicString contentType =
           AtomicString("multipart/form-data; boundary=") +
@@ -857,6 +858,24 @@
   createRequest(std::move(httpBody), exceptionState);
 }
 
+void XMLHttpRequest::send(URLSearchParams* body,
+                          ExceptionState& exceptionState) {
+  NETWORK_DVLOG(1) << this << " send() URLSearchParams " << body;
+
+  if (!initSend(exceptionState))
+    return;
+
+  RefPtr<EncodedFormData> httpBody;
+
+  if (areMethodAndURLValidForSend()) {
+    httpBody = body->toEncodedFormData();
+    updateContentTypeAndCharset(
+        "application/x-www-form-urlencoded;charset=UTF-8", "UTF-8");
+  }
+
+  createRequest(std::move(httpBody), exceptionState);
+}
+
 void XMLHttpRequest::send(DOMArrayBuffer* body,
                           ExceptionState& exceptionState) {
   NETWORK_DVLOG(1) << this << " send() ArrayBuffer " << body;
@@ -1443,6 +1462,20 @@
   return AtomicString("text/xml");
 }
 
+void XMLHttpRequest::updateContentTypeAndCharset(
+    const AtomicString& defaultContentType,
+    const String& charset) {
+  // http://xhr.spec.whatwg.org/#the-send()-method step 4's concilliation of
+  // "charset=" in any author-provided Content-Type: request header.
+  String contentType = getRequestHeader(HTTPNames::Content_Type);
+  if (contentType.isEmpty()) {
+    setRequestHeaderInternal(HTTPNames::Content_Type, defaultContentType);
+    return;
+  }
+  replaceCharsetInMediaType(contentType, charset);
+  m_requestHeaders.set(HTTPNames::Content_Type, AtomicString(contentType));
+}
+
 bool XMLHttpRequest::responseIsXML() const {
   return DOMImplementation::isXMLMIMEType(finalResponseMIMETypeWithFallback());
 }
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
index ce3ca65f..95bcb2f 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
@@ -48,7 +48,8 @@
 
 namespace blink {
 
-class ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData;
+class
+    ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams;
 class Blob;
 class BlobDataHandle;
 class DOMArrayBuffer;
@@ -62,6 +63,7 @@
 class SharedBuffer;
 class TextResourceDecoder;
 class ThreadableLoader;
+class URLSearchParams;
 class WebDataConsumerHandle;
 class XMLHttpRequestUpload;
 
@@ -133,7 +135,7 @@
             bool async,
             ExceptionState&);
   void send(
-      const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData&,
+      const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormDataOrURLSearchParams&,
       ExceptionState&);
   void abort();
   void dispose();
@@ -234,6 +236,7 @@
   void send(const String&, ExceptionState&);
   void send(Blob*, ExceptionState&);
   void send(FormData*, ExceptionState&);
+  void send(URLSearchParams*, ExceptionState&);
   void send(DOMArrayBuffer*, ExceptionState&);
   void send(DOMArrayBufferView*, ExceptionState&);
 
@@ -277,6 +280,9 @@
                           long long,
                           long long);
 
+  void updateContentTypeAndCharset(const AtomicString& contentType,
+                                   const String& charset);
+
   XMLHttpRequestProgressEventThrottle& progressEventThrottle();
 
   Member<XMLHttpRequestUpload> m_upload;
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.idl b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.idl
index 33b111a0..fbca69ca 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.idl
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.idl
@@ -66,7 +66,7 @@
     readonly attribute XMLHttpRequestUpload upload;
     // TODO(foolip): The data argument should be of type
     // (Document or BodyInit)?
-    [RaisesException] void send(optional (ArrayBuffer or ArrayBufferView or Blob or Document or DOMString or FormData)? body = null);
+    [RaisesException] void send(optional (ArrayBuffer or ArrayBufferView or Blob or Document or DOMString or FormData or URLSearchParams)? body = null);
     void abort();
 
     // response
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3c6c35c6..7a0a2b3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1694,6 +1694,9 @@
 </histogram>
 
 <histogram name="Ash.ActiveTouchPoints">
+  <obsolete>
+    Deprecated 02/2017 due to lack of usage.
+  </obsolete>
   <owner>kuscher@google.com</owner>
   <owner>rbyers@chromium.org</owner>
   <summary>
@@ -1978,6 +1981,9 @@
 </histogram>
 
 <histogram name="Ash.StationaryTouchDuration" units="seconds">
+  <obsolete>
+    Deprecated 02/2017 due to lack of usage.
+  </obsolete>
   <owner>kuscher@google.com</owner>
   <owner>rbyers@chromium.org</owner>
   <summary>The duration of mostly stationary long-duration touches.</summary>
@@ -2073,6 +2079,9 @@
 </histogram>
 
 <histogram name="Ash.TouchMoveInterval" units="ms">
+  <obsolete>
+    Deprecated 02/2017 due to lack of usage.
+  </obsolete>
   <owner>kuscher@google.com</owner>
   <owner>rbyers@chromium.org</owner>
   <summary>The interval between touch-move events.</summary>
@@ -2085,26 +2094,26 @@
 </histogram>
 
 <histogram name="Ash.TouchPositionX" units="pixels">
+  <owner>tdanderson@chromium.org</owner>
   <owner>kuscher@google.com</owner>
-  <owner>rbyers@chromium.org</owner>
   <summary>The position of the touch-events along the X axis.</summary>
 </histogram>
 
 <histogram name="Ash.TouchPositionY" units="pixels">
+  <owner>tdanderson@chromium.org</owner>
   <owner>kuscher@google.com</owner>
-  <owner>rbyers@chromium.org</owner>
   <summary>The position of the touch-events along the Y axis.</summary>
 </histogram>
 
 <histogram name="Ash.TouchRadius" units="pixels">
+  <owner>tdanderson@chromium.org</owner>
   <owner>kuscher@google.com</owner>
-  <owner>rbyers@chromium.org</owner>
   <summary>The radius of a touch event.</summary>
 </histogram>
 
 <histogram name="Ash.TouchStartAfterEnd" units="ms">
+  <owner>tdanderson@chromium.org</owner>
   <owner>kuscher@google.com</owner>
-  <owner>rbyers@chromium.org</owner>
   <summary>
     The interval between the end of a touch-sequence and the start of the next
     touch-sequence.
@@ -2112,6 +2121,9 @@
 </histogram>
 
 <histogram name="Ash.TouchStartBurst">
+  <obsolete>
+    Deprecated 02/2017 due to lack of usage.
+  </obsolete>
   <owner>kuscher@google.com</owner>
   <owner>rbyers@chromium.org</owner>
   <summary>
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index c543ecf3..9fb9e09 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -243,7 +243,6 @@
 
 
 @benchmark.Disabled('win8')  # http://crbug.com/462350
-@benchmark.Disabled('win-reference')  # http://crbug.com/642884
 class BlinkPerfLayout(_BlinkPerfBenchmark):
   tag = 'layout'
   subdir = 'Layout'
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index ebd428c..ba2ed35 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -533,6 +533,7 @@
     "gfx_export.h",
     "mac/io_surface.cc",
     "mac/io_surface.h",
+    "native_pixmap.h",
     "native_pixmap_handle.cc",
     "native_pixmap_handle.h",
   ]
@@ -549,6 +550,7 @@
   defines = [ "GFX_IMPLEMENTATION" ]
 
   deps = [
+    ":native_widget_types",
     "//base",
     "//ui/gfx/geometry",
   ]
diff --git a/ui/ozone/public/native_pixmap.h b/ui/gfx/native_pixmap.h
similarity index 95%
rename from ui/ozone/public/native_pixmap.h
rename to ui/gfx/native_pixmap.h
index 1009535..56ede7c 100644
--- a/ui/ozone/public/native_pixmap.h
+++ b/ui/gfx/native_pixmap.h
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
-#define UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
+#ifndef UI_GFX_NATIVE_PIXMAP_H_
+#define UI_GFX_NATIVE_PIXMAP_H_
 
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "ui/gfx/buffer_types.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/gfx/native_pixmap_handle.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/overlay_transform.h"
@@ -78,4 +79,4 @@
 
 }  // namespace ui
 
-#endif  // UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
+#endif  // UI_GFX_NATIVE_PIXMAP_H_
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn
index b5746be..a39302ed 100644
--- a/ui/ozone/BUILD.gn
+++ b/ui/ozone/BUILD.gn
@@ -67,7 +67,6 @@
     "public/gpu_platform_support_host.h",
     "public/input_controller.cc",
     "public/input_controller.h",
-    "public/native_pixmap.h",
     "public/overlay_candidates_ozone.cc",
     "public/overlay_candidates_ozone.h",
     "public/overlay_manager_ozone.h",
diff --git a/ui/ozone/gl/gl_image_ozone_native_pixmap.h b/ui/ozone/gl/gl_image_ozone_native_pixmap.h
index 744fb62f..b06a288 100644
--- a/ui/ozone/gl/gl_image_ozone_native_pixmap.h
+++ b/ui/ozone/gl/gl_image_ozone_native_pixmap.h
@@ -10,9 +10,9 @@
 #include <string>
 
 #include "ui/gfx/buffer_types.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gl/gl_image_egl.h"
 #include "ui/ozone/gl/ozone_gl_export.h"
-#include "ui/ozone/public/native_pixmap.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc
index 5d125908..8fca083 100644
--- a/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -11,8 +11,8 @@
 #include "chromecast/public/cast_egl_platform.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gfx/vsync_provider.h"
-#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/surface_ozone_canvas.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h
index 1936cd7..bd5dbfa 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -11,8 +11,8 @@
 #include "base/macros.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/platform/drm/gpu/gbm_buffer_base.h"
-#include "ui/ozone/public/native_pixmap.h"
 
 struct gbm_bo;
 
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface.cc b/ui/ozone/platform/drm/gpu/gbm_surface.cc
index ac3c038c..88faac0 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surface.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surface.cc
@@ -7,11 +7,11 @@
 #include <utility>
 
 #include "base/logging.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/ozone/gl/gl_image_ozone_native_pixmap.h"
 #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
 #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
-#include "ui/ozone/public/native_pixmap.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index e45a254..6abf013 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -13,6 +13,7 @@
 #include "build/build_config.h"
 #include "third_party/khronos/EGL/egl.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/ozone/common/egl_util.h"
 #include "ui/ozone/common/gl_ozone_egl.h"
@@ -24,7 +25,6 @@
 #include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h"
 #include "ui/ozone/platform/drm/gpu/proxy_helpers.h"
 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
-#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/surface_ozone_canvas.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 82c927d..7b577900 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -15,12 +15,12 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gfx/swap_result.h"
 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
 #include "ui/ozone/platform/drm/gpu/drm_device.h"
 #include "ui/ozone/platform/drm/gpu/page_flip_request.h"
-#include "ui/ozone/public/native_pixmap.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
index 9882517b..0dbd989 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -9,11 +9,11 @@
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
 #include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
 #include "ui/ozone/platform/drm/gpu/mock_scanout_buffer.h"
-#include "ui/ozone/public/native_pixmap.h"
 
 namespace {
 
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc
index 6b63cc6..73f4cfb 100644
--- a/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -13,11 +13,11 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/vsync_provider.h"
 #include "ui/ozone/platform/headless/headless_window.h"
 #include "ui/ozone/platform/headless/headless_window_manager.h"
-#include "ui/ozone/public/native_pixmap.h"
 #include "ui/ozone/public/surface_ozone_canvas.h"
 
 namespace ui {
diff --git a/ui/ozone/public/surface_factory_ozone.cc b/ui/ozone/public/surface_factory_ozone.cc
index 2926625..4376eea 100644
--- a/ui/ozone/public/surface_factory_ozone.cc
+++ b/ui/ozone/public/surface_factory_ozone.cc
@@ -7,7 +7,7 @@
 #include <stdlib.h>
 
 #include "base/command_line.h"
-#include "ui/ozone/public/native_pixmap.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/ozone/public/surface_ozone_canvas.h"
 
 namespace ui {
diff --git a/ui/ozone/public/surface_factory_ozone.h b/ui/ozone/public/surface_factory_ozone.h
index b230e17..7f1520d 100644
--- a/ui/ozone/public/surface_factory_ozone.h
+++ b/ui/ozone/public/surface_factory_ozone.h
@@ -16,12 +16,12 @@
 #include "base/native_library.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_pixmap.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/overlay_transform.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/ozone/ozone_base_export.h"
 #include "ui/ozone/public/gl_ozone.h"
-#include "ui/ozone/public/native_pixmap.h"
 
 namespace ui {