diff --git a/DEPS b/DEPS
index 97b9f99c..0e332e2a 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '1a74c531058ceecd10703da26b4729f4427d1f33',
+  'skia_revision': 'ce6b4b004b2842e61cd9f86ebb75d1872044b382',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
index 8907b3c7..5b07983 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
@@ -7,6 +7,9 @@
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
 
+import org.junit.Assert;
+
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
@@ -29,6 +32,8 @@
     private static final double LONGITUDE = 0.23;
     private static final float ACCURACY = 10;
     private static final String TEST_FILE = "/content/test/data/android/geolocation.html";
+    private static final String PERSIST_ACCEPT_HISTOGRAM =
+            "Permissions.Prompt.Accepted.Persisted.Geolocation";
 
     public GeolocationTest() {}
 
@@ -47,6 +52,12 @@
         runAllowTest(updateWaiter, TEST_FILE, javascript, nUpdates, withGesture, isDialog,
                 hasSwitch, toggleSwitch);
         tab.removeObserver(updateWaiter);
+        if (hasSwitch) {
+            int bucket = toggleSwitch ? 0 : 1;
+            Assert.assertEquals(1,
+                    RecordHistogram.getHistogramValueCountForTesting(
+                            PERSIST_ACCEPT_HISTOGRAM, bucket));
+        }
     }
 
     /**
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index b64fd81ee..c4e6a15 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -296,6 +296,8 @@
             <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_JS" file="resources\md_bookmarks\store_client.js" type="BINDATA" />
             <include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\md_bookmarks\store.html" type="BINDATA" />
             <include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\store.js" type="BINDATA" />
+            <include name="IDR_MD_BOOKMARKS_TIMER_PROXY_HTML" file="resources\md_bookmarks\timer_proxy.html" type="BINDATA" />
+            <include name="IDR_MD_BOOKMARKS_TIMER_PROXY_JS" file="resources\md_bookmarks\timer_proxy.js" type="BINDATA" />
             <include name="IDR_MD_BOOKMARKS_TOAST_MANAGER_HTML" file="resources\md_bookmarks\toast_manager.html" type="BINDATA" />
             <include name="IDR_MD_BOOKMARKS_TOAST_MANAGER_JS" file="resources\md_bookmarks\toast_manager.js" type="BINDATA" />
             <include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\md_bookmarks\toolbar.html" type="BINDATA" />
diff --git a/chrome/browser/permissions/permission_prompt_android.cc b/chrome/browser/permissions/permission_prompt_android.cc
index 9893147..b7c8440 100644
--- a/chrome/browser/permissions/permission_prompt_android.cc
+++ b/chrome/browser/permissions/permission_prompt_android.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/permissions/grouped_permission_infobar_delegate_android.h"
 #include "chrome/browser/permissions/permission_dialog_delegate.h"
 #include "chrome/browser/permissions/permission_request.h"
+#include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -18,7 +19,7 @@
 
 PermissionPromptAndroid::PermissionPromptAndroid(
     content::WebContents* web_contents)
-    : web_contents_(web_contents), delegate_(nullptr) {
+    : web_contents_(web_contents), delegate_(nullptr), persist_(true) {
   DCHECK(web_contents);
 }
 
@@ -77,18 +78,33 @@
 }
 
 void PermissionPromptAndroid::TogglePersist(bool value) {
+  persist_ = value;
   if (delegate_)
     delegate_->TogglePersist(value);
 }
 
 void PermissionPromptAndroid::Accept() {
-  if (delegate_)
+  if (delegate_) {
+    if (ShouldShowPersistenceToggle()) {
+      for (const PermissionRequest* request : delegate_->Requests()) {
+        PermissionUmaUtil::PermissionPromptAcceptedWithPersistenceToggle(
+            request->GetContentSettingsType(), persist_);
+      }
+    }
     delegate_->Accept();
+  }
 }
 
 void PermissionPromptAndroid::Deny() {
-  if (delegate_)
+  if (delegate_) {
+    if (ShouldShowPersistenceToggle()) {
+      for (const PermissionRequest* request : delegate_->Requests()) {
+        PermissionUmaUtil::PermissionPromptDeniedWithPersistenceToggle(
+            request->GetContentSettingsType(), persist_);
+      }
+    }
     delegate_->Deny();
+  }
 }
 
 size_t PermissionPromptAndroid::PermissionCount() const {
diff --git a/chrome/browser/permissions/permission_prompt_android.h b/chrome/browser/permissions/permission_prompt_android.h
index 7e164f88..80eda10 100644
--- a/chrome/browser/permissions/permission_prompt_android.h
+++ b/chrome/browser/permissions/permission_prompt_android.h
@@ -54,6 +54,8 @@
   // |delegate_| is the PermissionRequestManager, which owns this object.
   Delegate* delegate_;
 
+  bool persist_;
+
   DISALLOW_COPY_AND_ASSIGN(PermissionPromptAndroid);
 };
 
diff --git a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
index 6f9e4eaf..7b9ed535 100644
--- a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
+++ b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
@@ -63,6 +63,7 @@
         '<(EXTERNS_GYP):bookmark_manager_private',
         '<(EXTERNS_GYP):metrics_private',
         'store',
+        'timer_proxy',
         'types',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
@@ -157,11 +158,19 @@
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
     },
     {
+      'target_name': 'timer_proxy',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+      ],
+      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'toast_manager',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
         '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted',
+        'timer_proxy',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/chrome/browser/resources/md_bookmarks/dnd_manager.html b/chrome/browser/resources/md_bookmarks/dnd_manager.html
index 0a87bf0..a41e2cb 100644
--- a/chrome/browser/resources/md_bookmarks/dnd_manager.html
+++ b/chrome/browser/resources/md_bookmarks/dnd_manager.html
@@ -1,2 +1,3 @@
 <link rel="import" href="chrome://bookmarks/constants.html">
+<link rel="import" href="chrome://bookmarks/timer_proxy.html">
 <script src="chrome://bookmarks/dnd_manager.js"></script>
diff --git a/chrome/browser/resources/md_bookmarks/dnd_manager.js b/chrome/browser/resources/md_bookmarks/dnd_manager.js
index 71b1bcd..309bd95 100644
--- a/chrome/browser/resources/md_bookmarks/dnd_manager.js
+++ b/chrome/browser/resources/md_bookmarks/dnd_manager.js
@@ -186,7 +186,7 @@
     /**
      * @private {number|null} Timer id used to help minimize flicker.
      */
-    this.removeDropIndicatorTimer_ = null;
+    this.removeDropIndicatorTimeoutId_ = null;
 
     /**
      * The element that had a style applied it to indicate the drop location.
@@ -203,9 +203,9 @@
 
     /**
      * Used to instantly remove the indicator style in tests.
-     * @private {function((Function|null|string), number)}
+     * @private {bookmarks.TimerProxy}
      */
-    this.setTimeout = window.setTimeout.bind(window);
+    this.timerProxy = new bookmarks.TimerProxy();
   }
 
   DropIndicator.prototype = {
@@ -244,7 +244,7 @@
      * @param {DropDestination} dropDest
      */
     update: function(dropDest) {
-      window.clearTimeout(this.removeDropIndicatorTimer_);
+      this.timerProxy.clearTimeout(this.removeDropIndicatorTimeoutId_);
 
       var indicatorElement = dropDest.element.getDropTarget();
       var position = dropDest.position;
@@ -259,10 +259,11 @@
     finish: function() {
       // The use of a timeout is in order to reduce flickering as we move
       // between valid drop targets.
-      window.clearTimeout(this.removeDropIndicatorTimer_);
-      this.removeDropIndicatorTimer_ = this.setTimeout(function() {
-        this.removeDropIndicatorStyle();
-      }.bind(this), 100);
+      this.timerProxy.clearTimeout(this.removeDropIndicatorTimeoutId_);
+      this.removeDropIndicatorTimeoutId_ =
+          this.timerProxy.setTimeout(function() {
+            this.removeDropIndicatorStyle();
+          }.bind(this), 100);
     },
   };
 
@@ -285,9 +286,9 @@
 
     /**
      * Used to instantly clearDragData in tests.
-     * @private {function((Function|null|string), number)}
+     * @private {bookmarks.TimerProxy}
      */
-    this.setTimeout_ = window.setTimeout.bind(window);
+    this.timerProxy_ = new bookmarks.TimerProxy();
   }
 
   DNDManager.prototype = {
@@ -386,7 +387,7 @@
       // Defer the clearing of the data so that the bookmark manager API's drop
       // event doesn't clear the drop data before the web drop event has a
       // chance to execute (on Mac).
-      this.setTimeout_(function() {
+      this.timerProxy_.setTimeout(function() {
         this.dragInfo_.clearDragData();
         this.dropDestination_ = null;
         this.dropIndicator_.finish();
@@ -638,11 +639,10 @@
       return !this.dragInfo_.isDraggingChildBookmark(overElement.itemId);
     },
 
-    disableTimeoutsForTesting: function() {
-      this.setTimeout_ = function(fn) {
-        fn();
-      };
-      this.dropIndicator_.setTimeout = this.setTimeout_;
+    /** @param {bookmarks.TimerProxy} timerProxy */
+    setTimerProxyForTesting: function(timerProxy) {
+      this.timerProxy_ = timerProxy;
+      this.dropIndicator_.timerProxy = timerProxy;
     }
   };
 
diff --git a/chrome/browser/resources/md_bookmarks/timer_proxy.html b/chrome/browser/resources/md_bookmarks/timer_proxy.html
new file mode 100644
index 0000000..d70600a
--- /dev/null
+++ b/chrome/browser/resources/md_bookmarks/timer_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://bookmarks/timer_proxy.js"></script>
diff --git a/chrome/browser/resources/md_bookmarks/timer_proxy.js b/chrome/browser/resources/md_bookmarks/timer_proxy.js
new file mode 100644
index 0000000..de96c7fd
--- /dev/null
+++ b/chrome/browser/resources/md_bookmarks/timer_proxy.js
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A class that mediates window timer calls to support mockability
+ * in tests.
+ */
+
+cr.define('bookmarks', function() {
+  /** @constructor */
+  function TimerProxy() {}
+
+  TimerProxy.prototype = {
+    /**
+     * @param {Function|string} fn
+     * @param {number=} delay
+     * @return {number}
+     */
+    setTimeout: function(fn, delay) {
+      return window.setTimeout(fn, delay);
+    },
+
+    /** @param {number|undefined?} id */
+    clearTimeout: function(id) {
+      window.clearTimeout(id);
+    },
+  };
+
+  return {
+    TimerProxy: TimerProxy,
+  };
+});
diff --git a/chrome/browser/resources/md_bookmarks/toast_manager.js b/chrome/browser/resources/md_bookmarks/toast_manager.js
index c0e72fc..642ce382 100644
--- a/chrome/browser/resources/md_bookmarks/toast_manager.js
+++ b/chrome/browser/resources/md_bookmarks/toast_manager.js
@@ -26,14 +26,11 @@
       showUndo_: Boolean,
     },
 
-    /** @private {function(number)} */
-    clearTimeout_: window.clearTimeout.bind(window),
-
-    /** @private {function((Function|null|string), number)} */
-    setTimeout_: window.setTimeout.bind(window),
+    /** @private {bookmarks.TimerProxy} */
+    timerProxy_: new bookmarks.TimerProxy(),
 
     /** @private {number|null} */
-    hideTimeout_: null,
+    hideTimeoutId_: null,
 
     /** @override */
     attached: function() {
@@ -89,14 +86,12 @@
       if (!this.duration)
         return;
 
-      if (this.hideTimeout_ != null) {
-        this.clearTimeout_(this.hideTimeout_);
-        this.hideTimeout_ = null;
-      }
+      if (this.hideTimeoutId_ != null)
+        this.timerProxy_.clearTimeout(this.hideTimeoutId_);
 
-      this.hideTimeout_ = this.setTimeout_(function() {
+      this.hideTimeoutId_ = this.timerProxy_.setTimeout(function() {
         this.open_ = false;
-        this.hideTimeout_ = null;
+        this.hideTimeoutId_ = null;
       }.bind(this), this.duration);
     },
 
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
index e7fc1ac..50751bc 100644
--- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
+++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -144,6 +144,9 @@
   source->AddResourcePath("store_client.html",
                           IDR_MD_BOOKMARKS_STORE_CLIENT_HTML);
   source->AddResourcePath("store_client.js", IDR_MD_BOOKMARKS_STORE_CLIENT_JS);
+  source->AddResourcePath("timer_proxy.html",
+                          IDR_MD_BOOKMARKS_TIMER_PROXY_HTML);
+  source->AddResourcePath("timer_proxy.js", IDR_MD_BOOKMARKS_TIMER_PROXY_JS);
   source->AddResourcePath("toast_manager.html",
                           IDR_MD_BOOKMARKS_TOAST_MANAGER_HTML);
   source->AddResourcePath("toast_manager.js",
diff --git a/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js b/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js
index 02cfeac..2c71a90 100644
--- a/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js
+++ b/chrome/test/data/webui/md_bookmarks/dnd_manager_test.js
@@ -101,7 +101,7 @@
     list = app.$$('bookmarks-list');
     rootFolderNode = app.$$('bookmarks-folder-node');
     dndManager = app.dndManager_;
-    dndManager.disableTimeoutsForTesting();
+    dndManager.setTimerProxyForTesting(new bookmarks.TestTimerProxy());
     Polymer.dom.flush();
   });
 
diff --git a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
index c8d7eab..06c33b8 100644
--- a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
+++ b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
@@ -28,6 +28,7 @@
   extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
     'test_command_manager.js',
     'test_store.js',
+    'test_timer_proxy.js',
     'test_util.js',
   ]),
 };
diff --git a/chrome/test/data/webui/md_bookmarks/test_store.js b/chrome/test/data/webui/md_bookmarks/test_store.js
index 57f5505..f9c705d8 100644
--- a/chrome/test/data/webui/md_bookmarks/test_store.js
+++ b/chrome/test/data/webui/md_bookmarks/test_store.js
@@ -19,6 +19,7 @@
     TestStore.prototype = {
       __proto__: bookmarks.Store.prototype,
 
+      /** @override */
       init: function(state) {
         if (this.acceptInit_)
           bookmarks.Store.prototype.init.call(this, state);
@@ -57,6 +58,7 @@
         this.enableReducers_ = enabled;
       },
 
+      /** @override */
       reduce_: function(action) {
         this.lastAction_ = action;
         if (this.enableReducers_)
diff --git a/chrome/test/data/webui/md_bookmarks/test_timer_proxy.js b/chrome/test/data/webui/md_bookmarks/test_timer_proxy.js
new file mode 100644
index 0000000..b165726
--- /dev/null
+++ b/chrome/test/data/webui/md_bookmarks/test_timer_proxy.js
@@ -0,0 +1,69 @@
+// 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.
+
+suiteSetup(function() {
+  cr.define('bookmarks', function() {
+    var TestTimerProxy = function(data) {
+      bookmarks.TimerProxy.call(this);
+
+      this.immediatelyResolveTimeouts = true;
+
+      /** @private */
+      this.timeoutIds_ = 0;
+
+      /** @private {!Map<number, !Function>} */
+      this.activeTimeouts_ = new Map();
+    };
+
+    TestTimerProxy.prototype = {
+      __proto__: bookmarks.TimerProxy.prototype,
+
+      /**
+       * @param {Function|string} fn
+       * @param {number=} delay
+       * @return {number}
+       * @override
+       */
+      setTimeout: function(fn, delay) {
+        if (this.immediatelyResolveTimeouts)
+          fn();
+        else
+          this.activeTimeouts_[this.timeoutIds_] = fn;
+
+        return this.timeoutIds_++;
+      },
+
+      /**
+       * @param {number|undefined?} id
+       * @override
+       */
+      clearTimeout: function(id) {
+        this.activeTimeouts_.delete(id);
+      },
+
+      /**
+       * Run the function associated with a timeout id and clear it from the
+       * active timeouts.
+       * @param {number} id
+       */
+      runTimeoutFn: function(id) {
+        this.activeTimeouts_[id]();
+        this.clearTimeout(id);
+      },
+
+      /**
+       * Returns true if a given timeout id has not been run or cleared.
+       * @param {number} id
+       * @return {boolean}
+       */
+      hasTimeout: function(id) {
+        return this.activeTimeouts_.has(id);
+      },
+    };
+
+    return {
+      TestTimerProxy: TestTimerProxy,
+    };
+  });
+});
diff --git a/chrome/test/data/webui/md_bookmarks/toast_manager_test.js b/chrome/test/data/webui/md_bookmarks/toast_manager_test.js
index 8830c8b2..24ba421 100644
--- a/chrome/test/data/webui/md_bookmarks/toast_manager_test.js
+++ b/chrome/test/data/webui/md_bookmarks/toast_manager_test.js
@@ -25,35 +25,28 @@
   });
 
   test('auto hide', function() {
+    var timerProxy = new bookmarks.TestTimerProxy();
+    timerProxy.immediatelyResolveTimeouts = false;
+    toastManager.timerProxy_ = timerProxy;
+
     toastManager.duration = 100;
 
-    var timeoutFunc = null;
-    var timeoutCounter = 0;
-    var clearedTimeout = null;
-    toastManager.setTimeout_ = function(f) {
-      timeoutFunc = f;
-      return timeoutCounter++;
-    };
-    toastManager.clearTimeout_ = function(n) {
-      clearedTimeout = n;
-    };
-
     toastManager.show('test', false);
-    assertEquals(0, toastManager.hideTimeout_);
+    assertEquals(0, toastManager.hideTimeoutId_);
     assertTrue(toastManager.open_);
 
-    timeoutFunc();
-    assertEquals(null, toastManager.hideTimeout_);
+    timerProxy.runTimeoutFn(0);
+    assertEquals(null, toastManager.hideTimeoutId_);
     assertFalse(toastManager.open_);
 
     // Check that multiple shows reset the timeout.
     toastManager.show('test', false);
-    assertEquals(1, toastManager.hideTimeout_);
+    assertEquals(1, toastManager.hideTimeoutId_);
     assertTrue(toastManager.open_);
 
     toastManager.show('test2', false);
-    assertEquals(1, clearedTimeout);
-    assertEquals(2, toastManager.hideTimeout_);
+    assertFalse(timerProxy.hasTimeout(1));
+    assertEquals(2, toastManager.hideTimeoutId_);
     assertTrue(toastManager.open_);
   });
 });
diff --git a/content/child/url_loader_client_impl.cc b/content/child/url_loader_client_impl.cc
index e49889b3..ffb36011 100644
--- a/content/child/url_loader_client_impl.cc
+++ b/content/child/url_loader_client_impl.cc
@@ -164,8 +164,13 @@
   DCHECK(has_received_response_);
   body_consumer_ = new URLResponseBodyConsumer(
       request_id_, resource_dispatcher_, std::move(body), task_runner_);
-  if (is_deferred_)
+
+  if (is_deferred_) {
     body_consumer_->SetDefersLoading();
+    return;
+  }
+
+  body_consumer_->OnReadable(MOJO_RESULT_OK);
 }
 
 void URLLoaderClientImpl::OnComplete(
diff --git a/content/child/url_response_body_consumer.cc b/content/child/url_response_body_consumer.cc
index 48f1153..bce3d4e4 100644
--- a/content/child/url_response_body_consumer.cc
+++ b/content/child/url_response_body_consumer.cc
@@ -56,7 +56,6 @@
   handle_watcher_.Watch(
       handle_.get(), MOJO_HANDLE_SIGNAL_READABLE,
       base::Bind(&URLResponseBodyConsumer::OnReadable, base::Unretained(this)));
-  handle_watcher_.ArmOrNotify();
 }
 
 URLResponseBodyConsumer::~URLResponseBodyConsumer() {}
@@ -84,6 +83,12 @@
   OnReadable(MOJO_RESULT_OK);
 }
 
+void URLResponseBodyConsumer::ArmOrNotify() {
+  if (has_been_cancelled_)
+    return;
+  handle_watcher_.ArmOrNotify();
+}
+
 void URLResponseBodyConsumer::Reclaim(uint32_t size) {
   MojoResult result = mojo::EndReadDataRaw(handle_.get(), size);
   DCHECK_EQ(MOJO_RESULT_OK, result);
diff --git a/content/child/url_response_body_consumer.h b/content/child/url_response_body_consumer.h
index ce6b88a9..efa55dc 100644
--- a/content/child/url_response_body_consumer.h
+++ b/content/child/url_response_body_consumer.h
@@ -51,6 +51,11 @@
   void SetDefersLoading();
   void UnsetDefersLoading();
 
+  // Reads data and dispatches messages synchronously.
+  void OnReadable(MojoResult unused);
+
+  void ArmOrNotify();
+
   // The maximal number of bytes consumed in a task. When there are more bytes
   // in the data pipe, they will be consumed in following tasks. Setting a too
   // small number will generate ton of tasks but setting a too large number will
@@ -65,7 +70,6 @@
   class ReceivedData;
   void Reclaim(uint32_t size);
 
-  void OnReadable(MojoResult unused);
   void NotifyCompletionIfAppropriate();
 
   const int request_id_;
diff --git a/content/child/url_response_body_consumer_unittest.cc b/content/child/url_response_body_consumer_unittest.cc
index be64d79..c57d690 100644
--- a/content/child/url_response_body_consumer_unittest.cc
+++ b/content/child/url_response_body_consumer_unittest.cc
@@ -165,6 +165,7 @@
   scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
       request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
       message_loop_.task_runner()));
+  consumer->ArmOrNotify();
 
   mojo::ScopedDataPipeProducerHandle writer =
       std::move(data_pipe.producer_handle);
@@ -190,6 +191,7 @@
   scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
       request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
       message_loop_.task_runner()));
+  consumer->ArmOrNotify();
 
   consumer->OnComplete(ResourceRequestCompletionStatus());
   mojo::ScopedDataPipeProducerHandle writer =
@@ -225,6 +227,7 @@
   scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
       request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
       message_loop_.task_runner()));
+  consumer->ArmOrNotify();
 
   consumer->OnComplete(ResourceRequestCompletionStatus());
   mojo::ScopedDataPipeProducerHandle writer =
@@ -257,6 +260,7 @@
   scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
       request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
       message_loop_.task_runner()));
+  consumer->ArmOrNotify();
 
   ResourceRequestCompletionStatus status;
   status.error_code = net::ERR_FAILED;
@@ -300,6 +304,7 @@
   scoped_refptr<URLResponseBodyConsumer> consumer(new URLResponseBodyConsumer(
       request_id, dispatcher_.get(), std::move(data_pipe.consumer_handle),
       message_loop_.task_runner()));
+  consumer->ArmOrNotify();
 
   Run(&context);
   EXPECT_EQ(std::string(kMaxNumConsumedBytesInTask, 'a'), context.data);
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 5966d18..d2f27ddc 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1000,6 +1000,8 @@
       "nqe/network_quality_estimator.h",
       "nqe/network_quality_estimator_params.cc",
       "nqe/network_quality_estimator_params.h",
+      "nqe/network_quality_estimator_util.cc",
+      "nqe/network_quality_estimator_util.h",
       "nqe/network_quality_observation.h",
       "nqe/network_quality_observation_source.h",
       "nqe/network_quality_provider.cc",
@@ -4781,6 +4783,7 @@
     "nqe/network_qualities_prefs_manager_unittest.cc",
     "nqe/network_quality_estimator_params_unittest.cc",
     "nqe/network_quality_estimator_unittest.cc",
+    "nqe/network_quality_estimator_util_unittest.cc",
     "nqe/network_quality_store_unittest.cc",
     "nqe/observation_buffer_unittest.cc",
     "nqe/socket_watcher_unittest.cc",
diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc
index 608f16d..c6516349 100644
--- a/net/base/mime_util_unittest.cc
+++ b/net/base/mime_util_unittest.cc
@@ -4,8 +4,7 @@
 
 #include "net/base/mime_util.h"
 
-#include <algorithm>
-
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -273,8 +272,7 @@
           test.contained_result,
           test.contained_result + strlen(test.contained_result));
 
-      bool found = std::find(extensions.begin(), extensions.end(),
-                             contained_result) != extensions.end();
+      bool found = base::ContainsValue(extensions, contained_result);
 
       ASSERT_TRUE(found) << "Must find at least the contained result within "
                          << test.mime_type;
diff --git a/net/base/network_throttle_manager_impl.cc b/net/base/network_throttle_manager_impl.cc
index eda6fea..4ca235a 100644
--- a/net/base/network_throttle_manager_impl.cc
+++ b/net/base/network_throttle_manager_impl.cc
@@ -4,9 +4,8 @@
 
 #include "net/base/network_throttle_manager_impl.h"
 
-#include <algorithm>
-
 #include "base/logging.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_tick_clock.h"
 
@@ -241,10 +240,8 @@
       break;
   }
 
-  DCHECK(std::find(blocked_throttles_.begin(), blocked_throttles_.end(),
-                   throttle) == blocked_throttles_.end());
-  DCHECK(std::find(outstanding_throttles_.begin(), outstanding_throttles_.end(),
-                   throttle) == outstanding_throttles_.end());
+  DCHECK(!base::ContainsValue(blocked_throttles_, throttle));
+  DCHECK(!base::ContainsValue(outstanding_throttles_, throttle));
 
   // Unblock the throttles if there's some chance there's a throttle to
   // unblock.
diff --git a/net/cert/x509_certificate.cc b/net/cert/x509_certificate.cc
index cf5d2f6..e60a697 100644
--- a/net/cert/x509_certificate.cc
+++ b/net/cert/x509_certificate.cc
@@ -7,7 +7,6 @@
 #include <limits.h>
 #include <stdlib.h>
 
-#include <algorithm>
 #include <map>
 #include <memory>
 #include <string>
@@ -21,6 +20,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/pickle.h"
 #include "base/profiler/scoped_tracker.h"
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/lock.h"
@@ -540,8 +540,7 @@
     base::StringPiece ip_addr_string(
         reinterpret_cast<const char*>(host_info.address),
         host_info.AddressLength());
-    return std::find(cert_san_ip_addrs.begin(), cert_san_ip_addrs.end(),
-                     ip_addr_string) != cert_san_ip_addrs.end();
+    return base::ContainsValue(cert_san_ip_addrs, ip_addr_string);
   }
 
   // |reference_domain| is the remainder of |host| after the leading host
diff --git a/net/cert/x509_certificate_bytes.cc b/net/cert/x509_certificate_bytes.cc
index 7cada9fa..90d3813 100644
--- a/net/cert/x509_certificate_bytes.cc
+++ b/net/cert/x509_certificate_bytes.cc
@@ -6,6 +6,7 @@
 
 #include "base/numerics/safe_conversions.h"
 #include "base/pickle.h"
+#include "base/stl_util.h"
 #include "crypto/openssl_util.h"
 #include "net/base/ip_address.h"
 #include "net/cert/asn1_util.h"
@@ -263,15 +264,13 @@
   std::string normalized_cert_issuer;
   if (!GetNormalizedCertIssuer(cert_handle_, &normalized_cert_issuer))
     return false;
-  if (std::find(normalized_issuers.begin(), normalized_issuers.end(),
-                normalized_cert_issuer) != normalized_issuers.end())
+  if (base::ContainsValue(normalized_issuers, normalized_cert_issuer))
     return true;
 
   for (CRYPTO_BUFFER* intermediate : intermediate_ca_certs_) {
     if (!GetNormalizedCertIssuer(intermediate, &normalized_cert_issuer))
       return false;
-    if (std::find(normalized_issuers.begin(), normalized_issuers.end(),
-                  normalized_cert_issuer) != normalized_issuers.end())
+    if (base::ContainsValue(normalized_issuers, normalized_cert_issuer))
       return true;
   }
   return false;
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index b015999..ef08e7c 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -44,7 +44,6 @@
 
 #include "net/cookies/cookie_monster.h"
 
-#include <algorithm>
 #include <functional>
 #include <memory>
 #include <set>
@@ -59,6 +58,7 @@
 #include "base/metrics/histogram.h"
 #include "base/profiler/scoped_tracker.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -1011,8 +1011,7 @@
 bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
-                   scheme) != cookieable_schemes_.end();
+  return base::ContainsValue(cookieable_schemes_, scheme);
 }
 
 const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc
index 0869910..e6f5e8a 100644
--- a/net/dns/host_resolver_impl_unittest.cc
+++ b/net/dns/host_resolver_impl_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "net/dns/host_resolver_impl.h"
 
-#include <algorithm>
 #include <memory>
 #include <string>
 #include <tuple>
@@ -19,6 +18,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
@@ -203,9 +203,7 @@
   IPAddress ip;
   bool rv = ip.AssignFromIPLiteral(address);
   DCHECK(rv);
-  return std::find(list.begin(),
-                   list.end(),
-                   IPEndPoint(ip, port)) != list.end();
+  return base::ContainsValue(list, IPEndPoint(ip, port));
 }
 
 // A wrapper for requests to a HostResolver.
diff --git a/net/extras/sqlite/sqlite_channel_id_store.cc b/net/extras/sqlite/sqlite_channel_id_store.cc
index 70ca8d9..7b36b9c 100644
--- a/net/extras/sqlite/sqlite_channel_id_store.cc
+++ b/net/extras/sqlite/sqlite_channel_id_store.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "crypto/ec_private_key.h"
 #include "net/cert/asn1_util.h"
@@ -526,12 +527,8 @@
 
   for (PendingOperationsList::iterator it = pending_.begin();
        it != pending_.end();) {
-    bool remove =
-        std::find(server_identifiers.begin(), server_identifiers.end(),
-                  (*it)->channel_id().server_identifier()) !=
-        server_identifiers.end();
-
-    if (remove) {
+    if (base::ContainsValue(server_identifiers,
+                            (*it)->channel_id().server_identifier())) {
       std::unique_ptr<PendingOperation> po(*it);
       it = pending_.erase(it);
       --num_pending_;
diff --git a/net/http/http_security_headers.cc b/net/http/http_security_headers.cc
index e67eadf..cab2fff 100644
--- a/net/http/http_security_headers.cc
+++ b/net/http/http_security_headers.cc
@@ -5,6 +5,7 @@
 #include <limits>
 
 #include "base/base64.h"
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/string_util.h"
@@ -49,8 +50,7 @@
 bool IsBackupPinPresent(const HashValueVector& pins,
                         const HashValueVector& from_cert_chain) {
   for (const auto& pin : pins) {
-    auto p = std::find(from_cert_chain.begin(), from_cert_chain.end(), pin);
-    if (p == from_cert_chain.end())
+    if (!base::ContainsValue(from_cert_chain, pin))
       return true;
   }
   return false;
@@ -61,8 +61,7 @@
 bool HashesIntersect(const HashValueVector& a,
                      const HashValueVector& b) {
   for (const auto& pin : a) {
-    auto p = std::find(b.begin(), b.end(), pin);
-    if (p != b.end())
+    if (base::ContainsValue(b, pin))
       return true;
   }
   return false;
diff --git a/net/http/http_security_headers_unittest.cc b/net/http/http_security_headers_unittest.cc
index 2ddd6b1..7f1148a 100644
--- a/net/http/http_security_headers_unittest.cc
+++ b/net/http/http_security_headers_unittest.cc
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 #include <stdint.h>
-#include <algorithm>
 
 #include "base/base64.h"
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "crypto/sha2.h"
 #include "net/base/host_port_pair.h"
@@ -693,14 +693,9 @@
   EXPECT_EQ(2UL, dynamic_pkp_state.spki_hashes.size());
   EXPECT_EQ(report_uri, dynamic_pkp_state.report_uri);
 
-  HashValueVector::const_iterator hash =
-      std::find(dynamic_pkp_state.spki_hashes.begin(),
-                dynamic_pkp_state.spki_hashes.end(), good_hash);
-  EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash);
+  EXPECT_TRUE(base::ContainsValue(dynamic_pkp_state.spki_hashes, good_hash));
 
-  hash = std::find(dynamic_pkp_state.spki_hashes.begin(),
-                   dynamic_pkp_state.spki_hashes.end(), backup_hash);
-  EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash);
+  EXPECT_TRUE(base::ContainsValue(dynamic_pkp_state.spki_hashes, backup_hash));
 
   // Expect the overall state to reflect the header, too.
   EXPECT_TRUE(state.HasPublicKeyPins(domain));
@@ -719,13 +714,11 @@
   EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size());
   EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri);
 
-  hash = std::find(new_dynamic_pkp_state.spki_hashes.begin(),
-                   new_dynamic_pkp_state.spki_hashes.end(), good_hash);
-  EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash);
+  EXPECT_TRUE(
+      base::ContainsValue(new_dynamic_pkp_state.spki_hashes, good_hash));
 
-  hash = std::find(new_dynamic_pkp_state.spki_hashes.begin(),
-                   new_dynamic_pkp_state.spki_hashes.end(), backup_hash);
-  EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash);
+  EXPECT_TRUE(
+      base::ContainsValue(new_dynamic_pkp_state.spki_hashes, backup_hash));
 }
 
 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0) {
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index 422380b..73626e04 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -4,7 +4,6 @@
 
 #include "net/http/transport_security_state.h"
 
-#include <algorithm>
 #include <memory>
 #include <utility>
 #include <vector>
@@ -17,6 +16,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/sha1.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -224,8 +224,7 @@
 bool HashesIntersect(const HashValueVector& a,
                      const HashValueVector& b) {
   for (const auto& hash : a) {
-    auto p = std::find(b.begin(), b.end(), hash);
-    if (p != b.end())
+    if (base::ContainsValue(b, hash))
       return true;
   }
   return false;
diff --git a/net/log/net_log.cc b/net/log/net_log.cc
index 3ba872e..fdb0a189 100644
--- a/net/log/net_log.cc
+++ b/net/log/net_log.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -175,8 +176,7 @@
 
 bool NetLog::HasObserver(ThreadSafeObserver* observer) {
   lock_.AssertAcquired();
-  auto it = std::find(observers_.begin(), observers_.end(), observer);
-  return it != observers_.end();
+  return base::ContainsValue(observers_, observer);
 }
 
 // static
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index 0091c05..4c22849 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -8,7 +8,6 @@
 #include <cmath>
 #include <limits>
 #include <utility>
-#include <vector>
 
 #include "base/bind_helpers.h"
 #include "base/location.h"
@@ -27,17 +26,19 @@
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "net/base/host_port_pair.h"
 #include "net/base/load_flags.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/network_interfaces.h"
 #include "net/base/trace_constants.h"
-#include "net/base/url_util.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_response_info.h"
 #include "net/http/http_status_code.h"
+#include "net/nqe/network_quality_estimator_util.h"
 #include "net/nqe/socket_watcher_factory.h"
 #include "net/nqe/throughput_analyzer.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
 #include "url/gurl.h"
 
@@ -48,6 +49,8 @@
 
 namespace net {
 
+class HostResolver;
+
 namespace {
 
 // Returns the histogram that should be used to record the given statistic.
@@ -281,6 +284,7 @@
            NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE,
            NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE,
            NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM}),
+      net_log_(net_log),
       weak_ptr_factory_(this) {
   // None of the algorithms can have an empty name.
   DCHECK(algorithm_name_to_enum_.end() ==
@@ -310,7 +314,7 @@
       params_.get(), base::ThreadTaskRunnerHandle::Get(),
       base::Bind(&NetworkQualityEstimator::OnNewThroughputObservationAvailable,
                  base::Unretained(this)),
-      use_localhost_requests_, use_smaller_responses_for_tests));
+      use_localhost_requests_, use_smaller_responses_for_tests, net_log_));
 
   watcher_factory_.reset(new nqe::internal::SocketWatcherFactory(
       base::ThreadTaskRunnerHandle::Get(),
@@ -788,7 +792,12 @@
     const URLRequest& request) const {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  return (use_localhost_requests_ || !IsLocalhost(request.url().host())) &&
+  bool private_network_request = nqe::internal::IsPrivateHost(
+      request.context()->host_resolver(),
+      HostPortPair(request.url().host(), request.url().EffectiveIntPort()),
+      net_log_);
+
+  return (use_localhost_requests_ || !private_network_request) &&
          // Verify that response headers are received, so it can be ensured that
          // response is not cached.
          !request.response_info().response_time.is_null() &&
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h
index f74dffe..7b004ecda 100644
--- a/net/nqe/network_quality_estimator.h
+++ b/net/nqe/network_quality_estimator.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
@@ -22,6 +23,7 @@
 #include "base/time/time.h"
 #include "net/base/net_export.h"
 #include "net/base/network_change_notifier.h"
+#include "net/log/net_log_with_source.h"
 #include "net/nqe/cached_network_quality.h"
 #include "net/nqe/effective_connection_type.h"
 #include "net/nqe/effective_connection_type_observer.h"
@@ -662,6 +664,8 @@
   const std::vector<NetworkQualityObservationSource>
       disallowed_observation_sources_for_transport_;
 
+  NetLogWithSource net_log_;
+
   base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator);
diff --git a/net/nqe/network_quality_estimator_util.cc b/net/nqe/network_quality_estimator_util.cc
new file mode 100644
index 0000000..bffaac2
--- /dev/null
+++ b/net/nqe/network_quality_estimator_util.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/nqe/network_quality_estimator_util.h"
+
+#include "net/base/address_list.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ip_address.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/dns/host_resolver.h"
+
+namespace net {
+
+namespace nqe {
+
+namespace internal {
+
+bool IsPrivateHost(HostResolver* host_resolver,
+                   const HostPortPair& host_port_pair,
+                   const NetLogWithSource& net_log) {
+  // Try resolving |host_port_pair.host()| synchronously.
+  HostResolver::RequestInfo resolve_info(host_port_pair);
+  resolve_info.set_allow_cached_response(true);
+  AddressList addresses;
+  // Resolve synchronously using the resolver's cache.
+  int rv = host_resolver->ResolveFromCache(resolve_info, &addresses, net_log);
+
+  DCHECK_NE(rv, ERR_IO_PENDING);
+  if (rv == OK && !addresses.empty()) {
+    // Checking only the first address should be sufficient.
+    IPEndPoint ip_end_point = addresses.front();
+    net::IPAddress ip_address = ip_end_point.address();
+    if (ip_address.IsReserved())
+      return true;
+  }
+
+  return false;
+}
+
+}  // namespace internal
+
+}  // namespace nqe
+
+}  // namespace net
diff --git a/net/nqe/network_quality_estimator_util.h b/net/nqe/network_quality_estimator_util.h
new file mode 100644
index 0000000..94289c1e
--- /dev/null
+++ b/net/nqe/network_quality_estimator_util.h
@@ -0,0 +1,40 @@
+// 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 NET_NQE_NETWORK_QUALITY_ESTIMATOR_UTIL_H_
+#define NET_NQE_NETWORK_QUALITY_ESTIMATOR_UTIL_H_
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+class HostPortPair;
+class HostResolver;
+class NetLogWithSource;
+
+namespace nqe {
+
+namespace internal {
+
+// Returns true if the host contained in |host_port_pair| is a host in a
+// private Internet as defined by RFC 1918 or if the requests to
+// |host_port_pair| are not expected to generate useful network quality
+// information. This includes localhost, hosts on private subnets, and
+// hosts on subnets that are reserved for specific usage, and are unlikely
+// to be used by public web servers.
+// To make this determination, IsPrivateHost() makes the best
+// effort estimate including trying to resolve the host in the
+// |host_port_pair|. The method is synchronous.
+// |host_resolver| must not be null.
+NET_EXPORT_PRIVATE bool IsPrivateHost(HostResolver* host_resolver,
+                                      const HostPortPair& host_port_pair,
+                                      const NetLogWithSource& net_log);
+
+}  // namespace internal
+
+}  // namespace nqe
+
+}  // namespace net
+
+#endif  // NET_NQE_NETWORK_QUALITY_ESTIMATOR_UTIL_H_
diff --git a/net/nqe/network_quality_estimator_util_unittest.cc b/net/nqe/network_quality_estimator_util_unittest.cc
new file mode 100644
index 0000000..0f80d78
--- /dev/null
+++ b/net/nqe/network_quality_estimator_util_unittest.cc
@@ -0,0 +1,186 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/nqe/network_quality_estimator_util.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/dns/host_resolver.h"
+#include "net/dns/host_resolver_impl.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/log/test_net_log.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+
+namespace nqe {
+
+namespace internal {
+
+namespace {
+
+// Verify that the cached network qualities from the prefs are not used if the
+// reading of the network quality prefs is not enabled..
+TEST(NetworkQualityEstimatorUtilTest, ReservedHost) {
+  std::unique_ptr<BoundTestNetLog> net_log =
+      base::MakeUnique<BoundTestNetLog>();
+  BoundTestNetLog* net_log_ptr = net_log.get();
+
+  MockCachingHostResolver mock_host_resolver;
+
+  scoped_refptr<net::RuleBasedHostResolverProc> rules(
+      new net::RuleBasedHostResolverProc(nullptr));
+
+  // example1.com resolves to a private IP address.
+  rules->AddRule("example1.com", "127.0.0.3");
+
+  // example2.com resolves to a public IP address.
+  rules->AddRule("example2.com", "27.0.0.3");
+
+  mock_host_resolver.set_rules(rules.get());
+
+  EXPECT_EQ(0u, mock_host_resolver.num_resolve());
+
+  {
+    // Resolve example1.com so that the resolution entry is cached.
+    TestCompletionCallback callback;
+    std::unique_ptr<HostResolver::Request> request;
+    AddressList ignored;
+    int rv = mock_host_resolver.Resolve(
+        HostResolver::RequestInfo(HostPortPair("example1.com", 443)),
+        DEFAULT_PRIORITY, &ignored, callback.callback(), &request,
+        NetLogWithSource());
+    EXPECT_EQ(ERR_IO_PENDING, rv);
+    EXPECT_EQ(OK, callback.WaitForResult());
+  }
+
+  {
+    // Resolve example2.com so that the resolution entry is cached.
+    TestCompletionCallback callback;
+    std::unique_ptr<HostResolver::Request> request;
+    AddressList ignored;
+    int rv = mock_host_resolver.Resolve(
+        HostResolver::RequestInfo(HostPortPair("example2.com", 443)),
+        DEFAULT_PRIORITY, &ignored, callback.callback(), &request,
+        NetLogWithSource());
+    EXPECT_EQ(ERR_IO_PENDING, rv);
+    EXPECT_EQ(OK, callback.WaitForResult());
+  }
+
+  EXPECT_EQ(2u, mock_host_resolver.num_resolve());
+
+  EXPECT_FALSE(IsPrivateHost(&mock_host_resolver,
+                             HostPortPair("2607:f8b0:4006:819::200e", 80),
+                             net_log_ptr->bound()));
+  EXPECT_EQ(1u, mock_host_resolver.num_resolve_from_cache());
+
+  EXPECT_TRUE(IsPrivateHost(&mock_host_resolver,
+                            HostPortPair("192.168.0.1", 443),
+                            net_log_ptr->bound()));
+  EXPECT_EQ(2u, mock_host_resolver.num_resolve_from_cache());
+
+  EXPECT_FALSE(IsPrivateHost(&mock_host_resolver,
+                             HostPortPair("92.168.0.1", 443),
+                             net_log_ptr->bound()));
+  EXPECT_EQ(3u, mock_host_resolver.num_resolve_from_cache());
+
+  EXPECT_TRUE(IsPrivateHost(&mock_host_resolver,
+                            HostPortPair("example1.com", 443),
+                            net_log_ptr->bound()));
+  EXPECT_EQ(4u, mock_host_resolver.num_resolve_from_cache());
+
+  EXPECT_FALSE(IsPrivateHost(&mock_host_resolver,
+                             HostPortPair("example2.com", 443),
+                             net_log_ptr->bound()));
+  EXPECT_EQ(5u, mock_host_resolver.num_resolve_from_cache());
+
+  // IsPrivateHost() should have queried only the resolver's cache.
+  EXPECT_EQ(2u, mock_host_resolver.num_resolve());
+}
+
+// Verify that IsPrivateHost() returns false for a hostname whose DNS
+// resolution is not cached. Further, once the resolution is cached, verify that
+// the cached entry is used.
+TEST(NetworkQualityEstimatorUtilTest, ReservedHostUncached) {
+  std::unique_ptr<BoundTestNetLog> net_log =
+      base::MakeUnique<BoundTestNetLog>();
+  BoundTestNetLog* net_log_ptr = net_log.get();
+
+  MockCachingHostResolver mock_host_resolver;
+
+  scoped_refptr<net::RuleBasedHostResolverProc> rules(
+      new net::RuleBasedHostResolverProc(nullptr));
+
+  // Add example3.com resolution to the DNS cache.
+  rules->AddRule("example3.com", "127.0.0.3");
+  mock_host_resolver.set_rules(rules.get());
+
+  // Not in DNS host cache, so should not be marked as private.
+  EXPECT_FALSE(IsPrivateHost(&mock_host_resolver,
+                             HostPortPair("example3.com", 443),
+                             net_log_ptr->bound()));
+  EXPECT_EQ(0u, mock_host_resolver.num_resolve());
+  EXPECT_EQ(1u, mock_host_resolver.num_resolve_from_cache());
+
+  {
+    // Resolve example3.com so that the resolution entry is cached.
+    TestCompletionCallback callback;
+    std::unique_ptr<HostResolver::Request> request;
+    AddressList ignored;
+    int rv = mock_host_resolver.Resolve(
+        HostResolver::RequestInfo(HostPortPair("example3.com", 443)),
+        DEFAULT_PRIORITY, &ignored, callback.callback(), &request,
+        NetLogWithSource());
+    EXPECT_EQ(ERR_IO_PENDING, rv);
+    EXPECT_EQ(OK, callback.WaitForResult());
+    EXPECT_EQ(1u, mock_host_resolver.num_resolve());
+  }
+  EXPECT_TRUE(IsPrivateHost(&mock_host_resolver,
+                            HostPortPair("example3.com", 443),
+                            net_log_ptr->bound()));
+
+  // IsPrivateHost() should have queried only the resolver's cache.
+  EXPECT_EQ(1u, mock_host_resolver.num_resolve());
+  EXPECT_EQ(2u, mock_host_resolver.num_resolve_from_cache());
+}
+
+// Verify that IsPrivateHost() returns correct results for local hosts.
+TEST(NetworkQualityEstimatorUtilTest, Localhost) {
+  std::unique_ptr<BoundTestNetLog> net_log =
+      base::MakeUnique<BoundTestNetLog>();
+  BoundTestNetLog* net_log_ptr = net_log.get();
+
+  net::HostResolver::Options options;
+  // Use HostResolverImpl since MockCachingHostResolver does not determine the
+  // correct answer for localhosts.
+  HostResolverImpl resolver(options, net_log_ptr->bound().net_log());
+
+  scoped_refptr<net::RuleBasedHostResolverProc> rules(
+      new net::RuleBasedHostResolverProc(nullptr));
+
+  EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("localhost", 443),
+                            net_log_ptr->bound()));
+  EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("localhost6", 443),
+                            net_log_ptr->bound()));
+  EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("127.0.0.1", 80),
+                            net_log_ptr->bound()));
+  EXPECT_TRUE(IsPrivateHost(&resolver, HostPortPair("0.0.0.0", 80),
+                            net_log_ptr->bound()));
+  EXPECT_TRUE(
+      IsPrivateHost(&resolver, HostPortPair("::1", 80), net_log_ptr->bound()));
+  EXPECT_FALSE(IsPrivateHost(&resolver, HostPortPair("google.com", 80),
+                             net_log_ptr->bound()));
+}
+
+}  // namespace
+
+}  // namespace internal
+
+}  // namespace nqe
+
+}  // namespace net
diff --git a/net/nqe/throughput_analyzer.cc b/net/nqe/throughput_analyzer.cc
index de1b0ef..b38c1e7 100644
--- a/net/nqe/throughput_analyzer.cc
+++ b/net/nqe/throughput_analyzer.cc
@@ -8,10 +8,13 @@
 
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
+#include "net/base/host_port_pair.h"
 #include "net/base/network_activity_monitor.h"
 #include "net/base/url_util.h"
 #include "net/nqe/network_quality_estimator_params.h"
+#include "net/nqe/network_quality_estimator_util.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
 
 #if defined(OS_ANDROID)
 #include "net/android/traffic_stats.h"
@@ -19,6 +22,8 @@
 
 namespace net {
 
+class HostResolver;
+
 namespace {
 
 // Maximum number of accuracy degrading requests, and requests that do not
@@ -40,7 +45,8 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     ThroughputObservationCallback throughput_observation_callback,
     bool use_local_host_requests_for_tests,
-    bool use_smaller_responses_for_tests)
+    bool use_smaller_responses_for_tests,
+    const NetLogWithSource& net_log)
     : params_(params),
       task_runner_(task_runner),
       throughput_observation_callback_(throughput_observation_callback),
@@ -49,7 +55,8 @@
       bits_received_at_window_start_(0),
       disable_throughput_measurements_(false),
       use_localhost_requests_for_tests_(use_local_host_requests_for_tests),
-      use_small_responses_for_tests_(use_smaller_responses_for_tests) {
+      use_small_responses_for_tests_(use_smaller_responses_for_tests),
+      net_log_(net_log) {
   DCHECK(params_);
   DCHECK(task_runner_);
   DCHECK(!IsCurrentlyTrackingThroughput());
@@ -264,8 +271,12 @@
 bool ThroughputAnalyzer::DegradesAccuracy(const URLRequest& request) const {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  return !(use_localhost_requests_for_tests_ ||
-           !IsLocalhost(request.url().host())) ||
+  bool private_network_request = nqe::internal::IsPrivateHost(
+      request.context()->host_resolver(),
+      HostPortPair(request.url().host(), request.url().EffectiveIntPort()),
+      net_log_);
+
+  return !(use_localhost_requests_for_tests_ || !private_network_request) ||
          request.creation_time() < last_connection_change_;
 }
 
diff --git a/net/nqe/throughput_analyzer.h b/net/nqe/throughput_analyzer.h
index 6aeae16..00bf7a6 100644
--- a/net/nqe/throughput_analyzer.h
+++ b/net/nqe/throughput_analyzer.h
@@ -14,6 +14,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
+#include "net/log/net_log_with_source.h"
 
 namespace {
 typedef base::Callback<void(int32_t)> ThroughputObservationCallback;
@@ -60,7 +61,8 @@
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       ThroughputObservationCallback throughput_observation_callback,
       bool use_local_host_requests_for_tests,
-      bool use_smaller_responses_for_tests);
+      bool use_smaller_responses_for_tests,
+      const NetLogWithSource& net_log);
   virtual ~ThroughputAnalyzer();
 
   // Notifies |this| that the headers of |request| are about to be sent.
@@ -83,6 +85,10 @@
   // estimation.
   void SetUseSmallResponsesForTesting(bool use_small_responses);
 
+  // Returns true if throughput is currently tracked by a throughput
+  // observation window.
+  bool IsCurrentlyTrackingThroughput() const;
+
  protected:
   // Exposed for testing.
   bool disable_throughput_measurements() const {
@@ -122,10 +128,6 @@
   // EndThroughputObservationWindow ends the throughput observation window.
   void EndThroughputObservationWindow();
 
-  // Returns true if throughput is currently tracked by a throughput
-  // observation window.
-  bool IsCurrentlyTrackingThroughput() const;
-
   // Returns true if the |request| degrades the accuracy of the throughput
   // observation window. A local request or a request that spans a connection
   // change degrades the accuracy of the throughput computation.
@@ -178,6 +180,8 @@
 
   base::ThreadChecker thread_checker_;
 
+  NetLogWithSource net_log_;
+
   DISALLOW_COPY_AND_ASSIGN(ThroughputAnalyzer);
 };
 
diff --git a/net/nqe/throughput_analyzer_unittest.cc b/net/nqe/throughput_analyzer_unittest.cc
index 9d5020c..ca7091f 100644
--- a/net/nqe/throughput_analyzer_unittest.cc
+++ b/net/nqe/throughput_analyzer_unittest.cc
@@ -10,17 +10,22 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "net/base/url_util.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/log/test_net_log.h"
 #include "net/nqe/network_quality_estimator_params.h"
+#include "net/nqe/network_quality_estimator_util.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
@@ -42,7 +47,8 @@
                 &TestThroughputAnalyzer::OnNewThroughputObservationAvailable,
                 base::Unretained(this)),
             false,
-            false),
+            false,
+            base::MakeUnique<BoundTestNetLog>()->bound()),
         throughput_observations_received_(0),
         bits_received_(0) {}
 
@@ -62,6 +68,17 @@
     bits_received_ += additional_bits_received;
   }
 
+  // Uses a mock resolver to force example.com to resolve to a public IP
+  // address.
+  void AddIPAddressResolution(TestURLRequestContext* context) {
+    scoped_refptr<net::RuleBasedHostResolverProc> rules(
+        new net::RuleBasedHostResolverProc(nullptr));
+    // example1.com resolves to a public IP address.
+    rules->AddRule("example.com", "27.0.0.3");
+    mock_host_resolver_.set_rules(rules.get());
+    context->set_host_resolver(&mock_host_resolver_);
+  }
+
   using internal::ThroughputAnalyzer::disable_throughput_measurements;
 
  private:
@@ -69,6 +86,8 @@
 
   int64_t bits_received_;
 
+  MockCachingHostResolver mock_host_resolver_;
+
   DISALLOW_COPY_AND_ASSIGN(TestThroughputAnalyzer);
 };
 
@@ -89,6 +108,7 @@
 
     TestDelegate test_delegate;
     TestURLRequestContext context;
+    throughput_analyzer.AddIPAddressResolution(&context);
 
     ASSERT_FALSE(throughput_analyzer.disable_throughput_measurements());
     std::deque<std::unique_ptr<URLRequest>> requests;
@@ -98,19 +118,23 @@
     const std::string url = test.use_local_requests
                                 ? "http://127.0.0.1/test.html"
                                 : "http://example.com/test.html";
+
+    EXPECT_EQ(test.use_local_requests,
+              nqe::internal::IsPrivateHost(
+                  context.host_resolver(),
+                  HostPortPair(GURL(url).host(), GURL(url).EffectiveIntPort()),
+                  base::MakeUnique<BoundTestNetLog>()->bound()));
     for (size_t i = 0; i < 1000; ++i) {
       std::unique_ptr<URLRequest> request(
           context.CreateRequest(GURL(url), DEFAULT_PRIORITY, &test_delegate,
                                 TRAFFIC_ANNOTATION_FOR_TESTS));
-      ASSERT_EQ(test.use_local_requests, IsLocalhost(request->url().host()));
-
       throughput_analyzer.NotifyStartTransaction(*(request.get()));
       requests.push_back(std::move(request));
     }
     // Too many local requests should cause the |throughput_analyzer| to disable
     // throughput measurements.
-    EXPECT_EQ(test.use_local_requests,
-              throughput_analyzer.disable_throughput_measurements());
+    EXPECT_NE(test.use_local_requests,
+              throughput_analyzer.IsCurrentlyTrackingThroughput());
   }
 }
 
@@ -141,6 +165,7 @@
 
     TestDelegate test_delegate;
     TestURLRequestContext context;
+    throughput_analyzer.AddIPAddressResolution(&context);
 
     std::unique_ptr<URLRequest> request_local;
 
@@ -150,7 +175,7 @@
     request_not_local->Start();
 
     if (test.start_local_request) {
-      request_local = context.CreateRequest(GURL("http://localhost/echo.html"),
+      request_local = context.CreateRequest(GURL("http://127.0.0.1/echo.html"),
                                             DEFAULT_PRIORITY, &test_delegate,
                                             TRAFFIC_ANNOTATION_FOR_TESTS);
       request_local->Start();
@@ -229,6 +254,7 @@
     TestThroughputAnalyzer throughput_analyzer(&params);
     TestDelegate test_delegate;
     TestURLRequestContext context;
+    throughput_analyzer.AddIPAddressResolution(&context);
 
     EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
 
@@ -281,6 +307,7 @@
   TestThroughputAnalyzer throughput_analyzer(&params);
   TestDelegate test_delegate;
   TestURLRequestContext context;
+  throughput_analyzer.AddIPAddressResolution(&context);
 
   EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
 
diff --git a/net/quic/core/quic_tag.cc b/net/quic/core/quic_tag.cc
index 1df74e66..2d0f1ec 100644
--- a/net/quic/core/quic_tag.cc
+++ b/net/quic/core/quic_tag.cc
@@ -4,9 +4,8 @@
 
 #include "net/quic/core/quic_tag.h"
 
-#include <algorithm>
-
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "net/quic/platform/api/quic_text_utils.h"
 
 namespace net {
@@ -62,8 +61,7 @@
 }
 
 bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag) {
-  return std::find(tag_vector.begin(), tag_vector.end(), tag) !=
-         tag_vector.end();
+  return base::ContainsValue(tag_vector, tag);
 }
 
 }  // namespace net
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f3d0f35..f8d19d1 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2327,10 +2327,6 @@
 crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html [ Skip ]
 crbug.com/658997 external/wpt/service-workers/service-worker/fetch-canvas-tainting-cache.https.html [ Skip ]
 crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/fetch-canvas-tainting-cache.https.html [ Skip ]
-crbug.com/658997 external/wpt/service-workers/service-worker/invalid-blobtype.https.html [ Skip ]
-crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/invalid-blobtype.https.html [ Skip ]
-crbug.com/658997 external/wpt/service-workers/service-worker/invalid-header.https.html [ Skip ]
-crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/invalid-header.https.html [ Skip ]
 
 crbug.com/435547 http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ]
 crbug.com/435547 virtual/mojo-loading/http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html
index 738e0f0..1aef3568 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.html
@@ -8,7 +8,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice({acceptAllDevices: true})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices(),
       new DOMException(
         'Origin is not allowed to access any service. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html
index 1a69b79..2b9fef68 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/requestDevice/blocklisted-service-in-optionalServices.html
@@ -16,7 +16,7 @@
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['human_interface_device']
     })
-    .then(([device, fake_peripheral]) => {
+    .then(({device, fake_peripheral}) => {
       return fake_peripheral
         .setNextGATTConnectionResponse({code: HCI_SUCCESS})
         .then(() => device.gatt.connect())
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js
index 3945d6f..1c93f99 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-before.js
@@ -3,7 +3,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       device.gatt.disconnect();
       return assert_promise_rejects_with_message(
         device.gatt.CALLS([
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js
index f79f856..4dafb7b0 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-error.js
@@ -1,7 +1,7 @@
 'use strict';
 promise_test(() => {
   return getEmptyHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService('health_thermometer')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js
index 1256f567..722a04b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-called-during-success.js
@@ -3,7 +3,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService('health_thermometer')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js
index deb310d1..3367d92 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnect-invalidates-objects.js
@@ -3,7 +3,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       return device.gatt.CALLS([
         getPrimaryService('health_thermometer')|
         getPrimaryServices()|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js
index 2ae7af2..e1d66cb 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/disconnected-device.js
@@ -4,7 +4,7 @@
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']
     })
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.CALLS([
         getPrimaryService('health_thermometer')|
         getPrimaryServices()|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js
index 27f8bba..cba08269 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-no-permission-absent-service.js
@@ -7,7 +7,7 @@
                                   'SecurityError');
   return getHealthThermometerDeviceWithServicesDiscovered({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService(glucose.alias)|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js
index 879b6cd..39f8376 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/discovery-complete-service-not-found.js
@@ -3,7 +3,7 @@
   return getHealthThermometerDeviceWithServicesDiscovered({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['glucose']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.CALLS([
         getPrimaryService('glucose')|
         getPrimaryServices('glucose')[UUID]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js
index 360ee82..7ae3837 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-error.js
@@ -2,7 +2,7 @@
 promise_test(() => {
   let promise;
   return getEmptyHealthThermometerDevice()
-      .then(([device]) => {
+      .then(({device}) => {
         promise = assert_promise_rejects_with_message(
           device.gatt.CALLS([
             getPrimaryService('health_thermometer')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js
index 18e98f6a..f03a204 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/garbage-collection-ran-during-success.js
@@ -3,7 +3,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       promise = assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService('health_thermometer') |
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js
index 2dcc9ab6..e18bc2aa 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-different-service-after-reconnection.js
@@ -3,7 +3,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let services_first_connection;
       return device.gatt.CALLS([
           getPrimaryService('health_thermometer')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js
index 167e2c7e..10d440f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/get-same-object.js
@@ -3,7 +3,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       device.gatt.CALLS([
         getPrimaryService('health_thermometer')|
         getPrimaryServices()|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js
index 32544f0..5205b5c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js
@@ -1,7 +1,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       return assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService('wrong_name')|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js
index 5be6047..061ff09 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-absent-service.js
@@ -7,7 +7,7 @@
                                   'SecurityError');
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService(glucose.alias)|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js
index e2e95c2e..41286232 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js
@@ -1,7 +1,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice({acceptAllDevices: true})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService('heart_rate')|
           getPrimaryServices()|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js
index f7de4d2..eb9dc48c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-present-service.js
@@ -7,7 +7,7 @@
                                   'SecurityError');
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.CALLS([
           getPrimaryService(generic_access.alias)|
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js
index 09c7d916..888aee2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/service-not-found.js
@@ -3,7 +3,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['glucose']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.CALLS([
         getPrimaryService('glucose')|
         getPrimaryServices('glucose')[UUID]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html
index a5fb002..78067cb6 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html
@@ -8,7 +8,7 @@
 'use strict';
 promise_test(() => {
   return getDiscoveredHealthThermometerDevice()
-    .then(([device, fake_peripheral]) => {
+    .then(({device, fake_peripheral}) => {
       return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
         .then(() => device.gatt.connect())
         .then(gatt => assert_true(gatt.connected));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html
index 60156c1..7b735914 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html
@@ -8,7 +8,7 @@
 'use strict';
 promise_test(() => {
   return getDiscoveredHealthThermometerDevice()
-    .then(([device, fake_peripheral]) => {
+    .then(({device, fake_peripheral}) => {
       return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
         .then(() => {
           // Don't return the promise and let |device| go out of scope
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html
index d6d1a42..62f9d0b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html
@@ -8,7 +8,7 @@
 'use strict';
 promise_test(() => {
   return getDiscoveredHealthThermometerDevice()
-    .then(([device, fake_peripheral]) => {
+    .then(({device, fake_peripheral}) => {
       return fake_peripheral
         .setNextGATTConnectionResponse({code: HCI_SUCCESS})
         .then(() => device.gatt.connect())
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html
index c6f391c..f1aa39cc 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html
@@ -8,7 +8,7 @@
 'use strict';
 promise_test(() => {
   return getDiscoveredHealthThermometerDevice()
-    .then(([device, fake_peripheral]) => {
+    .then(({device, fake_peripheral}) => {
       return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
         .then(() => device.gatt.connect());
     })
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html
index 36e2de71..86e704f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       device.gatt.disconnect();
       return assert_promise_rejects_with_message(
         device.gatt.getPrimaryService('health_thermometer'),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html
index 4eb61ea1..b4fbe18 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getEmptyHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryService('health_thermometer'),
         new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html
index c2bd90f..9adb4ca6 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryService('health_thermometer'),
         new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
index 83741ef7..eb20948 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
@@ -11,7 +11,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       return device.gatt.getPrimaryService('health_thermometer')
         // Convert to array if necessary.
         .then(s => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html
index a7061fa..938b159b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnected-device.html
@@ -12,7 +12,7 @@
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']
     })
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryService('health_thermometer'),
       new DOMException('GATT Server is disconnected. ' +
                        'Cannot retrieve services. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html
index cb05a7a..1659be5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.html
@@ -15,7 +15,7 @@
                                   'SecurityError');
   return getHealthThermometerDeviceWithServicesDiscovered({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.getPrimaryService(glucose.alias), expected),
       assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html
index f6978485..962c713 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDeviceWithServicesDiscovered({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['glucose']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryService('glucose'),
       new DOMException(
         'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
index a0c3a56..ae48249 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
@@ -10,7 +10,7 @@
 promise_test(() => {
   let promise;
   return getEmptyHealthThermometerDevice()
-      .then(([device]) => {
+      .then(({device}) => {
         promise = assert_promise_rejects_with_message(
           device.gatt.getPrimaryService('health_thermometer'),
           new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
index a6429fb1..d275cea 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
@@ -11,7 +11,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryService('health_thermometer'),
         new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
index 92b3a1b8d..69411a5b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let services_first_connection;
       return device.gatt.getPrimaryService('health_thermometer')
         .then(services => services_first_connection = services)
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
index 3fc19c6..3783693f2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       device.gatt.getPrimaryService('health_thermometer'),
       device.gatt.getPrimaryService('health_thermometer')]))
     .then(([services_first_call, services_second_call]) => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html
index 591757d1..722be1a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       return assert_promise_rejects_with_message(
         device.gatt.getPrimaryService('wrong_name'),
         new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html
index 04fa5a1..88362fe 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.html
@@ -15,7 +15,7 @@
                                   'SecurityError');
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.getPrimaryService(glucose.alias), expected),
       assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
index d02d25d..7301f20 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice({acceptAllDevices: true})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
         device.gatt.getPrimaryService('heart_rate'),
         new DOMException('Origin is not allowed to access any service. Tip: ' +
                          'Add the service UUID to \'optionalServices\' in ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html
index 2a92858..d5e841c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.html
@@ -15,7 +15,7 @@
                                   'SecurityError');
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.getPrimaryService(generic_access.alias), expected),
       assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html
index ed44846d..d7290ba 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-service-not-found.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['glucose']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryService('glucose'),
       new DOMException(
         'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html
index 69338c2..a544178 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/service-found.html
@@ -10,7 +10,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       return Promise.all([
           device.gatt.getPrimaryService(generic_access.alias),
           device.gatt.getPrimaryService(generic_access.name),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html
index 5f72453..39d834d 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.html
@@ -10,7 +10,7 @@
   return getHIDDevice({
       filters: [{services: ['battery_service']}],
       optionalServices: ['human_interface_device']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices('human_interface_device'),
       new DOMException('Origin is not allowed to access the service. ' +
                        'Tip: Add the service UUID to \'optionalServices\' ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html
index ca39ae68..f7d2592a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/blocklisted-services.html
@@ -13,7 +13,7 @@
         'generic_access',
         'human_interface_device'
       ]})
-    .then(([device]) => device.gatt.getPrimaryServices())
+    .then(({device}) => device.gatt.getPrimaryServices())
     .then(services => {
       assert_equals(services.length, 2);
       let uuid_set = new Set(services.map(s => s.uuid));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html
index fa7df561..f5354b89 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       device.gatt.disconnect();
       return assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices('health_thermometer'),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html
index 2b6213db..2c19bda2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       device.gatt.disconnect();
       return assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html
index a29f4a6f..01017a2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getEmptyHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices('health_thermometer'),
         new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html
index aeecb4c..1e11f89 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getEmptyHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(),
         new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html
index 5069b35..a6c7211 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices('health_thermometer'),
         new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html
index 003aa676..523c668 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(),
         new DOMException('GATT Server is disconnected. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
index 8450d8e0..26b6589f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
@@ -11,7 +11,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       return device.gatt.getPrimaryServices('health_thermometer')
         // Convert to array if necessary.
         .then(s => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
index 45a160a..62a1165 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
@@ -11,7 +11,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       return device.gatt.getPrimaryServices()
         // Convert to array if necessary.
         .then(s => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html
index 48474bb5..202df7ec 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.html
@@ -12,7 +12,7 @@
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']
     })
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices('health_thermometer'),
       new DOMException('GATT Server is disconnected. ' +
                        'Cannot retrieve services. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html
index 9f7a190c..e327868 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnected-device.html
@@ -12,7 +12,7 @@
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']
     })
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices(),
       new DOMException('GATT Server is disconnected. ' +
                        'Cannot retrieve services. ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html
index 85737f76..2d341428 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.html
@@ -15,7 +15,7 @@
                                   'SecurityError');
   return getHealthThermometerDeviceWithServicesDiscovered({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(glucose.alias), expected),
       assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html
index 0682b61a..84e5bcef 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDeviceWithServicesDiscovered({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['glucose']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices('glucose'),
       new DOMException(
         'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
index d78d076..ae626b2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
@@ -10,7 +10,7 @@
 promise_test(() => {
   let promise;
   return getEmptyHealthThermometerDevice()
-      .then(([device]) => {
+      .then(({device}) => {
         promise = assert_promise_rejects_with_message(
           device.gatt.getPrimaryServices('health_thermometer'),
           new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
index 1beb3147..4d50a5c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
@@ -10,7 +10,7 @@
 promise_test(() => {
   let promise;
   return getEmptyHealthThermometerDevice()
-      .then(([device]) => {
+      .then(({device}) => {
         promise = assert_promise_rejects_with_message(
           device.gatt.getPrimaryServices(),
           new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
index 23c33e0..58f9f534 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
@@ -11,7 +11,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices('health_thermometer'),
         new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
index eb9b69ee..05983aa 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
@@ -11,7 +11,7 @@
   let promise;
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => {
+    .then(({device}) => {
       promise = assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(),
         new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
index cdd6a8f..6bb3339 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let services_first_connection;
       return device.gatt.getPrimaryServices('health_thermometer')
         .then(services => services_first_connection = services)
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
index 1c7d192..230c7485 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => {
+    .then(({device}) => {
       let services_first_connection;
       return device.gatt.getPrimaryServices()
         .then(services => services_first_connection = services)
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
index 0b50d54d..5f56fe0 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       device.gatt.getPrimaryServices('health_thermometer'),
       device.gatt.getPrimaryServices('health_thermometer')]))
     .then(([services_first_call, services_second_call]) => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
index 242ddf6c..1685f6f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       device.gatt.getPrimaryServices(),
       device.gatt.getPrimaryServices()]))
     .then(([services_first_call, services_second_call]) => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html
index f8d010b..ce17288 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice()
-    .then(([device]) => {
+    .then(({device}) => {
       return assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices('wrong_name'),
         new DOMException(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html
index bbebc7a..ce19ff45 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.html
@@ -15,7 +15,7 @@
                                   'SecurityError');
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(glucose.alias), expected),
       assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
index c80c983..e6e5be02 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice({acceptAllDevices: true})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices('heart_rate'),
         new DOMException('Origin is not allowed to access any service. Tip: ' +
                          'Add the service UUID to \'optionalServices\' in ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
index c771e477..45306589 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
@@ -9,7 +9,7 @@
 'use strict';
 promise_test(() => {
   return getHealthThermometerDevice({acceptAllDevices: true})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(),
         new DOMException('Origin is not allowed to access any service. Tip: ' +
                          'Add the service UUID to \'optionalServices\' in ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html
index bd8fd430..622bdaf 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.html
@@ -15,7 +15,7 @@
                                   'SecurityError');
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       assert_promise_rejects_with_message(
         device.gatt.getPrimaryServices(generic_access.alias), expected),
       assert_promise_rejects_with_message(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html
index cd9dce1..79c7d89 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.html
@@ -11,7 +11,7 @@
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['glucose']})
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices('glucose'),
       new DOMException(
         'No Services matching UUID ' + glucose.uuid + ' found in Device.',
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html
index 73409c8..63ac04e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found-with-uuid.html
@@ -7,9 +7,9 @@
 <script>
 'use strict';
 promise_test(() => {
-  return getHealthThermometerDevice({
+  return getTwoHealthThermometerServicesDevice({
     filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => Promise.all([
+    .then(({device}) => Promise.all([
       device.gatt.getPrimaryServices(health_thermometer.alias),
       device.gatt.getPrimaryServices(health_thermometer.name),
       device.gatt.getPrimaryServices(health_thermometer.uuid)]))
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html
index 79706f6..880108c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-found.html
@@ -7,10 +7,10 @@
 <script>
 'use strict';
 promise_test(function() {
-  return getHealthThermometerDevice({
+  return getTwoHealthThermometerServicesDevice({
       filters: [{services: ['health_thermometer']}],
       optionalServices: ['generic_access']})
-    .then(([device]) => device.gatt.getPrimaryServices())
+    .then(({device}) => device.gatt.getPrimaryServices())
     .then(services => {
       // Expect three service instances.
       assert_equals(services.length, 3);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html
index 744fda8..f621118 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/services-not-found.html
@@ -8,7 +8,7 @@
 'use strict';
 promise_test(() => {
   return getEmptyHealthThermometerDevice()
-    .then(([device]) => assert_promise_rejects_with_message(
+    .then(({device}) => assert_promise_rejects_with_message(
       device.gatt.getPrimaryServices(),
       new DOMException('No Services found in device.', 'NotFoundError')));
 }, 'Request for services in a device with no services. Reject with ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html
index be9e995..d1ef99d6 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-from-2-services.html
@@ -7,9 +7,9 @@
 <script>
 'use strict';
 promise_test(() => {
-  return getHealthThermometerDevice({
+  return getTwoHealthThermometerServicesDevice({
      filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => device.gatt.getPrimaryServices('health_thermometer'))
+    .then(({device}) => device.gatt.getPrimaryServices('health_thermometer'))
     .then(([service1, service2]) => {
       assert_equals(service1.device, service2.device);
     });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html
index 1029c3ef..d3f4808 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/device-same-object.html
@@ -9,7 +9,7 @@
 promise_test(() => {
   return getHealthThermometerDevice({
       filters: [{services: ['health_thermometer']}]})
-    .then(([device]) => device.gatt.getPrimaryService('health_thermometer'))
+    .then(({device}) => device.gatt.getPrimaryService('health_thermometer'))
     .then(service => {
       assert_equals(service.device, service.device);
     });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt
index 100c512..b3d57fb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-tabular-expected.txt
@@ -30,21 +30,15 @@
 PASS colgroup.hidden: 33 tests
 PASS colgroup.accessKey: 32 tests
 PASS colgroup.tabIndex: 24 tests
-PASS colgroup.span: 8 tests
-FAIL colgroup.span: setAttribute() to 2147483647 assert_equals: IDL get expected 1000 but got 8190
-FAIL colgroup.span: setAttribute() to 2147483648 assert_equals: IDL get expected 1000 but got 8190
-FAIL colgroup.span: setAttribute() to 4294967295 assert_equals: IDL get expected 1000 but got 8190
+PASS colgroup.span: 11 tests
 FAIL colgroup.span: setAttribute() to 4294967296 assert_equals: IDL get expected 1000 but got 1
-PASS colgroup.span: 43 tests
-FAIL colgroup.span: setAttribute() to 1001 assert_equals: IDL get expected 1000 but got 1001
+PASS colgroup.span: 44 tests
 FAIL colgroup.span: IDL set to 0 assert_equals: getAttribute() expected "0" but got "1"
-PASS colgroup.span: 2 tests
-FAIL colgroup.span: IDL set to 2147483647 assert_equals: IDL get expected 1000 but got 8190
+PASS colgroup.span: 3 tests
 FAIL colgroup.span: IDL set to "-0" assert_equals: getAttribute() expected "0" but got "1"
 FAIL colgroup.span: IDL set to 2147483648 assert_equals: getAttribute() expected "1" but got "0"
 FAIL colgroup.span: IDL set to 4294967295 assert_equals: getAttribute() expected "1" but got "0"
-PASS colgroup.span: IDL set to 1000 
-FAIL colgroup.span: IDL set to 1001 assert_equals: IDL get expected 1000 but got 1001
+PASS colgroup.span: 2 tests
 PASS colgroup.align: 32 tests
 PASS colgroup.ch (<colgroup char>): 32 tests
 PASS colgroup.chOff (<colgroup charoff>): 32 tests
@@ -57,21 +51,15 @@
 PASS col.hidden: 33 tests
 PASS col.accessKey: 32 tests
 PASS col.tabIndex: 24 tests
-PASS col.span: 8 tests
-FAIL col.span: setAttribute() to 2147483647 assert_equals: IDL get expected 1000 but got 8190
-FAIL col.span: setAttribute() to 2147483648 assert_equals: IDL get expected 1000 but got 8190
-FAIL col.span: setAttribute() to 4294967295 assert_equals: IDL get expected 1000 but got 8190
+PASS col.span: 11 tests
 FAIL col.span: setAttribute() to 4294967296 assert_equals: IDL get expected 1000 but got 1
-PASS col.span: 43 tests
-FAIL col.span: setAttribute() to 1001 assert_equals: IDL get expected 1000 but got 1001
+PASS col.span: 44 tests
 FAIL col.span: IDL set to 0 assert_equals: getAttribute() expected "0" but got "1"
-PASS col.span: 2 tests
-FAIL col.span: IDL set to 2147483647 assert_equals: IDL get expected 1000 but got 8190
+PASS col.span: 3 tests
 FAIL col.span: IDL set to "-0" assert_equals: getAttribute() expected "0" but got "1"
 FAIL col.span: IDL set to 2147483648 assert_equals: getAttribute() expected "1" but got "0"
 FAIL col.span: IDL set to 4294967295 assert_equals: getAttribute() expected "1" but got "0"
-PASS col.span: IDL set to 1000 
-FAIL col.span: IDL set to 1001 assert_equals: IDL get expected 1000 but got 1001
+PASS col.span: 2 tests
 PASS col.align: 32 tests
 PASS col.ch (<col char>): 32 tests
 PASS col.chOff (<col charoff>): 32 tests
@@ -129,20 +117,12 @@
 PASS td.hidden: 33 tests
 PASS td.accessKey: 32 tests
 PASS td.tabIndex: 24 tests
-PASS td.colSpan: 8 tests
-FAIL td.colSpan: setAttribute() to 2147483647 assert_equals: IDL get expected 1000 but got 8190
-FAIL td.colSpan: setAttribute() to 2147483648 assert_equals: IDL get expected 1000 but got 8190
-FAIL td.colSpan: setAttribute() to 4294967295 assert_equals: IDL get expected 1000 but got 8190
+PASS td.colSpan: 11 tests
 FAIL td.colSpan: setAttribute() to 4294967296 assert_equals: IDL get expected 1000 but got 1
-PASS td.colSpan: 43 tests
-FAIL td.colSpan: setAttribute() to 1001 assert_equals: IDL get expected 1000 but got 1001
-PASS td.colSpan: 3 tests
-FAIL td.colSpan: IDL set to 2147483647 assert_equals: IDL get expected 1000 but got 8190
-PASS td.colSpan: IDL set to "-0" 
+PASS td.colSpan: 49 tests
 FAIL td.colSpan: IDL set to 2147483648 assert_equals: getAttribute() expected "1" but got "0"
 FAIL td.colSpan: IDL set to 4294967295 assert_equals: getAttribute() expected "1" but got "0"
-PASS td.colSpan: IDL set to 1000 
-FAIL td.colSpan: IDL set to 1001 assert_equals: IDL get expected 1000 but got 1001
+PASS td.colSpan: 2 tests
 PASS td.rowSpan: 6 tests
 FAIL td.rowSpan: setAttribute() to 0 assert_equals: IDL get expected 0 but got 1
 PASS td.rowSpan: 4 tests
@@ -175,20 +155,12 @@
 PASS th.hidden: 33 tests
 PASS th.accessKey: 32 tests
 PASS th.tabIndex: 24 tests
-PASS th.colSpan: 8 tests
-FAIL th.colSpan: setAttribute() to 2147483647 assert_equals: IDL get expected 1000 but got 8190
-FAIL th.colSpan: setAttribute() to 2147483648 assert_equals: IDL get expected 1000 but got 8190
-FAIL th.colSpan: setAttribute() to 4294967295 assert_equals: IDL get expected 1000 but got 8190
+PASS th.colSpan: 11 tests
 FAIL th.colSpan: setAttribute() to 4294967296 assert_equals: IDL get expected 1000 but got 1
-PASS th.colSpan: 43 tests
-FAIL th.colSpan: setAttribute() to 1001 assert_equals: IDL get expected 1000 but got 1001
-PASS th.colSpan: 3 tests
-FAIL th.colSpan: IDL set to 2147483647 assert_equals: IDL get expected 1000 but got 8190
-PASS th.colSpan: IDL set to "-0" 
+PASS th.colSpan: 49 tests
 FAIL th.colSpan: IDL set to 2147483648 assert_equals: getAttribute() expected "1" but got "0"
 FAIL th.colSpan: IDL set to 4294967295 assert_equals: getAttribute() expected "1" but got "0"
-PASS th.colSpan: IDL set to 1000 
-FAIL th.colSpan: IDL set to 1001 assert_equals: IDL get expected 1000 but got 1001
+PASS th.colSpan: 2 tests
 PASS th.rowSpan: 6 tests
 FAIL th.rowSpan: setAttribute() to 0 assert_equals: IDL get expected 0 but got 1
 PASS th.rowSpan: 4 tests
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/col-span-limits-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/col-span-limits-expected.txt
deleted file mode 100644
index c26568a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/col-span-limits-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS col span of 1000 must work 
-FAIL col span of 1001 must be treated as 1000 assert_equals: table3 width expected 51 but got 53
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/html/tabular_data/col_span-expected.txt b/third_party/WebKit/LayoutTests/html/tabular_data/col_span-expected.txt
index e34c777..ddcbba3 100644
--- a/third_party/WebKit/LayoutTests/html/tabular_data/col_span-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/tabular_data/col_span-expected.txt
@@ -21,9 +21,9 @@
 PASS spanAttributeEffect("  7") is 7
 PASS spanAttributeEffect(arabicIndicDigitOne) is 1
 PASS spanAttributeEffect("2" + arabicIndicDigitOne) is 2
-PASS spanAttributeEffect("2147483647") is 8190
-PASS spanAttributeEffect("2147483648") is 8190
-PASS spanAttributeEffect("4294967295") is 8190
+PASS spanAttributeEffect("2147483647") is 1000
+PASS spanAttributeEffect("2147483648") is 1000
+PASS spanAttributeEffect("4294967295") is 1000
 PASS spanAttributeEffect("4294967296") is 1
 PASS successfullyParsed is true
 
diff --git a/third_party/WebKit/LayoutTests/html/tabular_data/col_span.html b/third_party/WebKit/LayoutTests/html/tabular_data/col_span.html
index 632ea91f..0999ded 100644
--- a/third_party/WebKit/LayoutTests/html/tabular_data/col_span.html
+++ b/third_party/WebKit/LayoutTests/html/tabular_data/col_span.html
@@ -41,9 +41,9 @@
 shouldBe('spanAttributeEffect(arabicIndicDigitOne)', '1');
 shouldBe('spanAttributeEffect("2" + arabicIndicDigitOne)', '2');
 
-shouldBe('spanAttributeEffect("2147483647")', '8190');
-shouldBe('spanAttributeEffect("2147483648")', '8190');
-shouldBe('spanAttributeEffect("4294967295")', '8190');
+shouldBe('spanAttributeEffect("2147483647")', '1000');
+shouldBe('spanAttributeEffect("2147483648")', '1000');
+shouldBe('spanAttributeEffect("4294967295")', '1000');
 shouldBe('spanAttributeEffect("4294967296")', '1');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan-expected.txt b/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan-expected.txt
index 9655954..53babaf 100644
--- a/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan-expected.txt
@@ -21,8 +21,8 @@
 PASS colspanAttributeEffect("  7") is 7
 PASS colspanAttributeEffect(arabicIndicDigitOne) is 1
 PASS colspanAttributeEffect("2" + arabicIndicDigitOne) is 2
-PASS colspanAttributeEffect("2147483647") is 8190
-PASS colspanAttributeEffect("4294967295") is 8190
+PASS colspanAttributeEffect("2147483647") is 1000
+PASS colspanAttributeEffect("4294967295") is 1000
 PASS colspanAttributeEffect("4294967296") is 1
 PASS successfullyParsed is true
 
diff --git a/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan.html b/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan.html
index 54f7411..3237c91 100644
--- a/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan.html
+++ b/third_party/WebKit/LayoutTests/html/tabular_data/td_colspan.html
@@ -41,8 +41,8 @@
 shouldBe('colspanAttributeEffect(arabicIndicDigitOne)', '1');
 shouldBe('colspanAttributeEffect("2" + arabicIndicDigitOne)', '2');
 
-shouldBe('colspanAttributeEffect("2147483647")', '8190');
-shouldBe('colspanAttributeEffect("4294967295")', '8190');
+shouldBe('colspanAttributeEffect("2147483647")', '1000');
+shouldBe('colspanAttributeEffect("4294967295")', '1000');
 shouldBe('colspanAttributeEffect("4294967296")', '1');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
index 86581b8..fbff635 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -456,26 +456,94 @@
      })]));
 }
 
-// Returns a BluetoothDevice discovered using |options| and its
-// corresponding FakePeripheral.
+// Returns an object containing a BluetoothDevice discovered using |options|,
+// its corresponding FakePeripheral and FakeRemoteGATTServices.
 // The simulated device is called 'Health Thermometer' it has two known service
-// UUIDs: 'generic_access' and 'health_thermometer'. The device has been
-// connected to and its services are ready to be discovered.
+// UUIDs: 'generic_access' and 'health_thermometer' which correspond to two
+// services with the same UUIDs. The device has been connected to and its
+// services are ready to be discovered.
 // TODO(crbug.com/719816): Add characteristics and descriptors.
 function getHealthThermometerDevice(options) {
+  let device;
+  let fake_peripheral;
+  let fake_generic_access;
+  let fake_health_thermometer;
+
+  return getConnectedHealthThermometerDevice(options)
+    .then(result => {
+      ({
+        device,
+        fake_peripheral,
+        fake_generic_access,
+        fake_health_thermometer,
+      } = result);
+    })
+    .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+      code: HCI_SUCCESS}))
+    .then(() => ({
+      device: device,
+      fake_peripheral: fake_peripheral,
+      fake_generic_access: fake_generic_access,
+      fake_health_thermometer1: fake_health_thermometer,
+    }));
+}
+
+// Similar to getHealthThermometerDevice except that the peripheral has
+// two 'health_thermometer' services.
+function getTwoHealthThermometerServicesDevice(options) {
+  let device;
+  let fake_peripheral;
+  let fake_generic_access;
+  let fake_health_thermometer1;
+  let fake_health_thermometer2;
+
+  return getConnectedHealthThermometerDevice(options)
+    .then(result => {
+      ({
+        device,
+        fake_peripheral,
+        fake_generic_access,
+        fake_health_thermometer: fake_health_thermometer1,
+      } = result);
+    })
+    .then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'}))
+    .then(s => fake_health_thermometer2 = s)
+    .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+      code: HCI_SUCCESS}))
+    .then(() => ({
+      device: device,
+      fake_peripheral: fake_peripheral,
+      fake_generic_access: fake_generic_access,
+      fake_health_thermometer1: fake_health_thermometer1,
+      fake_health_thermometer2: fake_health_thermometer2
+    }));
+}
+
+// Similar to getHealthThermometerDevice except the GATT discovery
+// response has not been set yet so more attributes can still be added.
+function getConnectedHealthThermometerDevice(options) {
+  let device;
+  let fake_peripheral;
+  let fake_generic_access;
+  let fake_health_thermometer;
   return getDiscoveredHealthThermometerDevice(options)
-    .then(([device, fake_peripheral]) => {
-      return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
-        .then(() => device.gatt.connect())
-        .then(() => fake_peripheral.addFakeService({uuid: 'generic_access'}))
-        .then(() => fake_peripheral.addFakeService({
-          uuid: 'health_thermometer'}))
-        .then(() => fake_peripheral.addFakeService({
-          uuid: 'health_thermometer'}))
-        .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
-          code: HCI_SUCCESS}))
-        .then(() => [device, fake_peripheral]);
-    });
+    .then(result => {
+      ({device, fake_peripheral} = result);
+    })
+    .then(() => fake_peripheral.setNextGATTConnectionResponse({
+      code: HCI_SUCCESS}))
+    .then(() => device.gatt.connect())
+    .then(() => fake_peripheral.addFakeService({uuid: 'generic_access'}))
+    .then(s => fake_generic_access = s)
+    .then(() => fake_peripheral.addFakeService({
+      uuid: 'health_thermometer'}))
+    .then(s => fake_health_thermometer = s)
+    .then(() => ({
+      device: device,
+      fake_peripheral: fake_peripheral,
+      fake_generic_access: fake_generic_access,
+      fake_health_thermometer: fake_health_thermometer,
+    }));
 }
 
 // Returns the same device and fake peripheral as getHealthThermometerDevice()
@@ -513,7 +581,10 @@
         }))
         .then(() => requestDeviceWithKeyDown(options))
         .then(device => device.gatt.connect())
-        .then(gatt => [gatt.device, fake_peripheral]);
+        .then(gatt => ({
+          device: gatt.device,
+          fake_peripheral: fake_peripheral
+        }));
     });
 }
 
@@ -521,12 +592,15 @@
 // characteristics, or descriptors.
 function getEmptyHealthThermometerDevice(options) {
   return getDiscoveredHealthThermometerDevice(options)
-    .then(([device, fake_peripheral]) => {
+    .then(({device, fake_peripheral}) => {
       return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
         .then(() => device.gatt.connect())
         .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
           code: HCI_SUCCESS}))
-        .then(() => [device, fake_peripheral]);
+        .then(() => ({
+          device: device,
+          fake_peripheral: fake_peripheral
+        }));
     });
 }
 
@@ -549,8 +623,7 @@
     .then(fake_peripheral => {
       return requestDeviceWithKeyDown(options)
         .then(device => {
-          return fake_peripheral
-            .setNextGATTConnectionResponse({
+          return fake_peripheral.setNextGATTConnectionResponse({
               code: HCI_SUCCESS})
             .then(() => device.gatt.connect())
             .then(() => fake_peripheral.addFakeService({
@@ -561,7 +634,10 @@
               uuid: 'human_interface_device'}))
             .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
               code: HCI_SUCCESS}))
-            .then(() => [device, fake_peripheral]);
+            .then(() => ({
+              device: device,
+              fake_peripheral: fake_peripheral
+            }));
         });
     });
 };
@@ -578,6 +654,9 @@
   })
   .then(fake_peripheral => {
     return requestDeviceWithKeyDown(options)
-      .then(device => [device, fake_peripheral]);
+      .then(device => ({
+        device: device,
+        fake_peripheral: fake_peripheral
+      }));
   });
 }
diff --git a/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
index 8cedb1cd..00b2f8b0 100644
--- a/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/StyleBuilderFunctions.cpp.tmpl
@@ -456,8 +456,8 @@
   state.Style()->SetGridTemplate{{type}}s(ComputedStyle::InitialGridTemplate{{type}}s());
   state.Style()->SetNamedGrid{{type}}Lines(ComputedStyle::InitialNamedGrid{{type}}Lines());
   state.Style()->SetOrderedNamedGrid{{type}}Lines(ComputedStyle::InitialOrderedNamedGrid{{type}}Lines());
-  state.Style()->SetGridAutoRepeat{{type}}s(ComputedStyle::InitialGridAutoRepeatTracks());
-  state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(ComputedStyle::InitialGridAutoRepeatInsertionPoint());
+  state.Style()->SetGridAutoRepeat{{type}}s(ComputedStyle::InitialGridAutoRepeat{{type}}s());
+  state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(ComputedStyle::InitialGridAutoRepeat{{type}}sInsertionPoint());
   state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(ComputedStyle::InitialNamedGrid{{type}}Lines());
   state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(ComputedStyle::InitialOrderedNamedGrid{{type}}Lines());
   state.Style()->SetGridAutoRepeat{{type}}sType(ComputedStyle::InitialGridAutoRepeatType());
diff --git a/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp b/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp
index e17f2aa..a4b0dee 100644
--- a/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp
+++ b/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp
@@ -84,7 +84,7 @@
     return CSSValue::Create(center.length(), style.EffectiveZoom());
 
   CSSValueID keyword =
-      orientation == HORIZONTAL ? CSSValueRight : CSSValueBottom;
+      orientation == EBoxOrient::kHorizontal ? CSSValueRight : CSSValueBottom;
 
   return CSSValuePair::Create(
       CSSIdentifierValue::Create(keyword),
@@ -136,10 +136,10 @@
       CSSBasicShapeCircleValue* circle_value =
           CSSBasicShapeCircleValue::Create();
 
-      circle_value->SetCenterX(
-          ValueForCenterCoordinate(style, circle->CenterX(), HORIZONTAL));
-      circle_value->SetCenterY(
-          ValueForCenterCoordinate(style, circle->CenterY(), VERTICAL));
+      circle_value->SetCenterX(ValueForCenterCoordinate(
+          style, circle->CenterX(), EBoxOrient::kHorizontal));
+      circle_value->SetCenterY(ValueForCenterCoordinate(
+          style, circle->CenterY(), EBoxOrient::kVertical));
       circle_value->SetRadius(
           BasicShapeRadiusToCSSValue(style, circle->Radius()));
       return circle_value;
@@ -149,10 +149,10 @@
       CSSBasicShapeEllipseValue* ellipse_value =
           CSSBasicShapeEllipseValue::Create();
 
-      ellipse_value->SetCenterX(
-          ValueForCenterCoordinate(style, ellipse->CenterX(), HORIZONTAL));
-      ellipse_value->SetCenterY(
-          ValueForCenterCoordinate(style, ellipse->CenterY(), VERTICAL));
+      ellipse_value->SetCenterX(ValueForCenterCoordinate(
+          style, ellipse->CenterX(), EBoxOrient::kHorizontal));
+      ellipse_value->SetCenterY(ValueForCenterCoordinate(
+          style, ellipse->CenterY(), EBoxOrient::kVertical));
       ellipse_value->SetRadiusX(
           BasicShapeRadiusToCSSValue(style, ellipse->RadiusX()));
       ellipse_value->SetRadiusY(
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index a6d99812..2dc0a6c 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -145,51 +145,51 @@
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(ColumnFill column_fill)
+inline CSSIdentifierValue::CSSIdentifierValue(EColumnFill column_fill)
     : CSSValue(kIdentifierClass) {
   switch (column_fill) {
-    case kColumnFillAuto:
+    case EColumnFill::kAuto:
       value_id_ = CSSValueAuto;
       break;
-    case kColumnFillBalance:
+    case EColumnFill::kBalance:
       value_id_ = CSSValueBalance;
       break;
   }
 }
 
 template <>
-inline ColumnFill CSSIdentifierValue::ConvertTo() const {
+inline EColumnFill CSSIdentifierValue::ConvertTo() const {
   if (value_id_ == CSSValueBalance)
-    return kColumnFillBalance;
+    return EColumnFill::kBalance;
   if (value_id_ == CSSValueAuto)
-    return kColumnFillAuto;
+    return EColumnFill::kAuto;
   NOTREACHED();
-  return kColumnFillBalance;
+  return EColumnFill::kBalance;
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(ColumnSpan column_span)
+inline CSSIdentifierValue::CSSIdentifierValue(EColumnSpan column_span)
     : CSSValue(kIdentifierClass) {
   switch (column_span) {
-    case kColumnSpanAll:
+    case EColumnSpan::kAll:
       value_id_ = CSSValueAll;
       break;
-    case kColumnSpanNone:
+    case EColumnSpan::kNone:
       value_id_ = CSSValueNone;
       break;
   }
 }
 
 template <>
-inline ColumnSpan CSSIdentifierValue::ConvertTo() const {
+inline EColumnSpan CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueAll:
-      return kColumnSpanAll;
+      return EColumnSpan::kAll;
     default:
       NOTREACHED();
     // fall-through
     case CSSValueNone:
-      return kColumnSpanNone;
+      return EColumnSpan::kNone;
   }
 }
 
@@ -596,16 +596,16 @@
 inline CSSIdentifierValue::CSSIdentifierValue(EBoxPack e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case kBoxPackStart:
+    case EBoxPack::kStart:
       value_id_ = CSSValueStart;
       break;
-    case kBoxPackCenter:
+    case EBoxPack::kCenter:
       value_id_ = CSSValueCenter;
       break;
-    case kBoxPackEnd:
+    case EBoxPack::kEnd:
       value_id_ = CSSValueEnd;
       break;
-    case kBoxPackJustify:
+    case EBoxPack::kJustify:
       value_id_ = CSSValueJustify;
       break;
   }
@@ -615,38 +615,38 @@
 inline EBoxPack CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueStart:
-      return kBoxPackStart;
+      return EBoxPack::kStart;
     case CSSValueEnd:
-      return kBoxPackEnd;
+      return EBoxPack::kEnd;
     case CSSValueCenter:
-      return kBoxPackCenter;
+      return EBoxPack::kCenter;
     case CSSValueJustify:
-      return kBoxPackJustify;
+      return EBoxPack::kJustify;
     default:
       break;
   }
 
   NOTREACHED();
-  return kBoxPackJustify;
+  return EBoxPack::kJustify;
 }
 
 template <>
 inline CSSIdentifierValue::CSSIdentifierValue(EBoxAlignment e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case BSTRETCH:
+    case EBoxAlignment::kStretch:
       value_id_ = CSSValueStretch;
       break;
-    case BSTART:
+    case EBoxAlignment::kStart:
       value_id_ = CSSValueStart;
       break;
-    case BCENTER:
+    case EBoxAlignment::kCenter:
       value_id_ = CSSValueCenter;
       break;
-    case BEND:
+    case EBoxAlignment::kBend:
       value_id_ = CSSValueEnd;
       break;
-    case BBASELINE:
+    case EBoxAlignment::kBaseline:
       value_id_ = CSSValueBaseline;
       break;
   }
@@ -656,21 +656,21 @@
 inline EBoxAlignment CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueStretch:
-      return BSTRETCH;
+      return EBoxAlignment::kStretch;
     case CSSValueStart:
-      return BSTART;
+      return EBoxAlignment::kStart;
     case CSSValueEnd:
-      return BEND;
+      return EBoxAlignment::kBend;
     case CSSValueCenter:
-      return BCENTER;
+      return EBoxAlignment::kCenter;
     case CSSValueBaseline:
-      return BBASELINE;
+      return EBoxAlignment::kBaseline;
     default:
       break;
   }
 
   NOTREACHED();
-  return BSTRETCH;
+  return EBoxAlignment::kStretch;
 }
 
 template <>
@@ -715,10 +715,10 @@
 inline CSSIdentifierValue::CSSIdentifierValue(EBoxLines e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case SINGLE:
+    case EBoxLines::kSingle:
       value_id_ = CSSValueSingle;
       break;
-    case MULTIPLE:
+    case EBoxLines::kMultiple:
       value_id_ = CSSValueMultiple;
       break;
   }
@@ -728,25 +728,25 @@
 inline EBoxLines CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueSingle:
-      return SINGLE;
+      return EBoxLines::kSingle;
     case CSSValueMultiple:
-      return MULTIPLE;
+      return EBoxLines::kMultiple;
     default:
       break;
   }
 
   NOTREACHED();
-  return SINGLE;
+  return EBoxLines::kSingle;
 }
 
 template <>
 inline CSSIdentifierValue::CSSIdentifierValue(EBoxOrient e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case HORIZONTAL:
+    case EBoxOrient::kHorizontal:
       value_id_ = CSSValueHorizontal;
       break;
-    case VERTICAL:
+    case EBoxOrient::kVertical:
       value_id_ = CSSValueVertical;
       break;
   }
@@ -757,32 +757,32 @@
   switch (value_id_) {
     case CSSValueHorizontal:
     case CSSValueInlineAxis:
-      return HORIZONTAL;
+      return EBoxOrient::kHorizontal;
     case CSSValueVertical:
     case CSSValueBlockAxis:
-      return VERTICAL;
+      return EBoxOrient::kVertical;
     default:
       break;
   }
 
   NOTREACHED();
-  return HORIZONTAL;
+  return EBoxOrient::kHorizontal;
 }
 
 template <>
 inline CSSIdentifierValue::CSSIdentifierValue(EFlexDirection e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
-    case kFlowRow:
+    case EFlexDirection::kRow:
       value_id_ = CSSValueRow;
       break;
-    case kFlowRowReverse:
+    case EFlexDirection::kRowReverse:
       value_id_ = CSSValueRowReverse;
       break;
-    case kFlowColumn:
+    case EFlexDirection::kColumn:
       value_id_ = CSSValueColumn;
       break;
-    case kFlowColumnReverse:
+    case EFlexDirection::kColumnReverse:
       value_id_ = CSSValueColumnReverse;
       break;
   }
@@ -792,19 +792,19 @@
 inline EFlexDirection CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueRow:
-      return kFlowRow;
+      return EFlexDirection::kRow;
     case CSSValueRowReverse:
-      return kFlowRowReverse;
+      return EFlexDirection::kRowReverse;
     case CSSValueColumn:
-      return kFlowColumn;
+      return EFlexDirection::kColumn;
     case CSSValueColumnReverse:
-      return kFlowColumnReverse;
+      return EFlexDirection::kColumnReverse;
     default:
       break;
   }
 
   NOTREACHED();
-  return kFlowRow;
+  return EFlexDirection::kRow;
 }
 
 template <>
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index c53f45a..a50c99a 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1063,11 +1063,11 @@
     },
     {
       name: "column-fill",
-      type_name: "ColumnFill",
       field_template: "storage_only",
-      default_value: "kColumnFillBalance",
+      default_value: "EColumnFill::kBalance",
       field_size: 1,
       field_group: "rare-non-inherited->multi-col",
+      getter: "GetColumnFill",
     },
     {
       name: "contain",
@@ -1216,7 +1216,7 @@
       name: "flex-direction",
       type_name: "EFlexDirection",
       field_template: "storage_only",
-      default_value: "kFlowRow",
+      default_value: "EFlexDirection::kRow",
       field_size: 2,
       field_group: "rare-non-inherited->flexible-box",
     },
@@ -1278,7 +1278,7 @@
       converter: "ConvertGridTrackSizeList",
       runtime_flag: "CSSGridLayout",
       type_name: "Vector<GridTrackSize>",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "Vector<GridTrackSize>(1, GridTrackSize(Length(kAuto)))",
       field_group: "rare-non-inherited->grid",
     },
@@ -1300,7 +1300,7 @@
       converter: "ConvertGridTrackSizeList",
       runtime_flag: "CSSGridLayout",
       type_name: "Vector<GridTrackSize>",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "Vector<GridTrackSize>(1, GridTrackSize(Length(kAuto)))",
       field_group: "rare-non-inherited->grid",
     },
@@ -1310,7 +1310,7 @@
       runtime_flag: "CSSGridLayout",
       api_class: "CSSPropertyAPIGridLine",
       type_name: "GridPosition",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "GridPosition()",
       field_group: "rare-non-inherited->grid-item",
     },
@@ -1319,7 +1319,7 @@
       converter: "ConvertLength",
       runtime_flag: "CSSGridLayout",
       type_name: "Length",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "Length(kFixed)",
       field_group: "rare-non-inherited->grid",
     },
@@ -1329,7 +1329,7 @@
       converter: "ConvertGridPosition",
       runtime_flag: "CSSGridLayout",
       type_name: "GridPosition",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "GridPosition()",
       field_group: "rare-non-inherited->grid-item",
     },
@@ -1339,7 +1339,7 @@
       converter: "ConvertGridPosition",
       runtime_flag: "CSSGridLayout",
       type_name: "GridPosition",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "GridPosition()",
       field_group: "rare-non-inherited->grid-item",
     },
@@ -1348,7 +1348,7 @@
       converter: "ConvertLength",
       runtime_flag: "CSSGridLayout",
       type_name: "Length",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "Length(kFixed)",
       field_group: "rare-non-inherited->grid",
     },
@@ -1358,7 +1358,7 @@
       converter: "ConvertGridPosition",
       runtime_flag: "CSSGridLayout",
       type_name: "GridPosition",
-      field_template: "storage_only",
+      field_template: "external",
       default_value: "GridPosition()",
       field_group: "rare-non-inherited->grid-item",
     },
@@ -1373,7 +1373,7 @@
       api_class: "CSSPropertyAPIGridTemplateLine",
       custom_all: true,
       runtime_flag: "CSSGridLayout",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "Vector<GridTrackSize>",
       field_group: "rare-non-inherited->grid",
       default_value: "Vector<GridTrackSize>()",
@@ -1383,7 +1383,7 @@
       api_class: "CSSPropertyAPIGridTemplateLine",
       custom_all: true,
       runtime_flag: "CSSGridLayout",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "Vector<GridTrackSize>",
       field_group: "rare-non-inherited->grid",
       default_value: "Vector<GridTrackSize>()",
@@ -2054,44 +2054,52 @@
       api_class: "CSSPropertyAPIScrollPadding",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollPadding",
       include_paths: ["platform/Length.h"],
       typedom_types: ["Length", "Percent"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-padding-bottom",
       api_class: "CSSPropertyAPIScrollPadding",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollPadding",
       include_paths: ["platform/Length.h"],
       typedom_types: ["Length", "Percent"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-padding-left",
       api_class: "CSSPropertyAPIScrollPadding",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollPadding",
       include_paths: ["platform/Length.h"],
       typedom_types: ["Length", "Percent"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-padding-right",
       api_class: "CSSPropertyAPIScrollPadding",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollPadding",
       include_paths: ["platform/Length.h"],
       typedom_types: ["Length", "Percent"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-padding-block-start",
@@ -2146,40 +2154,48 @@
       api_class: "CSSPropertyAPIScrollSnapMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollSnapMargin",
       include_paths: ["platform/Length.h"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-snap-margin-bottom",
       api_class: "CSSPropertyAPIScrollSnapMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollSnapMargin",
       include_paths: ["platform/Length.h"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-snap-margin-left",
       api_class: "CSSPropertyAPIScrollSnapMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollSnapMargin",
       include_paths: ["platform/Length.h"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-snap-margin-right",
       api_class: "CSSPropertyAPIScrollSnapMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
-      initial: "InitialScrollSnapMargin",
       include_paths: ["platform/Length.h"],
       type_name: "Length",
       runtime_flag: "CSSScrollSnapPoints",
+      field_template: "external",
+      field_group: "rare-non-inherited->scroll-snap",
+      default_value: "Length()",
     },
     {
       name: "scroll-snap-margin-block-start",
@@ -2760,7 +2776,7 @@
       name: "-webkit-box-align",
       type_name: "EBoxAlignment",
       field_template: "storage_only",
-      default_value: "BSTRETCH",
+      default_value: "EBoxAlignment::kStretch",
       field_size: 3,
       field_group: "rare-non-inherited->deprecated-flexible-box",
     },
@@ -2800,7 +2816,7 @@
       name: "-webkit-box-lines",
       type_name: "EBoxLines",
       field_template: "storage_only",
-      default_value: "SINGLE",
+      default_value: "EBoxLines::kSingle",
       field_size: 1,
       field_group: "rare-non-inherited->deprecated-flexible-box",
     },
@@ -2817,7 +2833,7 @@
       name: "-webkit-box-orient",
       type_name: "EBoxOrient",
       field_template: "storage_only",
-      default_value: "HORIZONTAL",
+      default_value: "EBoxOrient::kHorizontal",
       field_size: 1,
       field_group: "rare-non-inherited->deprecated-flexible-box",
     },
@@ -2825,7 +2841,7 @@
       name: "-webkit-box-pack",
       type_name: "EBoxPack",
       field_template: "storage_only",
-      default_value: "kBoxPackStart",
+      default_value: "EBoxPack::kStart",
       field_size: 2,
       field_group: "rare-non-inherited->deprecated-flexible-box",
     },
@@ -2885,10 +2901,10 @@
       name: "column-span",
       api_class: true,
       api_methods: ["parseSingleValue"],
-      type_name: "ColumnSpan",
       field_template: "storage_only",
       field_group: "rare-non-inherited->multi-col",
-      default_value: "kColumnSpanNone",
+      default_value: "EColumnSpan::kNone",
+      getter: "GetColumnSpan",
       field_size: 1,
     },
     {
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index 0b8ef9c0..cba547a 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -2381,8 +2381,9 @@
     case CSSPropertyColumnRuleWidth:
       return ZoomAdjustedPixelValue(style.ColumnRuleWidth(), style);
     case CSSPropertyColumnSpan:
-      return CSSIdentifierValue::Create(style.GetColumnSpan() ? CSSValueAll
-                                                              : CSSValueNone);
+      return CSSIdentifierValue::Create(
+          static_cast<unsigned>(style.GetColumnSpan()) ? CSSValueAll
+                                                       : CSSValueNone);
     case CSSPropertyWebkitColumnBreakAfter:
       return ValueForWebkitColumnBreakBetween(style.BreakAfter());
     case CSSPropertyWebkitColumnBreakBefore:
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5 b/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
index d54b9aa8..fc1bfa35 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
+++ b/third_party/WebKit/Source/core/css/ComputedStyleExtraFields.json5
@@ -607,7 +607,7 @@
     },
     {
       name: "PageSize",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "FloatSize",
       field_group: "rare-non-inherited",
       default_value: "FloatSize()",
@@ -700,11 +700,10 @@
     },
     {
       name: "PageSizeType",
-      field_template: "storage_only",
-      type_name: "PageSizeType",
+      field_template: "keyword",
+      keywords: ["auto", "landscape", "portrait", "resolved"],
       field_group: "rare-non-inherited",
-      default_value: "PageSizeType::kAuto",
-      field_size: 2,
+      default_value: "auto",
     },
     {
       name: "HasCurrentOpacityAnimation",
@@ -912,24 +911,8 @@
       include_paths: ["core/style/StyleMotionData.h"],
     },
     {
-      name: "ScrollPadding",
-      field_template: "storage_only",
-      type_name: "ScrollPadding",
-      field_group: "rare-non-inherited->scroll-snap",
-      default_value: "Length()",
-      include_paths: ["core/style/ScrollSnap.h"],
-    },
-    {
-      name: "ScrollSnapMargin",
-      field_template: "storage_only",
-      type_name: "ScrollSnapMargin",
-      field_group: "rare-non-inherited->scroll-snap",
-      default_value: "Length()",
-      include_paths: ["core/style/ScrollSnap.h"],
-    },
-    {
       name: "NamedGridColumnLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "NamedGridLinesMap",
       field_group: "rare-non-inherited->grid",
       default_value: "NamedGridLinesMap()",
@@ -937,7 +920,7 @@
     },
     {
       name: "NamedGridRowLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "NamedGridLinesMap",
       field_group: "rare-non-inherited->grid",
       default_value: "NamedGridLinesMap()",
@@ -945,7 +928,7 @@
     },
     {
       name: "OrderedNamedGridColumnLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "OrderedNamedGridLines",
       field_group: "rare-non-inherited->grid",
       default_value: "OrderedNamedGridLines()",
@@ -953,7 +936,7 @@
     },
     {
       name: "OrderedNamedGridRowLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "OrderedNamedGridLines",
       field_group: "rare-non-inherited->grid",
       default_value: "OrderedNamedGridLines()",
@@ -961,7 +944,7 @@
     },
     {
       name: "AutoRepeatNamedGridColumnLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "NamedGridLinesMap",
       field_group: "rare-non-inherited->grid",
       default_value: "NamedGridLinesMap()",
@@ -969,7 +952,7 @@
     },
     {
       name: "AutoRepeatNamedGridRowLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "NamedGridLinesMap",
       field_group: "rare-non-inherited->grid",
       default_value: "NamedGridLinesMap()",
@@ -977,7 +960,7 @@
     },
     {
       name: "AutoRepeatOrderedNamedGridColumnLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "OrderedNamedGridLines",
       field_group: "rare-non-inherited->grid",
       default_value: "OrderedNamedGridLines()",
@@ -985,7 +968,7 @@
     },
     {
       name: "AutoRepeatOrderedNamedGridRowLines",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "OrderedNamedGridLines",
       field_group: "rare-non-inherited->grid",
       default_value: "OrderedNamedGridLines()",
@@ -993,7 +976,7 @@
     },
     {
       name: "NamedGridArea",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "NamedGridAreaMap",
       field_group: "rare-non-inherited->grid",
       default_value: "NamedGridAreaMap()",
@@ -1001,21 +984,21 @@
     },
     {
       name: "NamedGridAreaRowCount",
-      field_template: "storage_only",
+      field_template: "primitive",
       type_name: "size_t",
       field_group: "rare-non-inherited->grid",
       default_value: "0",
     },
     {
       name: "NamedGridAreaColumnCount",
-      field_template: "storage_only",
+      field_template: "primitive",
       type_name: "size_t",
       field_group: "rare-non-inherited->grid",
       default_value: "0",
     },
     {
       name: "GridAutoRepeatColumns",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "Vector<GridTrackSize>",
       field_group: "rare-non-inherited->grid",
       default_value: "Vector<GridTrackSize>()",
@@ -1023,28 +1006,28 @@
     },
     {
       name: "GridAutoRepeatRows",
-      field_template: "storage_only",
+      field_template: "external",
       type_name: "Vector<GridTrackSize>",
       field_group: "rare-non-inherited->grid",
       default_value: "Vector<GridTrackSize>()",
       include_paths: ["platform/wtf/Vector.h", "core/style/GridTrackSize.h"],
     },
     {
-      name: "AutoRepeatColumnsInsertionPoint",
-      field_template: "storage_only",
+      name: "GridAutoRepeatColumnsInsertionPoint",
+      field_template: "primitive",
       type_name: "size_t",
       field_group: "rare-non-inherited->grid",
       default_value: "0",
     },
     {
-      name: "AutoRepeatRowsInsertionPoint",
-      field_template: "storage_only",
+      name: "GridAutoRepeatRowsInsertionPoint",
+      field_template: "primitive",
       type_name: "size_t",
       field_group: "rare-non-inherited->grid",
       default_value: "0",
     },
     {
-      name: "AutoRepeatColumnsType",
+      name: "GridAutoRepeatColumnsType",
       field_template: "storage_only",
       type_name: "AutoRepeatType",
       field_group: "rare-non-inherited->grid",
@@ -1052,7 +1035,7 @@
       default_value: "kNoAutoRepeat",
     },
     {
-      name: "AutoRepeatRowsType",
+      name: "GridAutoRepeatRowsType",
       field_template: "storage_only",
       type_name: "AutoRepeatType",
       field_group: "rare-non-inherited->grid",
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp
index c4a337c..8a26dbd 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp
@@ -11,7 +11,7 @@
 CSSParserLocalContext::CSSParserLocalContext(bool use_alias_parsing)
     : use_alias_parsing_(use_alias_parsing) {}
 
-bool CSSParserLocalContext::GetUseAliasParsing() const {
+bool CSSParserLocalContext::UseAliasParsing() const {
   return use_alias_parsing_;
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h
index 6240c75..a5bbefe 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h
@@ -18,7 +18,7 @@
  public:
   CSSParserLocalContext();
   explicit CSSParserLocalContext(bool use_alias_parsing);
-  bool GetUseAliasParsing() const;
+  bool UseAliasParsing() const;
 
  private:
   bool use_alias_parsing_;
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAnimationName.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAnimationName.cpp
index bd63423..a8ba83c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAnimationName.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAnimationName.cpp
@@ -19,7 +19,7 @@
   // Allow quoted name if this is an alias property.
   return CSSPropertyParserHelpers::ConsumeCommaSeparatedList(
       CSSPropertyAnimationNameUtils::ConsumeAnimationName, range, &context,
-      local_context.GetUseAliasParsing());
+      local_context.UseAliasParsing());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp
index 69efb48..57fc684 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp
@@ -197,8 +197,8 @@
 
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   do {
-    CSSValue* parsed_transform_value = ConsumeTransformValue(
-        range, &context, local_context.GetUseAliasParsing());
+    CSSValue* parsed_transform_value =
+        ConsumeTransformValue(range, &context, local_context.UseAliasParsing());
     if (!parsed_transform_value)
       return nullptr;
     list->Append(*parsed_transform_value);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp
index d1ca80ce..f2ca520 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp
@@ -23,7 +23,7 @@
 
   if (!CSSPropertyShapeUtils::ConsumeRadii(horizontal_radii, vertical_radii,
                                            range, context.Mode(),
-                                           local_context.GetUseAliasParsing()))
+                                           local_context.UseAliasParsing()))
     return false;
 
   CSSPropertyParserHelpers::AddProperty(
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
index 44bfbf5..f2e3d58 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -244,9 +244,9 @@
     StyleResolverState& state) {
   state.Style()->SetNamedGridArea(ComputedStyle::InitialNamedGridArea());
   state.Style()->SetNamedGridAreaRowCount(
-      ComputedStyle::InitialNamedGridAreaCount());
+      ComputedStyle::InitialNamedGridAreaRowCount());
   state.Style()->SetNamedGridAreaColumnCount(
-      ComputedStyle::InitialNamedGridAreaCount());
+      ComputedStyle::InitialNamedGridAreaColumnCount());
 }
 
 void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(
@@ -374,7 +374,7 @@
                                                       const CSSValue& value) {
   state.Style()->ResetPageSizeType();
   FloatSize size;
-  PageSizeType page_size_type = PageSizeType::kAuto;
+  EPageSizeType page_size_type = EPageSizeType::kAuto;
   const CSSValueList& list = ToCSSValueList(value);
   if (list.length() == 2) {
     // <length>{2} | <page-size> <orientation>
@@ -396,14 +396,14 @@
       if (ToCSSIdentifierValue(second).GetValueID() == CSSValueLandscape)
         size = size.TransposedSize();
     }
-    page_size_type = PageSizeType::kResolved;
+    page_size_type = EPageSizeType::kResolved;
   } else {
     DCHECK_EQ(list.length(), 1U);
     // <length> | auto | <page-size> | [ portrait | landscape]
     const CSSValue& first = list.Item(0);
     if (first.IsPrimitiveValue() && ToCSSPrimitiveValue(first).IsLength()) {
       // <length>
-      page_size_type = PageSizeType::kResolved;
+      page_size_type = EPageSizeType::kResolved;
       float width = ToCSSPrimitiveValue(first).ComputeLength<float>(
           state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0));
       size = FloatSize(width, width);
@@ -411,17 +411,17 @@
       const CSSIdentifierValue& ident = ToCSSIdentifierValue(first);
       switch (ident.GetValueID()) {
         case CSSValueAuto:
-          page_size_type = PageSizeType::kAuto;
+          page_size_type = EPageSizeType::kAuto;
           break;
         case CSSValuePortrait:
-          page_size_type = PageSizeType::kPortrait;
+          page_size_type = EPageSizeType::kPortrait;
           break;
         case CSSValueLandscape:
-          page_size_type = PageSizeType::kLandscape;
+          page_size_type = EPageSizeType::kLandscape;
           break;
         default:
           // <page-size>
-          page_size_type = PageSizeType::kResolved;
+          page_size_type = EPageSizeType::kResolved;
           size = GetPageSizeFromName(ident);
       }
     }
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 780fc4a..9296c4f4 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -2428,18 +2428,18 @@
 
   double width = page_size.Width();
   double height = page_size.Height();
-  switch (style->GetPageSizeType()) {
-    case PageSizeType::kAuto:
+  switch (style->PageSizeType()) {
+    case EPageSizeType::kAuto:
       break;
-    case PageSizeType::kLandscape:
+    case EPageSizeType::kLandscape:
       if (width < height)
         std::swap(width, height);
       break;
-    case PageSizeType::kPortrait:
+    case EPageSizeType::kPortrait:
       if (width > height)
         std::swap(width, height);
       break;
-    case PageSizeType::kResolved: {
+    case EPageSizeType::kResolved: {
       FloatSize size = style->PageSize();
       width = size.Width();
       height = size.Height();
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index 07534c1..7adb9b2 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1418,6 +1418,18 @@
   return last_visible.DeprecatedComputePosition();
 }
 
+// Returns true if |box| at |text_offset| can not continue on next line.
+static bool CanNotContinueOnNextLine(const LayoutText& text_layout_object,
+                                     InlineBox* box,
+                                     unsigned text_offset) {
+  InlineTextBox* const last_text_box = text_layout_object.LastTextBox();
+  if (box == last_text_box)
+    return true;
+  return LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem()) ==
+             text_layout_object &&
+         ToInlineTextBox(box)->Start() >= text_offset;
+}
+
 // The text continues on the next line only if the last text box is not on this
 // line and none of the boxes on this line have a larger start offset.
 static bool DoesContinueOnNextLine(const LayoutText& text_layout_object,
@@ -1427,21 +1439,13 @@
   DCHECK_NE(box, last_text_box);
   for (InlineBox* runner = box->NextLeafChild(); runner;
        runner = runner->NextLeafChild()) {
-    if (runner == last_text_box)
-      return false;
-    if (LineLayoutAPIShim::LayoutObjectFrom(runner->GetLineLayoutItem()) ==
-            text_layout_object &&
-        ToInlineTextBox(runner)->Start() >= text_offset)
+    if (CanNotContinueOnNextLine(text_layout_object, runner, text_offset))
       return false;
   }
 
   for (InlineBox* runner = box->PrevLeafChild(); runner;
        runner = runner->PrevLeafChild()) {
-    if (runner == last_text_box)
-      return false;
-    if (LineLayoutAPIShim::LayoutObjectFrom(runner->GetLineLayoutItem()) ==
-            text_layout_object &&
-        ToInlineTextBox(runner)->Start() >= text_offset)
+    if (CanNotContinueOnNextLine(text_layout_object, runner, text_offset))
       return false;
   }
 
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
index 376baa4..f882fb7 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
@@ -231,21 +231,18 @@
         PreviousLeafWithSameEditability(previous_node, editable_type);
   }
 
-  while (previous_node && !previous_node->IsShadowRoot()) {
-    if (HighestEditableRoot(FirstPositionInOrBeforeNode(previous_node),
+  for (Node* runner = previous_node; runner && !runner->IsShadowRoot();
+       runner = PreviousLeafWithSameEditability(runner, editable_type)) {
+    if (HighestEditableRoot(FirstPositionInOrBeforeNode(runner),
                             editable_type) != highest_root)
       break;
 
-    Position pos = isHTMLBRElement(*previous_node)
-                       ? Position::BeforeNode(previous_node)
-                       : Position::EditingPositionOf(
-                             previous_node, CaretMaxOffset(previous_node));
-
-    if (IsVisuallyEquivalentCandidate(pos))
-      return pos;
-
-    previous_node =
-        PreviousLeafWithSameEditability(previous_node, editable_type);
+    const Position& candidate =
+        isHTMLBRElement(*runner)
+            ? Position::BeforeNode(runner)
+            : Position::EditingPositionOf(runner, CaretMaxOffset(runner));
+    if (IsVisuallyEquivalentCandidate(candidate))
+      return candidate;
   }
   return Position();
 }
@@ -261,18 +258,16 @@
   while (next_node && InSameLine(*next_node, visible_position))
     next_node = NextLeafWithSameEditability(next_node, kContentIsEditable);
 
-  while (next_node && !next_node->IsShadowRoot()) {
-    if (HighestEditableRoot(FirstPositionInOrBeforeNode(next_node),
+  for (Node* runner = next_node; runner && !runner->IsShadowRoot();
+       runner = NextLeafWithSameEditability(runner, editable_type)) {
+    if (HighestEditableRoot(FirstPositionInOrBeforeNode(runner),
                             editable_type) != highest_root)
       break;
 
-    Position pos;
-    pos = Position::EditingPositionOf(next_node, CaretMinOffset(next_node));
-
-    if (IsVisuallyEquivalentCandidate(pos))
-      return pos;
-
-    next_node = NextLeafWithSameEditability(next_node, editable_type);
+    const Position& candidate =
+        Position::EditingPositionOf(runner, CaretMinOffset(runner));
+    if (IsVisuallyEquivalentCandidate(candidate))
+      return candidate;
   }
   return Position();
 }
diff --git a/third_party/WebKit/Source/core/exported/BUILD.gn b/third_party/WebKit/Source/core/exported/BUILD.gn
index 133c1eb..ea8ea32 100644
--- a/third_party/WebKit/Source/core/exported/BUILD.gn
+++ b/third_party/WebKit/Source/core/exported/BUILD.gn
@@ -34,6 +34,7 @@
     "WebFormElement.cpp",
     "WebFrame.cpp",
     "WebFrameContentDumper.cpp",
+    "WebFrameSerializer.cpp",
     "WebHeap.cpp",
     "WebHistoryItem.cpp",
     "WebImageCache.cpp",
diff --git a/third_party/WebKit/Source/web/WebFrameSerializer.cpp b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
similarity index 99%
rename from third_party/WebKit/Source/web/WebFrameSerializer.cpp
rename to third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
index 60af38cc..8bcba88de 100644
--- a/third_party/WebKit/Source/web/WebFrameSerializer.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameSerializer.cpp
@@ -40,6 +40,7 @@
 #include "core/frame/FrameSerializer.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/RemoteFrame.h"
+#include "core/frame/WebFrameSerializerImpl.h"
 #include "core/frame/WebLocalFrameBase.h"
 #include "core/html/HTMLAllCollection.h"
 #include "core/html/HTMLFrameElementBase.h"
@@ -75,7 +76,6 @@
 #include "public/web/WebFrame.h"
 #include "public/web/WebFrameSerializerCacheControlPolicy.h"
 #include "public/web/WebFrameSerializerClient.h"
-#include "web/WebFrameSerializerImpl.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn
index dcd6609b..0b8f193c 100644
--- a/third_party/WebKit/Source/core/frame/BUILD.gn
+++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -126,6 +126,8 @@
     "UseCounter.h",
     "VisualViewport.cpp",
     "VisualViewport.h",
+    "WebFrameSerializerImpl.cpp",
+    "WebFrameSerializerImpl.h",
     "WebFrameWidgetBase.cpp",
     "WebFrameWidgetBase.h",
     "WebLocalFrameBase.cpp",
diff --git a/third_party/WebKit/Source/web/WebFrameSerializerImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp
similarity index 99%
rename from third_party/WebKit/Source/web/WebFrameSerializerImpl.cpp
rename to third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp
index 92a47a79..d25c930 100644
--- a/third_party/WebKit/Source/web/WebFrameSerializerImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.cpp
@@ -75,7 +75,7 @@
 // override the incorrect base URL and make sure we alway load correct local
 // saved resource files.
 
-#include "web/WebFrameSerializerImpl.h"
+#include "core/frame/WebFrameSerializerImpl.h"
 
 #include "core/HTMLNames.h"
 #include "core/dom/Document.h"
diff --git a/third_party/WebKit/Source/web/WebFrameSerializerImpl.h b/third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.h
similarity index 100%
rename from third_party/WebKit/Source/web/WebFrameSerializerImpl.h
rename to third_party/WebKit/Source/core/frame/WebFrameSerializerImpl.h
diff --git a/third_party/WebKit/Source/core/html/HTMLTableCellElement.h b/third_party/WebKit/Source/core/html/HTMLTableCellElement.h
index de45ef51..cb02550 100644
--- a/third_party/WebKit/Source/core/html/HTMLTableCellElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLTableCellElement.h
@@ -50,15 +50,11 @@
   const AtomicString& Headers() const;
   void setRowSpan(unsigned);
 
-  // Rowspan: match Firefox's limit of 65,534. Edge has a higher limit, at
-  // least 2^17.
-  // Colspan: Firefox uses a limit of 1,000 for colspan and resets the value to
-  // 1.
-  // TODO(dgrogan): Change these to HTML's new specified behavior when
-  // https://github.com/whatwg/html/issues/1198 is resolved.
-  // Public so that HTMLColElement can use maxColSpan. maxRowSpan is only used
-  // by this class but keeping them together seems desirable.
-  static unsigned MaxColSpan() { return 8190u; }
+  // Public so that HTMLTableColElement can use MaxColSpan. MaxRowSpan is only
+  // used by this class but keeping them together seems desirable.
+  // https://html.spec.whatwg.org/#dom-tdth-colspan
+  static unsigned MaxColSpan() { return 1000u; }
+  // https://html.spec.whatwg.org/#dom-tdth-rowspan
   static unsigned MaxRowSpan() { return 65534u; }
 
  private:
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 18c45f98..cd339bcc 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -4266,7 +4266,7 @@
       IsWritingModeRoot() || Style()->Display() == EDisplay::kFlowRoot ||
       Style()->ContainsPaint() || Style()->ContainsLayout() ||
       Style()->SpecifiesColumns() ||
-      Style()->GetColumnSpan() == kColumnSpanAll) {
+      Style()->GetColumnSpan() == EColumnSpan::kAll) {
     // The specs require this object to establish a new formatting context.
     return true;
   }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 1e3b17b..72973e0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2692,9 +2692,10 @@
 
   // FIXME: Account for writing-mode in flexible boxes.
   // https://bugs.webkit.org/show_bug.cgi?id=46418
-  bool in_vertical_box = Parent()->IsDeprecatedFlexibleBox() &&
-                         (Parent()->Style()->BoxOrient() == VERTICAL);
-  bool stretching = (Parent()->Style()->BoxAlign() == BSTRETCH);
+  bool in_vertical_box =
+      Parent()->IsDeprecatedFlexibleBox() &&
+      (Parent()->Style()->BoxOrient() == EBoxOrient::kVertical);
+  bool stretching = (Parent()->Style()->BoxAlign() == EBoxAlignment::kStretch);
   // TODO (lajava): Stretching is the only reason why we don't want the box to
   // be treated as a replaced element, so we could perhaps refactor all this
   // logic, not only for flex and grid since alignment is intended to be applied
@@ -2904,8 +2905,8 @@
 bool LayoutBox::IsStretchingColumnFlexItem() const {
   LayoutObject* parent = this->Parent();
   if (parent->IsDeprecatedFlexibleBox() &&
-      parent->Style()->BoxOrient() == VERTICAL &&
-      parent->Style()->BoxAlign() == BSTRETCH)
+      parent->Style()->BoxOrient() == EBoxOrient::kVertical &&
+      parent->Style()->BoxAlign() == EBoxAlignment::kStretch)
     return true;
 
   // We don't stretch multiline flexboxes because they need to apply line
@@ -2971,8 +2972,8 @@
   // FIXME: Think about writing-mode here.
   // https://bugs.webkit.org/show_bug.cgi?id=46473
   if (Parent()->IsDeprecatedFlexibleBox() &&
-      (Parent()->Style()->BoxOrient() == HORIZONTAL ||
-       Parent()->Style()->BoxAlign() != BSTRETCH))
+      (Parent()->Style()->BoxOrient() == EBoxOrient::kHorizontal ||
+       Parent()->Style()->BoxAlign() != EBoxAlignment::kStretch))
     return true;
 
   // Button, input, select, textarea, and legend treat width value of 'auto' as
@@ -3182,9 +3183,10 @@
 
     // FIXME: Account for writing-mode in flexible boxes.
     // https://bugs.webkit.org/show_bug.cgi?id=46418
-    bool in_horizontal_box = Parent()->IsDeprecatedFlexibleBox() &&
-                             Parent()->Style()->BoxOrient() == HORIZONTAL;
-    bool stretching = Parent()->Style()->BoxAlign() == BSTRETCH;
+    bool in_horizontal_box =
+        Parent()->IsDeprecatedFlexibleBox() &&
+        Parent()->Style()->BoxOrient() == EBoxOrient::kHorizontal;
+    bool stretching = Parent()->Style()->BoxAlign() == EBoxAlignment::kStretch;
     bool treat_as_replaced =
         ShouldComputeSizeAsReplaced() && (!in_horizontal_box || !stretching);
     bool check_min_max_height = false;
diff --git a/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.cpp
index 08dc8f7..0b07bd9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.cpp
@@ -41,7 +41,7 @@
  public:
   FlexBoxIterator(LayoutDeprecatedFlexibleBox* parent)
       : box_(parent), largest_ordinal_(1) {
-    if (box_->Style()->BoxOrient() == HORIZONTAL &&
+    if (box_->Style()->BoxOrient() == EBoxOrient::kHorizontal &&
         !box_->Style()->IsLeftToRightDirection())
       forward_ = box_->Style()->BoxDirection() != EBoxDirection::kNormal;
     else
@@ -380,8 +380,8 @@
 
     if (previous_size != Size() ||
         (Parent()->IsDeprecatedFlexibleBox() &&
-         Parent()->Style()->BoxOrient() == HORIZONTAL &&
-         Parent()->Style()->BoxAlign() == BSTRETCH))
+         Parent()->Style()->BoxOrient() == EBoxOrient::kHorizontal &&
+         Parent()->Style()->BoxAlign() == EBoxAlignment::kStretch))
       relayout_children = true;
 
     SetHeight(LayoutUnit());
@@ -493,7 +493,7 @@
       child->LayoutIfNeeded();
 
       // Update our height and overflow height.
-      if (Style()->BoxAlign() == BBASELINE) {
+      if (Style()->BoxAlign() == EBoxAlignment::kBaseline) {
         LayoutUnit ascent(child->FirstLineBoxBaseline());
         if (ascent == -1)
           ascent = child->Size().Height() + child->MarginBottom();
@@ -535,7 +535,7 @@
       height_specified = true;
 
     // Now that our height is actually known, we can place our boxes.
-    stretching_children_ = (Style()->BoxAlign() == BSTRETCH);
+    stretching_children_ = (Style()->BoxAlign() == EBoxAlignment::kStretch);
     for (LayoutBox* child = iterator.First(); child; child = iterator.Next()) {
       if (child->IsOutOfFlowPositioned()) {
         child->ContainingBlock()->InsertPositionedObject(child);
@@ -581,14 +581,14 @@
       x_pos += child->MarginLeft();
       LayoutUnit child_y = y_pos;
       switch (Style()->BoxAlign()) {
-        case BCENTER:
+        case EBoxAlignment::kCenter:
           child_y += child->MarginTop() +
                      ((ContentHeight() -
                        (child->Size().Height() + child->MarginHeight())) /
                       2)
                          .ClampNegativeToZero();
           break;
-        case BBASELINE: {
+        case EBoxAlignment::kBaseline: {
           LayoutUnit ascent(child->FirstLineBoxBaseline());
           if (ascent == -1)
             ascent = child->Size().Height() + child->MarginBottom();
@@ -596,7 +596,7 @@
           child_y += child->MarginTop() + (max_ascent - ascent);
           break;
         }
-        case BEND:
+        case EBoxAlignment::kBend:
           child_y +=
               ContentHeight() - child->MarginBottom() - child->Size().Height();
           break;
@@ -724,12 +724,12 @@
   } while (have_flex);
 
   if (remaining_space > 0 && ((Style()->IsLeftToRightDirection() &&
-                               Style()->BoxPack() != kBoxPackStart) ||
+                               Style()->BoxPack() != EBoxPack::kStart) ||
                               (!Style()->IsLeftToRightDirection() &&
-                               Style()->BoxPack() != kBoxPackEnd))) {
+                               Style()->BoxPack() != EBoxPack::kEnd))) {
     // Children must be repositioned.
     LayoutUnit offset;
-    if (Style()->BoxPack() == kBoxPackJustify) {
+    if (Style()->BoxPack() == EBoxPack::kJustify) {
       // Determine the total number of children.
       int total_children = 0;
       for (LayoutBox* child = iterator.First(); child;
@@ -763,7 +763,7 @@
         }
       }
     } else {
-      if (Style()->BoxPack() == kBoxPackCenter)
+      if (Style()->BoxPack() == EBoxPack::kCenter)
         offset += remaining_space / 2;
       else  // END for LTR, START for RTL
         offset += remaining_space;
@@ -861,15 +861,16 @@
       // We can place the child now, using our value of box-align.
       LayoutUnit child_x = BorderLeft() + PaddingLeft();
       switch (Style()->BoxAlign()) {
-        case BCENTER:
-        case BBASELINE:  // Baseline just maps to center for vertical boxes
+        case EBoxAlignment::kCenter:
+        case EBoxAlignment::kBaseline:  // Baseline just maps to center for
+                                        // vertical boxes
           child_x += child->MarginLeft() +
                      ((ContentWidth() -
                        (child->Size().Width() + child->MarginWidth())) /
                       2)
                          .ClampNegativeToZero();
           break;
-        case BEND:
+        case EBoxAlignment::kBend:
           if (!Style()->IsLeftToRightDirection()) {
             child_x += child->MarginLeft();
           } else {
@@ -1030,10 +1031,10 @@
     }
   } while (have_flex);
 
-  if (Style()->BoxPack() != kBoxPackStart && remaining_space > 0) {
+  if (Style()->BoxPack() != EBoxPack::kStart && remaining_space > 0) {
     // Children must be repositioned.
     LayoutUnit offset;
-    if (Style()->BoxPack() == kBoxPackJustify) {
+    if (Style()->BoxPack() == EBoxPack::kJustify) {
       // Determine the total number of children.
       int total_children = 0;
       for (LayoutBox* child = iterator.First(); child;
@@ -1067,7 +1068,7 @@
         }
       }
     } else {
-      if (Style()->BoxPack() == kBoxPackCenter)
+      if (Style()->BoxPack() == EBoxPack::kCenter)
         offset += remaining_space / 2;
       else  // END
         offset += remaining_space;
diff --git a/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.h
index 7dfc6e4..97aa36e8 100644
--- a/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutDeprecatedFlexibleBox.h
@@ -55,9 +55,15 @@
 
   LayoutUnit AllowedChildFlex(LayoutBox* child, bool expanding, unsigned group);
 
-  bool HasMultipleLines() const { return Style()->BoxLines() == MULTIPLE; }
-  bool IsVertical() const { return Style()->BoxOrient() == VERTICAL; }
-  bool IsHorizontal() const { return Style()->BoxOrient() == HORIZONTAL; }
+  bool HasMultipleLines() const {
+    return Style()->BoxLines() == EBoxLines::kMultiple;
+  }
+  bool IsVertical() const {
+    return Style()->BoxOrient() == EBoxOrient::kVertical;
+  }
+  bool IsHorizontal() const {
+    return Style()->BoxOrient() == EBoxOrient::kHorizontal;
+  }
 
   void ApplyLineClamp(FlexBoxIterator&, bool relayout_children);
   void ClearLineClamp();
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 5e78690..0a9fda1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -275,7 +275,7 @@
   TextDirection text_direction = Style()->Direction();
   WritingMode writing_mode = Style()->GetWritingMode();
 
-  if (flex_direction == kFlowRow) {
+  if (flex_direction == EFlexDirection::kRow) {
     if (text_direction == TextDirection::kRtl) {
       if (blink::IsHorizontalWritingMode(writing_mode))
         size.Expand(adjustment_width, 0);
@@ -284,7 +284,7 @@
     }
     if (IsFlippedBlocksWritingMode(writing_mode))
       size.Expand(adjustment_width, 0);
-  } else if (flex_direction == kFlowRowReverse) {
+  } else if (flex_direction == EFlexDirection::kRowReverse) {
     if (text_direction == TextDirection::kLtr) {
       if (blink::IsHorizontalWritingMode(writing_mode))
         size.Expand(adjustment_width, 0);
@@ -293,7 +293,7 @@
     }
     if (IsFlippedBlocksWritingMode(writing_mode))
       size.Expand(adjustment_width, 0);
-  } else if (flex_direction == kFlowColumn) {
+  } else if (flex_direction == EFlexDirection::kColumn) {
     if (IsFlippedBlocksWritingMode(writing_mode))
       size.Expand(adjustment_width, 0);
   } else {
@@ -308,17 +308,20 @@
 bool LayoutFlexibleBox::HasTopOverflow() const {
   EFlexDirection flex_direction = Style()->FlexDirection();
   if (IsHorizontalWritingMode())
-    return flex_direction == kFlowColumnReverse;
-  return flex_direction ==
-         (Style()->IsLeftToRightDirection() ? kFlowRowReverse : kFlowRow);
+    return flex_direction == EFlexDirection::kColumnReverse;
+  return flex_direction == (Style()->IsLeftToRightDirection()
+                                ? EFlexDirection::kRowReverse
+                                : EFlexDirection::kRow);
 }
 
 bool LayoutFlexibleBox::HasLeftOverflow() const {
   EFlexDirection flex_direction = Style()->FlexDirection();
-  if (IsHorizontalWritingMode())
-    return flex_direction ==
-           (Style()->IsLeftToRightDirection() ? kFlowRowReverse : kFlowRow);
-  return flex_direction == kFlowColumnReverse;
+  if (IsHorizontalWritingMode()) {
+    return flex_direction == (Style()->IsLeftToRightDirection()
+                                  ? EFlexDirection::kRowReverse
+                                  : EFlexDirection::kRow);
+  }
+  return flex_direction == EFlexDirection::kColumnReverse;
 }
 
 void LayoutFlexibleBox::RemoveChild(LayoutObject* child) {
@@ -470,7 +473,7 @@
            IsFlippedLinesWritingMode(Style()->GetWritingMode());
   }
   return Style()->IsLeftToRightDirection() ^
-         (Style()->FlexDirection() == kFlowRowReverse);
+         (Style()->FlexDirection() == EFlexDirection::kRowReverse);
 }
 
 bool LayoutFlexibleBox::IsMultiline() const {
@@ -1628,8 +1631,8 @@
 
   LayoutUnit offset = InitialContentPositionOffset(available_space,
                                                    ResolvedJustifyContent(), 1);
-  if (StyleRef().FlexDirection() == kFlowRowReverse ||
-      StyleRef().FlexDirection() == kFlowColumnReverse)
+  if (StyleRef().FlexDirection() == EFlexDirection::kRowReverse ||
+      StyleRef().FlexDirection() == EFlexDirection::kColumnReverse)
     offset = available_space - offset;
   return offset;
 }
@@ -1806,7 +1809,7 @@
       FlowAwareBorderStart() + FlowAwarePaddingStart();
   main_axis_offset += InitialContentPositionOffset(
       available_free_space, justify_content, children.size());
-  if (Style()->FlexDirection() == kFlowRowReverse &&
+  if (Style()->FlexDirection() == EFlexDirection::kRowReverse &&
       ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
     main_axis_offset += IsHorizontalFlow() ? VerticalScrollbarWidth()
                                            : HorizontalScrollbarHeight();
@@ -1915,7 +1918,7 @@
         LogicalHeight(), main_axis_offset + FlowAwareBorderEnd() +
                              FlowAwarePaddingEnd() + ScrollbarLogicalHeight()));
 
-  if (Style()->FlexDirection() == kFlowColumnReverse) {
+  if (Style()->FlexDirection() == EFlexDirection::kColumnReverse) {
     // We have to do an extra pass for column-reverse to reposition the flex
     // items since the start depends on the height of the flexbox, which we
     // only know after we've positioned all the flex items.
diff --git a/third_party/WebKit/Source/core/layout/LayoutFullScreen.cpp b/third_party/WebKit/Source/core/layout/LayoutFullScreen.cpp
index 73c1d1f..b2d2956 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFullScreen.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFullScreen.cpp
@@ -108,7 +108,7 @@
   // Alignment (align-items) value can't be used to resolve its children Self
   // Alignment 'auto' values.
   fullscreen_style->SetAlignItemsPosition(kItemPositionCenter);
-  fullscreen_style->SetFlexDirection(kFlowColumn);
+  fullscreen_style->SetFlexDirection(EFlexDirection::kColumn);
 
   fullscreen_style->SetPosition(EPosition::kFixed);
   fullscreen_style->SetLeft(Length(0, blink::kFixed));
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
index 0353e31..729b6df5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
@@ -868,7 +868,7 @@
 
   // The spec says that column-span only applies to in-flow block-level
   // elements.
-  if (descendant->Style()->GetColumnSpan() != kColumnSpanAll ||
+  if (descendant->Style()->GetColumnSpan() != EColumnSpan::kAll ||
       !descendant->IsBox() || descendant->IsInline() ||
       descendant->IsFloatingOrOutOfFlowPositioned())
     return false;
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp
index dd06356f..0a34e82 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp
@@ -346,7 +346,8 @@
     // 'balance' - in accordance with the spec).
     // Pretending that column-fill is auto also matches the old multicol
     // implementation, which has no support for this property.
-    if (MultiColumnBlockFlow()->Style()->GetColumnFill() == kColumnFillBalance)
+    if (MultiColumnBlockFlow()->Style()->GetColumnFill() ==
+        EColumnFill::kBalance)
       return true;
     if (LayoutBox* next = NextSiblingBox()) {
       if (next->IsLayoutMultiColumnSpannerPlaceholder()) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index f105f1e..3b136db 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -925,7 +925,8 @@
     return nullptr;
   }
   bool IsColumnSpanAll() const {
-    return Style()->GetColumnSpan() == kColumnSpanAll && SpannerPlaceholder();
+    return Style()->GetColumnSpan() == EColumnSpan::kAll &&
+           SpannerPlaceholder();
   }
 
   // We include isLayoutButton() in this check, because buttons are
diff --git a/third_party/WebKit/Source/core/layout/LayoutSliderContainer.cpp b/third_party/WebKit/Source/core/layout/LayoutSliderContainer.cpp
index fc4b6f2d..8bda11e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutSliderContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutSliderContainer.cpp
@@ -99,7 +99,8 @@
 void LayoutSliderContainer::UpdateLayout() {
   HTMLInputElement* input = toHTMLInputElement(GetNode()->OwnerShadowHost());
   bool is_vertical = HasVerticalAppearance(input);
-  MutableStyleRef().SetFlexDirection(is_vertical ? kFlowColumn : kFlowRow);
+  MutableStyleRef().SetFlexDirection(is_vertical ? EFlexDirection::kColumn
+                                                 : EFlexDirection::kRow);
   TextDirection old_text_direction = Style()->Direction();
   if (is_vertical) {
     // FIXME: Work around rounding issues in RTL vertical sliders. We want them
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp
index 8ae6c8c..07a57bc 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp
@@ -90,12 +90,12 @@
 
 TEST_F(LayoutTableCellTest, ResetColspanIfTooBig) {
   SetBodyInnerHTML("<table><td id='cell' colspan='14000'></td></table>");
-  ASSERT_EQ(GetCellByElementId("cell")->ColSpan(), 8190U);
+  ASSERT_EQ(GetCellByElementId("cell")->ColSpan(), 1000U);
 }
 
 TEST_F(LayoutTableCellTest, DoNotResetColspanJustBelowBoundary) {
-  SetBodyInnerHTML("<table><td id='cell' colspan='8190'></td></table>");
-  ASSERT_EQ(GetCellByElementId("cell")->ColSpan(), 8190U);
+  SetBodyInnerHTML("<table><td id='cell' colspan='1000'></td></table>");
+  ASSERT_EQ(GetCellByElementId("cell")->ColSpan(), 1000U);
 }
 
 TEST_F(LayoutTableCellTest, ResetRowspanIfTooBig) {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index c698908..4b75a33 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -2197,21 +2197,6 @@
   return false;
 }
 
-static inline Vector<GridTrackSize> InitialGridAutoTracks() {
-  Vector<GridTrackSize> track_size_list;
-  track_size_list.ReserveInitialCapacity(1);
-  track_size_list.UncheckedAppend(GridTrackSize(Length(kAuto)));
-  return track_size_list;
-}
-
-Vector<GridTrackSize> ComputedStyle::InitialGridAutoColumns() {
-  return InitialGridAutoTracks();
-}
-
-Vector<GridTrackSize> ComputedStyle::InitialGridAutoRows() {
-  return InitialGridAutoTracks();
-}
-
 int AdjustForAbsoluteZoom(int value, float zoom_factor) {
   if (zoom_factor == 1)
     return value;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 5b45b5a..ea878fe 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -626,14 +626,14 @@
   }
 
   // column-fill
-  static ColumnFill InitialColumnFill() { return kColumnFillBalance; }
-  ColumnFill GetColumnFill() const {
-    return static_cast<ColumnFill>(
+  static EColumnFill InitialColumnFill() { return EColumnFill::kBalance; }
+  EColumnFill GetColumnFill() const {
+    return static_cast<EColumnFill>(
         rare_non_inherited_data_->multi_col_data_->column_fill_);
   }
-  void SetColumnFill(ColumnFill column_fill) {
+  void SetColumnFill(EColumnFill column_fill) {
     SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_fill_,
-                   column_fill);
+                   static_cast<unsigned>(column_fill));
   }
 
   // column-gap (aka -webkit-column-gap)
@@ -685,14 +685,14 @@
   }
 
   // column-span (aka -webkit-column-span)
-  static ColumnSpan InitialColumnSpan() { return kColumnSpanNone; }
-  ColumnSpan GetColumnSpan() const {
-    return static_cast<ColumnSpan>(
+  static EColumnSpan InitialColumnSpan() { return EColumnSpan::kNone; }
+  EColumnSpan GetColumnSpan() const {
+    return static_cast<EColumnSpan>(
         rare_non_inherited_data_->multi_col_data_->column_span_);
   }
-  void SetColumnSpan(ColumnSpan column_span) {
+  void SetColumnSpan(EColumnSpan column_span) {
     SET_NESTED_VAR(rare_non_inherited_data_, multi_col_data_, column_span_,
-                   column_span);
+                   static_cast<unsigned>(column_span));
   }
 
   // column-width (aka -webkit-column-width)
@@ -740,14 +740,14 @@
   }
 
   // flex-direction (aka -webkit-flex-direction)
-  static EFlexDirection InitialFlexDirection() { return kFlowRow; }
+  static EFlexDirection InitialFlexDirection() { return EFlexDirection::kRow; }
   EFlexDirection FlexDirection() const {
     return static_cast<EFlexDirection>(
         rare_non_inherited_data_->flexible_box_data_->flex_direction_);
   }
   void SetFlexDirection(EFlexDirection direction) {
     SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_,
-                   flex_direction_, direction);
+                   flex_direction_, static_cast<unsigned>(direction));
   }
 
   // flex-grow (aka -webkit-flex-grow)
@@ -782,25 +782,25 @@
   // -webkit-box-align
   // For valid values of box-align see
   // http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment
-  static EBoxAlignment InitialBoxAlign() { return BSTRETCH; }
+  static EBoxAlignment InitialBoxAlign() { return EBoxAlignment::kStretch; }
   EBoxAlignment BoxAlign() const {
     return static_cast<EBoxAlignment>(
         rare_non_inherited_data_->deprecated_flexible_box_data_->box_align_);
   }
   void SetBoxAlign(EBoxAlignment a) {
     SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
-                   box_align_, a);
+                   box_align_, static_cast<unsigned>(a));
   }
 
   // -webkit-box-lines
-  static EBoxLines InitialBoxLines() { return SINGLE; }
+  static EBoxLines InitialBoxLines() { return EBoxLines::kSingle; }
   EBoxLines BoxLines() const {
     return static_cast<EBoxLines>(
         rare_non_inherited_data_->deprecated_flexible_box_data_->box_lines_);
   }
   void SetBoxLines(EBoxLines lines) {
     SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
-                   box_lines_, lines);
+                   box_lines_, static_cast<unsigned>(lines));
   }
 
   // -webkit-box-ordinal-group
@@ -816,25 +816,25 @@
   }
 
   // -webkit-box-orient
-  static EBoxOrient InitialBoxOrient() { return HORIZONTAL; }
+  static EBoxOrient InitialBoxOrient() { return EBoxOrient::kHorizontal; }
   EBoxOrient BoxOrient() const {
     return static_cast<EBoxOrient>(
         rare_non_inherited_data_->deprecated_flexible_box_data_->box_orient_);
   }
   void SetBoxOrient(EBoxOrient o) {
     SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
-                   box_orient_, o);
+                   box_orient_, static_cast<unsigned>(o));
   }
 
   // -webkit-box-pack
-  static EBoxPack InitialBoxPack() { return kBoxPackStart; }
+  static EBoxPack InitialBoxPack() { return EBoxPack::kStart; }
   EBoxPack BoxPack() const {
     return static_cast<EBoxPack>(
         rare_non_inherited_data_->deprecated_flexible_box_data_->box_pack_);
   }
   void SetBoxPack(EBoxPack p) {
     SET_NESTED_VAR(rare_non_inherited_data_, deprecated_flexible_box_data_,
-                   box_pack_, p);
+                   box_pack_, static_cast<unsigned>(p));
   }
 
   // -webkit-box-reflect
@@ -848,35 +848,8 @@
   }
 
   // Grid properties.
-  static Vector<GridTrackSize> InitialGridAutoRepeatTracks() {
-    return Vector<GridTrackSize>(); /* none */
-  }
   static size_t InitialGridAutoRepeatInsertionPoint() { return 0; }
   static AutoRepeatType InitialGridAutoRepeatType() { return kNoAutoRepeat; }
-  static NamedGridLinesMap InitialNamedGridColumnLines() {
-    return NamedGridLinesMap();
-  }
-  static NamedGridLinesMap InitialNamedGridRowLines() {
-    return NamedGridLinesMap();
-  }
-  static OrderedNamedGridLines InitialOrderedNamedGridColumnLines() {
-    return OrderedNamedGridLines();
-  }
-  static OrderedNamedGridLines InitialOrderedNamedGridRowLines() {
-    return OrderedNamedGridLines();
-  }
-  static NamedGridAreaMap InitialNamedGridArea() { return NamedGridAreaMap(); }
-  static size_t InitialNamedGridAreaCount() { return 0; }
-
-  // grid-auto-columns
-  static Vector<GridTrackSize> InitialGridAutoColumns();
-  const Vector<GridTrackSize>& GridAutoColumns() const {
-    return rare_non_inherited_data_->grid_data_->grid_auto_columns_;
-  }
-  void SetGridAutoColumns(const Vector<GridTrackSize>& track_size_list) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_columns_,
-                   track_size_list);
-  }
 
   // grid-auto-flow
   static GridAutoFlow InitialGridAutoFlow() { return kAutoFlowRow; }
@@ -884,104 +857,6 @@
     SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_flow_, flow);
   }
 
-  // grid-auto-rows
-  static Vector<GridTrackSize> InitialGridAutoRows();
-  const Vector<GridTrackSize>& GridAutoRows() const {
-    return rare_non_inherited_data_->grid_data_->grid_auto_rows_;
-  }
-  void SetGridAutoRows(const Vector<GridTrackSize>& track_size_list) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_rows_,
-                   track_size_list);
-  }
-
-  // grid-column-gap
-  static Length InitialGridColumnGap() { return Length(kFixed); }
-  const Length& GridColumnGap() const {
-    return rare_non_inherited_data_->grid_data_->grid_column_gap_;
-  }
-  void SetGridColumnGap(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_column_gap_, v);
-  }
-
-  // grid-column-start
-  static GridPosition InitialGridColumnStart() {
-    return GridPosition(); /* auto */
-  }
-  const GridPosition& GridColumnStart() const {
-    return rare_non_inherited_data_->grid_item_data_->grid_column_start_;
-  }
-  void SetGridColumnStart(const GridPosition& column_start_position) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_,
-                   grid_column_start_, column_start_position);
-  }
-
-  // grid-column-end
-  static GridPosition InitialGridColumnEnd() {
-    return GridPosition(); /* auto */
-  }
-  const GridPosition& GridColumnEnd() const {
-    return rare_non_inherited_data_->grid_item_data_->grid_column_end_;
-  }
-  void SetGridColumnEnd(const GridPosition& column_end_position) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_, grid_column_end_,
-                   column_end_position);
-  }
-
-  // grid-row-gap
-  static Length InitialGridRowGap() { return Length(kFixed); }
-  const Length& GridRowGap() const {
-    return rare_non_inherited_data_->grid_data_->grid_row_gap_;
-  }
-  void SetGridRowGap(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_row_gap_, v);
-  }
-
-  // grid-row-start
-  static GridPosition InitialGridRowStart() {
-    return GridPosition(); /* auto */
-  }
-  const GridPosition& GridRowStart() const {
-    return rare_non_inherited_data_->grid_item_data_->grid_row_start_;
-  }
-  void SetGridRowStart(const GridPosition& row_start_position) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_, grid_row_start_,
-                   row_start_position);
-  }
-
-  // grid-row-end
-  static GridPosition InitialGridRowEnd() { return GridPosition(); /* auto */ }
-  const GridPosition& GridRowEnd() const {
-    return rare_non_inherited_data_->grid_item_data_->grid_row_end_;
-  }
-  void SetGridRowEnd(const GridPosition& row_end_position) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_item_data_, grid_row_end_,
-                   row_end_position);
-  }
-
-  // grid-template-columns
-  static Vector<GridTrackSize> InitialGridTemplateColumns() {
-    return Vector<GridTrackSize>(); /* none */
-  }
-  const Vector<GridTrackSize>& GridTemplateColumns() const {
-    return rare_non_inherited_data_->grid_data_->grid_template_columns_;
-  }
-  void SetGridTemplateColumns(const Vector<GridTrackSize>& lengths) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_template_columns_,
-                   lengths);
-  }
-
-  // grid-template-rows
-  static Vector<GridTrackSize> InitialGridTemplateRows() {
-    return Vector<GridTrackSize>(); /* none */
-  }
-  const Vector<GridTrackSize>& GridTemplateRows() const {
-    return rare_non_inherited_data_->grid_data_->grid_template_rows_;
-  }
-  void SetGridTemplateRows(const Vector<GridTrackSize>& lengths) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_template_rows_,
-                   lengths);
-  }
-
   // mix-blend-mode
   static WebBlendMode InitialBlendMode() { return kWebBlendModeNormal; }
   WebBlendMode BlendMode() const {
@@ -1267,45 +1142,6 @@
                    scroll_snap_type_, b);
   }
 
-  // Scroll Padding properties
-  static Length InitialScrollPadding() { return Length(); }
-
-  // scroll-padding-top
-  const Length& ScrollPaddingTop() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.top;
-  }
-  void SetScrollPaddingTop(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_padding_.top, v);
-  }
-
-  // scroll-padding-bottom
-  const Length& ScrollPaddingBottom() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.bottom;
-  }
-  void SetScrollPaddingBottom(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_padding_.bottom, v);
-  }
-
-  // scroll-padding-left
-  const Length& ScrollPaddingLeft() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.left;
-  }
-  void SetScrollPaddingLeft(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_padding_.left, v);
-  }
-
-  // scroll-padding-right
-  const Length& ScrollPaddingRight() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_padding_.right;
-  }
-  void SetScrollPaddingRight(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_padding_.right, v);
-  }
-
   // scroll-padding-block-start
   const Length& ScrollPaddingBlockStart() const {
     return IsHorizontalWritingMode() ? ScrollPaddingTop() : ScrollPaddingLeft();
@@ -1352,48 +1188,6 @@
       SetScrollPaddingBottom(v);
   }
 
-  // scroll-snap-margin
-  static Length InitialScrollSnapMargin() { return Length(); }
-
-  // scroll-snap-margin-top
-  const Length& ScrollSnapMarginTop() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_.top;
-  }
-  void SetScrollSnapMarginTop(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_snap_margin_.top, v);
-  }
-
-  // scroll-snap-margin-bottom
-  const Length& ScrollSnapMarginBottom() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_
-        .bottom;
-  }
-  void SetScrollSnapMarginBottom(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_snap_margin_.bottom, v);
-  }
-
-  // scroll-snap-margin-left
-  const Length& ScrollSnapMarginLeft() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_
-        .left;
-  }
-  void SetScrollSnapMarginLeft(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_snap_margin_.left, v);
-  }
-
-  // scroll-snap-margin-right
-  const Length& ScrollSnapMarginRight() const {
-    return rare_non_inherited_data_->scroll_snap_data_->scroll_snap_margin_
-        .right;
-  }
-  void SetScrollSnapMarginRight(const Length& v) {
-    SET_NESTED_VAR(rare_non_inherited_data_, scroll_snap_data_,
-                   scroll_snap_margin_.right, v);
-  }
-
   // scroll-snap-margin-block-start
   const Length& ScrollSnapMarginBlockStart() const {
     return IsHorizontalWritingMode() ? ScrollSnapMarginTop()
@@ -1478,21 +1272,6 @@
     return DataEquivalent(ShapeOutside(), other.ShapeOutside());
   }
 
-  // size
-  const FloatSize& PageSize() const {
-    return rare_non_inherited_data_->page_size_;
-  }
-  PageSizeType GetPageSizeType() const {
-    return static_cast<PageSizeType>(rare_non_inherited_data_->page_size_type_);
-  }
-  void SetPageSize(const FloatSize& s) {
-    SET_VAR(rare_non_inherited_data_, page_size_, s);
-  }
-  void SetPageSizeType(PageSizeType t) {
-    SET_VAR(rare_non_inherited_data_, page_size_type_,
-            static_cast<unsigned>(t));
-  }
-
   // Text decoration properties.
   // text-decoration-line
   static TextDecoration InitialTextDecoration() {
@@ -2030,12 +1809,12 @@
 
   // Flex utility functions.
   bool IsColumnFlexDirection() const {
-    return FlexDirection() == kFlowColumn ||
-           FlexDirection() == kFlowColumnReverse;
+    return FlexDirection() == EFlexDirection::kColumn ||
+           FlexDirection() == EFlexDirection::kColumnReverse;
   }
   bool IsReverseFlexDirection() const {
-    return FlexDirection() == kFlowRowReverse ||
-           FlexDirection() == kFlowColumnReverse;
+    return FlexDirection() == EFlexDirection::kRowReverse ||
+           FlexDirection() == EFlexDirection::kColumnReverse;
   }
   bool HasBoxReflect() const { return BoxReflect(); }
   bool ReflectionDataEquivalent(const ComputedStyle& other) const {
@@ -2079,65 +1858,13 @@
   bool HasTextCombine() const { return TextCombine() != ETextCombine::kNone; }
 
   // Grid utility functions.
-  const Vector<GridTrackSize>& GridAutoRepeatColumns() const {
-    return rare_non_inherited_data_->grid_data_->grid_auto_repeat_columns_;
-  }
-  const Vector<GridTrackSize>& GridAutoRepeatRows() const {
-    return rare_non_inherited_data_->grid_data_->grid_auto_repeat_rows_;
-  }
-  size_t GridAutoRepeatColumnsInsertionPoint() const {
-    return rare_non_inherited_data_->grid_data_
-        ->auto_repeat_columns_insertion_point_;
-  }
-  size_t GridAutoRepeatRowsInsertionPoint() const {
-    return rare_non_inherited_data_->grid_data_
-        ->auto_repeat_rows_insertion_point_;
-  }
   AutoRepeatType GridAutoRepeatColumnsType() const {
     return static_cast<AutoRepeatType>(
-        rare_non_inherited_data_->grid_data_->auto_repeat_columns_type_);
+        rare_non_inherited_data_->grid_data_->grid_auto_repeat_columns_type_);
   }
   AutoRepeatType GridAutoRepeatRowsType() const {
     return static_cast<AutoRepeatType>(
-        rare_non_inherited_data_->grid_data_->auto_repeat_rows_type_);
-  }
-  const NamedGridLinesMap& NamedGridColumnLines() const {
-    return rare_non_inherited_data_->grid_data_->named_grid_column_lines_;
-  }
-  const NamedGridLinesMap& NamedGridRowLines() const {
-    return rare_non_inherited_data_->grid_data_->named_grid_row_lines_;
-  }
-  const OrderedNamedGridLines& OrderedNamedGridColumnLines() const {
-    return rare_non_inherited_data_->grid_data_
-        ->ordered_named_grid_column_lines_;
-  }
-  const OrderedNamedGridLines& OrderedNamedGridRowLines() const {
-    return rare_non_inherited_data_->grid_data_->ordered_named_grid_row_lines_;
-  }
-  const NamedGridLinesMap& AutoRepeatNamedGridColumnLines() const {
-    return rare_non_inherited_data_->grid_data_
-        ->auto_repeat_named_grid_column_lines_;
-  }
-  const NamedGridLinesMap& AutoRepeatNamedGridRowLines() const {
-    return rare_non_inherited_data_->grid_data_
-        ->auto_repeat_named_grid_row_lines_;
-  }
-  const OrderedNamedGridLines& AutoRepeatOrderedNamedGridColumnLines() const {
-    return rare_non_inherited_data_->grid_data_
-        ->auto_repeat_ordered_named_grid_column_lines_;
-  }
-  const OrderedNamedGridLines& AutoRepeatOrderedNamedGridRowLines() const {
-    return rare_non_inherited_data_->grid_data_
-        ->auto_repeat_ordered_named_grid_row_lines_;
-  }
-  const NamedGridAreaMap& NamedGridArea() const {
-    return rare_non_inherited_data_->grid_data_->named_grid_area_;
-  }
-  size_t NamedGridAreaRowCount() const {
-    return rare_non_inherited_data_->grid_data_->named_grid_area_row_count_;
-  }
-  size_t NamedGridAreaColumnCount() const {
-    return rare_non_inherited_data_->grid_data_->named_grid_area_column_count_;
+        rare_non_inherited_data_->grid_data_->grid_auto_repeat_rows_type_);
   }
   GridAutoFlow GetGridAutoFlow() const {
     return static_cast<GridAutoFlow>(
@@ -2161,84 +1888,13 @@
     return (rare_non_inherited_data_->grid_data_->grid_auto_flow_ &
             kInternalAutoFlowAlgorithmDense) == kInternalAutoFlowAlgorithmDense;
   }
-  void SetGridAutoRepeatColumns(const Vector<GridTrackSize>& track_sizes) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   grid_auto_repeat_columns_, track_sizes);
-  }
-  void SetGridAutoRepeatRows(const Vector<GridTrackSize>& track_sizes) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_repeat_rows_,
-                   track_sizes);
-  }
-  void SetGridAutoRepeatColumnsInsertionPoint(const size_t insertion_point) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_columns_insertion_point_, insertion_point);
-  }
-  void SetGridAutoRepeatRowsInsertionPoint(const size_t insertion_point) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_rows_insertion_point_, insertion_point);
-  }
   void SetGridAutoRepeatColumnsType(const AutoRepeatType auto_repeat_type) {
     SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_columns_type_, auto_repeat_type);
+                   grid_auto_repeat_columns_type_, auto_repeat_type);
   }
   void SetGridAutoRepeatRowsType(const AutoRepeatType auto_repeat_type) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, auto_repeat_rows_type_,
-                   auto_repeat_type);
-  }
-  void SetNamedGridColumnLines(
-      const NamedGridLinesMap& named_grid_column_lines) {
     SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   named_grid_column_lines_, named_grid_column_lines);
-  }
-  void SetNamedGridRowLines(const NamedGridLinesMap& named_grid_row_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, named_grid_row_lines_,
-                   named_grid_row_lines);
-  }
-  void SetOrderedNamedGridColumnLines(
-      const OrderedNamedGridLines& ordered_named_grid_column_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   ordered_named_grid_column_lines_,
-                   ordered_named_grid_column_lines);
-  }
-  void SetOrderedNamedGridRowLines(
-      const OrderedNamedGridLines& ordered_named_grid_row_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   ordered_named_grid_row_lines_, ordered_named_grid_row_lines);
-  }
-  void SetAutoRepeatNamedGridColumnLines(
-      const NamedGridLinesMap& named_grid_column_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_named_grid_column_lines_,
-                   named_grid_column_lines);
-  }
-  void SetAutoRepeatNamedGridRowLines(
-      const NamedGridLinesMap& named_grid_row_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_named_grid_row_lines_, named_grid_row_lines);
-  }
-  void SetAutoRepeatOrderedNamedGridColumnLines(
-      const OrderedNamedGridLines& ordered_named_grid_column_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_ordered_named_grid_column_lines_,
-                   ordered_named_grid_column_lines);
-  }
-  void SetAutoRepeatOrderedNamedGridRowLines(
-      const OrderedNamedGridLines& ordered_named_grid_row_lines) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   auto_repeat_ordered_named_grid_row_lines_,
-                   ordered_named_grid_row_lines);
-  }
-  void SetNamedGridArea(const NamedGridAreaMap& named_grid_area) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, named_grid_area_,
-                   named_grid_area);
-  }
-  void SetNamedGridAreaRowCount(size_t row_count) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   named_grid_area_row_count_, row_count);
-  }
-  void SetNamedGridAreaColumnCount(size_t column_count) {
-    SET_NESTED_VAR(rare_non_inherited_data_, grid_data_,
-                   named_grid_area_column_count_, column_count);
+                   grid_auto_repeat_rows_type_, auto_repeat_type);
   }
 
   // align-content utility functions.
@@ -2786,12 +2442,6 @@
     return rare_non_inherited_data_->perspective_ > 0;
   }
 
-  // Page size utility functions.
-  void ResetPageSizeType() {
-    SET_VAR(rare_non_inherited_data_, page_size_type_,
-            static_cast<unsigned>(PageSizeType::kAuto));
-  }
-
   // Outline utility functions.
   bool HasOutline() const {
     return OutlineWidth() > 0 && OutlineStyle() > EBorderStyle::kHidden;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 49db345..24b2fb5 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -91,9 +91,9 @@
                          (1 << (kPseudoIdBackdrop - kFirstPublicPseudoId))
 };
 
-enum ColumnFill { kColumnFillBalance, kColumnFillAuto };
+enum class EColumnFill { kBalance, kAuto };
 
-enum ColumnSpan { kColumnSpanNone = 0, kColumnSpanAll };
+enum class EColumnSpan { kNone = 0, kAll };
 
 enum OutlineIsAuto { kOutlineIsAutoOff = 0, kOutlineIsAutoOn };
 
@@ -150,19 +150,14 @@
 
 // Deprecated Flexible Box Properties
 
-enum EBoxPack { kBoxPackStart, kBoxPackCenter, kBoxPackEnd, kBoxPackJustify };
-enum EBoxAlignment { BSTRETCH, BSTART, BCENTER, BEND, BBASELINE };
-enum EBoxOrient { HORIZONTAL, VERTICAL };
-enum EBoxLines { SINGLE, MULTIPLE };
+enum class EBoxPack { kStart, kCenter, kEnd, kJustify };
+enum class EBoxAlignment { kStretch, kStart, kCenter, kBend, kBaseline };
+enum class EBoxOrient { kHorizontal, kVertical };
+enum class EBoxLines { kSingle, kMultiple };
 
 // CSS3 Flexbox Properties
 
-enum EFlexDirection {
-  kFlowRow,
-  kFlowRowReverse,
-  kFlowColumn,
-  kFlowColumnReverse
-};
+enum class EFlexDirection { kRow, kRowReverse, kColumn, kColumnReverse };
 enum EFlexWrap { kFlexNoWrap, kFlexWrap, kFlexWrapReverse };
 
 // CSS3 Image Values
@@ -344,17 +339,6 @@
 };
 
 enum AutoRepeatType { kNoAutoRepeat, kAutoFill, kAutoFit };
-
-// Page size type.
-// StyleRareNonInheritedData::page_size_ is meaningful only when
-// StyleRareNonInheritedData::page_size_type_ is kResolved.
-enum class PageSizeType {
-  kAuto,       // size: auto
-  kLandscape,  // size: landscape
-  kPortrait,   // size: portrait
-  kResolved    // Size is fully resolved.
-};
-
 }  // namespace blink
 
 #endif  // ComputedStyleConstants_h
diff --git a/third_party/WebKit/Source/core/style/ScrollSnap.h b/third_party/WebKit/Source/core/style/ScrollSnap.h
index 24afd8b..c2139c67 100644
--- a/third_party/WebKit/Source/core/style/ScrollSnap.h
+++ b/third_party/WebKit/Source/core/style/ScrollSnap.h
@@ -10,9 +10,6 @@
 
 namespace blink {
 
-using ScrollPadding = QuadLengthValue;
-using ScrollSnapMargin = QuadLengthValue;
-
 struct ScrollSnapType {
   DISALLOW_NEW();
 
diff --git a/third_party/WebKit/Source/modules/quota/BUILD.gn b/third_party/WebKit/Source/modules/quota/BUILD.gn
index 7e2c269b..fcd9e3c 100644
--- a/third_party/WebKit/Source/modules/quota/BUILD.gn
+++ b/third_party/WebKit/Source/modules/quota/BUILD.gn
@@ -25,6 +25,8 @@
     "StorageQuotaCallback.h",
     "StorageQuotaClient.cpp",
     "StorageQuotaClient.h",
+    "StorageQuotaClientImpl.cpp",
+    "StorageQuotaClientImpl.h",
     "StorageUsageCallback.h",
     "WorkerNavigatorStorageQuota.cpp",
     "WorkerNavigatorStorageQuota.h",
diff --git a/third_party/WebKit/Source/web/StorageQuotaClientImpl.cpp b/third_party/WebKit/Source/modules/quota/StorageQuotaClientImpl.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/StorageQuotaClientImpl.cpp
rename to third_party/WebKit/Source/modules/quota/StorageQuotaClientImpl.cpp
index e3538b0c..a257a6a 100644
--- a/third_party/WebKit/Source/web/StorageQuotaClientImpl.cpp
+++ b/third_party/WebKit/Source/modules/quota/StorageQuotaClientImpl.cpp
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "web/StorageQuotaClientImpl.h"
+#include "modules/quota/StorageQuotaClientImpl.h"
 
 #include "core/dom/Document.h"
 #include "core/dom/ExecutionContext.h"
diff --git a/third_party/WebKit/Source/web/StorageQuotaClientImpl.h b/third_party/WebKit/Source/modules/quota/StorageQuotaClientImpl.h
similarity index 92%
rename from third_party/WebKit/Source/web/StorageQuotaClientImpl.h
rename to third_party/WebKit/Source/modules/quota/StorageQuotaClientImpl.h
index 6fd10ff..b639bea8 100644
--- a/third_party/WebKit/Source/web/StorageQuotaClientImpl.h
+++ b/third_party/WebKit/Source/modules/quota/StorageQuotaClientImpl.h
@@ -31,14 +31,16 @@
 #ifndef StorageQuotaClientImpl_h
 #define StorageQuotaClientImpl_h
 
+#include "modules/ModulesExport.h"
 #include "modules/quota/StorageQuotaClient.h"
 #include "platform/wtf/Forward.h"
 
 namespace blink {
 
-class StorageQuotaClientImpl
+// TODO(sashab): Merge this into StorageQuotaClient.
+class MODULES_EXPORT StorageQuotaClientImpl
     : public GarbageCollectedFinalized<StorageQuotaClientImpl>,
-      public StorageQuotaClient {
+      NON_EXPORTED_BASE(public StorageQuotaClient) {
   USING_GARBAGE_COLLECTED_MIXIN(StorageQuotaClientImpl);
 
  public:
diff --git a/third_party/WebKit/Source/modules/storage/BUILD.gn b/third_party/WebKit/Source/modules/storage/BUILD.gn
index 37006cc8..bef863f 100644
--- a/third_party/WebKit/Source/modules/storage/BUILD.gn
+++ b/third_party/WebKit/Source/modules/storage/BUILD.gn
@@ -17,6 +17,8 @@
     "StorageArea.cpp",
     "StorageArea.h",
     "StorageClient.h",
+    "StorageClientImpl.cpp",
+    "StorageClientImpl.h",
     "StorageEvent.cpp",
     "StorageEvent.h",
     "StorageNamespace.cpp",
diff --git a/third_party/WebKit/Source/web/StorageClientImpl.cpp b/third_party/WebKit/Source/modules/storage/StorageClientImpl.cpp
similarity index 97%
rename from third_party/WebKit/Source/web/StorageClientImpl.cpp
rename to third_party/WebKit/Source/modules/storage/StorageClientImpl.cpp
index 3b9df817..c58aea55 100644
--- a/third_party/WebKit/Source/web/StorageClientImpl.cpp
+++ b/third_party/WebKit/Source/modules/storage/StorageClientImpl.cpp
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "web/StorageClientImpl.h"
+#include "modules/storage/StorageClientImpl.h"
 
 #include <memory>
 #include "core/exported/WebViewBase.h"
diff --git a/third_party/WebKit/Source/web/StorageClientImpl.h b/third_party/WebKit/Source/modules/storage/StorageClientImpl.h
similarity index 78%
rename from third_party/WebKit/Source/web/StorageClientImpl.h
rename to third_party/WebKit/Source/modules/storage/StorageClientImpl.h
index f65cbeca..7d3c920 100644
--- a/third_party/WebKit/Source/web/StorageClientImpl.h
+++ b/third_party/WebKit/Source/modules/storage/StorageClientImpl.h
@@ -5,14 +5,17 @@
 #ifndef StorageClientImpl_h
 #define StorageClientImpl_h
 
-#include "modules/storage/StorageClient.h"
 #include <memory>
+#include "modules/ModulesExport.h"
+#include "modules/storage/StorageClient.h"
 
 namespace blink {
 
 class WebViewBase;
 
-class StorageClientImpl : public StorageClient {
+// TODO(sashab): Merge this into StorageClient.
+class MODULES_EXPORT StorageClientImpl
+    : NON_EXPORTED_BASE(public StorageClient) {
  public:
   explicit StorageClientImpl(WebViewBase*);
 
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index 3b8b0a1..6ae0715 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -49,10 +49,6 @@
     "PageOverlay.h",
     "PrerendererClientImpl.cpp",
     "PrerendererClientImpl.h",
-    "StorageClientImpl.cpp",
-    "StorageClientImpl.h",
-    "StorageQuotaClientImpl.cpp",
-    "StorageQuotaClientImpl.h",
     "WebDevToolsAgentImpl.cpp",
     "WebDevToolsAgentImpl.h",
     "WebDevToolsFrontendImpl.cpp",
@@ -62,9 +58,6 @@
     "WebFactoryImpl.h",
     "WebFormElementObserverImpl.cpp",
     "WebFormElementObserverImpl.h",
-    "WebFrameSerializer.cpp",
-    "WebFrameSerializerImpl.cpp",
-    "WebFrameSerializerImpl.h",
     "WebFrameWidgetImpl.cpp",
     "WebFrameWidgetImpl.h",
     "WebHelperPluginImpl.cpp",
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index cfb0aa80c..82c1c5f 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1443,10 +1443,8 @@
 }
 
 bool WebLocalFrameImpl::HasCustomPageSizeStyle(int page_index) {
-  return GetFrame()
-             ->GetDocument()
-             ->StyleForPage(page_index)
-             ->GetPageSizeType() != PageSizeType::kAuto;
+  return GetFrame()->GetDocument()->StyleForPage(page_index)->PageSizeType() !=
+         EPageSizeType::kAuto;
 }
 
 bool WebLocalFrameImpl::IsPageBoxVisible(int page_index) {
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index c348d41..34ca4911 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -104,6 +104,7 @@
 #include "modules/compositorworker/CompositorWorkerProxyClientImpl.h"
 #include "modules/credentialmanager/CredentialManagerClient.h"
 #include "modules/encryptedmedia/MediaKeysController.h"
+#include "modules/quota/StorageQuotaClientImpl.h"
 #include "modules/speech/SpeechRecognitionClientProxy.h"
 #include "modules/storage/StorageNamespaceController.h"
 #include "modules/webdatabase/DatabaseClient.h"
@@ -170,7 +171,6 @@
 #include "public/web/WebWindowFeatures.h"
 #include "web/PageOverlay.h"
 #include "web/PrerendererClientImpl.h"
-#include "web/StorageQuotaClientImpl.h"
 #include "web/WebDevToolsAgentImpl.h"
 
 #if USE(DEFAULT_RENDER_THEME)
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index 3cc0f13..c7102683 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -41,6 +41,7 @@
 #include "core/page/EditorClient.h"
 #include "core/page/EventWithHitTestResults.h"
 #include "core/page/PageWidgetDelegate.h"
+#include "modules/storage/StorageClientImpl.h"
 #include "platform/animation/CompositorAnimationTimeline.h"
 #include "platform/geometry/IntPoint.h"
 #include "platform/geometry/IntRect.h"
@@ -66,7 +67,6 @@
 #include "public/web/WebNavigationPolicy.h"
 #include "public/web/WebPageImportanceSignals.h"
 #include "web/MediaKeysClientImpl.h"
-#include "web/StorageClientImpl.h"
 #include "web/WebExport.h"
 #include "web/WebPagePopupImpl.h"
 
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 912ebb2e..fe492c6 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -173,7 +173,6 @@
 // Consider 3 characters with the script values {Kana}, {Hira, Kana}, {Kana}.
 // Without script extensions only the first script in each set would be taken
 // into account, resulting in 3 runs where 1 would be enough.
-// TODO(ckocagil): Write a unit test for the case above.
 int ScriptInterval(const base::string16& text,
                    size_t start,
                    size_t length,
@@ -187,9 +186,6 @@
   *script = scripts[0];
 
   while (char_iterator.Advance()) {
-    // Special handling to merge white space into the previous run.
-    if (u_isUWhiteSpace(char_iterator.get()))
-      continue;
     ScriptSetIntersect(char_iterator.get(), scripts, &scripts_size);
     if (scripts_size == 0U)
       return char_iterator.array_pos();
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index a3fef5ca..2ec7e69 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -305,6 +305,29 @@
   return base::string16(length, RenderText::kPasswordReplacementChar);
 }
 
+// Converts a vector of UTF8 literals into a vector of (UTF16) string16.
+std::vector<base::string16> ToString16Vec(
+    const std::vector<const char*>& utf8_literals) {
+  std::vector<base::string16> vec;
+  for (auto* const literal : utf8_literals)
+    vec.push_back(UTF8ToUTF16(literal));
+  return vec;
+}
+
+// Returns the combined character range from all text runs on |line|.
+Range LineCharRange(const internal::Line& line) {
+  if (line.segments.empty())
+    return Range();
+  Range ltr(line.segments.front().char_range.start(),
+            line.segments.back().char_range.end());
+  if (ltr.end() > ltr.start())
+    return ltr;
+
+  // For RTL, the order of segments is reversed, but the ranges are not.
+  return Range(line.segments.back().char_range.start(),
+               line.segments.front().char_range.end());
+}
+
 // The class which records the drawing operations so that the test case can
 // verify where exactly the glyphs are drawn.
 class TestSkiaTextRenderer : public internal::SkiaTextRenderer {
@@ -462,6 +485,26 @@
     return test_api_->GetHarfBuzzRunList();
   }
 
+  // Returns a vector of text fragments corresponding to the current list of
+  // text runs.
+  std::vector<base::string16> GetRuns() {
+    std::vector<base::string16> runs_as_text;
+    const std::vector<RenderText::FontSpan> spans =
+        render_text_->GetFontSpansForTesting();
+    for (const auto& span : spans) {
+      runs_as_text.push_back(render_text_->text().substr(span.second.GetMin(),
+                                                         span.second.length()));
+    }
+    return runs_as_text;
+  }
+
+  // Sets the text to |text|, then returns GetRuns().
+  std::vector<base::string16> RunsFor(const base::string16& text) {
+    render_text_->SetText(text);
+    test_api()->EnsureLayout();
+    return GetRuns();
+  }
+
   void ResetRenderTextInstance() {
     render_text_ = CreateRenderTextInstance();
     test_api_.reset(new test::RenderTextTestApi(GetRenderText()));
@@ -2922,6 +2965,71 @@
   }
 }
 
+// Test that characters commonly used in the context of several scripts do not
+// cause text runs to break. For example the Japanese "long sound symbol" --
+// normally only used in a Katakana script, is also used on occasion when in
+// Hiragana scripts. It shouldn't cause a Hiragana text run break since that
+// could upset kerning.
+TEST_P(RenderTextTest, ScriptExtensionsDoNotBreak) {
+  // Apparently ramen restaurants prefer "らーめん" over "らあめん". The "dash"
+  // is the long sound symbol and usually just appears in Katakana writing.
+  const base::string16 ramen_hiragana = UTF8ToUTF16("らーめん");
+  const base::string16 ramen_katakana = UTF8ToUTF16("ラーメン");
+  const base::string16 ramen_mixed = UTF8ToUTF16("らあメン");
+
+  EXPECT_EQ(std::vector<base::string16>({ramen_hiragana}),
+            RunsFor(ramen_hiragana));
+  EXPECT_EQ(std::vector<base::string16>({ramen_katakana}),
+            RunsFor(ramen_katakana));
+
+  // Currently Harfbuzz breaks this, but not Mac.
+  if (GetParam() == RENDER_TEXT_HARFBUZZ)
+    EXPECT_EQ(ToString16Vec({"らあ", "メン"}), RunsFor(ramen_mixed));
+  else
+    EXPECT_EQ(std::vector<base::string16>({ramen_mixed}), RunsFor(ramen_mixed));
+}
+
+// Test that whitespace breaks runs of text. E.g. this can permit better fonts
+// to be chosen by the fallback mechanism when a font does not provide
+// whitespace glyphs for all scripts. See http://crbug.com/731563.
+TEST_P(RenderTextTest, WhitespaceDoesBreak) {
+  // Title of the Wikipedia page for "bit". ASCII spaces. In Hebrew and English.
+  // Note that the hyphens that Wikipedia uses are different. English uses
+  // ASCII (U+002D) "hyphen minus", Hebrew uses the U+2013 "EN Dash".
+  const base::string16 ascii_space_he = UTF8ToUTF16("סיבית – ויקיפדיה");
+  const base::string16 ascii_space_en = ASCIIToUTF16("Bit - Wikipedia");
+
+  // This says "thank you very much" with a full-width non-ascii space (U+3000).
+  const base::string16 full_width_space = UTF8ToUTF16("ども ありがと");
+
+  if (GetParam() == RENDER_TEXT_HARFBUZZ) {
+    // Old behavior:
+    // { "סיבית ", "–", " ", "ויקיפדיה"" }
+    // { "Bit ", "- ", "Wikipedia" }
+    // { "ども ありがと"" }.
+    EXPECT_EQ(ToString16Vec({"סיבית", " ", "–", " ", "ויקיפדיה"}),
+              RunsFor(ascii_space_he));
+    EXPECT_EQ(ToString16Vec({"Bit", " - ", "Wikipedia"}),
+              RunsFor(ascii_space_en));
+    EXPECT_EQ(ToString16Vec({"ども", " ", "ありがと"}),
+              RunsFor(full_width_space));
+  } else {
+    // Mac is a black box. From this it seems to draw RTL runs right to left and
+    // is able to use typeface characteristics when breaking runs. On 10.9, the
+    // Hebrew string is given a single run, and on 10.12 it's given 3 runs. It
+    // doesn't really matter as far as the rest of the RenderText machinery is
+    // concerned.
+    auto actual = RunsFor(ascii_space_he);
+    if (actual.size() == 3) {
+      EXPECT_EQ(ToString16Vec({"ויקיפדיה", " – ", "סיבית"}), actual);
+    } else {
+      EXPECT_EQ(ToString16Vec({"סיבית – ויקיפדיה"}), actual);
+    }
+    EXPECT_EQ(ToString16Vec({"Bit - Wikipedia"}), RunsFor(ascii_space_en));
+    EXPECT_EQ(ToString16Vec({"ども ありがと"}), RunsFor(full_width_space));
+  }
+}
+
 // Ensure strings wrap onto multiple lines for a small available width.
 TEST_P(RenderTextHarfBuzzTest, Multiline_MinWidth) {
   const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl,
@@ -2942,20 +3050,39 @@
 
 // Ensure strings wrap onto multiple lines for a normal available width.
 TEST_P(RenderTextHarfBuzzTest, Multiline_NormalWidth) {
+  // Should RenderText suppress drawing whitespace at the end of a line?
+  // Currently it does not.
   const struct {
     const wchar_t* const text;
     const Range first_line_char_range;
     const Range second_line_char_range;
+
+    // Lengths of each text run. Runs break at whitespace.
+    std::vector<size_t> run_lengths;
+
+    // The index of the text run that should start the second line.
+    int second_line_run_index;
+
     bool is_ltr;
   } kTestStrings[] = {
-    { L"abc defg hijkl", Range(0, 9), Range(9, 14), true },
-    { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true },
-    { L"\x0627\x0644\x0644\x063A\x0629 "
-      L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
-      Range(0, 6), Range(6, 13), false },
-    { L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9"
-      L"\x05DA\x05DB\x05DD", Range(0, 5), Range(5, 13), false }
-  };
+      {L"abc defg hijkl", Range(0, 9), Range(9, 14), {3, 1, 4, 1, 5}, 4, true},
+      {L"qwertyzxcvbn", Range(0, 10), Range(10, 12), {10, 2}, 1, true},
+      // RTL: should render left-to-right as "<space>43210 \n cba9876".
+      {L"\x0627\x0644\x0644\x063A\x0629 "
+       L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
+       Range(0, 6),
+       Range(6, 13),
+       {1 /* space first */, 5, 7},
+       2,
+       false},
+      // RTL: should render left-to-right as "<space>3210 \n cba98765".
+      {L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9"
+       L"\x05DA\x05DB\x05DD",
+       Range(0, 5),
+       Range(5, 13),
+       {1 /* space first */, 5, 8},
+       2,
+       false}};
 
   RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
 
@@ -2973,31 +3100,31 @@
     DrawVisualText();
 
     ASSERT_EQ(2U, test_api()->lines().size());
-    ASSERT_EQ(1U, test_api()->lines()[0].segments.size());
     EXPECT_EQ(kTestStrings[i].first_line_char_range,
-              test_api()->lines()[0].segments[0].char_range);
-    ASSERT_EQ(1U, test_api()->lines()[1].segments.size());
+              LineCharRange(test_api()->lines()[0]));
     EXPECT_EQ(kTestStrings[i].second_line_char_range,
-              test_api()->lines()[1].segments[0].char_range);
+              LineCharRange(test_api()->lines()[1]));
 
     std::vector<TestSkiaTextRenderer::TextLog> text_log;
     renderer()->GetTextLogAndReset(&text_log);
-    ASSERT_EQ(2U, text_log.size());
+
+    ASSERT_EQ(kTestStrings[i].run_lengths.size(), text_log.size());
+
     // NOTE: this expectation compares the character length and glyph counts,
     // which isn't always equal. This is okay only because all the test
     // strings are simple (like, no compound characters nor UTF16-surrogate
     // pairs). Be careful in case more complicated test strings are added.
-    EXPECT_EQ(kTestStrings[i].first_line_char_range.length(),
-              text_log[0].glyph_count);
-    EXPECT_EQ(kTestStrings[i].second_line_char_range.length(),
-              text_log[1].glyph_count);
-    EXPECT_LT(text_log[0].origin.y(), text_log[1].origin.y());
+    EXPECT_EQ(kTestStrings[i].run_lengths[0], text_log[0].glyph_count);
+    const int second_line_start = kTestStrings[i].second_line_run_index;
+    EXPECT_EQ(kTestStrings[i].run_lengths[second_line_start],
+              text_log[second_line_start].glyph_count);
+    EXPECT_LT(text_log[0].origin.y(), text_log[second_line_start].origin.y());
     if (kTestStrings[i].is_ltr) {
       EXPECT_EQ(0, text_log[0].origin.x());
-      EXPECT_EQ(0, text_log[1].origin.x());
+      EXPECT_EQ(0, text_log[second_line_start].origin.x());
     } else {
       EXPECT_LT(0, text_log[0].origin.x());
-      EXPECT_LT(0, text_log[1].origin.x());
+      EXPECT_LT(0, text_log[second_line_start].origin.x());
     }
   }
 }
@@ -3184,7 +3311,7 @@
     for (size_t j = 0; j < test_api()->lines().size(); ++j) {
       SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
       EXPECT_EQ(kTestScenarios[i].char_ranges[j],
-                test_api()->lines()[j].segments[0].char_range);
+                LineCharRange(test_api()->lines()[j]));
       EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
                 test_api()->lines()[j].size.width());
     }
@@ -3593,6 +3720,7 @@
   render_text->SetText(WideToUTF16(L"x\x25B6y"));
   test_api()->EnsureLayout();
   internal::TextRunList* run_list = GetHarfBuzzRunList();
+  EXPECT_EQ(ToString16Vec({"x", "▶", "y"}), GetRuns());
   ASSERT_EQ(3U, run_list->size());
   EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
   EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
@@ -3601,11 +3729,13 @@
   render_text->SetText(WideToUTF16(L"x \x25B6 y"));
   test_api()->EnsureLayout();
   run_list = GetHarfBuzzRunList();
-  ASSERT_EQ(4U, run_list->size());
-  EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range);
-  EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range);
-  EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range);
-  EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range);
+  EXPECT_EQ(ToString16Vec({"x", " ", "▶", " ", "y"}), GetRuns());
+  ASSERT_EQ(5U, run_list->size());
+  EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
+  EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
+  EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
+  EXPECT_EQ(Range(3, 4), run_list->runs()[3]->range);
+  EXPECT_EQ(Range(4, 5), run_list->runs()[4]->range);
 }
 
 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByEmoji) {