diff --git a/DEPS b/DEPS
index 41dd62a..36807e5 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'f9b1cd343df071f543f07539513692367af25b06',
+  'v8_revision': '64735758443e0a81a2f8a67338a5203fd725c2f3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
index 69c36f9..a227626 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -208,10 +208,19 @@
 
 void ArcAccessibilityHelperBridge::OnAction(
     const ui::AXActionData& data) const {
-  arc::mojom::AccessibilityActionType mojo_action;
+  arc::mojom::AccessibilityActionDataPtr action_data =
+      arc::mojom::AccessibilityActionData::New();
+
+  action_data->node_id = data.target_node_id;
+
   switch (data.action) {
     case ui::AX_ACTION_DO_DEFAULT:
-      mojo_action = arc::mojom::AccessibilityActionType::CLICK;
+      action_data->action_type = arc::mojom::AccessibilityActionType::CLICK;
+      break;
+    case ui::AX_ACTION_CUSTOM_ACTION:
+      action_data->action_type =
+          arc::mojom::AccessibilityActionType::CUSTOM_ACTION;
+      action_data->custom_action_id = data.custom_action_id;
       break;
     default:
       return;
@@ -219,7 +228,7 @@
 
   auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
       arc_bridge_service()->accessibility_helper(), PerformAction);
-  instance->PerformAction(data.target_node_id, mojo_action);
+  instance->PerformAction(std::move(action_data));
 }
 
 void ArcAccessibilityHelperBridge::OnWindowActivated(
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
index bd69baf..58f8803 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -115,6 +115,34 @@
   return true;
 }
 
+bool GetIntListProperty(arc::mojom::AccessibilityNodeInfoData* node,
+                        arc::mojom::AccessibilityIntListProperty prop,
+                        std::vector<int32_t>* out_value) {
+  if (!node->int_list_properties)
+    return false;
+
+  auto it = node->int_list_properties->find(prop);
+  if (it == node->int_list_properties->end())
+    return false;
+
+  *out_value = it->second;
+  return true;
+}
+
+bool GetStringListProperty(arc::mojom::AccessibilityNodeInfoData* node,
+                           arc::mojom::AccessibilityStringListProperty prop,
+                           std::vector<std::string>* out_value) {
+  if (!node->string_list_properties)
+    return false;
+
+  auto it = node->string_list_properties->find(prop);
+  if (it == node->string_list_properties->end())
+    return false;
+
+  *out_value = it->second;
+  return true;
+}
+
 void PopulateAXRole(arc::mojom::AccessibilityNodeInfoData* node,
                     ui::AXNodeData* out_data) {
   std::string class_name;
@@ -364,8 +392,11 @@
     return;
   out_data->id = node->id;
 
+  using AXIntListProperty = arc::mojom::AccessibilityIntListProperty;
   using AXIntProperty = arc::mojom::AccessibilityIntProperty;
+  using AXStringListProperty = arc::mojom::AccessibilityStringListProperty;
   using AXStringProperty = arc::mojom::AccessibilityStringProperty;
+
   std::string text;
   if (GetStringProperty(node, AXStringProperty::TEXT, &text))
     out_data->SetName(text);
@@ -397,6 +428,25 @@
 
   if (GetIntProperty(node, AXIntProperty::TEXT_SELECTION_END, &val) && val >= 0)
     out_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, val);
+
+  // Custom actions.
+  std::vector<int32_t> custom_action_ids;
+  if (GetIntListProperty(node, AXIntListProperty::CUSTOM_ACTION_IDS,
+                         &custom_action_ids)) {
+    std::vector<std::string> custom_action_descriptions;
+
+    CHECK(GetStringListProperty(
+        node, AXStringListProperty::CUSTOM_ACTION_DESCRIPTIONS,
+        &custom_action_descriptions));
+    CHECK(!custom_action_ids.empty());
+    CHECK_EQ(custom_action_ids.size(), custom_action_descriptions.size());
+
+    out_data->AddAction(ui::AX_ACTION_CUSTOM_ACTION);
+    out_data->AddIntListAttribute(ui::AX_ATTR_CUSTOM_ACTION_IDS,
+                                  custom_action_ids);
+    out_data->AddStringListAttribute(ui::AX_ATTR_CUSTOM_ACTION_DESCRIPTIONS,
+                                     custom_action_descriptions);
+  }
 }
 
 void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) {
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 3871193..064ed25 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -393,6 +393,17 @@
           ui::AX_ACTION_SET_SEQUENTIAL_FOCUS_NAVIGATION_STARTING_POINT;
       break;
     }
+    case api::automation_internal::ACTION_TYPE_CUSTOMACTION: {
+      api::automation_internal::PerformCustomActionParams
+          perform_custom_action_params;
+      EXTENSION_FUNCTION_VALIDATE(
+          api::automation_internal::PerformCustomActionParams::Populate(
+              params->opt_args.additional_properties,
+              &perform_custom_action_params));
+      action->action = ui::AX_ACTION_CUSTOM_ACTION;
+      action->custom_action_id = perform_custom_action_params.custom_action_id;
+      break;
+    }
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js
index a7ac16c..c77635b 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js
@@ -446,6 +446,17 @@
     Panel.addNodeMenu(menuTitle, node, predicate, async);
   }
 
+  // Add actions menu if there are custom actions.
+  if (node.customActions && node.customActions.length > 0) {
+    var actionsMenu = Panel.addMenu('panel_menu_actions');
+    for (var i = 0; i < node.customActions.length; i++) {
+      var customAction = node.customActions[i];
+      actionsMenu.addMenuItem(customAction.description,
+          '' /* menuItemShortcut */, '' /* menuItemBraille */,
+          node.performCustomAction.bind(node, customAction.id));
+    }
+  }
+
   // Activate either the specified menu or the first menu.
   var selectedMenu = Panel.menus_[0];
   for (var i = 0; i < Panel.menus_.length; i++) {
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
index 3ef777b..37943929 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2515,6 +2515,9 @@
       <message desc="Title displayed in the panel for the ChromeVox menu." name="IDS_CHROMEVOX_PANEL_MENU_CHROMEVOX">
         ChromeVox
       </message>
+      <message desc="Title displayed in the panel for the actions menu." name="IDS_CHROMEVOX_PANEL_MENU_ACTIONS">
+        Actions
+      </message>
       <message desc="Title displayed in the panel when there are no menu items." name="IDS_CHROMEVOX_PANEL_MENU_ITEM_NONE">
         No items.
       </message>
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl
index 4b8b0e7..0df0d89 100644
--- a/chrome/common/extensions/api/automation.idl
+++ b/chrome/common/extensions/api/automation.idl
@@ -366,6 +366,11 @@
   // A listener for changes on the <code>AutomationNode</code> tree.
   callback TreeChangeObserver = void(TreeChange treeChange);
 
+  dictionary CustomAction {
+    long id;
+    DOMString description;
+  };
+
   // A single node in an Automation tree.
   [nocompile, noinline_doc] dictionary AutomationNode {
     // The root node of the tree containing this AutomationNode.
@@ -449,6 +454,9 @@
     // The target of an in-page link.
     AutomationNode? inPageLinkTarget;
 
+    // An array of custom actions.
+    CustomAction[]? customActions;
+
     //
     // Link attributes.
     //
@@ -722,6 +730,9 @@
     // Scrolls this node to make it visible.
     static void makeVisible();
 
+    // Performs custom action.
+    static void performCustomAction(long customActionId);
+
     // Sets selection within a text field.
     static void setSelection(long startIndex, long endIndex);
 
diff --git a/chrome/common/extensions/api/automation_internal.idl b/chrome/common/extensions/api/automation_internal.idl
index a5cc24f..68cf1f1 100644
--- a/chrome/common/extensions/api/automation_internal.idl
+++ b/chrome/common/extensions/api/automation_internal.idl
@@ -29,8 +29,9 @@
 
   // All possible actions that can be performed on automation nodes.
   enum ActionType {
-    focus,
+    customAction,
     doDefault,
+    focus,
     getImageData,
     hitTest,
     makeVisible,
@@ -38,10 +39,10 @@
     setAccessibilityFocus,
     setSequentialFocusNavigationStartingPoint,
     setSelection,
+    showContextMenu,
     startDuckingMedia,
     stopDuckingMedia,
-    suspendMedia,
-    showContextMenu
+    suspendMedia
   };
 
   // Arguments required for all actions supplied to performAction.
@@ -51,6 +52,12 @@
     ActionType actionType;
   };
 
+  // Arguments for the customAction action. Those args are passed to
+  // performAction as opt_args.
+  dictionary PerformCustomActionParams {
+    long customActionID;
+  };
+
   // Arguments for the setSelection action supplied to performAction.
   dictionary SetSelectionParams {
     // Reuses ActionRequiredParams automationNodeID to mean anchor node id,
diff --git a/chrome/common/extensions/chrome_extension_messages.h b/chrome/common/extensions/chrome_extension_messages.h
index 14712e95..210d86f 100644
--- a/chrome/common/extensions/chrome_extension_messages.h
+++ b/chrome/common/extensions/chrome_extension_messages.h
@@ -50,6 +50,7 @@
   IPC_STRUCT_TRAITS_MEMBER(float_attributes)
   IPC_STRUCT_TRAITS_MEMBER(bool_attributes)
   IPC_STRUCT_TRAITS_MEMBER(intlist_attributes)
+  IPC_STRUCT_TRAITS_MEMBER(stringlist_attributes)
   IPC_STRUCT_TRAITS_MEMBER(html_attributes)
   IPC_STRUCT_TRAITS_MEMBER(child_ids)
   IPC_STRUCT_TRAITS_MEMBER(offset_container_id)
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
index ce09ccf..cb26e43 100644
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -694,6 +694,35 @@
                   ui::AX_TEXT_STYLE_LINE_THROUGH) != 0;
     result.Set(v8::Boolean::New(isolate, value));
   });
+  RouteNodeIDFunction(
+      "GetCustomActions",
+      [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
+         TreeCache* cache, ui::AXNode* node) {
+        const std::vector<int32_t>& custom_action_ids =
+            node->data().GetIntListAttribute(ui::AX_ATTR_CUSTOM_ACTION_IDS);
+        if (custom_action_ids.empty()) {
+          result.SetUndefined();
+          return;
+        }
+
+        const std::vector<std::string>& custom_action_descriptions =
+            node->data().GetStringListAttribute(
+                ui::AX_ATTR_CUSTOM_ACTION_DESCRIPTIONS);
+        if (custom_action_ids.size() != custom_action_descriptions.size()) {
+          NOTREACHED();
+          return;
+        }
+
+        v8::Local<v8::Array> custom_actions(
+            v8::Array::New(isolate, custom_action_ids.size()));
+        for (size_t i = 0; i < custom_action_ids.size(); i++) {
+          gin::DataObjectBuilder custom_action(isolate);
+          custom_action.Set("id", custom_action_ids[i]);
+          custom_action.Set("description", custom_action_descriptions[i]);
+          custom_actions->Set(static_cast<uint32_t>(i), custom_action.Build());
+        }
+        result.Set(custom_actions);
+      });
   RouteNodeIDFunction("GetChecked", [](v8::Isolate* isolate,
                                        v8::ReturnValue<v8::Value> result,
                                        TreeCache* cache, ui::AXNode* node) {
diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js
index 1e359f8..26cd00c 100644
--- a/chrome/renderer/resources/extensions/automation/automation_node.js
+++ b/chrome/renderer/resources/extensions/automation/automation_node.js
@@ -266,6 +266,14 @@
  */
 var GetLineThrough = requireNative('automationInternal').GetLineThrough;
 
+/**
+ * @param {number} axTreeID The id of the accessibility tree.
+ * @param {number} nodeID The id of a node.
+ * @return {?Array.<automation.CustomAction>} List of custom actions of the
+ *     node.
+ */
+var GetCustomActions = requireNative('automationInternal').GetCustomActions;
+
 var lastError = require('lastError');
 var logging = requireNative('logging');
 var utils = require('utils');
@@ -424,6 +432,10 @@
     return GetLineThrough(this.treeID, this.id);
   },
 
+  get customActions() {
+    return GetCustomActions(this.treeID, this.id);
+  },
+
   doDefault: function() {
     this.performAction_('doDefault');
   },
@@ -451,6 +463,10 @@
     this.performAction_('makeVisible');
   },
 
+  performCustomAction: function(customActionId) {
+    this.performAction_('customAction', { customActionID: customActionId });
+  },
+
   resumeMedia: function() {
     this.performAction_('resumeMedia');
   },
@@ -1151,6 +1167,7 @@
     'hitTest',
     'makeVisible',
     'matches',
+    'performCustomAction',
     'resumeMedia',
     'setSelection',
     'setSequentialFocusNavigationStartingPoint',
@@ -1185,6 +1202,7 @@
       'italic',
       'underline',
       'lineThrough',
+      'customActions',
   ]),
 });
 
diff --git a/components/arc/common/accessibility_helper.mojom b/components/arc/common/accessibility_helper.mojom
index f3651b2..4fdba278 100644
--- a/components/arc/common/accessibility_helper.mojom
+++ b/components/arc/common/accessibility_helper.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next MinVersion: 3
+// Next MinVersion: 4
 
 module arc.mojom;
 
@@ -69,7 +69,16 @@
   EXPAND,
   COLLAPSE,
   DISMISS,
-  SET_TEXT
+  SET_TEXT,
+  CONTEXT_CLICK,
+  SCROLL_DOWN,
+  SCROLL_LEFT,
+  SCROLL_RIGHT,
+  SCROLL_TO_POSITION,
+  SCROLL_UP,
+  SET_PROGRESS,
+  SHOW_ON_SCREEN,
+  CUSTOM_ACTION  // Not a standard action.
 };
 
 // Possible boolean properties set on an AccessibilityNodeInfo.
@@ -130,7 +139,12 @@
 [Extensible]
 enum AccessibilityIntListProperty {
   CHILD_NODE_IDS,
-  ACTIONS
+  CUSTOM_ACTION_IDS
+};
+
+[Extensible]
+enum AccessibilityStringListProperty {
+  CUSTOM_ACTION_DESCRIPTIONS
 };
 
 // AccessibilityNodeInfoData is a struct to contain info of
@@ -144,6 +158,8 @@
   [MinVersion=1]map<AccessibilityIntProperty, int32>? int_properties;
   [MinVersion=1]
       map<AccessibilityIntListProperty, array<int32>>? int_list_properties;
+  [MinVersion=3]map<AccessibilityStringListProperty, array<string>>?
+      string_list_properties;
 };
 
 // Filters the event type (and implicitly the data) sent by the ARC
@@ -172,6 +188,18 @@
   array<AccessibilityNodeInfoData> node_data;
 };
 
+// AccessibilityActionData is a struct to contain info of AccessibilityAction in
+// Android.
+// https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction.html
+struct AccessibilityActionData {
+  int32 node_id;
+
+  AccessibilityActionType action_type;
+
+  // custom_action_id must be set if action_type is CUSTOM_ACTION.
+  int32 custom_action_id;
+};
+
 // Next method ID: 2
 interface AccessibilityHelperHost {
   OnAccessibilityEventDeprecated@0(AccessibilityEventType event_type,
@@ -182,13 +210,15 @@
   OnAccessibilityEvent@1(AccessibilityEventData event_data);
 };
 
-// Next method ID: 3
+// Next method ID: 4
 interface AccessibilityHelperInstance {
   Init@0(AccessibilityHelperHost host);
 
-  // Perform the specified action on a node requested by a Chrome client.
-  PerformAction@1(int32 id, AccessibilityActionType action);
+  PerformActionDeprecated@1(int32 id, AccessibilityActionType action);
 
   // Set a filter on the event types received.
   SetFilter@2(AccessibilityFilterType filter_type);
+
+  // Perform an action on a node requested by a Chrome client.
+  [MinVersion=3]PerformAction@3(AccessibilityActionData action_data);
 };
diff --git a/components/metrics/proto/translate_event.proto b/components/metrics/proto/translate_event.proto
index fb971737..c2ced5c 100644
--- a/components/metrics/proto/translate_event.proto
+++ b/components/metrics/proto/translate_event.proto
@@ -67,6 +67,7 @@
   optional RankerResponse ranker_response = 9;
 
   // The action performed by the user in the translate UI.
+  // Next tag 27.
   enum EventType {
     // The feedback event does not correspond to any of the enumerated
     // cases.
@@ -92,9 +93,15 @@
     // The user reverted the translation.
     USER_REVERT = 9;
 
+    // Deprecated. Use AUTO_TRANSLATION_BY_PREF or AUTO_TRANSLATION_BY_LINK
+    // instead.
+    AUTOMATICALLY_TRANSLATED = 10;
     // Automated feedback.
     // An automatic translation was triggered.
-    AUTOMATICALLY_TRANSLATED = 10;
+    // User sets always translate in user settings.
+    AUTO_TRANSLATION_BY_PREF = 25;
+    // User navigated through a click from a translated page.
+    AUTO_TRANSLATION_BY_LINK = 26;
     // The translation was not offered because translate is disabled
     // globally in the user preferences.
     DISABLED_BY_PREF = 11;
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc
index 2ff77244..4a73e953 100644
--- a/components/sync/protocol/proto_enum_conversions.cc
+++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -296,7 +296,7 @@
 
 const char* ProtoEnumToString(sync_pb::Translation::Interaction interaction) {
   ASSERT_ENUM_BOUNDS(sync_pb::Translation, Interaction, UNKNOWN,
-                     AUTOMATIC_TRANSLATION);
+                     AUTO_TRANSLATION_BY_LINK);
   switch (interaction) {
     ENUM_CASE(sync_pb::Translation, UNKNOWN);
     ENUM_CASE(sync_pb::Translation, ACCEPT);
@@ -305,7 +305,8 @@
     ENUM_CASE(sync_pb::Translation, DISMISSED);
     ENUM_CASE(sync_pb::Translation, MANUAL);
     ENUM_CASE(sync_pb::Translation, TRANSLATION_REVERTED);
-    ENUM_CASE(sync_pb::Translation, AUTOMATIC_TRANSLATION);
+    ENUM_CASE(sync_pb::Translation, AUTO_TRANSLATION_BY_PREF);
+    ENUM_CASE(sync_pb::Translation, AUTO_TRANSLATION_BY_LINK);
   }
   NOTREACHED();
   return "";
diff --git a/components/sync/protocol/user_event_specifics.proto b/components/sync/protocol/user_event_specifics.proto
index 95dc0338..8bc41a7 100644
--- a/components/sync/protocol/user_event_specifics.proto
+++ b/components/sync/protocol/user_event_specifics.proto
@@ -63,7 +63,10 @@
     // and to_language_code will be previous chosen values.
     TRANSLATION_REVERTED = 6;
     // Automatically triggered translation.
-    AUTOMATIC_TRANSLATION = 7;
+    // User sets always translate in user settings.
+    AUTO_TRANSLATION_BY_PREF = 7;
+    // User navigated through a click from a translated page.
+    AUTO_TRANSLATION_BY_LINK = 8;
   }
   optional Interaction interaction = 3;
 }
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index fdfc7f75..06812c57 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -267,7 +267,7 @@
           TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_CONFIG);
       translate_event_->set_modified_target_language(auto_target_lang);
       RecordTranslateEvent(
-          metrics::TranslateEventProto::AUTOMATICALLY_TRANSLATED);
+          metrics::TranslateEventProto::AUTO_TRANSLATION_BY_PREF);
       TranslatePage(language_code, auto_target_lang, false);
       return;
     }
@@ -280,7 +280,7 @@
         TranslateBrowserMetrics::INITIATION_STATUS_AUTO_BY_LINK);
     translate_event_->set_modified_target_language(auto_translate_to);
     RecordTranslateEvent(
-        metrics::TranslateEventProto::AUTOMATICALLY_TRANSLATED);
+        metrics::TranslateEventProto::AUTO_TRANSLATION_BY_LINK);
     TranslatePage(language_code, auto_translate_to, false);
     return;
   }
diff --git a/components/translate/core/common/translation_logging_helper.cc b/components/translate/core/common/translation_logging_helper.cc
index ac6c0d2..8b31b643 100644
--- a/components/translate/core/common/translation_logging_helper.cc
+++ b/components/translate/core/common/translation_logging_helper.cc
@@ -60,8 +60,13 @@
     case TranslateEventProto::USER_REVERT:
       translation->set_interaction(sync_pb::Translation::TRANSLATION_REVERTED);
       break;
-    case TranslateEventProto::AUTOMATICALLY_TRANSLATED:
-      translation->set_interaction(sync_pb::Translation::AUTOMATIC_TRANSLATION);
+    case TranslateEventProto::AUTO_TRANSLATION_BY_PREF:
+      translation->set_interaction(
+          sync_pb::Translation::AUTO_TRANSLATION_BY_PREF);
+      break;
+    case TranslateEventProto::AUTO_TRANSLATION_BY_LINK:
+      translation->set_interaction(
+          sync_pb::Translation::AUTO_TRANSLATION_BY_LINK);
       break;
     default:  // We don't care about other events.
       return false;
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc
index 2062fe0..3a00577 100644
--- a/content/browser/devtools/devtools_http_handler.cc
+++ b/content/browser/devtools/devtools_http_handler.cc
@@ -20,7 +20,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -171,18 +170,20 @@
 
 // Thread and ServerWrapper lifetime management ------------------------------
 
-void TerminateOnUI(std::unique_ptr<base::Thread> thread,
-                   std::unique_ptr<ServerWrapper> server_wrapper,
-                   std::unique_ptr<DevToolsSocketFactory> socket_factory) {
+void TerminateOnUI(base::Thread* thread,
+                   ServerWrapper* server_wrapper,
+                   DevToolsSocketFactory* socket_factory) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (server_wrapper)
-    thread->task_runner()->DeleteSoon(FROM_HERE, std::move(server_wrapper));
-  if (socket_factory)
-    thread->task_runner()->DeleteSoon(FROM_HERE, std::move(socket_factory));
+  if (server_wrapper) {
+    DCHECK(thread);
+    thread->task_runner()->DeleteSoon(FROM_HERE, server_wrapper);
+  }
+  if (socket_factory) {
+    DCHECK(thread);
+    thread->task_runner()->DeleteSoon(FROM_HERE, socket_factory);
+  }
   if (thread) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
-        BindOnce([](std::unique_ptr<base::Thread>) {}, std::move(thread)));
+    BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, thread);
   }
 }
 
@@ -193,33 +194,28 @@
                        std::unique_ptr<net::IPEndPoint> ip_address) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (handler && thread && server_wrapper) {
-    handler->ServerStarted(
-        std::unique_ptr<base::Thread>(thread),
-        std::unique_ptr<ServerWrapper>(server_wrapper),
-        std::unique_ptr<DevToolsSocketFactory>(socket_factory),
-        std::move(ip_address));
+    handler->ServerStarted(thread, server_wrapper, socket_factory,
+                           std::move(ip_address));
   } else {
-    TerminateOnUI(std::unique_ptr<base::Thread>(thread),
-                  std::unique_ptr<ServerWrapper>(server_wrapper),
-                  std::unique_ptr<DevToolsSocketFactory>(socket_factory));
+    TerminateOnUI(thread, server_wrapper, socket_factory);
   }
 }
 
 void StartServerOnHandlerThread(
     base::WeakPtr<DevToolsHttpHandler> handler,
-    std::unique_ptr<base::Thread> thread,
-    std::unique_ptr<DevToolsSocketFactory> socket_factory,
+    base::Thread* thread,
+    DevToolsSocketFactory* socket_factory,
     const base::FilePath& output_directory,
     const base::FilePath& frontend_dir,
     bool bundles_resources) {
   DCHECK(thread->task_runner()->BelongsToCurrentThread());
-  std::unique_ptr<ServerWrapper> server_wrapper;
+  ServerWrapper* server_wrapper = nullptr;
   std::unique_ptr<net::ServerSocket> server_socket =
       socket_factory->CreateForHttpServer();
   std::unique_ptr<net::IPEndPoint> ip_address(new net::IPEndPoint);
   if (server_socket) {
-    server_wrapper.reset(new ServerWrapper(handler, std::move(server_socket),
-                                           frontend_dir, bundles_resources));
+    server_wrapper = new ServerWrapper(handler, std::move(server_socket),
+                                       frontend_dir, bundles_resources);
     if (!output_directory.empty())
       server_wrapper->WriteActivePortToUserProfile(output_directory);
 
@@ -229,11 +225,34 @@
     ip_address.reset();
     LOG(ERROR) << "Cannot start http server for devtools. Stop devtools.";
   }
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&ServerStartedOnUI, std::move(handler), thread.release(),
-                     server_wrapper.release(), socket_factory.release(),
-                     std::move(ip_address)));
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+      base::Bind(&ServerStartedOnUI,
+                 handler,
+                 thread,
+                 server_wrapper,
+                 socket_factory,
+                 base::Passed(&ip_address)));
+}
+
+void StartServerOnFile(
+    base::WeakPtr<DevToolsHttpHandler> handler,
+    DevToolsSocketFactory* socket_factory,
+    const base::FilePath& output_directory,
+    const base::FilePath& frontend_dir,
+    bool bundles_resources) {
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  std::unique_ptr<base::Thread> thread(
+      new base::Thread(kDevToolsHandlerThreadName));
+  base::Thread::Options options;
+  options.message_loop_type = base::MessageLoop::TYPE_IO;
+  if (thread->StartWithOptions(options)) {
+    base::MessageLoop* message_loop = thread->message_loop();
+    message_loop->task_runner()->PostTask(
+        FROM_HERE,
+        base::Bind(&StartServerOnHandlerThread, handler,
+                   base::Unretained(thread.release()), socket_factory,
+                   output_directory, frontend_dir, bundles_resources));
+  }
 }
 
 // DevToolsAgentHostClientImpl -----------------------------------------------
@@ -309,8 +328,7 @@
 // DevToolsHttpHandler -------------------------------------------------------
 
 DevToolsHttpHandler::~DevToolsHttpHandler() {
-  TerminateOnUI(std::move(thread_), std::move(server_wrapper_),
-                std::move(socket_factory_));
+  TerminateOnUI(thread_, server_wrapper_, socket_factory_);
 }
 
 static std::string PathWithoutParams(const std::string& path) {
@@ -635,9 +653,9 @@
   response.SetBody(json_protocol, "application/json; charset=UTF-8");
 
   thread_->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
-                                base::Unretained(server_wrapper_.get()),
-                                connection_id, response));
+      FROM_HERE,
+      base::Bind(&ServerWrapper::SendResponse,
+                 base::Unretained(server_wrapper_), connection_id, response));
 }
 
 void DevToolsHttpHandler::RespondToJsonList(
@@ -677,9 +695,9 @@
         DevToolsAgentHost::CreateForBrowser(
             thread_->task_runner(),
             base::Bind(&DevToolsSocketFactory::CreateForTethering,
-                       base::Unretained(socket_factory_.get())));
+                       base::Unretained(socket_factory_)));
     connection_to_client_[connection_id].reset(new DevToolsAgentHostClientImpl(
-        thread_->message_loop(), server_wrapper_.get(), connection_id,
+        thread_->message_loop(), server_wrapper_, connection_id,
         browser_agent));
     AcceptWebSocket(connection_id, request);
     return;
@@ -706,7 +724,7 @@
   }
 
   connection_to_client_[connection_id].reset(new DevToolsAgentHostClientImpl(
-      thread_->message_loop(), server_wrapper_.get(), connection_id, agent));
+      thread_->message_loop(), server_wrapper_, connection_id, agent));
 
   AcceptWebSocket(connection_id, request);
 }
@@ -732,37 +750,37 @@
     const base::FilePath& debug_frontend_dir,
     const std::string& product_name,
     const std::string& user_agent)
-    : frontend_url_(frontend_url),
+    : thread_(nullptr),
+      frontend_url_(frontend_url),
       product_name_(product_name),
       user_agent_(user_agent),
+      server_wrapper_(nullptr),
       delegate_(delegate),
+      socket_factory_(nullptr),
       weak_factory_(this) {
   bool bundles_resources = frontend_url_.empty();
   if (frontend_url_.empty())
     frontend_url_ = "/devtools/inspector.html";
 
-  std::unique_ptr<base::Thread> thread(
-      new base::Thread(kDevToolsHandlerThreadName));
-  base::Thread::Options options;
-  options.message_loop_type = base::MessageLoop::TYPE_IO;
-  if (thread->StartWithOptions(options)) {
-    thread->task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&StartServerOnHandlerThread,
-                                  weak_factory_.GetWeakPtr(), std::move(thread),
-                                  std::move(socket_factory), output_directory,
-                                  debug_frontend_dir, bundles_resources));
-  }
+  BrowserThread::PostTask(
+      BrowserThread::FILE, FROM_HERE,
+      base::Bind(&StartServerOnFile,
+                 weak_factory_.GetWeakPtr(),
+                 socket_factory.release(),
+                 output_directory,
+                 debug_frontend_dir,
+                 bundles_resources));
 }
 
 void DevToolsHttpHandler::ServerStarted(
-    std::unique_ptr<base::Thread> thread,
-    std::unique_ptr<ServerWrapper> server_wrapper,
-    std::unique_ptr<DevToolsSocketFactory> socket_factory,
+    base::Thread* thread,
+    ServerWrapper* server_wrapper,
+    DevToolsSocketFactory* socket_factory,
     std::unique_ptr<net::IPEndPoint> ip_address) {
-  thread_ = std::move(thread);
-  server_wrapper_ = std::move(server_wrapper);
-  socket_factory_ = std::move(socket_factory);
-  server_ip_address_ = std::move(ip_address);
+  thread_ = thread;
+  server_wrapper_ = server_wrapper;
+  socket_factory_ = socket_factory;
+  server_ip_address_.swap(ip_address);
 }
 
 void ServerWrapper::WriteActivePortToUserProfile(
@@ -806,9 +824,9 @@
   response.SetBody(json_value + message, "application/json; charset=UTF-8");
 
   thread_->task_runner()->PostTask(
-      FROM_HERE, base::Bind(&ServerWrapper::SendResponse,
-                            base::Unretained(server_wrapper_.get()),
-                            connection_id, response));
+      FROM_HERE,
+      base::Bind(&ServerWrapper::SendResponse,
+                 base::Unretained(server_wrapper_), connection_id, response));
 }
 
 void DevToolsHttpHandler::Send200(int connection_id,
@@ -817,18 +835,17 @@
   if (!thread_)
     return;
   thread_->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&ServerWrapper::Send200,
-                                base::Unretained(server_wrapper_.get()),
-                                connection_id, data, mime_type));
+      FROM_HERE,
+      base::Bind(&ServerWrapper::Send200, base::Unretained(server_wrapper_),
+                 connection_id, data, mime_type));
 }
 
 void DevToolsHttpHandler::Send404(int connection_id) {
   if (!thread_)
     return;
   thread_->task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&ServerWrapper::Send404,
-                     base::Unretained(server_wrapper_.get()), connection_id));
+      FROM_HERE, base::Bind(&ServerWrapper::Send404,
+                            base::Unretained(server_wrapper_), connection_id));
 }
 
 void DevToolsHttpHandler::Send500(int connection_id,
@@ -836,9 +853,9 @@
   if (!thread_)
     return;
   thread_->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&ServerWrapper::Send500,
-                                base::Unretained(server_wrapper_.get()),
-                                connection_id, message));
+      FROM_HERE,
+      base::Bind(&ServerWrapper::Send500, base::Unretained(server_wrapper_),
+                 connection_id, message));
 }
 
 void DevToolsHttpHandler::AcceptWebSocket(
@@ -847,9 +864,9 @@
   if (!thread_)
     return;
   thread_->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&ServerWrapper::AcceptWebSocket,
-                                base::Unretained(server_wrapper_.get()),
-                                connection_id, request));
+      FROM_HERE,
+      base::Bind(&ServerWrapper::AcceptWebSocket,
+                 base::Unretained(server_wrapper_), connection_id, request));
 }
 
 std::unique_ptr<base::DictionaryValue> DevToolsHttpHandler::SerializeDescriptor(
diff --git a/content/browser/devtools/devtools_http_handler.h b/content/browser/devtools/devtools_http_handler.h
index 4ef44136..72836212 100644
--- a/content/browser/devtools/devtools_http_handler.h
+++ b/content/browser/devtools/devtools_http_handler.h
@@ -80,9 +80,9 @@
   void OnWebSocketMessage(int connection_id, const std::string& data);
   void OnClose(int connection_id);
 
-  void ServerStarted(std::unique_ptr<base::Thread> thread,
-                     std::unique_ptr<ServerWrapper> server_wrapper,
-                     std::unique_ptr<DevToolsSocketFactory> socket_factory,
+  void ServerStarted(base::Thread* thread,
+                     ServerWrapper* server_wrapper,
+                     DevToolsSocketFactory* socket_factory,
                      std::unique_ptr<net::IPEndPoint> ip_address);
 
   void SendJson(int connection_id,
@@ -109,17 +109,17 @@
       const std::string& host);
 
   // The thread used by the devtools handler to run server socket.
-  std::unique_ptr<base::Thread> thread_;
+  base::Thread* thread_;
   std::string frontend_url_;
   std::string product_name_;
   std::string user_agent_;
-  std::unique_ptr<ServerWrapper> server_wrapper_;
+  ServerWrapper* server_wrapper_;
   std::unique_ptr<net::IPEndPoint> server_ip_address_;
   using ConnectionToClientMap =
       std::map<int, std::unique_ptr<DevToolsAgentHostClientImpl>>;
   ConnectionToClientMap connection_to_client_;
   DevToolsManagerDelegate* delegate_;
-  std::unique_ptr<DevToolsSocketFactory> socket_factory_;
+  DevToolsSocketFactory* socket_factory_;
   base::WeakPtrFactory<DevToolsHttpHandler> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandler);
diff --git a/content/browser/devtools/devtools_http_handler_unittest.cc b/content/browser/devtools/devtools_http_handler_unittest.cc
index 7232833..a4ad827e 100644
--- a/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -158,8 +158,10 @@
   // Our dummy socket factory will post a quit message once the server will
   // become ready.
   run_loop.Run();
-  for (int i = 0; i < 5; i++)
+  for (int i = 0; i < 5; i++) {
     RunAllPendingInMessageLoop(BrowserThread::UI);
+    RunAllPendingInMessageLoop(BrowserThread::FILE);
+  }
   DevToolsAgentHost::StopRemoteDebuggingServer();
   // Make sure the handler actually stops.
   run_loop_2.Run();
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index d069b6b..bd99766 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -277,6 +277,8 @@
 IPC_ENUM_TRAITS_MAX_VALUE(ui::AXIntAttribute, ui::AX_INT_ATTRIBUTE_LAST)
 IPC_ENUM_TRAITS_MAX_VALUE(ui::AXIntListAttribute,
                           ui::AX_INT_LIST_ATTRIBUTE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(ui::AXStringListAttribute,
+                          ui::AX_STRING_LIST_ATTRIBUTE_LAST)
 IPC_ENUM_TRAITS_MAX_VALUE(ui::AXStringAttribute, ui::AX_STRING_ATTRIBUTE_LAST)
 IPC_ENUM_TRAITS_MAX_VALUE(ui::AXTextAffinity, ui::AX_TEXT_AFFINITY_LAST)
 IPC_ENUM_TRAITS_MAX_VALUE(ui::AXEventFrom, ui::AX_EVENT_FROM_LAST)
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index 10a3299..7c8f196 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -564,6 +564,7 @@
     case ui::AX_ACTION_SHOW_CONTEXT_MENU:
       target.ShowContextMenu();
       break;
+    case ui::AX_ACTION_CUSTOM_ACTION:
     case ui::AX_ACTION_REPLACE_SELECTED_TEXT:
     case ui::AX_ACTION_NONE:
       NOTREACHED();
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn
index 8b42553..304ac67 100644
--- a/device/bluetooth/BUILD.gn
+++ b/device/bluetooth/BUILD.gn
@@ -49,6 +49,8 @@
     "test/fake_central.h",
     "test/fake_peripheral.cc",
     "test/fake_peripheral.h",
+    "test/fake_read_response.cc",
+    "test/fake_read_response.h",
     "test/fake_remote_gatt_characteristic.cc",
     "test/fake_remote_gatt_characteristic.h",
     "test/fake_remote_gatt_descriptor.cc",
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
index 9443ba9..8d05f93 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -140,19 +140,6 @@
     return;
   }
 
-// After we migrate each platform to the new way of starting and stopping
-// notifications, we can remove them from this #if check. The goal is to get
-// rid of the entire check, and run SubscribeToNotifications on all
-// platforms.
-//
-// TODO(http://crbug.com/636270): Remove OS_WIN from this check.
-#if defined(OS_WIN)
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&BluetoothRemoteGattCharacteristic::OnStartNotifySessionError,
-                 GetWeakPtr(), error_callback,
-                 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
-#else   // defined(OS_WIN))
   // Find the Client Characteristic Configuration descriptor.
   std::vector<BluetoothRemoteGattDescriptor*> ccc_descriptor =
       GetDescriptorsByUUID(BluetoothRemoteGattDescriptor::
@@ -182,7 +169,6 @@
           GetWeakPtr(), callback),
       base::Bind(&BluetoothRemoteGattCharacteristic::OnStartNotifySessionError,
                  GetWeakPtr(), error_callback));
-#endif  // defined(OS_WIN)
 }
 
 void BluetoothRemoteGattCharacteristic::CancelStartNotifySession(
@@ -273,19 +259,6 @@
     return;
   }
 
-// After we migrate each platform to the new way of starting and stopping
-// notifications, we can remove them from this #if check. The goal is to get
-// rid of the entire check, and run SubscribeToNotifications on all
-// platforms.
-//
-// TODO(http://crbug.com/636270): Remove OS_WIN from this check.
-#if defined(OS_WIN)
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&BluetoothRemoteGattCharacteristic::OnStopNotifySessionError,
-                 GetWeakPtr(), session, callback,
-                 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
-#else   // defined(OS_WIN))
   // Find the Client Characteristic Configuration descriptor.
   std::vector<BluetoothRemoteGattDescriptor*> ccc_descriptor =
       GetDescriptorsByUUID(BluetoothRemoteGattDescriptor::
@@ -308,7 +281,6 @@
                  GetWeakPtr(), session, callback),
       base::Bind(&BluetoothRemoteGattCharacteristic::OnStopNotifySessionError,
                  GetWeakPtr(), session, callback));
-#endif  // defined(OS_WIN)
 }
 
 void BluetoothRemoteGattCharacteristic::CancelStopNotifySession(
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
index 625b9711..a8e356a 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
@@ -1463,49 +1463,6 @@
 
 #if defined(OS_WIN)
 // Tests StartNotifySession reentrant in start notify session error callback
-// and the reentrant start notify session success.
-TEST_F(BluetoothRemoteGattCharacteristicTest,
-       StartNotifySession_Reentrant_Error_Success) {
-  ASSERT_NO_FATAL_FAILURE(
-      FakeCharacteristicBoilerplate(/* properties: NOTIFY */ 0x10));
-  SimulateGattDescriptor(
-      characteristic1_,
-      BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid().value());
-  ASSERT_EQ(1u, characteristic1_->GetDescriptors().size());
-
-  SimulateGattNotifySessionStartError(
-      characteristic1_, BluetoothRemoteGattService::GATT_ERROR_UNKNOWN);
-  base::RunLoop().RunUntilIdle();
-
-  characteristic1_->StartNotifySession(
-      GetReentrantStartNotifySessionSuccessCallback(Call::NOT_EXPECTED,
-                                                    characteristic1_),
-      GetReentrantStartNotifySessionErrorCallback(
-          Call::EXPECTED, characteristic1_, false /* error_in_reentrant */));
-  EXPECT_EQ(0, callback_count_);
-  SimulateGattNotifySessionStarted(characteristic1_);
-  base::RunLoop().RunUntilIdle();
-  ExpectedChangeNotifyValueAttempts(0);
-  EXPECT_EQ(1, error_callback_count_);
-
-  // Simulate reentrant StartNotifySession request from
-  // BluetoothTestBase::ReentrantStartNotifySessionErrorCallback.
-  SimulateGattNotifySessionStarted(characteristic1_);
-  base::RunLoop().RunUntilIdle();
-  ExpectedChangeNotifyValueAttempts(1);
-  ExpectedNotifyValue(NotifyValueState::NOTIFY);
-  EXPECT_EQ(1, callback_count_);
-  EXPECT_EQ(1, error_callback_count_);
-  ASSERT_EQ(1u, notify_sessions_.size());
-  ASSERT_TRUE(notify_sessions_[0]);
-  EXPECT_EQ(characteristic1_->GetIdentifier(),
-            notify_sessions_[0]->GetCharacteristicIdentifier());
-  EXPECT_TRUE(notify_sessions_[0]->IsActive());
-}
-#endif  // defined(OS_WIN)
-
-#if defined(OS_WIN)
-// Tests StartNotifySession reentrant in start notify session error callback
 // and the reentrant start notify session error.
 TEST_F(BluetoothRemoteGattCharacteristicTest,
        StartNotifySession_Reentrant_Error_Error) {
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
index 22d2e09..e451732 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "device/bluetooth/bluetooth_adapter_win.h"
 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h"
@@ -25,7 +26,6 @@
       ui_task_runner_(ui_task_runner),
       characteristic_added_notified_(false),
       characteristic_value_read_or_write_in_progress_(false),
-      gatt_event_registeration_in_progress_(false),
       gatt_event_handle_(nullptr),
       weak_ptr_factory_(this) {
   DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
@@ -151,74 +151,6 @@
   return nullptr;
 }
 
-void BluetoothRemoteGattCharacteristicWin::StartNotifySession(
-    const NotifySessionCallback& callback,
-    const ErrorCallback& error_callback) {
-  DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
-
-  if (IsNotifying()) {
-    std::unique_ptr<BluetoothGattNotifySession> notify_session(
-        new BluetoothGattNotifySession(weak_ptr_factory_.GetWeakPtr()));
-    ui_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(callback, base::Passed(std::move(notify_session))));
-    return;
-  }
-
-  if (!characteristic_info_->IsNotifiable &&
-      !characteristic_info_->IsIndicatable) {
-    ui_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(error_callback,
-                   BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
-    return;
-  }
-
-  std::vector<BluetoothRemoteGattDescriptor*> ccc_descriptors =
-      GetDescriptorsByUUID(BluetoothRemoteGattDescriptor::
-                               ClientCharacteristicConfigurationUuid());
-  if (ccc_descriptors.size() < 1) {
-    ui_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(error_callback,
-                   BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
-    return;
-  }
-  if (ccc_descriptors.size() > 1) {
-    ui_task_runner_->PostTask(
-        FROM_HERE, base::Bind(error_callback,
-                              BluetoothRemoteGattService::GATT_ERROR_FAILED));
-    return;
-  }
-
-  start_notify_session_callbacks_.push_back(
-      std::make_pair(callback, error_callback));
-  if (gatt_event_registeration_in_progress_)
-    return;
-
-  task_manager_->PostRegisterGattCharacteristicValueChangedEvent(
-      parent_service_->GetServicePath(), characteristic_info_.get(),
-      static_cast<BluetoothRemoteGattDescriptorWin*>(ccc_descriptors[0])
-          ->GetWinDescriptorInfo(),
-      base::Bind(
-          &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback,
-          weak_ptr_factory_.GetWeakPtr()),
-      base::Bind(&BluetoothRemoteGattCharacteristicWin::
-                     OnGattCharacteristicValueChanged,
-                 weak_ptr_factory_.GetWeakPtr()));
-  gatt_event_registeration_in_progress_ = true;
-}
-
-void BluetoothRemoteGattCharacteristicWin::StopNotifySession(
-    BluetoothGattNotifySession* session,
-    const base::Closure& callback) {
-  // TODO(http://crbug.com/636270): Remove this method and use the base version.
-  //   Instead, we should implement SubscribeToNotifications and
-  //   UnsubscribeFromNotifications.
-
-  ui_task_runner_->PostTask(FROM_HERE, callback);
-}
-
 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
@@ -288,16 +220,24 @@
     BluetoothRemoteGattDescriptor* ccc_descriptor,
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
-  // TODO(http://crbug.com/636270): Implement this method
-  NOTIMPLEMENTED();
+  task_manager_->PostRegisterGattCharacteristicValueChangedEvent(
+      parent_service_->GetServicePath(), characteristic_info_.get(),
+      static_cast<BluetoothRemoteGattDescriptorWin*>(ccc_descriptor)
+          ->GetWinDescriptorInfo(),
+      base::Bind(
+          &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback,
+          weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
+      base::Bind(&BluetoothRemoteGattCharacteristicWin::
+                     OnGattCharacteristicValueChanged,
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
 void BluetoothRemoteGattCharacteristicWin::UnsubscribeFromNotifications(
     BluetoothRemoteGattDescriptor* ccc_descriptor,
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
-  // TODO(http://crbug.com/636270): Implement this method
-  NOTIMPLEMENTED();
+  // TODO(crbug.com/735828): Implement this method.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
 }
 
 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback(
@@ -446,22 +386,16 @@
 }
 
 void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
+    const base::Closure& callback,
+    const ErrorCallback& error_callback,
     BLUETOOTH_GATT_EVENT_HANDLE event_handle,
     HRESULT hr) {
   DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
-
-  gatt_event_registeration_in_progress_ = false;
-  std::vector<std::pair<NotifySessionCallback, ErrorCallback>> callbacks;
-  callbacks.swap(start_notify_session_callbacks_);
   if (SUCCEEDED(hr)) {
     gatt_event_handle_ = event_handle;
-    for (const auto& callback : callbacks) {
-      callback.first.Run(base::MakeUnique<BluetoothGattNotifySession>(
-          weak_ptr_factory_.GetWeakPtr()));
-    }
+    callback.Run();
   } else {
-    for (const auto& callback : callbacks)
-      callback.second.Run(HRESULTToGattErrorCode(hr));
+    error_callback.Run(HRESULTToGattErrorCode(hr));
   }
 }
 
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
index 486f3fc..dd29121 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -43,10 +43,6 @@
   std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
   BluetoothRemoteGattDescriptor* GetDescriptor(
       const std::string& identifier) const override;
-  void StartNotifySession(const NotifySessionCallback& callback,
-                          const ErrorCallback& error_callback) override;
-  void StopNotifySession(BluetoothGattNotifySession* session,
-                         const base::Closure& callback) override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -92,7 +88,10 @@
   BluetoothRemoteGattService::GattErrorCode HRESULTToGattErrorCode(HRESULT hr);
   void OnGattCharacteristicValueChanged(
       std::unique_ptr<std::vector<uint8_t>> new_value);
-  void GattEventRegistrationCallback(PVOID event_handle, HRESULT hr);
+  void GattEventRegistrationCallback(const base::Closure& callback,
+                                     const ErrorCallback& error_callback,
+                                     PVOID event_handle,
+                                     HRESULT hr);
   void ClearIncludedDescriptors();
 
   BluetoothRemoteGattServiceWin* parent_service_;
@@ -128,9 +127,6 @@
   std::vector<std::pair<NotifySessionCallback, ErrorCallback>>
       start_notify_session_callbacks_;
 
-  // Flag indicates if GATT event registration is in progress.
-  bool gatt_event_registeration_in_progress_;
-
   // GATT event handle returned by GattEventRegistrationCallback.
   PVOID gatt_event_handle_;
 
diff --git a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
index 8bb4458..76dbdd3 100644
--- a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
+++ b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
@@ -145,4 +145,21 @@
   SetNextReadCharacteristicResponse(uint16 gatt_code, array<uint8>? value,
                                     string characteristic_id, string service_id,
                                     string peripheral_address) => (bool success);
+
+  // Sets the next read response for descriptor with |descriptor_id| in
+  // |characteristics_id| in |service_id| and in |peripheral_address| to |code|
+  // and |value|. |code| could be a GATT Error Response from
+  // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
+  // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
+  // failure.
+  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+  // Calls callback with false if there was any error when simulating the next
+  // response.
+  SetNextReadDescriptorResponse(
+      uint16 gatt_code,
+      array<uint8>? value,
+      string descriptor_id,
+      string characteristic_id,
+      string service_id,
+      string peripheral_address) => (bool success);
 };
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc
index ddf584b..a089834 100644
--- a/device/bluetooth/test/fake_central.cc
+++ b/device/bluetooth/test/fake_central.cc
@@ -148,6 +148,25 @@
   std::move(callback).Run(true);
 }
 
+void FakeCentral::SetNextReadDescriptorResponse(
+    uint16_t gatt_code,
+    const base::Optional<std::vector<uint8_t>>& value,
+    const std::string& descriptor_id,
+    const std::string& characteristic_id,
+    const std::string& service_id,
+    const std::string& peripheral_address,
+    SetNextReadDescriptorResponseCallback callback) {
+  FakeRemoteGattDescriptor* fake_remote_gatt_descriptor =
+      GetFakeRemoteGattDescriptor(peripheral_address, service_id,
+                                  characteristic_id, descriptor_id);
+  if (fake_remote_gatt_descriptor == nullptr) {
+    std::move(callback).Run(false);
+  }
+
+  fake_remote_gatt_descriptor->SetNextReadResponse(gatt_code, value);
+  std::move(callback).Run(true);
+}
+
 std::string FakeCentral::GetAddress() const {
   NOTREACHED();
   return std::string();
@@ -309,4 +328,20 @@
       fake_remote_gatt_service->GetCharacteristic(characteristic_id));
 }
 
+FakeRemoteGattDescriptor* FakeCentral::GetFakeRemoteGattDescriptor(
+    const std::string& peripheral_address,
+    const std::string& service_id,
+    const std::string& characteristic_id,
+    const std::string& descriptor_id) const {
+  FakeRemoteGattCharacteristic* fake_remote_gatt_characteristic =
+      GetFakeRemoteGattCharacteristic(peripheral_address, service_id,
+                                      characteristic_id);
+  if (fake_remote_gatt_characteristic == nullptr) {
+    return nullptr;
+  }
+
+  return static_cast<FakeRemoteGattDescriptor*>(
+      fake_remote_gatt_characteristic->GetDescriptor(descriptor_id));
+}
+
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h
index adf3afb..0cb8c73c 100644
--- a/device/bluetooth/test/fake_central.h
+++ b/device/bluetooth/test/fake_central.h
@@ -16,6 +16,7 @@
 namespace bluetooth {
 
 class FakeRemoteGattCharacteristic;
+class FakeRemoteGattDescriptor;
 
 // Implementation of FakeCentral in
 // src/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom.
@@ -60,6 +61,14 @@
       const std::string& service_id,
       const std::string& peripheral_address,
       SetNextReadCharacteristicResponseCallback callback) override;
+  void SetNextReadDescriptorResponse(
+      uint16_t gatt_code,
+      const base::Optional<std::vector<uint8_t>>& value,
+      const std::string& descriptor_id,
+      const std::string& characteristic_id,
+      const std::string& service_id,
+      const std::string& peripheral_address,
+      SetNextReadDescriptorResponseCallback callback) override;
 
   // BluetoothAdapter overrides:
   std::string GetAddress() const override;
@@ -124,6 +133,11 @@
       const std::string& peripheral_address,
       const std::string& service_id,
       const std::string& characteristic_id) const;
+  FakeRemoteGattDescriptor* GetFakeRemoteGattDescriptor(
+      const std::string& peripheral_address,
+      const std::string& service_id,
+      const std::string& characteristic_id,
+      const std::string& descriptor_id) const;
 
   mojom::CentralState state_;
   mojo::Binding<mojom::FakeCentral> binding_;
diff --git a/device/bluetooth/test/fake_read_response.cc b/device/bluetooth/test/fake_read_response.cc
new file mode 100644
index 0000000..3d8782c5
--- /dev/null
+++ b/device/bluetooth/test/fake_read_response.cc
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/test/fake_read_response.h"
+
+namespace bluetooth {
+
+FakeReadResponse::FakeReadResponse(
+    uint16_t gatt_code,
+    const base::Optional<std::vector<uint8_t>>& value)
+    : gatt_code_(gatt_code), value_(value) {}
+
+FakeReadResponse::~FakeReadResponse() {}
+
+}  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_read_response.h b/device/bluetooth/test/fake_read_response.h
new file mode 100644
index 0000000..380d95a
--- /dev/null
+++ b/device/bluetooth/test/fake_read_response.h
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef DEVICE_BLUETOOTH_TEST_FAKE_READ_RESPONSE_H_
+#define DEVICE_BLUETOOTH_TEST_FAKE_READ_RESPONSE_H_
+
+#include <vector>
+
+#include "base/optional.h"
+
+namespace bluetooth {
+
+// Holds the necessary values for dispatching a fake read response.
+class FakeReadResponse {
+ public:
+  FakeReadResponse(uint16_t gatt_code,
+                   const base::Optional<std::vector<uint8_t>>& value);
+  ~FakeReadResponse();
+
+  uint16_t gatt_code() { return gatt_code_; }
+  const base::Optional<std::vector<uint8_t>>& value() { return value_; }
+
+ private:
+  uint16_t gatt_code_;
+  base::Optional<std::vector<uint8_t>> value_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeReadResponse);
+};
+
+}  // namespace bluetooth
+
+#endif  // DEVICE_BLUETOOTH_TEST_FAKE_READ_RESPONSE_H_
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.cc b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
index 44409da..54f7a63 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.cc
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
@@ -11,6 +11,7 @@
 #include "base/strings/stringprintf.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 #include "device/bluetooth/public/interfaces/test/fake_bluetooth.mojom.h"
+#include "device/bluetooth/test/fake_read_response.h"
 
 namespace bluetooth {
 
@@ -149,9 +150,8 @@
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
   DCHECK(next_read_response_);
-  uint16_t gatt_code = next_read_response_->gatt_code;
-  base::Optional<std::vector<uint8_t>> value =
-      std::move(next_read_response_->value);
+  uint16_t gatt_code = next_read_response_->gatt_code();
+  base::Optional<std::vector<uint8_t>> value = next_read_response_->value();
   next_read_response_.reset();
 
   if (gatt_code == mojom::kGATTSuccess) {
@@ -166,11 +166,4 @@
   }
 }
 
-FakeRemoteGattCharacteristic::ReadResponse::ReadResponse(
-    uint16_t gatt_code,
-    const base::Optional<std::vector<uint8_t>>& value)
-    : gatt_code(gatt_code), value(value) {}
-
-FakeRemoteGattCharacteristic::ReadResponse::~ReadResponse() {}
-
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.h b/device/bluetooth/test/fake_remote_gatt_characteristic.h
index 93630d1..c56c7cc 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.h
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.h
@@ -13,6 +13,7 @@
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 #include "device/bluetooth/public/interfaces/test/fake_bluetooth.mojom.h"
+#include "device/bluetooth/test/fake_read_response.h"
 #include "device/bluetooth/test/fake_remote_gatt_descriptor.h"
 
 namespace device {
@@ -84,20 +85,9 @@
   device::BluetoothRemoteGattService* service_;
   std::vector<uint8_t> value_;
 
-  struct ReadResponse {
-    ReadResponse(uint16_t gatt_code,
-                 const base::Optional<std::vector<uint8_t>>& value);
-    ~ReadResponse();
-
-    uint16_t gatt_code;
-    base::Optional<std::vector<uint8_t>> value;
-
-    DISALLOW_COPY_AND_ASSIGN(ReadResponse);
-  };
-
   // Used to decide which callback should be called when
   // ReadRemoteCharacteristic is called.
-  base::Optional<ReadResponse> next_read_response_;
+  base::Optional<FakeReadResponse> next_read_response_;
 
   size_t last_descriptor_id_;
 
diff --git a/device/bluetooth/test/fake_remote_gatt_descriptor.cc b/device/bluetooth/test/fake_remote_gatt_descriptor.cc
index 6bb9203..b763a92 100644
--- a/device/bluetooth/test/fake_remote_gatt_descriptor.cc
+++ b/device/bluetooth/test/fake_remote_gatt_descriptor.cc
@@ -4,6 +4,11 @@
 
 #include "device/bluetooth/test/fake_remote_gatt_descriptor.h"
 
+#include <utility>
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "device/bluetooth/public/interfaces/test/fake_bluetooth.mojom.h"
+
 namespace bluetooth {
 
 FakeRemoteGattDescriptor::FakeRemoteGattDescriptor(
@@ -12,10 +17,18 @@
     device::BluetoothRemoteGattCharacteristic* characteristic)
     : descriptor_id_(descriptor_id),
       descriptor_uuid_(descriptor_uuid),
-      characteristic_(characteristic) {}
+      characteristic_(characteristic),
+      weak_ptr_factory_(this) {}
 
 FakeRemoteGattDescriptor::~FakeRemoteGattDescriptor() {}
 
+void FakeRemoteGattDescriptor::SetNextReadResponse(
+    uint16_t gatt_code,
+    const base::Optional<std::vector<uint8_t>>& value) {
+  DCHECK(!next_read_response_);
+  next_read_response_.emplace(gatt_code, value);
+}
+
 std::string FakeRemoteGattDescriptor::GetIdentifier() const {
   return descriptor_id_;
 }
@@ -42,11 +55,36 @@
 
 void FakeRemoteGattDescriptor::ReadRemoteDescriptor(
     const ValueCallback& callback,
-    const ErrorCallback& error_callback) {}
+    const ErrorCallback& error_callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::Bind(&FakeRemoteGattDescriptor::DispatchReadResponse,
+                 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
+}
 
 void FakeRemoteGattDescriptor::WriteRemoteDescriptor(
     const std::vector<uint8_t>& value,
     const base::Closure& callback,
     const ErrorCallback& error_callback) {}
 
+void FakeRemoteGattDescriptor::DispatchReadResponse(
+    const ValueCallback& callback,
+    const ErrorCallback& error_callback) {
+  DCHECK(next_read_response_);
+  uint16_t gatt_code = next_read_response_->gatt_code();
+  base::Optional<std::vector<uint8_t>> value = next_read_response_->value();
+  next_read_response_.reset();
+
+  if (gatt_code == mojom::kGATTSuccess) {
+    DCHECK(value);
+    value_ = std::move(value.value());
+    callback.Run(value_);
+    return;
+  } else if (gatt_code == mojom::kGATTInvalidHandle) {
+    DCHECK(!value);
+    error_callback.Run(device::BluetoothGattService::GATT_ERROR_FAILED);
+    return;
+  }
+}
+
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_remote_gatt_descriptor.h b/device/bluetooth/test/fake_remote_gatt_descriptor.h
index 4721ad5b..74a4881 100644
--- a/device/bluetooth/test/fake_remote_gatt_descriptor.h
+++ b/device/bluetooth/test/fake_remote_gatt_descriptor.h
@@ -7,9 +7,12 @@
 #include <string>
 #include <vector>
 
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/test/fake_read_response.h"
 
 namespace bluetooth {
 
@@ -24,6 +27,12 @@
       device::BluetoothRemoteGattCharacteristic* characteristic);
   ~FakeRemoteGattDescriptor() override;
 
+  // If |gatt_code| is mojom::kGATTSuccess the next read request will call
+  // its success callback with |value|. Otherwise it will call its error
+  // callback.
+  void SetNextReadResponse(uint16_t gatt_code,
+                           const base::Optional<std::vector<uint8_t>>& value);
+
   // device::BluetoothGattDescriptor overrides:
   std::string GetIdentifier() const override;
   device::BluetoothUUID GetUUID() const override;
@@ -40,10 +49,19 @@
                              const ErrorCallback& error_callback) override;
 
  private:
+  void DispatchReadResponse(const ValueCallback& callback,
+                            const ErrorCallback& error_callback);
+
   const std::string descriptor_id_;
   const device::BluetoothUUID descriptor_uuid_;
   device::BluetoothRemoteGattCharacteristic* characteristic_;
   std::vector<uint8_t> value_;
+
+  // Used to decide which callback should be called when
+  // ReadRemoteDescriptor is called.
+  base::Optional<FakeReadResponse> next_read_response_;
+
+  base::WeakPtrFactory<FakeRemoteGattDescriptor> weak_ptr_factory_;
 };
 
 }  // namespace bluetooth
diff --git a/third_party/WebKit/LayoutTests/animations/get-css-players.html b/third_party/WebKit/LayoutTests/animations/get-css-players.html
index 9127df5..94521a9 100644
--- a/third_party/WebKit/LayoutTests/animations/get-css-players.html
+++ b/third_party/WebKit/LayoutTests/animations/get-css-players.html
@@ -15,20 +15,20 @@
 
 <script>
 async_test(function(t) {
-    assert_equals(document.timeline.getAnimations().length, 0);
+    assert_equals(document.getAnimations().length, 0);
     assert_equals(container.getAnimations().length, 0);
     assert_equals(element.getAnimations().length, 0);
 
     element.className = 'cssAnimation';
     onload = function () {
         t.step(function() {
-            var animations = document.timeline.getAnimations();
+            var animations = document.getAnimations();
             assert_equals(animations.length, 1);
             assert_equals(container.getAnimations().length, 0);
             assert_equals(element.getAnimations().length, 1);
 
             animations[0].finish();
-            assert_equals(document.timeline.getAnimations().length, 0);
+            assert_equals(document.getAnimations().length, 0);
             assert_equals(container.getAnimations().length, 0);
             assert_equals(element.getAnimations().length, 0);
             t.done();
diff --git a/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop-expected.txt b/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop-expected.txt
index d9f23ec..77070adc 100644
--- a/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop-expected.txt
+++ b/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop-expected.txt
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS document.timeline.getAnimations().length is 0
+PASS document.getAnimations().length is 0
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop.html b/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop.html
index e8ccb1e1..d8aa6a8 100644
--- a/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop.html
+++ b/third_party/WebKit/LayoutTests/animations/lazy-detached-animation-stop.html
@@ -45,7 +45,7 @@
         input.id = "target2";
         // Insert the element again.
         document.body.appendChild(input);
-        shouldBe("document.timeline.getAnimations().length", "0");
+        shouldBe("document.getAnimations().length", "0");
         finishJSTest();
     });
 });
diff --git a/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html b/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html
index 3474d84..1989981 100644
--- a/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html
+++ b/third_party/WebKit/LayoutTests/animations/multiple-same-name-css-animations.html
@@ -12,7 +12,7 @@
 }
 
 function getAnimations() {
-  return document.timeline.getAnimations();
+  return document.getAnimations();
 }
 
 function clearAnimations() {
diff --git a/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js b/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js
index 23d644e..7164a1b0 100644
--- a/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js
+++ b/third_party/WebKit/LayoutTests/animations/resources/animation-test-helpers.js
@@ -212,7 +212,7 @@
 function runChecksWithPauseAPI(checks) {
     for (var k in checks) {
         var timeMs = Number(k);
-        log('Pausing at time: ' + timeMs + ', current animations: ' + document.timeline.getAnimations().length);
+        log('Pausing at time: ' + timeMs + ', current animations: ' + document.getAnimations().length);
         internals.pauseAnimations(timeMs / 1000);
         checks[k].forEach(function(check) { check(); });
     }
@@ -243,7 +243,7 @@
 
 function waitForAnimationsToStart(callback)
 {
-    if (document.timeline.getAnimations().length > 0) {
+    if (document.getAnimations().length > 0) {
         callback();
     } else {
         setTimeout(waitForAnimationsToStart.bind(this, callback), 0);
diff --git a/third_party/WebKit/LayoutTests/animations/transitions-replay.html b/third_party/WebKit/LayoutTests/animations/transitions-replay.html
index 083b041..a6ddb6d 100644
--- a/third_party/WebKit/LayoutTests/animations/transitions-replay.html
+++ b/third_party/WebKit/LayoutTests/animations/transitions-replay.html
@@ -16,8 +16,8 @@
     element.style.background = "green";
     element.offsetTop; // Force recalc
 
-    assert_equals(document.timeline.getAnimations().length, 1);
-    var animation = document.timeline.getAnimations()[0];
+    assert_equals(document.getAnimations().length, 1);
+    var animation = document.getAnimations()[0];
     animation.onfinish = function() {
         requestAnimationFrame(function() {
             requestAnimationFrame(function() {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html
index f0ac2da..093f39a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/read-succeeds.html
@@ -2,21 +2,20 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
-  return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter')
-    .then(() => requestDeviceWithKeyDown({
-      filters: [{services: ['health_thermometer']}]}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => gattServer.getPrimaryService('health_thermometer'))
-    .then(service => service.getCharacteristic('measurement_interval'))
-    .then(characteristic => characteristic.getDescriptor(user_description.name))
-    .then(descriptor => descriptor.readValue())
-    .then(value => {
-      let decoder = new TextDecoder('utf-8');
-      let value_str = decoder.decode(value);
-      assert_equals(value_str, "gatt.characteristic_user_description");
+  const EXPECTED_VALUE = [0, 1, 2];
+  return getUserDescriptionDescriptor()
+    .then(({descriptor, fake_descriptor}) => {
+      return fake_descriptor.setNextReadResponse(GATT_SUCCESS, EXPECTED_VALUE)
+        .then(() => descriptor.readValue())
+        .then(value => {
+          assert_array_equals(Array.from(new Uint8Array(
+            value.buffer)), EXPECTED_VALUE);
+        });
     });
 }, 'A read request succeeds and returns the descriptor\'s value.');
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
index 9566290..514c3d4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
@@ -90,7 +90,7 @@
 PASS Element.animate() correctly sets the Animation's timeline 
 PASS Element.animate() correctly sets the Animation's timeline when triggered on an element in a different document 
 PASS Element.animate() calls play on the Animation 
-FAIL CSSPseudoElement.animate() creates an Animation object document.getAnimations is not a function
-FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object document.getAnimations is not a function
+FAIL CSSPseudoElement.animate() creates an Animation object Cannot read property 'parentElement' of undefined
+FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object Cannot read property 'parentElement' of undefined
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations-expected.txt
index 58e88962..2779933 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations-expected.txt
@@ -1,7 +1,7 @@
 This is a testharness.js-based test.
-FAIL Test document.getAnimations for non-animated content document.getAnimations is not a function
-FAIL Test document.getAnimations for script-generated animations document.getAnimations is not a function
-FAIL Test the order of document.getAnimations with script generated animations document.getAnimations is not a function
-FAIL Test document.getAnimations with null target document.getAnimations is not a function
+PASS Test document.getAnimations for non-animated content 
+PASS Test document.getAnimations for script-generated animations 
+PASS Test the order of document.getAnimations with script generated animations 
+FAIL Test document.getAnimations with null target assert_equals: document.getAnimations() only returns animations targeting elements in this document expected 0 but got 3
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-above-min-size-and-below-initial-size.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-above-min-size-and-below-initial-size.html
new file mode 100644
index 0000000..ac11e0ce
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-above-min-size-and-below-initial-size.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<div style="width:800px; height:800px">
+<textarea id="textInputID">
+Some text
+</textarea>
+</div>
+
+<script>
+function drag(startX, startY, destX, destY, callback) {
+  chrome.gpuBenchmarking.pointerActionSequence([{source: 'mouse', actions:[
+    {name: 'pointerDown', x: startX, y: startY},
+    {name: 'pointerMove', x: destX, y: destY},
+    {name: 'pointerUp'}]}],
+    callback);
+}
+
+function testDragAndMove(textArea, nextCallback) {
+  var startX = textArea.offsetLeft + 400;
+  var startY = textArea.offsetTop + 400;
+  drag(startX, startY, startX - 150, startY - 150, t.step_func(() => {
+    assert_equals(textArea.style.width, '250px');
+    assert_equals(textArea.style.height, '250px');
+    nextCallback();
+  }));
+}
+
+var t = async_test('Test for resizing the TEXTAREA above minimum size set and below its initial size.');
+t.step(() => {
+  assert_exists(window, 'chrome');
+  assert_exists(chrome, 'gpuBenchmarking');
+
+  var textArea = document.getElementById('textInputID');
+  textArea.style.width = '400px';
+  textArea.style.height = '400px';
+  textArea.style.minWidth = '200px';
+  textArea.style.minHeight = '200px';
+  testDragAndMove(textArea, t.step_func(() => {
+    textArea.style.width = '400px';
+    textArea.style.height = '400px';
+    textArea.style.minWidth = '15vw';
+    textArea.style.minHeight = '15vh';
+    testDragAndMove(textArea, t.step_func(() => {
+      textArea.style.width = '400px';
+      textArea.style.height = '400px';
+      textArea.style.minWidth = '10%';
+      textArea.style.minHeight = '10%';
+      testDragAndMove(textArea, t.step_func_done());
+    }));
+  }));
+});
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-intrinsic-size.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-intrinsic-size.html
new file mode 100644
index 0000000..d76fe6b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-intrinsic-size.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<textarea style="width:400px; height:400px" id="textInputID">
+Some text
+</textarea>
+
+<script>
+function drag(startX, startY, destX, destY, callback) {
+  chrome.gpuBenchmarking.pointerActionSequence([{source: 'mouse', actions:[
+    {name: 'pointerDown', x: startX, y: startY},
+    {name: 'pointerMove', x: destX, y: destY},
+    {name: 'pointerUp'}]}],
+    callback);
+}
+
+var t = async_test('Test for resizing the TEXTAREA below its min intrinsic size.');
+t.step(() => {
+  assert_exists(window, 'chrome');
+  assert_exists(chrome, 'gpuBenchmarking');
+
+  var textArea = document.getElementById("textInputID");
+  var startX = textArea.offsetLeft + 400;
+  var startY = textArea.offsetTop + 400;
+  drag(startX, startY, startX - 395, startY - 395, t.step_func_done(() => {
+    // The min-width/min-height includes padding and border and width/height
+    // does not include padding and border.
+    // So when we set say min-width = 200px it means actual minimum width of box
+    // to be 194px (as 2px padding and 1px border on all side).
+    // Hence the condition check here for 9px as default minimum size for
+    // resizing is 15x15.
+    assert_equals(textArea.style.width, '9px');
+    assert_equals(textArea.style.height, '9px');
+  }));
+});
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-size-zoomed.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-size-zoomed.html
new file mode 100644
index 0000000..019eb12
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-size-zoomed.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<style>
+body {
+  zoom: 2;
+}
+
+textarea {
+  box-sizing: border-box;
+  width: 200px;
+  height: 200px;
+  min-width: 100px;
+  min-height: 100px;
+}
+</style>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<textarea id="textInputID">
+Some text
+</textarea>
+
+<script>
+var zoomFactor = 2;
+
+function drag(startX, startY, destX, destY, callback) {
+  chrome.gpuBenchmarking.pointerActionSequence([{source: 'mouse', actions:[
+    {name: 'pointerDown', x: startX * zoomFactor, y: startY * zoomFactor},
+    {name: 'pointerMove', x: destX * zoomFactor, y: destY * zoomFactor},
+    {name: 'pointerUp'}]}],
+    callback);
+}
+
+var t = async_test('Test for resizing the TEXTAREA below the minimum size set in zoomed environment.');
+t.step(() => {
+  assert_exists(window, 'chrome');
+  assert_exists(chrome, 'gpuBenchmarking');
+
+  var textArea = document.getElementById('textInputID');
+  var startX = textArea.offsetLeft + 195;
+  var startY = textArea.offsetTop + 195;
+  drag(startX, startY, startX - 150, startY - 150, t.step_func_done(() => {
+    assert_equals(textArea.style.width, '100px');
+    assert_equals(textArea.style.height, '100px');
+  }));
+});
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-size.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-size.html
new file mode 100644
index 0000000..b3ef76fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-below-min-size.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<div style="width:800px; height:800px">
+<textarea id="textInputID">
+Some text
+</textarea>
+</div>
+
+<script>
+function drag(startX, startY, destX, destY, callback) {
+  chrome.gpuBenchmarking.pointerActionSequence([{source: 'mouse', actions:[
+    {name: 'pointerDown', x: startX, y: startY},
+    {name: 'pointerMove', x: destX, y: destY},
+    {name: 'pointerUp'}]}],
+    callback);
+}
+
+function testDragAndMove(textArea, callback) {
+  var startX = textArea.offsetLeft + 400;
+  var startY = textArea.offsetTop + 400;
+  drag(startX, startY, startX - 350, startY - 350, callback);
+}
+
+var t = async_test('Test for resizing the TEXTAREA below the minimum size set.');
+t.step(() => {
+  assert_exists(window, 'chrome');
+  assert_exists(chrome, 'gpuBenchmarking');
+
+  var textArea = document.getElementById('textInputID');
+  textArea.style.width = '400px';
+  textArea.style.height = '400px';
+  textArea.style.minWidth = '200px';
+  textArea.style.minHeight = '200px';
+  testDragAndMove(textArea, t.step_func(() => {
+    // The min-width/min-height includes padding and border and width/height
+    // does not include padding and border.
+    // So when we set say min-width = 200px it means actual minimum width of box
+    // to be 194px (as 2px padding and 1px border on all side).
+    // Hence the condition check here for values which are lesser than original
+    // value by 6px.
+    assert_equals(textArea.style.width, '194px');
+    assert_equals(textArea.style.height, '194px');
+
+    textArea.style.width = '400px';
+    textArea.style.height = '400px';
+    textArea.style.minWidth = '15vw';
+    textArea.style.minHeight = '15vh';
+    testDragAndMove(textArea, t.step_func(() => {
+      assert_equals(textArea.style.width, '114px');
+      assert_equals(textArea.style.height, '84px');
+
+      textArea.style.width = '400px';
+      textArea.style.height = '400px';
+      textArea.style.minWidth = '10%';
+      textArea.style.minHeight = '10%';
+      testDragAndMove(textArea, t.step_func_done(() => {
+        assert_equals(textArea.style.width, '74px');
+        assert_equals(textArea.style.height, '74px');
+      }));
+    }));
+  }));
+});
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-orthogonal-containing-block.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-orthogonal-containing-block.html
new file mode 100644
index 0000000..fc45fd6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-resize-orthogonal-containing-block.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<div id="res" style="-webkit-writing-mode: vertical-lr; width:800px; height:700px">
+<textarea style="-webkit-writing-mode: horizontal-tb; width:400px; height:400px; min-width:10%; min-height:10%" id="textInputID">
+Some text
+</textarea>
+</div>
+
+<script>
+function drag(startX, startY, destX, destY, callback) {
+  chrome.gpuBenchmarking.pointerActionSequence([{source: 'mouse', actions:[
+    {name: 'pointerDown', x: startX, y: startY},
+    {name: 'pointerMove', x: destX, y: destY},
+    {name: 'pointerUp'}]}],
+    callback);
+}
+
+var t = async_test('Test for resizing the TEXTAREA below its initial size and with orthogonal containing block.');
+t.step(() => {
+  assert_exists(window, 'chrome');
+  assert_exists(chrome, 'gpuBenchmarking');
+
+  var textArea = document.getElementById("textInputID");
+  var startX = textArea.offsetLeft + 400;
+  var startY = textArea.offsetTop + 400;
+  drag(startX, startY, startX - 395, startY - 395, t.step_func_done(() => {
+    // The min-width/min-height includes padding and border and width/height
+    // does not include padding and border.
+    // So when we set say min-width = 200px it means actual minimum width of box
+    // to be 194px (as 2px padding and 1px border on all side).
+    // Also the containing block is orthogonal to the textarea so min-width will
+    // be 10% of height of containing block and min-height is 10% of width of
+    // containing block.
+    assert_equals(textArea.style.width, '74px');
+    assert_equals(textArea.style.height, '64px');
+  }));
+});
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
index e81942e2..7d2407e4 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -479,6 +479,9 @@
 //  - 'temperature_measurement' (indicate),
 //  - 'temperature_type' (read),
 //  - 'measurement_interval' (read, write, indicate)
+// The 'measurement_interval' characteristic contains a
+// 'gatt.client_characteristic_configuration' descriptor and a
+// 'characteristic_user_description' descriptor.
 // The device has been connected to and its attributes are ready to be
 // discovered.
 // TODO(crbug.com/719816): Add descriptors.
@@ -488,6 +491,7 @@
   let fake_generic_access;
   let fake_health_thermometer;
   let fake_measurement_interval;
+  let fake_user_description;
   return getConnectedHealthThermometerDevice(options)
     .then(result => {
       ({
@@ -496,6 +500,7 @@
         fake_generic_access,
         fake_health_thermometer,
         fake_measurement_interval,
+        fake_user_description,
       } = result);
     })
     .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
@@ -506,6 +511,7 @@
       fake_generic_access: fake_generic_access,
       fake_health_thermometer: fake_health_thermometer,
       fake_measurement_interval: fake_measurement_interval,
+      fake_user_description: fake_user_description,
     }));
 }
 
@@ -568,6 +574,21 @@
     });
 }
 
+function getUserDescriptionDescriptor() {
+  return getHealthThermometerDevice()
+    .then(result => {
+      return result
+        .device.gatt.getPrimaryService('health_thermometer')
+        .then(service => service.getCharacteristic('measurement_interval'))
+        .then(characteristic => characteristic.getDescriptor(
+          'gatt.characteristic_user_description'))
+        .then(descriptor => ({
+          descriptor: descriptor,
+          fake_descriptor: result.fake_user_description,
+        }));
+    });
+}
+
 // Similar to getHealthThermometerDevice except the GATT discovery
 // response has not been set yet so more attributes can still be added.
 function getConnectedHealthThermometerDevice(options) {
@@ -576,6 +597,7 @@
   let fake_generic_access;
   let fake_health_thermometer;
   let fake_measurement_interval;
+  let fake_user_description;
   let fake_temperature_measurement;
   let fake_temperature_type;
   return getDiscoveredHealthThermometerDevice(options)
@@ -595,6 +617,7 @@
     .then(c => fake_measurement_interval = c)
     .then(() => fake_measurement_interval.addFakeDescriptor({
       uuid: 'gatt.characteristic_user_description'}))
+    .then(d => fake_user_description = d)
     .then(() => fake_health_thermometer.addFakeCharacteristic({
       uuid: 'temperature_measurement', properties: ['indicate']}))
     .then(c => fake_temperature_measurement = c)
@@ -607,6 +630,7 @@
       fake_generic_access: fake_generic_access,
       fake_health_thermometer: fake_health_thermometer,
       fake_measurement_interval: fake_measurement_interval,
+      fake_user_description: fake_user_description,
       fake_temperature_measurement: fake_temperature_measurement,
       fake_temperature_type: fake_temperature_type,
     }));
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
index 08aaa81..2e54a3d 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
@@ -320,6 +320,27 @@
       this.ids_ = [descriptor_id, characteristic_id, service_id, peripheral_address];
       this.fake_central_ptr_ = fake_central_ptr;
     }
+
+    // Sets the next read response for descriptor to |code| and |value|.
+    // |code| could be a GATT Error Response from
+    // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
+    // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
+    // failure.
+    // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+    async setNextReadResponse(gatt_code, value=null) {
+      if (gatt_code === 0 && value === null) {
+        throw '|value| can\'t be null if read should success.';
+      }
+      if (gatt_code !== 0 && value !== null) {
+        throw '|value| must be null if read should fail.';
+      }
+
+      let {success} =
+        await this.fake_central_ptr_.setNextReadDescriptorResponse(
+          gatt_code, value, ...this.ids_);
+
+      if (!success) throw 'setNextReadDescriptorResponse failed';
+    }
   }
 
   navigator.bluetooth.test = new FakeBluetooth();
diff --git a/third_party/WebKit/LayoutTests/transitions/interrupted-immediately.html b/third_party/WebKit/LayoutTests/transitions/interrupted-immediately.html
index 92b58e8..08ee7a1 100644
--- a/third_party/WebKit/LayoutTests/transitions/interrupted-immediately.html
+++ b/third_party/WebKit/LayoutTests/transitions/interrupted-immediately.html
@@ -40,7 +40,7 @@
       // Force at least one timing update and recalc after the interruption.
       id = requestAnimationFrame(function() {
         cancelAnimationFrame(id);
-        var current = document.timeline.getAnimations().length;
+        var current = document.getAnimations().length;
         document.getElementById('result').innerHTML = (current == 0) ? "PASS" : "FAIL";
         if (window.testRunner)
             testRunner.notifyDone();
diff --git a/third_party/WebKit/LayoutTests/transitions/repeated-firing-background-color.html b/third_party/WebKit/LayoutTests/transitions/repeated-firing-background-color.html
index 16bd142..818cdc0 100644
--- a/third_party/WebKit/LayoutTests/transitions/repeated-firing-background-color.html
+++ b/third_party/WebKit/LayoutTests/transitions/repeated-firing-background-color.html
@@ -11,7 +11,7 @@
   <script>
     function checkRunning()
     {
-      var current = document.timeline.getAnimations().length;
+      var current = document.getAnimations().length;
       if (current == 0)
         document.getElementById('result').innerHTML = "PASS: Number of active transitions is (0) as expected";
       else
diff --git a/third_party/WebKit/LayoutTests/transitions/webkit-clip-path-equality.html b/third_party/WebKit/LayoutTests/transitions/webkit-clip-path-equality.html
index f0c23752..b62319b 100644
--- a/third_party/WebKit/LayoutTests/transitions/webkit-clip-path-equality.html
+++ b/third_party/WebKit/LayoutTests/transitions/webkit-clip-path-equality.html
@@ -20,14 +20,14 @@
 };
 function step1() {
   target.offsetTop;
-  result = document.timeline.getAnimations().length == 0 ?
+  result = document.getAnimations().length == 0 ?
       'PASS - No transition started.' :
       'FAIL - Unexpected transition started.';
   target.style.webkitClipPath = 'circle(200px at 0px 0px)';
   requestAnimationFrame(step2);
 }
 function step2() {
-  result += document.timeline.getAnimations().length == 1 ?
+  result += document.getAnimations().length == 1 ?
       '\nPASS - Transition started.' :
       '\nFAIL - Transition did not start.';
   document.documentElement.style.whiteSpace = 'pre';
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index 974714f..fce37a3 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -194,7 +194,6 @@
     attribute @@toStringTag
     getter currentTime
     method constructor
-    method getAnimations
 interface AppBannerPromptResult
     attribute @@toStringTag
     getter outcome
@@ -1583,6 +1582,7 @@
     method execCommand
     method exitFullscreen
     method exitPointerLock
+    method getAnimations
     method getElementById
     method getElementsByClassName
     method getElementsByName
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 1503604..40ee1b6 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -194,7 +194,6 @@
     attribute @@toStringTag
     getter currentTime
     method constructor
-    method getAnimations
 interface AppBannerPromptResult
     attribute @@toStringTag
     getter outcome
@@ -1583,6 +1582,7 @@
     method execCommand
     method exitFullscreen
     method exitPointerLock
+    method getAnimations
     method getElementById
     method getElementsByClassName
     method getElementsByName
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 628c88a8..2d37787 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1359,6 +1359,8 @@
     "html/track/vtt/VTTScannerTest.cpp",
     "imagebitmap/ImageBitmapTest.cpp",
     "input/EventHandlerTest.cpp",
+    "input/ImeOnFocusTest.cpp",
+    "input/TouchActionTest.cpp",
     "inspector/ProtocolParserTest.cpp",
     "layout/CollapsedBorderValueTest.cpp",
     "layout/ImageQualityControllerTest.cpp",
@@ -1445,7 +1447,9 @@
     "page/PageOverlayTest.cpp",
     "page/PagePopupClientTest.cpp",
     "page/PrintContextTest.cpp",
+    "page/ViewportTest.cpp",
     "page/WindowFeaturesTest.cpp",
+    "page/scrolling/RootScrollerTest.cpp",
     "page/scrolling/ScrollStateTest.cpp",
     "page/scrolling/ScrollingCoordinatorTest.cpp",
     "page/scrolling/SnapCoordinatorTest.cpp",
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
index 5b98218..dd32f96f 100644
--- a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
+++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
@@ -8,7 +8,4 @@
     RuntimeEnabled=WebAnimationsAPI
 ] interface AnimationTimeline {
     readonly attribute double? currentTime;
-
-    // TODO(crbug.com/624639): Move getAnimations() to DocumentAnimatable
-    sequence<Animation> getAnimations();
 };
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimation.h b/third_party/WebKit/Source/core/animation/DocumentAnimation.h
index 4dd9c118..a8963b3 100644
--- a/third_party/WebKit/Source/core/animation/DocumentAnimation.h
+++ b/third_party/WebKit/Source/core/animation/DocumentAnimation.h
@@ -5,6 +5,8 @@
 #ifndef DocumentAnimation_h
 #define DocumentAnimation_h
 
+#include "core/animation/Animation.h"
+#include "core/animation/DocumentTimeline.h"
 #include "core/dom/Document.h"
 #include "platform/wtf/Allocator.h"
 
@@ -17,6 +19,10 @@
   static DocumentTimeline* timeline(Document& document) {
     return &document.Timeline();
   }
+
+  static HeapVector<Member<Animation>> getAnimations(Document& document) {
+    return document.Timeline().getAnimations();
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/DocumentAnimation.idl b/third_party/WebKit/Source/core/animation/DocumentAnimation.idl
index 57d618e..c15faaa 100644
--- a/third_party/WebKit/Source/core/animation/DocumentAnimation.idl
+++ b/third_party/WebKit/Source/core/animation/DocumentAnimation.idl
@@ -8,4 +8,6 @@
     RuntimeEnabled=WebAnimationsAPI
 ] partial interface Document {
     readonly attribute DocumentTimeline timeline;
+
+    sequence<Animation> getAnimations();
 };
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index d2e018e..8ded0bc 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -3248,17 +3248,6 @@
   return false;
 }
 
-LayoutSize Element::MinimumSizeForResizing() const {
-  return HasRareData() ? GetElementRareData()->MinimumSizeForResizing()
-                       : DefaultMinimumSizeForResizing();
-}
-
-void Element::SetMinimumSizeForResizing(const LayoutSize& size) {
-  if (!HasRareData() && size == DefaultMinimumSizeForResizing())
-    return;
-  EnsureElementRareData().SetMinimumSizeForResizing(size);
-}
-
 const ComputedStyle* Element::EnsureComputedStyle(
     PseudoId pseudo_element_specifier) {
   if (PseudoElement* element = GetPseudoElement(pseudo_element_specifier))
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index c9a79e5..68baf15 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -633,9 +633,6 @@
   // used only in UA stylesheet.
   void SetShadowPseudoId(const AtomicString&);
 
-  LayoutSize MinimumSizeForResizing() const;
-  void SetMinimumSizeForResizing(const LayoutSize&);
-
   // Called by the parser when this element's close tag is reached, signaling
   // that all child tags have been parsed and added.  This is needed for
   // <applet> and <object> elements, which can't lay themselves out until they
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.cpp b/third_party/WebKit/Source/core/dom/ElementRareData.cpp
index 6c30355..a5ea8092 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.cpp
@@ -38,7 +38,6 @@
 namespace blink {
 
 struct SameSizeAsElementRareData : NodeRareData {
-  LayoutSize size_for_resizing;
   IntSize scroll_offset;
   AtomicString nonce;
   void* pointers[1];
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.h b/third_party/WebKit/Source/core/dom/ElementRareData.h
index 57cab33..ffbf5a7 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.h
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.h
@@ -106,13 +106,6 @@
     ScriptWrappableVisitor::WriteBarrier(this, dataset_);
   }
 
-  LayoutSize MinimumSizeForResizing() const {
-    return minimum_size_for_resizing_;
-  }
-  void SetMinimumSizeForResizing(LayoutSize size) {
-    minimum_size_for_resizing_ = size;
-  }
-
   ScrollOffset SavedLayerScrollOffset() const {
     return saved_layer_scroll_offset_;
   }
@@ -187,7 +180,6 @@
   DECLARE_TRACE_WRAPPERS_AFTER_DISPATCH();
 
  private:
-  LayoutSize minimum_size_for_resizing_;
   ScrollOffset saved_layer_scroll_offset_;
   AtomicString nonce_;
 
@@ -222,7 +214,6 @@
 
 inline ElementRareData::ElementRareData(NodeRenderingData* node_layout_data)
     : NodeRareData(node_layout_data),
-      minimum_size_for_resizing_(DefaultMinimumSizeForResizing()),
       class_list_(nullptr) {
   is_element_rare_data_ = true;
 }
diff --git a/third_party/WebKit/Source/core/dom/Modulator.cpp b/third_party/WebKit/Source/core/dom/Modulator.cpp
index d240b8e0..47a504e 100644
--- a/third_party/WebKit/Source/core/dom/Modulator.cpp
+++ b/third_party/WebKit/Source/core/dom/Modulator.cpp
@@ -7,6 +7,7 @@
 #include "bindings/core/v8/V8BindingForCore.h"
 #include "core/dom/Document.h"
 #include "core/dom/ModulatorImpl.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrame.h"
 #include "core/workers/MainThreadWorkletGlobalScope.h"
 #include "platform/bindings/ScriptState.h"
@@ -35,12 +36,19 @@
     Document* document = ToDocument(execution_context);
     modulator = ModulatorImpl::Create(script_state, document->Fetcher());
     Modulator::SetModulator(script_state, modulator);
+
+    // See comment in LocalDOMWindow::modulator_ for this workaround.
+    LocalDOMWindow* window = document->ExecutingWindow();
+    window->SetModulator(modulator);
   } else if (execution_context->IsMainThreadWorkletGlobalScope()) {
     MainThreadWorkletGlobalScope* global_scope =
         ToMainThreadWorkletGlobalScope(execution_context);
     modulator = ModulatorImpl::Create(
         script_state, global_scope->GetFrame()->GetDocument()->Fetcher());
     Modulator::SetModulator(script_state, modulator);
+
+    // See comment in WorkletGlobalScope::modulator_ for this workaround.
+    global_scope->SetModulator(modulator);
   } else {
     NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/core/editing/Position.cpp b/third_party/WebKit/Source/core/editing/Position.cpp
index 9647826..bb52336 100644
--- a/third_party/WebKit/Source/core/editing/Position.cpp
+++ b/third_party/WebKit/Source/core/editing/Position.cpp
@@ -188,7 +188,7 @@
     case PositionAnchorType::kBeforeChildren:
       return 0;
     case PositionAnchorType::kAfterChildren:
-      return LastOffsetInNode(anchor_node_.Get());
+      return LastOffsetInNode(*anchor_node_);
     case PositionAnchorType::kOffsetInAnchor:
       return MinOffsetForNode<Strategy>(anchor_node_.Get(), offset_);
     case PositionAnchorType::kBeforeAnchor:
@@ -481,10 +481,10 @@
 
 // static
 template <typename Strategy>
-int PositionTemplate<Strategy>::LastOffsetInNode(Node* node) {
-  return node->IsCharacterDataNode()
-             ? node->MaxCharacterOffset()
-             : static_cast<int>(Strategy::CountChildren(*node));
+int PositionTemplate<Strategy>::LastOffsetInNode(const Node& node) {
+  return node.IsCharacterDataNode()
+             ? node.MaxCharacterOffset()
+             : static_cast<int>(Strategy::CountChildren(node));
 }
 
 // static
@@ -501,9 +501,10 @@
 template <typename Strategy>
 PositionTemplate<Strategy> PositionTemplate<Strategy>::LastPositionInNode(
     Node* anchor_node) {
-  if (anchor_node->IsTextNode())
+  if (anchor_node->IsTextNode()) {
     return PositionTemplate<Strategy>(anchor_node,
-                                      LastOffsetInNode(anchor_node));
+                                      LastOffsetInNode(*anchor_node));
+  }
   return PositionTemplate<Strategy>(anchor_node,
                                     PositionAnchorType::kAfterChildren);
 }
diff --git a/third_party/WebKit/Source/core/editing/Position.h b/third_party/WebKit/Source/core/editing/Position.h
index 0e97aae..572c83a 100644
--- a/third_party/WebKit/Source/core/editing/Position.h
+++ b/third_party/WebKit/Source/core/editing/Position.h
@@ -192,7 +192,7 @@
   static PositionTemplate<Strategy> AfterNode(const Node& anchor_node);
   static PositionTemplate<Strategy> InParentBeforeNode(const Node& anchor_node);
   static PositionTemplate<Strategy> InParentAfterNode(const Node& anchor_node);
-  static int LastOffsetInNode(Node* anchor_node);
+  static int LastOffsetInNode(const Node& anchor_node);
   static PositionTemplate<Strategy> FirstPositionInNode(
       const Node& anchor_node);
   static PositionTemplate<Strategy> LastPositionInNode(Node* anchor_node);
diff --git a/third_party/WebKit/Source/core/editing/VisiblePosition.cpp b/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
index 63daef9..e119c14 100644
--- a/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
+++ b/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
@@ -109,9 +109,9 @@
 
 template <typename Strategy>
 VisiblePositionTemplate<Strategy> VisiblePositionTemplate<Strategy>::BeforeNode(
-    Node* node) {
+    const Node& node) {
   return Create(PositionWithAffinityTemplate<Strategy>(
-      PositionTemplate<Strategy>::BeforeNode(*node)));
+      PositionTemplate<Strategy>::BeforeNode(node)));
 }
 
 template <typename Strategy>
diff --git a/third_party/WebKit/Source/core/editing/VisiblePosition.h b/third_party/WebKit/Source/core/editing/VisiblePosition.h
index 496ad6a..a98122b 100644
--- a/third_party/WebKit/Source/core/editing/VisiblePosition.h
+++ b/third_party/WebKit/Source/core/editing/VisiblePosition.h
@@ -105,7 +105,7 @@
   TextAffinity Affinity() const { return position_with_affinity_.Affinity(); }
 
   static VisiblePositionTemplate<Strategy> AfterNode(const Node&);
-  static VisiblePositionTemplate<Strategy> BeforeNode(Node*);
+  static VisiblePositionTemplate<Strategy> BeforeNode(const Node&);
   static VisiblePositionTemplate<Strategy> FirstPositionInNode(Node*);
   static VisiblePositionTemplate<Strategy> InParentAfterNode(const Node&);
   static VisiblePositionTemplate<Strategy> InParentBeforeNode(const Node&);
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 21d0a7b..56ff069 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -1729,7 +1729,7 @@
 
   GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
 
-  VisiblePosition at_br = VisiblePosition::BeforeNode(br);
+  VisiblePosition at_br = VisiblePosition::BeforeNode(*br);
   // If the br we inserted collapsed, for example:
   //   foo<br><blockquote>...</blockquote>
   // insert a second one.
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index 12c6052..c3d742ef 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -431,7 +431,7 @@
   if (upstream_start_is_br && downstream_start_is_br) {
     GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
     if (!(IsStartOfBlock(
-              VisiblePosition::BeforeNode(node_after_upstream_start)) &&
+              VisiblePosition::BeforeNode(*node_after_upstream_start)) &&
           IsEndOfBlock(
               VisiblePosition::AfterNode(*node_after_upstream_start)))) {
       starts_at_empty_line_ = true;
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
index bfaba53..7bd2a581 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
@@ -333,7 +333,7 @@
   end_of_paragraph_to_move =
       CreateVisiblePosition(end_of_paragraph_to_move.ToPositionWithAffinity());
   MoveParagraph(start_of_paragraph_to_move, end_of_paragraph_to_move,
-                VisiblePosition::BeforeNode(placeholder), editing_state,
+                VisiblePosition::BeforeNode(*placeholder), editing_state,
                 kPreserveSelection);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
index 4d8630f..80f43f9 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertLineBreakCommand.cpp
@@ -137,7 +137,7 @@
     GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
 
     // Insert an extra br or '\n' if the just inserted one collapsed.
-    if (!IsStartOfParagraph(VisiblePosition::BeforeNode(node_to_insert))) {
+    if (!IsStartOfParagraph(VisiblePosition::BeforeNode(*node_to_insert))) {
       InsertNodeBefore(node_to_insert->cloneNode(false), node_to_insert,
                        editing_state);
       if (editing_state->IsAborted())
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index 3635296f..b3a5d0f 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -421,7 +421,8 @@
       if (range_start_is_in_list && new_list)
         current_selection.setStart(new_list, 0, IGNORE_EXCEPTION_FOR_TESTING);
       if (range_end_is_in_list && new_list) {
-        current_selection.setEnd(new_list, Position::LastOffsetInNode(new_list),
+        current_selection.setEnd(new_list,
+                                 Position::LastOffsetInNode(*new_list),
                                  IGNORE_EXCEPTION_FOR_TESTING);
       }
 
@@ -527,7 +528,7 @@
   start = CreateVisiblePosition(start_position);
   end = CreateVisiblePosition(end_position);
 
-  VisiblePosition insertion_point = VisiblePosition::BeforeNode(placeholder);
+  VisiblePosition insertion_point = VisiblePosition::BeforeNode(*placeholder);
   MoveParagraphs(start, end, insertion_point, editing_state, kPreserveSelection,
                  kPreserveStyle, list_child_node);
 }
@@ -680,7 +681,7 @@
       StartOfParagraph(valid_pos, kCanSkipOverEditingBoundary);
   const VisiblePosition& end =
       EndOfParagraph(valid_pos, kCanSkipOverEditingBoundary);
-  MoveParagraph(start, end, VisiblePosition::BeforeNode(placeholder),
+  MoveParagraph(start, end, VisiblePosition::BeforeNode(*placeholder),
                 editing_state, kPreserveSelection);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index 760d55c..e2f5bfc 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -538,7 +538,7 @@
 
   // Move the start node and the siblings of the start node.
   if (CreateVisiblePosition(insertion_position).DeepEquivalent() !=
-      VisiblePosition::BeforeNode(block_to_insert).DeepEquivalent()) {
+      VisiblePosition::BeforeNode(*block_to_insert).DeepEquivalent()) {
     Node* n;
     if (insertion_position.ComputeContainerNode() == start_block) {
       n = insertion_position.ComputeNodeAfterPosition();
@@ -554,7 +554,7 @@
       GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
 
       for (n = start_block->firstChild(); n; n = n->nextSibling()) {
-        VisiblePosition before_node_position = VisiblePosition::BeforeNode(n);
+        VisiblePosition before_node_position = VisiblePosition::BeforeNode(*n);
         if (!before_node_position.IsNull() &&
             ComparePositions(CreateVisiblePosition(insertion_position),
                              before_node_position) <= 0)
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index e44d9d4f..7a6123b9 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -934,7 +934,7 @@
     // needs to be audited.  See http://crbug.com/590369 for more details.
     GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
 
-    destination = VisiblePosition::BeforeNode(placeholder);
+    destination = VisiblePosition::BeforeNode(*placeholder);
     start_of_paragraph_to_move = CreateVisiblePosition(
         start_of_paragraph_to_move.ToPositionWithAffinity());
   }
@@ -1184,9 +1184,10 @@
                 MostForwardCaretPosition(insertion_pos).AnchorNode())
           : 0;
   VisiblePosition original_vis_pos_before_end_br;
-  if (end_br)
+  if (end_br) {
     original_vis_pos_before_end_br =
-        PreviousPositionOf(VisiblePosition::BeforeNode(end_br));
+        PreviousPositionOf(VisiblePosition::BeforeNode(*end_br));
+  }
 
   Element* enclosing_block_of_insertion_pos =
       EnclosingBlock(insertion_pos.AnchorNode());
@@ -1597,7 +1598,7 @@
   if (!end_br || !end_br->isConnected())
     return false;
 
-  VisiblePosition visible_pos = VisiblePosition::BeforeNode(end_br);
+  VisiblePosition visible_pos = VisiblePosition::BeforeNode(*end_br);
 
   // Don't remove the br if nothing was inserted.
   if (PreviousPositionOf(visible_pos).DeepEquivalent() ==
@@ -1980,7 +1981,7 @@
       isHTMLBRElement(*node_after_insertion_pos) &&
       ShouldRemoveEndBR(
           toHTMLBRElement(node_after_insertion_pos),
-          VisiblePosition::BeforeNode(node_after_insertion_pos))) {
+          VisiblePosition::BeforeNode(*node_after_insertion_pos))) {
     RemoveNodeAndPruneAncestors(node_after_insertion_pos, editing_state);
     if (editing_state->IsAborted())
       return false;
diff --git a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
index d4b8ca1..9e84c9f 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
@@ -116,7 +116,7 @@
     // traversing the children twice.
     if (Node* child_at_offset = Strategy::ChildAt(*end_node, end_offset - 1)) {
       end_node = child_at_offset;
-      end_offset = Position::LastOffsetInNode(end_node);
+      end_offset = Position::LastOffsetInNode(*end_node);
     }
   }
 
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index 65ac5ee..3bfb044 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -737,7 +737,7 @@
   // for them either.
   VisiblePosition start_pos =
       CreateVisiblePosition(Position(start_container_, start_offset_));
-  VisiblePosition curr_pos = VisiblePosition::BeforeNode(node_);
+  VisiblePosition curr_pos = VisiblePosition::BeforeNode(*node_);
   return start_pos.IsNotNull() && curr_pos.IsNotNull() &&
          !InSameLine(start_pos, curr_pos);
 }
diff --git a/third_party/WebKit/Source/core/exported/BUILD.gn b/third_party/WebKit/Source/core/exported/BUILD.gn
index d8d2281..1d645502 100644
--- a/third_party/WebKit/Source/core/exported/BUILD.gn
+++ b/third_party/WebKit/Source/core/exported/BUILD.gn
@@ -34,6 +34,8 @@
     "WebFileChooserCompletionImpl.h",
     "WebFormControlElement.cpp",
     "WebFormElement.cpp",
+    "WebFormElementObserverImpl.cpp",
+    "WebFormElementObserverImpl.h",
     "WebFrame.cpp",
     "WebFrameContentDumper.cpp",
     "WebFrameSerializer.cpp",
diff --git a/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp b/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
rename to third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp
index 2bfc9e2c..9c06a9f 100644
--- a/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp
@@ -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 "web/WebFormElementObserverImpl.h"
+#include "core/exported/WebFormElementObserverImpl.h"
 
 #include "core/css/CSSComputedStyleDeclaration.h"
 #include "core/dom/MutationCallback.h"
diff --git a/third_party/WebKit/Source/web/WebFormElementObserverImpl.h b/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.h
similarity index 93%
rename from third_party/WebKit/Source/web/WebFormElementObserverImpl.h
rename to third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.h
index e6a734b..50983ba 100644
--- a/third_party/WebKit/Source/web/WebFormElementObserverImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.h
@@ -5,19 +5,19 @@
 #ifndef WebFormElementObserverImpl_h
 #define WebFormElementObserverImpl_h
 
+#include "core/CoreExport.h"
 #include "platform/heap/HeapAllocator.h"
 #include "platform/heap/Member.h"
 #include "platform/heap/SelfKeepAlive.h"
 #include "platform/wtf/Compiler.h"
 #include "public/web/modules/password_manager/WebFormElementObserver.h"
-#include "web/WebExport.h"
 
 namespace blink {
 
 class HTMLElement;
 class WebFormElementObserverCallback;
 
-class WEB_EXPORT WebFormElementObserverImpl final
+class CORE_EXPORT WebFormElementObserverImpl final
     : public GarbageCollectedFinalized<WebFormElementObserverImpl>,
       NON_EXPORTED_BASE(public WebFormElementObserver) {
   WTF_MAKE_NONCOPYABLE(WebFormElementObserverImpl);
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index 90e2efa..58ae6f4 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -38,6 +38,7 @@
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/DOMImplementation.h"
 #include "core/dom/FrameRequestCallback.h"
+#include "core/dom/Modulator.h"
 #include "core/dom/SandboxFlags.h"
 #include "core/dom/SinkDocument.h"
 #include "core/dom/TaskRunnerHelper.h"
@@ -277,7 +278,8 @@
           this,
           &LocalDOMWindow::WarnUnusedPreloads),
       should_print_when_finished_loading_(false),
-      custom_elements_(this, nullptr) {}
+      custom_elements_(this, nullptr),
+      modulator_(this, nullptr) {}
 
 void LocalDOMWindow::ClearDocument() {
   if (!document_)
@@ -1407,6 +1409,11 @@
   return custom_elements_;
 }
 
+void LocalDOMWindow::SetModulator(Modulator* modulator) {
+  DCHECK(!modulator_);
+  modulator_ = modulator;
+}
+
 External* LocalDOMWindow::external() {
   if (!external_)
     external_ = new External;
@@ -1668,6 +1675,7 @@
 
 DEFINE_TRACE_WRAPPERS(LocalDOMWindow) {
   visitor->TraceWrappers(custom_elements_);
+  visitor->TraceWrappers(modulator_);
   DOMWindow::TraceWrappers(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
index 2ad0b6a..dbd662c 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -63,6 +63,7 @@
 class IdleRequestOptions;
 class MediaQueryList;
 class MessageEvent;
+class Modulator;
 class Navigator;
 class PostMessageTimer;
 class Screen;
@@ -232,6 +233,8 @@
   CustomElementRegistry* customElements() const;
   CustomElementRegistry* MaybeCustomElements() const;
 
+  void SetModulator(Modulator*);
+
   // Obsolete APIs
   void captureEvents() {}
   void releaseEvents() {}
@@ -361,6 +364,13 @@
   mutable Member<Navigator> navigator_;
   mutable Member<StyleMedia> media_;
   mutable TraceWrapperMember<CustomElementRegistry> custom_elements_;
+  // We store reference to Modulator here to have it TraceWrapper-ed.
+  // This is wrong, as Modulator is per-context, where as LocalDOMWindow is
+  // shared among context. However, this *works* as Modulator is currently only
+  // enabled in the main world,
+  // TODO(kouhei): Remove this workaround once V8PerContextData::Data is
+  // TraceWrapperBase.
+  TraceWrapperMember<Modulator> modulator_;
   Member<External> external_;
 
   String status_;
diff --git a/third_party/WebKit/Source/core/html/TextControlElement.cpp b/third_party/WebKit/Source/core/html/TextControlElement.cpp
index fd8032bd..d05dac2d 100644
--- a/third_party/WebKit/Source/core/html/TextControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/TextControlElement.cpp
@@ -630,7 +630,7 @@
   for (Node& node : NodeTraversal::DescendantsOf(*inner_text)) {
     DCHECK(!node.hasChildren());
     DCHECK(node.IsTextNode() || isHTMLBRElement(node));
-    int length = node.IsTextNode() ? Position::LastOffsetInNode(&node) : 1;
+    int length = node.IsTextNode() ? Position::LastOffsetInNode(node) : 1;
 
     if (offset <= start && start <= offset + length)
       SetContainerAndOffsetForRange(&node, start - offset, start_node, start);
diff --git a/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp b/third_party/WebKit/Source/core/input/ImeOnFocusTest.cpp
similarity index 100%
rename from third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
rename to third_party/WebKit/Source/core/input/ImeOnFocusTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/TouchActionTest.cpp b/third_party/WebKit/Source/core/input/TouchActionTest.cpp
similarity index 100%
rename from third_party/WebKit/Source/web/tests/TouchActionTest.cpp
rename to third_party/WebKit/Source/core/input/TouchActionTest.cpp
diff --git a/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp b/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp
index 3930605..658e00c 100644
--- a/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp
+++ b/third_party/WebKit/Source/core/loader/SubresourceFilter.cpp
@@ -69,7 +69,7 @@
   // preloads) happening here.
   RefPtr<WebTaskRunner> task_runner = TaskRunnerHelper::Get(
       TaskType::kNetworking, document_loader_->GetFrame());
-  DCHECK(task_runner->RunsTasksOnCurrentThread());
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
   task_runner->PostTask(BLINK_FROM_HERE,
                         WTF::Bind(&SubresourceFilter::ReportLoad,
                                   WrapPersistent(this), url, load_policy));
diff --git a/third_party/WebKit/Source/web/tests/ViewportTest.cpp b/third_party/WebKit/Source/core/page/ViewportTest.cpp
similarity index 100%
rename from third_party/WebKit/Source/web/tests/ViewportTest.cpp
rename to third_party/WebKit/Source/core/page/ViewportTest.cpp
diff --git a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
similarity index 100%
rename from third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
rename to third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 13a42ca9..821c591 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -88,6 +88,15 @@
 
 namespace blink {
 
+namespace {
+
+// Default value is set to 15 as the default
+// minimum size used by firefox is 15x15.
+static const int kDefaultMinimumWidthForResizing = 15;
+static const int kDefaultMinimumHeightForResizing = 15;
+
+}  // namespace
+
 static LayoutRect LocalToAbsolute(LayoutBox& offset, LayoutRect rect) {
   return LayoutRect(
       offset.LocalToAbsoluteQuad(FloatQuad(FloatRect(rect)), kUseTransforms)
@@ -1672,6 +1681,18 @@
   return local_point - resizer_point;
 }
 
+LayoutSize PaintLayerScrollableArea::MinimumSizeForResizing(float zoom_factor) {
+  LayoutUnit min_width = MinimumValueForLength(
+      Box().StyleRef().MinWidth(), Box().ContainingBlock()->Size().Width());
+  LayoutUnit min_height = MinimumValueForLength(
+      Box().StyleRef().MinHeight(), Box().ContainingBlock()->Size().Height());
+  min_width = std::max(LayoutUnit(min_width / zoom_factor),
+                       LayoutUnit(kDefaultMinimumWidthForResizing));
+  min_height = std::max(LayoutUnit(min_height / zoom_factor),
+                        LayoutUnit(kDefaultMinimumHeightForResizing));
+  return LayoutSize(min_width, min_height);
+}
+
 void PaintLayerScrollableArea::Resize(const IntPoint& pos,
                                       const LayoutSize& old_offset) {
   // FIXME: This should be possible on generated content but is not right now.
@@ -1692,9 +1713,6 @@
 
   LayoutSize current_size = Box().Size();
   current_size.Scale(1 / zoom_factor);
-  LayoutSize minimum_size =
-      element->MinimumSizeForResizing().ShrunkTo(current_size);
-  element->SetMinimumSizeForResizing(minimum_size);
 
   LayoutSize adjusted_old_offset = LayoutSize(
       old_offset.Width() / zoom_factor, old_offset.Height() / zoom_factor);
@@ -1704,7 +1722,7 @@
   }
 
   LayoutSize difference((current_size + new_offset - adjusted_old_offset)
-                            .ExpandedTo(minimum_size) -
+                            .ExpandedTo(MinimumSizeForResizing(zoom_factor)) -
                         current_size);
 
   bool is_box_sizing_border =
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
index e3fa7ab..10c6f8b7 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -531,6 +531,7 @@
   bool SetHasVerticalScrollbar(bool has_scrollbar);
 
   void UpdateScrollCornerStyle();
+  LayoutSize MinimumSizeForResizing(float zoom_factor);
 
   // See comments on isPointInResizeControl.
   void UpdateResizerAreaSet();
diff --git a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
index dbd8255..84d8b86 100644
--- a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
@@ -7,8 +7,10 @@
 #include <memory>
 #include "bindings/core/v8/SourceLocation.h"
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
+#include "core/dom/Modulator.h"
 #include "core/inspector/MainThreadDebugger.h"
 #include "core/probe/CoreProbes.h"
+#include "platform/bindings/TraceWrapperMember.h"
 
 namespace blink {
 
@@ -20,7 +22,8 @@
     WorkerClients* worker_clients)
     : WorkerOrWorkletGlobalScope(isolate, worker_clients),
       url_(url),
-      user_agent_(user_agent) {
+      user_agent_(user_agent),
+      modulator_(this, nullptr) {
   SetSecurityOrigin(std::move(security_origin));
 }
 
@@ -65,6 +68,10 @@
   return false;
 }
 
+void WorkletGlobalScope::SetModulator(Modulator* modulator) {
+  modulator_ = modulator;
+}
+
 KURL WorkletGlobalScope::VirtualCompleteURL(const String& url) const {
   // Always return a null URL when passed a null string.
   // TODO(ikilpatrick): Should we change the KURL constructor to have this
@@ -76,9 +83,14 @@
 }
 
 DEFINE_TRACE(WorkletGlobalScope) {
+  visitor->Trace(modulator_);
   ExecutionContext::Trace(visitor);
   SecurityContext::Trace(visitor);
   WorkerOrWorkletGlobalScope::Trace(visitor);
 }
 
+DEFINE_TRACE_WRAPPERS(WorkletGlobalScope) {
+  visitor->TraceWrappers(modulator_);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.h
index b8c97e6..6328235 100644
--- a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.h
@@ -13,11 +13,13 @@
 #include "core/workers/WorkerOrWorkletGlobalScope.h"
 #include "platform/bindings/ActiveScriptWrappable.h"
 #include "platform/bindings/ScriptWrappable.h"
+#include "platform/bindings/TraceWrapperMember.h"
 #include "platform/heap/Handle.h"
 
 namespace blink {
 
 class EventQueue;
+class Modulator;
 
 class CORE_EXPORT WorkletGlobalScope
     : public GarbageCollectedFinalized<WorkletGlobalScope>,
@@ -70,7 +72,10 @@
     return nullptr;
   }  // WorkletGlobalScopes don't have timers.
 
+  void SetModulator(Modulator*);
+
   DECLARE_VIRTUAL_TRACE();
+  DECLARE_VIRTUAL_TRACE_WRAPPERS();
 
  protected:
   // The url, userAgent and securityOrigin arguments are inherited from the
@@ -90,6 +95,9 @@
 
   KURL url_;
   String user_agent_;
+  // LocalDOMWindow::modulator_ workaround equivalent.
+  // TODO(kouhei): Remove this.
+  TraceWrapperMember<Modulator> modulator_;
 };
 
 DEFINE_TYPE_CASTS(WorkletGlobalScope,
diff --git a/third_party/WebKit/Source/platform/Timer.cpp b/third_party/WebKit/Source/platform/Timer.cpp
index a1612d50..781095c4 100644
--- a/third_party/WebKit/Source/platform/Timer.cpp
+++ b/third_party/WebKit/Source/platform/Timer.cpp
@@ -88,7 +88,7 @@
 void TimerBase::MoveToNewTaskRunner(RefPtr<WebTaskRunner> task_runner) {
 #if DCHECK_IS_ON()
   DCHECK_EQ(thread_, CurrentThread());
-  DCHECK(task_runner->RunsTasksOnCurrentThread());
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
 #endif
   // If the underlying task runner stays the same, ignore it.
   if (web_task_runner_->ToSingleThreadTaskRunner() ==
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.cpp b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
index 8bdfe57..e23f058e 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.cpp
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
@@ -111,10 +111,6 @@
   DCHECK(runner_);
 }
 
-bool WebTaskRunner::RunsTasksOnCurrentThread() {
-  return RunsTasksInCurrentSequence();
-}
-
 // Use a custom function for base::Bind instead of convertToBaseCallback to
 // avoid copying the closure later in the call chain. Copying the bound state
 // can lead to data races with ref counted objects like StringImpl. See
@@ -148,7 +144,7 @@
 TaskHandle WebTaskRunner::PostCancellableTask(
     const WebTraceLocation& location,
     std::unique_ptr<WTF::Closure> task) {
-  DCHECK(RunsTasksOnCurrentThread());
+  DCHECK(RunsTasksInCurrentSequence());
   RefPtr<TaskHandle::Runner> runner =
       AdoptRef(new TaskHandle::Runner(std::move(task)));
   PostTask(location, WTF::Bind(&TaskHandle::Runner::Run, runner->AsWeakPtr(),
@@ -160,7 +156,7 @@
     const WebTraceLocation& location,
     std::unique_ptr<WTF::Closure> task,
     TimeDelta delay) {
-  DCHECK(RunsTasksOnCurrentThread());
+  DCHECK(RunsTasksInCurrentSequence());
   RefPtr<TaskHandle::Runner> runner =
       AdoptRef(new TaskHandle::Runner(std::move(task)));
   PostDelayedTask(location,
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.h b/third_party/WebKit/Source/platform/WebTaskRunner.h
index 19f8690..74f90016 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.h
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.h
@@ -60,10 +60,6 @@
 class BLINK_PLATFORM_EXPORT WebTaskRunner
     : public ThreadSafeRefCounted<WebTaskRunner> {
  public:
-  // Drepecated: favor RunsTasksInCurrentSequence().
-  // TODO(http://crbug.com/665062): mass redirect callers and remove this.
-  bool RunsTasksOnCurrentThread();
-
   // Returns true if tasks posted to this TaskRunner are sequenced
   // with this call.
   virtual bool RunsTasksInCurrentSequence() = 0;
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
index c56e36a..85397741 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
@@ -218,7 +218,7 @@
   if (!observer_list)
     return;
 
-  DCHECK(task_runner->RunsTasksOnCurrentThread());
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
 
   observer_list->iterating = true;
 
@@ -249,7 +249,7 @@
 void NetworkStateNotifier::AddObserver(ObserverListMap& map,
                                        NetworkStateObserver* observer,
                                        PassRefPtr<WebTaskRunner> task_runner) {
-  DCHECK(task_runner->RunsTasksOnCurrentThread());
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
   DCHECK(observer);
 
   MutexLocker locker(mutex_);
@@ -265,7 +265,7 @@
 void NetworkStateNotifier::RemoveObserver(ObserverListMap& map,
                                           NetworkStateObserver* observer,
                                           RefPtr<WebTaskRunner> task_runner) {
-  DCHECK(task_runner->RunsTasksOnCurrentThread());
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
   DCHECK(observer);
 
   ObserverList* observer_list = LockAndFindObserverList(map, task_runner);
@@ -296,7 +296,7 @@
     ObserverListMap& map,
     ObserverList* list,
     PassRefPtr<WebTaskRunner> task_runner) {
-  DCHECK(task_runner->RunsTasksOnCurrentThread());
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
   DCHECK(!list->iterating);
 
   // If any observers were removed during the iteration they will have
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
index faab2f9..d21cd7b0 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -63,7 +63,7 @@
 
   // TaskQueueManagerDelegateForTest:
   bool IsNested() const override {
-    DCHECK(RunsTasksOnCurrentThread());
+    DCHECK(RunsTasksInCurrentSequence());
     return base::RunLoop::IsNestedOnCurrentThread();
   }
 
@@ -1021,9 +1021,9 @@
 
 TEST_F(TaskQueueManagerTest, ThreadCheckAfterTermination) {
   Initialize(1u);
-  EXPECT_TRUE(runners_[0]->RunsTasksOnCurrentThread());
+  EXPECT_TRUE(runners_[0]->RunsTasksInCurrentSequence());
   manager_.reset();
-  EXPECT_TRUE(runners_[0]->RunsTasksOnCurrentThread());
+  EXPECT_TRUE(runners_[0]->RunsTasksInCurrentSequence());
 }
 
 TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime) {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_tqm_delegate_impl.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_tqm_delegate_impl.cc
index 442d43273..4f491b4 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_tqm_delegate_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_tqm_delegate_impl.cc
@@ -61,7 +61,7 @@
 }
 
 bool SchedulerTqmDelegateImpl::IsNested() const {
-  DCHECK(RunsTasksOnCurrentThread());
+  DCHECK(RunsTasksInCurrentSequence());
   return base::RunLoop::IsNestedOnCurrentThread();
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
index bb68098..26c98e0 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
@@ -186,7 +186,7 @@
 void TaskQueueThrottler::OnQueueNextWakeUpChanged(
     TaskQueue* queue,
     base::TimeTicks next_wake_up) {
-  if (!control_task_queue_->RunsTasksOnCurrentThread()) {
+  if (!control_task_queue_->RunsTasksInCurrentSequence()) {
     control_task_queue_->PostTask(
         FROM_HERE,
         base::Bind(forward_immediate_work_callback_, queue, next_wake_up));
diff --git a/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc b/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
index a193e52..45799646bc 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
+++ b/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
@@ -91,7 +91,7 @@
 }
 
 bool LazySchedulerMessageLoopDelegateForTests::IsNested() const {
-  DCHECK(RunsTasksOnCurrentThread());
+  DCHECK(RunsTasksInCurrentSequence());
   EnsureMessageLoop();
   return base::RunLoop::IsNestedOnCurrentThread();
 }
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index a576e36f..6f09c91 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -46,8 +46,6 @@
     "WebExport.h",
     "WebFactoryImpl.cpp",
     "WebFactoryImpl.h",
-    "WebFormElementObserverImpl.cpp",
-    "WebFormElementObserverImpl.h",
     "WebFrameWidgetImpl.cpp",
     "WebFrameWidgetImpl.h",
     "WebKit.cpp",
@@ -93,7 +91,6 @@
     "tests/FakeWebPlugin.cpp",
     "tests/FakeWebPlugin.h",
     "tests/HTMLImportSheetsTest.cpp",
-    "tests/ImeOnFocusTest.cpp",
     "tests/LayoutGeometryMapTest.cpp",
     "tests/LinkElementLoadingTest.cpp",
     "tests/ListenerLeakTest.cpp",
@@ -103,7 +100,6 @@
     "tests/NGInlineLayoutTest.cpp",
     "tests/PrerenderingTest.cpp",
     "tests/ProgrammaticScrollTest.cpp",
-    "tests/RootScrollerTest.cpp",
     "tests/RunAllTests.cpp",
     "tests/ScreenWakeLockTest.cpp",
     "tests/ScrollMetricsTest.cpp",
@@ -112,8 +108,6 @@
     "tests/SpinLockTest.cpp",
     "tests/TextSelectionRepaintTest.cpp",
     "tests/TimerPerfTest.cpp",
-    "tests/TouchActionTest.cpp",
-    "tests/ViewportTest.cpp",
     "tests/VirtualTimeTest.cpp",
     "tests/WebDocumentSubresourceFilterTest.cpp",
     "tests/WebFrameSerializerSanitizationTest.cpp",
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index 6bcb195c..b06a678 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -367,6 +367,15 @@
 };
 
 /**
+ * @typedef {{
+ *   id: number,
+ *   description: string
+ * }}
+ * @see https://developer.chrome.com/extensions/automation#type-CustomAction
+ */
+chrome.automation.CustomAction;
+
+/**
  * @constructor
  * @private
  * @see https://developer.chrome.com/extensions/automation#type-AutomationNode
@@ -532,6 +541,13 @@
 chrome.automation.AutomationNode.prototype.inPageLinkTarget;
 
 /**
+ * An array of custom actions.
+ * @type {(!Array<!chrome.automation.CustomAction>|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-customActions
+ */
+chrome.automation.AutomationNode.prototype.customActions;
+
+/**
  * The URL that this link will navigate to.
  * @type {(string|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-url
@@ -1077,6 +1093,13 @@
 chrome.automation.AutomationNode.prototype.makeVisible = function() {};
 
 /**
+ * Performs custom action.
+ * @param {number} customActionId
+ * @see https://developer.chrome.com/extensions/automation#method-performCustomAction
+ */
+chrome.automation.AutomationNode.prototype.performCustomAction = function(customActionId) {};
+
+/**
  * Sets selection within a text field.
  * @param {number} startIndex
  * @param {number} endIndex
diff --git a/ui/accessibility/ax_action_data.cc b/ui/accessibility/ax_action_data.cc
index b65fd2d..7769b27 100644
--- a/ui/accessibility/ax_action_data.cc
+++ b/ui/accessibility/ax_action_data.cc
@@ -23,6 +23,7 @@
       anchor_offset(-1),
       focus_node_id(-1),
       focus_offset(-1),
+      custom_action_id(-1),
       hit_test_event_to_fire(AX_EVENT_NONE) {}
 
 AXActionData::AXActionData(const AXActionData& other) = default;
diff --git a/ui/accessibility/ax_action_data.h b/ui/accessibility/ax_action_data.h
index cc6e856..a80f4a5 100644
--- a/ui/accessibility/ax_action_data.h
+++ b/ui/accessibility/ax_action_data.h
@@ -45,6 +45,9 @@
   int focus_node_id;
   int focus_offset;
 
+  // For custom action.
+  int custom_action_id;
+
   // The target rect for the action.
   gfx::Rect target_rect;
 
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl
index 8320bd7..0dfdc5e2 100644
--- a/ui/accessibility/ax_enums.idl
+++ b/ui/accessibility/ax_enums.idl
@@ -246,6 +246,8 @@
   enum AXAction {
     blur,
 
+    custom_action,
+
     // Decrement a slider or range control by one step value.
     decrement,
 
@@ -529,7 +531,19 @@
     // For inline text. These int lists must be the same size; they represent
     // the start and end character offset of each word within this text.
     word_starts,
-    word_ends
+    word_ends,
+
+    // Used for an UI element to define custom actions for it. For example, a
+    // list UI will allow a user to reorder items in the list by dragging the
+    // items. Developer can expose those actions as custom actions. Currently
+    // custom actions are used only in Android window.
+    custom_action_ids
+  };
+
+  [cpp_enum_prefix_override="ax_attr"] enum AXStringListAttribute {
+    // Descriptions for custom actions. This must be aligned with
+    // custom_action_ids.
+    custom_action_descriptions
   };
 
   // TODO(dmazzoni, nektar): make this list not grow exponentially as new
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index 35955d2..eedfdd9 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -62,6 +62,16 @@
   return str;
 }
 
+std::string StringVectorToString(const std::vector<std::string>& items) {
+  std::string str;
+  for (size_t i = 0; i < items.size(); ++i) {
+    if (i > 0)
+      str += ",";
+    str += items[i];
+  }
+  return str;
+}
+
 // Predicate that returns true if the first value of a pair is |first|.
 template<typename FirstType, typename SecondType>
 struct FirstIs {
@@ -178,6 +188,7 @@
     case AX_ATTR_CACHED_LINE_STARTS:
     case AX_ATTR_WORD_STARTS:
     case AX_ATTR_WORD_ENDS:
+    case AX_ATTR_CUSTOM_ACTION_IDS:
       return false;
   }
 
@@ -205,6 +216,7 @@
   float_attributes = other.float_attributes;
   bool_attributes = other.bool_attributes;
   intlist_attributes = other.intlist_attributes;
+  stringlist_attributes = other.stringlist_attributes;
   html_attributes = other.html_attributes;
   child_ids = other.child_ids;
   location = other.location;
@@ -223,6 +235,7 @@
   float_attributes = other.float_attributes;
   bool_attributes = other.bool_attributes;
   intlist_attributes = other.intlist_attributes;
+  stringlist_attributes = other.stringlist_attributes;
   html_attributes = other.html_attributes;
   child_ids = other.child_ids;
   location = other.location;
@@ -369,6 +382,31 @@
   return false;
 }
 
+bool AXNodeData::HasStringListAttribute(AXStringListAttribute attribute) const {
+  auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
+  return iter != stringlist_attributes.end();
+}
+
+const std::vector<std::string>& AXNodeData::GetStringListAttribute(
+    AXStringListAttribute attribute) const {
+  CR_DEFINE_STATIC_LOCAL(std::vector<std::string>, empty_vector, ());
+  auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
+  if (iter != stringlist_attributes.end())
+    return iter->second;
+  return empty_vector;
+}
+
+bool AXNodeData::GetStringListAttribute(AXStringListAttribute attribute,
+                                        std::vector<std::string>* value) const {
+  auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
+  if (iter != stringlist_attributes.end()) {
+    *value = iter->second;
+    return true;
+  }
+
+  return false;
+}
+
 bool AXNodeData::GetHtmlAttribute(
     const char* html_attr, std::string* value) const {
   for (size_t i = 0; i < html_attributes.size(); ++i) {
@@ -416,6 +454,11 @@
   intlist_attributes.push_back(std::make_pair(attribute, value));
 }
 
+void AXNodeData::AddStringListAttribute(AXStringListAttribute attribute,
+                                        const std::vector<std::string>& value) {
+  stringlist_attributes.push_back(std::make_pair(attribute, value));
+}
+
 void AXNodeData::SetName(const std::string& name) {
   for (size_t i = 0; i < string_attributes.size(); ++i) {
     if (string_attributes[i].first == AX_ATTR_NAME) {
@@ -475,6 +518,7 @@
           (action_enum == AX_ACTION_BLUR) ? AX_ACTION_FOCUS : AX_ACTION_BLUR;
       DCHECK(HasAction(excluded_action));
     } break;
+    case AX_ACTION_CUSTOM_ACTION:
     case AX_ACTION_DECREMENT:
     case AX_ACTION_DO_DEFAULT:
     case AX_ACTION_GET_IMAGE_DATA:
@@ -958,11 +1002,26 @@
       case AX_ATTR_WORD_ENDS:
         result += " word_ends=" + IntVectorToString(values);
         break;
+      case AX_ATTR_CUSTOM_ACTION_IDS:
+        result += " custom_action_ids=" + IntVectorToString(values);
+        break;
       case AX_INT_LIST_ATTRIBUTE_NONE:
         break;
     }
   }
 
+  for (size_t i = 0; i < stringlist_attributes.size(); ++i) {
+    const std::vector<std::string>& values = stringlist_attributes[i].second;
+    switch (stringlist_attributes[i].first) {
+      case AX_ATTR_CUSTOM_ACTION_DESCRIPTIONS:
+        result +=
+            " custom_action_descriptions: " + StringVectorToString(values);
+        break;
+      case AX_STRING_LIST_ATTRIBUTE_NONE:
+        break;
+    }
+  }
+
   result += " actions=" + ActionsBitfieldToString(actions);
 
   if (!child_ids.empty())
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h
index 8d64ef5..29e7998 100644
--- a/ui/accessibility/ax_node_data.h
+++ b/ui/accessibility/ax_node_data.h
@@ -86,6 +86,12 @@
   bool GetIntListAttribute(AXIntListAttribute attribute,
                            std::vector<int32_t>* value) const;
 
+  bool HasStringListAttribute(AXStringListAttribute attribute) const;
+  const std::vector<std::string>& GetStringListAttribute(
+      AXStringListAttribute attribute) const;
+  bool GetStringListAttribute(AXStringListAttribute attribute,
+                              std::vector<std::string>* value) const;
+
   bool GetHtmlAttribute(const char* attr, base::string16* value) const;
   bool GetHtmlAttribute(const char* attr, std::string* value) const;
 
@@ -97,6 +103,8 @@
   void AddBoolAttribute(AXBoolAttribute attribute, bool value);
   void AddIntListAttribute(AXIntListAttribute attribute,
                            const std::vector<int32_t>& value);
+  void AddStringListAttribute(AXStringListAttribute attribute,
+                              const std::vector<std::string>& value);
 
   // Convenience functions, mainly for writing unit tests.
   // Equivalent to AddStringAttribute(ATTR_NAME, name).
@@ -129,6 +137,8 @@
   std::vector<std::pair<AXBoolAttribute, bool>> bool_attributes;
   std::vector<std::pair<AXIntListAttribute, std::vector<int32_t>>>
       intlist_attributes;
+  std::vector<std::pair<AXStringListAttribute, std::vector<std::string>>>
+      stringlist_attributes;
   base::StringPairs html_attributes;
   std::vector<int32_t> child_ids;
 
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 43e635a..a77b221 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -466,6 +466,17 @@
   CallIfAttributeValuesChanged(old_data.intlist_attributes,
                                new_data.intlist_attributes,
                                std::vector<int32_t>(), intlist_callback);
+
+  auto stringlist_callback =
+      [this, node](AXStringListAttribute attr,
+                   const std::vector<std::string>& old_stringlist,
+                   const std::vector<std::string>& new_stringlist) {
+        delegate_->OnStringListAttributeChanged(this, node, attr,
+                                                old_stringlist, new_stringlist);
+      };
+  CallIfAttributeValuesChanged(old_data.stringlist_attributes,
+                               new_data.stringlist_attributes,
+                               std::vector<std::string>(), stringlist_callback);
 }
 
 void AXTree::DestroySubtree(AXNode* node,
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index 36fe655..95885de 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -83,6 +83,12 @@
       AXIntListAttribute attr,
       const std::vector<int32_t>& old_value,
       const std::vector<int32_t>& new_value) {}
+  virtual void OnStringListAttributeChanged(
+      AXTree* tree,
+      AXNode* node,
+      AXStringListAttribute attr,
+      const std::vector<std::string>& old_value,
+      const std::vector<std::string>& new_value) {}
 
   // Called when tree data changes.
   virtual void OnTreeDataChanged(AXTree* tree,