diff --git a/DEPS b/DEPS
index 83028855..1f18b40f 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': '3f3075819f242158dcfc1690df5c15ba39c5dbb3',
+  'skia_revision': 'baf41bd1c8d9d3741349d6cc531d0bfc3df96f92',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -52,7 +52,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '63d8c2662c284955459eccbf7f40fcf8a8f51651',
+  'angle_revision': '9216a6e26db957681faefc40884e8bf21fde5063',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
diff --git a/ash/shell.cc b/ash/shell.cc
index c5cd6e2b..1c72b47 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -1117,6 +1117,8 @@
     keyboard::KeyboardController::ResetInstance(
         new keyboard::KeyboardController(shell_delegate_->CreateKeyboardUI(),
                                          virtual_keyboard_controller_.get()));
+    for (auto& observer : shell_observers_)
+      observer.OnKeyboardControllerCreated();
   }
 }
 
diff --git a/ash/shell_observer.h b/ash/shell_observer.h
index 5937bb2..c76ede7 100644
--- a/ash/shell_observer.h
+++ b/ash/shell_observer.h
@@ -63,6 +63,9 @@
   virtual void OnVirtualKeyboardStateChanged(bool activated,
                                              aura::Window* root_window) {}
 
+  // Called when a new KeyboardController is created.
+  virtual void OnKeyboardControllerCreated() {}
+
   // Called at the end of Shell::Init.
   virtual void OnShellInitialized() {}
 
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
index 89d55053..c53f82f2 100644
--- a/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
+++ b/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
@@ -39,8 +39,10 @@
   tray_container()->AddChildView(icon_);
 
   // The Shell may not exist in some unit tests.
-  if (Shell::HasInstance())
+  if (Shell::HasInstance()) {
     Shell::Get()->keyboard_ui()->AddObserver(this);
+    Shell::Get()->AddShellObserver(this);
+  }
   // Try observing keyboard controller, in case it is already constructed.
   ObserveKeyboardController();
 }
@@ -49,8 +51,10 @@
   // Try unobserving keyboard controller, in case it still exists.
   UnobserveKeyboardController();
   // The Shell may not exist in some unit tests.
-  if (Shell::HasInstance())
+  if (Shell::HasInstance()) {
+    Shell::Get()->RemoveShellObserver(this);
     Shell::Get()->keyboard_ui()->RemoveObserver(this);
+  }
 }
 
 base::string16 VirtualKeyboardTray::GetAccessibleNameForTray() {
@@ -96,10 +100,14 @@
 
 void VirtualKeyboardTray::OnKeyboardClosed() {}
 
+void VirtualKeyboardTray::OnKeyboardControllerCreated() {
+  ObserveKeyboardController();
+}
+
 void VirtualKeyboardTray::ObserveKeyboardController() {
   keyboard::KeyboardController* keyboard_controller =
       keyboard::KeyboardController::GetInstance();
-  if (keyboard_controller)
+  if (keyboard_controller && !keyboard_controller->HasObserver(this))
     keyboard_controller->AddObserver(this);
 }
 
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray.h b/ash/system/virtual_keyboard/virtual_keyboard_tray.h
index c741a03..2ae272dd 100644
--- a/ash/system/virtual_keyboard/virtual_keyboard_tray.h
+++ b/ash/system/virtual_keyboard/virtual_keyboard_tray.h
@@ -6,6 +6,7 @@
 #define ASH_SYSTEM_VIRTUAL_KEYBOARD_VIRTUAL_KEYBOARD_TRAY_H_
 
 #include "ash/keyboard/keyboard_ui_observer.h"
+#include "ash/shell_observer.h"
 #include "ash/system/tray/tray_background_view.h"
 #include "base/macros.h"
 #include "ui/keyboard/keyboard_controller_observer.h"
@@ -19,7 +20,8 @@
 // TODO(sky): make this visible on non-chromeos platforms.
 class VirtualKeyboardTray : public TrayBackgroundView,
                             public KeyboardUIObserver,
-                            public keyboard::KeyboardControllerObserver {
+                            public keyboard::KeyboardControllerObserver,
+                            public ShellObserver {
  public:
   explicit VirtualKeyboardTray(Shelf* shelf);
   ~VirtualKeyboardTray() override;
@@ -37,6 +39,9 @@
   void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) override;
   void OnKeyboardClosed() override;
 
+  // ShellObserver:
+  void OnKeyboardControllerCreated() override;
+
  private:
   void ObserveKeyboardController();
   void UnobserveKeyboardController();
diff --git a/base/deferred_sequenced_task_runner_unittest.cc b/base/deferred_sequenced_task_runner_unittest.cc
index 799ddcd..a96befa 100644
--- a/base/deferred_sequenced_task_runner_unittest.cc
+++ b/base/deferred_sequenced_task_runner_unittest.cc
@@ -11,15 +11,13 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/threading/thread.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-class DeferredSequencedTaskRunnerTest : public testing::Test,
-                                        public base::NonThreadSafe {
+class DeferredSequencedTaskRunnerTest : public testing::Test {
  public:
   class ExecuteTaskOnDestructor :
       public base::RefCounted<ExecuteTaskOnDestructor> {
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc
index 5088bd99..0696c96 100644
--- a/base/files/important_file_writer.cc
+++ b/base/files/important_file_writer.cc
@@ -152,11 +152,11 @@
       serializer_(nullptr),
       commit_interval_(interval),
       weak_factory_(this) {
-  DCHECK(CalledOnValidThread());
   DCHECK(task_runner_);
 }
 
 ImportantFileWriter::~ImportantFileWriter() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // We're usually a member variable of some other object, which also tends
   // to be our serializer. It may not be safe to call back to the parent object
   // being destructed.
@@ -164,12 +164,12 @@
 }
 
 bool ImportantFileWriter::HasPendingWrite() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return timer().IsRunning();
 }
 
 void ImportantFileWriter::WriteNow(std::unique_ptr<std::string> data) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!IsValueInRangeForNumericType<int32_t>(data->length())) {
     NOTREACHED();
     return;
@@ -192,7 +192,7 @@
 }
 
 void ImportantFileWriter::ScheduleWrite(DataSerializer* serializer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DCHECK(serializer);
   serializer_ = serializer;
diff --git a/base/files/important_file_writer.h b/base/files/important_file_writer.h
index 46efbaa1..5fcd515 100644
--- a/base/files/important_file_writer.h
+++ b/base/files/important_file_writer.h
@@ -12,8 +12,8 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_piece.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 
@@ -35,7 +35,7 @@
 //
 // Also note that ImportantFileWriter can be *really* slow (cf. File::Flush()
 // for details) and thus please don't block shutdown on ImportantFileWriter.
-class BASE_EXPORT ImportantFileWriter : public NonThreadSafe {
+class BASE_EXPORT ImportantFileWriter {
  public:
   // Used by ScheduleSave to lazily provide the data to be saved. Allows us
   // to also batch data serializations.
@@ -143,6 +143,8 @@
   // Time delta after which scheduled data will be written to disk.
   const TimeDelta commit_interval_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   WeakPtrFactory<ImportantFileWriter> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ImportantFileWriter);
diff --git a/base/message_loop/message_pump.h b/base/message_loop/message_pump.h
index c53be80..cc72663 100644
--- a/base/message_loop/message_pump.h
+++ b/base/message_loop/message_pump.h
@@ -7,13 +7,13 @@
 
 #include "base/base_export.h"
 #include "base/message_loop/timer_slack.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 
 namespace base {
 
 class TimeTicks;
 
-class BASE_EXPORT MessagePump : public NonThreadSafe {
+class BASE_EXPORT MessagePump {
  public:
   // Please see the comments above the Run method for an illustration of how
   // these delegate methods are used.
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 5fd684a0..4810737 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -196,6 +196,9 @@
   }
 
   if (is_android) {
+    set_sources_assignment_filter([])
+    sources += [ "test_file_util_linux.cc" ]
+    set_sources_assignment_filter(sources_assignment_filter)
     deps += [
       ":base_unittests_jni_headers",
       ":test_support_jni_headers",
diff --git a/base/test/test_file_util_linux.cc b/base/test/test_file_util_linux.cc
index 0ef5c0a1..cf8b056 100644
--- a/base/test/test_file_util_linux.cc
+++ b/base/test/test_file_util_linux.cc
@@ -9,11 +9,42 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#if defined(OS_ANDROID)
+#include <asm/unistd.h>
+#include <errno.h>
+#include <linux/fadvise.h>
+#include <sys/syscall.h>
+#endif
+
 #include "base/files/file_path.h"
 #include "base/files/scoped_file.h"
 
 namespace base {
 
+// Inconveniently, the NDK doesn't provide for posix_fadvise
+// until native API level = 21, which we don't use yet, so provide a wrapper, at
+// least on ARM32
+#if defined(OS_ANDROID) && __ANDROID_API__ < 21
+
+namespace {
+int posix_fadvise(int fd, off_t offset, off_t len, int advice) {
+#if defined(ARCH_CPU_ARMEL)
+  // Note that the syscall argument order on ARM is different from the C
+  // function; this is helpfully documented in the Linux posix_fadvise manpage.
+  return syscall(__NR_arm_fadvise64_64, fd, advice,
+                 0,  // Upper 32-bits for offset
+                 offset,
+                 0,  // Upper 32-bits for length
+                 len);
+#endif
+  NOTIMPLEMENTED();
+  return ENOSYS;
+}
+
+}  // namespace
+
+#endif  // OS_ANDROID
+
 bool EvictFileFromSystemCache(const FilePath& file) {
   ScopedFD fd(open(file.value().c_str(), O_RDONLY));
   if (!fd.is_valid())
diff --git a/base/test/test_file_util_posix.cc b/base/test/test_file_util_posix.cc
index b8172831..5b5d4d85 100644
--- a/base/test/test_file_util_posix.cc
+++ b/base/test/test_file_util_posix.cc
@@ -79,7 +79,7 @@
   return DeleteFile(file, recurse);
 }
 
-#if !defined(OS_LINUX) && !defined(OS_MACOSX)
+#if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
 bool EvictFileFromSystemCache(const FilePath& file) {
   // There doesn't seem to be a POSIX way to cool the disk cache.
   NOTIMPLEMENTED();
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
index d5783d0..69a4e50 100644
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -42,7 +42,7 @@
 
 // The names of dump providers whitelisted for summary tracing.
 const char* const kDumpProviderSummaryWhitelist[] = {
-    "Malloc", "PartitionAlloc", "ProcessMemoryMetrics", "V8Isolate",
+    "BlinkGC", "Malloc", "PartitionAlloc", "ProcessMemoryMetrics", "V8Isolate",
     nullptr  // End of list marker.
 };
 
diff --git a/build/package_mac_toolchain.py b/build/package_mac_toolchain.py
index ecdc4d7..48672bb 100755
--- a/build/package_mac_toolchain.py
+++ b/build/package_mac_toolchain.py
@@ -41,7 +41,6 @@
 'Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift',
 'Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-migrator',
 'Contents/Resources/Packages/MobileDevice.pkg',
-'Contents/SharedFrameworks/DNTDocumentationSupport.framework'
 ]
 
 MAC_EXCLUDE_FOLDERS = [
diff --git a/chrome/android/java/res/anim/stay_hidden.xml b/chrome/android/java/res/anim/stay_hidden.xml
new file mode 100644
index 0000000..be44bde0
--- /dev/null
+++ b/chrome/android/java/res/anim/stay_hidden.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- The delay here must be long enough for the Activity being resumed to draw
+     its first frame of UI. This is to avoid showing stale 2D screenshots when
+     launching Chrome in VR. Note that the larger this value is, the more
+     latency we add to resuming Chrome after going through the Daydream Device
+     ON flow. -->
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@android:anim/linear_interpolator"
+        android:fromAlpha="0" android:toAlpha="0"
+        android:duration="500" />
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 7e56d48..4f24ef9 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -730,4 +730,10 @@
         <item name="android:windowEnterAnimation">@anim/design_bottom_sheet_slide_in</item>
         <item name="android:windowExitAnimation">@null</item>
     </style>
+
+    <!-- VR animations -->
+    <style name="VrEntryAnimation">
+        <item name="android:windowEnterAnimation">@anim/stay_hidden</item>
+        <item name="android:windowExitAnimation">@null</item>
+    </style>
 </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
index afac072a..100e403 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -39,7 +39,11 @@
     public static final int GOOGLE_PLAY_INSTALL_FAILED_DOWNLOAD_ERROR = 8;
     public static final int GOOGLE_PLAY_INSTALL_FAILED_INSTALL_ERROR = 9;
     public static final int GOOGLE_PLAY_INSTALL_FAILED_INSTALL_TIMEOUT = 10;
-    public static final int GOOGLE_PLAY_INSTALL_RESULT_MAX = 11;
+    public static final int GOOGLE_PLAY_INSTALL_REQUEST_FAILED_POLICY_DISABLED = 11;
+    public static final int GOOGLE_PLAY_INSTALL_REQUEST_FAILED_UNKNOWN_ACCOUNT = 12;
+    public static final int GOOGLE_PLAY_INSTALL_REQUEST_FAILED_NETWORK_ERROR = 13;
+    public static final int GOOGLE_PLAY_INSTALL_REQUSET_FAILED_RESOLVE_ERROR = 14;
+    public static final int GOOGLE_PLAY_INSTALL_RESULT_MAX = 14;
 
     public static final String HISTOGRAM_UPDATE_REQUEST_SENT =
             "WebApk.Update.RequestSent";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
index 18d372a..37c4cb2a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -74,7 +74,11 @@
     private static final int[] FAVICON_SERVICE_SUPPORTED_SIZES = {16, 24, 32, 48, 64};
     private static final String FAVICON_SERVICE_FORMAT =
             "https://s2.googleusercontent.com/s2/favicons?domain=%s&src=chrome_newtab_mobile&sz=%d&alt=404";
+
+    /** Min size for site attribution: only 16px as many sites do not have any other small icon. */
     private static final int PUBLISHER_FAVICON_MINIMUM_SIZE_PX = 16;
+    /** Desired size for site attribution: only 32px as larger icons are often too complex */
+    private static final int PUBLISHER_FAVICON_DESIRED_SIZE_PX = 32;
 
     private static final int THUMBNAIL_SOURCE_ARTICLE = 0;
     private static final int THUMBNAIL_SOURCE_DOWNLOAD = 1;
@@ -457,9 +461,10 @@
     }
 
     private void fetchFaviconFromLocalCacheOrGoogleServer(final long faviconFetchStartTimeMs) {
-        // Set the desired size to 0 to specify we do not want to resize in c++, we'll resize here.
+        // The bitmap will not be resized to desired size in c++, this only expresses preference.
         mUiDelegate.getSuggestionsSource().fetchSuggestionFavicon(mArticle,
-                PUBLISHER_FAVICON_MINIMUM_SIZE_PX, /* desiredSizePx */ 0, new Callback<Bitmap>() {
+                PUBLISHER_FAVICON_MINIMUM_SIZE_PX, PUBLISHER_FAVICON_DESIRED_SIZE_PX,
+                new Callback<Bitmap>() {
                     @Override
                     public void onResult(Bitmap image) {
                         recordFaviconFetchTime(faviconFetchStartTimeMs);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 4debec59..3d3f272 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -6,6 +6,7 @@
 
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -13,9 +14,11 @@
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
+import android.graphics.Color;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.StrictMode;
 import android.os.SystemClock;
@@ -127,6 +130,7 @@
     private TabModelSelector mTabModelSelector;
 
     private boolean mInVr;
+    private final Handler mEnterVrHandler;
 
     // Whether or not the VR Device ON flow succeeded. If this is true it means the user has a VR
     // headset on, but we haven't switched into VR mode yet.
@@ -153,6 +157,8 @@
     // presentation experience.
     private boolean mVrBrowserUsed;
 
+    private View mOverlayView;
+
     private static final class VrBroadcastReceiver extends BroadcastReceiver {
         private final WeakReference<ChromeActivity> mTargetActivity;
 
@@ -164,11 +170,28 @@
         public void onReceive(Context context, Intent intent) {
             ChromeActivity activity = mTargetActivity.get();
             if (activity == null) return;
-            getInstance(activity).mDonSucceeded = true;
+            getInstance(activity);
+            assert sInstance != null;
+            if (sInstance == null) return;
+            sInstance.mDonSucceeded = true;
             if (sInstance.mPaused) {
                 if (sInstance.mInVrAtChromeLaunch == null) sInstance.mInVrAtChromeLaunch = false;
-                ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
-                        .moveTaskToFront(activity.getTaskId(), 0);
+                // We add a black overlay view so that we can show black while the VR UI is loading.
+                // Note that this alone isn't sufficient to prevent 2D UI from showing while
+                // resuming the Activity, see the comment about the custom animation below.
+                sInstance.addOverlayView();
+
+                // We start the Activity with a custom animation that keeps it hidden for a few
+                // hundred milliseconds - enough time for us to draw the first black view.
+                // TODO(mthiesse): This is really hacky. If we can find a way to cancel the
+                // transition animation (I couldn't), then we can just make it indefinite until the
+                // VR UI is ready, and then cancel it, rather than trying to guess how long it will
+                // take to draw the first view, and possibly adding latency to VR startup.
+                Bundle options =
+                        ActivityOptions.makeCustomAnimation(activity, R.anim.stay_hidden, 0)
+                                .toBundle();
+                ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))
+                        .moveTaskToFront(activity.getTaskId(), 0, options);
             } else {
                 if (sInstance.mInVrAtChromeLaunch == null) sInstance.mInVrAtChromeLaunch = true;
                 // If a WebVR app calls requestPresent in response to the displayactivate event
@@ -430,8 +453,8 @@
         updateVrSupportLevel();
         mNativeVrShellDelegate = nativeInit();
         mFeedbackFrequency = VrFeedbackStatus.getFeedbackFrequency();
-        Choreographer choreographer = Choreographer.getInstance();
-        choreographer.postFrameCallback(new FrameCallback() {
+        mEnterVrHandler = new Handler();
+        Choreographer.getInstance().postFrameCallback(new FrameCallback() {
             @Override
             public void doFrame(long frameTimeNanos) {
                 if (mNativeVrShellDelegate == 0) return;
@@ -456,6 +479,9 @@
                 // Other activities should only pause while we're paused due to Android lifecycle.
                 assert mPaused;
                 break;
+            case ActivityState.STOPPED:
+                if (activity == mActivity) cancelPendingVrEntry();
+                break;
             case ActivityState.RESUMED:
                 assert !mInVr || mShowingDaydreamDoff;
                 if (mInVr && activity != mActivity) {
@@ -557,12 +583,17 @@
     private void enterVr(final boolean tentativeWebVrMode) {
         // We can't enter VR before the application resumes, or we encounter bizarre crashes
         // related to gpu surfaces.
+        // TODO(mthiesse): Is the above comment still accurate? It may have been tied to our HTML
+        // UI which is gone.
         assert !mPaused;
-        if (mNativeVrShellDelegate == 0) return;
         if (mInVr) return;
+        if (mNativeVrShellDelegate == 0) {
+            cancelPendingVrEntry();
+            return;
+        }
         if (!isWindowModeCorrectForVr()) {
             setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-            new Handler().post(new Runnable() {
+            mEnterVrHandler.post(new Runnable() {
                 @Override
                 public void run() {
                     enterVr(tentativeWebVrMode);
@@ -570,9 +601,27 @@
             });
             return;
         }
+        // We need to add VR UI asynchronously, or we get flashes of 2D content. Presumably this is
+        // because adding the VR UI is slow and Android times out and decides to just show
+        // something.
+        mEnterVrHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                enterVrWithCorrectWindowMode(tentativeWebVrMode);
+            }
+        });
+    }
+
+    private void enterVrWithCorrectWindowMode(final boolean tentativeWebVrMode) {
+        if (mInVr) return;
+        if (mNativeVrShellDelegate == 0) {
+            cancelPendingVrEntry();
+            return;
+        }
         if (!createVrShell()) {
             maybeSetPresentResult(false);
             mVrDaydreamApi.launchVrHomescreen();
+            cancelPendingVrEntry();
             return;
         }
         mVrClassesWrapper.setVrModeEnabled(mActivity, true);
@@ -581,20 +630,21 @@
         mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
 
         addVrViews();
-        mVrShell.initializeNative(mActivity.getActivityTab(), mRequestedWebVr || tentativeWebVrMode,
-                mActivity instanceof CustomTabActivity);
         boolean webVrMode = mRequestedWebVr || tentativeWebVrMode;
+        mVrShell.initializeNative(
+                mActivity.getActivityTab(), webVrMode, mActivity instanceof CustomTabActivity);
         mVrShell.setWebVrModeEnabled(webVrMode);
 
         // We're entering VR, but not in WebVr mode.
         mVrBrowserUsed = !webVrMode;
 
-        // onResume needs to be called on GvrLayout after initialization to make sure DON flow work
+        // onResume needs to be called on GvrLayout after initialization to make sure DON flow works
         // properly.
-        mVrShell.resume();
+        if (!mPaused) mVrShell.resume();
 
         maybeSetPresentResult(true);
         mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this);
+        removeOverlayView();
     }
 
     private boolean launchInVr() {
@@ -772,6 +822,8 @@
             return;
         }
 
+        // This handles the case where we're already in VR, and an NFC scan is received that pauses
+        // and resumes Chrome without going through the DON flow or firing the DON success intent.
         if (isDaydreamCurrentViewer()
                 && mLastVrExit + REENTER_VR_TIMEOUT_MS > SystemClock.uptimeMillis()) {
             mDonSucceeded = true;
@@ -790,6 +842,7 @@
         mDonSucceeded = false;
         // If we fail to enter VR when we should have entered VR, return to the home screen.
         if (!enterVrAfterDon()) {
+            cancelPendingVrEntry();
             maybeSetPresentResult(false);
             mVrDaydreamApi.launchVrHomescreen();
         }
@@ -800,6 +853,8 @@
         unregisterDaydreamIntent(mVrDaydreamApi);
         if (mVrSupportLevel == VR_NOT_AVAILABLE) return;
 
+        cancelPendingVrEntry();
+
         // When the active web page has a vrdisplayactivate event handler,
         // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
         // should be fired once DON flow finished. However, DON flow will pause our activity,
@@ -825,6 +880,7 @@
 
     private boolean onBackPressedInternal() {
         if (mVrSupportLevel == VR_NOT_AVAILABLE) return false;
+        cancelPendingVrEntry();
         if (!mInVr) return false;
         shutdownVr(true /* disableVrMode */, false /* canReenter */, true /* stayingInChrome */);
         return true;
@@ -895,11 +951,19 @@
         }
     }
 
+    private void cancelPendingVrEntry() {
+        // Ensure we can't asynchronously enter VR after trying to exit it.
+        mEnterVrHandler.removeCallbacksAndMessages(null);
+        mDonSucceeded = false;
+        removeOverlayView();
+    }
+
     /**
      * Exits VR Shell, performing all necessary cleanup.
      */
     /* package */ void shutdownVr(
             boolean disableVrMode, boolean canReenter, boolean stayingInChrome) {
+        cancelPendingVrEntry();
         if (!mInVr) return;
         if (mShowingDaydreamDoff) {
             onExitVrResult(true);
@@ -1094,6 +1158,23 @@
         mRestoreSystemUiVisibilityFlag = -1;
     }
 
+    private void addOverlayView() {
+        if (mOverlayView != null) return;
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
+        FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
+        mOverlayView = new View(mActivity);
+        mOverlayView.setBackgroundColor(Color.BLACK);
+        decor.addView(mOverlayView, -1, params);
+    }
+
+    private void removeOverlayView() {
+        if (mOverlayView == null) return;
+        FrameLayout decor = (FrameLayout) sInstance.mActivity.getWindow().getDecorView();
+        decor.removeView(mOverlayView);
+        mOverlayView = null;
+    }
+
     /**
      * Clean up VrShell, and associated native objects.
      */
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 44bd37a..f5c2bb7 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3520,6 +3520,8 @@
       "obsolete_system/obsolete_system_win.cc",
       "pdf/pdf_extension_util.cc",
       "pdf/pdf_extension_util.h",
+      "policy/local_sync_policy_handler.cc",
+      "policy/local_sync_policy_handler.h",
       "process_singleton_modal_dialog_lock.cc",
       "process_singleton_modal_dialog_lock.h",
       "process_singleton_posix.cc",
diff --git a/chrome/browser/android/metrics/uma_session_stats.cc b/chrome/browser/android/metrics/uma_session_stats.cc
index 2358ad98..6f266f0 100644
--- a/chrome/browser/android/metrics/uma_session_stats.cc
+++ b/chrome/browser/android/metrics/uma_session_stats.cc
@@ -151,6 +151,8 @@
   DCHECK(pref);
   int value = pref->GetInteger(metrics::prefs::kStabilityRendererCrashCount);
   pref->SetInteger(metrics::prefs::kStabilityRendererCrashCount, value + 1);
+  // Migrate proto to histogram to repurpose proto count.
+  UMA_HISTOGRAM_BOOLEAN("Stability.Android.RendererCrash", true);
 }
 
 static void RegisterExternalExperiment(
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 2b2f6729..1d65fd5 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3990,6 +3990,55 @@
 }
 
 #if defined(USE_AURA)
+// This verifies the fix for crbug.com/694393 .
+IN_PROC_BROWSER_TEST_P(WebViewScrollGuestContentTest,
+                       OverscrollControllerSeesConsumedScrollsInGuest) {
+  // This test is only relevant for non-OOPIF WebView as OOPIF-based WebView
+  // uses different scroll bubbling logic.
+  DCHECK(
+      !base::FeatureList::IsEnabled(::features::kGuestViewCrossProcessFrames));
+
+  LoadAppWithGuest("web_view/scrollable_embedder_and_guest");
+
+  content::WebContents* embedder_contents = GetEmbedderWebContents();
+
+  std::vector<content::WebContents*> guest_web_contents_list;
+  GetGuestViewManager()->WaitForNumGuestsCreated(1u);
+  GetGuestViewManager()->GetGuestWebContentsList(&guest_web_contents_list);
+  ASSERT_EQ(1u, guest_web_contents_list.size());
+
+  content::WebContents* guest_contents = guest_web_contents_list[0];
+  content::RenderWidgetHostView* guest_host_view =
+      guest_contents->GetRenderWidgetHostView();
+
+  gfx::Rect embedder_rect = embedder_contents->GetContainerBounds();
+  gfx::Rect guest_rect = guest_contents->GetContainerBounds();
+  guest_rect.set_x(guest_rect.x() - embedder_rect.x());
+  guest_rect.set_y(guest_rect.y() - embedder_rect.y());
+
+  content::RenderWidgetHostView* embedder_host_view =
+      embedder_contents->GetRenderWidgetHostView();
+  EXPECT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
+  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+
+  // If we scroll the guest, the OverscrollController for the
+  // RenderWidgetHostViewAura should see that the scroll was consumed.
+  // If it doesn't, this test will time out indicating failure.
+  content::MockOverscrollController* mock_overscroll_controller =
+      content::MockOverscrollController::Create(embedder_host_view);
+
+  gfx::Point guest_scroll_location(guest_rect.width() / 2, 0);
+  float gesture_distance = 15.f;
+  // It's sufficient to scroll vertically, since all we need to test is that
+  // the OverscrollController sees consumed scrolls.
+  content::SimulateGestureScrollSequence(guest_contents, guest_scroll_location,
+                                         gfx::Vector2dF(0, -gesture_distance));
+
+  mock_overscroll_controller->WaitForConsumedScroll();
+}
+#endif
+
+#if defined(USE_AURA)
 // TODO(wjmaclean): when WebViewTest is re-enabled on the site-isolation
 // bots, then re-enable this test class as well.
 // https://crbug.com/503751
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index bfa6f696..c9c6d7c 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -135,7 +135,6 @@
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
-#include "ui/views/focus/view_storage.h"
 #elif defined(OS_MACOSX)
 #include "chrome/browser/chrome_browser_main_mac.h"
 #endif
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 4981e0b..b80cb13d 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -78,6 +78,7 @@
 
 #if !defined(OS_ANDROID)
 #include "chrome/browser/download/download_dir_policy_handler.h"
+#include "chrome/browser/policy/local_sync_policy_handler.h"
 #endif
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -669,11 +670,8 @@
   { key::kRoamingProfileSupportEnabled,
     syncer::prefs::kEnableLocalSyncBackend,
     base::Value::Type::BOOLEAN },
-  { key::kRoamingProfileLocation,
-    syncer::prefs::kLocalSyncBackendDir,
-    base::Value::Type::STRING },
 
-  { key::kNetworkTimeQueriesEnabled,
+  { key::kBrowserNetworkTimeQueriesEnabled,
     network_time::prefs::kNetworkTimeQueriesEnabled,
     base::Value::Type::BOOLEAN },
 };
@@ -922,6 +920,7 @@
 
 #if !defined(OS_ANDROID)
   handlers->AddHandler(base::WrapUnique(new DownloadDirPolicyHandler));
+  handlers->AddHandler(base::MakeUnique<LocalSyncPolicyHandler>());
 
   handlers->AddHandler(base::MakeUnique<SimpleSchemaValidatingPolicyHandler>(
       key::kRegisteredProtocolHandlers,
diff --git a/chrome/browser/policy/local_sync_policy_handler.cc b/chrome/browser/policy/local_sync_policy_handler.cc
new file mode 100644
index 0000000..88758efee
--- /dev/null
+++ b/chrome/browser/policy/local_sync_policy_handler.cc
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/local_sync_policy_handler.h"
+
+#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
+#include "chrome/browser/policy/policy_path_parser.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_value_map.h"
+#include "components/sync/base/pref_names.h"
+
+namespace policy {
+
+LocalSyncPolicyHandler::LocalSyncPolicyHandler()
+    : TypeCheckingPolicyHandler(key::kRoamingProfileLocation,
+                                base::Value::Type::STRING) {}
+
+LocalSyncPolicyHandler::~LocalSyncPolicyHandler() {}
+
+void LocalSyncPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
+                                                 PrefValueMap* prefs) {
+  const base::Value* value = policies.GetValue(policy_name());
+  base::FilePath::StringType string_value;
+  if (value && value->GetAsString(&string_value)) {
+    base::FilePath::StringType expanded_value =
+        policy::path_parser::ExpandPathVariables(string_value);
+    prefs->SetValue(syncer::prefs::kLocalSyncBackendDir,
+                    base::MakeUnique<base::Value>(expanded_value));
+  }
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/local_sync_policy_handler.h b/chrome/browser/policy/local_sync_policy_handler.h
new file mode 100644
index 0000000..99e9802
--- /dev/null
+++ b/chrome/browser/policy/local_sync_policy_handler.h
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_LOCAL_SYNC_POLICY_HANDLER_H_
+#define CHROME_BROWSER_POLICY_LOCAL_SYNC_POLICY_HANDLER_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "components/policy/core/browser/configuration_policy_handler.h"
+
+namespace policy {
+
+// ConfigurationPolicyHandler for the RoamingProfileLocation policy.
+class LocalSyncPolicyHandler : public TypeCheckingPolicyHandler {
+ public:
+  LocalSyncPolicyHandler();
+  ~LocalSyncPolicyHandler() override;
+
+  // ConfigurationPolicyHandler methods:
+  void ApplyPolicySettings(const PolicyMap& policies,
+                           PrefValueMap* prefs) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LocalSyncPolicyHandler);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_LOCAL_SYNC_POLICY_HANDLER_H_
diff --git a/chrome/browser/policy/local_sync_policy_handler_unittest.cc b/chrome/browser/policy/local_sync_policy_handler_unittest.cc
new file mode 100644
index 0000000..075c586
--- /dev/null
+++ b/chrome/browser/policy/local_sync_policy_handler_unittest.cc
@@ -0,0 +1,56 @@
+// 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 <string>
+
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
+#include "chrome/browser/policy/local_sync_policy_handler.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_value_map.h"
+#include "components/sync/base/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+class LocalSyncPolicyTest : public testing::Test {
+ protected:
+  PolicyMap policy_;
+  LocalSyncPolicyHandler handler_;
+  PrefValueMap prefs_;
+};
+
+TEST_F(LocalSyncPolicyTest, Default) {
+  handler_.ApplyPolicySettings(policy_, &prefs_);
+  EXPECT_FALSE(prefs_.GetValue(syncer::prefs::kLocalSyncBackendDir, nullptr));
+}
+
+// RoamingProfileLocation policy expects a string; give it a boolean.
+TEST_F(LocalSyncPolicyTest, SetPolicyInvalid) {
+  policy_.Set(key::kRoamingProfileLocation, POLICY_LEVEL_MANDATORY,
+              POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+              base::MakeUnique<base::Value>(false), nullptr);
+  handler_.ApplyPolicySettings(policy_, &prefs_);
+  EXPECT_FALSE(prefs_.GetValue(syncer::prefs::kLocalSyncBackendDir, nullptr));
+}
+
+// Use a variable in the value. It should be expanded by the handler.
+TEST_F(LocalSyncPolicyTest, SetPolicyValid) {
+  const std::string in = "${user_name}/foo";
+  policy_.Set(key::kRoamingProfileLocation, POLICY_LEVEL_MANDATORY,
+              POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+              base::MakeUnique<base::Value>(in), nullptr);
+  handler_.ApplyPolicySettings(policy_, &prefs_);
+
+  const base::Value* value;
+  ASSERT_TRUE(prefs_.GetValue(syncer::prefs::kLocalSyncBackendDir, &value));
+  std::string out;
+  ASSERT_TRUE(value->GetAsString(&out));
+  EXPECT_NE(std::string::npos, out.find("foo"));
+  EXPECT_EQ(std::string::npos, out.find("${user_name}"));
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index b7eae5b..cfcd519 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -4547,7 +4547,7 @@
 IN_PROC_BROWSER_TEST_F(NetworkTimePolicyTest, NetworkTimeQueriesDisabled) {
   // Set a policy to disable network time queries.
   PolicyMap policies;
-  policies.Set(key::kNetworkTimeQueriesEnabled, POLICY_LEVEL_MANDATORY,
+  policies.Set(key::kBrowserNetworkTimeQueriesEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                base::MakeUnique<base::Value>(false), nullptr);
   UpdateProviderPolicy(policies);
@@ -4573,7 +4573,7 @@
   EXPECT_EQ(0u, num_requests());
 
   // Now enable the policy and check that a network time query is sent.
-  policies.Set(key::kNetworkTimeQueriesEnabled, POLICY_LEVEL_MANDATORY,
+  policies.Set(key::kBrowserNetworkTimeQueriesEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                base::MakeUnique<base::Value>(true), nullptr);
   UpdateProviderPolicy(policies);
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
index ca881350..ccb342d 100644
--- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
+++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
@@ -131,6 +131,14 @@
               blink::WebGestureEvent::kMomentumPhase) {
         return;
       }
+      // GestureScrollBegin and GestureScrollEnd events are created to wrap
+      // individual resent GestureScrollUpdates from a plugin. Hence these
+      // should not be used to indicate the beginning/end of the swipe gesture.
+      // TODO(mcnee): When we remove BrowserPlugin, delete this code.
+      // See crbug.com/533069
+      if (event.resending_plugin_id != -1) {
+        return;
+      }
       waitingForFirstGestureScroll_ = YES;
       break;
     case blink::WebInputEvent::kGestureScrollUpdate:
diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc
index 5a4d93b..487b3e58 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host.cc
@@ -14,7 +14,6 @@
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/scrollbar_size.h"
 #include "ui/views/focus/external_focus_tracker.h"
-#include "ui/views/focus/view_storage.h"
 #include "ui/views/widget/widget.h"
 
 // static
diff --git a/chrome/browser/ui/views/find_bar_host.cc b/chrome/browser/ui/views/find_bar_host.cc
index 81c33c9..311921d 100644
--- a/chrome/browser/ui/views/find_bar_host.cc
+++ b/chrome/browser/ui/views/find_bar_host.cc
@@ -18,7 +18,6 @@
 #include "ui/events/event.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/views/focus/external_focus_tracker.h"
-#include "ui/views/focus/view_storage.h"
 #include "ui/views/widget/root_view.h"
 #include "ui/views/widget/widget.h"
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 8fe09989..ef9ffcd2 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -68,7 +68,6 @@
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/native_theme/native_theme_aura.h"
 #include "ui/vector_icons/vector_icons.h"
-#include "ui/views/focus/view_storage.h"
 #include "ui/views/widget/tooltip_manager.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/non_client_view.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8fa665c0..39fd326 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3724,6 +3724,7 @@
       "../browser/media/router/mojo/media_route_controller_unittest.cc",
       "../browser/media/router/mojo/media_router_mojo_impl_unittest.cc",
       "../browser/media/router/mojo/media_router_mojo_metrics_unittest.cc",
+      "../browser/policy/local_sync_policy_handler_unittest.cc",
       "../browser/renderer_context_menu/render_view_context_menu_test_util.cc",
       "../browser/renderer_context_menu/render_view_context_menu_test_util.h",
       "../browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 5e7d51dd..4870a688 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -3078,9 +3078,9 @@
     ]
   },
 
-  "NetworkTimeQueriesEnabled": {
+  "BrowserNetworkTimeQueriesEnabled": {
     "os": ["win", "linux", "mac", "chromeos"],
-    "test_policy": { "NetworkTimeQueriesEnabled": true },
+    "test_policy": { "BrowserNetworkTimeQueriesEnabled": true },
     "pref_mappings": [
       { "pref": "network_time.network_time_queries_enabled",
         "local_state": true
diff --git a/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc b/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
index 816addcb..c0e86025 100644
--- a/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
@@ -73,7 +73,7 @@
 }
 
 AutocompleteSyncableService::~AutocompleteSyncableService() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 // static
@@ -106,7 +106,7 @@
     const syncer::SyncDataList& initial_sync_data,
     std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
     std::unique_ptr<syncer::SyncErrorFactory> error_handler) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!sync_processor_);
   DCHECK(sync_processor);
   DCHECK(error_handler);
@@ -167,7 +167,7 @@
 }
 
 void AutocompleteSyncableService::StopSyncing(syncer::ModelType type) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(syncer::AUTOFILL, type);
 
   sync_processor_.reset();
@@ -176,7 +176,7 @@
 
 syncer::SyncDataList AutocompleteSyncableService::GetAllSyncData(
     syncer::ModelType type) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_processor_);
   DCHECK_EQ(type, syncer::AUTOFILL);
 
@@ -195,7 +195,7 @@
 syncer::SyncError AutocompleteSyncableService::ProcessSyncChanges(
     const tracked_objects::Location& from_here,
     const syncer::SyncChangeList& change_list) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_processor_);
 
   if (!sync_processor_) {
@@ -290,7 +290,7 @@
 
 bool AutocompleteSyncableService::SaveChangesToWebData(
     const std::vector<AutofillEntry>& new_entries) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!GetAutofillTable()->UpdateAutofillEntries(new_entries))
     return false;
 
diff --git a/components/autofill/core/browser/webdata/autocomplete_syncable_service.h b/components/autofill/core/browser/webdata/autocomplete_syncable_service.h
index 52932be..c94383b7 100644
--- a/components/autofill/core/browser/webdata/autocomplete_syncable_service.h
+++ b/components/autofill/core/browser/webdata/autocomplete_syncable_service.h
@@ -13,8 +13,8 @@
 
 #include "base/macros.h"
 #include "base/scoped_observer.h"
+#include "base/sequence_checker.h"
 #include "base/supports_user_data.h"
-#include "base/threading/non_thread_safe.h"
 #include "components/autofill/core/browser/webdata/autofill_change.h"
 #include "components/autofill/core/browser/webdata/autofill_entry.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
@@ -49,8 +49,7 @@
 class AutocompleteSyncableService
     : public base::SupportsUserData::Data,
       public syncer::SyncableService,
-      public AutofillWebDataServiceObserverOnDBThread,
-      public base::NonThreadSafe {
+      public AutofillWebDataServiceObserverOnDBThread {
  public:
   ~AutocompleteSyncableService() override;
 
@@ -162,6 +161,8 @@
 
   syncer::SyncableService::StartSyncFlare flare_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AutocompleteSyncableService);
 };
 
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
index 1fa55f74..e67793d 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
@@ -63,7 +63,7 @@
 }
 
 AutofillProfileSyncableService::~AutofillProfileSyncableService() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 // static
@@ -95,7 +95,7 @@
     const syncer::SyncDataList& initial_sync_data,
     std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
     std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!sync_processor_.get());
   DCHECK(sync_processor.get());
   DCHECK(sync_error_factory.get());
@@ -205,7 +205,7 @@
 }
 
 void AutofillProfileSyncableService::StopSyncing(syncer::ModelType type) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(type, syncer::AUTOFILL_PROFILE);
 
   sync_processor_.reset();
@@ -216,7 +216,7 @@
 
 syncer::SyncDataList AutofillProfileSyncableService::GetAllSyncData(
     syncer::ModelType type) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_processor_.get());
   DCHECK_EQ(type, syncer::AUTOFILL_PROFILE);
 
@@ -229,7 +229,7 @@
 syncer::SyncError AutofillProfileSyncableService::ProcessSyncChanges(
     const tracked_objects::Location& from_here,
     const syncer::SyncChangeList& change_list) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!sync_processor_.get()) {
     syncer::SyncError error(FROM_HERE,
                             syncer::SyncError::DATATYPE_ERROR,
@@ -295,7 +295,7 @@
 
 bool AutofillProfileSyncableService::SaveChangesToWebData(
     const DataBundle& bundle) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   AutofillTable* autofill_table = GetAutofillTable();
 
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
index bed681d..8972048 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
+++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
@@ -12,9 +12,9 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/scoped_observer.h"
+#include "base/sequence_checker.h"
 #include "base/supports_user_data.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/non_thread_safe.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/webdata/autofill_change.h"
 #include "components/autofill/core/browser/webdata/autofill_entry.h"
@@ -48,8 +48,7 @@
 class AutofillProfileSyncableService
     : public base::SupportsUserData::Data,
       public syncer::SyncableService,
-      public AutofillWebDataServiceObserverOnDBThread,
-      public base::NonThreadSafe {
+      public AutofillWebDataServiceObserverOnDBThread {
  public:
   ~AutofillProfileSyncableService() override;
 
@@ -194,6 +193,8 @@
 
   syncer::SyncableService::StartSyncFlare flare_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AutofillProfileSyncableService);
 };
 
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc
index 4ac9eab..1c463d3 100644
--- a/components/cronet/android/cronet_library_loader.cc
+++ b/components/cronet/android/cronet_library_loader.cc
@@ -13,7 +13,6 @@
 #include "base/android/jni_registrar.h"
 #include "base/android/jni_utils.h"
 #include "base/android/library_loader/library_loader_hooks.h"
-#include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -102,9 +101,6 @@
 #endif
 
   base::FeatureList::InitializeInstance(std::string(), std::string());
-  // TODO(bengr): Remove once Data Reduction Proxy no longer needs this for
-  // configuration information.
-  base::CommandLine::Init(0, nullptr);
   DCHECK(!base::MessageLoop::current());
   DCHECK(!g_init_message_loop);
   g_init_message_loop =
diff --git a/components/drive/service/drive_api_service.cc b/components/drive/service/drive_api_service.cc
index 89672e6..fd0a027 100644
--- a/components/drive/service/drive_api_service.cc
+++ b/components/drive/service/drive_api_service.cc
@@ -189,6 +189,7 @@
 }
 
 BatchRequestConfigurator::~BatchRequestConfigurator() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // The batch requst has not been committed.
   if (batch_request_)
     cancel_callback_.Run();
@@ -203,7 +204,7 @@
     const UploadNewFileOptions& options,
     const google_apis::FileResourceCallback& callback,
     const google_apis::ProgressCallback& progress_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!callback.is_null());
 
   std::unique_ptr<google_apis::BatchableDelegate> delegate(
@@ -230,7 +231,7 @@
     const UploadExistingFileOptions& options,
     const google_apis::FileResourceCallback& callback,
     const google_apis::ProgressCallback& progress_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!callback.is_null());
 
   std::unique_ptr<google_apis::BatchableDelegate> delegate(
@@ -250,7 +251,7 @@
 }
 
 void BatchRequestConfigurator::Commit() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!batch_request_)
     return;
   batch_request_->Commit();
diff --git a/components/drive/service/drive_api_service.h b/components/drive/service/drive_api_service.h
index b83e0b0..78d8092 100644
--- a/components/drive/service/drive_api_service.h
+++ b/components/drive/service/drive_api_service.h
@@ -14,6 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/sequence_checker.h"
 #include "base/threading/thread_checker.h"
 #include "components/drive/service/drive_service_interface.h"
 #include "google_apis/drive/auth_service_interface.h"
@@ -44,8 +45,7 @@
 namespace drive {
 
 // Builder for batch request returned by |DriveAPIService|.
-class BatchRequestConfigurator : public BatchRequestConfiguratorInterface,
-                                 public base::NonThreadSafe {
+class BatchRequestConfigurator : public BatchRequestConfiguratorInterface {
  public:
   BatchRequestConfigurator(
       const base::WeakPtr<google_apis::drive::BatchUploadRequest>&
@@ -82,6 +82,8 @@
   google_apis::DriveApiUrlGenerator url_generator_;
   google_apis::CancelCallback cancel_callback_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(BatchRequestConfigurator);
 };
 
diff --git a/components/favicon/core/large_icon_service.cc b/components/favicon/core/large_icon_service.cc
index bc2ebc2e..a6587e9 100644
--- a/components/favicon/core/large_icon_service.cc
+++ b/components/favicon/core/large_icon_service.cc
@@ -46,7 +46,7 @@
 
 const char kCheckSeenParam[] = "check_seen=true&";
 
-const int kGoogleServerV2EnforcedMinSizeInPixel = 32;
+const int kGoogleServerV2EnforcedMinSizeInPixel = 16;
 const char kGoogleServerV2EnforcedMinSizeInPixelParam[] =
     "enforced_min_size_in_pixel";
 
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc
index 36a6167..71f3235 100644
--- a/components/ntp_snippets/content_suggestions_service.cc
+++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -207,12 +207,14 @@
   // TODO(jkrcal): Create a general wrapper function in LargeIconService that
   // does handle the get-from-cache-and-fallback-to-google-server functionality
   // in one shot (for all clients that do not need to react in between).
+
+  // Use desired_size = 0 for getting the icon from the cache (so that the icon
+  // is not poorly rescaled by LargeIconService).
   large_icon_service_->GetLargeIconImageOrFallbackStyle(
-      publisher_url, minimum_size_in_pixel, desired_size_in_pixel,
+      publisher_url, minimum_size_in_pixel, /*desired_size_in_pixel=*/0,
       base::Bind(&ContentSuggestionsService::OnGetFaviconFromCacheFinished,
                  base::Unretained(this), publisher_url, minimum_size_in_pixel,
-                 /*desired_size_in_pixel=*/0, callback,
-                 continue_to_google_server),
+                 desired_size_in_pixel, callback, continue_to_google_server),
       &favicons_task_tracker_);
 }
 
diff --git a/components/ntp_tiles/constants.cc b/components/ntp_tiles/constants.cc
index 20bf4c36..6af7a172 100644
--- a/components/ntp_tiles/constants.cc
+++ b/components/ntp_tiles/constants.cc
@@ -18,9 +18,6 @@
 extern const base::Feature kNtpMostLikelyFaviconsFromServerFeature{
     "NTPMostLikelyFaviconsFromServer", base::FEATURE_DISABLED_BY_DEFAULT};
 
-extern const base::Feature kPinHomePageAsTileFeature{
-    "PinHomePageAsTile", base::FEATURE_DISABLED_BY_DEFAULT};
-
 bool AreNtpMostLikelyFaviconsFromServerEnabled() {
   // Check if the experimental flag is forced on or off.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/components/ntp_tiles/constants.h b/components/ntp_tiles/constants.h
index 6619450..4af8d544 100644
--- a/components/ntp_tiles/constants.h
+++ b/components/ntp_tiles/constants.h
@@ -23,9 +23,6 @@
 // Likely tiles on the New Tab Page.
 extern const base::Feature kNtpMostLikelyFaviconsFromServerFeature;
 
-// Feature to pin any set home page as first tile.
-extern const base::Feature kPinHomePageAsTileFeature;
-
 // Use this to find out whether the kNtpMostLikelyFaviconsFromServerFeature is
 // enabled. This helper function abstracts iOS special way to override the
 // feature (via command-line params).
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 81fe916..f0307c60 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -479,8 +479,7 @@
 }
 
 bool MostVisitedSites::ShouldAddHomeTile() const {
-  return base::FeatureList::IsEnabled(kPinHomePageAsTileFeature) &&
-         num_sites_ > 0u &&
+  return num_sites_ > 0u &&
          home_page_client_ &&  // No platform-specific implementation - no tile.
          home_page_client_->IsHomePageEnabled() &&
          !home_page_client_->IsNewTabPageUsedAsHomePage() &&
diff --git a/components/ntp_tiles/most_visited_sites_unittest.cc b/components/ntp_tiles/most_visited_sites_unittest.cc
index c20ff799..09c16d9 100644
--- a/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -437,8 +437,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldIncludeTileForHomePage) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   DisableRemoteSuggestions();
@@ -456,8 +454,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageWithoutClient) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   DisableRemoteSuggestions();
   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_, false))
       .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
@@ -470,29 +466,7 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageIfFeatureDisabled) {
-  base::test::ScopedFeatureList features;
-  features.InitAndDisableFeature(ntp_tiles::kPinHomePageAsTileFeature);
-  FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
-  home_page_client->SetHomePageEnabled(true);
-  DisableRemoteSuggestions();
-  EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_, false))
-      .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
-  EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
-  EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomePageUrl))))
-      .Times(AnyNumber())
-      .WillRepeatedly(Return(false));
-  EXPECT_CALL(mock_observer_,
-              OnMostVisitedURLsAvailable(Not(Contains(
-                  MatchesTile("", kHomePageUrl, TileSource::HOMEPAGE)))));
-  most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
-                                                  /*num_sites=*/3);
-  base::RunLoop().RunUntilIdle();
-}
-
 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageIfNoTileRequested) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   DisableRemoteSuggestions();
@@ -509,8 +483,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldReturnOnlyHomePageIfOneTileRequested) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   DisableRemoteSuggestions();
@@ -530,8 +502,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldDeduplicateHomePageWithTopSites) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   DisableRemoteSuggestions();
@@ -554,8 +524,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageIfItIsNewTabPage) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   home_page_client->SetNtpIsHomePage(true);
@@ -575,8 +543,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageIfThereIsNone) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(false);
   DisableRemoteSuggestions();
@@ -596,8 +562,6 @@
 
 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageIfEmptyUrl) {
   const std::string kEmptyHomePageUrl;
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   home_page_client->SetHomePageUrl(GURL(kEmptyHomePageUrl));
@@ -617,8 +581,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomePageIfBlacklisted) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
   DisableRemoteSuggestions();
@@ -643,8 +605,6 @@
 }
 
 TEST_P(MostVisitedSitesTest, ShouldPinHomePageAgainIfBlacklistingUndone) {
-  base::test::ScopedFeatureList features;
-  features.InitAndEnableFeature(ntp_tiles::kPinHomePageAsTileFeature);
   FakeHomePageClient* home_page_client = RegisterNewHomePageClient();
   home_page_client->SetHomePageEnabled(true);
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index a727a0a..0a92960 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -9549,10 +9549,10 @@
       If this policy is left not set, the default is not allowed for enterprise-managed users and allowed for non-managed users.''',
     },
     {
-      'name': 'NetworkTimeQueriesEnabled',
+      'name': 'BrowserNetworkTimeQueriesEnabled',
       'type': 'main',
       'schema': { 'type': 'boolean' },
-      'supported_on': ['chrome.*:60-', 'chrome_os:60-'],
+      'supported_on': ['chrome.*:60-'],
       'features': {
         'dynamic_refresh': True,
         'per_profile': True,
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index cbd7258..d8dfac8 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -733,6 +733,23 @@
     }
   }
 
+  // TODO(mcnee): Allow the root RWHV to consume the child's
+  // GestureScrollUpdates. This is needed to prevent the child from consuming
+  // them after the root has started an overscroll.
+  // See crbug.com/713368
+
+  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
+InputEventAckState RenderWidgetHostViewChildFrame::FilterChildGestureEvent(
+    const blink::WebGestureEvent& gesture_event) {
+  // We may be the owner of a RenderWidgetHostViewGuest,
+  // so we talk to the root RWHV on its behalf.
+  // TODO(mcnee): Remove once MimeHandlerViewGuest is based on OOPIF.
+  // See crbug.com/659750
+  if (frame_connector_)
+    return frame_connector_->GetRootRenderWidgetHostView()
+        ->FilterChildGestureEvent(gesture_event);
   return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 }
 
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h
index e7c5915..e2c7555 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -166,6 +166,8 @@
 
   InputEventAckState FilterInputEvent(
       const blink::WebInputEvent& input_event) override;
+  InputEventAckState FilterChildGestureEvent(
+      const blink::WebGestureEvent& gesture_event) override;
   void OnSetNeedsFlushInput() override;
   BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
       BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index b7e4883..7d6ef8cb 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -203,8 +203,8 @@
     // touch. Sends a synthetic event for the focusing side effect.
     // TODO(wjmaclean): When we remove BrowserPlugin, delete this code.
     // http://crbug.com/533069
-    MaybeSendSyntheticTapGesture(event.touches[0].position,
-                                 event.touches[0].screen_position);
+    MaybeSendSyntheticTapGesture(event.touches[0].PositionInWidget(),
+                                 event.touches[0].PositionInScreen());
   }
 
   host_->ForwardTouchEventWithLatencyInfo(event, latency);
@@ -554,9 +554,38 @@
                       ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
   // GestureScrollBegin/End are always consumed by the guest, so we only
   // forward GestureScrollUpdate.
+  // Consumed GestureScrollUpdates and GestureScrollBegins must still be
+  // forwarded to the owner RWHV so it may update its state.
   if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
-      not_consumed)
+      not_consumed) {
     guest_->ResendEventToEmbedder(event);
+  } else if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
+             event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
+    GetOwnerRenderWidgetHostView()->GestureEventAck(event, ack_result);
+  }
+}
+
+InputEventAckState RenderWidgetHostViewGuest::FilterInputEvent(
+    const blink::WebInputEvent& input_event) {
+  InputEventAckState ack_state =
+      RenderWidgetHostViewChildFrame::FilterInputEvent(input_event);
+  if (ack_state != INPUT_EVENT_ACK_STATE_NOT_CONSUMED)
+    return ack_state;
+
+  // The owner RWHV may want to consume the guest's GestureScrollUpdates.
+  // Also, we don't resend GestureFlingStarts, GestureScrollBegins, or
+  // GestureScrollEnds, so we let the owner RWHV know about them here.
+  if (input_event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
+      input_event.GetType() == blink::WebInputEvent::kGestureFlingStart ||
+      input_event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
+      input_event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
+    const blink::WebGestureEvent& gesture_event =
+        static_cast<const blink::WebGestureEvent&>(input_event);
+    return GetOwnerRenderWidgetHostView()->FilterChildGestureEvent(
+        gesture_event);
+  }
+
+  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 }
 
 bool RenderWidgetHostViewGuest::IsRenderWidgetHostViewGuest() {
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h
index e85a8d6..db302a3a 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -126,6 +126,9 @@
   void GestureEventAck(const blink::WebGestureEvent& event,
                        InputEventAckState ack_result) override;
 
+  InputEventAckState FilterInputEvent(
+      const blink::WebInputEvent& input_event) override;
+
   bool IsRenderWidgetHostViewGuest() override;
   RenderWidgetHostViewBase* GetOwnerRenderWidgetHostView() const;
 
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index a9c9cb76..8466893 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -628,11 +628,11 @@
     if (touch_point->state == blink::WebTouchPoint::kStateMoved) {
       const gfx::Point& last_position = global_touch_position_[touch_point->id];
       touch_point->movement_x =
-          touch_point->screen_position.x - last_position.x();
+          touch_point->PositionInScreen().x - last_position.x();
       touch_point->movement_y =
-          touch_point->screen_position.y - last_position.y();
+          touch_point->PositionInScreen().y - last_position.y();
       global_touch_position_[touch_point->id].SetPoint(
-          touch_point->screen_position.x, touch_point->screen_position.y);
+          touch_point->PositionInScreen().x, touch_point->PositionInScreen().y);
     } else {
       touch_point->movement_x = 0;
       touch_point->movement_y = 0;
@@ -642,8 +642,9 @@
       } else if (touch_point->state == blink::WebTouchPoint::kStatePressed) {
         DCHECK(global_touch_position_.find(touch_point->id) ==
                global_touch_position_.end());
-        global_touch_position_[touch_point->id] = gfx::Point(
-            touch_point->screen_position.x, touch_point->screen_position.y);
+        global_touch_position_[touch_point->id] =
+            gfx::Point(touch_point->PositionInScreen().x,
+                       touch_point->PositionInScreen().y);
       }
     }
   }
diff --git a/content/browser/renderer_host/input/input_router_impl_perftest.cc b/content/browser/renderer_host/input/input_router_impl_perftest.cc
index 394380b..84f2430 100644
--- a/content/browser/renderer_host/input/input_router_impl_perftest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_perftest.cc
@@ -160,19 +160,19 @@
   touch.touches_length = 1;
   touch.touches[0].id = 0;
   touch.touches[0].state = WebTouchPoint::kStatePressed;
-  touch.touches[0].position.x = origin.x();
-  touch.touches[0].position.y = origin.y();
-  touch.touches[0].screen_position.x = origin.x();
-  touch.touches[0].screen_position.y = origin.y();
+  touch.touches[0].SetPositionInWidget(origin.x(), origin.y());
+  touch.touches[0].SetPositionInScreen(origin.x(), origin.y());
   touches.push_back(touch);
 
   touch.SetType(WebInputEvent::kTouchMove);
   touch.touches[0].state = WebTouchPoint::kStateMoved;
   for (size_t i = 0; i < steps; ++i) {
-    touch.touches[0].position.x += delta.x();
-    touch.touches[0].position.y += delta.y();
-    touch.touches[0].screen_position.x += delta.x();
-    touch.touches[0].screen_position.y += delta.y();
+    touch.touches[0].SetPositionInWidget(
+        touch.touches[0].PositionInWidget().x + delta.x(),
+        touch.touches[0].PositionInWidget().y + delta.y());
+    touch.touches[0].SetPositionInScreen(
+        touch.touches[0].PositionInScreen().x + delta.x(),
+        touch.touches[0].PositionInScreen().y + delta.y());
     touches.push_back(touch);
   }
 
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 21fde0e9..c6b52ea 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -2093,33 +2093,33 @@
     const WebTouchEvent* sent_event = GetSentWebInputEvent<WebTouchEvent>();
     ASSERT_EQ(2u, sent_event->touches_length);
     EXPECT_EQ(state, sent_event->touches[0].state);
-    EXPECT_EQ(20, sent_event->touches[0].position.x);
-    EXPECT_EQ(40, sent_event->touches[0].position.y);
-    EXPECT_EQ(10, sent_event->touches[0].screen_position.x);
-    EXPECT_EQ(20, sent_event->touches[0].screen_position.y);
+    EXPECT_EQ(20, sent_event->touches[0].PositionInWidget().x);
+    EXPECT_EQ(40, sent_event->touches[0].PositionInWidget().y);
+    EXPECT_EQ(10, sent_event->touches[0].PositionInScreen().x);
+    EXPECT_EQ(20, sent_event->touches[0].PositionInScreen().y);
     EXPECT_EQ(2, sent_event->touches[0].radius_x);
     EXPECT_EQ(2, sent_event->touches[0].radius_y);
 
-    EXPECT_EQ(200, sent_event->touches[1].position.x);
-    EXPECT_EQ(400, sent_event->touches[1].position.y);
-    EXPECT_EQ(100, sent_event->touches[1].screen_position.x);
-    EXPECT_EQ(200, sent_event->touches[1].screen_position.y);
+    EXPECT_EQ(200, sent_event->touches[1].PositionInWidget().x);
+    EXPECT_EQ(400, sent_event->touches[1].PositionInWidget().y);
+    EXPECT_EQ(100, sent_event->touches[1].PositionInScreen().x);
+    EXPECT_EQ(200, sent_event->touches[1].PositionInScreen().y);
     EXPECT_EQ(2, sent_event->touches[1].radius_x);
     EXPECT_EQ(2, sent_event->touches[1].radius_y);
 
     const WebTouchEvent* filter_event = GetFilterWebInputEvent<WebTouchEvent>();
     ASSERT_EQ(2u, filter_event->touches_length);
-    EXPECT_EQ(10, filter_event->touches[0].position.x);
-    EXPECT_EQ(20, filter_event->touches[0].position.y);
-    EXPECT_EQ(10, filter_event->touches[0].screen_position.x);
-    EXPECT_EQ(20, filter_event->touches[0].screen_position.y);
+    EXPECT_EQ(10, filter_event->touches[0].PositionInWidget().x);
+    EXPECT_EQ(20, filter_event->touches[0].PositionInWidget().y);
+    EXPECT_EQ(10, filter_event->touches[0].PositionInScreen().x);
+    EXPECT_EQ(20, filter_event->touches[0].PositionInScreen().y);
     EXPECT_EQ(1, filter_event->touches[0].radius_x);
     EXPECT_EQ(1, filter_event->touches[0].radius_y);
 
-    EXPECT_EQ(100, filter_event->touches[1].position.x);
-    EXPECT_EQ(200, filter_event->touches[1].position.y);
-    EXPECT_EQ(100, filter_event->touches[1].screen_position.x);
-    EXPECT_EQ(200, filter_event->touches[1].screen_position.y);
+    EXPECT_EQ(100, filter_event->touches[1].PositionInWidget().x);
+    EXPECT_EQ(200, filter_event->touches[1].PositionInWidget().y);
+    EXPECT_EQ(100, filter_event->touches[1].PositionInScreen().x);
+    EXPECT_EQ(200, filter_event->touches[1].PositionInScreen().y);
     EXPECT_EQ(1, filter_event->touches[1].radius_x);
     EXPECT_EQ(1, filter_event->touches[1].radius_y);
   }
diff --git a/content/browser/renderer_host/input/legacy_touch_event_queue.cc b/content/browser/renderer_host/input/legacy_touch_event_queue.cc
index 393229e..79e27c4 100644
--- a/content/browser/renderer_host/input/legacy_touch_event_queue.cc
+++ b/content/browser/renderer_host/input/legacy_touch_event_queue.cc
@@ -32,8 +32,8 @@
 bool HasPointChanged(const WebTouchPoint& point_1,
                      const WebTouchPoint& point_2) {
   DCHECK_EQ(point_1.id, point_2.id);
-  if (point_1.screen_position != point_2.screen_position ||
-      point_1.position != point_2.position ||
+  if (point_1.PositionInScreen() != point_2.PositionInScreen() ||
+      point_1.PositionInWidget() != point_2.PositionInWidget() ||
       point_1.radius_x != point_2.radius_x ||
       point_1.radius_y != point_2.radius_y ||
       point_1.rotation_angle != point_2.rotation_angle ||
diff --git a/content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc b/content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc
index b87871d..c346dde 100644
--- a/content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc
+++ b/content/browser/renderer_host/input/legacy_touch_event_queue_unittest.cc
@@ -115,9 +115,9 @@
     if (slop_length_dips_) {
       event.moved_beyond_slop_region = false;
       if (WebTouchEventTraits::IsTouchSequenceStart(event))
-        anchor_ = event.touches[0].position;
+        anchor_ = event.touches[0].PositionInWidget();
       if (event.GetType() == WebInputEvent::kTouchMove) {
-        gfx::Vector2dF delta = anchor_ - event.touches[0].position;
+        gfx::Vector2dF delta = anchor_ - event.touches[0].PositionInWidget();
         if (delta.LengthSquared() > slop_length_dips_ * slop_length_dips_)
           event.moved_beyond_slop_region = true;
       }
@@ -1790,8 +1790,8 @@
   EXPECT_EQ(2U, all_sent_events().size());
   EXPECT_EQ(WebInputEvent::kTouchMove, all_sent_events()[0].GetType());
   EXPECT_NE(WebInputEvent::kBlocking, all_sent_events()[0].dispatch_type);
-  EXPECT_EQ(0, all_sent_events()[0].touches[0].position.x);
-  EXPECT_EQ(0, all_sent_events()[0].touches[0].position.y);
+  EXPECT_EQ(0, all_sent_events()[0].touches[0].PositionInWidget().x);
+  EXPECT_EQ(0, all_sent_events()[0].touches[0].PositionInWidget().y);
   EXPECT_EQ(WebInputEvent::kTouchEnd, all_sent_events()[1].GetType());
   EXPECT_NE(WebInputEvent::kBlocking, all_sent_events()[1].dispatch_type);
   EXPECT_EQ(2U, GetAndResetSentEventCount());
@@ -2151,8 +2151,10 @@
     EXPECT_EQ(2U, all_sent_events().size());
     EXPECT_EQ(WebInputEvent::kTouchMove, all_sent_events()[0].GetType());
     EXPECT_NE(WebInputEvent::kBlocking, all_sent_events()[0].dispatch_type);
-    EXPECT_EQ(10 + 10 * i, all_sent_events()[0].touches[0].position.x);
-    EXPECT_EQ(10 + 10 * i, all_sent_events()[0].touches[0].position.y);
+    EXPECT_EQ(10 + 10 * i,
+              all_sent_events()[0].touches[0].PositionInWidget().x);
+    EXPECT_EQ(10 + 10 * i,
+              all_sent_events()[0].touches[0].PositionInWidget().y);
     EXPECT_EQ(static_cast<size_t>(i + 2),
               uncancelable_touch_moves_pending_ack_count());
     EXPECT_EQ(WebInputEvent::kTouchStart, all_sent_events()[1].GetType());
diff --git a/content/browser/renderer_host/input/motion_event_web.cc b/content/browser/renderer_host/input/motion_event_web.cc
index 0286eee..20931c2 100644
--- a/content/browser/renderer_host/input/motion_event_web.cc
+++ b/content/browser/renderer_host/input/motion_event_web.cc
@@ -99,22 +99,22 @@
 
 float MotionEventWeb::GetX(size_t pointer_index) const {
   DCHECK_LT(pointer_index, GetPointerCount());
-  return event_.touches[pointer_index].position.x;
+  return event_.touches[pointer_index].PositionInWidget().x;
 }
 
 float MotionEventWeb::GetY(size_t pointer_index) const {
   DCHECK_LT(pointer_index, GetPointerCount());
-  return event_.touches[pointer_index].position.y;
+  return event_.touches[pointer_index].PositionInWidget().y;
 }
 
 float MotionEventWeb::GetRawX(size_t pointer_index) const {
   DCHECK_LT(pointer_index, GetPointerCount());
-  return event_.touches[pointer_index].screen_position.x;
+  return event_.touches[pointer_index].PositionInScreen().x;
 }
 
 float MotionEventWeb::GetRawY(size_t pointer_index) const {
   DCHECK_LT(pointer_index, GetPointerCount());
-  return event_.touches[pointer_index].screen_position.y;
+  return event_.touches[pointer_index].PositionInScreen().y;
 }
 
 float MotionEventWeb::GetTouchMajor(size_t pointer_index) const {
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
index ae2131f..329290e 100644
--- a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
+++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
@@ -28,8 +28,8 @@
 bool HasPointChanged(const WebTouchPoint& point_1,
                      const WebTouchPoint& point_2) {
   DCHECK_EQ(point_1.id, point_2.id);
-  if (point_1.screen_position != point_2.screen_position ||
-      point_1.position != point_2.position ||
+  if (point_1.PositionInScreen() != point_2.PositionInScreen() ||
+      point_1.PositionInWidget() != point_2.PositionInWidget() ||
       point_1.radius_x != point_2.radius_x ||
       point_1.radius_y != point_2.radius_y ||
       point_1.rotation_angle != point_2.rotation_angle ||
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
index e138306e..1b76ac6 100644
--- a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
+++ b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -116,9 +116,9 @@
     if (slop_length_dips_) {
       event.moved_beyond_slop_region = false;
       if (WebTouchEventTraits::IsTouchSequenceStart(event))
-        anchor_ = event.touches[0].position;
+        anchor_ = event.touches[0].PositionInWidget();
       if (event.GetType() == WebInputEvent::kTouchMove) {
-        gfx::Vector2dF delta = anchor_ - event.touches[0].position;
+        gfx::Vector2dF delta = anchor_ - event.touches[0].PositionInWidget();
         if (delta.LengthSquared() > slop_length_dips_ * slop_length_dips_)
           event.moved_beyond_slop_region = true;
       }
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index 4483b36..1280173 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -208,16 +208,16 @@
 
     if (!started_) {
       ASSERT_EQ(touch_event.GetType(), WebInputEvent::kTouchStart);
-      start_.SetPoint(touch_event.touches[0].position.x,
-                      touch_event.touches[0].position.y);
+      start_.SetPoint(touch_event.touches[0].PositionInWidget().x,
+                      touch_event.touches[0].PositionInWidget().y);
       last_touch_point_ = gfx::PointF(start_);
       started_ = true;
     } else {
       ASSERT_NE(touch_event.GetType(), WebInputEvent::kTouchStart);
       ASSERT_NE(touch_event.GetType(), WebInputEvent::kTouchCancel);
 
-      gfx::PointF touch_point(touch_event.touches[0].position.x,
-                              touch_event.touches[0].position.y);
+      gfx::PointF touch_point(touch_event.touches[0].PositionInWidget().x,
+                              touch_event.touches[0].PositionInWidget().y);
       gfx::Vector2dF delta = touch_point - last_touch_point_;
       total_abs_move_distance_length_ += delta.Length();
 
@@ -292,8 +292,8 @@
     if (!started_) {
       ASSERT_EQ(touch_event.GetType(), WebInputEvent::kTouchStart);
 
-      start_0_ = gfx::PointF(touch_event.touches[0].position);
-      start_1_ = gfx::PointF(touch_event.touches[1].position);
+      start_0_ = gfx::PointF(touch_event.touches[0].PositionInWidget());
+      start_1_ = gfx::PointF(touch_event.touches[1].PositionInWidget());
       last_pointer_distance_ = (start_0_ - start_1_).Length();
       initial_pointer_distance_ = last_pointer_distance_;
       EXPECT_GE(initial_pointer_distance_, GetMinScalingSpanInDips());
@@ -303,8 +303,10 @@
       ASSERT_NE(touch_event.GetType(), WebInputEvent::kTouchStart);
       ASSERT_NE(touch_event.GetType(), WebInputEvent::kTouchCancel);
 
-      gfx::PointF current_0 = gfx::PointF(touch_event.touches[0].position);
-      gfx::PointF current_1 = gfx::PointF(touch_event.touches[1].position);
+      gfx::PointF current_0 =
+          gfx::PointF(touch_event.touches[0].PositionInWidget());
+      gfx::PointF current_1 =
+          gfx::PointF(touch_event.touches[1].PositionInWidget());
 
       float pointer_distance = (current_0 - current_1).Length();
 
@@ -457,14 +459,15 @@
     switch (state_) {
       case NOT_STARTED:
         EXPECT_EQ(touch_event.GetType(), WebInputEvent::kTouchStart);
-        position_ = gfx::PointF(touch_event.touches[0].position);
+        position_ = gfx::PointF(touch_event.touches[0].PositionInWidget());
         start_time_ = base::TimeDelta::FromMilliseconds(
             static_cast<int64_t>(touch_event.TimeStampSeconds() * 1000));
         state_ = STARTED;
         break;
       case STARTED:
         EXPECT_EQ(touch_event.GetType(), WebInputEvent::kTouchEnd);
-        EXPECT_EQ(position_, gfx::PointF(touch_event.touches[0].position));
+        EXPECT_EQ(position_,
+                  gfx::PointF(touch_event.touches[0].PositionInWidget()));
         stop_time_ = base::TimeDelta::FromMilliseconds(
             static_cast<int64_t>(touch_event.TimeStampSeconds() * 1000));
         state_ = FINISHED;
@@ -537,7 +540,7 @@
     type_ = touch_event.GetType();
     for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) {
       indexes_[i] = touch_event.touches[i].id;
-      positions_[i] = gfx::PointF(touch_event.touches[i].position);
+      positions_[i] = gfx::PointF(touch_event.touches[i].PositionInWidget());
       states_[i] = touch_event.touches[i].state;
     }
     touch_length_ = touch_event.touches_length;
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_android.cc b/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
index 717e008..f9482534 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_target_android.cc
@@ -74,7 +74,8 @@
   const unsigned num_touches = web_touch.touches_length;
   for (unsigned i = 0; i < num_touches; ++i) {
     const blink::WebTouchPoint* point = &web_touch.touches[i];
-    TouchSetPointer(env, i, point->position.x, point->position.y, point->id);
+    TouchSetPointer(env, i, point->PositionInWidget().x,
+                    point->PositionInWidget().y, point->id);
   }
 
   TouchInject(env, action, num_touches,
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
index 60019ad..a2c6b302 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -57,8 +57,8 @@
     // Check that all touch pointers are within the content bounds.
     for (unsigned i = 0; i < web_touch.touches_length; i++)
       CHECK(web_touch.touches[i].state != WebTouchPoint::kStatePressed ||
-            PointIsWithinContents(web_touch.touches[i].position.x,
-                                  web_touch.touches[i].position.y))
+            PointIsWithinContents(web_touch.touches[i].PositionInWidget().x,
+                                  web_touch.touches[i].PositionInWidget().y))
           << "Touch coordinates are not within content bounds on TouchStart.";
 
     DispatchWebTouchEventToPlatform(web_touch, latency_info);
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
index 07773e5..abf6780 100644
--- a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -98,7 +98,7 @@
     type_ = touch_event.GetType();
     for (size_t i = 0; i < WebTouchEvent::kTouchesLengthCap; ++i) {
       indexes_[i] = touch_event.touches[i].id;
-      positions_[i] = gfx::PointF(touch_event.touches[i].position);
+      positions_[i] = gfx::PointF(touch_event.touches[i].PositionInWidget());
       states_[i] = touch_event.touches[i].state;
     }
     touch_length_ = touch_event.touches_length;
diff --git a/content/browser/renderer_host/input/touch_emulator.cc b/content/browser/renderer_host/input/touch_emulator.cc
index ac58300..4f6eb86e 100644
--- a/content/browser/renderer_host/input/touch_emulator.cc
+++ b/content/browser/renderer_host/input/touch_emulator.cc
@@ -470,10 +470,10 @@
   point.radius_y = 0.5f * cursor_size_.height();
   point.force = eventType == WebInputEvent::kTouchEnd ? 0.f : 1.f;
   point.rotation_angle = 0.f;
-  point.position.x = mouse_event.PositionInWidget().x;
-  point.screen_position.x = mouse_event.PositionInScreen().x;
-  point.position.y = mouse_event.PositionInWidget().y;
-  point.screen_position.y = mouse_event.PositionInScreen().y;
+  point.SetPositionInWidget(mouse_event.PositionInWidget().x,
+                            mouse_event.PositionInWidget().y);
+  point.SetPositionInScreen(mouse_event.PositionInScreen().x,
+                            mouse_event.PositionInScreen().y);
   point.tilt_x = 0;
   point.tilt_y = 0;
   point.pointer_type = blink::WebPointerProperties::PointerType::kTouch;
diff --git a/content/browser/renderer_host/input/touch_emulator_unittest.cc b/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 5cee142a..139d5a6 100644
--- a/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -66,8 +66,8 @@
   void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) override {
     forwarded_events_.push_back(event.GetType());
     EXPECT_EQ(1U, event.touches_length);
-    EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
-    EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
+    EXPECT_EQ(last_mouse_x_, event.touches[0].PositionInWidget().x);
+    EXPECT_EQ(last_mouse_y_, event.touches[0].PositionInWidget().y);
     const int all_buttons =
         WebInputEvent::kLeftButtonDown | WebInputEvent::kMiddleButtonDown |
         WebInputEvent::kRightButtonDown | WebInputEvent::kBackButtonDown |
@@ -203,10 +203,8 @@
     event.touches_length = 1;
     event.touches[0].id = 0;
     event.touches[0].state = state;
-    event.touches[0].position.x = x;
-    event.touches[0].position.y = y;
-    event.touches[0].screen_position.x = x;
-    event.touches[0].screen_position.y = y;
+    event.touches[0].SetPositionInWidget(x, y);
+    event.touches[0].SetPositionInScreen(x, y);
     return event;
   }
 
diff --git a/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/content/browser/renderer_host/input/web_input_event_util_unittest.cc
index 0f16e5a..4f8f418 100644
--- a/content/browser/renderer_host/input/web_input_event_util_unittest.cc
+++ b/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -58,9 +58,8 @@
     WebTouchPoint expected_pointer;
     expected_pointer.id = pointer.id;
     expected_pointer.state = WebTouchPoint::kStatePressed;
-    expected_pointer.position = blink::WebFloatPoint(pointer.x, pointer.y);
-    expected_pointer.screen_position =
-        blink::WebFloatPoint(pointer.raw_x, pointer.raw_y);
+    expected_pointer.SetPositionInWidget(pointer.x, pointer.y);
+    expected_pointer.SetPositionInScreen(pointer.raw_x, pointer.raw_y);
     expected_pointer.radius_x = pointer.touch_major / 2.f;
     expected_pointer.radius_y = pointer.touch_minor / 2.f;
     expected_pointer.rotation_angle = 0.f;
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index ef9fcafc..7f32ae0 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -51,6 +51,16 @@
     case blink::WebInputEvent::kGestureScrollEnd: {
       const blink::WebGestureEvent& gesture =
           static_cast<const blink::WebGestureEvent&>(event);
+
+      // GestureScrollBegin and GestureScrollEnd events are created to wrap
+      // individual resent GestureScrollUpdates from a plugin. Hence these
+      // should not be used to indicate the beginning/end of the overscroll.
+      // TODO(mcnee): When we remove BrowserPlugin, delete this code.
+      // See crbug.com/533069
+      if (gesture.resending_plugin_id != -1 &&
+          event.GetType() != blink::WebInputEvent::kGestureScrollUpdate)
+        return false;
+
       blink::WebGestureEvent::ScrollUnits scrollUnits;
       switch (event.GetType()) {
         case blink::WebInputEvent::kGestureScrollBegin:
diff --git a/content/browser/renderer_host/overscroll_controller.h b/content/browser/renderer_host/overscroll_controller.h
index 4e6134d..ebb9fc8 100644
--- a/content/browser/renderer_host/overscroll_controller.h
+++ b/content/browser/renderer_host/overscroll_controller.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 
@@ -38,8 +39,11 @@
 // status accordingly.
 class OverscrollController {
  public:
-  OverscrollController();
-  virtual ~OverscrollController();
+  // Exported for testing.
+  // TODO(mcnee): Tests needing CONTENT_EXPORT are BrowserPlugin specific.
+  // Remove after removing BrowserPlugin (crbug.com/533069).
+  CONTENT_EXPORT OverscrollController();
+  CONTENT_EXPORT virtual ~OverscrollController();
 
   // This must be called when dispatching any event from the
   // RenderWidgetHostView so that the state of the overscroll gesture can be
@@ -49,7 +53,12 @@
 
   // This must be called when the ACK for any event comes in. This updates the
   // overscroll gesture status as appropriate.
-  void ReceivedEventACK(const blink::WebInputEvent& event, bool processed);
+  // Virtual and exported for testing.
+  // TODO(mcnee): Tests needing CONTENT_EXPORT and virtual are BrowserPlugin
+  // specific. Remove after removing BrowserPlugin (crbug.com/533069).
+  CONTENT_EXPORT virtual void ReceivedEventACK(
+      const blink::WebInputEvent& event,
+      bool processed);
 
   // This must be called when a gesture event is filtered out and not sent to
   // the renderer.
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 4b92f18..fe73293b 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -22,8 +22,9 @@
 void TransformEventTouchPositions(blink::WebTouchEvent* event,
                                   const gfx::Vector2d& delta) {
   for (unsigned i = 0; i < event->touches_length; ++i) {
-    event->touches[i].position.x += delta.x();
-    event->touches[i].position.y += delta.y();
+    event->touches[i].SetPositionInWidget(
+        event->touches[i].PositionInWidget().x + delta.x(),
+        event->touches[i].PositionInWidget().y + delta.y());
   }
 }
 
@@ -370,8 +371,8 @@
         // of this sequence.
         DCHECK(!touch_target_.target);
         gfx::Point transformed_point;
-        gfx::Point original_point(event->touches[0].position.x,
-                                  event->touches[0].position.y);
+        gfx::Point original_point(event->touches[0].PositionInWidget().x,
+                                  event->touches[0].PositionInWidget().y);
         touch_target_.target =
             FindEventTarget(root_view, original_point, &transformed_point);
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index f62e781..bf51068 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1116,6 +1116,14 @@
                   : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 }
 
+InputEventAckState RenderWidgetHostViewAura::FilterChildGestureEvent(
+    const blink::WebGestureEvent& gesture_event) {
+  if (overscroll_controller_ &&
+      overscroll_controller_->WillHandleEvent(gesture_event))
+    return INPUT_EVENT_ACK_STATE_CONSUMED;
+  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
 BrowserAccessibilityManager*
 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
     BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
@@ -2103,6 +2111,11 @@
     overscroll_controller_.reset(new OverscrollController());
 }
 
+void RenderWidgetHostViewAura::SetOverscrollControllerForTesting(
+    std::unique_ptr<OverscrollController> controller) {
+  overscroll_controller_ = std::move(controller);
+}
+
 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
   // The top left corner of our view in window coordinates might not land on a
   // device pixel boundary if we have a non-integer device scale. In that case,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 9e8caf2..e0ca6486 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -155,6 +155,8 @@
       override;
   InputEventAckState FilterInputEvent(
       const blink::WebInputEvent& input_event) override;
+  InputEventAckState FilterChildGestureEvent(
+      const blink::WebGestureEvent& gesture_event) override;
   BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
       BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
   gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
@@ -292,6 +294,11 @@
   // Sets whether the overscroll controller should be enabled for this page.
   void SetOverscrollControllerEnabled(bool enabled);
 
+  // TODO(mcnee): Tests needing this are BrowserPlugin specific. Remove after
+  // removing BrowserPlugin (crbug.com/533069).
+  void SetOverscrollControllerForTesting(
+      std::unique_ptr<OverscrollController> controller);
+
   void SnapToPhysicalPixelBoundary();
 
   // Called when the context menu is about to be displayed.
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 527e5ea..9a6befb 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -188,6 +188,12 @@
   return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 }
 
+InputEventAckState RenderWidgetHostViewBase::FilterChildGestureEvent(
+    const blink::WebGestureEvent& gesture_event) {
+  // By default, do nothing with the child's gesture events.
+  return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
 void RenderWidgetHostViewBase::WheelEventAck(
     const blink::WebMouseWheelEvent& event,
     InputEventAckState ack_result) {
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 3f7581a..59aa4a1 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -193,6 +193,10 @@
   virtual InputEventAckState FilterInputEvent(
       const blink::WebInputEvent& input_event);
 
+  // Allows a root RWHV to filter gesture events in a child.
+  virtual InputEventAckState FilterChildGestureEvent(
+      const blink::WebGestureEvent& gesture_event);
+
   // Called by the host when it requires an input flush; the flush call should
   // by synchronized with BeginFrame.
   virtual void OnSetNeedsFlushInput() = 0;
diff --git a/content/browser/renderer_host/ui_events_helper.cc b/content/browser/renderer_host/ui_events_helper.cc
index 3e60adbe..8ee439c 100644
--- a/content/browser/renderer_host/ui_events_helper.cc
+++ b/content/browser/renderer_host/ui_events_helper.cc
@@ -74,9 +74,9 @@
     // ui events start in the co-ordinate space of the EventDispatcher.
     gfx::PointF location;
     if (coordinate_system == LOCAL_COORDINATES)
-      location = point.position;
+      location = point.PositionInWidget();
     else
-      location = point.screen_position;
+      location = point.PositionInScreen();
     auto uievent = base::MakeUnique<ui::TouchEvent>(
         type, gfx::Point(), timestamp,
         ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, point.id,
diff --git a/content/common/input/synthetic_web_input_event_builders.cc b/content/common/input/synthetic_web_input_event_builders.cc
index 5e5638e..b0c2d12f 100644
--- a/content/common/input/synthetic_web_input_event_builders.cc
+++ b/content/common/input/synthetic_web_input_event_builders.cc
@@ -196,8 +196,8 @@
     return -1;
   WebTouchPoint& point = touches[index];
   point.id = index;
-  point.position.x = point.screen_position.x = x;
-  point.position.y = point.screen_position.y = y;
+  point.SetPositionInWidget(x, y);
+  point.SetPositionInScreen(x, y);
   point.state = WebTouchPoint::kStatePressed;
   point.radius_x = point.radius_y = 1.f;
   point.rotation_angle = 1.f;
@@ -216,8 +216,8 @@
   // The caller can opt-out explicitly, if necessary.
   moved_beyond_slop_region = true;
   WebTouchPoint& point = touches[index];
-  point.position.x = point.screen_position.x = x;
-  point.position.y = point.screen_position.y = y;
+  point.SetPositionInWidget(x, y);
+  point.SetPositionInScreen(x, y);
   touches[index].state = WebTouchPoint::kStateMoved;
   WebTouchEventTraits::ResetType(WebInputEvent::kTouchMove, TimeStampSeconds(),
                                  this);
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index b9a3011..35c79b06 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -93,6 +93,7 @@
 #include "ui/resources/grit/webui_resources.h"
 
 #if defined(USE_AURA)
+#include "content/browser/renderer_host/overscroll_controller.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "ui/aura/test/window_event_dispatcher_test_api.h"
 #include "ui/aura/window.h"
@@ -2055,4 +2056,60 @@
                             privileged));
 }
 
+#if defined(USE_AURA)
+namespace {
+class MockOverscrollControllerImpl : public OverscrollController,
+                                     public MockOverscrollController {
+ public:
+  MockOverscrollControllerImpl()
+      : content_scrolling_(false),
+        message_loop_runner_(new MessageLoopRunner) {}
+  ~MockOverscrollControllerImpl() override {}
+
+  // OverscrollController:
+  void ReceivedEventACK(const blink::WebInputEvent& event,
+                        bool processed) override {
+    // Since we're only mocking this one method of OverscrollController and its
+    // other methods are non-virtual, we'll delegate to it so that it doesn't
+    // get into an inconsistent state.
+    OverscrollController::ReceivedEventACK(event, processed);
+
+    if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate &&
+        processed) {
+      content_scrolling_ = true;
+      if (message_loop_runner_->loop_running())
+        message_loop_runner_->Quit();
+    }
+  }
+
+  // MockOverscrollController:
+  void WaitForConsumedScroll() override {
+    if (!content_scrolling_)
+      message_loop_runner_->Run();
+  }
+
+ private:
+  bool content_scrolling_;
+  scoped_refptr<MessageLoopRunner> message_loop_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockOverscrollControllerImpl);
+};
+}  // namespace
+
+// static
+MockOverscrollController* MockOverscrollController::Create(
+    RenderWidgetHostView* rwhv) {
+  std::unique_ptr<MockOverscrollControllerImpl> mock =
+      base::MakeUnique<MockOverscrollControllerImpl>();
+  MockOverscrollController* raw_mock = mock.get();
+
+  RenderWidgetHostViewAura* rwhva =
+      static_cast<RenderWidgetHostViewAura*>(rwhv);
+  rwhva->SetOverscrollControllerForTesting(std::move(mock));
+
+  return raw_mock;
+}
+
+#endif  // defined(USE_AURA)
+
 }  // namespace content
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 4122a90..fdbacfe 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -850,6 +850,25 @@
   DISALLOW_COPY_AND_ASSIGN(PwnMessageHelper);
 };
 
+#if defined(USE_AURA)
+// Mock of an OverscrollController so we can inspect the scroll events that it
+// receives. Note that this is only a partial mock as the methods of a real
+// OverscrollController are being invoked.
+// TODO(mcnee): Tests needing this are BrowserPlugin specific. Remove after
+// removing BrowserPlugin (crbug.com/533069).
+class MockOverscrollController {
+ public:
+  // Creates a mock and installs it on the given RenderWidgetHostViewAura.
+  // The returned mock is owned by the RWHVA.
+  static MockOverscrollController* Create(RenderWidgetHostView* rwhv);
+
+  virtual ~MockOverscrollController() {}
+
+  // Waits until the mock receives a consumed GestureScrollUpdate.
+  virtual void WaitForConsumedScroll() = 0;
+};
+#endif  // defined(USE_AURA)
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_TEST_BROWSER_TEST_UTILS_H_
diff --git a/content/renderer/input/input_event_filter_unittest.cc b/content/renderer/input/input_event_filter_unittest.cc
index 7c33174..19e2c1b 100644
--- a/content/renderer/input/input_event_filter_unittest.cc
+++ b/content/renderer/input/input_event_filter_unittest.cc
@@ -543,8 +543,10 @@
 
     EXPECT_EQ(kEvents[3].size(), event.size());
     EXPECT_EQ(1u, kEvents[3].touches_length);
-    EXPECT_EQ(kEvents[3].touches[0].position.x, event.touches[0].position.x);
-    EXPECT_EQ(kEvents[3].touches[0].position.y, event.touches[0].position.y);
+    EXPECT_EQ(kEvents[3].touches[0].PositionInWidget().x,
+              event.touches[0].PositionInWidget().x);
+    EXPECT_EQ(kEvents[3].touches[0].PositionInWidget().y,
+              event.touches[0].PositionInWidget().y);
     EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING,
               dispatch_type);
   }
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc
index 047ba03..a84bdb3 100644
--- a/content/renderer/input/render_widget_input_handler.cc
+++ b/content/renderer/input/render_widget_input_handler.cc
@@ -368,7 +368,7 @@
     for (size_t i = 0; i < touch_event.touches_length; ++i) {
       if (touch_event.touches[i].state == WebTouchPoint::kStatePressed &&
           delegate_->HasTouchEventHandlersAt(
-              gfx::ToFlooredPoint(touch_event.touches[i].position))) {
+              gfx::ToFlooredPoint(touch_event.touches[i].PositionInWidget()))) {
         ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
         break;
       }
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc
index 5b15f807..d4366b5 100644
--- a/content/renderer/pepper/event_conversion.cc
+++ b/content/renderer/pepper/event_conversion.cc
@@ -260,8 +260,8 @@
     }
     PP_TouchPoint pp_pt;
     pp_pt.id = touch_point.id;
-    pp_pt.position.x = touch_point.position.x;
-    pp_pt.position.y = touch_point.position.y;
+    pp_pt.position.x = touch_point.PositionInWidget().x;
+    pp_pt.position.y = touch_point.PositionInWidget().y;
     pp_pt.radius.x = touch_point.radius_x;
     pp_pt.radius.y = touch_point.radius_y;
     pp_pt.rotation_angle = touch_point.rotation_angle;
@@ -306,11 +306,9 @@
   WebTouchPoint pt;
   pt.pointer_type = blink::WebPointerProperties::PointerType::kTouch;
   pt.id = pp_pt.id;
-  pt.position.x = pp_pt.position.x;
-  pt.position.y = pp_pt.position.y;
+  pt.SetPositionInWidget(pp_pt.position.x, pp_pt.position.y);
   // TODO(crbug.com/93902): Add screen coordinate calculation.
-  pt.screen_position.x = 0;
-  pt.screen_position.y = 0;
+  pt.SetPositionInScreen(0, 0);
   pt.force = pp_pt.pressure;
   pt.radius_x = pp_pt.radius.x;
   pt.radius_y = pp_pt.radius.y;
diff --git a/content/renderer/pepper/event_conversion_unittest.cc b/content/renderer/pepper/event_conversion_unittest.cc
index fdc93b9e..26595c9e 100644
--- a/content/renderer/pepper/event_conversion_unittest.cc
+++ b/content/renderer/pepper/event_conversion_unittest.cc
@@ -30,8 +30,10 @@
       ASSERT_NE(j, actual.touches_length);
       EXPECT_EQ(expected.touches[i].id, actual.touches[j].id);
       EXPECT_EQ(expected.touches[i].state, actual.touches[j].state);
-      EXPECT_EQ(expected.touches[i].position.x, actual.touches[j].position.x);
-      EXPECT_EQ(expected.touches[i].position.y, actual.touches[j].position.y);
+      EXPECT_EQ(expected.touches[i].PositionInWidget().x,
+                actual.touches[j].PositionInWidget().x);
+      EXPECT_EQ(expected.touches[i].PositionInWidget().y,
+                actual.touches[j].PositionInWidget().y);
       EXPECT_EQ(expected.touches[i].radius_x, actual.touches[j].radius_x);
       EXPECT_EQ(expected.touches[i].radius_y, actual.touches[j].radius_y);
       EXPECT_EQ(expected.touches[i].rotation_angle,
diff --git a/content/shell/test_runner/event_sender.cc b/content/shell/test_runner/event_sender.cc
index 3f20c73..d25385e 100644
--- a/content/shell/test_runner/event_sender.cc
+++ b/content/shell/test_runner/event_sender.cc
@@ -1875,8 +1875,8 @@
 
   WebTouchPoint* touch_point = &touch_points_[index];
   touch_point->state = WebTouchPoint::kStateMoved;
-  touch_point->position = WebFloatPoint(x, y);
-  touch_point->screen_position = touch_point->position;
+  touch_point->SetPositionInWidget(x, y);
+  touch_point->SetPositionInScreen(x, y);
 
   InitPointerProperties(args, touch_point, &touch_point->radius_x,
                         &touch_point->radius_y);
@@ -2082,8 +2082,8 @@
   WebTouchPoint touch_point;
   touch_point.pointer_type = WebPointerProperties::PointerType::kTouch;
   touch_point.state = WebTouchPoint::kStatePressed;
-  touch_point.position = WebFloatPoint(x, y);
-  touch_point.screen_position = touch_point.position;
+  touch_point.SetPositionInWidget(x, y);
+  touch_point.SetPositionInScreen(x, y);
 
   int highest_id = -1;
   for (size_t i = 0; i < touch_points_.size(); i++) {
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc
index bb7bdde..30f59f03 100644
--- a/content/shell/test_runner/test_plugin.cc
+++ b/content/shell/test_runner/test_plugin.cc
@@ -72,9 +72,9 @@
                     const blink::WebTouchPoint* points,
                     int length) {
   for (int i = 0; i < length; ++i) {
-    delegate->PrintMessage(
-        base::StringPrintf("* %.2f, %.2f: %s\n", points[i].position.x,
-                           points[i].position.y, PointState(points[i].state)));
+    delegate->PrintMessage(base::StringPrintf(
+        "* %.2f, %.2f: %s\n", points[i].PositionInWidget().x,
+        points[i].PositionInWidget().y, PointState(points[i].state)));
   }
 }
 
diff --git a/extensions/browser/api/api_resource_manager.h b/extensions/browser/api/api_resource_manager.h
index 064e7454..8626e21 100644
--- a/extensions/browser/api/api_resource_manager.h
+++ b/extensions/browser/api/api_resource_manager.h
@@ -14,7 +14,6 @@
 #include "base/scoped_observer.h"
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "content/public/browser/browser_thread.h"
@@ -89,7 +88,6 @@
 // }
 template <class T, typename ThreadingTraits = NamedThreadTraits<T>>
 class ApiResourceManager : public BrowserContextKeyedAPI,
-                           public base::NonThreadSafe,
                            public ExtensionRegistryObserver,
                            public ProcessManagerObserver {
  public:
@@ -102,7 +100,7 @@
   }
 
   virtual ~ApiResourceManager() {
-    DCHECK(CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     DCHECK(ThreadingTraits::IsMessageLoopValid())
         << "A unit test is using an ApiResourceManager but didn't provide "
            "the thread message loop needed for that kind of resource. "
@@ -365,6 +363,8 @@
       extension_registry_observer_;
   ScopedObserver<ProcessManager, ProcessManagerObserver>
       process_manager_observer_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 template <class T>
diff --git a/extensions/browser/extension_throttle_manager.cc b/extensions/browser/extension_throttle_manager.cc
index c33d0207..bc3a810a 100644
--- a/extensions/browser/extension_throttle_manager.cc
+++ b/extensions/browser/extension_throttle_manager.cc
@@ -40,6 +40,7 @@
 }
 
 ExtensionThrottleManager::~ExtensionThrottleManager() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
   net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
 
@@ -69,7 +70,9 @@
 
 scoped_refptr<ExtensionThrottleEntryInterface>
 ExtensionThrottleManager::RegisterRequestUrl(const GURL& url) {
-  DCHECK(!enable_thread_checks_ || CalledOnValidThread());
+#if DCHECK_IS_ON()
+  DCHECK(!enable_thread_checks_ || sequence_checker_.CalledOnValidSequence());
+#endif  // DCHECK_IS_ON()
 
   // Normalize the url.
   std::string url_id = GetIdFromUrl(url);
diff --git a/extensions/browser/extension_throttle_manager.h b/extensions/browser/extension_throttle_manager.h
index cad766b..6b4723a 100644
--- a/extensions/browser/extension_throttle_manager.h
+++ b/extensions/browser/extension_throttle_manager.h
@@ -11,7 +11,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/threading/platform_thread.h"
 #include "extensions/browser/extension_throttle_entry.h"
 #include "net/base/backoff_entry.h"
@@ -40,8 +40,7 @@
 // clean out outdated entries. URL ID consists of lowercased scheme, host, port
 // and path. All URLs converted to the same ID will share the same entry.
 class ExtensionThrottleManager
-    : NON_EXPORTED_BASE(public base::NonThreadSafe),
-      public net::NetworkChangeNotifier::IPAddressObserver,
+    : public net::NetworkChangeNotifier::IPAddressObserver,
       public net::NetworkChangeNotifier::ConnectionTypeObserver {
  public:
   ExtensionThrottleManager();
@@ -178,6 +177,8 @@
   // This is NULL when it is not set for tests.
   std::unique_ptr<net::BackoffEntry::Policy> backoff_policy_for_tests_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionThrottleManager);
 };
 
diff --git a/extensions/browser/quota_service.cc b/extensions/browser/quota_service.cc
index 99967d7..3d53713 100644
--- a/extensions/browser/quota_service.cc
+++ b/extensions/browser/quota_service.cc
@@ -33,7 +33,7 @@
 }
 
 QuotaService::~QuotaService() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   purge_timer_.Stop();
   Purge();
 }
@@ -42,7 +42,7 @@
                                  ExtensionFunction* function,
                                  const base::ListValue* args,
                                  const base::TimeTicks& event_time) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   if (function->ShouldSkipQuotaLimiting())
     return std::string();
@@ -86,7 +86,7 @@
 }
 
 void QuotaService::Purge() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   for (auto it = function_heuristics_.begin(); it != function_heuristics_.end();
        function_heuristics_.erase(it++)) {
     it->second.clear();
diff --git a/extensions/browser/quota_service.h b/extensions/browser/quota_service.h
index 433ea32..ef71f3c 100644
--- a/extensions/browser/quota_service.h
+++ b/extensions/browser/quota_service.h
@@ -24,7 +24,7 @@
 #include "base/compiler_specific.h"
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "base/values.h"
@@ -44,7 +44,7 @@
 // called and destroyed on the same thread, due to its use of a RepeatingTimer.
 // It is not a KeyedService because instances exist on both the UI
 // and IO threads.
-class QuotaService : public base::NonThreadSafe {
+class QuotaService {
  public:
   // Some concrete heuristics (declared below) that ExtensionFunctions can
   // use to help the service make decisions about quota violations.
@@ -91,6 +91,8 @@
   // Each heuristic will be evaluated and ANDed together to get a final answer.
   std::map<ExtensionId, FunctionHeuristicsMap> function_heuristics_;
 
+  THREAD_CHECKER(thread_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(QuotaService);
 };
 
diff --git a/extensions/browser/value_store/value_store_frontend.cc b/extensions/browser/value_store/value_store_frontend.cc
index 964fdbe..cf2379a 100644
--- a/extensions/browser/value_store/value_store_frontend.cc
+++ b/extensions/browser/value_store/value_store_frontend.cc
@@ -109,15 +109,17 @@
 ValueStoreFrontend::ValueStoreFrontend(
     const scoped_refptr<ValueStoreFactory>& store_factory,
     BackendType backend_type)
-    : backend_(new Backend(store_factory, backend_type)) {}
+    : backend_(new Backend(store_factory, backend_type)) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
 
 ValueStoreFrontend::~ValueStoreFrontend() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 void ValueStoreFrontend::Get(const std::string& key,
                              const ReadCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
       base::Bind(&ValueStoreFrontend::Backend::Get,
@@ -126,7 +128,7 @@
 
 void ValueStoreFrontend::Set(const std::string& key,
                              std::unique_ptr<base::Value> value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
       base::Bind(&ValueStoreFrontend::Backend::Set,
@@ -134,7 +136,7 @@
 }
 
 void ValueStoreFrontend::Remove(const std::string& key) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
       base::Bind(&ValueStoreFrontend::Backend::Remove,
diff --git a/extensions/browser/value_store/value_store_frontend.h b/extensions/browser/value_store/value_store_frontend.h
index 015c6f3..82d0a99 100644
--- a/extensions/browser/value_store/value_store_frontend.h
+++ b/extensions/browser/value_store/value_store_frontend.h
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/values.h"
 #include "extensions/browser/value_store/value_store.h"
 
@@ -21,9 +20,7 @@
 }  // namespace extensions
 
 // A frontend for a LeveldbValueStore, for use on the UI thread.
-class ValueStoreFrontend
-    : public base::SupportsWeakPtr<ValueStoreFrontend>,
-      public base::NonThreadSafe {
+class ValueStoreFrontend : public base::SupportsWeakPtr<ValueStoreFrontend> {
  public:
   // The kind of extensions data stored in a backend.
   enum class BackendType { RULES, STATE };
diff --git a/extensions/browser/warning_service.cc b/extensions/browser/warning_service.cc
index c6f643b..1f5cf12 100644
--- a/extensions/browser/warning_service.cc
+++ b/extensions/browser/warning_service.cc
@@ -16,14 +16,16 @@
 
 WarningService::WarningService(content::BrowserContext* browser_context)
     : browser_context_(browser_context), extension_registry_observer_(this) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (browser_context_) {
     extension_registry_observer_.Add(ExtensionRegistry::Get(
         ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context_)));
   }
 }
 
-WarningService::~WarningService() {}
+WarningService::~WarningService() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
 
 // static
 WarningService* WarningService::Get(content::BrowserContext* browser_context) {
@@ -32,7 +34,7 @@
 
 void WarningService::ClearWarnings(
     const std::set<Warning::WarningType>& types) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ExtensionIdSet affected_extensions;
   for (WarningSet::iterator i = warnings_.begin();
        i != warnings_.end();) {
@@ -50,7 +52,7 @@
 
 std::set<Warning::WarningType> WarningService::
     GetWarningTypesAffectingExtension(const std::string& extension_id) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::set<Warning::WarningType> result;
   for (WarningSet::const_iterator i = warnings_.begin();
        i != warnings_.end(); ++i) {
@@ -62,7 +64,7 @@
 
 std::vector<std::string> WarningService::GetWarningMessagesForExtension(
     const std::string& extension_id) const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::vector<std::string> result;
 
   const ExtensionSet& extension_set =
@@ -77,7 +79,7 @@
 }
 
 void WarningService::AddWarnings(const WarningSet& warnings) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ExtensionIdSet affected_extensions;
   for (const Warning& warning : warnings) {
diff --git a/extensions/browser/warning_service.h b/extensions/browser/warning_service.h
index 8fd3b633..5accc0d 100644
--- a/extensions/browser/warning_service.h
+++ b/extensions/browser/warning_service.h
@@ -11,7 +11,6 @@
 
 #include "base/observer_list.h"
 #include "base/scoped_observer.h"
-#include "base/threading/non_thread_safe.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/browser/warning_set.h"
@@ -30,9 +29,7 @@
 // conflicting modifications of network requests by extensions, slow extensions,
 // etc.) trigger a warning badge in the UI and and provide means to resolve
 // them. This class must be used on the UI thread only.
-class WarningService : public KeyedService,
-                       public ExtensionRegistryObserver,
-                       public base::NonThreadSafe {
+class WarningService : public KeyedService, public ExtensionRegistryObserver {
  public:
   class Observer {
    public:
diff --git a/extensions/browser/warning_service_unittest.cc b/extensions/browser/warning_service_unittest.cc
index 83a3ea0..96b6c5d3 100644
--- a/extensions/browser/warning_service_unittest.cc
+++ b/extensions/browser/warning_service_unittest.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/warning_service.h"
 
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extensions_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -45,6 +46,7 @@
 // Check that inserting a warning triggers notifications, whereas inserting
 // the same warning again is silent.
 TEST_F(WarningServiceTest, SetWarning) {
+  content::TestBrowserThreadBundle thread_bundle_;
   content::TestBrowserContext browser_context;
   TestWarningService warning_service(&browser_context);
   MockObserver observer;
@@ -68,6 +70,7 @@
 // Check that ClearWarnings deletes exactly the specified warnings and
 // triggers notifications where appropriate.
 TEST_F(WarningServiceTest, ClearWarnings) {
+  content::TestBrowserThreadBundle thread_bundle_;
   content::TestBrowserContext browser_context;
   TestWarningService warning_service(&browser_context);
   MockObserver observer;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
index 64020a71..1180cf6b 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -790,26 +790,7 @@
   // will also activate the text field.
   if (point.y < 0)
     point.y = 0;
-  UIView* view = [super hitTest:point withEvent:event];
-
-  // For some reason when the |leftView| has interaction enabled, hitTest
-  // returns the leftView even when |point| is 50 pixels to the right.  Tapping
-  // the hint text will fire the leftView, causing b/6281652. Fails especially
-  // on iPad and iPhone devices in landscape mode.
-  // TODO(crbug.com/546295): Check to see if this UIKit bug is fixed, and remove
-  // this workaround.
-  UIView* leftView = [self leftView];
-  if (leftView) {
-    if (leftView == view && !CGRectContainsPoint([leftView frame], point)) {
-      return self;
-    } else if ([self leftViewMode] == UITextFieldViewModeAlways) {
-      CGRect targetFrame = CGRectInset([leftView frame], -5, -5);
-      if (CGRectContainsPoint(targetFrame, point)) {
-        return leftView;
-      }
-    }
-  }
-  return view;
+  return [super hitTest:point withEvent:event];
 }
 
 - (BOOL)isTextFieldLTR {
diff --git a/media/audio/alsa/alsa_output.cc b/media/audio/alsa/alsa_output.cc
index f127c6f2..2edd276d 100644
--- a/media/audio/alsa/alsa_output.cc
+++ b/media/audio/alsa/alsa_output.cc
@@ -186,6 +186,7 @@
 }
 
 AlsaPcmOutputStream::~AlsaPcmOutputStream() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   InternalState current_state = state();
   DCHECK(current_state == kCreated ||
          current_state == kIsClosed ||
@@ -194,7 +195,7 @@
 }
 
 bool AlsaPcmOutputStream::Open() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (state() == kInError)
     return false;
@@ -252,7 +253,7 @@
 }
 
 void AlsaPcmOutputStream::Close() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (state() != kIsClosed)
     TransitionTo(kIsClosed);
@@ -280,7 +281,7 @@
 }
 
 void AlsaPcmOutputStream::Start(AudioSourceCallback* callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   CHECK(callback);
 
@@ -329,7 +330,7 @@
 }
 
 void AlsaPcmOutputStream::Stop() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Reset the callback, so that it is not called anymore.
   set_source_callback(NULL);
@@ -339,13 +340,13 @@
 }
 
 void AlsaPcmOutputStream::SetVolume(double volume) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   volume_ = static_cast<float>(volume);
 }
 
 void AlsaPcmOutputStream::GetVolume(double* volume) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   *volume = volume_;
 }
@@ -357,7 +358,7 @@
 }
 
 void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // If stopped, simulate a 0-length packet.
   if (stop_stream_) {
@@ -431,7 +432,7 @@
 }
 
 void AlsaPcmOutputStream::WritePacket() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // If the device is in error, just eat the bytes.
   if (stop_stream_) {
@@ -490,7 +491,7 @@
 }
 
 void AlsaPcmOutputStream::WriteTask() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (stop_stream_)
     return;
@@ -506,7 +507,7 @@
 }
 
 void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (stop_stream_ || state() != kIsPlaying)
     return;
@@ -633,7 +634,7 @@
 }
 
 snd_pcm_sframes_t AlsaPcmOutputStream::GetAvailableFrames() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (stop_stream_)
     return 0;
@@ -766,7 +767,7 @@
 
 AlsaPcmOutputStream::InternalState
 AlsaPcmOutputStream::TransitionTo(InternalState to) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!CanTransitionTo(to)) {
     NOTREACHED() << "Cannot transition from: " << state_ << " to: " << to;
@@ -800,7 +801,7 @@
 // Changes the AudioSourceCallback to proxy calls to.  Pass in NULL to
 // release ownership of the currently registered callback.
 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   source_callback_ = callback;
 }
 
diff --git a/media/audio/alsa/alsa_output.h b/media/audio/alsa/alsa_output.h
index e31776bf..f6f046a 100644
--- a/media/audio/alsa/alsa_output.h
+++ b/media/audio/alsa/alsa_output.h
@@ -32,8 +32,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "media/audio/audio_io.h"
@@ -46,8 +46,7 @@
 class ChannelMixer;
 class SeekableBuffer;
 
-class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream,
-                                         public base::NonThreadSafe {
+class MEDIA_EXPORT AlsaPcmOutputStream : public AudioOutputStream {
  public:
   // String for the generic "default" ALSA device that has the highest
   // compatibility and chance of working.
@@ -214,6 +213,8 @@
 
   std::unique_ptr<base::TickClock> tick_clock_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // Allows us to run tasks on the AlsaPcmOutputStream instance which are
   // bound by its lifetime.
   // NOTE: Weak pointers must be invalidated before all other member variables.
diff --git a/media/audio/sounds/audio_stream_handler.cc b/media/audio/sounds/audio_stream_handler.cc
index 614de24..fd42e86 100644
--- a/media/audio/sounds/audio_stream_handler.cc
+++ b/media/audio/sounds/audio_stream_handler.cc
@@ -197,7 +197,7 @@
 }
 
 AudioStreamHandler::~AudioStreamHandler() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (IsInitialized()) {
     AudioManager::Get()->GetTaskRunner()->PostTask(
         FROM_HERE, base::Bind(&AudioStreamContainer::Stop,
@@ -208,12 +208,12 @@
 }
 
 bool AudioStreamHandler::IsInitialized() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return !!stream_;
 }
 
 bool AudioStreamHandler::Play() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!IsInitialized())
     return false;
@@ -226,7 +226,7 @@
 }
 
 void AudioStreamHandler::Stop() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!IsInitialized())
     return;
@@ -237,7 +237,7 @@
 }
 
 base::TimeDelta AudioStreamHandler::duration() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return duration_;
 }
 
diff --git a/media/audio/sounds/audio_stream_handler.h b/media/audio/sounds/audio_stream_handler.h
index 009021f..0e1de61b 100644
--- a/media/audio/sounds/audio_stream_handler.h
+++ b/media/audio/sounds/audio_stream_handler.h
@@ -11,8 +11,8 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_piece.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/time.h"
 #include "media/audio/audio_io.h"
 #include "media/base/audio_parameters.h"
@@ -21,7 +21,7 @@
 namespace media {
 
 // This class sends a sound to the audio manager.
-class MEDIA_EXPORT AudioStreamHandler : public base::NonThreadSafe {
+class MEDIA_EXPORT AudioStreamHandler {
  public:
   class TestObserver {
    public:
@@ -71,6 +71,8 @@
   base::TimeDelta duration_;
   std::unique_ptr<AudioStreamContainer> stream_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AudioStreamHandler);
 };
 
diff --git a/media/audio/sounds/sounds_manager.cc b/media/audio/sounds/sounds_manager.cc
index c678645..46ba140 100644
--- a/media/audio/sounds/sounds_manager.cc
+++ b/media/audio/sounds/sounds_manager.cc
@@ -23,7 +23,9 @@
 class SoundsManagerImpl : public SoundsManager {
  public:
   SoundsManagerImpl() {}
-  ~SoundsManagerImpl() override { DCHECK(CalledOnValidThread()); }
+  ~SoundsManagerImpl() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  }
 
   // SoundsManager implementation:
   bool Initialize(SoundKey key, const base::StringPiece& data) override;
@@ -62,13 +64,13 @@
 }
 
 bool SoundsManagerImpl::Play(SoundKey key) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AudioStreamHandler* handler = GetHandler(key);
   return handler && handler->Play();
 }
 
 bool SoundsManagerImpl::Stop(SoundKey key) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AudioStreamHandler* handler = GetHandler(key);
   if (!handler)
     return false;
@@ -77,7 +79,7 @@
 }
 
 base::TimeDelta SoundsManagerImpl::GetDuration(SoundKey key) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   AudioStreamHandler* handler = GetHandler(key);
   return !handler ? base::TimeDelta() : handler->duration();
 }
@@ -94,7 +96,9 @@
 
 SoundsManager::SoundsManager() {}
 
-SoundsManager::~SoundsManager() { DCHECK(CalledOnValidThread()); }
+SoundsManager::~SoundsManager() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 // static
 void SoundsManager::Create() {
diff --git a/media/audio/sounds/sounds_manager.h b/media/audio/sounds/sounds_manager.h
index 004886d6..6faf6523 100644
--- a/media/audio/sounds/sounds_manager.h
+++ b/media/audio/sounds/sounds_manager.h
@@ -7,8 +7,8 @@
 
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_piece.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/time.h"
 #include "media/base/media_export.h"
 
@@ -16,7 +16,7 @@
 
 // This class is used for reproduction of system sounds. All methods
 // should be accessed from the Audio thread.
-class MEDIA_EXPORT SoundsManager : public base::NonThreadSafe {
+class MEDIA_EXPORT SoundsManager {
  public:
   typedef int SoundKey;
 
@@ -55,6 +55,8 @@
   SoundsManager();
   virtual ~SoundsManager();
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(SoundsManager);
 };
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index c1c44024..60f4865 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -103,11 +103,11 @@
 }
 
 WASAPIAudioInputStream::~WASAPIAudioInputStream() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 bool WASAPIAudioInputStream::Open() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(OPEN_RESULT_OK, open_result_);
 
   // Verify that we are not already opened.
@@ -160,7 +160,7 @@
 }
 
 void WASAPIAudioInputStream::Start(AudioInputCallback* callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(callback);
   DLOG_IF(ERROR, !opened_) << "Open() has not been called successfully";
   if (!opened_)
@@ -209,7 +209,7 @@
 }
 
 void WASAPIAudioInputStream::Stop() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(1) << "WASAPIAudioInputStream::Stop()";
   if (!started_)
     return;
@@ -278,7 +278,7 @@
 
 void WASAPIAudioInputStream::SetVolume(double volume) {
   DVLOG(1) << "SetVolume(volume=" << volume << ")";
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_GE(volume, 0.0);
   DCHECK_LE(volume, 1.0);
 
@@ -317,7 +317,7 @@
 
 bool WASAPIAudioInputStream::IsMuted() {
   DCHECK(opened_) << "Open() has not been called successfully";
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!opened_)
     return false;
 
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h
index c371beda..2cb36060 100644
--- a/media/audio/win/audio_low_latency_input_win.h
+++ b/media/audio/win/audio_low_latency_input_win.h
@@ -67,7 +67,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/simple_thread.h"
 #include "base/win/scoped_co_mem.h"
@@ -89,8 +89,7 @@
 class MEDIA_EXPORT WASAPIAudioInputStream
     : public AgcAudioStream<AudioInputStream>,
       public base::DelegateSimpleThread::Delegate,
-      public AudioConverter::InputCallback,
-      NON_EXPORTED_BASE(public base::NonThreadSafe) {
+      public AudioConverter::InputCallback {
  public:
   // The ctor takes all the usual parameters, plus |manager| which is the
   // the audio manager who is creating this object.
@@ -255,6 +254,8 @@
   std::unique_ptr<AudioBus> convert_bus_;
   bool imperfect_buffer_size_conversion_ = false;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(WASAPIAudioInputStream);
 };
 
diff --git a/media/midi/midi_manager_win.cc b/media/midi/midi_manager_win.cc
index c14d638..de73e13 100644
--- a/media/midi/midi_manager_win.cc
+++ b/media/midi/midi_manager_win.cc
@@ -148,6 +148,38 @@
 // TODO(toyoshim): Factor out TaskRunner related functionaliries above, and
 // deprecate MidiScheduler. It should be available via MidiManager::scheduler().
 
+// Obtains base::Lock instance pointer to protect
+// |g_midi_in_get_num_devs_thread_id|.
+base::Lock* GetMidiInGetNumDevsThreadIdLock() {
+  static base::Lock* lock = new base::Lock;
+  return lock;
+}
+
+// Holds a thread id that calls midiInGetNumDevs() now. We use a platform
+// primitive to identify the thread because the following functions can be
+// called on a thread that Windows allocates internally, and Chrome or //base
+// library does not know.
+base::PlatformThreadId g_midi_in_get_num_devs_thread_id;
+
+// Prepares to call midiInGetNumDevs().
+void EnterMidiInGetNumDevs() {
+  base::AutoLock lock(*GetMidiInGetNumDevsThreadIdLock());
+  g_midi_in_get_num_devs_thread_id = base::PlatformThread::CurrentId();
+}
+
+// Finalizes to call midiInGetNumDevs().
+void LeaveMidiInGetNumDevs() {
+  base::AutoLock lock(*GetMidiInGetNumDevsThreadIdLock());
+  g_midi_in_get_num_devs_thread_id = base::PlatformThreadId();
+}
+
+// Checks if the current thread is running midiInGetNumDevs(), that means
+// current code is invoked inside midiInGetNumDevs().
+bool IsRunningInsideMidiInGetNumDevs() {
+  base::AutoLock lock(*GetMidiInGetNumDevsThreadIdLock());
+  return base::PlatformThread::CurrentId() == g_midi_in_get_num_devs_thread_id;
+}
+
 // Utility class to handle MIDIHDR struct safely.
 class MIDIHDRDeleter {
  public:
@@ -319,7 +351,12 @@
       MidiManagerWin* manager,
       int instance_id) {
     std::vector<std::unique_ptr<InPort>> ports;
+
+    // Allow callback invocations indie midiInGetNumDevs().
+    EnterMidiInGetNumDevs();
     const UINT num_devices = midiInGetNumDevs();
+    LeaveMidiInGetNumDevs();
+
     for (UINT device_id = 0; device_id < num_devices; ++device_id) {
       MIDIINCAPS2W caps;
       MMRESULT result = midiInGetDevCaps(
@@ -579,7 +616,14 @@
 
   // Use |g_task_lock| so to ensure the instance can keep alive while running,
   // and to access member variables that are used on TaskRunner.
-  base::AutoLock task_lock(*GetTaskLock());
+  // Exceptionally, we do not take the lock when this callback is invoked inside
+  // midiInGetNumDevs() on the caller thread because the lock is already
+  // obtained by the current caller thread.
+  std::unique_ptr<base::AutoLock> task_lock;
+  if (IsRunningInsideMidiInGetNumDevs())
+    GetTaskLock()->AssertAcquired();
+  else
+    task_lock.reset(new base::AutoLock(*GetTaskLock()));
   {
     base::AutoLock lock(*GetInstanceIdLock());
     if (instance_id != g_active_instance_id)
diff --git a/remoting/base/oauth_token_getter_impl.cc b/remoting/base/oauth_token_getter_impl.cc
index 4f49a455..bb57c7db 100644
--- a/remoting/base/oauth_token_getter_impl.cc
+++ b/remoting/base/oauth_token_getter_impl.cc
@@ -56,12 +56,14 @@
   }
 }
 
-OAuthTokenGetterImpl::~OAuthTokenGetterImpl() {}
+OAuthTokenGetterImpl::~OAuthTokenGetterImpl() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void OAuthTokenGetterImpl::OnGetTokensResponse(const std::string& refresh_token,
                                                const std::string& access_token,
                                                int expires_seconds) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(intermediate_credentials_);
   VLOG(1) << "Received OAuth tokens.";
 
@@ -85,7 +87,7 @@
 void OAuthTokenGetterImpl::OnRefreshTokenResponse(
     const std::string& access_token,
     int expires_seconds) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(authorization_credentials_);
   VLOG(1) << "Received OAuth token.";
 
@@ -104,7 +106,7 @@
 
 void OAuthTokenGetterImpl::OnGetUserEmailResponse(
     const std::string& user_email) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(authorization_credentials_);
   VLOG(1) << "Received user info.";
 
@@ -148,7 +150,7 @@
     Status status,
     const std::string& user_email,
     const std::string& access_token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::queue<TokenCallback> callbacks(pending_callbacks_);
   pending_callbacks_ = std::queue<TokenCallback>();
 
@@ -161,14 +163,14 @@
 void OAuthTokenGetterImpl::NotifyUpdatedCallbacks(
     const std::string& user_email,
     const std::string& refresh_token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (credentials_updated_callback_) {
     credentials_updated_callback_.Run(user_email, refresh_token);
   }
 }
 
 void OAuthTokenGetterImpl::OnOAuthError() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   LOG(ERROR) << "OAuth: invalid credentials.";
   response_pending_ = false;
 
@@ -182,7 +184,7 @@
 }
 
 void OAuthTokenGetterImpl::OnNetworkError(int response_code) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   LOG(ERROR) << "Network error when trying to update OAuth token: "
              << response_code;
   response_pending_ = false;
@@ -191,7 +193,7 @@
 }
 
 void OAuthTokenGetterImpl::CallWithToken(const TokenCallback& on_access_token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (intermediate_credentials_) {
     pending_callbacks_.push(on_access_token);
     if (!response_pending_) {
@@ -216,12 +218,12 @@
 }
 
 void OAuthTokenGetterImpl::InvalidateCache() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   access_token_expiry_time_ = base::Time();
 }
 
 void OAuthTokenGetterImpl::GetOauthTokensFromAuthCode() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   VLOG(1) << "Fetching OAuth token from Auth Code.";
   DCHECK(!response_pending_);
 
@@ -254,7 +256,7 @@
 }
 
 void OAuthTokenGetterImpl::RefreshAccessToken() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   VLOG(1) << "Refreshing OAuth Access token.";
   DCHECK(!response_pending_);
 
diff --git a/remoting/base/oauth_token_getter_impl.h b/remoting/base/oauth_token_getter_impl.h
index c725d524..e5450a2 100644
--- a/remoting/base/oauth_token_getter_impl.h
+++ b/remoting/base/oauth_token_getter_impl.h
@@ -8,7 +8,7 @@
 #include <queue>
 
 #include "base/callback.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
@@ -29,7 +29,6 @@
 // On first usage it is likely an application will only have an auth code,
 // from this you can get a refresh token which can be reused next app launch.
 class OAuthTokenGetterImpl : public OAuthTokenGetter,
-                             public base::NonThreadSafe,
                              public gaia::GaiaOAuthClient::Delegate {
  public:
   OAuthTokenGetterImpl(
@@ -83,6 +82,8 @@
   base::Time access_token_expiry_time_;
   std::queue<OAuthTokenGetter::TokenCallback> pending_callbacks_;
   std::unique_ptr<base::OneShotTimer> refresh_timer_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 }  // namespace remoting
diff --git a/remoting/base/rate_counter.cc b/remoting/base/rate_counter.cc
index f676fc5..0d4acf2 100644
--- a/remoting/base/rate_counter.cc
+++ b/remoting/base/rate_counter.cc
@@ -13,10 +13,12 @@
   DCHECK_GT(time_window, base::TimeDelta());
 }
 
-RateCounter::~RateCounter() {}
+RateCounter::~RateCounter() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void RateCounter::Record(int64_t value) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::TimeTicks now = tick_clock_->NowTicks();
   EvictOldDataPoints(now);
@@ -25,7 +27,7 @@
 }
 
 double RateCounter::Rate() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   EvictOldDataPoints(tick_clock_->NowTicks());
   return sum_ / time_window_.InSecondsF();
diff --git a/remoting/base/rate_counter.h b/remoting/base/rate_counter.h
index a7e0f35..2950d82 100644
--- a/remoting/base/rate_counter.h
+++ b/remoting/base/rate_counter.h
@@ -11,7 +11,7 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/time/default_tick_clock.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
@@ -21,7 +21,7 @@
 // Measures average rate per second of a sequence of point rate samples
 // over a specified time window. This can be used to measure bandwidth, frame
 // rates, etc.
-class RateCounter : public base::NonThreadSafe {
+class RateCounter {
  public:
   // Constructs a rate counter over the specified |time_window|.
   explicit RateCounter(base::TimeDelta time_window);
@@ -57,6 +57,8 @@
   base::DefaultTickClock default_tick_clock_;
   base::TickClock* tick_clock_ = &default_tick_clock_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(RateCounter);
 };
 
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index adc33f4..ea0bfcb 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -174,6 +174,7 @@
     "host_status_logger.h",
     "host_status_monitor.h",
     "host_status_observer.h",
+    "host_window.cc",
     "host_window.h",
     "host_window_proxy.cc",
     "host_window_proxy.h",
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc
index 0dd72d1..4bfd9e2 100644
--- a/remoting/host/chromoting_host.cc
+++ b/remoting/host/chromoting_host.cc
@@ -83,7 +83,7 @@
 }
 
 ChromotingHost::~ChromotingHost() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Disconnect all of the clients.
   while (!clients_.empty()) {
@@ -102,7 +102,7 @@
 }
 
 void ChromotingHost::Start(const std::string& host_owner_email) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!started_);
 
   HOST_LOG << "Starting host";
@@ -115,12 +115,12 @@
 }
 
 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   status_observers_.AddObserver(observer);
 }
 
 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   status_observers_.RemoveObserver(observer);
 }
 
@@ -130,7 +130,7 @@
 
 void ChromotingHost::SetAuthenticatorFactory(
     std::unique_ptr<protocol::AuthenticatorFactory> authenticator_factory) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   session_manager_->set_authenticator_factory(std::move(authenticator_factory));
 }
 
@@ -156,7 +156,7 @@
 }
 
 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   login_backoff_.Reset();
 
@@ -181,7 +181,7 @@
 }
 
 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Notify observers.
   for (auto& observer : status_observers_)
@@ -189,7 +189,7 @@
 }
 
 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Notify observers.
   for (auto& observer : status_observers_)
@@ -197,7 +197,7 @@
 }
 
 void ChromotingHost::OnSessionClosed(ClientSession* client) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   ClientSessions::iterator it =
       std::find_if(clients_.begin(), clients_.end(),
@@ -220,7 +220,7 @@
     ClientSession* session,
     const std::string& channel_name,
     const protocol::TransportRoute& route) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : status_observers_)
     observer.OnClientRouteChange(session->client_jid(), channel_name, route);
 }
@@ -228,7 +228,7 @@
 void ChromotingHost::OnIncomingSession(
       protocol::Session* session,
       protocol::SessionManager::IncomingSessionResponse* response) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(started_);
 
   if (login_backoff_.ShouldRejectRequest()) {
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h
index 73d5a1e..049c120 100644
--- a/remoting/host/chromoting_host.h
+++ b/remoting/host/chromoting_host.h
@@ -13,7 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/threading/thread.h"
 #include "net/base/backoff_entry.h"
 #include "remoting/host/client_session.h"
@@ -62,8 +62,7 @@
 //    all pending tasks to complete. After all of that completed we
 //    return to the idle state. We then go to step (2) if there a new
 //    incoming connection.
-class ChromotingHost : public base::NonThreadSafe,
-                       public ClientSession::EventHandler,
+class ChromotingHost : public ClientSession::EventHandler,
                        public HostStatusMonitor {
  public:
   typedef std::vector<std::unique_ptr<ClientSession>> ClientSessions;
@@ -179,6 +178,8 @@
   // List of host extensions.
   std::vector<std::unique_ptr<HostExtension>> extensions_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<ChromotingHost> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromotingHost);
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index 2edb8f9..da82ef7 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -82,7 +82,7 @@
 }
 
 ClientSession::~ClientSession() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!audio_stream_);
   DCHECK(!desktop_environment_);
   DCHECK(!input_injector_);
@@ -94,7 +94,7 @@
 
 void ClientSession::NotifyClientResolution(
     const protocol::ClientResolution& resolution) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(resolution.dips_width() > 0 && resolution.dips_height() > 0);
 
   VLOG(1) << "Received ClientResolution (dips_width="
@@ -124,7 +124,7 @@
 }
 
 void ClientSession::ControlVideo(const protocol::VideoControl& video_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Note that |video_stream_| may be null, depending upon whether
   // extensions choose to wrap or "steal" the video capturer or encoder.
@@ -152,7 +152,7 @@
 }
 
 void ClientSession::ControlAudio(const protocol::AudioControl& audio_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (audio_control.has_enable()) {
     VLOG(1) << "Received AudioControl (enable="
@@ -164,7 +164,7 @@
 
 void ClientSession::SetCapabilities(
     const protocol::Capabilities& capabilities) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Ignore all the messages but the 1st one.
   if (client_capabilities_) {
@@ -223,7 +223,7 @@
 }
 
 void ClientSession::OnConnectionAuthenticated() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!audio_stream_);
   DCHECK(!desktop_environment_);
   DCHECK(!input_injector_);
@@ -280,7 +280,7 @@
 }
 
 void ClientSession::CreateMediaStreams() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Create a VideoStream to pump frames from the capturer to the client.
   video_stream_ = connection_->StartVideoStream(
@@ -307,7 +307,7 @@
 }
 
 void ClientSession::OnConnectionChannelsConnected() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DCHECK(!channels_connected_);
   channels_connected_ = true;
@@ -337,7 +337,7 @@
 }
 
 void ClientSession::OnConnectionClosed(protocol::ErrorCode error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   HOST_LOG << "Client disconnected: " << client_jid_ << "; error = " << error;
 
@@ -368,7 +368,7 @@
 void ClientSession::OnRouteChange(
     const std::string& channel_name,
     const protocol::TransportRoute& route) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   event_handler_->OnSessionRouteChange(this, channel_name, route);
 }
 
@@ -377,7 +377,7 @@
 }
 
 void ClientSession::DisconnectSession(protocol::ErrorCode error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(connection_.get());
 
   max_duration_timer_.Stop();
@@ -388,12 +388,12 @@
 }
 
 void ClientSession::OnLocalMouseMoved(const webrtc::DesktopVector& position) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   remote_input_filter_.LocalMouseMoved(position);
 }
 
 void ClientSession::SetDisableInputs(bool disable_inputs) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (disable_inputs)
     input_tracker_.ReleaseAll();
@@ -403,27 +403,27 @@
 }
 
 uint32_t ClientSession::desktop_session_id() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(desktop_environment_);
   return desktop_environment_->GetDesktopSessionId();
 }
 
 ClientSessionControl* ClientSession::session_control() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return this;
 }
 
 void ClientSession::SetEventTimestampsSourceForTests(
     scoped_refptr<protocol::InputEventTimestampsSource>
         event_timestamp_source) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   event_timestamp_source_for_tests_ = event_timestamp_source;
   if (video_stream_)
     video_stream_->SetEventTimestampsSource(event_timestamp_source_for_tests_);
 }
 
 std::unique_ptr<protocol::ClipboardStub> ClientSession::CreateClipboardProxy() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return base::MakeUnique<protocol::ClipboardThreadProxy>(
       client_clipboard_factory_.GetWeakPtr(),
       base::ThreadTaskRunnerHandle::Get());
@@ -432,7 +432,7 @@
 void ClientSession::OnVideoSizeChanged(protocol::VideoStream* video_stream,
                                        const webrtc::DesktopSize& size,
                                        const webrtc::DesktopVector& dpi) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   mouse_clamping_filter_.set_output_size(size);
 
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h
index 55e06d1..24440d8 100644
--- a/remoting/host/client_session.h
+++ b/remoting/host/client_session.h
@@ -12,8 +12,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
 #include "base/sequenced_task_runner_helpers.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "remoting/host/client_session_control.h"
@@ -50,8 +50,7 @@
 
 // A ClientSession keeps a reference to a connection to a client, and maintains
 // per-client state.
-class ClientSession : public base::NonThreadSafe,
-                      public protocol::HostStub,
+class ClientSession : public protocol::HostStub,
                       public protocol::ConnectionToClient::EventHandler,
                       public protocol::VideoStream::Observer,
                       public ClientSessionControl,
@@ -248,6 +247,8 @@
 
   HostExperimentSessionPlugin host_experiment_session_plugin_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   // Used to disable callbacks to |this| once DisconnectSession() has been
   // called.
   base::WeakPtrFactory<ClientSessionControl> weak_factory_;
diff --git a/remoting/host/continue_window.cc b/remoting/host/continue_window.cc
index 9871591c9..97446da 100644
--- a/remoting/host/continue_window.cc
+++ b/remoting/host/continue_window.cc
@@ -21,7 +21,7 @@
 
 void ContinueWindow::Start(
     const base::WeakPtr<ClientSessionControl>& client_session_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!client_session_control_.get());
   DCHECK(client_session_control.get());
 
@@ -33,7 +33,7 @@
 }
 
 void ContinueWindow::ContinueSession() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   disconnect_timer_.Stop();
 
@@ -50,7 +50,7 @@
 }
 
 void ContinueWindow::DisconnectSession() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   disconnect_timer_.Stop();
   if (client_session_control_.get())
@@ -60,7 +60,7 @@
 ContinueWindow::ContinueWindow() {}
 
 void ContinueWindow::OnSessionExpired() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!client_session_control_.get())
     return;
diff --git a/remoting/host/continue_window_linux.cc b/remoting/host/continue_window_linux.cc
index bdbe724..5092781e 100644
--- a/remoting/host/continue_window_linux.cc
+++ b/remoting/host/continue_window_linux.cc
@@ -49,7 +49,7 @@
 }
 
 void ContinueWindowGtk::ShowUi() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!continue_window_);
 
   CreateWindow();
@@ -58,7 +58,7 @@
 }
 
 void ContinueWindowGtk::HideUi() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (continue_window_) {
     gtk_widget_destroy(continue_window_);
@@ -67,7 +67,7 @@
 }
 
 void ContinueWindowGtk::CreateWindow() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!continue_window_);
 
   GtkDialogFlags flags = GTK_DIALOG_MODAL;
@@ -111,7 +111,7 @@
 }
 
 void ContinueWindowGtk::OnResponse(GtkDialog* dialog, int response_id) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (response_id == GTK_RESPONSE_OK) {
     ContinueSession();
diff --git a/remoting/host/continue_window_mac.mm b/remoting/host/continue_window_mac.mm
index 1dcd458..d61b0fef 100644
--- a/remoting/host/continue_window_mac.mm
+++ b/remoting/host/continue_window_mac.mm
@@ -55,11 +55,11 @@
 }
 
 ContinueWindowMac::~ContinueWindowMac() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void ContinueWindowMac::ShowUi() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::mac::ScopedNSAutoreleasePool pool;
   controller_.reset(
@@ -68,7 +68,7 @@
 }
 
 void ContinueWindowMac::HideUi() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::mac::ScopedNSAutoreleasePool pool;
   [controller_ hide];
diff --git a/remoting/host/continue_window_win.cc b/remoting/host/continue_window_win.cc
index e733daa..39ba651 100644
--- a/remoting/host/continue_window_win.cc
+++ b/remoting/host/continue_window_win.cc
@@ -54,7 +54,7 @@
 }
 
 void ContinueWindowWin::ShowUi() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!hwnd_);
 
   hwnd_ = CreateDialogParam(CURRENT_MODULE(), MAKEINTRESOURCE(IDD_CONTINUE),
@@ -68,7 +68,7 @@
 }
 
 void ContinueWindowWin::HideUi() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   EndDialog();
 }
@@ -91,7 +91,7 @@
 
 BOOL ContinueWindowWin::OnDialogMessage(HWND hwnd, UINT msg,
                                         WPARAM wParam, LPARAM lParam) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   switch (msg) {
     case WM_CLOSE:
@@ -119,7 +119,7 @@
 }
 
 void ContinueWindowWin::EndDialog() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (hwnd_) {
     ::DestroyWindow(hwnd_);
diff --git a/remoting/host/disconnect_window_linux.cc b/remoting/host/disconnect_window_linux.cc
index d9c95b95f..f42fd437 100644
--- a/remoting/host/disconnect_window_linux.cc
+++ b/remoting/host/disconnect_window_linux.cc
@@ -141,7 +141,7 @@
 }
 
 DisconnectWindowGtk::~DisconnectWindowGtk() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (disconnect_window_) {
     gtk_widget_destroy(disconnect_window_);
@@ -151,7 +151,7 @@
 
 void DisconnectWindowGtk::Start(
     const base::WeakPtr<ClientSessionControl>& client_session_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!client_session_control_.get());
   DCHECK(client_session_control.get());
   DCHECK(!disconnect_window_);
@@ -254,7 +254,7 @@
 }
 
 void DisconnectWindowGtk::OnClicked(GtkButton* button) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (client_session_control_.get())
     client_session_control_->DisconnectSession(protocol::OK);
@@ -262,7 +262,7 @@
 
 gboolean DisconnectWindowGtk::OnDelete(GtkWidget* window,
                                        GdkEvent* event) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (client_session_control_.get())
     client_session_control_->DisconnectSession(protocol::OK);
@@ -271,7 +271,7 @@
 
 gboolean DisconnectWindowGtk::OnConfigure(GtkWidget* widget,
                                           GdkEventConfigure* event) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Only generate bitmaps if the size has actually changed.
   if (event->width == current_width_ && event->height == current_height_)
@@ -327,7 +327,7 @@
 #if GTK_MAJOR_VERSION == 2
   NOTREACHED();
 #endif
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DrawBackground(cr, current_width_, current_height_);
   return FALSE;
@@ -335,7 +335,7 @@
 
 gboolean DisconnectWindowGtk::OnButtonPress(GtkWidget* widget,
                                             GdkEventButton* event) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   gtk_window_begin_move_drag(GTK_WINDOW(disconnect_window_),
                              event->button,
diff --git a/remoting/host/disconnect_window_mac.mm b/remoting/host/disconnect_window_mac.mm
index 0d03b86..d8d9c8de 100644
--- a/remoting/host/disconnect_window_mac.mm
+++ b/remoting/host/disconnect_window_mac.mm
@@ -48,7 +48,7 @@
 }
 
 DisconnectWindowMac::~DisconnectWindowMac() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // DisconnectWindowController is responsible for releasing itself in its
   // windowWillClose: method.
@@ -58,7 +58,7 @@
 
 void DisconnectWindowMac::Start(
     const base::WeakPtr<ClientSessionControl>& client_session_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(client_session_control);
   DCHECK(window_controller_ == nil);
 
diff --git a/remoting/host/disconnect_window_win.cc b/remoting/host/disconnect_window_win.cc
index 19e7356b..adde9223 100644
--- a/remoting/host/disconnect_window_win.cc
+++ b/remoting/host/disconnect_window_win.cc
@@ -121,7 +121,7 @@
 
 void DisconnectWindowWin::Start(
     const base::WeakPtr<ClientSessionControl>& client_session_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!client_session_control_);
   DCHECK(client_session_control);
 
@@ -161,7 +161,7 @@
                                           UINT message,
                                           WPARAM wparam,
                                           LPARAM lparam) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   switch (message) {
     // Ignore close messages.
@@ -228,7 +228,7 @@
 }
 
 bool DisconnectWindowWin::BeginDialog() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!hwnd_);
 
   hwnd_ =
@@ -252,7 +252,7 @@
 }
 
 void DisconnectWindowWin::EndDialog() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (has_hotkey_) {
     UnregisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID);
@@ -282,7 +282,7 @@
 }
 
 void DisconnectWindowWin::SetDialogPosition() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Try to center the window above the task-bar. If that fails, use the
   // primary monitor. If that fails (very unlikely), use the default position.
@@ -302,7 +302,7 @@
 }
 
 bool DisconnectWindowWin::SetStrings() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Localize the disconnect button text and measure length of the old and new
   // labels.
diff --git a/remoting/host/host_status_logger.cc b/remoting/host/host_status_logger.cc
index 992a155..b81e03297 100644
--- a/remoting/host/host_status_logger.cc
+++ b/remoting/host/host_status_logger.cc
@@ -23,13 +23,14 @@
 }
 
 HostStatusLogger::~HostStatusLogger() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (monitor_.get())
     monitor_->RemoveStatusObserver(this);
 }
 
 void HostStatusLogger::LogSessionStateChange(const std::string& jid,
                                              bool connected) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   std::unique_ptr<ServerLogEntry> entry(
       MakeLogEntryForSessionStateChange(connected));
@@ -43,12 +44,12 @@
 }
 
 void HostStatusLogger::OnClientConnected(const std::string& jid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   LogSessionStateChange(jid, true);
 }
 
 void HostStatusLogger::OnClientDisconnected(const std::string& jid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   LogSessionStateChange(jid, false);
   connection_route_type_.erase(jid);
 }
diff --git a/remoting/host/host_status_logger.h b/remoting/host/host_status_logger.h
index 19983db..55771cc3 100644
--- a/remoting/host/host_status_logger.h
+++ b/remoting/host/host_status_logger.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/host/host_status_observer.h"
 #include "remoting/protocol/transport.h"
 #include "remoting/signaling/log_to_server.h"
@@ -21,8 +21,7 @@
 // HostStatusLogger sends host log entries to a server.
 // The contents of the log entries are described in server_log_entry_host.cc.
 // They do not contain any personally identifiable information.
-class HostStatusLogger : public HostStatusObserver,
-                         public base::NonThreadSafe {
+class HostStatusLogger : public HostStatusObserver {
  public:
   HostStatusLogger(base::WeakPtr<HostStatusMonitor> monitor,
                   ServerLogEntry::Mode mode,
@@ -54,6 +53,8 @@
   std::map<std::string, protocol::TransportRoute::RouteType>
       connection_route_type_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(HostStatusLogger);
 };
 
diff --git a/remoting/host/host_window.cc b/remoting/host/host_window.cc
new file mode 100644
index 0000000..0b2be09
--- /dev/null
+++ b/remoting/host/host_window.cc
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/host_window.h"
+
+namespace remoting {
+
+HostWindow::~HostWindow() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+}  // namespace remoting
diff --git a/remoting/host/host_window.h b/remoting/host/host_window.h
index 0a2e309..61099e8 100644
--- a/remoting/host/host_window.h
+++ b/remoting/host/host_window.h
@@ -10,15 +10,15 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 
 namespace remoting {
 
 class ClientSessionControl;
 
-class HostWindow : public base::NonThreadSafe {
+class HostWindow {
  public:
-  virtual ~HostWindow() {}
+  virtual ~HostWindow();
 
   // Creates a platform-specific instance of the continue window.
   static std::unique_ptr<HostWindow> CreateContinueWindow();
@@ -32,13 +32,15 @@
       const base::WeakPtr<ClientSessionControl>& client_session_control) = 0;
 
  protected:
-  HostWindow() {}
-
- private:
-  // Let |HostWindowProxy| to call DetachFromThread() when passing an instance
-  // of |HostWindow| to a different thread.
+  // Let |HostWindowProxy| to call DetachFromSequence() when passing an instance
+  // of |HostWindow| to a different sequence.
   friend class HostWindowProxy;
 
+  HostWindow() {}
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+ private:
   DISALLOW_COPY_AND_ASSIGN(HostWindow);
 };
 
diff --git a/remoting/host/host_window_proxy.cc b/remoting/host/host_window_proxy.cc
index 862398b..d9f23b0 100644
--- a/remoting/host/host_window_proxy.cc
+++ b/remoting/host/host_window_proxy.cc
@@ -75,19 +75,19 @@
 
   // Detach |host_window| from the calling thread so that |Core| could run it on
   // the |ui_task_runner_| thread.
-  host_window->DetachFromThread();
+  DETACH_FROM_SEQUENCE(host_window->sequence_checker_);
   core_ = new Core(caller_task_runner, ui_task_runner, std::move(host_window));
 }
 
 HostWindowProxy::~HostWindowProxy() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   core_->Stop();
 }
 
 void HostWindowProxy::Start(
     const base::WeakPtr<ClientSessionControl>& client_session_control) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   core_->Start(client_session_control);
 }
diff --git a/remoting/host/ipc_host_event_logger.cc b/remoting/host/ipc_host_event_logger.cc
index 154ac60..501e20ca 100644
--- a/remoting/host/ipc_host_event_logger.cc
+++ b/remoting/host/ipc_host_event_logger.cc
@@ -21,33 +21,33 @@
 }
 
 IpcHostEventLogger::~IpcHostEventLogger() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (monitor_.get())
     monitor_->RemoveStatusObserver(this);
 }
 
 void IpcHostEventLogger::OnAccessDenied(const std::string& jid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   daemon_channel_->Send(new ChromotingNetworkDaemonMsg_AccessDenied(jid));
 }
 
 void IpcHostEventLogger::OnClientAuthenticated(const std::string& jid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   daemon_channel_->Send(
       new ChromotingNetworkDaemonMsg_ClientAuthenticated(jid));
 }
 
 void IpcHostEventLogger::OnClientConnected(const std::string& jid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   daemon_channel_->Send(new ChromotingNetworkDaemonMsg_ClientConnected(jid));
 }
 
 void IpcHostEventLogger::OnClientDisconnected(const std::string& jid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   daemon_channel_->Send(new ChromotingNetworkDaemonMsg_ClientDisconnected(jid));
 }
@@ -56,7 +56,7 @@
     const std::string& jid,
     const std::string& channel_name,
     const protocol::TransportRoute& route) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   SerializedTransportRoute serialized_route;
   serialized_route.type = route.type;
@@ -70,13 +70,13 @@
 }
 
 void IpcHostEventLogger::OnShutdown() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   daemon_channel_->Send(new ChromotingNetworkDaemonMsg_HostShutdown());
 }
 
 void IpcHostEventLogger::OnStart(const std::string& xmpp_login) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   daemon_channel_->Send(new ChromotingNetworkDaemonMsg_HostStarted(xmpp_login));
 }
diff --git a/remoting/host/ipc_host_event_logger.h b/remoting/host/ipc_host_event_logger.h
index bf15d58..b292fa45 100644
--- a/remoting/host/ipc_host_event_logger.h
+++ b/remoting/host/ipc_host_event_logger.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/host/host_event_logger.h"
 #include "remoting/host/host_status_observer.h"
 
@@ -23,10 +23,7 @@
 
 class HostStatusMonitor;
 
-class IpcHostEventLogger
-    : public base::NonThreadSafe,
-      public HostEventLogger,
-      public HostStatusObserver {
+class IpcHostEventLogger : public HostEventLogger, public HostStatusObserver {
  public:
   // Initializes the logger. |daemon_channel| must outlive this object.
   IpcHostEventLogger(base::WeakPtr<HostStatusMonitor> monitor,
@@ -50,6 +47,8 @@
 
   base::WeakPtr<HostStatusMonitor> monitor_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(IpcHostEventLogger);
 };
 
diff --git a/remoting/host/local_input_monitor_mac.mm b/remoting/host/local_input_monitor_mac.mm
index 961d7ef..e3b4aa7 100644
--- a/remoting/host/local_input_monitor_mac.mm
+++ b/remoting/host/local_input_monitor_mac.mm
@@ -17,9 +17,9 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/non_thread_safe.h"
 #include "remoting/host/client_session_control.h"
 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMCarbonEvent.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
@@ -31,8 +31,7 @@
 namespace remoting {
 namespace {
 
-class LocalInputMonitorMac : public base::NonThreadSafe,
-                             public LocalInputMonitor {
+class LocalInputMonitorMac : public LocalInputMonitor {
  public:
   // Invoked by LocalInputMonitorManager.
   class EventHandler {
@@ -54,6 +53,8 @@
   class Core;
   scoped_refptr<Core> core_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorMac);
 };
 
@@ -209,6 +210,7 @@
 }
 
 LocalInputMonitorMac::~LocalInputMonitorMac() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->Stop();
 }
 
diff --git a/remoting/host/local_input_monitor_win.cc b/remoting/host/local_input_monitor_win.cc
index ac6525e..7567a657 100644
--- a/remoting/host/local_input_monitor_win.cc
+++ b/remoting/host/local_input_monitor_win.cc
@@ -12,9 +12,9 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/win/message_window.h"
 #include "remoting/host/client_session_control.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
@@ -27,8 +27,7 @@
 const USHORT kGenericDesktopPage = 1;
 const USHORT kMouseUsage = 2;
 
-class LocalInputMonitorWin : public base::NonThreadSafe,
-                             public LocalInputMonitor {
+class LocalInputMonitorWin : public LocalInputMonitor {
  public:
   LocalInputMonitorWin(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
@@ -80,6 +79,8 @@
 
   scoped_refptr<Core> core_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorWin);
 };
 
@@ -94,6 +95,7 @@
 }
 
 LocalInputMonitorWin::~LocalInputMonitorWin() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->Stop();
 }
 
diff --git a/remoting/host/local_input_monitor_x11.cc b/remoting/host/local_input_monitor_x11.cc
index 906139b..cca14fda 100644
--- a/remoting/host/local_input_monitor_x11.cc
+++ b/remoting/host/local_input_monitor_x11.cc
@@ -8,6 +8,7 @@
 #include <unistd.h>
 
 #include "base/memory/ptr_util.h"
+#include "base/sequence_checker.h"
 #define XK_MISCELLANY
 #include <X11/keysymdef.h>
 
@@ -19,7 +20,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "remoting/host/client_session_control.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 
@@ -33,8 +33,7 @@
 
 namespace {
 
-class LocalInputMonitorX11 : public base::NonThreadSafe,
-                               public LocalInputMonitor {
+class LocalInputMonitorX11 : public LocalInputMonitor {
  public:
   LocalInputMonitorX11(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
@@ -97,6 +96,8 @@
 
   scoped_refptr<Core> core_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorX11);
 };
 
@@ -111,6 +112,7 @@
 }
 
 LocalInputMonitorX11::~LocalInputMonitorX11() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->Stop();
 }
 
diff --git a/remoting/host/native_messaging/pipe_messaging_channel.cc b/remoting/host/native_messaging/pipe_messaging_channel.cc
index 014e67de..0b288a1 100644
--- a/remoting/host/native_messaging/pipe_messaging_channel.cc
+++ b/remoting/host/native_messaging/pipe_messaging_channel.cc
@@ -54,10 +54,12 @@
   weak_ptr_ = weak_factory_.GetWeakPtr();
 }
 
-PipeMessagingChannel::~PipeMessagingChannel() {}
+PipeMessagingChannel::~PipeMessagingChannel() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void PipeMessagingChannel::Start(EventHandler* event_handler) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!event_handler_);
 
   event_handler_ = event_handler;
@@ -70,14 +72,14 @@
 
 void PipeMessagingChannel::ProcessMessage(
     std::unique_ptr<base::Value> message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (event_handler_)
     event_handler_->OnMessage(std::move(message));
 }
 
 void PipeMessagingChannel::SendMessage(std::unique_ptr<base::Value> message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   bool success = message && native_messaging_writer_;
   if (success)
@@ -91,7 +93,7 @@
 }
 
 void PipeMessagingChannel::Shutdown() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (event_handler_) {
     // Set |event_handler_| to nullptr to indicate the object is in a shutdown
diff --git a/remoting/host/native_messaging/pipe_messaging_channel.h b/remoting/host/native_messaging/pipe_messaging_channel.h
index 685ce99..4ebd2f4 100644
--- a/remoting/host/native_messaging/pipe_messaging_channel.h
+++ b/remoting/host/native_messaging/pipe_messaging_channel.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "extensions/browser/api/messaging/native_messaging_channel.h"
 #include "remoting/host/native_messaging/native_messaging_reader.h"
 #include "remoting/host/native_messaging/native_messaging_writer.h"
@@ -28,8 +28,7 @@
 // communicate with the chrome process.
 // TODO(kelvinp): Move this class to the extensions/browser/api/messaging
 // directory.
-class PipeMessagingChannel : public extensions::NativeMessagingChannel,
-                             public base::NonThreadSafe {
+class PipeMessagingChannel : public extensions::NativeMessagingChannel {
  public:
   typedef extensions::NativeMessagingChannel::EventHandler EventHandler;
 
@@ -54,6 +53,9 @@
 
   EventHandler* event_handler_;
   base::WeakPtr<PipeMessagingChannel> weak_ptr_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<PipeMessagingChannel> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PipeMessagingChannel);
diff --git a/remoting/host/policy_watcher.cc b/remoting/host/policy_watcher.cc
index 2b9a60a4..b8078863 100644
--- a/remoting/host/policy_watcher.cc
+++ b/remoting/host/policy_watcher.cc
@@ -141,7 +141,7 @@
 void PolicyWatcher::StartWatching(
     const PolicyUpdatedCallback& policy_updated_callback,
     const PolicyErrorCallback& policy_error_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!policy_updated_callback.is_null());
   DCHECK(!policy_error_callback.is_null());
   DCHECK(policy_updated_callback_.is_null());
@@ -207,6 +207,7 @@
 }
 
 PolicyWatcher::~PolicyWatcher() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Stop observing |policy_service_| if StartWatching() has been called.
   if (!policy_updated_callback_.is_null()) {
     policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
diff --git a/remoting/host/policy_watcher.h b/remoting/host/policy_watcher.h
index 37195c5..076cd45 100644
--- a/remoting/host/policy_watcher.h
+++ b/remoting/host/policy_watcher.h
@@ -10,7 +10,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "components/policy/core/common/policy_service.h"
 
 namespace base {
@@ -28,8 +28,7 @@
 namespace remoting {
 
 // Watches for changes to the managed remote access host policies.
-class PolicyWatcher : public policy::PolicyService::Observer,
-                      public base::NonThreadSafe {
+class PolicyWatcher : public policy::PolicyService::Observer {
  public:
   // Called first with all policies, and subsequently with any changed policies.
   typedef base::Callback<void(std::unique_ptr<base::DictionaryValue>)>
@@ -158,6 +157,8 @@
   std::unique_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider_;
   std::unique_ptr<policy::PolicyService> owned_policy_service_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(PolicyWatcher);
 };
 
diff --git a/remoting/host/setup/win/auth_code_getter.cc b/remoting/host/setup/win/auth_code_getter.cc
index 4e51e58..8396027c 100644
--- a/remoting/host/setup/win/auth_code_getter.cc
+++ b/remoting/host/setup/win/auth_code_getter.cc
@@ -24,6 +24,7 @@
 }
 
 AuthCodeGetter::~AuthCodeGetter() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   KillBrowser();
 }
 
diff --git a/remoting/host/setup/win/auth_code_getter.h b/remoting/host/setup/win/auth_code_getter.h
index b4a5756..22aa0534 100644
--- a/remoting/host/setup/win/auth_code_getter.h
+++ b/remoting/host/setup/win/auth_code_getter.h
@@ -12,14 +12,14 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/timer/timer.h"
 #include "base/win/scoped_comptr.h"
 
 namespace remoting {
 
 // A class for getting an OAuth authorization code.
-class AuthCodeGetter : public base::NonThreadSafe {
+class AuthCodeGetter {
  public:
   AuthCodeGetter();
   ~AuthCodeGetter();
@@ -49,6 +49,8 @@
   // The interval at which the timer fires.
   base::TimeDelta timer_interval_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AuthCodeGetter);
 };
 
diff --git a/remoting/host/signaling_connector.cc b/remoting/host/signaling_connector.cc
index 1b617f4..b338072 100644
--- a/remoting/host/signaling_connector.cc
+++ b/remoting/host/signaling_connector.cc
@@ -60,6 +60,7 @@
 }
 
 SignalingConnector::~SignalingConnector() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   signal_strategy_->RemoveListener(this);
   net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
   net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
@@ -67,7 +68,7 @@
 
 void SignalingConnector::OnSignalStrategyStateChange(
     SignalStrategy::State state) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (state == SignalStrategy::CONNECTED) {
     HOST_LOG << "Signaling connected. New JID: "
@@ -92,7 +93,7 @@
 
 void SignalingConnector::OnConnectionTypeChanged(
     net::NetworkChangeNotifier::ConnectionType type) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (type != net::NetworkChangeNotifier::CONNECTION_NONE &&
       signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) {
     HOST_LOG << "Network state changed to online.";
@@ -101,7 +102,7 @@
 }
 
 void SignalingConnector::OnIPAddressChanged() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) {
     HOST_LOG << "IP address has changed.";
     ResetAndTryReconnect();
@@ -111,7 +112,7 @@
 void SignalingConnector::OnAccessToken(OAuthTokenGetter::Status status,
                                        const std::string& user_email,
                                        const std::string& access_token) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (status == OAuthTokenGetter::AUTH_ERROR) {
     auth_failed_callback_.Run();
@@ -133,13 +134,13 @@
 }
 
 void SignalingConnector::OnNetworkError() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   reconnect_attempts_++;
   ScheduleTryReconnect();
 }
 
 void SignalingConnector::ScheduleTryReconnect() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (timer_.IsRunning() || net::NetworkChangeNotifier::IsOffline())
     return;
   int delay_s = std::min(1 << reconnect_attempts_,
@@ -149,7 +150,7 @@
 }
 
 void SignalingConnector::ResetAndTryReconnect() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   signal_strategy_->Disconnect();
   reconnect_attempts_ = 0;
   timer_.Stop();
@@ -157,7 +158,7 @@
 }
 
 void SignalingConnector::TryReconnect() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(dns_blackhole_checker_.get());
 
   // This will check if this machine is allowed to access the chromoting
@@ -168,7 +169,7 @@
 }
 
 void SignalingConnector::OnDnsBlackholeCheckerDone(bool allow) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Unable to access the host talkgadget. Don't allow the connection, but
   // schedule a reconnect in case this is a transient problem rather than
diff --git a/remoting/host/signaling_connector.h b/remoting/host/signaling_connector.h
index 7f5e8a0..b057438 100644
--- a/remoting/host/signaling_connector.h
+++ b/remoting/host/signaling_connector.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/timer/timer.h"
 #include "net/base/network_change_notifier.h"
 #include "remoting/base/oauth_token_getter.h"
@@ -25,7 +25,6 @@
 // whenever connection type changes or IP address changes.
 class SignalingConnector
     : public base::SupportsWeakPtr<SignalingConnector>,
-      public base::NonThreadSafe,
       public SignalStrategy::Listener,
       public net::NetworkChangeNotifier::ConnectionTypeObserver,
       public net::NetworkChangeNotifier::IPAddressObserver {
@@ -71,6 +70,8 @@
 
   base::OneShotTimer timer_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(SignalingConnector);
 };
 
diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc
index 81ec5b9e..e7b57d2 100644
--- a/remoting/host/win/rdp_client.cc
+++ b/remoting/host/win/rdp_client.cc
@@ -103,19 +103,19 @@
 }
 
 RdpClient::~RdpClient() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   core_->Disconnect();
 }
 
 void RdpClient::InjectSas() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   core_->InjectSas();
 }
 
 void RdpClient::ChangeResolution(const ScreenResolution& resolution) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   core_->ChangeResolution(resolution);
 }
diff --git a/remoting/host/win/rdp_client.h b/remoting/host/win/rdp_client.h
index e30f16ec..8225a524 100644
--- a/remoting/host/win/rdp_client.h
+++ b/remoting/host/win/rdp_client.h
@@ -10,7 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -21,7 +21,7 @@
 class ScreenResolution;
 
 // Establishes a loopback RDP connection to spawn a new Windows session.
-class RdpClient : public base::NonThreadSafe {
+class RdpClient {
  public:
   class EventHandler {
    public:
@@ -54,6 +54,8 @@
   class Core;
   scoped_refptr<Core> core_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(RdpClient);
 };
 
diff --git a/remoting/host/win/unprivileged_process_delegate.cc b/remoting/host/win/unprivileged_process_delegate.cc
index 5789ae2..dfff10c 100644
--- a/remoting/host/win/unprivileged_process_delegate.cc
+++ b/remoting/host/win/unprivileged_process_delegate.cc
@@ -228,14 +228,14 @@
       event_handler_(nullptr) {}
 
 UnprivilegedProcessDelegate::~UnprivilegedProcessDelegate() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!channel_);
   DCHECK(!worker_process_.IsValid());
 }
 
 void UnprivilegedProcessDelegate::LaunchProcess(
     WorkerProcessLauncher* event_handler) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!event_handler_);
 
   event_handler_ = event_handler;
@@ -322,7 +322,7 @@
 }
 
 void UnprivilegedProcessDelegate::Send(IPC::Message* message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (channel_) {
     channel_->Send(message);
@@ -332,12 +332,12 @@
 }
 
 void UnprivilegedProcessDelegate::CloseChannel() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   channel_.reset();
 }
 
 void UnprivilegedProcessDelegate::KillProcess() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   CloseChannel();
   event_handler_ = nullptr;
@@ -350,13 +350,13 @@
 
 bool UnprivilegedProcessDelegate::OnMessageReceived(
     const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return event_handler_->OnMessageReceived(message);
 }
 
 void UnprivilegedProcessDelegate::OnChannelConnected(int32_t peer_pid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DWORD pid = GetProcessId(worker_process_.Get());
   if (pid != static_cast<DWORD>(peer_pid)) {
@@ -371,13 +371,13 @@
 }
 
 void UnprivilegedProcessDelegate::OnChannelError() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   event_handler_->OnChannelError();
 }
 
 void UnprivilegedProcessDelegate::ReportFatalError() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   CloseChannel();
 
@@ -388,7 +388,7 @@
 
 void UnprivilegedProcessDelegate::ReportProcessLaunched(
     base::win::ScopedHandle worker_process) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!worker_process_.IsValid());
 
   worker_process_ = std::move(worker_process);
diff --git a/remoting/host/win/unprivileged_process_delegate.h b/remoting/host/win/unprivileged_process_delegate.h
index 5059234ff..aea3326 100644
--- a/remoting/host/win/unprivileged_process_delegate.h
+++ b/remoting/host/win/unprivileged_process_delegate.h
@@ -13,7 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/win/scoped_handle.h"
 #include "ipc/ipc_listener.h"
 #include "remoting/host/win/worker_process_launcher.h"
@@ -32,10 +32,8 @@
 
 // Implements logic for launching and monitoring a worker process under a less
 // privileged user account.
-class UnprivilegedProcessDelegate
-    : public base::NonThreadSafe,
-      public IPC::Listener,
-      public WorkerProcessLauncher::Delegate {
+class UnprivilegedProcessDelegate : public IPC::Listener,
+                                    public WorkerProcessLauncher::Delegate {
  public:
   UnprivilegedProcessDelegate(
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
@@ -72,6 +70,8 @@
   // The handle of the worker process, if launched.
   base::win::ScopedHandle worker_process_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(UnprivilegedProcessDelegate);
 };
 
diff --git a/remoting/host/win/worker_process_launcher.cc b/remoting/host/win/worker_process_launcher.cc
index 4b1dd169..e4bf86c 100644
--- a/remoting/host/win/worker_process_launcher.cc
+++ b/remoting/host/win/worker_process_launcher.cc
@@ -67,7 +67,7 @@
 }
 
 WorkerProcessLauncher::~WorkerProcessLauncher() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   ipc_handler_ = nullptr;
   StopWorker();
@@ -75,7 +75,7 @@
 
 void WorkerProcessLauncher::Crash(
     const tracked_objects::Location& location) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Ask the worker process to crash voluntarily if it is still connected.
   if (ipc_enabled_) {
@@ -96,7 +96,7 @@
 }
 
 void WorkerProcessLauncher::Send(IPC::Message* message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (ipc_enabled_) {
     launcher_delegate_->Send(message);
@@ -107,7 +107,7 @@
 
 void WorkerProcessLauncher::OnProcessLaunched(
     base::win::ScopedHandle worker_process) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!ipc_enabled_);
   DCHECK(!launch_timer_.IsRunning());
   DCHECK(!process_watcher_.GetWatchedObject());
@@ -123,14 +123,14 @@
 }
 
 void WorkerProcessLauncher::OnFatalError() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   StopWorker();
 }
 
 bool WorkerProcessLauncher::OnMessageReceived(
   const IPC::Message& message) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!ipc_enabled_)
     return false;
@@ -139,7 +139,7 @@
 }
 
 void WorkerProcessLauncher::OnChannelConnected(int32_t peer_pid) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!ipc_enabled_)
     return;
@@ -150,7 +150,7 @@
 }
 
 void WorkerProcessLauncher::OnChannelError() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Schedule a delayed termination of the worker process. Usually, the pipe is
   // disconnected when the worker process is about to exit. Waiting a little bit
@@ -164,7 +164,7 @@
 }
 
 void WorkerProcessLauncher::OnObjectSignaled(HANDLE object) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!process_watcher_.GetWatchedObject());
   DCHECK_EQ(exit_code_, CONTROL_C_EXIT);
   DCHECK_EQ(worker_process_.Get(), object);
@@ -180,7 +180,7 @@
 }
 
 void WorkerProcessLauncher::LaunchWorker() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!ipc_enabled_);
   DCHECK(!kill_process_timer_.IsRunning());
   DCHECK(!launch_timer_.IsRunning());
@@ -198,7 +198,7 @@
 }
 
 void WorkerProcessLauncher::RecordLaunchResult() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!worker_process_.IsValid()) {
     LOG(WARNING) << "A worker process failed to start within "
@@ -214,7 +214,7 @@
 }
 
 void WorkerProcessLauncher::RecordSuccessfulLaunchForTest() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (launch_result_timer_.IsRunning()) {
     launch_result_timer_.Stop();
@@ -224,13 +224,13 @@
 
 void WorkerProcessLauncher::SetKillProcessTimeoutForTest(
     const base::TimeDelta& timeout) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   kill_process_timeout_ = timeout;
 }
 
 void WorkerProcessLauncher::StopWorker() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Record a launch failure if the process exited too soon.
   if (launch_result_timer_.IsRunning()) {
diff --git a/remoting/host/win/worker_process_launcher.h b/remoting/host/win/worker_process_launcher.h
index 638d633..6c68206 100644
--- a/remoting/host/win/worker_process_launcher.h
+++ b/remoting/host/win/worker_process_launcher.h
@@ -13,7 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "base/timer/timer.h"
 #include "base/win/object_watcher.h"
 #include "base/win/scoped_handle.h"
@@ -39,9 +39,7 @@
 // interaction with the spawned process is through WorkerProcessIpcDelegate and
 // Send() method. In case of error the channel is closed and the worker process
 // is terminated.
-class WorkerProcessLauncher
-    : public base::NonThreadSafe,
-      public base::win::ObjectWatcher::Delegate {
+class WorkerProcessLauncher : public base::win::ObjectWatcher::Delegate {
  public:
   class Delegate {
    public:
@@ -163,6 +161,8 @@
   // The handle of the worker process, if launched.
   base::win::ScopedHandle worker_process_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(WorkerProcessLauncher);
 };
 
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc
index a29f5c0..6a55c11 100644
--- a/remoting/host/win/wts_session_process_delegate.cc
+++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -591,6 +591,7 @@
 }
 
 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->Stop();
 }
 
diff --git a/remoting/host/win/wts_session_process_delegate.h b/remoting/host/win/wts_session_process_delegate.h
index 407e0af6..f170c5c 100644
--- a/remoting/host/win/wts_session_process_delegate.h
+++ b/remoting/host/win/wts_session_process_delegate.h
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/host/win/worker_process_launcher.h"
 
 namespace base {
@@ -28,9 +28,7 @@
 
 // Implements logic for launching and monitoring a worker process in a different
 // session.
-class WtsSessionProcessDelegate
-    : public base::NonThreadSafe,
-      public WorkerProcessLauncher::Delegate {
+class WtsSessionProcessDelegate : public WorkerProcessLauncher::Delegate {
  public:
   WtsSessionProcessDelegate(
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
@@ -53,6 +51,8 @@
   class Core;
   scoped_refptr<Core> core_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(WtsSessionProcessDelegate);
 };
 
diff --git a/remoting/protocol/channel_multiplexer.cc b/remoting/protocol/channel_multiplexer.cc
index 97233d23..5331bc4 100644
--- a/remoting/protocol/channel_multiplexer.cc
+++ b/remoting/protocol/channel_multiplexer.cc
@@ -15,6 +15,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/net_errors.h"
@@ -97,7 +98,6 @@
 };
 
 class ChannelMultiplexer::MuxSocket : public P2PStreamSocket,
-                                      public base::NonThreadSafe,
                                       public base::SupportsWeakPtr<MuxSocket> {
  public:
   MuxSocket(MuxChannel* channel);
@@ -126,6 +126,8 @@
   int write_result_;
   net::CompletionCallback write_callback_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(MuxSocket);
 };
 
@@ -220,7 +222,7 @@
 int ChannelMultiplexer::MuxSocket::Read(
     const scoped_refptr<net::IOBuffer>& buffer, int buffer_len,
     const net::CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(read_callback_.is_null());
 
   if (base_channel_error_ != net::OK)
@@ -239,7 +241,7 @@
 int ChannelMultiplexer::MuxSocket::Write(
     const scoped_refptr<net::IOBuffer>& buffer, int buffer_len,
     const net::CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(write_callback_.is_null());
 
   if (base_channel_error_ != net::OK)
@@ -307,6 +309,7 @@
       weak_factory_(this) {}
 
 ChannelMultiplexer::~ChannelMultiplexer() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(pending_channels_.empty());
 
   // Cancel creation of the base channel if it hasn't finished.
diff --git a/remoting/protocol/ice_connection_to_host.cc b/remoting/protocol/ice_connection_to_host.cc
index 4fa7eae..be42dea 100644
--- a/remoting/protocol/ice_connection_to_host.cc
+++ b/remoting/protocol/ice_connection_to_host.cc
@@ -28,7 +28,9 @@
 namespace protocol {
 
 IceConnectionToHost::IceConnectionToHost() {}
-IceConnectionToHost::~IceConnectionToHost() {}
+IceConnectionToHost::~IceConnectionToHost() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void IceConnectionToHost::Connect(
     std::unique_ptr<Session> session,
@@ -88,7 +90,7 @@
 }
 
 void IceConnectionToHost::OnSessionStateChange(Session::State state) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(event_callback_);
 
   switch (state) {
@@ -216,7 +218,7 @@
 }
 
 void IceConnectionToHost::SetState(State state, ErrorCode error) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // |error| should be specified only when |state| is set to FAILED.
   DCHECK(state == FAILED || error == OK);
 
diff --git a/remoting/protocol/ice_connection_to_host.h b/remoting/protocol/ice_connection_to_host.h
index 3a0b7ff3..bdb5da4 100644
--- a/remoting/protocol/ice_connection_to_host.h
+++ b/remoting/protocol/ice_connection_to_host.h
@@ -12,8 +12,8 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
-#include "base/threading/non_thread_safe.h"
 #include "remoting/proto/internal.pb.h"
 #include "remoting/protocol/channel_dispatcher_base.h"
 #include "remoting/protocol/clipboard_filter.h"
@@ -37,8 +37,7 @@
 class IceConnectionToHost : public ConnectionToHost,
                             public Session::EventHandler,
                             public IceTransport::EventHandler,
-                            public ChannelDispatcherBase::EventHandler,
-                            public base::NonThreadSafe {
+                            public ChannelDispatcherBase::EventHandler {
  public:
   IceConnectionToHost();
   ~IceConnectionToHost() override;
@@ -107,6 +106,8 @@
   ErrorCode error_ = OK;
 
  private:
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(IceConnectionToHost);
 };
 
diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc
index c13cdb09..b4eebeb 100644
--- a/remoting/protocol/jingle_session_manager.cc
+++ b/remoting/protocol/jingle_session_manager.cc
@@ -56,7 +56,7 @@
 
 void JingleSessionManager::set_authenticator_factory(
     std::unique_ptr<AuthenticatorFactory> authenticator_factory) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   authenticator_factory_ = std::move(authenticator_factory);
 }
 
diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h
index 2024a7a4..3274e04 100644
--- a/remoting/protocol/jingle_session_manager.h
+++ b/remoting/protocol/jingle_session_manager.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/sequence_checker.h"
 #include "remoting/protocol/jingle_messages.h"
 #include "remoting/protocol/session_manager.h"
 #include "remoting/signaling/signal_strategy.h"
@@ -71,6 +72,8 @@
 
   SessionsMap sessions_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(JingleSessionManager);
 };
 
diff --git a/remoting/protocol/message_reader.cc b/remoting/protocol/message_reader.cc
index 948ac2f6..db9030b 100644
--- a/remoting/protocol/message_reader.cc
+++ b/remoting/protocol/message_reader.cc
@@ -25,13 +25,15 @@
 static const int kReadBufferSize = 4096;
 
 MessageReader::MessageReader() : weak_factory_(this) {}
-MessageReader::~MessageReader() {}
+MessageReader::~MessageReader() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void MessageReader::StartReading(
     P2PStreamSocket* socket,
     const MessageReceivedCallback& message_received_callback,
     const ReadFailedCallback& read_failed_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!socket_);
   DCHECK(socket);
   DCHECK(!message_received_callback.is_null());
@@ -44,7 +46,7 @@
 }
 
 void MessageReader::DoRead() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Don't try to read again if there is another read pending or we
   // have messages that we haven't finished processing yet.
   bool read_succeeded = true;
@@ -60,7 +62,7 @@
 }
 
 void MessageReader::OnRead(int result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(read_pending_);
   read_pending_ = false;
 
@@ -73,7 +75,7 @@
 }
 
 void MessageReader::HandleReadResult(int result, bool* read_succeeded) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (closed_)
     return;
 
@@ -95,7 +97,7 @@
 }
 
 void MessageReader::OnDataReceived(net::IOBuffer* data, int data_size) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   message_decoder_.AddData(data, data_size);
 
   // Get list of all new messages first, and then call the callback
diff --git a/remoting/protocol/message_reader.h b/remoting/protocol/message_reader.h
index 9114258..38c7a9c 100644
--- a/remoting/protocol/message_reader.h
+++ b/remoting/protocol/message_reader.h
@@ -10,7 +10,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/base/compound_buffer.h"
 #include "remoting/protocol/message_decoder.h"
 
@@ -34,7 +34,7 @@
 // It is still possible that the MessageReceivedCallback is called
 // twice (so that there is more than one outstanding message),
 // e.g. when we the sender sends multiple messages in one TCP packet.
-class MessageReader : public base::NonThreadSafe {
+class MessageReader {
  public:
   typedef base::Callback<void(std::unique_ptr<CompoundBuffer> message)>
       MessageReceivedCallback;
@@ -71,6 +71,8 @@
   // Callback is called when a message is received.
   MessageReceivedCallback message_received_callback_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<MessageReader> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageReader);
diff --git a/remoting/protocol/pseudotcp_adapter.cc b/remoting/protocol/pseudotcp_adapter.cc
index 2ba797e..2b89c78 100644
--- a/remoting/protocol/pseudotcp_adapter.cc
+++ b/remoting/protocol/pseudotcp_adapter.cc
@@ -455,6 +455,7 @@
     : core_(new Core(std::move(socket))) {}
 
 PseudoTcpAdapter::~PseudoTcpAdapter() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Make sure that the underlying socket is destroyed before PseudoTcp.
   core_->DeleteSocket();
 }
@@ -462,46 +463,46 @@
 int PseudoTcpAdapter::Read(const scoped_refptr<net::IOBuffer>& buffer,
                            int buffer_size,
                            const net::CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return core_->Read(buffer, buffer_size, callback);
 }
 
 int PseudoTcpAdapter::Write(const scoped_refptr<net::IOBuffer>& buffer,
                             int buffer_size,
                             const net::CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return core_->Write(buffer, buffer_size, callback);
 }
 
 int PseudoTcpAdapter::SetReceiveBufferSize(int32_t size) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->SetReceiveBufferSize(size);
   return net::OK;
 }
 
 int PseudoTcpAdapter::SetSendBufferSize(int32_t size) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->SetSendBufferSize(size);
   return net::OK;
 }
 
 int PseudoTcpAdapter::Connect(const net::CompletionCallback& callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return core_->Connect(callback);
 }
 
 void PseudoTcpAdapter::SetAckDelay(int delay_ms) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->SetAckDelay(delay_ms);
 }
 
 void PseudoTcpAdapter::SetNoDelay(bool no_delay) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->SetNoDelay(no_delay);
 }
 
 void PseudoTcpAdapter::SetWriteWaitsForSend(bool write_waits_for_send) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   core_->SetWriteWaitsForSend(write_waits_for_send);
 }
 
diff --git a/remoting/protocol/pseudotcp_adapter.h b/remoting/protocol/pseudotcp_adapter.h
index bde7cca..93e1ac7 100644
--- a/remoting/protocol/pseudotcp_adapter.h
+++ b/remoting/protocol/pseudotcp_adapter.h
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "net/log/net_log_with_source.h"
 #include "remoting/protocol/p2p_stream_socket.h"
 #include "third_party/webrtc/p2p/base/pseudotcp.h"
@@ -27,7 +27,7 @@
 // while PseudoTcp cannot, the core of the PseudoTcpAdapter is reference
 // counted, with a reference held by the adapter, and an additional reference
 // held on the stack during callbacks.
-class PseudoTcpAdapter : public P2PStreamSocket, base::NonThreadSafe {
+class PseudoTcpAdapter : public P2PStreamSocket {
  public:
   explicit PseudoTcpAdapter(std::unique_ptr<P2PDatagramSocket> socket);
   ~PseudoTcpAdapter() override;
@@ -75,6 +75,8 @@
 
   net::NetLogWithSource net_log_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(PseudoTcpAdapter);
 };
 
diff --git a/remoting/protocol/session_manager.h b/remoting/protocol/session_manager.h
index b8cd08f0..827d436f 100644
--- a/remoting/protocol/session_manager.h
+++ b/remoting/protocol/session_manager.h
@@ -57,7 +57,6 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
 #include "remoting/protocol/session.h"
 
 namespace remoting {
@@ -71,7 +70,7 @@
 class AuthenticatorFactory;
 
 // Generic interface for Chromoting session manager.
-class SessionManager : public base::NonThreadSafe {
+class SessionManager {
  public:
   enum IncomingSessionResponse {
     // Accept the session.
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc
index 177699a..5cad111 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator.cc
+++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc
@@ -223,12 +223,13 @@
 }
 
 SslHmacChannelAuthenticator::~SslHmacChannelAuthenticator() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void SslHmacChannelAuthenticator::SecureAndAuthenticate(
     std::unique_ptr<P2PStreamSocket> socket,
     const DoneCallback& done_callback) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   done_callback_ = done_callback;
 
@@ -377,7 +378,7 @@
 }
 
 void SslHmacChannelAuthenticator::OnAuthBytesWritten(int result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (HandleAuthBytesWritten(result, nullptr))
     WriteAuthenticationBytes(nullptr);
@@ -417,7 +418,7 @@
 }
 
 void SslHmacChannelAuthenticator::OnAuthBytesRead(int result) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (HandleAuthBytesRead(result))
     ReadAuthenticationBytes();
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.h b/remoting/protocol/ssl_hmac_channel_authenticator.h
index c76341c8..462aaea 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator.h
+++ b/remoting/protocol/ssl_hmac_channel_authenticator.h
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/protocol/channel_authenticator.h"
 
 namespace net {
@@ -34,8 +34,7 @@
 // SslHmacChannelAuthenticator implements ChannelAuthenticator that
 // secures channels using SSL and authenticates them with a shared
 // secret HMAC.
-class SslHmacChannelAuthenticator : public ChannelAuthenticator,
-                                    public base::NonThreadSafe {
+class SslHmacChannelAuthenticator : public ChannelAuthenticator {
  public:
   enum LegacyMode {
     NONE,
@@ -104,6 +103,8 @@
   scoped_refptr<net::DrainableIOBuffer> auth_write_buf_;
   scoped_refptr<net::GrowableIOBuffer> auth_read_buf_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(SslHmacChannelAuthenticator);
 };
 
diff --git a/remoting/protocol/stream_channel_factory.h b/remoting/protocol/stream_channel_factory.h
index a28b0272..e078659 100644
--- a/remoting/protocol/stream_channel_factory.h
+++ b/remoting/protocol/stream_channel_factory.h
@@ -10,14 +10,14 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 
 namespace remoting {
 namespace protocol {
 
 class P2PStreamSocket;
 
-class StreamChannelFactory : public base::NonThreadSafe {
+class StreamChannelFactory {
  public:
   // TODO(sergeyu): Specify connection error code when channel
   // connection fails.
@@ -42,6 +42,8 @@
  protected:
   virtual ~StreamChannelFactory() {}
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(StreamChannelFactory);
 };
diff --git a/remoting/signaling/fake_signal_strategy.cc b/remoting/signaling/fake_signal_strategy.cc
index dc4db99..33f3242 100644
--- a/remoting/signaling/fake_signal_strategy.cc
+++ b/remoting/signaling/fake_signal_strategy.cc
@@ -33,10 +33,11 @@
       address_(address),
       last_id_(0),
       weak_factory_(this) {
-  DetachFromThread();
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 FakeSignalStrategy::~FakeSignalStrategy() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   while (!received_messages_.empty()) {
     delete received_messages_.front();
     received_messages_.pop_front();
@@ -60,23 +61,23 @@
 }
 
 void FakeSignalStrategy::SetLocalAddress(const SignalingAddress& address) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   address_ = address;
 }
 
 void FakeSignalStrategy::SimulateMessageReordering() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   simulate_reorder_ = true;
 }
 
 void FakeSignalStrategy::Connect() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : listeners_)
     observer.OnSignalStrategyStateChange(CONNECTED);
 }
 
 void FakeSignalStrategy::Disconnect() {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : listeners_)
     observer.OnSignalStrategyStateChange(DISCONNECTED);
 }
@@ -90,22 +91,22 @@
 }
 
 const SignalingAddress& FakeSignalStrategy::GetLocalAddress() const {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return address_;
 }
 
 void FakeSignalStrategy::AddListener(Listener* listener) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   listeners_.AddObserver(listener);
 }
 
 void FakeSignalStrategy::RemoveListener(Listener* listener) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   listeners_.RemoveObserver(listener);
 }
 
 bool FakeSignalStrategy::SendStanza(std::unique_ptr<buzz::XmlElement> stanza) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   address_.SetInMessage(stanza.get(), SignalingAddress::FROM);
 
@@ -139,7 +140,7 @@
 
 void FakeSignalStrategy::OnIncomingMessage(
     std::unique_ptr<buzz::XmlElement> stanza) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!simulate_reorder_) {
     NotifyListeners(std::move(stanza));
@@ -159,7 +160,7 @@
 
 void FakeSignalStrategy::NotifyListeners(
     std::unique_ptr<buzz::XmlElement> stanza) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   buzz::XmlElement* stanza_ptr = stanza.get();
   received_messages_.push_back(stanza.release());
diff --git a/remoting/signaling/fake_signal_strategy.h b/remoting/signaling/fake_signal_strategy.h
index c4da7e4..e22a216 100644
--- a/remoting/signaling/fake_signal_strategy.h
+++ b/remoting/signaling/fake_signal_strategy.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/signaling/iq_sender.h"
 #include "remoting/signaling/signal_strategy.h"
 #include "remoting/signaling/signaling_address.h"
@@ -23,8 +23,7 @@
 
 namespace remoting {
 
-class FakeSignalStrategy : public SignalStrategy,
-                           public base::NonThreadSafe {
+class FakeSignalStrategy : public SignalStrategy {
  public:
   // Calls ConenctTo() to connect |peer1| and |peer2|. Both |peer1| and |peer2|
   // must belong to the current thread.
@@ -91,6 +90,8 @@
   // All received messages, includes thouse still in |pending_messages_|.
   std::list<buzz::XmlElement*> received_messages_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<FakeSignalStrategy> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeSignalStrategy);
diff --git a/remoting/signaling/log_to_server.cc b/remoting/signaling/log_to_server.cc
index 5e05ace..97f8989 100644
--- a/remoting/signaling/log_to_server.cc
+++ b/remoting/signaling/log_to_server.cc
@@ -27,11 +27,12 @@
 }
 
 LogToServer::~LogToServer() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   signal_strategy_->RemoveListener(this);
 }
 
 void LogToServer::OnSignalStrategyStateChange(SignalStrategy::State state) {
-  DCHECK(CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (state == SignalStrategy::CONNECTED) {
     iq_sender_.reset(new IqSender(signal_strategy_));
diff --git a/remoting/signaling/log_to_server.h b/remoting/signaling/log_to_server.h
index 6986c816..2746268 100644
--- a/remoting/signaling/log_to_server.h
+++ b/remoting/signaling/log_to_server.h
@@ -10,7 +10,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/sequence_checker.h"
 #include "remoting/signaling/server_log_entry.h"
 #include "remoting/signaling/signal_strategy.h"
 
@@ -25,8 +25,7 @@
 // LogToServer sends log entries to a server.
 // The contents of the log entries are described in server_log_entry.cc.
 // They do not contain any personally identifiable information.
-class LogToServer : public base::NonThreadSafe,
-                    public SignalStrategy::Listener {
+class LogToServer : public SignalStrategy::Listener {
  public:
   LogToServer(ServerLogEntry::Mode mode,
               SignalStrategy* signal_strategy,
@@ -51,6 +50,8 @@
 
   std::deque<ServerLogEntry> pending_entries_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(LogToServer);
 };
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 6e5b1d3..b9ba46a 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -83,6 +83,11 @@
 crbug.com/664852 virtual/gpu/fast/canvas/canvas-createImageBitmap-webgl.html [ Pass Failure ]
 crbug.com/664852 virtual/gpu/fast/canvas/OffscreenCanvas-2d-drawImage.html [ Pass Failure ]
 
+########## Skia issues ##########
+crbug.com/728566 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png.html [ NeedsManualRebaseline ]
+crbug.com/728566 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade.html [ NeedsManualRebaseline ]
+crbug.com/728566 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ NeedsManualRebaseline ]
+
 ########## Bugs to fix ##########
 # This is a missing event and increasing the timeout or using run-after-layout-and-paint doesn't
 # seem to fix it.
@@ -122,8 +127,8 @@
 #### external/wpt/css/css-position-3
 crbug.com/702927 external/wpt/css/css-position-3/position-sticky-table-tr-top.html [ Failure ]
 crbug.com/702927 external/wpt/css/css-position-3/position-sticky-table-tr-bottom.html [ Failure ]
-crbug.com/728527 external/wpt/css/css-position-3/position-sticky-table-tfoot-bottom.html [ Failure ]
-crbug.com/728527 external/wpt/css/css-position-3/position-sticky-table-thead-top.html [ Failure ]
+crbug.com/702927 external/wpt/css/css-position-3/position-sticky-table-tfoot-bottom.html [ Failure ]
+crbug.com/702927 external/wpt/css/css-position-3/position-sticky-table-thead-top.html [ Failure ]
 
 # ====== Layout team owned tests from here ======
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-custom-scrollbars.html b/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-custom-scrollbars.html
index 3b3f029..10d332c 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-custom-scrollbars.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-custom-scrollbars.html
@@ -37,16 +37,27 @@
       internals.setPageScaleFactor(pageScaleFactor);
 
       // Verify viewport dimensions exclude scrollbar.
-      assert_equals(viewport().width, 800 / pageScaleFactor - scrollbarWidthCSSPixels);
-      assert_equals(viewport().height, 600 / pageScaleFactor - scrollbaHeightCSSPixels);
+      assert_equals(
+          viewport().width,
+          800 / pageScaleFactor - scrollbarWidthCSSPixels,
+          "Width with pinch-zoom");
+      assert_equals(
+          viewport().height, 600 / pageScaleFactor - scrollbaHeightCSSPixels,
+          "Height with pinch-zoom");
 
       // Apply browser zoom.
       window.internals.setZoomFactor(browserZoomFactor);
 
       // Verify scrollbar exclusion with browser zoom. Custom scrollbars are
       // scaled with browser zoom but remain unchanged with pinch zoom.
-      assert_equals(viewport().width, 800 / browserZoomFactor / pageScaleFactor - scrollbarWidthCSSPixels * browserZoomFactor);
-      assert_equals(viewport().height, 600 / browserZoomFactor / pageScaleFactor - scrollbaHeightCSSPixels * browserZoomFactor);
+      assert_equals(
+          viewport().width,
+          800 / browserZoomFactor / pageScaleFactor - scrollbarWidthCSSPixels,
+          "Width with pinch-zoom and browser-zoom");
+      assert_equals(
+          viewport().height,
+          600 / browserZoomFactor / pageScaleFactor - scrollbaHeightCSSPixels,
+          "Height with pinch-zoom and browser-zoom");
       t.done();
     });
   }, 'Verify viewport dimensions exclude custom scrollbars.');
diff --git a/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-scrollbars.html b/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-scrollbars.html
index 2e6405b8..55256d9 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-scrollbars.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/viewport/viewport-dimensions-exclude-scrollbars.html
@@ -24,15 +24,32 @@
       internals.setPageScaleFactor(pageScaleFactor);
 
       // Verify viewport dimensions exclude scrollbar.
-      assert_equals(viewport().width, 800 / pageScaleFactor - scrollbarWidthCSSPixels);
-      assert_equals(viewport().height, 600 / pageScaleFactor - scrollbarHeightCSSPixels);
+      assert_equals(
+          viewport().width,
+          800 / pageScaleFactor - scrollbarWidthCSSPixels,
+          "Width with pinch-zoom");
+      assert_equals(
+          viewport().height,
+          600 / pageScaleFactor - scrollbarHeightCSSPixels,
+          "Height with pinch-zoom");
 
       // Apply browser zoom.
       window.internals.setZoomFactor(browserZoomFactor);
 
+      // Since the scrollbars don't change size to the user as we zoom, they're
+      // actuall smaller in CSS pixels.
+      scrollbarWidthCSSPixels /= browserZoomFactor;
+      scrollbarHeightCSSPixels /= browserZoomFactor;
+
       // Verify scrollbar exclusion with browser zoom.
-      assert_equals(viewport().width, 800 / pageScaleFactor / browserZoomFactor - scrollbarWidthCSSPixels);
-      assert_equals(viewport().height, 600 / pageScaleFactor / browserZoomFactor - scrollbarHeightCSSPixels);
+      assert_equals(
+          viewport().width, 
+          800 / pageScaleFactor / browserZoomFactor - scrollbarWidthCSSPixels,
+          "Width with pinch-zoom and browser zoom");
+      assert_equals(
+          viewport().height,
+          600 / pageScaleFactor / browserZoomFactor - scrollbarHeightCSSPixels,
+          "Height with pinch-zoom and browser zoom");
       t.done();
     });
   }, 'Verify viewport dimensions exclude scrollbars.');
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/doubly-nested-with-zero-width-flexbox-and-forced-break-crash.html b/third_party/WebKit/LayoutTests/fast/multicol/doubly-nested-with-zero-width-flexbox-and-forced-break-crash.html
new file mode 100644
index 0000000..cf936520
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/doubly-nested-with-zero-width-flexbox-and-forced-break-crash.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<div style="columns:30;">
+    <div style="columns:1; width:0;">
+        <div style="display:flex; flex-flow:column;">
+            <div style="columns:1;">
+                <div style="height:8px;"></div>
+                <div style="break-before:column; height:4096px;"></div>
+            </div>
+        </div>
+    </div>
+</div>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(() => { }, "No crash or assertion failure.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/nested-with-spanner-inside-margins-crash.html b/third_party/WebKit/LayoutTests/fast/multicol/nested-with-spanner-inside-margins-crash.html
new file mode 100644
index 0000000..13090e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/nested-with-spanner-inside-margins-crash.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<div style="columns:2; column-fill:auto; height:16px;">
+    <div style="columns:1;">
+        <div style="margin-top:16px; margin-bottom:16px;">
+            <div style="column-span:all;"></div>
+        </div>
+        <br>
+    </div>
+</div>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(() => { }, "No crash or assertion failure.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces-script-added-expected.txt b/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces-script-added-expected.txt
deleted file mode 100644
index b44b78e..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces-script-added-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-FAIL WebUSB related properties on interfaces before adding trial token via script. assert_equals: Property usb exists on Navigator expected false but got true
-FAIL WebUSB related interfaces before adding trial token via script. assert_equals: Interface USBAlternateInterface exists on provided object expected false but got true
-PASS WebUSB related properties on interfaces after adding trial token via script. 
-PASS WebUSB related interfaces after adding trial token via script. 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces-script-added.html b/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces-script-added.html
deleted file mode 100644
index d069555..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces-script-added.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>WebUSB - origin trial is enabled by script-added meta tag</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/origin-trials-helper.js"></script>
-<script>
-// Generate token with the command:
-// generate_token.py  http://127.0.0.1:8000 WebUSB2 --expire-timestamp=2000000000
-let token = "AmgWWAL+v07ElzPwp9oXvY1ldvKTbMlEUFopboMutESil7WUfQNVdYFUzfai6GRq5MndTa+ln+w1gLlRw8VshwAAAABPeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiV2ViVVNCMiIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==";
-
-let properties_to_check = {'Navigator': ['usb']};
-let interfaces_to_check = ['USBAlternateInterface',
-    'USBConfiguration',
-    'USBConnectionEvent',
-    'USBDevice',
-    'USBEndpoint',
-    'USBInTransferResult',
-    'USBInterface',
-    'USBIsochronousInTransferPacket',
-    'USBIsochronousInTransferResult',
-    'USBIsochronousOutTransferPacket',
-    'USBIsochronousOutTransferResult',
-    'USBOutTransferResult'];
-
-test(t => {
-  OriginTrialsHelper.check_properties_missing(this, properties_to_check);
-}, "WebUSB related properties on interfaces before adding trial token via script.");
-
-test(t => {
-  OriginTrialsHelper.check_interfaces_missing(this, interfaces_to_check);
-}, "WebUSB related interfaces before adding trial token via script.");
-
-OriginTrialsHelper.add_token(token);
-
-test(t => {
-  OriginTrialsHelper.check_properties(this, properties_to_check);
-}, "WebUSB related properties on interfaces after adding trial token via script.");
-
-test(t => {
-  OriginTrialsHelper.check_interfaces(this, interfaces_to_check);
-}, "WebUSB related interfaces after adding trial token via script.");
-</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces.html b/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces.html
deleted file mode 100644
index 68a9358b..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/origin_trials/webexposed/webusb-origin-trial-interfaces.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<!-- Generate token with the command:
-generate_token.py  http://127.0.0.1:8000 WebUSB2 --expire-timestamp=2000000000
--->
-<meta http-equiv="origin-trial" content="AmgWWAL+v07ElzPwp9oXvY1ldvKTbMlEUFopboMutESil7WUfQNVdYFUzfai6GRq5MndTa+ln+w1gLlRw8VshwAAAABPeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiV2ViVVNCMiIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==" />
-<title>WebUSB - interfaces exposed by origin trial</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/origin-trials-helper.js"></script>
-<script>
-test(t => {
-  OriginTrialsHelper.check_properties(this, {'Navigator': ['usb']});
-}, "WebUSB related properties on interfaces in Origin-Trial enabled document.");
-
-test(t => {
-  OriginTrialsHelper.check_interfaces(this,
-    ['USBAlternateInterface',
-     'USBConfiguration',
-     'USBConnectionEvent',
-     'USBDevice',
-     'USBEndpoint',
-     'USBInTransferResult',
-     'USBInterface',
-     'USBIsochronousInTransferPacket',
-     'USBIsochronousInTransferResult',
-     'USBIsochronousOutTransferPacket',
-     'USBIsochronousOutTransferResult',
-     'USBOutTransferResult']);
-}, "WebUSB related interfaces in Origin-Trial enabled document.");
-</script>
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
index 17043d4a..e01e629 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -3631,6 +3631,7 @@
     getter productSub
     getter serviceWorker
     getter storage
+    getter usb
     getter userAgent
     getter vendor
     getter vendorSub
@@ -5938,6 +5939,111 @@
     method set
     method toString
     method values
+interface USB : EventTarget
+    attribute @@toStringTag
+    getter onconnect
+    getter ondisconnect
+    method constructor
+    method getDevices
+    method requestDevice
+    setter onconnect
+    setter ondisconnect
+interface USBAlternateInterface
+    attribute @@toStringTag
+    getter alternateSetting
+    getter endpoints
+    getter interfaceClass
+    getter interfaceName
+    getter interfaceProtocol
+    getter interfaceSubclass
+    method constructor
+interface USBConfiguration
+    attribute @@toStringTag
+    getter configurationName
+    getter configurationValue
+    getter interfaces
+    method constructor
+interface USBConnectionEvent : Event
+    attribute @@toStringTag
+    getter device
+    method constructor
+interface USBDevice
+    attribute @@toStringTag
+    getter configuration
+    getter configurations
+    getter deviceClass
+    getter deviceProtocol
+    getter deviceSubclass
+    getter deviceVersionMajor
+    getter deviceVersionMinor
+    getter deviceVersionSubminor
+    getter manufacturerName
+    getter opened
+    getter productId
+    getter productName
+    getter serialNumber
+    getter usbVersionMajor
+    getter usbVersionMinor
+    getter usbVersionSubminor
+    getter vendorId
+    method claimInterface
+    method clearHalt
+    method close
+    method constructor
+    method controlTransferIn
+    method controlTransferOut
+    method isochronousTransferIn
+    method isochronousTransferOut
+    method open
+    method releaseInterface
+    method reset
+    method selectAlternateInterface
+    method selectConfiguration
+    method transferIn
+    method transferOut
+interface USBEndpoint
+    attribute @@toStringTag
+    getter direction
+    getter endpointNumber
+    getter packetSize
+    getter type
+    method constructor
+interface USBInTransferResult
+    attribute @@toStringTag
+    getter data
+    getter status
+    method constructor
+interface USBInterface
+    attribute @@toStringTag
+    getter alternate
+    getter alternates
+    getter claimed
+    getter interfaceNumber
+    method constructor
+interface USBIsochronousInTransferPacket
+    attribute @@toStringTag
+    getter data
+    getter status
+    method constructor
+interface USBIsochronousInTransferResult
+    attribute @@toStringTag
+    getter data
+    getter packets
+    method constructor
+interface USBIsochronousOutTransferPacket
+    attribute @@toStringTag
+    getter bytesWritten
+    getter status
+    method constructor
+interface USBIsochronousOutTransferResult
+    attribute @@toStringTag
+    getter packets
+    method constructor
+interface USBOutTransferResult
+    attribute @@toStringTag
+    getter bytesWritten
+    getter status
+    method constructor
 interface VTTCue : TextTrackCue
     attribute @@toStringTag
     getter align
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index ef2bb83e..61567ac 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -3559,6 +3559,7 @@
     getter productSub
     getter serviceWorker
     getter storage
+    getter usb
     getter userAgent
     getter vendor
     getter vendorSub
@@ -5867,6 +5868,111 @@
     method set
     method toString
     method values
+interface USB : EventTarget
+    attribute @@toStringTag
+    getter onconnect
+    getter ondisconnect
+    method constructor
+    method getDevices
+    method requestDevice
+    setter onconnect
+    setter ondisconnect
+interface USBAlternateInterface
+    attribute @@toStringTag
+    getter alternateSetting
+    getter endpoints
+    getter interfaceClass
+    getter interfaceName
+    getter interfaceProtocol
+    getter interfaceSubclass
+    method constructor
+interface USBConfiguration
+    attribute @@toStringTag
+    getter configurationName
+    getter configurationValue
+    getter interfaces
+    method constructor
+interface USBConnectionEvent : Event
+    attribute @@toStringTag
+    getter device
+    method constructor
+interface USBDevice
+    attribute @@toStringTag
+    getter configuration
+    getter configurations
+    getter deviceClass
+    getter deviceProtocol
+    getter deviceSubclass
+    getter deviceVersionMajor
+    getter deviceVersionMinor
+    getter deviceVersionSubminor
+    getter manufacturerName
+    getter opened
+    getter productId
+    getter productName
+    getter serialNumber
+    getter usbVersionMajor
+    getter usbVersionMinor
+    getter usbVersionSubminor
+    getter vendorId
+    method claimInterface
+    method clearHalt
+    method close
+    method constructor
+    method controlTransferIn
+    method controlTransferOut
+    method isochronousTransferIn
+    method isochronousTransferOut
+    method open
+    method releaseInterface
+    method reset
+    method selectAlternateInterface
+    method selectConfiguration
+    method transferIn
+    method transferOut
+interface USBEndpoint
+    attribute @@toStringTag
+    getter direction
+    getter endpointNumber
+    getter packetSize
+    getter type
+    method constructor
+interface USBInTransferResult
+    attribute @@toStringTag
+    getter data
+    getter status
+    method constructor
+interface USBInterface
+    attribute @@toStringTag
+    getter alternate
+    getter alternates
+    getter claimed
+    getter interfaceNumber
+    method constructor
+interface USBIsochronousInTransferPacket
+    attribute @@toStringTag
+    getter data
+    getter status
+    method constructor
+interface USBIsochronousInTransferResult
+    attribute @@toStringTag
+    getter data
+    getter packets
+    method constructor
+interface USBIsochronousOutTransferPacket
+    attribute @@toStringTag
+    getter bytesWritten
+    getter status
+    method constructor
+interface USBIsochronousOutTransferResult
+    attribute @@toStringTag
+    getter packets
+    method constructor
+interface USBOutTransferResult
+    attribute @@toStringTag
+    getter bytesWritten
+    getter status
+    method constructor
 interface VTTCue : TextTrackCue
     attribute @@toStringTag
     getter align
diff --git a/third_party/WebKit/PerformanceTests/Paint/resources/paint.js b/third_party/WebKit/PerformanceTests/Paint/resources/paint.js
index 2253b5a..98d128fa0 100644
--- a/third_party/WebKit/PerformanceTests/Paint/resources/paint.js
+++ b/third_party/WebKit/PerformanceTests/Paint/resources/paint.js
@@ -4,6 +4,9 @@
 
 function measurePaint(test) {
   test.tracingCategories = 'blink';
-  test.traceEventsToMeasure = ['FrameView::prePaint', 'FrameView::paintTree'];
+  test.traceEventsToMeasure = [
+    'LocalFrameView::prePaint',
+    'LocalFrameView::paintTree'
+  ];
   PerfTestRunner.measureFrameTime(test);
 }
diff --git a/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html b/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html
index 95369bb8..803bd59 100644
--- a/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html
+++ b/third_party/WebKit/PerformanceTests/TestData/append-child-measure-time.html
@@ -29,7 +29,7 @@
     warmUpCount: 3,
     iterationCount: 5,
     tracingCategories: 'blink',
-    traceEventsToMeasure: ['FrameView::layout', 'UpdateLayoutTree']
+    traceEventsToMeasure: ['LocalFrameView::layout', 'UpdateLayoutTree']
 });
 </script>
 </body>
diff --git a/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html b/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html
index d1c7ee33..617de03 100644
--- a/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html
+++ b/third_party/WebKit/PerformanceTests/TestData/color-changes-measure-frame-time.html
@@ -61,10 +61,13 @@
     for (var index = 0; index < elementsToChange.length; index++)
       elementsToChange[index].style.backgroundColor = newColor;
   },
-   warmUpCount: 3,
-   iterationCount: 10,
-   tracingCategories: 'blink',
-   traceEventsToMeasure: ['FrameView::prePaint', 'FrameView::paintTree']
+  warmUpCount: 3,
+  iterationCount: 10,
+  tracingCategories: 'blink',
+  traceEventsToMeasure: [
+    'LocalFrameView::prePaint',
+    'LocalFrameView::paintTree'
+  ]
 });
 </script>
 </body>
diff --git a/third_party/WebKit/PerformanceTests/TestData/simple-html-measure-page-load-time.html b/third_party/WebKit/PerformanceTests/TestData/simple-html-measure-page-load-time.html
index 6aaca14f..01d818d 100644
--- a/third_party/WebKit/PerformanceTests/TestData/simple-html-measure-page-load-time.html
+++ b/third_party/WebKit/PerformanceTests/TestData/simple-html-measure-page-load-time.html
@@ -8,7 +8,7 @@
         iterationCount: 7,
         tracingCategories: 'blink',
         traceEventsToMeasure: ['WebLocalFrameImpl::createChildframe',
-            'FrameView::performPostLayoutTasks']
+            'LocalFrameView::performPostLayoutTasks']
     });
 </script>
 </body>
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ConditionalFeaturesForModules.cpp b/third_party/WebKit/Source/bindings/modules/v8/ConditionalFeaturesForModules.cpp
index 5304afe..d107c76 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/ConditionalFeaturesForModules.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/ConditionalFeaturesForModules.cpp
@@ -61,10 +61,6 @@
                                           v8::Local<v8::Object>(),
                                           prototype_object, interface_object);
     }
-    if (OriginTrials::webUSBEnabled(execution_context)) {
-      V8NavigatorPartial::installWebUSB(isolate, world, v8::Local<v8::Object>(),
-                                        prototype_object, interface_object);
-    }
     if (OriginTrials::webVREnabled(execution_context)) {
       V8NavigatorPartial::installWebVR(isolate, world, v8::Local<v8::Object>(),
                                        prototype_object, interface_object);
@@ -72,13 +68,6 @@
   } else if (wrapper_type_info == &V8Window::wrapperTypeInfo) {
     v8::Local<v8::Object> instance_object =
         script_state->GetContext()->Global();
-    // Mimics the [SecureContext] extended attribute. Work-around for
-    // https://crbug.com/695123.
-    if (OriginTrials::webUSBEnabled(execution_context) &&
-        execution_context->IsSecureContext()) {
-      V8WindowPartial::installWebUSB(isolate, world, instance_object,
-                                     prototype_object, interface_object);
-    }
     if (OriginTrials::webVREnabled(execution_context)) {
       V8WindowPartial::installWebVR(isolate, world, instance_object,
                                     prototype_object, interface_object);
@@ -189,19 +178,6 @@
     }
     return;
   }
-  if (feature == "WebUSB2") {
-    global_instance_object = script_state->GetContext()->Global();
-    V8WindowPartial::installWebUSB(isolate, world, global_instance_object,
-                                   v8::Local<v8::Object>(),
-                                   v8::Local<v8::Function>());
-    if (context_data->GetExistingConstructorAndPrototypeForType(
-            &V8Navigator::wrapperTypeInfo, &prototype_object,
-            &interface_object)) {
-      V8NavigatorPartial::installWebUSB(isolate, world, v8::Local<v8::Object>(),
-                                        prototype_object, interface_object);
-    }
-    return;
-  }
   if (feature == "WebVR1.1") {
     global_instance_object = script_state->GetContext()->Global();
     V8WindowPartial::installGamepadExtensions(
diff --git a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp
index 1bb3b3a..7fe6e4ab 100644
--- a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp
@@ -52,7 +52,7 @@
 
 void ElementVisibilityObserver::OnVisibilityChanged(
     const HeapVector<Member<IntersectionObserverEntry>>& entries) {
-  bool is_visible = entries.back()->intersectionRatio() >
+  bool is_visible = entries.back()->intersectionRatio() >=
                     intersection_observer_->thresholds()[0];
   (*callback_.get())(is_visible);
 }
diff --git a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h
index ef982b86..fbc0197 100644
--- a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h
+++ b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h
@@ -5,6 +5,8 @@
 #ifndef ElementVisibilityObserver_h
 #define ElementVisibilityObserver_h
 
+#include <limits>
+
 #include "core/CoreExport.h"
 #include "core/dom/IntersectionObserver.h"
 #include "platform/heap/Heap.h"
@@ -34,7 +36,9 @@
   virtual ~ElementVisibilityObserver();
 
   // The |threshold| is the minimum fraction that needs to be visible.
-  void Start(float threshold = 0.0);
+  // See https://github.com/WICG/IntersectionObserver/issues/164 for why this
+  // defaults to std::numeric_limits<float>::min() rather than zero.
+  void Start(float threshold = std::numeric_limits<float>::min());
   void Stop();
 
   void DeliverObservationsForTesting();
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
index c003617..8fd5795f 100644
--- a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
+++ b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
@@ -108,8 +108,8 @@
   // dispatched event.
 
   if (target_frame) {
-    FloatPoint page_point =
-        target_frame->View()->RootFrameToContents(touch_point.position);
+    FloatPoint page_point = target_frame->View()->RootFrameToContents(
+        touch_point.PositionInWidget());
     float scale_factor = 1.0f / target_frame->PageZoomFactor();
     FloatPoint scroll_position(target_frame->View()->GetScrollOffset());
     FloatPoint client_point = page_point.ScaledBy(scale_factor);
@@ -130,8 +130,8 @@
     pointer_event_init->setHeight(point_radius.Height());
   }
 
-  pointer_event_init->setScreenX(touch_point.screen_position.x);
-  pointer_event_init->setScreenY(touch_point.screen_position.y);
+  pointer_event_init->setScreenX(touch_point.PositionInScreen().x);
+  pointer_event_init->setScreenY(touch_point.PositionInScreen().y);
   pointer_event_init->setPressure(GetPointerEventPressure(
       touch_point.force, pointer_event_init->buttons()));
   pointer_event_init->setTiltX(touch_point.tilt_x);
diff --git a/third_party/WebKit/Source/core/frame/VisualViewport.cpp b/third_party/WebKit/Source/core/frame/VisualViewport.cpp
index eb922b6..8bdaba2 100644
--- a/third_party/WebKit/Source/core/frame/VisualViewport.cpp
+++ b/third_party/WebKit/Source/core/frame/VisualViewport.cpp
@@ -216,9 +216,11 @@
 
   UpdateStyleAndLayoutIgnorePendingStylesheets();
 
-  float width = AdjustScrollForAbsoluteZoom(VisibleSize().Width(),
-                                            MainFrame()->PageZoomFactor());
-  return width - MainFrame()->View()->VerticalScrollbarWidth() / scale_;
+  float zoom = MainFrame()->PageZoomFactor();
+  float width_css_px = AdjustScrollForAbsoluteZoom(VisibleSize().Width(), zoom);
+  float scrollbar_thickness_css_px =
+      MainFrame()->View()->VerticalScrollbarWidth() / (zoom * scale_);
+  return width_css_px - scrollbar_thickness_css_px;
 }
 
 double VisualViewport::Height() const {
@@ -227,9 +229,12 @@
 
   UpdateStyleAndLayoutIgnorePendingStylesheets();
 
-  float height = AdjustScrollForAbsoluteZoom(VisibleSize().Height(),
-                                             MainFrame()->PageZoomFactor());
-  return height - MainFrame()->View()->HorizontalScrollbarHeight() / scale_;
+  float zoom = MainFrame()->PageZoomFactor();
+  float height_css_px =
+      AdjustScrollForAbsoluteZoom(VisibleSize().Height(), zoom);
+  float scrollbar_thickness_css_px =
+      MainFrame()->View()->HorizontalScrollbarHeight() / (zoom * scale_);
+  return height_css_px - scrollbar_thickness_css_px;
 }
 
 double VisualViewport::ScaleForVisualViewport() const {
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
index ccafa27e..fa66da1 100644
--- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
@@ -341,8 +341,8 @@
       HitTestRequest::HitTestRequestType hit_type =
           HitTestRequest::kTouchEvent | HitTestRequest::kReadOnly |
           HitTestRequest::kActive;
-      LayoutPoint page_point = LayoutPoint(
-          frame_->View()->RootFrameToContents(touch_info.point.position));
+      LayoutPoint page_point = LayoutPoint(frame_->View()->RootFrameToContents(
+          touch_info.point.PositionInWidget()));
       HitTestResult hit_test_tesult =
           frame_->GetEventHandler().HitTestResultAtPoint(page_point, hit_type);
       Node* node = hit_test_tesult.InnerNode();
diff --git a/third_party/WebKit/Source/core/input/TouchEventManager.cpp b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
index dfe8aa9..86c234e 100644
--- a/third_party/WebKit/Source/core/input/TouchEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/TouchEventManager.cpp
@@ -157,7 +157,7 @@
 
     Touch* touch = Touch::Create(
         touch_info.target_frame.Get(), touch_info.touch_node.Get(), point.id,
-        point.screen_position, touch_info.content_point,
+        point.PositionInScreen(), touch_info.content_point,
         touch_info.adjusted_radius, point.rotation_angle, point.force,
         touch_info.region);
 
@@ -334,7 +334,7 @@
         if (touch_sequence_document_->GetFrame()) {
           LayoutPoint frame_point = LayoutPoint(
               touch_sequence_document_->GetFrame()->View()->RootFrameToContents(
-                  touch_info.point.position));
+                  touch_info.point.PositionInWidget()));
           result = EventHandlingUtil::HitTestResultInFrame(
               touch_sequence_document_->GetFrame(), frame_point, hit_type);
           Node* node = result.InnerNode();
@@ -443,8 +443,8 @@
     DCHECK(target_frame);
 
     // pagePoint should always be in the target element's document coordinates.
-    FloatPoint page_point =
-        target_frame->View()->RootFrameToContents(touch_info.point.position);
+    FloatPoint page_point = target_frame->View()->RootFrameToContents(
+        touch_info.point.PositionInWidget());
     float scale_factor = 1.0f / target_frame->PageZoomFactor();
 
     touch_info.touch_node = touch_node;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp
index 6c95485..bd73a16 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorInputAgent.cpp
@@ -87,14 +87,14 @@
   SyntheticInspectorTouchPoint(int idParam,
                                State stateParam,
                                const blink::IntPoint& screenPos,
-                               const blink::IntPoint& pos,
+                               const blink::IntPoint& widgetPos,
                                int radiusXParam,
                                int radiusYParam,
                                double rotationAngleParam,
                                double forceParam) {
     id = idParam;
-    screen_position = screenPos;
-    position = pos;
+    SetPositionInScreen(screenPos.X(), screenPos.Y());
+    SetPositionInWidget(widgetPos.X(), widgetPos.Y());
     state = stateParam;
     radius_x = radiusXParam;
     radius_y = radiusYParam;
diff --git a/third_party/WebKit/Source/core/layout/ColumnBalancer.h b/third_party/WebKit/Source/core/layout/ColumnBalancer.h
index ead4b11c..d9a49f8b 100644
--- a/third_party/WebKit/Source/core/layout/ColumnBalancer.h
+++ b/third_party/WebKit/Source/core/layout/ColumnBalancer.h
@@ -55,9 +55,11 @@
       // in a previous fragmentainer group.
       return false;
     }
+    const auto& group = GroupAtOffset(flow_thread_offset);
+    if (!group.IsLogicalHeightKnown())
+      return false;
     return flow_thread_offset ==
-           GroupAtOffset(flow_thread_offset)
-               .ColumnLogicalTopForOffset(flow_thread_offset);
+           group.ColumnLogicalTopForOffset(flow_thread_offset);
   }
 
   bool IsLogicalTopWithinBounds(LayoutUnit logical_top_in_flow_thread) const {
diff --git a/third_party/WebKit/Source/core/layout/FragmentationContext.h b/third_party/WebKit/Source/core/layout/FragmentationContext.h
index beb34cd..eee4dc8 100644
--- a/third_party/WebKit/Source/core/layout/FragmentationContext.h
+++ b/third_party/WebKit/Source/core/layout/FragmentationContext.h
@@ -37,8 +37,10 @@
   virtual bool IsFragmentainerLogicalHeightKnown() = 0;
 
   // Return the height of the fragmentainer at the specified offset. The
-  // fragmentainer height isn't necessarily uniform all across the fragmentation
-  // context.
+  // fragmentainer height isn't necessarily uniform all across the
+  // fragmentation context. This method may only be called if the logical
+  // height has been calculated, i.e. if IsFragmentainerLogicalHeightKnown()
+  // returns true.
   virtual LayoutUnit FragmentainerLogicalHeightAt(LayoutUnit block_offset) = 0;
 
   // Return how much is left of the fragmentainer at the specified offset.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 3d46733..4ad7605 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -1047,7 +1047,7 @@
     } else {
       // Even if we didn't break before the border box to the next
       // fragmentainer, we need to check if we can fit the margin before it.
-      if (PageLogicalHeightForOffset(logical_top_margin_edge)) {
+      if (IsPageLogicalHeightKnown()) {
         LayoutUnit remaining_space = PageRemainingLogicalHeightForOffset(
             logical_top_margin_edge, kAssociateWithLatterPage);
         if (remaining_space <= margin_before) {
@@ -1133,9 +1133,9 @@
   LayoutState* layout_state = View()->GetLayoutState();
   if (!layout_state->IsPaginated())
     return;
-  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
-  if (!page_logical_height)
+  if (!IsPageLogicalHeightKnown())
     return;
+  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
   LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
       logical_offset, kAssociateWithLatterPage);
   int line_index = LineCount(&line_box);
@@ -1242,8 +1242,7 @@
   if (child.IsFloating())
     child_logical_height +=
         MarginBeforeForChild(child) + MarginAfterForChild(child);
-  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
-  if (!page_logical_height)
+  if (!IsPageLogicalHeightKnown())
     return logical_offset;
   LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
       logical_offset, kAssociateWithLatterPage);
@@ -1252,7 +1251,7 @@
   LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
       logical_offset, remaining_logical_height, child_logical_height);
   if (pagination_strut == remaining_logical_height &&
-      remaining_logical_height == page_logical_height) {
+      remaining_logical_height == PageLogicalHeightForOffset(logical_offset)) {
     // Don't break if we were at the top of a page, and we failed to fit the
     // content completely. No point in leaving a page completely blank.
     return logical_offset;
@@ -2393,13 +2392,13 @@
   // next fragmentainer of the fragmentation context we're in. However, we may
   // want to find the next left or right page - even if we're inside a multicol
   // container when printing.
-  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
-  if (!page_logical_height)
-    return logical_offset;  // Page height is still unknown, so we cannot insert
-                            // forced breaks.
+  if (!IsPageLogicalHeightKnown()) {
+    // Page height is still unknown, so we cannot insert forced breaks.
+    return logical_offset;
+  }
   LayoutUnit remaining_logical_height = PageRemainingLogicalHeightForOffset(
       logical_offset, kAssociateWithLatterPage);
-  if (remaining_logical_height == page_logical_height)
+  if (remaining_logical_height == PageLogicalHeightForOffset(logical_offset))
     return logical_offset;  // Don't break if we're already at the block start
                             // of a fragmentainer.
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 1440fc9..6141f60d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -4913,7 +4913,7 @@
   LayoutState* layout_state = View()->GetLayoutState();
   DCHECK(layout_state->IsPaginated());
   child.SetOffsetToNextPage(LayoutUnit());
-  if (!PageLogicalHeightForOffset(child.LogicalTop()))
+  if (!IsPageLogicalHeightKnown())
     return;
 
   LayoutUnit logical_top = child.LogicalTop();
@@ -4930,11 +4930,11 @@
   if (child.IsFloating())
     return true;
   const LayoutFlowThread* flow_thread = child.FlowThreadContainingBlock();
-  LayoutUnit logical_top = child.LogicalTop();
   // Figure out if we really need to force re-layout of the child. We only need
   // to do this if there's a chance that we need to recalculate pagination
   // struts inside.
-  if (PageLogicalHeightForOffset(logical_top)) {
+  if (IsPageLogicalHeightKnown()) {
+    LayoutUnit logical_top = child.LogicalTop();
     LayoutUnit logical_height = child.LogicalHeightWithVisibleOverflow();
     LayoutUnit remaining_space = PageRemainingLogicalHeightForOffset(
         logical_top, kAssociateWithLatterPage);
@@ -5731,12 +5731,22 @@
 }
 
 LayoutUnit LayoutBox::PageLogicalHeightForOffset(LayoutUnit offset) const {
+  // We need to have calculated some fragmentainer logical height (even a
+  // tentative one will do, though) in order to tell how tall one fragmentainer
+  // is.
+  DCHECK(IsPageLogicalHeightKnown());
+
   LayoutView* layout_view = View();
   LayoutFlowThread* flow_thread = FlowThreadContainingBlock();
-  if (!flow_thread)
-    return layout_view->PageLogicalHeight();
-  return flow_thread->PageLogicalHeightForOffset(
-      offset + OffsetFromLogicalTopOfFirstPage());
+  LayoutUnit page_logical_height;
+  if (!flow_thread) {
+    page_logical_height = layout_view->PageLogicalHeight();
+  } else {
+    page_logical_height = flow_thread->PageLogicalHeightForOffset(
+        offset + OffsetFromLogicalTopOfFirstPage());
+  }
+  DCHECK_GT(page_logical_height, LayoutUnit());
+  return page_logical_height;
 }
 
 bool LayoutBox::IsPageLogicalHeightKnown() const {
@@ -5748,6 +5758,7 @@
 LayoutUnit LayoutBox::PageRemainingLogicalHeightForOffset(
     LayoutUnit offset,
     PageBoundaryRule page_boundary_rule) const {
+  DCHECK(IsPageLogicalHeightKnown());
   LayoutView* layout_view = View();
   offset += OffsetFromLogicalTopOfFirstPage();
 
@@ -5771,7 +5782,7 @@
 
 bool LayoutBox::CrossesPageBoundary(LayoutUnit offset,
                                     LayoutUnit logical_height) const {
-  if (!PageLogicalHeightForOffset(offset))
+  if (!IsPageLogicalHeightKnown())
     return false;
   return PageRemainingLogicalHeightForOffset(offset, kAssociateWithLatterPage) <
          logical_height;
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
index d08d4abf..3037541 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
@@ -168,10 +168,11 @@
 }
 
 LayoutUnit LayoutFlowThread::PageLogicalHeightForOffset(LayoutUnit offset) {
+  DCHECK(IsPageLogicalHeightKnown());
   LayoutMultiColumnSet* column_set =
       ColumnSetAtBlockOffset(offset, kAssociateWithLatterPage);
   if (!column_set)
-    return LayoutUnit();
+    return LayoutUnit(1);
 
   return column_set->PageLogicalHeightForOffset(offset);
 }
@@ -179,10 +180,11 @@
 LayoutUnit LayoutFlowThread::PageRemainingLogicalHeightForOffset(
     LayoutUnit offset,
     PageBoundaryRule page_boundary_rule) {
+  DCHECK(IsPageLogicalHeightKnown());
   LayoutMultiColumnSet* column_set =
       ColumnSetAtBlockOffset(offset, page_boundary_rule);
   if (!column_set)
-    return LayoutUnit();
+    return LayoutUnit(1);
 
   return column_set->PageRemainingLogicalHeightForOffset(offset,
                                                          page_boundary_rule);
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
index 0e0e2bd..0353e31 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
@@ -680,13 +680,7 @@
             logical_offset_in_outer, kAssociateWithLatterPage);
       }
 
-      const MultiColumnFragmentainerGroup& new_row =
-          column_set->AppendNewFragmentainerGroup();
-      // Zero-height rows should really not occur here, but if it does anyway,
-      // break, so that we don't get stuck in an infinite loop.
-      DCHECK_GT(new_row.ColumnLogicalHeight(), 0);
-      if (new_row.ColumnLogicalHeight() <= 0)
-        break;
+      column_set->AppendNewFragmentainerGroup();
     } while (column_set->NeedsNewFragmentainerGroupAt(offset_in_flow_thread,
                                                       page_boundary_rule));
   }
@@ -698,11 +692,13 @@
 
 LayoutUnit LayoutMultiColumnFlowThread::FragmentainerLogicalHeightAt(
     LayoutUnit block_offset) {
+  DCHECK(IsPageLogicalHeightKnown());
   return PageLogicalHeightForOffset(block_offset);
 }
 
 LayoutUnit LayoutMultiColumnFlowThread::RemainingLogicalHeightAt(
     LayoutUnit block_offset) {
+  DCHECK(IsPageLogicalHeightKnown());
   return PageRemainingLogicalHeightForOffset(block_offset,
                                              kAssociateWithLatterPage);
 }
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp
index 9d6ea75..c42f2b9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnSet.cpp
@@ -87,42 +87,38 @@
 
 LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset(
     LayoutUnit offset_in_flow_thread) const {
+  DCHECK(IsPageLogicalHeightKnown());
   const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup();
-  if (!last_row.GroupLogicalHeight() && fragmentainer_groups_.size() == 1) {
-    // In the first layout pass of an auto-height multicol container, height
-    // isn't set. No need to perform the series of complicated dance steps below
-    // to figure out that we should simply return 0. Bail now.
-    return LayoutUnit();
-  }
   if (offset_in_flow_thread >= last_row.LogicalTopInFlowThread() +
                                    FragmentainerGroupCapacity(last_row)) {
     // The offset is outside the bounds of the fragmentainer groups that we have
     // established at this point. If we're nested inside another fragmentation
     // context, we need to calculate the height on our own.
     const LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread();
-    if (FragmentationContext* enclosing_fragmentation_context =
-            flow_thread->EnclosingFragmentationContext()) {
-      // We'd ideally like to translate |offsetInFlowThread| to an offset in the
-      // coordinate space of the enclosing fragmentation context here, but
+    FragmentationContext* enclosing_fragmentation_context =
+        flow_thread->EnclosingFragmentationContext();
+    if (enclosing_fragmentation_context &&
+        enclosing_fragmentation_context->IsFragmentainerLogicalHeightKnown()) {
+      // We'd ideally like to translate |offset_in_flow_thread| to an offset in
+      // the coordinate space of the enclosing fragmentation context here, but
       // that's hard, since the offset is out of bounds. So just use the bottom
       // we have found so far.
       LayoutUnit enclosing_context_bottom =
           last_row.BlockOffsetInEnclosingFragmentationContext() +
           last_row.GroupLogicalHeight();
-      LayoutUnit enclosing_fragmentainer_height =
+      LayoutUnit extra_row_height =
           enclosing_fragmentation_context->FragmentainerLogicalHeightAt(
               enclosing_context_bottom);
-      // Constrain against specified height / max-height.
       LayoutUnit current_multicol_height = LogicalTopFromMulticolContentEdge() +
                                            last_row.LogicalTop() +
                                            last_row.GroupLogicalHeight();
+      // Constrain against specified height / max-height.
       LayoutUnit multicol_height_with_extra_row =
-          current_multicol_height + enclosing_fragmentainer_height;
-      multicol_height_with_extra_row =
-          std::min(multicol_height_with_extra_row,
+          std::min(current_multicol_height + extra_row_height,
                    flow_thread->MaxColumnLogicalHeight());
-      return std::max(LayoutUnit(1),
-                      multicol_height_with_extra_row - current_multicol_height);
+      extra_row_height =
+          multicol_height_with_extra_row - current_multicol_height;
+      return extra_row_height.ClampNegativeToZero();
     }
   }
   return FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread,
@@ -161,7 +157,7 @@
 }
 
 bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const {
-  return FirstFragmentainerGroup().ColumnLogicalHeight();
+  return FirstFragmentainerGroup().IsLogicalHeightKnown();
 }
 
 bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const {
@@ -462,8 +458,15 @@
     LayoutUnit logical_top,
     LogicalExtentComputedValues& computed_values) const {
   LayoutUnit logical_height;
-  for (const auto& group : fragmentainer_groups_)
-    logical_height += group.GroupLogicalHeight();
+  // Under some circumstances column heights are unknown at this point. This
+  // happens e.g. when this column set got pushed down by a preceding spanner
+  // (and when that affects the available space for this column set). Just set
+  // the height to 0 for now. Another layout pass has already been scheduled, to
+  // calculate the correct height.
+  if (IsPageLogicalHeightKnown()) {
+    for (const auto& group : fragmentainer_groups_)
+      logical_height += group.GroupLogicalHeight();
+  }
   computed_values.extent_ = logical_height;
   computed_values.position_ = logical_top;
 }
@@ -511,6 +514,10 @@
 }
 
 void LayoutMultiColumnSet::AddOverflowFromChildren() {
+  // It's useless to calculate overflow if we haven't determined the page
+  // logical height yet.
+  if (!IsPageLogicalHeightKnown())
+    return;
   LayoutRect overflow_rect;
   for (const auto& group : fragmentainer_groups_) {
     LayoutRect rect = group.CalculateOverflow();
diff --git a/third_party/WebKit/Source/core/layout/LayoutPagedFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutPagedFlowThread.cpp
index bfe72a3..f6bee400 100644
--- a/third_party/WebKit/Source/core/layout/LayoutPagedFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutPagedFlowThread.cpp
@@ -45,11 +45,13 @@
   LayoutMultiColumnSet* column_set = FirstMultiColumnSet();
   if (!column_set)
     return;
+  if (!IsPageLogicalHeightKnown()) {
+    // Page height not calculated yet. Happens in the first layout pass when
+    // height is auto.
+    return;
+  }
   LayoutUnit page_logical_height =
       column_set->PageLogicalHeightForOffset(LayoutUnit());
-  if (!page_logical_height)
-    return;  // Page height not calculated yet. Happens in the first layout pass
-             // when height is auto.
   // Ensure uniform page height. We don't want the last page to be shorter than
   // the others, or it'll be impossible to scroll that whole page into view.
   LayoutUnit padded_logical_bottom_in_flow_thread =
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index 0c8b64c3..408bd532 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -651,7 +651,7 @@
     if (LayoutTableSection* section = Header()) {
       LayoutSection(*section, layouter, section_logical_left,
                     table_height_changing);
-      if (state.IsPaginated()) {
+      if (state.IsPaginated() && IsPageLogicalHeightKnown()) {
         // If the repeating header group allows at least one row of content,
         // then store the offset for other sections to offset their rows
         // against.
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index 92766866..37406594 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1217,9 +1217,9 @@
   DCHECK(row);
   if (row->GetPaginationBreakability() == kAllowAnyBreaks)
     return 0;
-  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
-  if (!page_logical_height)
+  if (!IsPageLogicalHeightKnown())
     return 0;
+  LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
   // If the row is too tall for the page don't insert a strut.
   LayoutUnit row_logical_height = row->LogicalHeight();
   if (row_logical_height > page_logical_height)
@@ -1891,6 +1891,8 @@
                                                 SubtreeLayoutScope& layouter) {
   row_object.SetPaginationStrut(LayoutUnit());
   row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
+  if (!IsPageLogicalHeightKnown())
+    return;
   int pagination_strut =
       PaginationStrutForRow(&row_object, row_object.LogicalTop());
   bool row_is_at_top_of_column = false;
@@ -1898,7 +1900,7 @@
   if (!pagination_strut) {
     LayoutUnit page_logical_height =
         PageLogicalHeightForOffset(row_object.LogicalTop());
-    if (page_logical_height && Table()->Header() && Table()->Header() != this &&
+    if (Table()->Header() && Table()->Header() != this &&
         Table()->RowOffsetFromRepeatingHeader()) {
       offset_from_top_of_page =
           page_logical_height -
@@ -1952,10 +1954,10 @@
   // TODO(rhogan): Sections can be self-painting.
   if (HasSelfPaintingLayer())
     return false;
-  LayoutUnit page_height = PageLogicalHeightForOffset(LayoutUnit());
   // If we don't know the page height yet, just assume we fit.
-  if (!page_height)
+  if (!IsPageLogicalHeightKnown())
     return true;
+  LayoutUnit page_height = PageLogicalHeightForOffset(LayoutUnit());
 
   if (LogicalHeight() > page_height)
     return false;
diff --git a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.cpp b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.cpp
index 728b340..d62249b3 100644
--- a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.cpp
+++ b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.cpp
@@ -39,9 +39,8 @@
 
 LayoutUnit MultiColumnFragmentainerGroup::LogicalHeightInFlowThreadAt(
     unsigned column_index) const {
+  DCHECK(IsLogicalHeightKnown());
   LayoutUnit column_height = ColumnLogicalHeight();
-  if (!column_height)
-    return LayoutUnit();
   LayoutUnit logical_top = LogicalTopInFlowThreadAt(column_index);
   LayoutUnit logical_bottom = logical_top + column_height;
   if (logical_bottom > LogicalBottomInFlowThread()) {
@@ -65,6 +64,7 @@
       // fragmentation context, in order to tell how much content this
       // MultiColumnFragmentainerGroup can hold, and when we need to append a
       // new one.
+      is_logical_height_known_ = true;
       logical_height_ = max_logical_height_;
       return;
     }
@@ -76,8 +76,10 @@
   // height, we have to balance and shrink the height and lay out the columns
   // over again.
   if (LayoutUnit logical_height = flow_thread->ColumnHeightAvailable()) {
+    is_logical_height_known_ = true;
     SetAndConstrainColumnHeight(HeightAdjustedForRowOffset(logical_height));
   } else {
+    is_logical_height_known_ = false;
     logical_height_ = LayoutUnit();
   }
 }
@@ -120,6 +122,10 @@
     SetAndConstrainColumnHeight(logical_height_);
   }
 
+  // We may not have found our final height yet, but at least we've found a
+  // height.
+  is_logical_height_known_ = true;
+
   if (logical_height_ == old_column_height)
     return false;  // No change. We're done.
 
@@ -295,16 +301,15 @@
   // We must always return a value of 1 or greater. Column count = 0 is a
   // meaningless situation, and will confuse and cause problems in other parts
   // of the code.
-  LayoutUnit column_height = ColumnLogicalHeight();
-  if (!column_height)
+  if (!IsLogicalHeightKnown())
     return 1;
-
   // Our flow thread portion determines our column count. We have as many
   // columns as needed to fit all the content.
   LayoutUnit flow_thread_portion_height = LogicalHeightInFlowThread();
   if (!flow_thread_portion_height)
     return 1;
 
+  LayoutUnit column_height = ColumnLogicalHeight();
   unsigned count = (flow_thread_portion_height / column_height).Floor();
   // flowThreadPortionHeight may be saturated, so detect the remainder manually.
   if (count * column_height < flow_thread_portion_height)
@@ -315,11 +320,9 @@
 
 LayoutUnit MultiColumnFragmentainerGroup::HeightAdjustedForRowOffset(
     LayoutUnit height) const {
-  // Let's avoid zero height, as that would cause an infinite amount of columns
-  // to be created.
-  return std::max(
-      height - LogicalTop() - column_set_.LogicalTopFromMulticolContentEdge(),
-      LayoutUnit(1));
+  LayoutUnit adjusted_height =
+      height - LogicalTop() - column_set_.LogicalTopFromMulticolContentEdge();
+  return adjusted_height.ClampNegativeToZero();
 }
 
 LayoutUnit MultiColumnFragmentainerGroup::CalculateMaxColumnHeight() const {
@@ -500,9 +503,9 @@
   if (offset_in_flow_thread < logical_top_in_flow_thread_)
     return 0;
 
-  LayoutUnit column_height = ColumnLogicalHeight();
-  if (!column_height)
+  if (!IsLogicalHeightKnown())
     return 0;
+  LayoutUnit column_height = ColumnLogicalHeight();
   unsigned column_index =
       ((offset_in_flow_thread - logical_top_in_flow_thread_) / column_height)
           .Floor();
diff --git a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.h b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.h
index 31c7ad3..df3a481 100644
--- a/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.h
+++ b/third_party/WebKit/Source/core/layout/MultiColumnFragmentainerGroup.h
@@ -46,20 +46,25 @@
 
   // Return the amount of block space that this fragmentainer group takes up in
   // its containing LayoutMultiColumnSet.
-  LayoutUnit GroupLogicalHeight() const { return logical_height_; }
+  LayoutUnit GroupLogicalHeight() const {
+    DCHECK(IsLogicalHeightKnown());
+    return logical_height_;
+  }
 
   // Return the block size of a column (or fragmentainer) in this fragmentainer
   // group. The spec says that this value must always be >= 1px, to ensure
   // progress.
   LayoutUnit ColumnLogicalHeight() const {
-    // If the height hasn't been calculated yet, though, we allow returning 0
-    // (and the caller is then expected to refrain from attempting to fragment).
-    if (!logical_height_)
-      return logical_height_;
-
+    DCHECK(IsLogicalHeightKnown());
     return std::max(LayoutUnit(1), logical_height_);
   }
 
+  // Return whether we have some column height to work with. This doesn't have
+  // to be the final height. It will only return false in the first layout pass,
+  // and even then only if column height is auto and there's no way to even make
+  // a guess (i.e. when there are no usable constraints).
+  bool IsLogicalHeightKnown() const { return is_logical_height_known_; }
+
   LayoutSize OffsetFromColumnSet() const;
 
   // Return the block offset from the enclosing fragmentation context, if
@@ -191,6 +196,8 @@
 
   // Maximum logical height allowed.
   LayoutUnit max_logical_height_;
+
+  bool is_logical_height_known_ = false;
 };
 
 // List of all fragmentainer groups within a column set. There will always be at
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
index f194dc6..056b9a2 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImplTest.cpp
@@ -39,6 +39,14 @@
 #include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// The MediaTimelineWidths histogram suffix expected to be encountered in these
+// tests. Depends on the OS, since Android sizes its timeline differently.
+#if OS(ANDROID)
+#define TIMELINE_W "80_127"
+#else
+#define TIMELINE_W "128_255"
+#endif
+
 namespace blink {
 
 namespace {
@@ -618,13 +626,7 @@
       "Media.Timeline.Width.FullscreenPortrait", 0);
 }
 
-// TODO(johnme): Fix and re-enable this on Android.
-#if OS(ANDROID)
-#define MAYBE_TimelineMetricsClick DISABLED_TimelineMetricsClick
-#else
-#define MAYBE_TimelineMetricsClick TimelineMetricsClick
-#endif
-TEST_F(MediaControlsImplTest, MAYBE_TimelineMetricsClick) {
+TEST_F(MediaControlsImplTest, TimelineMetricsClick) {
   double duration = 540;  // 9 minutes
   LoadMediaWithDuration(duration);
   EnsureSizing();
@@ -645,27 +647,19 @@
   EXPECT_LE(0.49 * duration, MediaControls().MediaElement().currentTime());
   EXPECT_GE(0.51 * duration, MediaControls().MediaElement().currentTime());
 
-  GetHistogramTester().ExpectUniqueSample("Media.Timeline.SeekType.128_255",
+  GetHistogramTester().ExpectUniqueSample("Media.Timeline.SeekType." TIMELINE_W,
                                           0 /* SeekType::kClick */, 1);
   GetHistogramTester().ExpectTotalCount(
-      "Media.Timeline.DragGestureDuration.128_255", 0);
-  GetHistogramTester().ExpectTotalCount("Media.Timeline.DragPercent.128_255",
-                                        0);
+      "Media.Timeline.DragGestureDuration." TIMELINE_W, 0);
   GetHistogramTester().ExpectTotalCount(
-      "Media.Timeline.DragSumAbsTimeDelta.128_255", 0);
-  GetHistogramTester().ExpectTotalCount("Media.Timeline.DragTimeDelta.128_255",
-                                        0);
+      "Media.Timeline.DragPercent." TIMELINE_W, 0);
+  GetHistogramTester().ExpectTotalCount(
+      "Media.Timeline.DragSumAbsTimeDelta." TIMELINE_W, 0);
+  GetHistogramTester().ExpectTotalCount(
+      "Media.Timeline.DragTimeDelta." TIMELINE_W, 0);
 }
 
-// TODO(johnme): Fix and re-enable this on Android.
-#if OS(ANDROID)
-#define MAYBE_TimelineMetricsDragFromCurrentPosition \
-  DISABLED_TimelineMetricsDragFromCurrentPosition
-#else
-#define MAYBE_TimelineMetricsDragFromCurrentPosition \
-  TimelineMetricsDragFromCurrentPosition
-#endif
-TEST_F(MediaControlsImplTest, MAYBE_TimelineMetricsDragFromCurrentPosition) {
+TEST_F(MediaControlsImplTest, TimelineMetricsDragFromCurrentPosition) {
   double duration = 540;  // 9 minutes
   LoadMediaWithDuration(duration);
   EnsureSizing();
@@ -689,26 +683,19 @@
   EXPECT_GE(0.68 * duration, MediaControls().MediaElement().currentTime());
 
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.SeekType.128_255",
+      "Media.Timeline.SeekType." TIMELINE_W,
       1 /* SeekType::kDragFromCurrentPosition */, 1);
   GetHistogramTester().ExpectTotalCount(
-      "Media.Timeline.DragGestureDuration.128_255", 1);
-  GetHistogramTester().ExpectUniqueSample("Media.Timeline.DragPercent.128_255",
-                                          47 /* [60.0%, 70.0%) */, 1);
+      "Media.Timeline.DragGestureDuration." TIMELINE_W, 1);
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.DragSumAbsTimeDelta.128_255", 16 /* [4m, 8m) */, 1);
+      "Media.Timeline.DragPercent." TIMELINE_W, 47 /* [60.0%, 70.0%) */, 1);
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.DragTimeDelta.128_255", 40 /* [4m, 8m) */, 1);
+      "Media.Timeline.DragSumAbsTimeDelta." TIMELINE_W, 16 /* [4m, 8m) */, 1);
+  GetHistogramTester().ExpectUniqueSample(
+      "Media.Timeline.DragTimeDelta." TIMELINE_W, 40 /* [4m, 8m) */, 1);
 }
 
-// TODO(johnme): Fix and re-enable this on Android.
-#if OS(ANDROID)
-#define MAYBE_TimelineMetricsDragFromElsewhere \
-  DISABLED_TimelineMetricsDragFromElsewhere
-#else
-#define MAYBE_TimelineMetricsDragFromElsewhere TimelineMetricsDragFromElsewhere
-#endif
-TEST_F(MediaControlsImplTest, MAYBE_TimelineMetricsDragFromElsewhere) {
+TEST_F(MediaControlsImplTest, TimelineMetricsDragFromElsewhere) {
   double duration = 540;  // 9 minutes
   LoadMediaWithDuration(duration);
   EnsureSizing();
@@ -732,27 +719,20 @@
   EXPECT_LE(0.66 * duration, MediaControls().MediaElement().currentTime());
   EXPECT_GE(0.68 * duration, MediaControls().MediaElement().currentTime());
 
-  GetHistogramTester().ExpectUniqueSample("Media.Timeline.SeekType.128_255",
+  GetHistogramTester().ExpectUniqueSample("Media.Timeline.SeekType." TIMELINE_W,
                                           2 /* SeekType::kDragFromElsewhere */,
                                           1);
   GetHistogramTester().ExpectTotalCount(
-      "Media.Timeline.DragGestureDuration.128_255", 1);
-  GetHistogramTester().ExpectUniqueSample("Media.Timeline.DragPercent.128_255",
-                                          42 /* [30.0%, 35.0%) */, 1);
+      "Media.Timeline.DragGestureDuration." TIMELINE_W, 1);
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.DragSumAbsTimeDelta.128_255", 15 /* [2m, 4m) */, 1);
+      "Media.Timeline.DragPercent." TIMELINE_W, 42 /* [30.0%, 35.0%) */, 1);
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.DragTimeDelta.128_255", 39 /* [2m, 4m) */, 1);
+      "Media.Timeline.DragSumAbsTimeDelta." TIMELINE_W, 15 /* [2m, 4m) */, 1);
+  GetHistogramTester().ExpectUniqueSample(
+      "Media.Timeline.DragTimeDelta." TIMELINE_W, 39 /* [2m, 4m) */, 1);
 }
 
-// TODO(johnme): Fix and re-enable this on Android.
-#if OS(ANDROID)
-#define MAYBE_TimelineMetricsDragBackAndForth \
-  DISABLED_TimelineMetricsDragBackAndForth
-#else
-#define MAYBE_TimelineMetricsDragBackAndForth TimelineMetricsDragBackAndForth
-#endif
-TEST_F(MediaControlsImplTest, MAYBE_TimelineMetricsDragBackAndForth) {
+TEST_F(MediaControlsImplTest, TimelineMetricsDragBackAndForth) {
   double duration = 540;  // 9 minutes
   LoadMediaWithDuration(duration);
   EnsureSizing();
@@ -778,17 +758,17 @@
   EXPECT_LE(0.32 * duration, MediaControls().MediaElement().currentTime());
   EXPECT_GE(0.34 * duration, MediaControls().MediaElement().currentTime());
 
-  GetHistogramTester().ExpectUniqueSample("Media.Timeline.SeekType.128_255",
+  GetHistogramTester().ExpectUniqueSample("Media.Timeline.SeekType." TIMELINE_W,
                                           2 /* SeekType::kDragFromElsewhere */,
                                           1);
   GetHistogramTester().ExpectTotalCount(
-      "Media.Timeline.DragGestureDuration.128_255", 1);
-  GetHistogramTester().ExpectUniqueSample("Media.Timeline.DragPercent.128_255",
-                                          8 /* (-35.0%, -30.0%] */, 1);
+      "Media.Timeline.DragGestureDuration." TIMELINE_W, 1);
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.DragSumAbsTimeDelta.128_255", 17 /* [8m, 15m) */, 1);
+      "Media.Timeline.DragPercent." TIMELINE_W, 8 /* (-35.0%, -30.0%] */, 1);
   GetHistogramTester().ExpectUniqueSample(
-      "Media.Timeline.DragTimeDelta.128_255", 9 /* (-4m, -2m] */, 1);
+      "Media.Timeline.DragSumAbsTimeDelta." TIMELINE_W, 17 /* [8m, 15m) */, 1);
+  GetHistogramTester().ExpectUniqueSample(
+      "Media.Timeline.DragTimeDelta." TIMELINE_W, 9 /* (-4m, -2m] */, 1);
 }
 
 namespace {
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationAvailability.cpp b/third_party/WebKit/Source/modules/presentation/PresentationAvailability.cpp
index a6be63d..797d0fe 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationAvailability.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationAvailability.cpp
@@ -16,22 +16,6 @@
 
 namespace blink {
 
-namespace {
-
-WebPresentationClient* PresentationClient(ExecutionContext* execution_context) {
-  if (!execution_context)
-    return nullptr;
-  DCHECK(execution_context->IsDocument());
-  Document* document = ToDocument(execution_context);
-  if (!document->GetFrame())
-    return nullptr;
-  PresentationController* controller =
-      PresentationController::From(*document->GetFrame());
-  return controller ? controller->Client() : nullptr;
-}
-
-}  // anonymous namespace
-
 // static
 PresentationAvailability* PresentationAvailability::Take(
     PresentationAvailabilityProperty* resolver,
@@ -118,7 +102,8 @@
 }
 
 void PresentationAvailability::UpdateListening() {
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (!client)
     return;
 
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
index aff5037..cd5962ba 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
@@ -32,19 +32,6 @@
 
 namespace {
 
-// TODO(mlamouri): refactor in one common place.
-WebPresentationClient* PresentationClient(ExecutionContext* execution_context) {
-  DCHECK(execution_context);
-  DCHECK(execution_context->IsDocument());
-
-  Document* document = ToDocument(execution_context);
-  if (!document->GetFrame())
-    return nullptr;
-  PresentationController* controller =
-      PresentationController::From(*document->GetFrame());
-  return controller ? controller->Client() : nullptr;
-}
-
 const AtomicString& ConnectionStateToString(
     WebPresentationConnectionState state) {
   DEFINE_STATIC_LOCAL(const AtomicString, connecting_value, ("connecting"));
@@ -311,11 +298,12 @@
   }
 
   // The connection can send a message if there is a client available.
-  return !!PresentationClient(GetExecutionContext());
+  return !!PresentationController::ClientFromContext(GetExecutionContext());
 }
 
 void PresentationConnection::HandleMessageQueue() {
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (!client || !proxy_)
     return;
 
@@ -402,7 +390,8 @@
       state_ != WebPresentationConnectionState::kConnected) {
     return;
   }
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (client)
     client->CloseConnection(url_, id_, proxy_.get());
 
@@ -412,7 +401,8 @@
 void PresentationConnection::terminate() {
   if (state_ != WebPresentationConnectionState::kConnected)
     return;
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (client)
     client->TerminatePresentation(url_, id_);
 
@@ -491,7 +481,8 @@
   DCHECK(buffer);
   DCHECK(buffer->Buffer());
   // Send the loaded blob immediately here and continue processing the queue.
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (client) {
     client->SendBlobData(url_, id_, static_cast<const uint8_t*>(buffer->Data()),
                          buffer->ByteLength(), proxy_.get());
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
index 20e8a6f..c689f1f9 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
@@ -59,6 +59,28 @@
   return client_;
 }
 
+// static
+PresentationController* PresentationController::FromContext(
+    ExecutionContext* execution_context) {
+  if (!execution_context)
+    return nullptr;
+
+  DCHECK(execution_context->IsDocument());
+  Document* document = ToDocument(execution_context);
+  if (!document->GetFrame())
+    return nullptr;
+
+  return PresentationController::From(*document->GetFrame());
+}
+
+// static
+WebPresentationClient* PresentationController::ClientFromContext(
+    ExecutionContext* execution_context) {
+  PresentationController* controller =
+      PresentationController::FromContext(execution_context);
+  return controller ? controller->Client() : nullptr;
+}
+
 DEFINE_TRACE(PresentationController) {
   visitor->Trace(presentation_);
   visitor->Trace(connections_);
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.h b/third_party/WebKit/Source/modules/presentation/PresentationController.h
index 99e3268..69cebf5f 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationController.h
+++ b/third_party/WebKit/Source/modules/presentation/PresentationController.h
@@ -40,6 +40,8 @@
   static void ProvideTo(LocalFrame&, WebPresentationClient*);
 
   WebPresentationClient* Client();
+  static WebPresentationClient* ClientFromContext(ExecutionContext*);
+  static PresentationController* FromContext(ExecutionContext*);
 
   // Implementation of Supplement.
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp
index 155bee0c..6b7ee90 100644
--- a/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp
+++ b/third_party/WebKit/Source/modules/presentation/PresentationRequest.cpp
@@ -28,23 +28,6 @@
 
 namespace {
 
-// TODO(mlamouri): refactor in one common place.
-PresentationController* GetPresentationController(
-    ExecutionContext* execution_context) {
-  DCHECK(execution_context);
-
-  Document* document = ToDocument(execution_context);
-  if (!document->GetFrame())
-    return nullptr;
-  return PresentationController::From(*document->GetFrame());
-}
-
-WebPresentationClient* PresentationClient(ExecutionContext* execution_context) {
-  PresentationController* controller =
-      GetPresentationController(execution_context);
-  return controller ? controller->Client() : nullptr;
-}
-
 Settings* GetSettings(ExecutionContext* execution_context) {
   DCHECK(execution_context);
 
@@ -143,7 +126,8 @@
             kInvalidAccessError,
             "PresentationRequest::start() requires user gesture."));
 
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (!client)
     return ScriptPromise::RejectWithDOMException(
         script_state,
@@ -159,7 +143,8 @@
 
 ScriptPromise PresentationRequest::reconnect(ScriptState* script_state,
                                              const String& id) {
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (!client)
     return ScriptPromise::RejectWithDOMException(
         script_state,
@@ -170,7 +155,7 @@
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
 
   PresentationController* controller =
-      GetPresentationController(GetExecutionContext());
+      PresentationController::FromContext(GetExecutionContext());
   DCHECK(controller);
 
   PresentationConnection* existing_connection =
@@ -189,7 +174,8 @@
 }
 
 ScriptPromise PresentationRequest::getAvailability(ScriptState* script_state) {
-  WebPresentationClient* client = PresentationClient(GetExecutionContext());
+  WebPresentationClient* client =
+      PresentationController::ClientFromContext(GetExecutionContext());
   if (!client)
     return ScriptPromise::RejectWithDOMException(
         script_state,
diff --git a/third_party/WebKit/Source/modules/webusb/NavigatorUSB.idl b/third_party/WebKit/Source/modules/webusb/NavigatorUSB.idl
index 746d02b..344441a 100644
--- a/third_party/WebKit/Source/modules/webusb/NavigatorUSB.idl
+++ b/third_party/WebKit/Source/modules/webusb/NavigatorUSB.idl
@@ -5,5 +5,5 @@
 // https://wicg.github.io/webusb/#enumeration
 
 partial interface Navigator {
-    [SecureContext, OriginTrialEnabled=WebUSB] readonly attribute USB usb;
+    [SecureContext, RuntimeEnabled=WebUSB] readonly attribute USB usb;
 };
diff --git a/third_party/WebKit/Source/modules/webusb/USB.idl b/third_party/WebKit/Source/modules/webusb/USB.idl
index 6f26238..1c7a34f 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.idl
+++ b/third_party/WebKit/Source/modules/webusb/USB.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usb
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USB : EventTarget {
     attribute EventHandler onconnect;
     attribute EventHandler ondisconnect;
diff --git a/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.idl b/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.idl
index 2943668..61a79baf 100644
--- a/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBAlternateInterface.idl
@@ -7,7 +7,7 @@
 [
     Constructor(USBInterface deviceInterface, octet alternateSetting),
     RaisesException=Constructor,
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USBAlternateInterface {
     readonly attribute octet alternateSetting;
     readonly attribute octet interfaceClass;
diff --git a/third_party/WebKit/Source/modules/webusb/USBConfiguration.idl b/third_party/WebKit/Source/modules/webusb/USBConfiguration.idl
index 09b75bf7..0fe7083 100644
--- a/third_party/WebKit/Source/modules/webusb/USBConfiguration.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBConfiguration.idl
@@ -7,7 +7,7 @@
 [
     Constructor(USBDevice device, octet configurationValue),
     RaisesException=Constructor,
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USBConfiguration {
     readonly attribute octet configurationValue;
     readonly attribute DOMString? configurationName;
diff --git a/third_party/WebKit/Source/modules/webusb/USBConnectionEvent.idl b/third_party/WebKit/Source/modules/webusb/USBConnectionEvent.idl
index e1a301ad..cbc9f81796 100644
--- a/third_party/WebKit/Source/modules/webusb/USBConnectionEvent.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBConnectionEvent.idl
@@ -6,7 +6,7 @@
 
 [
     Constructor(DOMString type, USBConnectionEventInit eventInitDict),
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USBConnectionEvent : Event {
     [SameObject] readonly attribute USBDevice device;
 };
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.idl b/third_party/WebKit/Source/modules/webusb/USBDevice.idl
index 70db97c..4d5dbe8c 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.idl
@@ -13,7 +13,7 @@
 // https://wicg.github.io/webusb/#device-usage
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USBDevice {
     readonly attribute octet usbVersionMajor;
     readonly attribute octet usbVersionMinor;
diff --git a/third_party/WebKit/Source/modules/webusb/USBEndpoint.idl b/third_party/WebKit/Source/modules/webusb/USBEndpoint.idl
index 12f7b3df..d991059 100644
--- a/third_party/WebKit/Source/modules/webusb/USBEndpoint.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBEndpoint.idl
@@ -18,7 +18,7 @@
 [
     Constructor(USBAlternateInterface alternate, octet endpointNumber, USBDirection direction),
     RaisesException=Constructor,
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USBEndpoint {
     readonly attribute octet endpointNumber;
     readonly attribute USBDirection direction;
diff --git a/third_party/WebKit/Source/modules/webusb/USBInTransferResult.idl b/third_party/WebKit/Source/modules/webusb/USBInTransferResult.idl
index 60c6965..e8b950b 100644
--- a/third_party/WebKit/Source/modules/webusb/USBInTransferResult.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBInTransferResult.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usbintransferresult
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
     Constructor(USBTransferStatus status, optional DataView? data)
 ] interface USBInTransferResult {
     readonly attribute DataView? data;
diff --git a/third_party/WebKit/Source/modules/webusb/USBInterface.idl b/third_party/WebKit/Source/modules/webusb/USBInterface.idl
index 4771689..5bce5290 100644
--- a/third_party/WebKit/Source/modules/webusb/USBInterface.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBInterface.idl
@@ -7,7 +7,7 @@
 [
     Constructor(USBConfiguration configuration, octet interfaceNumber),
     RaisesException=Constructor,
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
 ] interface USBInterface {
     readonly attribute octet interfaceNumber;
     readonly attribute USBAlternateInterface? alternate;
diff --git a/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferPacket.idl b/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferPacket.idl
index e483f689..7bca63a 100644
--- a/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferPacket.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferPacket.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usbisochronousintransferpacket
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
     Constructor(USBTransferStatus status, optional DataView? data)
 ] interface USBIsochronousInTransferPacket {
     readonly attribute USBTransferStatus status;
diff --git a/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferResult.idl b/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferResult.idl
index ba42758b..e0120ee 100644
--- a/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferResult.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBIsochronousInTransferResult.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usbisochronousintransferresult
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
     Constructor(sequence<USBIsochronousInTransferPacket> packets,
                 optional DataView? data)
 ] interface USBIsochronousInTransferResult {
diff --git a/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferPacket.idl b/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferPacket.idl
index 90e11269..5c9da5f 100644
--- a/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferPacket.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferPacket.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usbisochronousouttransferpacket
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
     Constructor(USBTransferStatus status, optional unsigned long bytesWritten = 0)
 ] interface USBIsochronousOutTransferPacket {
     readonly attribute unsigned long bytesWritten;
diff --git a/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferResult.idl b/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferResult.idl
index fa77891..2acee95 100644
--- a/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferResult.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBIsochronousOutTransferResult.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usbisochronousouttransferresult
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
     Constructor(sequence<USBIsochronousOutTransferPacket> packets)
 ] interface USBIsochronousOutTransferResult {
     readonly attribute FrozenArray<USBIsochronousOutTransferPacket> packets;
diff --git a/third_party/WebKit/Source/modules/webusb/USBOutTransferResult.idl b/third_party/WebKit/Source/modules/webusb/USBOutTransferResult.idl
index 20d95a8..52caf05 100644
--- a/third_party/WebKit/Source/modules/webusb/USBOutTransferResult.idl
+++ b/third_party/WebKit/Source/modules/webusb/USBOutTransferResult.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/webusb/#usbouttransferresult
 
 [
-    OriginTrialEnabled=WebUSB,
+    RuntimeEnabled=WebUSB,
     Constructor(USBTransferStatus status, optional unsigned long bytesWritten = 0)
 ] interface USBOutTransferResult {
     readonly attribute unsigned long bytesWritten;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 407f3408..c9513942 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -1078,8 +1078,7 @@
     },
     {
       name: "WebUSB",
-      origin_trial_feature_name: "WebUSB2",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "WebVR",
diff --git a/third_party/WebKit/Source/platform/WebMouseEvent.cpp b/third_party/WebKit/Source/platform/WebMouseEvent.cpp
index 1460576..2823b7a7 100644
--- a/third_party/WebKit/Source/platform/WebMouseEvent.cpp
+++ b/third_party/WebKit/Source/platform/WebMouseEvent.cpp
@@ -17,11 +17,11 @@
                              PointerId id_param)
     : WebInputEvent(sizeof(WebMouseEvent), type, modifiers, time_stamp_seconds),
       WebPointerProperties(id_param,
-                           button_param,
-                           WebPointerProperties::PointerType::kMouse),
-      click_count(click_count_param),
-      position_in_widget_(gesture_event.x, gesture_event.y),
-      position_in_screen_(gesture_event.global_x, gesture_event.global_y) {
+                           WebPointerProperties::PointerType::kMouse,
+                           button_param),
+      click_count(click_count_param) {
+  SetPositionInWidget(gesture_event.x, gesture_event.y);
+  SetPositionInScreen(gesture_event.global_x, gesture_event.global_y);
   SetFrameScale(gesture_event.FrameScale());
   SetFrameTranslate(gesture_event.FrameTranslate());
 }
diff --git a/third_party/WebKit/Source/platform/WebTouchEvent.cpp b/third_party/WebKit/Source/platform/WebTouchEvent.cpp
index ab709f3..edc1c14c 100644
--- a/third_party/WebKit/Source/platform/WebTouchEvent.cpp
+++ b/third_party/WebKit/Source/platform/WebTouchEvent.cpp
@@ -28,10 +28,11 @@
   transformed_point.radius_y /= frame_scale_;
   transformed_point.movement_x /= frame_scale_;
   transformed_point.movement_y /= frame_scale_;
-  transformed_point.position.x =
-      (transformed_point.position.x / frame_scale_) + frame_translate_.x;
-  transformed_point.position.y =
-      (transformed_point.position.y / frame_scale_) + frame_translate_.y;
+  transformed_point.SetPositionInWidget(
+      (transformed_point.PositionInWidget().x / frame_scale_) +
+          frame_translate_.x,
+      (transformed_point.PositionInWidget().y / frame_scale_) +
+          frame_translate_.y);
   return transformed_point;
 }
 
diff --git a/third_party/WebKit/Source/platform/wtf/StdLibExtras.h b/third_party/WebKit/Source/platform/wtf/StdLibExtras.h
index 2232e78..1cf4967 100644
--- a/third_party/WebKit/Source/platform/wtf/StdLibExtras.h
+++ b/third_party/WebKit/Source/platform/wtf/StdLibExtras.h
@@ -27,6 +27,7 @@
 #define WTF_StdLibExtras_h
 
 #include <cstddef>
+#include "base/memory/aligned_memory.h"
 #include "base/numerics/safe_conversions.h"
 #include "platform/wtf/Assertions.h"
 #include "platform/wtf/CPU.h"
@@ -38,6 +39,14 @@
 #include "platform/wtf/Threading.h"
 #endif
 
+#define DEFINE_STATIC_LOCAL_IMPL(Type, Name, Arguments, allow_cross_thread)    \
+  static WTF::StaticSingleton<Type> s_##Name(                                  \
+      [&]() { return new WTF::StaticSingleton<Type>::WrapperType Arguments; }, \
+      [&](void* leaked_ptr) {                                                  \
+        new (leaked_ptr) WTF::StaticSingleton<Type>::WrapperType Arguments;    \
+      });                                                                      \
+  Type& Name = s_##Name.Get(allow_cross_thread)
+
 // Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable
 // (|static T;|) so that it is leaked and its destructors are not called at
 // exit. T may also be a Blink garbage collected object, in which case it is
@@ -47,10 +56,8 @@
 // A |DEFINE_STATIC_LOCAL()| static should only be used on the thread it was
 // created on.
 //
-#define DEFINE_STATIC_LOCAL(Type, Name, Arguments)            \
-  static WTF::StaticSingleton<Type> s_##Name(                 \
-      new WTF::StaticSingleton<Type>::WrapperType Arguments); \
-  Type& Name = s_##Name.Get(false)
+#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
+  DEFINE_STATIC_LOCAL_IMPL(Type, Name, Arguments, false)
 
 // |DEFINE_THREAD_SAFE_STATIC_LOCAL()| is the cross-thread accessible variant
 // of |DEFINE_STATIC_LOCAL()|; use it if the singleton can be accessed by
@@ -58,9 +65,7 @@
 //
 // TODO: rename as DEFINE_CROSS_THREAD_STATIC_LOCAL() ?
 #define DEFINE_THREAD_SAFE_STATIC_LOCAL(Type, Name, Arguments) \
-  static WTF::StaticSingleton<Type> s_##Name(                  \
-      new WTF::StaticSingleton<Type>::WrapperType Arguments);  \
-  Type& Name = s_##Name.Get(true)
+  DEFINE_STATIC_LOCAL_IMPL(Type, Name, Arguments, true)
 
 namespace blink {
 template <typename T>
@@ -108,22 +113,24 @@
   // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
   // details.
 
-  explicit StaticSingleton(WrapperType* instance)
-      : instance_(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance))
+  template <typename HeapNew, typename PlacementNew>
+  StaticSingleton(const HeapNew& heap_new, const PlacementNew& placement_new)
+      : instance_(heap_new, placement_new)
 #if DCHECK_IS_ON()
         ,
         safely_initialized_(WTF::IsBeforeThreadCreated()),
         thread_(WTF::internal::CurrentThreadSyscall())
 #endif
   {
+    LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance_.Get());
   }
 
-  Type& Get(bool allow_cross_thread_use) const {
+  Type& Get(bool allow_cross_thread_use) {
 #if DCHECK_IS_ON()
     DCHECK(IsNotRacy(allow_cross_thread_use));
 #endif
     ALLOW_UNUSED_LOCAL(allow_cross_thread_use);
-    return Wrapper<Type>::Unwrap(instance_);
+    return Wrapper<Type>::Unwrap(instance_.Get());
   }
 
   operator Type&() { return Get(); }
@@ -139,8 +146,32 @@
            thread_ == WTF::internal::CurrentThreadSyscall();
   }
 #endif
+  template <typename T, bool is_small = sizeof(T) <= 32>
+  class InstanceStorage {
+   public:
+    template <typename HeapNew, typename PlacementNew>
+    InstanceStorage(const HeapNew& heap_new, const PlacementNew&)
+        : pointer_(heap_new()) {}
+    T* Get() { return pointer_; }
 
-  WrapperType* instance_;
+   private:
+    T* pointer_;
+  };
+
+  template <typename T>
+  class InstanceStorage<T, true> {
+   public:
+    template <typename HeapNew, typename PlacementNew>
+    InstanceStorage(const HeapNew&, const PlacementNew& placement_new) {
+      placement_new(object_.void_data());
+    }
+    T* Get() { return object_.template data_as<T>(); }
+
+   private:
+    base::AlignedMemory<sizeof(T), ALIGNOF(T)> object_;
+  };
+
+  InstanceStorage<WrapperType> instance_;
 #if DCHECK_IS_ON()
   bool safely_initialized_;
   ThreadIdentifier thread_;
diff --git a/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp b/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp
index 2b0d46e..79bb19d 100644
--- a/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp
+++ b/third_party/WebKit/Source/web/InspectorOverlayAgent.cpp
@@ -125,8 +125,9 @@
   if (!event.touches_length)
     return nullptr;
   WebTouchPoint transformed_point = event.TouchPointInRootFrame(0);
-  return HoveredNodeForPoint(frame, RoundedIntPoint(transformed_point.position),
-                             ignore_pointer_events_none);
+  return HoveredNodeForPoint(
+      frame, RoundedIntPoint(transformed_point.PositionInWidget()),
+      ignore_pointer_events_none);
 }
 
 bool ParseQuad(std::unique_ptr<protocol::Array<double>> quad_array,
diff --git a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp
index 0826300..f39385d 100644
--- a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp
@@ -849,7 +849,8 @@
   WebTouchEvent transformed_event = touch_event->FlattenTransform();
 
   for (unsigned i = 0; i < transformed_event.touches_length; ++i) {
-    WebFloatPoint absolute_location = transformed_event.touches[i].position;
+    WebFloatPoint absolute_location =
+        transformed_event.touches[i].PositionInWidget();
 
     // Translate the root frame position to content coordinates.
     if (LocalFrameView* parent = ParentFrameView())
@@ -858,8 +859,8 @@
     IntPoint local_point =
         RoundedIntPoint(element_->GetLayoutObject()->AbsoluteToLocal(
             absolute_location, kUseTransforms));
-    transformed_event.touches[i].position.x = local_point.X();
-    transformed_event.touches[i].position.y = local_point.Y();
+    transformed_event.touches[i].SetPositionInWidget(local_point.X(),
+                                                     local_point.Y());
   }
   return transformed_event;
 }
diff --git a/third_party/WebKit/Source/web/tests/TouchActionTest.cpp b/third_party/WebKit/Source/web/tests/TouchActionTest.cpp
index ff4e4892..a1b2c8d 100644
--- a/third_party/WebKit/Source/web/tests/TouchActionTest.cpp
+++ b/third_party/WebKit/Source/web/tests/TouchActionTest.cpp
@@ -391,10 +391,10 @@
       (type == WebInputEvent::kTouchStart ? WebTouchPoint::kStatePressed
                                           : WebTouchPoint::kStateCancelled);
   web_touch_event.touches[0].id = kKfakeTouchId;
-  web_touch_event.touches[0].screen_position.x = client_point.X();
-  web_touch_event.touches[0].screen_position.y = client_point.Y();
-  web_touch_event.touches[0].position.x = client_point.X();
-  web_touch_event.touches[0].position.y = client_point.Y();
+  web_touch_event.touches[0].SetPositionInScreen(client_point.X(),
+                                                 client_point.Y());
+  web_touch_event.touches[0].SetPositionInWidget(client_point.X(),
+                                                 client_point.Y());
   web_touch_event.touches[0].radius_x = 10;
   web_touch_event.touches[0].radius_y = 10;
   web_touch_event.touches[0].force = 1.0;
diff --git a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
index 626cf24..6f0a7e3 100644
--- a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
@@ -309,19 +309,17 @@
                                   WebInputEvent::kTimeStampForTesting);
     web_touch_event.touches_length = 1;
     web_touch_event.touches[0].state = WebTouchPoint::kStateMoved;
-    web_touch_event.touches[0].screen_position.x = 10.6f;
-    web_touch_event.touches[0].screen_position.y = 10.4f;
-    web_touch_event.touches[0].position.x = 10.6f;
-    web_touch_event.touches[0].position.y = 10.4f;
+    web_touch_event.touches[0].SetPositionInScreen(10.6f, 10.4f);
+    web_touch_event.touches[0].SetPositionInWidget(10.6f, 10.4f);
     web_touch_event.touches[0].radius_x = 10.6f;
     web_touch_event.touches[0].radius_y = 10.4f;
     web_touch_event.touches[0].movement_x = 20;
     web_touch_event.touches[0].movement_y = 20;
 
-    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].screen_position.x);
-    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].screen_position.y);
-    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].position.x);
-    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].position.y);
+    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].PositionInScreen().x);
+    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].PositionInScreen().y);
+    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].PositionInWidget().x);
+    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].PositionInWidget().y);
     EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].radius_x);
     EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].radius_y);
     EXPECT_EQ(20, web_touch_event.touches[0].movement_x);
@@ -331,10 +329,10 @@
         TransformWebTouchEvent(view, web_touch_event);
     WebTouchPoint transformed_point =
         transformed_event.TouchPointInRootFrame(0);
-    EXPECT_FLOAT_EQ(10.6f, transformed_point.screen_position.x);
-    EXPECT_FLOAT_EQ(10.4f, transformed_point.screen_position.y);
-    EXPECT_FLOAT_EQ(5.3f, transformed_point.position.x);
-    EXPECT_FLOAT_EQ(5.2f, transformed_point.position.y);
+    EXPECT_FLOAT_EQ(10.6f, transformed_point.PositionInScreen().x);
+    EXPECT_FLOAT_EQ(10.4f, transformed_point.PositionInScreen().y);
+    EXPECT_FLOAT_EQ(5.3f, transformed_point.PositionInWidget().x);
+    EXPECT_FLOAT_EQ(5.2f, transformed_point.PositionInWidget().y);
     EXPECT_FLOAT_EQ(5.3f, transformed_point.radius_x);
     EXPECT_FLOAT_EQ(5.2f, transformed_point.radius_y);
     EXPECT_EQ(10, transformed_point.movement_x);
@@ -552,10 +550,8 @@
                                   WebInputEvent::kTimeStampForTesting);
     web_touch_event.touches_length = 1;
     web_touch_event.touches[0].state = WebTouchPoint::kStateMoved;
-    web_touch_event.touches[0].screen_position.x = 100;
-    web_touch_event.touches[0].screen_position.y = 110;
-    web_touch_event.touches[0].position.x = 100;
-    web_touch_event.touches[0].position.y = 110;
+    web_touch_event.touches[0].SetPositionInScreen(100, 110);
+    web_touch_event.touches[0].SetPositionInWidget(100, 110);
     web_touch_event.touches[0].radius_x = 30;
     web_touch_event.touches[0].radius_y = 30;
 
@@ -564,10 +560,10 @@
 
     WebTouchPoint transformed_point =
         transformed_event.TouchPointInRootFrame(0);
-    EXPECT_FLOAT_EQ(100, transformed_point.screen_position.x);
-    EXPECT_FLOAT_EQ(110, transformed_point.screen_position.y);
-    EXPECT_FLOAT_EQ(30, transformed_point.position.x);
-    EXPECT_FLOAT_EQ(30, transformed_point.position.y);
+    EXPECT_FLOAT_EQ(100, transformed_point.PositionInScreen().x);
+    EXPECT_FLOAT_EQ(110, transformed_point.PositionInScreen().y);
+    EXPECT_FLOAT_EQ(30, transformed_point.PositionInWidget().x);
+    EXPECT_FLOAT_EQ(30, transformed_point.PositionInWidget().y);
     EXPECT_FLOAT_EQ(10, transformed_point.radius_x);
     EXPECT_FLOAT_EQ(10, transformed_point.radius_y);
   }
@@ -578,16 +574,14 @@
                                    WebInputEvent::kTimeStampForTesting);
     web_touch_event1.touches_length = 1;
     web_touch_event1.touches[0].state = WebTouchPoint::kStateMoved;
-    web_touch_event1.touches[0].screen_position.x = 100;
-    web_touch_event1.touches[0].screen_position.y = 110;
-    web_touch_event1.touches[0].position.x = 100;
-    web_touch_event1.touches[0].position.y = 110;
+    web_touch_event1.touches[0].SetPositionInScreen(100, 110);
+    web_touch_event1.touches[0].SetPositionInWidget(100, 110);
     web_touch_event1.touches[0].radius_x = 30;
     web_touch_event1.touches[0].radius_y = 30;
 
     WebTouchEvent web_touch_event2 = web_touch_event1;
-    web_touch_event2.touches[0].screen_position.x = 130;
-    web_touch_event2.touches[0].position.x = 130;
+    web_touch_event2.touches[0].SetPositionInScreen(130, 110);
+    web_touch_event2.touches[0].SetPositionInWidget(130, 110);
     web_touch_event2.touches[0].radius_x = 60;
 
     std::vector<const WebInputEvent*> events;
@@ -600,18 +594,18 @@
 
     WebTouchPoint transformed_point =
         coalescedevents[0].TouchPointInRootFrame(0);
-    EXPECT_FLOAT_EQ(100, transformed_point.screen_position.x);
-    EXPECT_FLOAT_EQ(110, transformed_point.screen_position.y);
-    EXPECT_FLOAT_EQ(30, transformed_point.position.x);
-    EXPECT_FLOAT_EQ(30, transformed_point.position.y);
+    EXPECT_FLOAT_EQ(100, transformed_point.PositionInScreen().x);
+    EXPECT_FLOAT_EQ(110, transformed_point.PositionInScreen().y);
+    EXPECT_FLOAT_EQ(30, transformed_point.PositionInWidget().x);
+    EXPECT_FLOAT_EQ(30, transformed_point.PositionInWidget().y);
     EXPECT_FLOAT_EQ(10, transformed_point.radius_x);
     EXPECT_FLOAT_EQ(10, transformed_point.radius_y);
 
     transformed_point = coalescedevents[1].TouchPointInRootFrame(0);
-    EXPECT_FLOAT_EQ(130, transformed_point.screen_position.x);
-    EXPECT_FLOAT_EQ(110, transformed_point.screen_position.y);
-    EXPECT_FLOAT_EQ(40, transformed_point.position.x);
-    EXPECT_FLOAT_EQ(30, transformed_point.position.y);
+    EXPECT_FLOAT_EQ(130, transformed_point.PositionInScreen().x);
+    EXPECT_FLOAT_EQ(110, transformed_point.PositionInScreen().y);
+    EXPECT_FLOAT_EQ(40, transformed_point.PositionInWidget().x);
+    EXPECT_FLOAT_EQ(30, transformed_point.PositionInWidget().y);
     EXPECT_FLOAT_EQ(20, transformed_point.radius_x);
     EXPECT_FLOAT_EQ(10, transformed_point.radius_y);
   }
@@ -736,24 +730,24 @@
                                   WebInputEvent::kTimeStampForTesting);
     web_touch_event.touches_length = 1;
     web_touch_event.touches[0].state = WebTouchPoint::kStateMoved;
-    web_touch_event.touches[0].screen_position.x = 10.6f;
-    web_touch_event.touches[0].screen_position.y = 10.4f;
-    web_touch_event.touches[0].position.x = 10.6f;
-    web_touch_event.touches[0].position.y = 10.4f;
+    web_touch_event.touches[0].SetPositionInScreen(10.6f, 10.4f);
+    web_touch_event.touches[0].SetPositionInWidget(10.6f, 10.4f);
 
-    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].screen_position.x);
-    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].screen_position.y);
-    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].position.x);
-    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].position.y);
+    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].PositionInScreen().x);
+    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].PositionInScreen().y);
+    EXPECT_FLOAT_EQ(10.6f, web_touch_event.touches[0].PositionInWidget().x);
+    EXPECT_FLOAT_EQ(10.4f, web_touch_event.touches[0].PositionInWidget().y);
 
     WebTouchEvent transformed_touch_event =
         TransformWebTouchEvent(view, web_touch_event);
     WebTouchPoint transformed_point =
         transformed_touch_event.TouchPointInRootFrame(0);
-    EXPECT_FLOAT_EQ(10.6f, transformed_point.screen_position.x);
-    EXPECT_FLOAT_EQ(10.4f, transformed_point.screen_position.y);
-    EXPECT_FLOAT_EQ(5.3f + visual_offset.X(), transformed_point.position.x);
-    EXPECT_FLOAT_EQ(5.2f + visual_offset.Y(), transformed_point.position.y);
+    EXPECT_FLOAT_EQ(10.6f, transformed_point.PositionInScreen().x);
+    EXPECT_FLOAT_EQ(10.4f, transformed_point.PositionInScreen().y);
+    EXPECT_FLOAT_EQ(5.3f + visual_offset.X(),
+                    transformed_point.PositionInWidget().x);
+    EXPECT_FLOAT_EQ(5.2f + visual_offset.Y(),
+                    transformed_point.PositionInWidget().y);
   }
 }
 
diff --git a/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp b/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp
index 8f20518..b93512a 100644
--- a/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp
@@ -467,8 +467,9 @@
       const WebTouchEvent& touch_event =
           static_cast<const WebTouchEvent&>(event);
       if (touch_event.touches_length == 1) {
-        last_event_location_ = IntPoint(touch_event.touches[0].position.x,
-                                        touch_event.touches[0].position.y);
+        last_event_location_ =
+            IntPoint(touch_event.touches[0].PositionInWidget().x,
+                     touch_event.touches[0].PositionInWidget().y);
       } else {
         last_event_location_ = IntPoint();
       }
@@ -606,8 +607,8 @@
   event.touches_length = 1;
   WebRect rect = plugin_container_one_element.BoundsInViewport();
   event.touches[0].state = WebTouchPoint::kStatePressed;
-  event.touches[0].position =
-      WebFloatPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+  event.touches[0].SetPositionInWidget(rect.x + rect.width / 2,
+                                       rect.y + rect.height / 2);
 
   web_view->HandleInputEvent(WebCoalescedInputEvent(event));
   RunPendingTasks();
@@ -648,8 +649,8 @@
   WebRect rect = plugin_container_one_element.BoundsInViewport();
   event.touches_length = 1;
   event.touches[0].state = WebTouchPoint::kStatePressed;
-  event.touches[0].position =
-      WebFloatPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+  event.touches[0].SetPositionInWidget(rect.x + rect.width / 2,
+                                       rect.y + rect.height / 2);
 
   WebCoalescedInputEvent coalesced_event(event);
 
@@ -657,12 +658,12 @@
                         WebInputEvent::kTimeStampForTesting);
   c_event.touches_length = 1;
   c_event.touches[0].state = WebTouchPoint::kStatePressed;
-  c_event.touches[0].position =
-      WebFloatPoint(rect.x + rect.width / 2 + 1, rect.y + rect.height / 2 + 1);
+  c_event.touches[0].SetPositionInWidget(rect.x + rect.width / 2 + 1,
+                                         rect.y + rect.height / 2 + 1);
 
   coalesced_event.AddCoalescedEvent(c_event);
-  c_event.touches[0].position =
-      WebFloatPoint(rect.x + rect.width / 2 + 2, rect.y + rect.height / 2 + 2);
+  c_event.touches[0].SetPositionInWidget(rect.x + rect.width / 2 + 2,
+                                         rect.y + rect.height / 2 + 2);
   coalesced_event.AddCoalescedEvent(c_event);
 
   web_view->HandleInputEvent(coalesced_event);
@@ -870,8 +871,8 @@
   WebRect rect = plugin_container_one_element.BoundsInViewport();
 
   event.touches[0].state = WebTouchPoint::kStatePressed;
-  event.touches[0].position =
-      WebFloatPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
+  event.touches[0].SetPositionInWidget(rect.x + rect.width / 2,
+                                       rect.y + rect.height / 2);
 
   web_view->HandleInputEvent(WebCoalescedInputEvent(event));
   RunPendingTasks();
diff --git a/third_party/WebKit/public/platform/WebMouseEvent.h b/third_party/WebKit/public/platform/WebMouseEvent.h
index b5530cd..c2a0095 100644
--- a/third_party/WebKit/public/platform/WebMouseEvent.h
+++ b/third_party/WebKit/public/platform/WebMouseEvent.h
@@ -37,9 +37,11 @@
                       type_param,
                       modifiers_param,
                       time_stamp_seconds_param),
-        WebPointerProperties(id_param),
-        position_in_widget_(x_param, y_param),
-        position_in_screen_(global_x_param, global_y_param) {}
+        WebPointerProperties(id_param,
+                             PointerType::kUnknown,
+                             Button::kNoButton,
+                             WebFloatPoint(x_param, y_param),
+                             WebFloatPoint(global_x_param, global_y_param)) {}
 
   WebMouseEvent(Type type_param,
                 WebFloatPoint position,
@@ -53,11 +55,13 @@
                       type_param,
                       modifiers_param,
                       time_stamp_seconds_param),
-        WebPointerProperties(id_param, button_param, PointerType::kMouse),
-        click_count(click_count_param),
-        position_in_widget_(floor(position.x), floor(position.y)),
-        position_in_screen_(floor(global_position.x),
-                            floor(global_position.y)) {}
+        WebPointerProperties(
+            id_param,
+            PointerType::kMouse,
+            button_param,
+            WebFloatPoint(floor(position.x), floor(position.y)),
+            WebFloatPoint(floor(global_position.x), floor(global_position.y))),
+        click_count(click_count_param) {}
 
   WebMouseEvent(Type type_param,
                 int modifiers_param,
@@ -92,12 +96,10 @@
   BLINK_PLATFORM_EXPORT WebMouseEvent FlattenTransform() const;
 #endif
 
-  WebFloatPoint PositionInWidget() const { return position_in_widget_; }
   void SetPositionInWidget(float x, float y) {
     position_in_widget_ = WebFloatPoint(floor(x), floor(y));
   }
 
-  WebFloatPoint PositionInScreen() const { return position_in_screen_; }
   void SetPositionInScreen(float x, float y) {
     position_in_screen_ = WebFloatPoint(floor(x), floor(y));
   }
@@ -115,15 +117,6 @@
         WebPointerProperties(id_param) {}
 
   void FlattenTransformSelf();
-
- private:
-  // Widget coordinate, which is relative to the bound of current RenderWidget
-  // (e.g. a plugin or OOPIF inside a RenderView). Similar to viewport
-  // coordinates but without DevTools emulation transform or overscroll applied.
-  WebFloatPoint position_in_widget_;
-
-  // Screen coordinate
-  WebFloatPoint position_in_screen_;
 };
 
 #pragma pack(pop)
diff --git a/third_party/WebKit/public/platform/WebPointerProperties.h b/third_party/WebKit/public/platform/WebPointerProperties.h
index 91eb1e7..7af81c14 100644
--- a/third_party/WebKit/public/platform/WebPointerProperties.h
+++ b/third_party/WebKit/public/platform/WebPointerProperties.h
@@ -5,6 +5,9 @@
 #ifndef WebPointerProperties_h
 #define WebPointerProperties_h
 
+#include "WebCommon.h"
+#include "WebFloatPoint.h"
+
 #include <cstdint>
 #include <limits>
 
@@ -15,8 +18,8 @@
 // This class encapsulates the properties that are common between mouse and
 // pointer events and touch points as we transition towards the unified pointer
 // event model.
-// TODO(e_hakkinen): Replace WebTouchEvent with WebPointerEvent, remove
-// WebTouchEvent and WebTouchPoint and merge this into WebPointerEvent.
+// TODO(mustaq): Unify WebTouchPoint & WebMouseEvent into WebPointerEvent.
+// crbug.com/508283
 class WebPointerProperties {
  public:
   enum class Button {
@@ -48,21 +51,12 @@
     kLastEntry = kTouch  // Must be the last entry in the list
   };
 
-  explicit WebPointerProperties(PointerId id_param)
-      : id(id_param),
-        force(std::numeric_limits<float>::quiet_NaN()),
-        tilt_x(0),
-        tilt_y(0),
-        tangential_pressure(0.0f),
-        twist(0),
-        button(Button::kNoButton),
-        pointer_type(PointerType::kUnknown),
-        movement_x(0),
-        movement_y(0) {}
-
-  WebPointerProperties(PointerId id_param,
-                       Button button_param,
-                       PointerType pointer_type_param)
+  explicit WebPointerProperties(
+      PointerId id_param,
+      PointerType pointer_type_param = PointerType::kUnknown,
+      Button button_param = Button::kNoButton,
+      WebFloatPoint position_in_widget = WebFloatPoint(),
+      WebFloatPoint position_in_screen = WebFloatPoint())
       : id(id_param),
         force(std::numeric_limits<float>::quiet_NaN()),
         tilt_x(0),
@@ -72,7 +66,16 @@
         button(button_param),
         pointer_type(pointer_type_param),
         movement_x(0),
-        movement_y(0) {}
+        movement_y(0),
+        position_in_widget_(position_in_widget),
+        position_in_screen_(position_in_screen) {}
+
+  WebFloatPoint PositionInWidget() const { return position_in_widget_; }
+  WebFloatPoint PositionInScreen() const { return position_in_screen_; }
+
+  // TODO(mustaq): Move the setters for position_in_widget_ and
+  // position_in_screen_ here from the subclasses when mouse event coordinate
+  // truncation is removed. crbug.com/456625
 
   PointerId id;
 
@@ -107,6 +110,15 @@
 
   int movement_x;
   int movement_y;
+
+ protected:
+  // Widget coordinate, which is relative to the bound of current RenderWidget
+  // (e.g. a plugin or OOPIF inside a RenderView). Similar to viewport
+  // coordinates but without DevTools emulation transform or overscroll applied.
+  WebFloatPoint position_in_widget_;
+
+  // Screen coordinate
+  WebFloatPoint position_in_screen_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebTouchPoint.h b/third_party/WebKit/public/platform/WebTouchPoint.h
index d26611fd..e204cd7 100644
--- a/third_party/WebKit/public/platform/WebTouchPoint.h
+++ b/third_party/WebKit/public/platform/WebTouchPoint.h
@@ -31,14 +31,14 @@
 #ifndef WebTouchPoint_h
 #define WebTouchPoint_h
 
-#include "public/platform/WebCommon.h"
-#include "public/platform/WebFloatPoint.h"
-#include "public/platform/WebPointerProperties.h"
+#include "WebCommon.h"
+#include "WebFloatPoint.h"
+#include "WebPointerProperties.h"
 
 namespace blink {
 
-// TODO(e_hakkinen): Replace WebTouchEvent with WebPointerEvent and remove
-// WebTouchEvent and this.
+// TODO(mustaq): Unify WebTouchPoint & WebMouseEvent into WebPointerEvent.
+// crbug.com/508283
 class WebTouchPoint : public WebPointerProperties {
  public:
   WebTouchPoint()
@@ -48,6 +48,14 @@
         radius_y(0),
         rotation_angle(0) {}
 
+  void SetPositionInWidget(float x, float y) {
+    position_in_widget_ = WebFloatPoint(x, y);
+  }
+
+  void SetPositionInScreen(float x, float y) {
+    position_in_screen_ = WebFloatPoint(x, y);
+  }
+
   enum State {
     kStateUndefined,
     kStateReleased,
@@ -60,11 +68,6 @@
 
   State state;
 
-  // TODO(mustaq): Move these coordinates to WebPointerProperties as private
-  // class members, as in WebMouseEvent.h now. crbug.com/508283
-  WebFloatPoint screen_position;
-  WebFloatPoint position;
-
   float radius_x;
   float radius_y;
   float rotation_angle;
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 573f1a3..c46ee61 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -37051,6 +37051,11 @@
   <int value="8" label="Download error"/>
   <int value="9" label="Install error"/>
   <int value="10" label="Install timed out"/>
+  <int value="11" label="Request to Play install API failed - Policy disabled"/>
+  <int value="12"
+      label="Request to Play install API failed - User not signed into Play"/>
+  <int value="13" label="Request to Play install API failed - Network Error"/>
+  <int value="14" label="Request to Play install API failed - Resolve Error"/>
 </enum>
 
 <enum name="WebApkGooglePlayInstallState" type="int">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e4580c7..7a88302 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -71577,6 +71577,14 @@
   </summary>
 </histogram>
 
+<histogram name="Stability.Android.RendererCrash" enum="Boolean">
+  <owner>wnwen@chromium.org</owner>
+  <summary>
+    Counts renderer crashes including OOMs. Android only. Mirrors old stability
+    proto renderer crashes.
+  </summary>
+</histogram>
+
 <histogram name="Stability.BadMessageTerminated.Chrome"
     enum="BadMessageReasonChrome">
   <owner>nick@chromium.org</owner>
diff --git a/tools/perf/benchmarks/blink_perf_unittest.py b/tools/perf/benchmarks/blink_perf_unittest.py
index 696ea098..b5cb03ab 100644
--- a/tools/perf/benchmarks/blink_perf_unittest.py
+++ b/tools/perf/benchmarks/blink_perf_unittest.py
@@ -46,11 +46,11 @@
     self.assertEquals(len(results.FindAllTraceValues()), 1)
 
     frame_view_layouts = results.FindAllPageSpecificValuesNamed(
-        'FrameView::layout')
+        'LocalFrameView::layout')
     self.assertEquals(len(frame_view_layouts), 1)
     # append-child-measure-time.html specifies 5 iterationCount.
     self.assertEquals(len(frame_view_layouts[0].values), 5)
-    self.assertGreater(frame_view_layouts[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(frame_view_layouts[0].GetRepresentativeNumber(), 0.001)
 
     update_layout_trees = results.FindAllPageSpecificValuesNamed(
         'UpdateLayoutTree')
@@ -58,7 +58,7 @@
     # append-child-measure-time.html specifies 5 iterationCount.
     self.assertEquals(len(update_layout_trees[0].values), 5)
 
-    self.assertGreater(update_layout_trees[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(update_layout_trees[0].GetRepresentativeNumber(), 0.001)
 
   def testBlinkPerfTracingMetricsForMeasureFrameTime(self):
     results = self.RunMeasurement(measurement=self._measurement,
@@ -69,18 +69,20 @@
     self.assertEquals(len(results.FindAllTraceValues()), 1)
 
     frame_view_prepaints = results.FindAllPageSpecificValuesNamed(
-        'FrameView::prePaint')
+        'LocalFrameView::prePaint')
+
     self.assertEquals(len(frame_view_prepaints), 1)
     # color-changes-measure-frame-time.html specifies 9 iterationCount.
     self.assertEquals(len(frame_view_prepaints[0].values), 9)
-    self.assertGreater(frame_view_prepaints[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(frame_view_prepaints[0].GetRepresentativeNumber(), 0.001)
 
     frame_view_painttrees = results.FindAllPageSpecificValuesNamed(
-        'FrameView::paintTree')
+        'LocalFrameView::paintTree')
     self.assertEquals(len(frame_view_painttrees), 1)
     # color-changes-measure-frame-time.html specifies 9 iterationCount.
     self.assertEquals(len(frame_view_painttrees[0].values), 9)
-    self.assertGreater(frame_view_painttrees[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(frame_view_painttrees[0].GetRepresentativeNumber(),
+        0.001)
 
   def testBlinkPerfTracingMetricsForMeasurePageLoadTime(self):
     results = self.RunMeasurement(measurement=self._measurement,
@@ -95,14 +97,14 @@
     self.assertEquals(len(create_child_frame), 1)
     # color-changes-measure-frame-time.html specifies 7 iterationCount.
     self.assertEquals(len(create_child_frame[0].values), 7)
-    self.assertGreater(create_child_frame[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(create_child_frame[0].GetRepresentativeNumber(), 0.001)
 
     post_layout_task = results.FindAllPageSpecificValuesNamed(
-        'FrameView::performPostLayoutTasks')
+        'LocalFrameView::performPostLayoutTasks')
     self.assertEquals(len(post_layout_task), 1)
     # color-changes-measure-frame-time.html specifies 7 iterationCount.
     self.assertEquals(len(post_layout_task[0].values), 7)
-    self.assertGreater(post_layout_task[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(post_layout_task[0].GetRepresentativeNumber(), 0.001)
 
 
   def testBlinkPerfTracingMetricsForMeasureAsync(self):
@@ -118,7 +120,7 @@
     self.assertEquals(len(blob_requests), 1)
     # simple-blob-measure-async.html specifies 6 iterationCount.
     self.assertEquals(len(blob_requests[0].values), 6)
-    self.assertGreater(blob_requests[0].GetRepresentativeNumber, 0.1)
+    self.assertGreater(blob_requests[0].GetRepresentativeNumber(), 0.001)
 
     blob_request_read_raw_data = results.FindAllPageSpecificValuesNamed(
         'BlobRequest::ReadRawData')
@@ -126,7 +128,7 @@
     # simple-blob-measure-async.html specifies 6 iterationCount.
     self.assertEquals(len(blob_request_read_raw_data[0].values), 6)
     self.assertGreater(
-        blob_request_read_raw_data[0].GetRepresentativeNumber, 0.01)
+        blob_request_read_raw_data[0].GetRepresentativeNumber(), 0.001)
 
 
 # pylint: disable=protected-access
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index 795efcc..0fcc6db 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -106,6 +106,7 @@
 ##############################################################################
 
 
+@decorators.Disabled('mac')  # crbug.com/728576
 class CnnStory(_ArticleBrowsingStory):
   """The second top website in http://www.alexa.com/topsites/category/News"""
   NAME = 'browse:news:cnn'
diff --git a/tools/perf/page_sets/system_health/long_running_stories.py b/tools/perf/page_sets/system_health/long_running_stories.py
index 6f1a947..47e634b 100644
--- a/tools/perf/page_sets/system_health/long_running_stories.py
+++ b/tools/perf/page_sets/system_health/long_running_stories.py
@@ -92,6 +92,7 @@
         'document.getElementById("loading").style.display === "none"')
 
 
+@decorators.Disabled('android')  # crbug.com/726301
 class LongRunningGmailMobileForegroundStory(_LongRunningGmailMobileBase):
   NAME = 'long_running:tools:gmail-foreground'
 
@@ -101,7 +102,7 @@
 
 
 @decorators.Disabled('android-webview',  # Weview does not have tabs.
-                     'android')  # crbug.com/657433
+                     'android')  # crbug.com/726301
 class LongRunningGmailMobileBackgroundStory(_LongRunningGmailMobileBase):
   BACKGROUND = True
   NAME = 'long_running:tools:gmail-background'
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
index 349e0ed..7dfbe29 100644
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -149,10 +149,10 @@
       0 /* no button changed */, event.GetToolType(pointer_index));
 
   touch.state = ToWebTouchPointState(event, pointer_index);
-  touch.position.x = event.GetX(pointer_index);
-  touch.position.y = event.GetY(pointer_index);
-  touch.screen_position.x = event.GetRawX(pointer_index);
-  touch.screen_position.y = event.GetRawY(pointer_index);
+  touch.SetPositionInWidget(event.GetX(pointer_index),
+                            event.GetY(pointer_index));
+  touch.SetPositionInScreen(event.GetRawX(pointer_index),
+                            event.GetRawY(pointer_index));
 
   // A note on touch ellipse specifications:
   //
@@ -783,10 +783,9 @@
     scaled_event.reset(touch_event);
     *touch_event = static_cast<const blink::WebTouchEvent&>(event);
     for (unsigned i = 0; i < touch_event->touches_length; i++) {
-      touch_event->touches[i].position.x += delta.x();
-      touch_event->touches[i].position.y += delta.y();
-      touch_event->touches[i].position.x *= scale;
-      touch_event->touches[i].position.y *= scale;
+      touch_event->touches[i].SetPositionInWidget(
+          (touch_event->touches[i].PositionInWidget().x + delta.x()) * scale,
+          (touch_event->touches[i].PositionInWidget().y + delta.y()) * scale);
       touch_event->touches[i].radius_x *= scale;
       touch_event->touches[i].radius_y *= scale;
     }
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 7ef9ca6..30bfed6 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -1049,8 +1049,8 @@
       continue;
     cc::InputHandler::TouchStartEventListenerType event_listener_type =
         input_handler_->EventListenerTypeForTouchStartAt(
-            gfx::Point(touch_event.touches[i].position.x,
-                       touch_event.touches[i].position.y));
+            gfx::Point(touch_event.touches[i].PositionInWidget().x,
+                       touch_event.touches[i].PositionInWidget().y));
     if (event_listener_type !=
         cc::InputHandler::TouchStartEventListenerType::NO_HANDLER) {
       is_touching_scrolling_layer =
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index 2a93385..9ce7a41 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -337,8 +337,8 @@
                                   float y) {
   WebTouchPoint point;
   point.state = state;
-  point.screen_position = WebFloatPoint(x, y);
-  point.position = WebFloatPoint(x, y);
+  point.SetPositionInScreen(x, y);
+  point.SetPositionInWidget(x, y);
   return point;
 }
 
diff --git a/ui/events/blink/web_input_event_traits.cc b/ui/events/blink/web_input_event_traits.cc
index 1ced9d9e..a68e299 100644
--- a/ui/events/blink/web_input_event_traits.cc
+++ b/ui/events/blink/web_input_event_traits.cc
@@ -71,10 +71,10 @@
                 "  (ID: %d, State: %d, ScreenPos: (%f, %f), Pos: (%f, %f),"
                 " Radius: (%f, %f), Rot: %f, Force: %f,"
                 " Tilt: (%d, %d)),\n",
-                point.id, point.state, point.screen_position.x,
-                point.screen_position.y, point.position.x, point.position.y,
-                point.radius_x, point.radius_y, point.rotation_angle,
-                point.force, point.tilt_x, point.tilt_y);
+                point.id, point.state, point.PositionInScreen().x,
+                point.PositionInScreen().y, point.PositionInWidget().x,
+                point.PositionInWidget().y, point.radius_x, point.radius_y,
+                point.rotation_angle, point.force, point.tilt_x, point.tilt_y);
 }
 
 void ApppendEventDetails(const WebTouchEvent& event, std::string* result) {
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 143b513..0758776 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -346,6 +346,8 @@
     "view_targeter.h",
     "view_targeter_delegate.cc",
     "view_targeter_delegate.h",
+    "view_tracker.cc",
+    "view_tracker.h",
     "views_delegate.cc",
     "views_delegate.h",
     "views_export.h",
diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc
index 12a80c65..153e928 100644
--- a/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/ui/views/accessibility/native_view_accessibility_win.cc
@@ -24,7 +24,6 @@
 #include "ui/base/win/atl_module.h"
 #include "ui/views/controls/button/custom_button.h"
 #include "ui/views/focus/focus_manager.h"
-#include "ui/views/focus/view_storage.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/win/hwnd_util.h"
 
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
index ba056cc1..e926db1 100644
--- a/ui/views/controls/native/native_view_host.cc
+++ b/ui/views/controls/native/native_view_host.cc
@@ -28,6 +28,9 @@
 }
 
 NativeViewHost::~NativeViewHost() {
+  // As part of deleting NativeViewHostWrapper the native view is unparented.
+  // Make sure the FocusManager is updated.
+  ClearFocus();
 }
 
 void NativeViewHost::Attach(gfx::NativeView native_view) {
diff --git a/ui/views/controls/native/native_view_host_aura_unittest.cc b/ui/views/controls/native/native_view_host_aura_unittest.cc
index 047ef98..a4732c3a 100644
--- a/ui/views/controls/native/native_view_host_aura_unittest.cc
+++ b/ui/views/controls/native/native_view_host_aura_unittest.cc
@@ -13,9 +13,11 @@
 #include "ui/events/event_utils.h"
 #include "ui/views/controls/native/native_view_host.h"
 #include "ui/views/controls/native/native_view_host_test_base.h"
+#include "ui/views/focus/focus_manager.h"
 #include "ui/views/view.h"
 #include "ui/views/view_constants_aura.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
 
 namespace views {
 
@@ -382,4 +384,80 @@
   DestroyTopLevel();
 }
 
+namespace {
+
+class TestFocusChangeListener : public FocusChangeListener {
+ public:
+  TestFocusChangeListener(FocusManager* focus_manager)
+      : focus_manager_(focus_manager) {
+    focus_manager_->AddFocusChangeListener(this);
+  }
+
+  ~TestFocusChangeListener() override {
+    focus_manager_->RemoveFocusChangeListener(this);
+  }
+
+  int did_change_focus_count() const { return did_change_focus_count_; }
+
+ private:
+  // FocusChangeListener:
+  void OnWillChangeFocus(View* focused_before, View* focused_now) override {}
+  void OnDidChangeFocus(View* focused_before, View* focused_now) override {
+    did_change_focus_count_++;
+  }
+
+  FocusManager* focus_manager_;
+  int did_change_focus_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestFocusChangeListener);
+};
+
+}  // namespace
+
+// Verifies the FocusManager is properly updated if focus is in a child widget
+// that is parented to a NativeViewHost and the NativeViewHost is destroyed.
+TEST_F(NativeViewHostAuraTest, FocusManagerUpdatedDuringDestruction) {
+  CreateTopLevel();
+  toplevel()->Show();
+
+  std::unique_ptr<aura::Window> window =
+      base::MakeUnique<aura::Window>(nullptr);
+  window->Init(ui::LAYER_NOT_DRAWN);
+  window->set_owned_by_parent(false);
+
+  std::unique_ptr<NativeViewHost> native_view_host =
+      base::MakeUnique<NativeViewHost>();
+  toplevel()->GetContentsView()->AddChildView(native_view_host.get());
+
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_CONTROL);
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.delegate = new views::WidgetDelegateView();  // Owned by the widget.
+  params.child = true;
+  params.bounds = gfx::Rect(10, 10, 100, 100);
+  params.parent = window.get();
+  std::unique_ptr<Widget> child_widget = base::MakeUnique<Widget>();
+  child_widget->Init(params);
+
+  native_view_host->Attach(window.get());
+
+  View* view1 = new View;  // Owned by |child_widget|.
+  view1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
+  view1->SetBounds(0, 0, 20, 20);
+  child_widget->GetContentsView()->AddChildView(view1);
+  child_widget->Show();
+  view1->RequestFocus();
+  EXPECT_EQ(view1, toplevel()->GetFocusManager()->GetFocusedView());
+
+  TestFocusChangeListener focus_change_listener(toplevel()->GetFocusManager());
+
+  // ~NativeViewHost() unparents |window|.
+  native_view_host.reset();
+
+  EXPECT_EQ(nullptr, toplevel()->GetFocusManager()->GetFocusedView());
+  EXPECT_EQ(1, focus_change_listener.did_change_focus_count());
+
+  child_widget.reset();
+  EXPECT_EQ(nullptr, toplevel()->GetFocusManager()->GetFocusedView());
+}
+
 }  // namespace views
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 03a3d6a..81acdf82 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -16,9 +16,9 @@
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/views/focus/focus_manager_delegate.h"
 #include "ui/views/focus/focus_search.h"
-#include "ui/views/focus/view_storage.h"
 #include "ui/views/focus/widget_focus_manager.h"
 #include "ui/views/view.h"
+#include "ui/views/view_tracker.h"
 #include "ui/views/widget/root_view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -29,10 +29,7 @@
 
 FocusManager::FocusManager(Widget* widget,
                            std::unique_ptr<FocusManagerDelegate> delegate)
-    : widget_(widget),
-      delegate_(std::move(delegate)),
-      stored_focused_view_storage_id_(
-          ViewStorage::GetInstance()->CreateStorageID()) {
+    : widget_(widget), delegate_(std::move(delegate)) {
   DCHECK(widget_);
 }
 
@@ -424,37 +421,23 @@
 }
 
 void FocusManager::SetStoredFocusView(View* focus_view) {
-  ViewStorage* view_storage = ViewStorage::GetInstance();
-  if (!view_storage) {
-    // This should never happen but bug 981648 seems to indicate it could.
-    NOTREACHED();
+  if (focus_view == GetStoredFocusView())
     return;
-  }
-
-  // TODO(jcivelli): when a TabContents containing a popup is closed, the focus
-  // is stored twice causing an assert. We should find a better alternative than
-  // removing the view from the storage explicitly.
-  view_storage->RemoveView(stored_focused_view_storage_id_);
-
+  view_tracker_for_stored_view_.reset();
   if (!focus_view)
     return;
 
-  view_storage->StoreView(stored_focused_view_storage_id_, focus_view);
+  view_tracker_for_stored_view_ = base::MakeUnique<ViewTracker>();
+  view_tracker_for_stored_view_->Add(focus_view);
 }
 
 View* FocusManager::GetStoredFocusView() {
-  ViewStorage* view_storage = ViewStorage::GetInstance();
-  if (!view_storage) {
-    // This should never happen but bug 981648 seems to indicate it could.
-    NOTREACHED();
-    return NULL;
+  if (!view_tracker_for_stored_view_ ||
+      view_tracker_for_stored_view_->views().empty()) {
+    return nullptr;
   }
-
-  return view_storage->RetrieveView(stored_focused_view_storage_id_);
-}
-
-void FocusManager::ClearStoredFocusedView() {
-  SetStoredFocusView(NULL);
+  DCHECK_EQ(1u, view_tracker_for_stored_view_->views().size());
+  return view_tracker_for_stored_view_->views()[0];
 }
 
 // Find the next (previous if reverse is true) focusable view for the specified
@@ -572,9 +555,17 @@
 }
 
 void FocusManager::OnViewIsDeleting(View* view) {
+  // Typically ViewRemoved() is called and all the cleanup happens there. With
+  // child widgets it's possible to change the parent out from under the Widget
+  // such that ViewRemoved() is never called.
   CHECK_EQ(view, focused_view_);
-  focused_view_->RemoveObserver(this);
-  focused_view_ = nullptr;
+  SetFocusedView(nullptr);
+  if (GetStoredFocusView() == view) {
+    // SetFocusedView() stored |view|. As |view| is being deleting and because
+    // a ViewObserver was just added, ViewTracker won't get
+    // OnViewIsDeleting() to properly clean up. Force that cleanup by
+    SetStoredFocusView(nullptr);
+  }
 }
 
 }  // namespace views
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index 0741d5a..c5fb0373 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -82,6 +82,7 @@
 class FocusManagerDelegate;
 class FocusSearch;
 class View;
+class ViewTracker;
 class Widget;
 
 // The FocusTraversable interface is used by components that want to process
@@ -207,9 +208,6 @@
   // the view that last had focus.
   View* GetStoredFocusView();
 
-  // Clears the stored focused view.
-  void ClearStoredFocusedView();
-
   // Disable shortcut handling.
   void set_shortcut_handling_suspended(bool suspended) {
     shortcut_handling_suspended_ = suspended;
@@ -355,9 +353,7 @@
   // Keeps track of whether shortcut handling is currently suspended.
   bool shortcut_handling_suspended_ = false;
 
-  // The storage id used in the ViewStorage to store/restore the view that last
-  // had focus.
-  const int stored_focused_view_storage_id_;
+  std::unique_ptr<ViewTracker> view_tracker_for_stored_view_;
 
   // The reason why the focus most recently changed.
   FocusChangeReason focus_change_reason_ = kReasonDirectFocusChange;
diff --git a/ui/views/view_tracker.cc b/ui/views/view_tracker.cc
new file mode 100644
index 0000000..709d9e1
--- /dev/null
+++ b/ui/views/view_tracker.cc
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/view_tracker.h"
+
+#include "base/stl_util.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+ViewTracker::ViewTracker() {}
+
+ViewTracker::~ViewTracker() {
+  for (View* view : views_)
+    view->RemoveObserver(this);
+}
+
+void ViewTracker::Add(View* view) {
+  if (!view || base::ContainsValue(views_, view))
+    return;
+
+  view->AddObserver(this);
+  views_.push_back(view);
+}
+
+void ViewTracker::Remove(View* view) {
+  auto iter = std::find(views_.begin(), views_.end(), view);
+  if (iter != views_.end()) {
+    view->RemoveObserver(this);
+    views_.erase(iter);
+  }
+}
+
+void ViewTracker::OnViewIsDeleting(View* observed_view) {
+  Remove(observed_view);
+}
+
+}  // namespace views
diff --git a/ui/views/view_tracker.h b/ui/views/view_tracker.h
new file mode 100644
index 0000000..57d29d2
--- /dev/null
+++ b/ui/views/view_tracker.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_VIEW_TRACKER_H_
+#define UI_VIEWS_VIEW_TRACKER_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "ui/views/view_observer.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+// ViewTracker tracks a set of Views. When a View is deleted the View is removed
+// from the list of tracked views.
+//
+// The behavior of this matches WindowTracker, see it for specifics.
+class VIEWS_EXPORT ViewTracker : public ViewObserver {
+ public:
+  ViewTracker();
+  ~ViewTracker() override;
+
+  void Add(View* view);
+  void Remove(View* view);
+
+  const std::vector<View*> views() const { return views_; }
+
+  // ViewObserver:
+  void OnViewIsDeleting(View* observed_view) override;
+
+ private:
+  std::vector<View*> views_;
+
+  DISALLOW_COPY_AND_ASSIGN(ViewTracker);
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_VIEW_TRACKER_H_
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index 639f239..37e54bdf 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -19,7 +19,6 @@
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/drag_controller.h"
-#include "ui/views/focus/view_storage.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/view_targeter.h"
 #include "ui/views/widget/root_view_targeter.h"
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
index 57a0ee00..1d3510f 100644
--- a/ui/views/window/dialog_client_view.cc
+++ b/ui/views/window/dialog_client_view.cc
@@ -20,6 +20,7 @@
 #include "ui/views/layout/layout_provider.h"
 #include "ui/views/style/platform_style.h"
 #include "ui/views/view_observer.h"
+#include "ui/views/view_tracker.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
 
@@ -51,36 +52,6 @@
                    size1.height() + size2.height());
 }
 
-// ViewDeletionObserver implements an observer to track the deletion of the
-// view in focus.
-class ViewDeletionObserver : public ViewObserver {
- public:
-  explicit ViewDeletionObserver(View* observed_view)
-      : observed_view_(observed_view) {
-    if (observed_view_)
-      observed_view_->AddObserver(this);
-  }
-
-  ~ViewDeletionObserver() override {
-    if (observed_view_)
-      observed_view_->RemoveObserver(this);
-  }
-
-  // ViewObserver:
-  void OnViewIsDeleting(View* observed_view) override {
-    DCHECK_EQ(observed_view, observed_view_);
-    observed_view_ = nullptr;
-    observed_view_->RemoveObserver(this);
-  }
-
-  View* observed_view() { return observed_view_; }
-
- private:
-  View* observed_view_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(ViewDeletionObserver);
-};
-
 }  // namespace
 
 // Simple container to bubble child view changes up the view hierarchy.
@@ -358,7 +329,8 @@
   GridLayout* layout = new GridLayout(button_row_container_);
   layout->set_minimum_size(minimum_size_);
   FocusManager* focus_manager = GetFocusManager();
-  ViewDeletionObserver deletion_observer(focus_manager->GetFocusedView());
+  ViewTracker view_tracker;
+  view_tracker.Add(focus_manager->GetFocusedView());
 
   // Clobber any existing LayoutManager since it has weak references to child
   // Views which may be removed by SetupViews().
@@ -449,7 +421,8 @@
 
   // The default focus is lost when child views are added back into the dialog.
   // This restores focus if the button is still available.
-  View* previously_focused_view = deletion_observer.observed_view();
+  View* previously_focused_view =
+      view_tracker.views().empty() ? nullptr : view_tracker.views()[0];
   if (previously_focused_view && !focus_manager->GetFocusedView() &&
       Contains(previously_focused_view)) {
     previously_focused_view->RequestFocus();