diff --git a/DEPS b/DEPS
index 22124cd..d9206ee7 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # 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': '19391ac4d393874797e1d34970fecf0f0182bf98',
+  'skia_revision': '21171e50f486a7234e1d8edeb0977719c81d5d3b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '79e7abbdffdd26b0967642876fe740af532eb5f8',
+  'v8_revision': 'fca6d7563e4fad451e9bff85e96f6490596cc9dd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index e6eafa0..deda4e2 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -324,6 +324,7 @@
       case PermissionType::PUSH_MESSAGING:
       case PermissionType::DURABLE_STORAGE:
       case PermissionType::BACKGROUND_SYNC:
+      case PermissionType::SENSORS:
       case PermissionType::FLASH:
         NOTIMPLEMENTED() << "RequestPermissions is not implemented for "
                          << static_cast<int>(permissions[i]);
@@ -462,6 +463,7 @@
       case PermissionType::AUDIO_CAPTURE:
       case PermissionType::VIDEO_CAPTURE:
       case PermissionType::BACKGROUND_SYNC:
+      case PermissionType::SENSORS:
       case PermissionType::FLASH:
         NOTIMPLEMENTED() << "CancelPermission not implemented for "
                          << static_cast<int>(permission);
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index 50d9f93..c68d235 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -438,6 +438,7 @@
       e.set_location_f(event.location_f());
       e.set_root_location_f(event.root_location_f());
       e.set_flags(event.flags());
+      ui::Event::DispatcherApi(&e).set_target(target);
       delegate->OnDragEntered(e);
     }
   } else {
@@ -449,6 +450,7 @@
       e.set_location_f(event.location_f());
       e.set_root_location_f(event.root_location_f());
       e.set_flags(event.flags());
+      ui::Event::DispatcherApi(&e).set_target(target);
       op = delegate->OnDragUpdated(e);
       gfx::NativeCursor cursor = ui::CursorType::kNoDrop;
       if (op & ui::DragDropTypes::DRAG_COPY)
@@ -491,6 +493,7 @@
     e.set_location_f(event.location_f());
     e.set_root_location_f(event.root_location_f());
     e.set_flags(event.flags());
+    ui::Event::DispatcherApi(&e).set_target(target);
     drag_operation_ = delegate->OnPerformDrop(e);
     if (drag_operation_ == 0)
       StartCanceledAnimation(kCancelAnimationDuration);
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 2b8d55d..38ef159 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -25,11 +25,9 @@
 }
 
 bool IsImageOp(const PaintOp* op) {
-  PaintOpType type = static_cast<PaintOpType>(op->type);
-
-  if (type == PaintOpType::DrawImage)
+  if (op->GetType() == PaintOpType::DrawImage)
     return true;
-  else if (type == PaintOpType::DrawImageRect)
+  else if (op->GetType() == PaintOpType::DrawImageRect)
     return true;
   else if (op->IsDrawOp() && op->IsPaintOpWithFlags())
     return IsImageShader(static_cast<const PaintOpWithFlags*>(op)->flags);
@@ -117,7 +115,7 @@
                      const SkRect& bounds,
                      uint8_t alpha) {
   DCHECK(op->IsDrawOp());
-  DCHECK_NE(static_cast<PaintOpType>(op->type), PaintOpType::DrawRecord);
+  DCHECK_NE(op->GetType(), PaintOpType::DrawRecord);
 
   // TODO(enne): partially specialize RasterWithAlpha for draw color?
   if (op->IsPaintOpWithFlags()) {
@@ -154,6 +152,17 @@
         flags_op->RasterWithFlags(canvas, &alpha_flags, params);
       }
     }
+  } else if (op->GetType() == PaintOpType::DrawColor &&
+             static_cast<const DrawColorOp*>(op)->mode ==
+                 SkBlendMode::kSrcOver) {
+    auto* draw_color_op = static_cast<const DrawColorOp*>(op);
+
+    SkColor color = draw_color_op->color;
+    canvas->drawColor(
+        SkColorSetARGB(SkMulDiv255Round(alpha, SkColorGetA(color)),
+                       SkColorGetR(color), SkColorGetG(color),
+                       SkColorGetB(color)),
+        draw_color_op->mode);
   } else {
     bool unset = bounds.x() == PaintOp::kUnsetRect.x();
     canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha);
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 5b3e53b4..1e01b3f 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -469,18 +469,22 @@
   EXPECT_EQ(1, canvas.restore_count_);
 }
 
-TEST(PaintOpBufferTest, SaveLayerRestore_NoFlagsDraw) {
+TEST(PaintOpBufferTest, SaveLayerRestore_DrawColor) {
   PaintOpBuffer buffer;
   uint8_t alpha = 100;
+  SkColor original = SkColorSetA(50, SK_ColorRED);
+
   buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false);
-  buffer.push<DrawColorOp>(SK_ColorRED, SkBlendMode::kSrc);
+  buffer.push<DrawColorOp>(original, SkBlendMode::kSrcOver);
   buffer.push<RestoreOp>();
 
-  testing::StrictMock<MockCanvas> canvas;
-  EXPECT_CALL(canvas, OnSaveLayer());
-  EXPECT_CALL(canvas, OnDrawPaintWithColor(SK_ColorRED));
-  EXPECT_CALL(canvas, willRestore());
+  SaveCountingCanvas canvas;
   buffer.Playback(&canvas);
+  EXPECT_EQ(canvas.save_count_, 0);
+  EXPECT_EQ(canvas.restore_count_, 0);
+
+  uint8_t expected_alpha = SkMulDiv255Round(alpha, SkColorGetA(original));
+  EXPECT_EQ(canvas.paint_.getColor(), SkColorSetA(original, expected_alpha));
 }
 
 TEST(PaintOpBufferTest, DiscardableImagesTracking_EmptyBuffer) {
diff --git a/cc/test/test_skcanvas.cc b/cc/test/test_skcanvas.cc
index 9ddd45d..b62d56b 100644
--- a/cc/test/test_skcanvas.cc
+++ b/cc/test/test_skcanvas.cc
@@ -23,6 +23,10 @@
   paint_ = paint;
 }
 
+void SaveCountingCanvas::onDrawPaint(const SkPaint& paint) {
+  paint_ = paint;
+}
+
 MockCanvas::MockCanvas() : SkNoDrawCanvas(100, 100) {}
 
 MockCanvas::~MockCanvas() = default;
diff --git a/cc/test/test_skcanvas.h b/cc/test/test_skcanvas.h
index 56cd420d..6bb6989 100644
--- a/cc/test/test_skcanvas.h
+++ b/cc/test/test_skcanvas.h
@@ -20,6 +20,7 @@
   SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;
   void willRestore() override;
   void onDrawRect(const SkRect& rect, const SkPaint& paint) override;
+  void onDrawPaint(const SkPaint& paint) override;
 
   int save_count_ = 0;
   int restore_count_ = 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index c6f5ef8..0db0159 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1635,6 +1635,15 @@
     }
 
     /**
+     * Sets the overlay mode.
+     * Overlay mode means that we are currently using AndroidOverlays to display video, and
+     * that the compositor's surface should support alpha and not be marked as opaque.
+     */
+    public void setOverlayMode(boolean useOverlayMode) {
+        mCompositorViewHolder.setOverlayMode(useOverlayMode);
+    }
+
+    /**
      * @return The content offset provider, may be null.
      */
     public ContentOffsetProvider getContentOffsetProvider() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index d472179..822280d82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -73,7 +73,6 @@
 public class CompositorViewHolder extends FrameLayout
         implements ContentOffsetProvider, LayoutManagerHost, LayoutRenderHost, Invalidator.Host,
                 FullscreenListener {
-
     private boolean mIsKeyboardShowing;
 
     private final Invalidator mInvalidator = new Invalidator();
@@ -481,6 +480,15 @@
         }
     }
 
+    /**
+     * Sets the overlay mode.
+     */
+    public void setOverlayMode(boolean useOverlayMode) {
+        if (mCompositorView != null) {
+            mCompositorView.setOverlayVideoMode(useOverlayMode);
+        }
+    }
+
     private void setContentViewMotionEventOffsets(MotionEvent e, boolean canClear) {
         // TODO(dtrainor): Factor this out to LayoutDriver.
         if (e == null || mTabVisible == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
index 1779036a..f1d8cc4b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticle.java
@@ -133,6 +133,11 @@
         return mCategory == KnownCategories.ARTICLES;
     }
 
+    /** @return whether a snippet is a contextual suggestion. */
+    public boolean isContextual() {
+        return mCategory == KnownCategories.CONTEXTUAL;
+    }
+
     /** @return whether a snippet is either offline page or asset download. */
     public boolean isDownload() {
         return mCategory == KnownCategories.DOWNLOADS;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
index 327001c6..707b0ac 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
@@ -159,6 +159,14 @@
     }
 
     @Override
+    public void fetchContextualSuggestionImage(
+            SnippetArticle suggestion, Callback<Bitmap> callback) {
+        assert mNativeSnippetsBridge != 0;
+        nativeFetchContextualSuggestionImage(mNativeSnippetsBridge, suggestion.mCategory,
+                suggestion.mIdWithinCategory, callback);
+    }
+
+    @Override
     public void dismissSuggestion(SnippetArticle suggestion) {
         assert mNativeSnippetsBridge != 0;
         nativeDismissSuggestion(mNativeSnippetsBridge, suggestion.mUrl, suggestion.getGlobalRank(),
@@ -287,6 +295,8 @@
             String[] knownSuggestions, Callback<List<SnippetArticle>> callback);
     private native void nativeFetchContextualSuggestions(
             long nativeNTPSnippetsBridge, String url, Callback<List<SnippetArticle>> callback);
+    private native void nativeFetchContextualSuggestionImage(long nativeNTPSnippetsBridge,
+            int category, String idWithinCategory, Callback<Bitmap> callback);
     private native void nativeDismissSuggestion(long nativeNTPSnippetsBridge, String url,
             int globalPosition, int category, int positionInCategory, String idWithinCategory);
     private native void nativeDismissCategory(long nativeNTPSnippetsBridge, int category);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SuggestionsSource.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SuggestionsSource.java
index 327c180..e9879d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SuggestionsSource.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SuggestionsSource.java
@@ -113,6 +113,12 @@
     void fetchContextualSuggestions(String url, Callback<List<SnippetArticle>> callback);
 
     /**
+     * Fetches the thumbnail image for a contextual suggestion. A {@code null} Bitmap is returned if
+     * no image is available.
+     */
+    void fetchContextualSuggestionImage(SnippetArticle suggestion, Callback<Bitmap> callback);
+
+    /**
      * Tells the source to dismiss the content suggestion.
      */
     void dismissSuggestion(SnippetArticle suggestion);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
index eb55755..d6925e71 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
@@ -98,7 +98,11 @@
     public void makeArticleThumbnailRequest(SnippetArticle suggestion, Callback<Bitmap> callback) {
         assert !mIsDestroyed;
 
-        mSuggestionsSource.fetchSuggestionImage(suggestion, callback);
+        if (suggestion.isContextual()) {
+            mSuggestionsSource.fetchContextualSuggestionImage(suggestion, callback);
+        } else {
+            mSuggestionsSource.fetchSuggestionImage(suggestion, callback);
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
index 6b0b05e..f59019e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -506,6 +506,11 @@
         if (tab != null) nativeNotifyStopped(tab.getWebContents());
     }
 
+    @CalledByNative
+    private void setOverlayMode(boolean useOverlayMode) {
+        mTab.getActivity().setOverlayMode(useOverlayMode);
+    }
+
     @Override
     public ContentVideoViewEmbedder getContentVideoViewEmbedder() {
         return new ActivityContentVideoViewEmbedder(mTab.getActivity()) {
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 474b130..87ac0e6 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -57,8 +57,6 @@
     "my_location.icon",
     "navigate_home.1x.icon",
     "navigate_home.icon",
-    "navigate_reload.1x.icon",
-    "navigate_reload.icon",
     "navigate_stop.1x.icon",
     "navigate_stop.icon",
     "overflow_chevron.1x.icon",
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 22042d8..9661ebe94 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -443,6 +443,8 @@
     "gcm/instance_id/instance_id_profile_service.h",
     "gcm/instance_id/instance_id_profile_service_factory.cc",
     "gcm/instance_id/instance_id_profile_service_factory.h",
+    "generic_sensor/sensor_permission_context.cc",
+    "generic_sensor/sensor_permission_context.h",
     "geolocation/chrome_access_token_store.cc",
     "geolocation/chrome_access_token_store.h",
     "geolocation/geolocation_permission_context.cc",
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
index 3faa4e2..d49d33ef 100644
--- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc
+++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -337,24 +337,28 @@
     const JavaParamRef<jobject>& j_callback) {
   DCHECK(base::FeatureList::IsEnabled(
       chrome::android::kContextualSuggestionsCarousel));
+  GURL url(ConvertJavaStringToUTF8(env, j_url));
+  content_suggestions_service_->contextual_suggestions_source()
+      ->FetchContextualSuggestions(
+          url, base::Bind(&NTPSnippetsBridge::OnContextualSuggestionsFetched,
+                          weak_ptr_factory_.GetWeakPtr(),
+                          ScopedJavaGlobalRef<jobject>(j_callback)));
+}
 
-  // We don't currently have a contextual suggestions service or provider, so
-  // we use articles as placeholders.
-  Category category = Category::FromKnownCategory(KnownCategories::ARTICLES);
-  auto suggestions = ToJavaSuggestionList(
-      env, category,
-      content_suggestions_service_->GetSuggestionsForCategory(category));
-
-  // We would eventually have to hit the network or a database, so let's
-  // pretend here the call is asynchronous.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(
-                     [](const base::android::JavaRef<jobject>& j_callback,
-                        const base::android::JavaRef<jobject>& j_suggestions) {
-                       RunCallbackAndroid(j_callback, j_suggestions);
-                     },
-                     ScopedJavaGlobalRef<jobject>(j_callback),
-                     ScopedJavaGlobalRef<jobject>(suggestions)));
+void NTPSnippetsBridge::FetchContextualSuggestionImage(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jint j_category_id,
+    const JavaParamRef<jstring>& id_within_category,
+    const JavaParamRef<jobject>& j_callback) {
+  ScopedJavaGlobalRef<jobject> callback(j_callback);
+  content_suggestions_service_->contextual_suggestions_source()
+      ->FetchContextualSuggestionImage(
+          ContentSuggestion::ID(
+              Category::FromIDValue(j_category_id),
+              ConvertJavaStringToUTF8(env, id_within_category)),
+          base::Bind(&NTPSnippetsBridge::OnImageFetched,
+                     weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
 void NTPSnippetsBridge::ReloadSuggestions(JNIEnv* env,
@@ -458,3 +462,15 @@
   RunCallbackAndroid(callback,
                      ToJavaSuggestionList(env, category, suggestions));
 }
+
+void NTPSnippetsBridge::OnContextualSuggestionsFetched(
+    ScopedJavaGlobalRef<jobject> j_callback,
+    ntp_snippets::Status status,
+    const GURL& url,
+    std::vector<ContentSuggestion> suggestions) {
+  JNIEnv* env = AttachCurrentThread();
+  auto j_suggestions = ToJavaSuggestionList(
+      env, Category::FromKnownCategory(KnownCategories::CONTEXTUAL),
+      suggestions);
+  RunCallbackAndroid(j_callback, j_suggestions);
+}
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.h b/chrome/browser/android/ntp/ntp_snippets_bridge.h
index 65aa5c99..83e26b47 100644
--- a/chrome/browser/android/ntp/ntp_snippets_bridge.h
+++ b/chrome/browser/android/ntp/ntp_snippets_bridge.h
@@ -84,6 +84,13 @@
       const base::android::JavaParamRef<jstring>& j_url,
       const base::android::JavaParamRef<jobject>& j_callback);
 
+  void FetchContextualSuggestionImage(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint j_category_id,
+      const base::android::JavaParamRef<jstring>& id_within_category,
+      const base::android::JavaParamRef<jobject>& j_callback);
+
   void ReloadSuggestions(JNIEnv* env,
                          const base::android::JavaParamRef<jobject>& obj);
 
@@ -125,6 +132,12 @@
       ntp_snippets::Status status,
       std::vector<ntp_snippets::ContentSuggestion> suggestions);
 
+  void OnContextualSuggestionsFetched(
+      base::android::ScopedJavaGlobalRef<jobject> j_callback,
+      ntp_snippets::Status status,
+      const GURL& url,
+      std::vector<ntp_snippets::ContentSuggestion> suggestions);
+
   ntp_snippets::ContentSuggestionsService* content_suggestions_service_;
   history::HistoryService* history_service_;
   base::CancelableTaskTracker tracker_;
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index 5210f8a..20f389be 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -290,6 +290,15 @@
       ->CheckMediaAccessPermission(web_contents, security_origin, type);
 }
 
+void TabWebContentsDelegateAndroid::SetOverlayMode(bool use_overlay_mode) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
+  if (obj.is_null())
+    return;
+
+  Java_TabWebContentsDelegateAndroid_setOverlayMode(env, obj, use_overlay_mode);
+}
+
 bool TabWebContentsDelegateAndroid::RequestPpapiBrokerPermission(
     WebContents* web_contents,
     const GURL& url,
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.h b/chrome/browser/android/tab_web_contents_delegate_android.h
index fa5d84db..2347e96 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.h
+++ b/chrome/browser/android/tab_web_contents_delegate_android.h
@@ -65,6 +65,7 @@
   bool CheckMediaAccessPermission(content::WebContents* web_contents,
                                   const GURL& security_origin,
                                   content::MediaStreamType type) override;
+  void SetOverlayMode(bool use_overlay_mode) override;
   bool RequestPpapiBrokerPermission(
       content::WebContents* web_contents,
       const GURL& url,
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index 0f49138..34e7264 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -603,6 +603,7 @@
   SET_STRING("OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL",
              IDS_FILE_BROWSER_OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL);
   SET_STRING("OPEN_LABEL", IDS_FILE_BROWSER_OPEN_LABEL);
+  SET_STRING("OPEN_WITH_BUTTON_LABEL", IDS_FILE_BROWSER_OPEN_WITH_BUTTON_LABEL);
   SET_STRING("MORE_ACTIONS_BUTTON_LABEL",
              IDS_FILE_BROWSER_MORE_ACTIONS_BUTTON_LABEL);
   SET_STRING("OPEN_WITH_VERB_BUTTON_LABEL",
diff --git a/chrome/browser/generic_sensor/OWNERS b/chrome/browser/generic_sensor/OWNERS
new file mode 100644
index 0000000..8abe7701
--- /dev/null
+++ b/chrome/browser/generic_sensor/OWNERS
@@ -0,0 +1,7 @@
+file://services/device/generic_sensor/OWNERS
+
+per-file *permission_context*=set noparent
+per-file *permission_context*=file://chrome/browser/permissions/PERMISSIONS_OWNERS
+
+# COMPONENT: Blink>Sensor
+# TEAM: device-dev@chromium.org
diff --git a/chrome/browser/generic_sensor/sensor_permission_context.cc b/chrome/browser/generic_sensor/sensor_permission_context.cc
new file mode 100644
index 0000000..0389cb4
--- /dev/null
+++ b/chrome/browser/generic_sensor/sensor_permission_context.cc
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/generic_sensor/sensor_permission_context.h"
+
+SensorPermissionContext::SensorPermissionContext(Profile* profile)
+    : PermissionContextBase(profile,
+                            CONTENT_SETTINGS_TYPE_SENSORS,
+                            blink::WebFeaturePolicyFeature::kNotFound) {}
+
+SensorPermissionContext::~SensorPermissionContext() {}
+
+ContentSetting SensorPermissionContext::GetPermissionStatusInternal(
+    content::RenderFrameHost* render_frame_host,
+    const GURL& requesting_origin,
+    const GURL& embedding_origin) const {
+  if (requesting_origin != embedding_origin)
+    return CONTENT_SETTING_BLOCK;
+
+  return CONTENT_SETTING_ALLOW;
+}
+
+bool SensorPermissionContext::IsRestrictedToSecureOrigins() const {
+  return true;
+}
diff --git a/chrome/browser/generic_sensor/sensor_permission_context.h b/chrome/browser/generic_sensor/sensor_permission_context.h
new file mode 100644
index 0000000..cdbf6ac
--- /dev/null
+++ b/chrome/browser/generic_sensor/sensor_permission_context.h
@@ -0,0 +1,28 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_GENERIC_SENSOR_SENSOR_PERMISSION_CONTEXT_H_
+#define CHROME_BROWSER_GENERIC_SENSOR_SENSOR_PERMISSION_CONTEXT_H_
+
+#include "base/macros.h"
+#include "chrome/browser/permissions/permission_context_base.h"
+
+class SensorPermissionContext : public PermissionContextBase {
+ public:
+  explicit SensorPermissionContext(Profile* profile);
+
+  ~SensorPermissionContext() override;
+
+ private:
+  // PermissionContextBase:
+  ContentSetting GetPermissionStatusInternal(
+      content::RenderFrameHost* render_frame_host,
+      const GURL& requesting_origin,
+      const GURL& embedding_origin) const override;
+  bool IsRestrictedToSecureOrigins() const override;
+
+  DISALLOW_COPY_AND_ASSIGN(SensorPermissionContext);
+};
+
+#endif  // CHROME_BROWSER_GENERIC_SENSOR_SENSOR_PERMISSION_CONTEXT_H_
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc
index bc068fc..f5c16ad 100644
--- a/chrome/browser/permissions/permission_manager.cc
+++ b/chrome/browser/permissions/permission_manager.cc
@@ -12,6 +12,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/background_sync/background_sync_permission_context.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/generic_sensor/sensor_permission_context.h"
 #include "chrome/browser/media/midi_permission_context.h"
 #include "chrome/browser/media/midi_sysex_permission_context.h"
 #include "chrome/browser/media/webrtc/media_stream_device_permission_context.h"
@@ -104,6 +105,8 @@
       return CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC;
     case PermissionType::FLASH:
       return CONTENT_SETTINGS_TYPE_PLUGINS;
+    case PermissionType::SENSORS:
+      return CONTENT_SETTINGS_TYPE_SENSORS;
     case PermissionType::NUM:
       // This will hit the NOTREACHED below.
       break;
@@ -284,6 +287,8 @@
   permission_contexts_[CONTENT_SETTINGS_TYPE_PLUGINS] =
       base::MakeUnique<FlashPermissionContext>(profile);
 #endif
+  permission_contexts_[CONTENT_SETTINGS_TYPE_SENSORS] =
+      base::MakeUnique<SensorPermissionContext>(profile);
 }
 
 PermissionManager::~PermissionManager() {
diff --git a/chrome/browser/permissions/permission_util.cc b/chrome/browser/permissions/permission_util.cc
index 8e3e390..86ffa28 100644
--- a/chrome/browser/permissions/permission_util.cc
+++ b/chrome/browser/permissions/permission_util.cc
@@ -43,6 +43,8 @@
       return "BackgroundSync";
     case CONTENT_SETTINGS_TYPE_PLUGINS:
       return "Flash";
+    case CONTENT_SETTINGS_TYPE_SENSORS:
+      return "Sensors";
     default:
       break;
   }
@@ -73,6 +75,8 @@
       return "BACKGROUND_SYNC";
     case CONTENT_SETTINGS_TYPE_PLUGINS:
       return "FLASH";
+    case CONTENT_SETTINGS_TYPE_SENSORS:
+      return "SENSORS";
     default:
       break;
   }
@@ -135,6 +139,8 @@
   } else if (type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) {
     *out = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
 #endif
+  } else if (type == CONTENT_SETTINGS_TYPE_SENSORS) {
+    *out = PermissionType::SENSORS;
   } else {
     return false;
   }
@@ -162,6 +168,7 @@
 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
     case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
 #endif
+    case CONTENT_SETTINGS_TYPE_SENSORS:
       return true;
     default:
       return false;
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index 3d097097..11a1e24 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -615,15 +615,13 @@
     // Update the fakebox style to match the current key capturing state.
     setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
 
-    // Inject the OneGoogleBar loader script. It'll create a global variable
-    // named "og" with the following fields:
-    //  .html - the main bar HTML.
-    //  .end_of_body_html - HTML to be inserted at the end of the body.
+    // Load the OneGoogleBar script. It'll create a global variable name "og"
+    // which is a dict corresponding to the native OneGoogleBarData type.
     var ogScript = document.createElement('script');
     ogScript.src = 'chrome-search://local-ntp/one-google.js';
     document.body.appendChild(ogScript);
     ogScript.onload = function() {
-      injectOneGoogleBar(og.html, og.end_of_body_html);
+      injectOneGoogleBar(og);
     };
   } else {
     document.body.classList.add(CLASSES.NON_GOOGLE_PAGE);
@@ -676,37 +674,32 @@
  * Injects the One Google Bar into the page. Called asynchronously, so that it
  * doesn't block the main page load.
  */
-function injectOneGoogleBar(barHtml, endOfBodyHtml) {
-  var inHeadStyle = document.createElement('link');
-  inHeadStyle.rel = "stylesheet";
-  inHeadStyle.href = 'chrome-search://local-ntp/one-google/in-head.css';
+function injectOneGoogleBar(ogb) {
+  var inHeadStyle = document.createElement('style');
+  inHeadStyle.type = 'text/css';
+  inHeadStyle.appendChild(document.createTextNode(ogb.inHeadStyle));
   document.head.appendChild(inHeadStyle);
 
-  inHeadStyle.onload = function() {
-    var inHeadScript = document.createElement('script');
-    inHeadScript.src = 'chrome-search://local-ntp/one-google/in-head.js';
-    document.head.appendChild(inHeadScript);
+  var inHeadScript = document.createElement('script');
+  inHeadScript.type = 'text/javascript';
+  inHeadScript.appendChild(document.createTextNode(ogb.inHeadScript));
+  document.head.appendChild(inHeadScript);
 
-    inHeadScript.onload = function() {
-      var ogElem = $('one-google');
-      ogElem.innerHTML = barHtml;
-      ogElem.classList.remove('hidden');
+  var ogElem = $('one-google');
+  ogElem.innerHTML = ogb.barHtml;
+  ogElem.classList.remove('hidden');
 
-      var afterBarScript = document.createElement('script');
-      afterBarScript.src =
-          'chrome-search://local-ntp/one-google/after-bar.js';
-      ogElem.parentNode.insertBefore(afterBarScript, ogElem.nextSibling);
+  var afterBarScript = document.createElement('script');
+  afterBarScript.type = 'text/javascript';
+  afterBarScript.appendChild(document.createTextNode(ogb.afterBarScript));
+  ogElem.parentNode.insertBefore(afterBarScript, ogElem.nextSibling);
 
-      afterBarScript.onload = function() {
-        $('one-google-end-of-body').innerHTML = endOfBodyHtml;
+  $('one-google-end-of-body').innerHTML = ogb.endOfBodyHtml;
 
-        var endOfBodyScript = document.createElement('script');
-        endOfBodyScript.src =
-            'chrome-search://local-ntp/one-google/end-of-body.js';
-        document.body.appendChild(endOfBodyScript);
-      };
-    };
-  };
+  var endOfBodyScript = document.createElement('script');
+  endOfBodyScript.type = 'text/javascript';
+  endOfBodyScript.appendChild(document.createTextNode(ogb.endOfBodyScript));
+  document.body.appendChild(endOfBodyScript);
 }
 
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 94786b2..3f17aee 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -1490,7 +1490,7 @@
       public SafeBrowsingServiceTest {};
 
 IN_PROC_BROWSER_TEST_P(SafeBrowsingServiceWebSocketTest,
-                       MalwareWebSocketBlocked) {
+                       DISABLED_MalwareWebSocketBlocked) {
   GURL main_url = embedded_test_server()->GetURL(kMalwareWebSocketPage);
   // This constructs the URL with the same logic as malware_websocket.html.
   GURL resolved = main_url.Resolve("/safe_browsing/malware-ws");
@@ -2269,7 +2269,7 @@
 // SafeBrowsingServiceWebSocketTest.MalwareWebSocketBlocked. That test will be
 // deleted when the old database backend is removed.
 IN_PROC_BROWSER_TEST_P(V4SafeBrowsingServiceWebSocketTest,
-                       MalwareWebSocketBlocked) {
+                       DISABLED_MalwareWebSocketBlocked) {
   GURL main_url = embedded_test_server()->GetURL(kMalwareWebSocketPage);
   // This constructs the URL with the same logic as malware_websocket.html.
   GURL resolved = main_url.Resolve("/safe_browsing/malware-ws");
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 3448d60..3a805207d 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -57,10 +57,6 @@
 const char kThemeCSSFilename[] = "theme.css";
 const char kMainHtmlFilename[] = "local-ntp.html";
 const char kOneGoogleBarScriptFilename[] = "one-google.js";
-const char kOneGoogleBarInHeadStyleFilename[] = "one-google/in-head.css";
-const char kOneGoogleBarInHeadScriptFilename[] = "one-google/in-head.js";
-const char kOneGoogleBarAfterBarScriptFilename[] = "one-google/after-bar.js";
-const char kOneGoogleBarEndOfBodyScriptFilename[] = "one-google/end-of-body.js";
 
 const char kIntegrityFormat[] = "integrity=\"sha256-%s\"";
 
@@ -77,10 +73,6 @@
     {"images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png"},
     {"images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png"},
     {kOneGoogleBarScriptFilename, kLocalResource, "text/javascript"},
-    {kOneGoogleBarInHeadStyleFilename, kLocalResource, "text/css"},
-    {kOneGoogleBarInHeadScriptFilename, kLocalResource, "text/javascript"},
-    {kOneGoogleBarAfterBarScriptFilename, kLocalResource, "text/javascript"},
-    {kOneGoogleBarEndOfBodyScriptFilename, kLocalResource, "text/javascript"},
 };
 
 // Strips any query parameters from the specified path.
@@ -172,10 +164,12 @@
 std::unique_ptr<base::DictionaryValue> ConvertOGBDataToDict(
     const OneGoogleBarData& og) {
   auto result = base::MakeUnique<base::DictionaryValue>();
-  // Only provide the html parts here. The js and css are injected separately
-  // via <script src=...> and <link rel="stylesheet" href=...>.
-  result->SetString("html", og.bar_html);
-  result->SetString("end_of_body_html", og.end_of_body_html);
+  result->SetString("barHtml", og.bar_html);
+  result->SetString("inHeadScript", og.in_head_script);
+  result->SetString("inHeadStyle", og.in_head_style);
+  result->SetString("afterBarScript", og.after_bar_script);
+  result->SetString("endOfBodyHtml", og.end_of_body_html);
+  result->SetString("endOfBodyScript", og.end_of_body_script);
   return result;
 }
 
@@ -278,37 +272,16 @@
     return;
   }
 
-  if (base::StartsWith(stripped_path, "one-google",
-                       base::CompareCase::SENSITIVE)) {
+  if (stripped_path == kOneGoogleBarScriptFilename) {
     if (!one_google_bar_service_) {
       callback.Run(nullptr);
       return;
     }
 
-    // The OneGoogleBar injector helper.
-    if (stripped_path == kOneGoogleBarScriptFilename) {
-      one_google_bar_requests_.emplace_back(base::TimeTicks::Now(), callback);
-      // TODO(treib): Figure out if there are cases where we can safely serve
-      // cached data. crbug.com/742937
-      one_google_bar_service_->Refresh();
-    } else {
-      // The actual OneGoogleBar sources.
-      const base::Optional<OneGoogleBarData>& data =
-          one_google_bar_service_->one_google_bar_data();
-      std::string result;
-      if (data.has_value()) {
-        if (stripped_path == kOneGoogleBarInHeadStyleFilename) {
-          result = data->in_head_style;
-        } else if (stripped_path == kOneGoogleBarInHeadScriptFilename) {
-          result = data->in_head_script;
-        } else if (stripped_path == kOneGoogleBarAfterBarScriptFilename) {
-          result = data->after_bar_script;
-        } else if (stripped_path == kOneGoogleBarEndOfBodyScriptFilename) {
-          result = data->end_of_body_script;
-        }
-      }
-      callback.Run(base::RefCountedString::TakeString(&result));
-    }
+    one_google_bar_requests_.emplace_back(base::TimeTicks::Now(), callback);
+    // TODO(treib): Figure out if there are cases where we can safely serve
+    // cached data. crbug.com/742937
+    one_google_bar_service_->Refresh();
 
     return;
   }
diff --git a/chrome/browser/ui/cocoa/browser_window_touch_bar.mm b/chrome/browser/ui/cocoa/browser_window_touch_bar.mm
index a1b6826..28282ba 100644
--- a/chrome/browser/ui/cocoa/browser_window_touch_bar.mm
+++ b/chrome/browser/ui/cocoa/browser_window_touch_bar.mm
@@ -246,7 +246,7 @@
                           IDS_TOUCH_BAR_BACK_FORWARD_CUSTOMIZATION_LABEL)];
   } else if ([identifier hasSuffix:kReloadOrStopTouchId]) {
     const gfx::VectorIcon& icon =
-        isPageLoading_ ? kNavigateStopIcon : kNavigateReloadIcon;
+        isPageLoading_ ? kNavigateStopIcon : vector_icons::kReloadIcon;
     int commandId = isPageLoading_ ? IDC_STOP : IDC_RELOAD;
     int tooltipId = isPageLoading_ ? IDS_TOOLTIP_STOP : IDS_TOOLTIP_RELOAD;
     [touchBarItem
diff --git a/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm b/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm
index b07f7a4..7cc8562 100644
--- a/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm
+++ b/chrome/browser/ui/cocoa/toolbar/reload_button_cocoa.mm
@@ -14,6 +14,7 @@
 #import "chrome/browser/ui/cocoa/themed_window.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/vector_icons/vector_icons.h"
 #include "ui/base/accelerators/platform_accelerator_cocoa.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
@@ -197,7 +198,7 @@
 
 - (const gfx::VectorIcon*)vectorIcon {
   if ([self tag] == IDC_RELOAD) {
-    return &kNavigateReloadIcon;
+    return &vector_icons::kReloadIcon;
   } else if ([self tag] == IDC_STOP) {
     return &kNavigateStopIcon;
   } else {
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
index b842324e..adf8628f 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button_cocoa.mm
@@ -323,7 +323,7 @@
       if (isRTL)
         normalIcon = cocoa_l10n_util::FlippedImage(normalIcon);
       // The home button has no icon for its disabled state.
-      if (icon != &kNavigateReloadIcon) {
+      if (icon != &vector_icons::kReloadIcon) {
         disabledIcon = NSImageFromImageSkia(
             gfx::CreateVectorIcon(*icon,
                                   kMDButtonIconSize.width,
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index 470ec75b..539e3756 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/theme_provider.h"
@@ -230,7 +231,7 @@
   // |tp| can be NULL in unit tests.
   if (tp) {
     const gfx::VectorIcon& icon =
-        (mode == MODE_RELOAD) ? kNavigateReloadIcon : kNavigateStopIcon;
+        (mode == MODE_RELOAD) ? vector_icons::kReloadIcon : kNavigateStopIcon;
     const SkColor normal_color =
         tp->GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
     const SkColor disabled_color =
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index b5d008e..67fdaae 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1358,9 +1358,7 @@
 
 std::unique_ptr<blink::WebSocketHandshakeThrottle>
 ChromeContentRendererClient::CreateWebSocketHandshakeThrottle() {
-  InitSafeBrowsingIfNecessary();
-  return base::MakeUnique<safe_browsing::WebSocketSBHandshakeThrottle>(
-      safe_browsing_.get());
+  return nullptr;
 }
 
 std::unique_ptr<blink::WebSpeechSynthesizer>
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeSuggestionsSource.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeSuggestionsSource.java
index 9125c009..ff7bddb6 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeSuggestionsSource.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/FakeSuggestionsSource.java
@@ -244,6 +244,12 @@
     }
 
     @Override
+    public void fetchContextualSuggestionImage(
+            SnippetArticle suggestion, Callback<Bitmap> callback) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void addObserver(Observer observer) {
         mObserverList.addObserver(observer);
     }
diff --git a/chrome/test/mini_installer/test_installer.py b/chrome/test/mini_installer/test_installer.py
index 21f10a9..4a06b7b 100644
--- a/chrome/test/mini_installer/test_installer.py
+++ b/chrome/test/mini_installer/test_installer.py
@@ -10,15 +10,19 @@
 """
 
 import argparse
+import contextlib
 import datetime
 import inspect
 import json
 import os
+import shutil
 import subprocess
 import sys
 import time
 import traceback
 import unittest
+import win32api
+from win32com.shell import shell, shellcon
 import _winreg
 
 from variable_expander import VariableExpander
@@ -332,7 +336,57 @@
   return config
 
 
-def main():
+@contextlib.contextmanager
+def ConfigureTempOnDrive(drive):
+  """Ensures that TMP is on |drive|, restoring state on completion.
+
+  This does not change the current Python runtime's idea of tempdir.
+  """
+  tmp_set = False
+  old_tmp = None
+  tmp_created = None
+  # Set TMP to something reasonable if the default temp path is not on the
+  # desired drive. Note that os.environ is used to mutate the environment since
+  # doing so writes through to the process's underlying environment block. Reads
+  # are performed directly in the off chance that code elsewhere has modified
+  # the environment without going through os.environ.
+  temp = win32api.GetTempPath()
+  if not temp or os.path.splitdrive(temp)[0] != drive:
+    # Try to use one of the standard Temp dir locations.
+    for candidate in [os.getenv(v) for v in ['LOCALAPPDATA', 'windir']]:
+      if candidate and os.path.splitdrive(candidate)[0] == drive:
+        temp = os.path.join(candidate, 'Temp')
+        if os.path.isdir(temp):
+          old_tmp = os.getenv('TMP')
+          os.environ['TMP'] = temp
+          tmp_set = True
+          break
+    # Otherwise make a Temp dir at the root of the drive.
+    if not tmp_set:
+      temp = os.path.join(drive, os.sep, 'Temp')
+      if not os.path.exists(temp):
+        os.mkdir(temp)
+        tmp_created = temp
+      elif not os.path.isdir(temp):
+        raise Exception('Cannot create %s without clobbering something' % temp)
+      old_tmp = os.getenv('TMP')
+      os.environ['TMP'] = temp
+      tmp_set = True
+  try:
+    yield
+  finally:
+    if tmp_set:
+      if old_tmp is None:
+        del os.environ['TMP']
+      else:
+        os.environ['TMP'] = old_tmp
+    if tmp_created:
+      shutil.rmtree(tmp_created, True)
+      if os.path.isdir(tmp_created):
+        raise Exception('Failed to entirely delete directory %s' % tmp_created)
+
+
+def DoMain():
   parser = argparse.ArgumentParser()
   parser.add_argument('--build-dir', default='out',
                       help='Path to main build directory (the parent of the '
@@ -388,6 +442,16 @@
   return 0 if result.wasSuccessful() else 1
 
 
+def main():
+  # Make sure that TMP and Chrome's installation directory are on the same
+  # drive to work around https://crbug.com/700809. (CSIDL_PROGRAM_FILESX86 is
+  # valid for both 32 and 64-bit apps running on 32 or 64-bit Windows.)
+  drive = os.path.splitdrive(
+      shell.SHGetFolderPath(0, shellcon.CSIDL_PROGRAM_FILESX86, None, 0))[0]
+  with ConfigureTempOnDrive(drive):
+    return DoMain()
+
+
 # TODO(dpranke): Find a way for this to be shared with the mojo and other tests.
 TEST_SEPARATOR = '.'
 
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
index d9314d2..c17c7086 100644
--- a/components/content_settings/core/common/content_settings.cc
+++ b/components/content_settings/core/common/content_settings.cc
@@ -28,7 +28,7 @@
 // content settings type name instead.
 //
 // The array size must be explicit for the static_asserts below.
-constexpr size_t kNumHistogramValues = 31;
+constexpr size_t kNumHistogramValues = 32;
 constexpr HistogramValue kHistogramValue[kNumHistogramValues] = {
     {CONTENT_SETTINGS_TYPE_COOKIES, 0},
     {CONTENT_SETTINGS_TYPE_IMAGES, 1},
@@ -61,6 +61,7 @@
     {CONTENT_SETTINGS_TYPE_MEDIA_ENGAGEMENT, 35},
     {CONTENT_SETTINGS_TYPE_SOUND, 36},
     {CONTENT_SETTINGS_TYPE_CLIENT_HINTS, 37},
+    {CONTENT_SETTINGS_TYPE_SENSORS, 38},
 };
 
 }  // namespace
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h
index ed3470f..6e0c1e67 100644
--- a/components/content_settings/core/common/content_settings_types.h
+++ b/components/content_settings/core/common/content_settings_types.h
@@ -85,6 +85,13 @@
   // the HTTP request headers for every resource requested from that origin.
   CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
 
+  // Generic Sensor API covering ambient-light-sensor, accelerometer, gyroscope
+  // and magnetometer are all mapped to a single content_settings_type.
+  // Setting for the Generic Sensor API covering ambient-light-sensor,
+  // accelerometer, gyroscope and magnetometer. These are all mapped to a single
+  // ContentSettingsType.
+  CONTENT_SETTINGS_TYPE_SENSORS,
+
   CONTENT_SETTINGS_NUM_TYPES,
 };
 
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index 38cc02c..0b87ee0 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -251,11 +251,14 @@
     "mock_content_suggestions_provider_observer.h",
     "offline_pages/offline_pages_test_utils.cc",
     "offline_pages/offline_pages_test_utils.h",
+    "remote/remote_suggestion_builder.cc",
+    "remote/remote_suggestion_builder.h",
   ]
 
   deps = [
     ":ntp_snippets",
     "//base",
+    "//components/ntp_snippets/remote/proto",
     "//components/offline_pages/core",
     "//components/offline_pages/core:test_support",
     "//testing/gmock",
diff --git a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider_unittest.cc b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider_unittest.cc
index 4ebccde..61dec565c 100644
--- a/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider_unittest.cc
+++ b/components/ntp_snippets/breaking_news/breaking_news_suggestions_provider_unittest.cc
@@ -16,7 +16,7 @@
 #include "components/ntp_snippets/breaking_news/breaking_news_listener.h"
 #include "components/ntp_snippets/breaking_news/breaking_news_suggestions_provider.h"
 #include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
-#include "components/ntp_snippets/remote/test_utils.h"
+#include "components/ntp_snippets/remote/remote_suggestion_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ntp_snippets::test::RemoteSuggestionBuilder;
diff --git a/components/ntp_snippets/content_suggestions_service.h b/components/ntp_snippets/content_suggestions_service.h
index 332c6eb..2f02f584 100644
--- a/components/ntp_snippets/content_suggestions_service.h
+++ b/components/ntp_snippets/content_suggestions_service.h
@@ -280,6 +280,11 @@
 
   CategoryRanker* category_ranker() { return category_ranker_.get(); }
 
+  ContextualSuggestionsSource* contextual_suggestions_source() {
+    DCHECK(contextual_suggestions_source_);
+    return contextual_suggestions_source_.get();
+  }
+
  private:
   friend class ContentSuggestionsServiceTest;
 
diff --git a/components/ntp_snippets/contextual_suggestions_source_unittest.cc b/components/ntp_snippets/contextual_suggestions_source_unittest.cc
index 960d8ee..c632242 100644
--- a/components/ntp_snippets/contextual_suggestions_source_unittest.cc
+++ b/components/ntp_snippets/contextual_suggestions_source_unittest.cc
@@ -20,8 +20,8 @@
 #include "components/ntp_snippets/remote/contextual_suggestions_fetcher.h"
 #include "components/ntp_snippets/remote/json_to_categories.h"
 #include "components/ntp_snippets/remote/remote_suggestion.h"
+#include "components/ntp_snippets/remote/remote_suggestion_builder.h"
 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
-#include "components/ntp_snippets/remote/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/ntp_snippets/remote/remote_suggestion_builder.cc b/components/ntp_snippets/remote/remote_suggestion_builder.cc
new file mode 100644
index 0000000..ff77a45
--- /dev/null
+++ b/components/ntp_snippets/remote/remote_suggestion_builder.cc
@@ -0,0 +1,222 @@
+// Copyright 2016 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 "components/ntp_snippets/remote/remote_suggestion_builder.h"
+
+#include <limits>
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "components/ntp_snippets/remote/proto/ntp_snippets.pb.h"
+#include "components/ntp_snippets/time_serialization.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ntp_snippets {
+
+namespace test {
+
+namespace {
+
+base::Time GetDefaultSuggestionCreationTime() {
+  base::Time out_time;
+  EXPECT_TRUE(base::Time::FromUTCString("2000-01-01T00:00:01Z", &out_time));
+  return out_time;
+}
+
+base::Time GetDefaultSuggestionExpirationTime() {
+  base::Time out_time;
+  EXPECT_TRUE(base::Time::FromUTCString("2100-01-01T00:00:01Z", &out_time));
+  return out_time;
+}
+
+}  // namespace
+
+RemoteSuggestionBuilder::RemoteSuggestionBuilder() = default;
+RemoteSuggestionBuilder::RemoteSuggestionBuilder(
+    const RemoteSuggestionBuilder& other) = default;
+RemoteSuggestionBuilder::~RemoteSuggestionBuilder() = default;
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::AddId(const std::string& id) {
+  if (!ids_) {
+    ids_ = std::vector<std::string>();
+  }
+  ids_->push_back(id);
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetTitle(
+    const std::string& title) {
+  title_ = title;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetSnippet(
+    const std::string& snippet) {
+  snippet_ = snippet;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetImageUrl(
+    const std::string& image_url) {
+  salient_image_url_ = image_url;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetPublishDate(
+    const base::Time& publish_date) {
+  publish_date_ = publish_date;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetExpiryDate(
+    const base::Time& expiry_date) {
+  expiry_date_ = expiry_date;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetScore(double score) {
+  score_ = score;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetIsDismissed(
+    bool is_dismissed) {
+  is_dismissed_ = is_dismissed;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetRemoteCategoryId(
+    int remote_category_id) {
+  remote_category_id_ = remote_category_id;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetUrl(
+    const std::string& url) {
+  url_ = url;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetPublisher(
+    const std::string& publisher) {
+  publisher_name_ = publisher;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetAmpUrl(
+    const std::string& amp_url) {
+  amp_url_ = amp_url;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetFetchDate(
+    const base::Time& fetch_date) {
+  fetch_date_ = fetch_date;
+  return *this;
+}
+
+RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetRank(int rank) {
+  rank_ = rank;
+  return *this;
+}
+
+std::unique_ptr<RemoteSuggestion> RemoteSuggestionBuilder::Build() const {
+  SnippetProto proto;
+  proto.set_title(title_.value_or("Title"));
+  proto.set_snippet(snippet_.value_or("Snippet"));
+  proto.set_salient_image_url(
+      salient_image_url_.value_or("http://image_url.com/"));
+  proto.set_publish_date(SerializeTime(
+      publish_date_.value_or(GetDefaultSuggestionCreationTime())));
+  proto.set_expiry_date(SerializeTime(
+      expiry_date_.value_or(GetDefaultSuggestionExpirationTime())));
+  proto.set_score(score_.value_or(1));
+  proto.set_dismissed(is_dismissed_.value_or(false));
+  proto.set_remote_category_id(remote_category_id_.value_or(1));
+  auto* source = proto.add_sources();
+  source->set_url(url_.value_or("http://url.com/"));
+  source->set_publisher_name(publisher_name_.value_or("Publisher"));
+  source->set_amp_url(amp_url_.value_or("http://amp_url.com/"));
+  proto.set_fetch_date(SerializeTime(fetch_date_.value_or(base::Time::Now())));
+  for (const auto& id :
+       ids_.value_or(std::vector<std::string>{source->url()})) {
+    proto.add_ids(id);
+  }
+  proto.set_rank(rank_.value_or(std::numeric_limits<int>::max()));
+  return RemoteSuggestion::CreateFromProto(proto);
+}
+
+FetchedCategoryBuilder::FetchedCategoryBuilder() = default;
+FetchedCategoryBuilder::FetchedCategoryBuilder(
+    const FetchedCategoryBuilder& other) = default;
+FetchedCategoryBuilder::~FetchedCategoryBuilder() = default;
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::SetCategory(Category category) {
+  category_ = category;
+  return *this;
+}
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::SetTitle(
+    const std::string& title) {
+  title_ = base::UTF8ToUTF16(title);
+  return *this;
+}
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::SetCardLayout(
+    ContentSuggestionsCardLayout card_layout) {
+  card_layout_ = card_layout;
+  return *this;
+}
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::SetAdditionalAction(
+    ContentSuggestionsAdditionalAction additional_action) {
+  additional_action_ = additional_action;
+  return *this;
+}
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::SetShowIfEmpty(
+    bool show_if_empty) {
+  show_if_empty_ = show_if_empty;
+  return *this;
+}
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::SetNoSuggestionsMessage(
+    const std::string& no_suggestions_message) {
+  no_suggestions_message_ = base::UTF8ToUTF16(no_suggestions_message);
+  return *this;
+}
+
+FetchedCategoryBuilder& FetchedCategoryBuilder::AddSuggestionViaBuilder(
+    const RemoteSuggestionBuilder& builder) {
+  if (!suggestion_builders_) {
+    suggestion_builders_ = std::vector<RemoteSuggestionBuilder>();
+  }
+  suggestion_builders_->push_back(builder);
+  return *this;
+}
+
+FetchedCategory FetchedCategoryBuilder::Build() const {
+  FetchedCategory result = FetchedCategory(
+      category_.value_or(Category::FromRemoteCategory(1)),
+      CategoryInfo(
+          title_.value_or(base::UTF8ToUTF16("Category title")),
+          card_layout_.value_or(ContentSuggestionsCardLayout::FULL_CARD),
+          additional_action_.value_or(
+              ContentSuggestionsAdditionalAction::FETCH),
+          show_if_empty_.value_or(false),
+          no_suggestions_message_.value_or(
+              base::UTF8ToUTF16("No suggestions message"))));
+
+  if (suggestion_builders_) {
+    for (const auto& suggestion_builder : *suggestion_builders_)
+      result.suggestions.push_back(suggestion_builder.Build());
+  }
+  return result;
+}
+
+}  // namespace test
+
+}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/remote/remote_suggestion_builder.h b/components/ntp_snippets/remote/remote_suggestion_builder.h
new file mode 100644
index 0000000..457386b0
--- /dev/null
+++ b/components/ntp_snippets/remote/remote_suggestion_builder.h
@@ -0,0 +1,93 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTION_BUILDER_H_
+#define COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTION_BUILDER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "components/ntp_snippets/remote/json_to_categories.h"
+#include "components/ntp_snippets/remote/remote_suggestion.h"
+
+namespace ntp_snippets {
+
+namespace test {
+
+class RemoteSuggestionBuilder {
+ public:
+  RemoteSuggestionBuilder();
+  RemoteSuggestionBuilder(const RemoteSuggestionBuilder& other);
+  ~RemoteSuggestionBuilder();
+
+  RemoteSuggestionBuilder& AddId(const std::string& id);
+  RemoteSuggestionBuilder& SetTitle(const std::string& title);
+  RemoteSuggestionBuilder& SetSnippet(const std::string& snippet);
+  RemoteSuggestionBuilder& SetImageUrl(const std::string& image_url);
+  RemoteSuggestionBuilder& SetPublishDate(const base::Time& publish_date);
+  RemoteSuggestionBuilder& SetExpiryDate(const base::Time& expiry_date);
+  RemoteSuggestionBuilder& SetScore(double score);
+  RemoteSuggestionBuilder& SetIsDismissed(bool is_dismissed);
+  RemoteSuggestionBuilder& SetRemoteCategoryId(int remote_category_id);
+  RemoteSuggestionBuilder& SetUrl(const std::string& url);
+  RemoteSuggestionBuilder& SetPublisher(const std::string& publisher);
+  RemoteSuggestionBuilder& SetAmpUrl(const std::string& amp_url);
+  RemoteSuggestionBuilder& SetFetchDate(const base::Time& fetch_date);
+  RemoteSuggestionBuilder& SetRank(int rank);
+
+  std::unique_ptr<RemoteSuggestion> Build() const;
+
+ private:
+  base::Optional<std::vector<std::string>> ids_;
+  base::Optional<std::string> title_;
+  base::Optional<std::string> snippet_;
+  base::Optional<std::string> salient_image_url_;
+  base::Optional<base::Time> publish_date_;
+  base::Optional<base::Time> expiry_date_;
+  base::Optional<double> score_;
+  base::Optional<bool> is_dismissed_;
+  base::Optional<int> remote_category_id_;
+  base::Optional<std::string> url_;
+  base::Optional<std::string> publisher_name_;
+  base::Optional<std::string> amp_url_;
+  base::Optional<base::Time> fetch_date_;
+  base::Optional<int> rank_;
+};
+
+class FetchedCategoryBuilder {
+ public:
+  FetchedCategoryBuilder();
+  FetchedCategoryBuilder(const FetchedCategoryBuilder& other);
+  ~FetchedCategoryBuilder();
+
+  FetchedCategoryBuilder& SetCategory(Category category);
+  FetchedCategoryBuilder& SetTitle(const std::string& title);
+  FetchedCategoryBuilder& SetCardLayout(
+      ContentSuggestionsCardLayout card_layout);
+  FetchedCategoryBuilder& SetAdditionalAction(
+      ContentSuggestionsAdditionalAction additional_action);
+  FetchedCategoryBuilder& SetShowIfEmpty(bool show_if_empty);
+  FetchedCategoryBuilder& SetNoSuggestionsMessage(
+      const std::string& no_suggestions_message);
+  FetchedCategoryBuilder& AddSuggestionViaBuilder(
+      const RemoteSuggestionBuilder& builder);
+
+  FetchedCategory Build() const;
+
+ private:
+  base::Optional<Category> category_;
+  base::Optional<base::string16> title_;
+  base::Optional<ContentSuggestionsCardLayout> card_layout_;
+  base::Optional<ContentSuggestionsAdditionalAction> additional_action_;
+  base::Optional<bool> show_if_empty_;
+  base::Optional<base::string16> no_suggestions_message_;
+  base::Optional<std::vector<RemoteSuggestionBuilder>> suggestion_builders_;
+};
+
+}  // namespace test
+
+}  // namespace ntp_snippets
+
+#endif  // COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTION_BUILDER_H_
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
index 919fc0f..a285aa2 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -46,6 +46,7 @@
 #include "components/ntp_snippets/remote/persistent_scheduler.h"
 #include "components/ntp_snippets/remote/proto/ntp_snippets.pb.h"
 #include "components/ntp_snippets/remote/remote_suggestion.h"
+#include "components/ntp_snippets/remote/remote_suggestion_builder.h"
 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
 #include "components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h"
 #include "components/ntp_snippets/remote/remote_suggestions_scheduler.h"
@@ -417,8 +418,7 @@
     provider->FetchSuggestions(
         interactive_request, RemoteSuggestionsProvider::FetchStatusCallback());
     std::move(snippets_callback)
-        .Run(Status(StatusCode::SUCCESS, "message"),
-             std::move(fetched_categories));
+        .Run(Status::Success(), std::move(fetched_categories));
   }
 
   void FetchMoreTheseSuggestions(
@@ -437,8 +437,7 @@
         .RetiresOnSaturation();
     provider->Fetch(category, known_suggestion_ids, fetch_done_callback);
     std::move(snippets_callback)
-        .Run(Status(StatusCode::SUCCESS, "message"),
-             std::move(fetched_categories));
+        .Run(Status::Success(), std::move(fetched_categories));
   }
 
   void SetOrderNewRemoteCategoriesBasedOnArticlesCategoryParam(bool value) {
@@ -507,8 +506,7 @@
                                        .SetPublisher(kSuggestionPublisherName))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
@@ -550,8 +548,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder())
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
@@ -594,8 +591,7 @@
                   .SetPublisher(kSuggestionPublisherName))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().statuses(),
               Eq(std::map<Category, CategoryStatus, Category::CompareByID>{
@@ -661,8 +657,7 @@
   // Load data with multiple categories so that a new experimental category gets
   // registered.
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   CategoryInfo info = provider->GetCategoryInfo(unknown_category());
   EXPECT_THAT(info.additional_action(),
@@ -703,8 +698,7 @@
   }
   auto provider = MakeSuggestionsProvider();
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 }
 
 TEST_F(RemoteSuggestionsProviderImplTest,
@@ -756,8 +750,7 @@
   }
   auto provider = MakeSuggestionsProvider();
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 }
 
 TEST_F(
@@ -779,8 +772,7 @@
               AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
   auto provider = MakeSuggestionsProvider();
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 }
 
 TEST_F(RemoteSuggestionsProviderImplTest, PersistCategoryInfos) {
@@ -797,8 +789,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId("2"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_EQ(observer().StatusForCategory(articles_category()),
             CategoryStatus::AVAILABLE);
@@ -856,8 +847,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId("12"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   // We manually recreate the provider to simulate Chrome restart and enforce a
   // mock ranker.
@@ -900,8 +890,7 @@
               RemoteSuggestionBuilder().AddId("2").SetRemoteCategoryId(2))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
@@ -931,8 +920,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId("2"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
@@ -965,8 +953,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId("1"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(1));
@@ -987,8 +974,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId(first))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               ElementsAre(Pointee(Property(&RemoteSuggestion::id, first))));
 
@@ -1000,8 +986,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId(second))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   // The suggestions loaded last replace all that was loaded previously.
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               ElementsAre(Pointee(Property(&RemoteSuggestion::id, second))));
@@ -1018,8 +1003,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId("id"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               ElementsAre(Pointee(Property(&RemoteSuggestion::id, "id"))));
 
@@ -1045,8 +1029,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder().AddId("first"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               ElementsAre(Pointee(Property(&RemoteSuggestion::id, "first"))));
 
@@ -1065,7 +1048,7 @@
       provider.get(), articles_category(),
       /*known_suggestion_ids=*/std::set<std::string>(),
       /*fetch_done_callback=*/expect_only_second_suggestion_received,
-      Status(StatusCode::SUCCESS, "message"), std::move(fetched_categories));
+      Status::Success(), std::move(fetched_categories));
 }
 
 TEST_F(RemoteSuggestionsProviderImplTest,
@@ -1088,7 +1071,7 @@
       provider.get(), articles_category(),
       /*known_suggestion_ids=*/std::set<std::string>(),
       /*fetch_done_callback=*/assert_only_first_suggestion_received,
-      Status(StatusCode::SUCCESS, "message"), std::move(fetched_categories));
+      Status::Success(), std::move(fetched_categories));
 
   image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1));
   ServeImageCallback serve_one_by_one_image_callback =
@@ -1119,8 +1102,7 @@
               RemoteSuggestionBuilder().AddId("http://old.com/"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               ElementsAre(Property(&ContentSuggestion::id,
@@ -1146,7 +1128,7 @@
       provider.get(), articles_category(),
       /*known_suggestion_ids=*/{"http://old.com/"},
       /*fetch_done_callback=*/assert_receiving_one_new_suggestion,
-      Status(StatusCode::SUCCESS, "message"), std::move(fetched_categories));
+      Status::Success(), std::move(fetched_categories));
 
   // Other surfaces should remain the same.
   EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
@@ -1190,8 +1172,7 @@
                   /*known_suggestion_ids=*/std::set<std::string>(),
                   assert_receiving_one_new_suggestion);
   std::move(snippets_callback)
-      .Run(Status(StatusCode::SUCCESS, "message"),
-           std::move(fetched_categories));
+      .Run(Status::Success(), std::move(fetched_categories));
 
   // Now fetch more on the surface B. The response is the same as before.
   fetched_categories.clear();
@@ -1224,8 +1205,7 @@
                   /*known_suggestion_ids=*/std::set<std::string>(),
                   expect_receiving_same_suggestion);
   std::move(snippets_callback)
-      .Run(Status(StatusCode::SUCCESS, "message"),
-           std::move(fetched_categories));
+      .Run(Status::Success(), std::move(fetched_categories));
 }
 
 TEST_F(RemoteSuggestionsProviderImplTest,
@@ -1245,8 +1225,7 @@
               RemoteSuggestionBuilder().AddId("http://id-2"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   fetched_categories.clear();
   fetched_categories.push_back(
       FetchedCategoryBuilder()
@@ -1257,8 +1236,7 @@
               RemoteSuggestionBuilder().AddId("http://new-id-2"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   // Make sure images of both batches are available. This is to sanity check our
   // assumptions for the test are right.
   ServeImageCallback cb =
@@ -1358,8 +1336,7 @@
   fetched_categories[0].suggestions.push_back(
       CreateTestRemoteSuggestion(base::StringPrintf("http://abc.com/")));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/false,
-                        Status(StatusCode::SUCCESS, "success message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(
       provider->GetSuggestionsForTesting(articles_category()),
@@ -1386,8 +1363,7 @@
               RemoteSuggestionBuilder().AddId("http://site.com"));
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(1));
@@ -1424,8 +1400,7 @@
   fetched_categories.clear();
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               IsEmpty());
 
@@ -1434,8 +1409,7 @@
   fetched_categories.clear();
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               IsEmpty());
 
@@ -1446,8 +1420,7 @@
   fetched_categories.clear();
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(1));
 }
@@ -1463,8 +1436,7 @@
               RemoteSuggestionBuilder().AddId("http://site.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   provider->DismissSuggestion(MakeArticleID("http://site.com"));
 
@@ -1509,8 +1481,7 @@
                                        .SetExpiryDate(base::Time::Now()))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   // Load the image to store it in the database.
   // TODO(tschumann): Introduce some abstraction to nicely work with image
   // fetching expectations.
@@ -1536,8 +1507,7 @@
               RemoteSuggestionBuilder().AddId("http://second/"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(provider->GetDismissedSuggestionsForTesting(articles_category()),
               IsEmpty());
@@ -1558,8 +1528,7 @@
               RemoteSuggestionBuilder().SetExpiryDate(base::Time::Now()))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(1));
@@ -1579,8 +1548,7 @@
                                        .SetAmpUrl("http://source1.amp.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(1));
@@ -1603,8 +1571,7 @@
               RemoteSuggestionBuilder().SetPublisher("").SetAmpUrl(""))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               IsEmpty());
@@ -1626,8 +1593,7 @@
 
   // Emptry categories list.
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::vector<FetchedCategory>());
+                        Status::Success(), std::vector<FetchedCategory>());
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
               ElementsAre(base::Bucket(/*min=*/0, /*count=*/2)));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"),
@@ -1638,8 +1604,7 @@
   fetched_categories.push_back(
       FetchedCategoryBuilder().SetCategory(articles_category()).Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
               ElementsAre(base::Bucket(/*min=*/0, /*count=*/3)));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"),
@@ -1654,8 +1619,7 @@
   fetched_categories.clear();
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
               ElementsAre(base::Bucket(/*min=*/0, /*count=*/3),
                           base::Bucket(/*min=*/1, /*count=*/1)));
@@ -1667,8 +1631,7 @@
   fetched_categories.clear();
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
               ElementsAre(base::Bucket(/*min=*/0, /*count=*/3),
                           base::Bucket(/*min=*/1, /*count=*/2)));
@@ -1685,8 +1648,7 @@
   fetched_categories.clear();
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
               ElementsAre(base::Bucket(/*min=*/0, /*count=*/4),
                           base::Bucket(/*min=*/1, /*count=*/2)));
@@ -1723,8 +1685,7 @@
                                        .SetPublisher(publishers[0]))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(1));
   // Dismiss the suggestion via the mashable source corpus ID.
@@ -1745,8 +1706,7 @@
                                        .SetPublisher(publishers[1]))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               IsEmpty());
 }
@@ -1762,8 +1722,7 @@
               RemoteSuggestionBuilder().AddId(kSuggestionUrl))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   gfx::Image image;
   MockFunction<void(const gfx::Image&)> image_fetched;
@@ -1841,8 +1800,7 @@
               RemoteSuggestionBuilder().AddId("http://second/"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(provider->GetSuggestionsForTesting(articles_category()),
               SizeIs(2));
 
@@ -1890,8 +1848,7 @@
               RemoteSuggestionBuilder().AddId(kSuggestionUrl))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ServeImageCallback cb =
       base::Bind(&ServeOneByOneImage, &provider->GetImageFetcherForTesting());
 
@@ -1913,8 +1870,7 @@
               "http://something.com/pletely/unrelated"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   // The image should still be available until a restart happens.
   EXPECT_FALSE(
       FetchImage(provider.get(), MakeArticleID(kSuggestionUrl)).IsEmpty());
@@ -1937,8 +1893,7 @@
   }
   fetched_categories.push_back(category_builder.Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   // TODO(tschumann): We should probably trim out any additional results and
   // only serve the MaxSuggestionCount items.
   EXPECT_THAT(provider->GetSuggestionsForTesting(articles_category()),
@@ -1977,8 +1932,7 @@
   provider->RefetchInTheBackground(
       RemoteSuggestionsProvider::FetchStatusCallback());
   base::RunLoop().RunUntilIdle();
-  std::move(snippets_callback)
-      .Run(Status(StatusCode::SUCCESS, "message"), base::nullopt);
+  std::move(snippets_callback).Run(Status::Success(), base::nullopt);
   // TODO(jkrcal): Move together with the pref storage into the scheduler.
   EXPECT_EQ(
       simple_test_clock_ptr->Now().ToInternalValue(),
@@ -2097,8 +2051,7 @@
   ASSERT_TRUE(fetched_categories[0].suggestions[0]->is_complete());
 
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   provider->DismissSuggestion(MakeArticleID("http://abc.com/"));
 
   std::set<std::string> expected_excluded_ids({"http://abc.com/"});
@@ -2132,8 +2085,7 @@
   fetched_categories.push_back(category_builder.Build());
 
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   // Dismiss them.
   for (int i = 0; i < kSuggestionsCount; ++i) {
     provider->DismissSuggestion(
@@ -2170,8 +2122,7 @@
   fetched_categories.push_back(category_builder.Build());
 
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   // Dismiss them in reverse order.
   std::string first_dismissed_suggestion_id;
@@ -2226,8 +2177,7 @@
   fetched_categories.push_back(second_category_builder.Build());
 
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   // Dismiss all suggestions.
   std::set<std::string> expected_excluded_ids;
@@ -2281,8 +2231,7 @@
       CreateTestRemoteSuggestion("http://other.com/"));
 
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   // Dismiss article suggestions first.
   for (int i = 0; i < kMaxExcludedDismissedIds; ++i) {
@@ -2323,8 +2272,7 @@
           .AddSuggestionViaBuilder(RemoteSuggestionBuilder())
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
 }
@@ -2351,8 +2299,7 @@
                                        .SetAmpUrl("http://amp.prefetched.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
@@ -2371,8 +2318,7 @@
                                        .SetAmpUrl("http://amp.other.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(
       observer().SuggestionsForCategory(articles_category()),
@@ -2405,8 +2351,7 @@
                   .SetAmpUrl("http://amp.not_prefetched.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
@@ -2425,8 +2370,7 @@
                                        .SetAmpUrl("http://amp.other.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
               UnorderedElementsAre(Property(
@@ -2460,8 +2404,7 @@
 
   EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(true));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(prefetched_suggestions_count));
 
@@ -2483,8 +2426,7 @@
                   .SetAmpUrl("http://amp.not_prefetched.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(kMaxAdditionalPrefetchedSuggestions + 1));
@@ -2519,8 +2461,7 @@
           .Build());
   EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(true));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(2));
 
@@ -2548,8 +2489,7 @@
       .WillOnce(Return(true));
   EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(true));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   EXPECT_THAT(
       observer().SuggestionsForCategory(articles_category()),
@@ -2596,8 +2536,7 @@
     }
 
     FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                          Status(StatusCode::SUCCESS, "message"),
-                          std::move(fetched_categories));
+                          Status::Success(), std::move(fetched_categories));
   }
 
   const std::vector<ContentSuggestion>& actual_suggestions =
@@ -2652,8 +2591,7 @@
           .Build());
   EXPECT_CALL(*mock_tracker, IsInitialized()).WillRepeatedly(Return(true));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(1));
 
@@ -2677,8 +2615,7 @@
               PrefetchedOfflinePageExists(GURL("http://amp.prefetched.com")))
       .WillOnce(Return(true));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
 
   ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(2));
@@ -2702,8 +2639,7 @@
               PrefetchedOfflinePageExists(GURL("http://amp.prefetched.com")))
       .WillOnce(Return(true));
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
               ElementsAre(Property(&ContentSuggestion::id,
                                    MakeArticleID("http://other.com"))));
@@ -2735,8 +2671,7 @@
                                        .SetAmpUrl("http://amp.prefetched.com"))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
               SizeIs(0));
 
@@ -2768,8 +2703,7 @@
                                        .SetScore(2))
           .Build());
   FetchTheseSuggestions(provider.get(), /*interactive_request=*/true,
-                        Status(StatusCode::SUCCESS, "message"),
-                        std::move(fetched_categories));
+                        Status::Success(), std::move(fetched_categories));
   ASSERT_THAT(
       observer().SuggestionsForCategory(articles_category()),
       ElementsAre(
diff --git a/components/ntp_snippets/remote/test_utils.cc b/components/ntp_snippets/remote/test_utils.cc
index d362b029..3c568747 100644
--- a/components/ntp_snippets/remote/test_utils.cc
+++ b/components/ntp_snippets/remote/test_utils.cc
@@ -4,12 +4,9 @@
 
 #include "components/ntp_snippets/remote/test_utils.h"
 
-#include <limits>
 #include <memory>
 
 #include "base/memory/ptr_util.h"
-#include "components/ntp_snippets/remote/proto/ntp_snippets.pb.h"
-#include "components/ntp_snippets/time_serialization.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
@@ -21,22 +18,6 @@
 
 namespace test {
 
-namespace {
-
-base::Time GetDefaultSuggestionCreationTime() {
-  base::Time out_time;
-  EXPECT_TRUE(base::Time::FromUTCString("2000-01-01T00:00:01Z", &out_time));
-  return out_time;
-}
-
-base::Time GetDefaultSuggestionExpirationTime() {
-  base::Time out_time;
-  EXPECT_TRUE(base::Time::FromUTCString("2100-01-01T00:00:01Z", &out_time));
-  return out_time;
-}
-
-}  // namespace
-
 FakeSyncService::FakeSyncService()
     : can_sync_start_(true),
       is_sync_active_(true),
@@ -100,189 +81,6 @@
 #endif
 }
 
-RemoteSuggestionBuilder::RemoteSuggestionBuilder() = default;
-RemoteSuggestionBuilder::RemoteSuggestionBuilder(
-    const RemoteSuggestionBuilder& other) = default;
-RemoteSuggestionBuilder::~RemoteSuggestionBuilder() = default;
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::AddId(const std::string& id) {
-  if (!ids_) {
-    ids_ = std::vector<std::string>();
-  }
-  ids_->push_back(id);
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetTitle(
-    const std::string& title) {
-  title_ = title;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetSnippet(
-    const std::string& snippet) {
-  snippet_ = snippet;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetImageUrl(
-    const std::string& image_url) {
-  salient_image_url_ = image_url;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetPublishDate(
-    const base::Time& publish_date) {
-  publish_date_ = publish_date;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetExpiryDate(
-    const base::Time& expiry_date) {
-  expiry_date_ = expiry_date;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetScore(double score) {
-  score_ = score;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetIsDismissed(
-    bool is_dismissed) {
-  is_dismissed_ = is_dismissed;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetRemoteCategoryId(
-    int remote_category_id) {
-  remote_category_id_ = remote_category_id;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetUrl(
-    const std::string& url) {
-  url_ = url;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetPublisher(
-    const std::string& publisher) {
-  publisher_name_ = publisher;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetAmpUrl(
-    const std::string& amp_url) {
-  amp_url_ = amp_url;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetFetchDate(
-    const base::Time& fetch_date) {
-  fetch_date_ = fetch_date;
-  return *this;
-}
-
-RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetRank(int rank) {
-  rank_ = rank;
-  return *this;
-}
-
-std::unique_ptr<RemoteSuggestion> RemoteSuggestionBuilder::Build() const {
-  SnippetProto proto;
-  proto.set_title(title_.value_or("Title"));
-  proto.set_snippet(snippet_.value_or("Snippet"));
-  proto.set_salient_image_url(
-      salient_image_url_.value_or("http://image_url.com/"));
-  proto.set_publish_date(SerializeTime(
-      publish_date_.value_or(GetDefaultSuggestionCreationTime())));
-  proto.set_expiry_date(SerializeTime(
-      expiry_date_.value_or(GetDefaultSuggestionExpirationTime())));
-  proto.set_score(score_.value_or(1));
-  proto.set_dismissed(is_dismissed_.value_or(false));
-  proto.set_remote_category_id(remote_category_id_.value_or(1));
-  auto* source = proto.add_sources();
-  source->set_url(url_.value_or("http://url.com/"));
-  source->set_publisher_name(publisher_name_.value_or("Publisher"));
-  source->set_amp_url(amp_url_.value_or("http://amp_url.com/"));
-  proto.set_fetch_date(SerializeTime(fetch_date_.value_or(base::Time::Now())));
-  for (const auto& id :
-       ids_.value_or(std::vector<std::string>{source->url()})) {
-    proto.add_ids(id);
-  }
-  proto.set_rank(rank_.value_or(std::numeric_limits<int>::max()));
-  return RemoteSuggestion::CreateFromProto(proto);
-}
-
-FetchedCategoryBuilder::FetchedCategoryBuilder() = default;
-FetchedCategoryBuilder::FetchedCategoryBuilder(
-    const FetchedCategoryBuilder& other) = default;
-FetchedCategoryBuilder::~FetchedCategoryBuilder() = default;
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::SetCategory(Category category) {
-  category_ = category;
-  return *this;
-}
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::SetTitle(
-    const std::string& title) {
-  title_ = base::UTF8ToUTF16(title);
-  return *this;
-}
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::SetCardLayout(
-    ContentSuggestionsCardLayout card_layout) {
-  card_layout_ = card_layout;
-  return *this;
-}
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::SetAdditionalAction(
-    ContentSuggestionsAdditionalAction additional_action) {
-  additional_action_ = additional_action;
-  return *this;
-}
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::SetShowIfEmpty(
-    bool show_if_empty) {
-  show_if_empty_ = show_if_empty;
-  return *this;
-}
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::SetNoSuggestionsMessage(
-    const std::string& no_suggestions_message) {
-  no_suggestions_message_ = base::UTF8ToUTF16(no_suggestions_message);
-  return *this;
-}
-
-FetchedCategoryBuilder& FetchedCategoryBuilder::AddSuggestionViaBuilder(
-    const RemoteSuggestionBuilder& builder) {
-  if (!suggestion_builders_) {
-    suggestion_builders_ = std::vector<RemoteSuggestionBuilder>();
-  }
-  suggestion_builders_->push_back(builder);
-  return *this;
-}
-
-FetchedCategory FetchedCategoryBuilder::Build() const {
-  FetchedCategory result = FetchedCategory(
-      category_.value_or(Category::FromRemoteCategory(1)),
-      CategoryInfo(
-          title_.value_or(base::UTF8ToUTF16("Category title")),
-          card_layout_.value_or(ContentSuggestionsCardLayout::FULL_CARD),
-          additional_action_.value_or(
-              ContentSuggestionsAdditionalAction::FETCH),
-          show_if_empty_.value_or(false),
-          no_suggestions_message_.value_or(
-              base::UTF8ToUTF16("No suggestions message"))));
-
-  if (suggestion_builders_) {
-    for (const auto& suggestion_builder : *suggestion_builders_)
-      result.suggestions.push_back(suggestion_builder.Build());
-  }
-  return result;
-}
-
 }  // namespace test
 
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/remote/test_utils.h b/components/ntp_snippets/remote/test_utils.h
index fef26e8..ca77097 100644
--- a/components/ntp_snippets/remote/test_utils.h
+++ b/components/ntp_snippets/remote/test_utils.h
@@ -9,10 +9,7 @@
 #include <string>
 #include <vector>
 
-#include "base/optional.h"
 #include "build/build_config.h"
-#include "components/ntp_snippets/remote/json_to_categories.h"
-#include "components/ntp_snippets/remote/remote_suggestion.h"
 #include "components/signin/core/browser/fake_signin_manager.h"
 #include "components/sync/driver/fake_sync_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -80,76 +77,6 @@
   std::unique_ptr<AccountTrackerService> account_tracker_;
 };
 
-class RemoteSuggestionBuilder {
- public:
-  RemoteSuggestionBuilder();
-  RemoteSuggestionBuilder(const RemoteSuggestionBuilder& other);
-  ~RemoteSuggestionBuilder();
-
-  RemoteSuggestionBuilder& AddId(const std::string& id);
-  RemoteSuggestionBuilder& SetTitle(const std::string& title);
-  RemoteSuggestionBuilder& SetSnippet(const std::string& snippet);
-  RemoteSuggestionBuilder& SetImageUrl(const std::string& image_url);
-  RemoteSuggestionBuilder& SetPublishDate(const base::Time& publish_date);
-  RemoteSuggestionBuilder& SetExpiryDate(const base::Time& expiry_date);
-  RemoteSuggestionBuilder& SetScore(double score);
-  RemoteSuggestionBuilder& SetIsDismissed(bool is_dismissed);
-  RemoteSuggestionBuilder& SetRemoteCategoryId(int remote_category_id);
-  RemoteSuggestionBuilder& SetUrl(const std::string& url);
-  RemoteSuggestionBuilder& SetPublisher(const std::string& publisher);
-  RemoteSuggestionBuilder& SetAmpUrl(const std::string& amp_url);
-  RemoteSuggestionBuilder& SetFetchDate(const base::Time& fetch_date);
-  RemoteSuggestionBuilder& SetRank(int rank);
-
-  std::unique_ptr<RemoteSuggestion> Build() const;
-
- private:
-  base::Optional<std::vector<std::string>> ids_;
-  base::Optional<std::string> title_;
-  base::Optional<std::string> snippet_;
-  base::Optional<std::string> salient_image_url_;
-  base::Optional<base::Time> publish_date_;
-  base::Optional<base::Time> expiry_date_;
-  base::Optional<double> score_;
-  base::Optional<bool> is_dismissed_;
-  base::Optional<int> remote_category_id_;
-  base::Optional<std::string> url_;
-  base::Optional<std::string> publisher_name_;
-  base::Optional<std::string> amp_url_;
-  base::Optional<base::Time> fetch_date_;
-  base::Optional<int> rank_;
-};
-
-class FetchedCategoryBuilder {
- public:
-  FetchedCategoryBuilder();
-  FetchedCategoryBuilder(const FetchedCategoryBuilder& other);
-  ~FetchedCategoryBuilder();
-
-  FetchedCategoryBuilder& SetCategory(Category category);
-  FetchedCategoryBuilder& SetTitle(const std::string& title);
-  FetchedCategoryBuilder& SetCardLayout(
-      ContentSuggestionsCardLayout card_layout);
-  FetchedCategoryBuilder& SetAdditionalAction(
-      ContentSuggestionsAdditionalAction additional_action);
-  FetchedCategoryBuilder& SetShowIfEmpty(bool show_if_empty);
-  FetchedCategoryBuilder& SetNoSuggestionsMessage(
-      const std::string& no_suggestions_message);
-  FetchedCategoryBuilder& AddSuggestionViaBuilder(
-      const RemoteSuggestionBuilder& builder);
-
-  FetchedCategory Build() const;
-
- private:
-  base::Optional<Category> category_;
-  base::Optional<base::string16> title_;
-  base::Optional<ContentSuggestionsCardLayout> card_layout_;
-  base::Optional<ContentSuggestionsAdditionalAction> additional_action_;
-  base::Optional<bool> show_if_empty_;
-  base::Optional<base::string16> no_suggestions_message_;
-  base::Optional<std::vector<RemoteSuggestionBuilder>> suggestion_builders_;
-};
-
 }  // namespace test
 
 }  // namespace ntp_snippets
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn
index bb842f42..3d6eb013 100644
--- a/components/vector_icons/BUILD.gn
+++ b/components/vector_icons/BUILD.gn
@@ -32,6 +32,8 @@
     "notifications.icon",
     "notifications_off.icon",
     "protocol_handler.icon",
+    "reload.1x.icon",
+    "reload.icon",
     "screen_share.icon",
     "search.icon",
     "videocam.icon",
diff --git a/chrome/app/vector_icons/navigate_reload.1x.icon b/components/vector_icons/reload.1x.icon
similarity index 100%
rename from chrome/app/vector_icons/navigate_reload.1x.icon
rename to components/vector_icons/reload.1x.icon
diff --git a/chrome/app/vector_icons/navigate_reload.icon b/components/vector_icons/reload.icon
similarity index 100%
rename from chrome/app/vector_icons/navigate_reload.icon
rename to components/vector_icons/reload.icon
diff --git a/content/browser/android/dialog_overlay_impl.cc b/content/browser/android/dialog_overlay_impl.cc
index 947701a..d3d63d8 100644
--- a/content/browser/android/dialog_overlay_impl.cc
+++ b/content/browser/android/dialog_overlay_impl.cc
@@ -5,6 +5,7 @@
 #include "content/browser/android/dialog_overlay_impl.h"
 
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "gpu/ipc/common/gpu_surface_tracker.h"
 #include "jni/DialogOverlayImpl_jni.h"
 #include "ui/android/window_android.h"
@@ -67,6 +68,12 @@
 void DialogOverlayImpl::CompleteInit(JNIEnv* env,
                                      const JavaParamRef<jobject>& obj) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  // Note: It's ok to call SetOverlayMode() directly here, because there can be
+  // at most one overlay alive at the time. This logic needs to be updated if
+  // ever AndroidOverlayProviderImpl.MAX_OVERLAYS > 1.
+  web_contents()->GetDelegate()->SetOverlayMode(true);
+
   // Send the initial token, if there is one.  The observer will notify us about
   // changes only.
   if (ui::WindowAndroid* window = cvc_->GetWindowAndroid()) {
@@ -120,6 +127,11 @@
   if (!cvc_)
     return;
 
+  // We clear overlay mode here rather than in Destroy(), because we may have
+  // been called via a WebContentsDestroyed() event, and this might be the last
+  // opportunity we have to access web_contents().
+  web_contents()->GetDelegate()->SetOverlayMode(false);
+
   cvc_->RemoveObserver(this);
   cvc_ = nullptr;
   rfhi_ = nullptr;
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc
index b223db0..196d2eb 100644
--- a/content/browser/permissions/permission_service_impl.cc
+++ b/content/browser/permissions/permission_service_impl.cc
@@ -54,6 +54,8 @@
       return PermissionType::VIDEO_CAPTURE;
     case PermissionName::BACKGROUND_SYNC:
       return PermissionType::BACKGROUND_SYNC;
+    case PermissionName::SENSORS:
+      return PermissionType::SENSORS;
   }
 
   NOTREACHED();
@@ -79,6 +81,7 @@
     case PermissionType::DURABLE_STORAGE:
     case PermissionType::BACKGROUND_SYNC:
     case PermissionType::FLASH:
+    case PermissionType::SENSORS:
     case PermissionType::NUM:
       // These aren't exposed by feature policy.
       return blink::WebFeaturePolicyFeature::kNotFound;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
index e96316b..ee29872 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
@@ -81,6 +81,13 @@
                 assert mNativeContentViewRenderView != 0;
                 nativeSurfaceCreated(mNativeContentViewRenderView);
 
+                // On pre-M Android, layers start in the hidden state until a relayout happens.
+                // There is a bug that manifests itself when entering overlay mode on pre-M devices,
+                // where a relayout never happens. This bug is out of Chromium's control, but can be
+                // worked around by forcibly re-setting the visibility of the surface view.
+                // Otherwise, the screen stays black, and some tests fail.
+                mSurfaceView.setVisibility(mSurfaceView.getVisibility());
+
                 onReadyToRender();
             }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java
index 03637d8b..2b7d8255 100644
--- a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java
@@ -28,6 +28,9 @@
     private static final String TAG = "AndroidOverlayProvider";
 
     // Maximum number of concurrent overlays that we allow.
+    // Note: DialogOverlayImpl::CompleteInit() calls WebContentsDelegate::SetOverlayMode() directly,
+    // because there can only be one overlay alive at a time. If we were to support multiple
+    // concurrent overlays, we need to revisit this logic.
     private static final int MAX_OVERLAYS = 1;
 
     // We maintain a thread with a Looper for the AndroidOverlays to use, since Dialog requires one.
@@ -57,6 +60,9 @@
             AndroidOverlayConfig config) {
         ThreadUtils.assertOnUiThread();
 
+        // If this is no longer true, we need to update DialogOverlayImpl::CompleteInit().
+        assert MAX_OVERLAYS == 1;
+
         // Limit the number of concurrent surfaces.
         if (mNumOverlays >= MAX_OVERLAYS) {
             client.onDestroyed();
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTest.java b/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTest.java
index 14fc1bee..3699576 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTest.java
@@ -26,6 +26,9 @@
     @SmallTest
     @Feature({"AndroidOverlay"})
     public void testCreateDestroyOverlay() {
+        Assert.assertFalse(getClient().hasReceivedOverlayModeChange());
+        Assert.assertFalse(getClient().isUsingOverlayMode());
+
         final DialogOverlayImpl overlay = createOverlay(0, 0, 10, 10);
 
         // We should get a new overlay with a valid surface key.
@@ -33,6 +36,9 @@
         Assert.assertEquals(Client.SURFACE_READY, event.which);
         Assert.assertTrue(event.surfaceKey > 0);
 
+        Assert.assertTrue(getClient().hasReceivedOverlayModeChange());
+        Assert.assertTrue(getClient().isUsingOverlayMode());
+
         // Close the overlay, and make sure that the provider is notified.
         // Note that we should not get a 'destroyed' message when we close it.
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -42,6 +48,7 @@
             }
         });
         Assert.assertEquals(Client.RELEASED, getClient().nextEvent().which);
+        Assert.assertFalse(getClient().isUsingOverlayMode());
     }
 
     @SmallTest
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestBase.java b/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestBase.java
index aec3631..73e728f 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestBase.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestBase.java
@@ -9,6 +9,7 @@
 
 import org.junit.Assert;
 
+import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
 import org.chromium.content.browser.framehost.RenderFrameHostImpl;
 import org.chromium.content_shell_apk.ContentShellTestBase;
@@ -75,6 +76,9 @@
             public long surfaceKey;
         }
 
+        private boolean mHasReceivedOverlayModeChange = false;
+        private boolean mUseOverlayMode = false;
+
         private ArrayBlockingQueue<Event> mPending;
 
         public Client() {
@@ -101,6 +105,19 @@
             mPending.add(new Event(CONNECTION_ERROR, exception));
         }
 
+        public void onOverlayModeChanged(boolean useOverlayMode) {
+            mHasReceivedOverlayModeChange = true;
+            mUseOverlayMode = useOverlayMode;
+        }
+
+        public boolean hasReceivedOverlayModeChange() {
+            return mHasReceivedOverlayModeChange;
+        }
+
+        public boolean isUsingOverlayMode() {
+            return mUseOverlayMode;
+        }
+
         // This isn't part of the overlay client.  It's called by the overlay to indicate that it
         // has been released by the client, but it's routed to us anyway.  It's on the Browser UI
         // thread, and it's convenient for us to keep track of it here.
@@ -176,6 +193,16 @@
                 mClient.notifyReleased();
             }
         };
+
+        Callback<Boolean> overlayModeChanged = new Callback<Boolean>() {
+            @Override
+            public void onResult(Boolean useOverlayMode) {
+                mClient.onOverlayModeChanged(useOverlayMode);
+            }
+        };
+
+        getActivityForTestCommon().getActiveShell().setOverayModeChangedCallbackForTesting(
+                overlayModeChanged);
     }
 
     // Create an overlay with the given parameters and return it.
diff --git a/content/public/browser/permission_type.h b/content/public/browser/permission_type.h
index 071add6..22b3c3b 100644
--- a/content/public/browser/permission_type.h
+++ b/content/public/browser/permission_type.h
@@ -24,6 +24,7 @@
   VIDEO_CAPTURE = 9,
   BACKGROUND_SYNC = 10,
   FLASH = 11,
+  SENSORS = 12,
 
   // Always keep this at the end.
   NUM,
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 1a716df8..30c545b 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -217,6 +217,8 @@
 bool WebContentsDelegate::ShouldBlockMediaRequest(const GURL& url) {
   return false;
 }
+
+void WebContentsDelegate::SetOverlayMode(bool use_overlay_mode) {}
 #endif
 
 bool WebContentsDelegate::RequestPpapiBrokerPermission(
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 9363eff..1e3c7fe1 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -491,6 +491,12 @@
 
   // Returns true if the given media should be blocked to load.
   virtual bool ShouldBlockMediaRequest(const GURL& url);
+
+  // Tells the delegate to enter overlay mode.
+  // Overlay mode means that we are currently using AndroidOverlays to display
+  // video, and that the compositor's surface should support alpha and not be
+  // marked as opaque. See media/base/android/android_overlay.h.
+  virtual void SetOverlayMode(bool use_overlay_mode);
 #endif
 
   // Requests permission to access the PPAPI broker. The delegate should return
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 4aaf19c..cd2d66f6 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -261,10 +261,6 @@
     "media/video_capture_impl_manager.h",
     "media/web_media_element_source_utils.cc",
     "media/web_media_element_source_utils.h",
-    "media/webmediaplayer_ms.cc",
-    "media/webmediaplayer_ms.h",
-    "media/webmediaplayer_ms_compositor.cc",
-    "media/webmediaplayer_ms_compositor.h",
     "menu_item_builder.cc",
     "menu_item_builder.h",
     "message_delivery_policy.h",
@@ -660,6 +656,10 @@
       "media/video_track_adapter.h",
       "media/webaudio_media_stream_source.cc",
       "media/webaudio_media_stream_source.h",
+      "media/webmediaplayer_ms.cc",
+      "media/webmediaplayer_ms.h",
+      "media/webmediaplayer_ms_compositor.cc",
+      "media/webmediaplayer_ms_compositor.h",
       "media/webrtc/media_stream_remote_video_source.cc",
       "media/webrtc/media_stream_remote_video_source.h",
       "media/webrtc/media_stream_track_metrics.cc",
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc
index 04bb278..4e022cc 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -61,7 +61,7 @@
       break;
     case media::AudioLatency::LATENCY_PLAYBACK:
       return media::AudioLatency::GetHighLatencyBufferSize(
-          hardware_params.sample_rate(), 0);
+          hardware_params.sample_rate(), hardware_params.frames_per_buffer());
       break;
     case media::AudioLatency::LATENCY_EXACT_MS:
       return media::AudioLatency::GetExactBufferSize(
diff --git a/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc b/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
index e4c26a73..96068a8 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc
@@ -193,8 +193,8 @@
 
   blink::WebAudioLatencyHint playbackLatencyHint(
       blink::WebAudioLatencyHint::kCategoryPlayback);
-  int playbackBufferSize =
-      media::AudioLatency::GetHighLatencyBufferSize(kHardwareSampleRate, 0);
+  int playbackBufferSize = media::AudioLatency::GetHighLatencyBufferSize(
+      kHardwareSampleRate, kHardwareBufferSize);
   SetupDevice(playbackLatencyHint);
 
   EXPECT_EQ(webaudio_device_->SampleRate(), kHardwareSampleRate);
diff --git a/content/shell/android/java/src/org/chromium/content_shell/Shell.java b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
index 63077b4..9333181c 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/Shell.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
@@ -24,6 +24,7 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
+import org.chromium.base.Callback;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.browser.ActivityContentVideoViewEmbedder;
@@ -70,6 +71,8 @@
     private boolean mLoading;
     private boolean mIsFullscreen;
 
+    private Callback<Boolean> mOverlayModeChangedCallbackForTesting;
+
     /**
      * Constructor for inflating via XML.
      */
@@ -365,6 +368,18 @@
         };
     }
 
+    @CalledByNative
+    public void setOverlayMode(boolean useOverlayMode) {
+        mContentViewRenderView.setOverlayVideoMode(useOverlayMode);
+        if (mOverlayModeChangedCallbackForTesting != null) {
+            mOverlayModeChangedCallbackForTesting.onResult(useOverlayMode);
+        }
+    }
+
+    public void setOverayModeChangedCallbackForTesting(Callback<Boolean> callback) {
+        mOverlayModeChangedCallbackForTesting = callback;
+    }
+
     /**
      * Enable/Disable navigation(Prev/Next) button if navigation is allowed/disallowed
      * in respective direction.
diff --git a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
index a15cae7..751d2cf 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
@@ -88,15 +88,6 @@
         if (previousShell != null) previousShell.close();
     }
 
-    /**
-     * Enter or leave overlay video mode.
-     * @param enabled Whether overlay mode is enabled.
-     */
-    public void setOverlayVideoMode(boolean enabled) {
-        if (mContentViewRenderView == null) return;
-        mContentViewRenderView.setOverlayVideoMode(enabled);
-    }
-
     @SuppressWarnings("unused")
     @CalledByNative
     private Object createShell(long nativeShellPtr) {
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h
index 8882f4e1..013cce1 100644
--- a/content/shell/browser/shell.h
+++ b/content/shell/browser/shell.h
@@ -132,6 +132,7 @@
   void LoadProgressChanged(WebContents* source, double progress) override;
   base::android::ScopedJavaLocalRef<jobject>
       GetContentVideoViewEmbedder() override;
+  void SetOverlayMode(bool use_overlay_mode) override;
 #endif
   void EnterFullscreenModeForTab(WebContents* web_contents,
                                  const GURL& origin) override;
diff --git a/content/shell/browser/shell_android.cc b/content/shell/browser/shell_android.cc
index 6784258..ad30c47 100644
--- a/content/shell/browser/shell_android.cc
+++ b/content/shell/browser/shell_android.cc
@@ -82,6 +82,11 @@
   return Java_Shell_getContentVideoViewEmbedder(env, java_object_);
 }
 
+void Shell::SetOverlayMode(bool use_overlay_mode) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  return Java_Shell_setOverlayMode(env, java_object_, use_overlay_mode);
+}
+
 void Shell::PlatformToggleFullscreenModeForTab(WebContents* web_contents,
                                                bool enter_fullscreen) {
   JNIEnv* env = AttachCurrentThread();
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
index b275d6a..d06ff589 100644
--- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
+++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -213,8 +213,8 @@
           media::AudioLatency::GetRtcBufferSize(hw_sample_rate, hw_buffer_size);
       break;
     case blink::WebAudioLatencyHint::kCategoryPlayback:
-      buffer_size =
-          media::AudioLatency::GetHighLatencyBufferSize(hw_sample_rate, 0);
+      buffer_size = media::AudioLatency::GetHighLatencyBufferSize(
+          hw_sample_rate, hw_buffer_size);
       break;
     case blink::WebAudioLatencyHint::kCategoryExact:
       buffer_size = media::AudioLatency::GetExactBufferSize(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index e73978db..fe2ac15 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1468,7 +1468,6 @@
     "../renderer/media/renderer_webaudiodevice_impl_unittest.cc",
     "../renderer/media/video_capture_impl_manager_unittest.cc",
     "../renderer/media/video_capture_impl_unittest.cc",
-    "../renderer/media/webmediaplayer_ms_unittest.cc",
     "../renderer/peripheral_content_heuristic_unittest.cc",
     "../renderer/presentation/presentation_connection_proxy_unittest.cc",
     "../renderer/presentation/presentation_dispatcher_unittest.cc",
@@ -1692,6 +1691,7 @@
       "../renderer/media/rtc_peer_connection_handler_unittest.cc",
       "../renderer/media/speech_recognition_audio_sink_unittest.cc",
       "../renderer/media/user_media_client_impl_unittest.cc",
+      "../renderer/media/webmediaplayer_ms_unittest.cc",
       "../renderer/media/webrtc/media_stream_remote_video_source_unittest.cc",
       "../renderer/media/webrtc/media_stream_track_metrics_unittest.cc",
       "../renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc",
diff --git a/gin/OWNERS b/gin/OWNERS
index ae52483..481dea8 100644
--- a/gin/OWNERS
+++ b/gin/OWNERS
@@ -1,4 +1,6 @@
 jochen@chromium.org
+jbroman@chromium.org
+rmcilroy@chromium.org
 
 # TEAM: blink-reviews-bindings@chromium.org
 # COMPONENT: Blink>Bindings
diff --git a/ios/chrome/app/application_delegate/mock_tab_opener.h b/ios/chrome/app/application_delegate/mock_tab_opener.h
index 3bfab7c..c019b6a6 100644
--- a/ios/chrome/app/application_delegate/mock_tab_opener.h
+++ b/ios/chrome/app/application_delegate/mock_tab_opener.h
@@ -22,6 +22,9 @@
 
 // Clear the URL.
 - (void)resetURL;
+
+- (ProceduralBlock)completionBlockForTriggeringAction:
+    (NTPTabOpeningPostOpeningAction)action;
 @end
 
 #endif  // IOS_CHROME_APP_APPLICATION_DELEGATE_MOCK_TAB_OPENER_H_
diff --git a/ios/chrome/app/application_delegate/mock_tab_opener.mm b/ios/chrome/app/application_delegate/mock_tab_opener.mm
index 100a9e04..e41a08d 100644
--- a/ios/chrome/app/application_delegate/mock_tab_opener.mm
+++ b/ios/chrome/app/application_delegate/mock_tab_opener.mm
@@ -44,4 +44,10 @@
   return YES;
 }
 
+- (ProceduralBlock)completionBlockForTriggeringAction:
+    (NTPTabOpeningPostOpeningAction)action {
+  // Stub
+  return nil;
+}
+
 @end
diff --git a/ios/chrome/app/application_delegate/tab_opening.h b/ios/chrome/app/application_delegate/tab_opening.h
index 93bf745..ff5ae8d 100644
--- a/ios/chrome/app/application_delegate/tab_opening.h
+++ b/ios/chrome/app/application_delegate/tab_opening.h
@@ -7,6 +7,7 @@
 
 #include "base/ios/block_types.h"
 #include "ios/chrome/app/application_mode.h"
+#import "ios/chrome/browser/app_startup_parameters.h"
 #include "ui/base/page_transition_types.h"
 
 @class AppState;
@@ -33,6 +34,13 @@
 // made current.
 - (BOOL)shouldOpenNTPTabOnActivationOfTabModel:(TabModel*)tabModel;
 
+// Returns a block that can be executed on the new tab to trigger one of the
+// commands. This block can be passed to
+// |dismissModalsAndOpenSelectedTabInMode:withURL:transition:completion:|.
+// This block must only be executed if new tab opened on NTP.
+- (ProceduralBlock)completionBlockForTriggeringAction:
+    (NTPTabOpeningPostOpeningAction)action;
+
 @end
 
 #endif  // IOS_CHROME_APP_APPLICATION_DELEGATE_TAB_OPENING_H_
diff --git a/ios/chrome/app/application_delegate/url_opener.mm b/ios/chrome/app/application_delegate/url_opener.mm
index 2f48018..2c648a5 100644
--- a/ios/chrome/app/application_delegate/url_opener.mm
+++ b/ios/chrome/app/application_delegate/url_opener.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/app/application_delegate/startup_information.h"
 #import "ios/chrome/app/application_delegate/tab_opening.h"
 #include "ios/chrome/app/chrome_app_startup_parameters.h"
+#import "ios/chrome/browser/chrome_url_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -57,10 +58,17 @@
     // never be called. Open the requested URL immediately and return YES if
     // the parsed URL was valid.
     if (params) {
-      [tabOpener dismissModalsAndOpenSelectedTabInMode:ApplicationMode::NORMAL
-                                               withURL:[params externalURL]
-                                            transition:ui::PAGE_TRANSITION_LINK
-                                            completion:nil];
+      ProceduralBlock tabOpenedCompletion = [tabOpener
+          completionBlockForTriggeringAction:[params postOpeningAction]];
+      DCHECK(IsURLNtp([params externalURL]) || !tabOpenedCompletion);
+
+      [tabOpener
+          dismissModalsAndOpenSelectedTabInMode:[params launchInIncognito]
+                                                    ? ApplicationMode::INCOGNITO
+                                                    : ApplicationMode::NORMAL
+                                        withURL:[params externalURL]
+                                     transition:ui::PAGE_TRANSITION_LINK
+                                     completion:tabOpenedCompletion];
       return YES;
     }
     return NO;
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index 3aaf0f3b..3dcee1f 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -271,14 +271,14 @@
   } else if ([shortcutItem.type isEqualToString:kShortcutVoiceSearch]) {
     base::RecordAction(
         UserMetricsAction("ApplicationShortcut.VoiceSearchPressed"));
-    [startupParams setLaunchVoiceSearch:YES];
+    [startupParams setPostOpeningAction:START_VOICE_SEARCH];
     [startupInformation setStartupParameters:startupParams];
     return YES;
 
   } else if ([shortcutItem.type isEqualToString:kShortcutQRScanner]) {
     base::RecordAction(
         UserMetricsAction("ApplicationShortcut.ScanQRCodePressed"));
-    [startupParams setLaunchQRScanner:YES];
+    [startupParams setPostOpeningAction:START_QR_CODE_SCANNER];
     [startupInformation setStartupParameters:startupParams];
     return YES;
   }
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
index 6cedf95..a9c8cc0e 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -403,19 +403,19 @@
 
   NSArray* parametersToTest = @[
     @[
-      base::SysUTF8ToNSString(spotlight::kSpotlightActionNewTab), @NO, @NO, @NO
+      base::SysUTF8ToNSString(spotlight::kSpotlightActionNewTab), @(NO_ACTION)
     ],
     @[
-      base::SysUTF8ToNSString(spotlight::kSpotlightActionNewIncognitoTab), @YES,
-      @NO, @NO
+      base::SysUTF8ToNSString(spotlight::kSpotlightActionNewIncognitoTab),
+      @(NO_ACTION)
     ],
     @[
-      base::SysUTF8ToNSString(spotlight::kSpotlightActionVoiceSearch), @NO,
-      @YES, @NO
+      base::SysUTF8ToNSString(spotlight::kSpotlightActionVoiceSearch),
+      @(START_VOICE_SEARCH)
     ],
     @[
-      base::SysUTF8ToNSString(spotlight::kSpotlightActionQRScanner), @NO, @NO,
-      @YES
+      base::SysUTF8ToNSString(spotlight::kSpotlightActionQRScanner),
+      @(START_QR_CODE_SCANNER)
     ]
   ];
 
@@ -447,12 +447,8 @@
     EXPECT_TRUE(result);
     EXPECT_EQ(gurlNewTab,
               [fakeStartupInformation startupParameters].externalURL);
-    EXPECT_EQ([parameters[1] boolValue],
-              [fakeStartupInformation startupParameters].launchInIncognito);
-    EXPECT_EQ([parameters[2] boolValue],
-              [fakeStartupInformation startupParameters].launchVoiceSearch);
-    EXPECT_EQ([parameters[3] boolValue],
-              [fakeStartupInformation startupParameters].launchQRScanner);
+    EXPECT_EQ([parameters[1] intValue],
+              [fakeStartupInformation startupParameters].postOpeningAction);
   }
 }
 
@@ -546,9 +542,10 @@
   [fakeStartupInformation setIsPresentingFirstRunUI:NO];
 
   NSArray* parametersToTest = @[
-    @[ @"OpenNewTab", @NO, @NO, @NO ], @[ @"OpenIncognitoTab", @YES, @NO, @NO ],
-    @[ @"OpenVoiceSearch", @NO, @YES, @NO ],
-    @[ @"OpenQRScanner", @NO, @NO, @YES ]
+    @[ @"OpenNewTab", @NO, @(NO_ACTION) ],
+    @[ @"OpenIncognitoTab", @YES, @(NO_ACTION) ],
+    @[ @"OpenVoiceSearch", @NO, @(START_VOICE_SEARCH) ],
+    @[ @"OpenQRScanner", @NO, @(START_QR_CODE_SCANNER) ]
   ];
 
   swizzleHandleStartupParameters();
@@ -578,10 +575,8 @@
               [fakeStartupInformation startupParameters].externalURL);
     EXPECT_EQ([[parameters objectAtIndex:1] boolValue],
               [fakeStartupInformation startupParameters].launchInIncognito);
-    EXPECT_EQ([[parameters objectAtIndex:2] boolValue],
-              [fakeStartupInformation startupParameters].launchVoiceSearch);
-    EXPECT_EQ([[parameters objectAtIndex:3] boolValue],
-              [fakeStartupInformation startupParameters].launchQRScanner);
+    EXPECT_EQ([[parameters objectAtIndex:2] intValue],
+              [fakeStartupInformation startupParameters].postOpeningAction);
     EXPECT_TRUE(completionHandlerExecuted());
     EXPECT_TRUE(completionHandlerArgument());
     EXPECT_TRUE(getHandleStartupParametersHasBeenCalled());
diff --git a/ios/chrome/app/chrome_app_startup_parameters.mm b/ios/chrome/app/chrome_app_startup_parameters.mm
index 5e3153b..7b8864d 100644
--- a/ios/chrome/app/chrome_app_startup_parameters.mm
+++ b/ios/chrome/app/chrome_app_startup_parameters.mm
@@ -231,7 +231,7 @@
           declaredSourceApp:appId
             secureSourceApp:secureSourceApp
                 completeURL:url];
-    [params setLaunchVoiceSearch:YES];
+    [params setPostOpeningAction:START_VOICE_SEARCH];
     return params;
   }
 
@@ -252,7 +252,7 @@
           declaredSourceApp:appId
             secureSourceApp:secureSourceApp
                 completeURL:url];
-    [params setLaunchFocusOmnibox:YES];
+    [params setPostOpeningAction:FOCUS_OMNIBOX];
     return params;
   }
 
@@ -278,7 +278,7 @@
           declaredSourceApp:appId
             secureSourceApp:secureSourceApp
                 completeURL:url];
-    [params setLaunchQRScanner:YES];
+    [params setPostOpeningAction:START_QR_CODE_SCANNER];
     return params;
   }
 
@@ -291,7 +291,7 @@
             secureSourceApp:secureSourceApp
                 completeURL:url];
     [params setLaunchInIncognito:YES];
-    [params setLaunchFocusOmnibox:YES];
+    [params setPostOpeningAction:FOCUS_OMNIBOX];
     return params;
   }
 
diff --git a/ios/chrome/app/chrome_app_startup_parameters_unittest.mm b/ios/chrome/app/chrome_app_startup_parameters_unittest.mm
index 62dd5c33..94bad32 100644
--- a/ios/chrome/app/chrome_app_startup_parameters_unittest.mm
+++ b/ios/chrome/app/chrome_app_startup_parameters_unittest.mm
@@ -161,7 +161,37 @@
       base::StringPrintf("%s://%s/", kChromeUIScheme, kChromeUINewTabHost);
 
   EXPECT_EQ(expectedUrlString, [params externalURL].spec());
-  EXPECT_TRUE([params launchVoiceSearch]);
+  EXPECT_EQ([params postOpeningAction], START_VOICE_SEARCH);
+}
+
+TEST_F(AppStartupParametersTest, ParseURLWithAppGroupQRCode) {
+  ChromeAppStartupParameters* params =
+      [ChromeAppStartupParameters newAppStartupParametersForCommand:@"qrscanner"
+                                                      withParameter:nil
+                                                            withURL:nil
+                                              fromSourceApplication:nil
+                                        fromSecureSourceApplication:nil];
+
+  std::string expectedUrlString =
+      base::StringPrintf("%s://%s/", kChromeUIScheme, kChromeUINewTabHost);
+
+  EXPECT_EQ(expectedUrlString, [params externalURL].spec());
+  EXPECT_EQ([params postOpeningAction], START_QR_CODE_SCANNER);
+}
+
+TEST_F(AppStartupParametersTest, ParseURLWithAppGroupFocusOmbnibox) {
+  ChromeAppStartupParameters* params = [ChromeAppStartupParameters
+      newAppStartupParametersForCommand:@"focusomnibox"
+                          withParameter:nil
+                                withURL:nil
+                  fromSourceApplication:nil
+            fromSecureSourceApplication:nil];
+
+  std::string expectedUrlString =
+      base::StringPrintf("%s://%s/", kChromeUIScheme, kChromeUINewTabHost);
+
+  EXPECT_EQ(expectedUrlString, [params externalURL].spec());
+  EXPECT_EQ([params postOpeningAction], FOCUS_OMNIBOX);
 }
 
 TEST_F(AppStartupParametersTest, ParseURLWithAppGroupNewTab) {
@@ -175,7 +205,7 @@
       base::StringPrintf("%s://%s/", kChromeUIScheme, kChromeUINewTabHost);
 
   EXPECT_EQ(expectedUrlString, [params externalURL].spec());
-  EXPECT_FALSE([params launchVoiceSearch]);
+  EXPECT_EQ([params postOpeningAction], NO_ACTION);
 }
 
 TEST_F(AppStartupParametersTest, ParseURLWithAppGroupOpenURL) {
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm
index 4f7a0546..bb4a6ac 100644
--- a/ios/chrome/app/main_application_delegate.mm
+++ b/ios/chrome/app/main_application_delegate.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/app/main_application_delegate.h"
 
+#include "base/ios/ios_util.h"
 #include "base/mac/foundation_util.h"
 #import "ios/chrome/app/application_delegate/app_navigation.h"
 #import "ios/chrome/app/application_delegate/app_state.h"
@@ -244,6 +245,8 @@
 
   BOOL applicationActive =
       [application applicationState] == UIApplicationStateActive;
+  DCHECK(applicationActive || !base::ios::IsRunningOnIOS11OrLater());
+
   return [URLOpener openURL:url
           applicationActive:applicationActive
                     options:options
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 457976d..821bb10 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -217,11 +217,6 @@
   GetApplicationContext()->GetCRLSetFetcher()->StartInitialLoad(cus, path);
 }
 
-// Returns YES if |url| matches chrome://newtab.
-BOOL IsURLNtp(const GURL& url) {
-  return UrlHasChromeScheme(url) && url.host() == kChromeUINewTabHost;
-}
-
 // Used to update the current BVC mode if a new tab is added while the stack
 // view is being dimissed.  This is different than ApplicationMode in that it
 // can be set to |NONE| when not in use.
@@ -349,11 +344,8 @@
 // A property to track whether the QR Scanner should be started upon tab
 // switcher dismissal. It can only be YES if the QR Scanner experiment is
 // enabled.
-@property(nonatomic, readwrite) BOOL startQRScannerAfterTabSwitcherDismissal;
-// Whether the QR Scanner should be started upon tab switcher dismissal.
-@property(nonatomic, readwrite) BOOL startVoiceSearchAfterTabSwitcherDismissal;
-// Whether the omnibox should be focused upon tab switcher dismissal.
-@property(nonatomic, readwrite) BOOL startFocusOmniboxAfterTabSwitcherDismissal;
+@property(nonatomic, readwrite)
+    NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal;
 
 // Activates browsing and enables web views if |enabled| is YES.
 // Disables browsing and purges web views if |enabled| is NO.
@@ -524,12 +516,8 @@
 @synthesize window = _window;
 @synthesize isPresentingFirstRunUI = _isPresentingFirstRunUI;
 @synthesize isColdStart = _isColdStart;
-@synthesize startVoiceSearchAfterTabSwitcherDismissal =
-    _startVoiceSearchAfterTabSwitcherDismissal;
-@synthesize startQRScannerAfterTabSwitcherDismissal =
-    _startQRScannerAfterTabSwitcherDismissal;
-@synthesize startFocusOmniboxAfterTabSwitcherDismissal =
-    _startFocusOmniboxAfterTabSwitcherDismissal;
+@synthesize NTPActionAfterTabSwitcherDismissal =
+    _NTPActionAfterTabSwitcherDismissal;
 @synthesize launchOptions = _launchOptions;
 @synthesize startupParameters = _startupParameters;
 @synthesize metricsMediator = _metricsMediator;
@@ -1832,17 +1820,11 @@
   // Displaying the current BVC dismisses the stack view.
   [self displayCurrentBVC];
 
-  // Start Voice Search or QR Scanner now that they can be presented from the
-  // current BVC.
-  if (self.startVoiceSearchAfterTabSwitcherDismissal) {
-    self.startVoiceSearchAfterTabSwitcherDismissal = NO;
-    [self.currentBVC startVoiceSearchWithOriginView:nil];
-  } else if (self.startQRScannerAfterTabSwitcherDismissal) {
-    self.startQRScannerAfterTabSwitcherDismissal = NO;
-    [self.currentBVC.dispatcher showQRScanner];
-  } else if (self.startFocusOmniboxAfterTabSwitcherDismissal) {
-    self.startFocusOmniboxAfterTabSwitcherDismissal = NO;
-    [self.currentBVC focusOmnibox];
+  ProceduralBlock action = [self completionBlockForTriggeringAction:
+                                     self.NTPActionAfterTabSwitcherDismissal];
+  self.NTPActionAfterTabSwitcherDismissal = NO_ACTION;
+  if (action) {
+    action();
   }
 
   [_tabSwitcherController setDelegate:nil];
@@ -2176,6 +2158,26 @@
   return newTab;
 }
 
+- (ProceduralBlock)completionBlockForTriggeringAction:
+    (NTPTabOpeningPostOpeningAction)action {
+  switch (action) {
+    case START_VOICE_SEARCH:
+      return ^{
+        [self startVoiceSearchInCurrentBVCWithOriginView:nil];
+      };
+    case START_QR_CODE_SCANNER:
+      return ^{
+        [self.currentBVC.dispatcher showQRScanner];
+      };
+    case FOCUS_OMNIBOX:
+      return ^{
+        [self.currentBVC focusOmnibox];
+      };
+    default:
+      return nil;
+  }
+}
+
 - (Tab*)openSelectedTabInMode:(ApplicationMode)targetMode
                       withURL:(const GURL&)url
                    transition:(ui::PageTransition)transition {
@@ -2183,33 +2185,11 @@
       targetMode == ApplicationMode::NORMAL ? self.mainBVC : self.otrBVC;
   NSUInteger tabIndex = NSNotFound;
 
-  // Commands are only allowed on NTP and there must be at most one command.
-  DCHECK_GE(
-      1,
-      (IsURLNtp(url) ? 0 : 1) +  // Not NTP URL
-          ([_startupParameters launchVoiceSearch] ? 1
-                                                  : 0) +  // Open Voice Search
-          ([_startupParameters launchQRScanner] ? 1
-                                                : 0) +  // Launch QR Code search
-          ([_startupParameters launchFocusOmnibox] ? 1 : 0)  // Focus Omnibox
-      );
-
-  ProceduralBlock tabOpenedCompletion;
-  if ([_startupParameters launchVoiceSearch]) {
-    tabOpenedCompletion = ^{
-      [self startVoiceSearchInCurrentBVCWithOriginView:nil];
-    };
-  }
-  if ([_startupParameters launchQRScanner]) {
-    tabOpenedCompletion = ^{
-      [targetBVC.dispatcher showQRScanner];
-    };
-  }
-  if ([_startupParameters launchFocusOmnibox]) {
-    tabOpenedCompletion = ^{
-      [targetBVC focusOmnibox];
-    };
-  }
+  ProceduralBlock tabOpenedCompletion =
+      [self completionBlockForTriggeringAction:[_startupParameters
+                                                   postOpeningAction]];
+  // Commands are only allowed on NTP.
+  DCHECK(IsURLNtp(url) || !tabOpenedCompletion);
 
   Tab* tab = nil;
   if (_tabSwitcherIsActive) {
@@ -2228,12 +2208,8 @@
     } else {
       // Voice search, QRScanner and the omnibox are presented by the BVC.
       // They must be started after the BVC view is added in the hierarchy.
-      self.startVoiceSearchAfterTabSwitcherDismissal =
-          [_startupParameters launchVoiceSearch];
-      self.startQRScannerAfterTabSwitcherDismissal =
-          [_startupParameters launchQRScanner];
-      self.startFocusOmniboxAfterTabSwitcherDismissal =
-          [_startupParameters launchFocusOmnibox];
+      self.NTPActionAfterTabSwitcherDismissal =
+          [_startupParameters postOpeningAction];
       tab = [_tabSwitcherController
           dismissWithNewTabAnimationToModel:targetBVC.tabModel
                                     withURL:url
diff --git a/ios/chrome/app/spotlight/actions_spotlight_manager.mm b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
index 98e2e613..153fa99d 100644
--- a/ios/chrome/app/spotlight/actions_spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
@@ -77,13 +77,13 @@
     UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
                               SPOTLIGHT_ACTION_VOICE_SEARCH_PRESSED,
                               SPOTLIGHT_ACTION_COUNT);
-    [startupParams setLaunchVoiceSearch:YES];
+    [startupParams setPostOpeningAction:START_VOICE_SEARCH];
   } else if ([action isEqualToString:base::SysUTF8ToNSString(
                                          kSpotlightActionQRScanner)]) {
     UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
                               SPOTLIGHT_ACTION_QR_CODE_SCANNER_PRESSED,
                               SPOTLIGHT_ACTION_COUNT);
-    [startupParams setLaunchQRScanner:YES];
+    [startupParams setPostOpeningAction:START_QR_CODE_SCANNER];
   } else if ([action isEqualToString:base::SysUTF8ToNSString(
                                          kSpotlightActionNewTab)]) {
     UMA_HISTOGRAM_ENUMERATION(kSpotlightActionsHistogram,
diff --git a/ios/chrome/browser/app_startup_parameters.h b/ios/chrome/browser/app_startup_parameters.h
index c732c7c..547a79ea 100644
--- a/ios/chrome/browser/app_startup_parameters.h
+++ b/ios/chrome/browser/app_startup_parameters.h
@@ -7,6 +7,15 @@
 
 #import <Foundation/Foundation.h>
 
+enum NTPTabOpeningPostOpeningAction {
+  // No action should be done
+  NO_ACTION = 0,
+  START_VOICE_SEARCH,
+  START_QR_CODE_SCANNER,
+  FOCUS_OMNIBOX,
+  NTP_TAB_OPENING_POST_OPENING_ACTION_COUNT,
+};
+
 class GURL;
 
 // This class stores all the parameters relevant to the app startup in case
@@ -16,14 +25,16 @@
 // The URL received that should be opened.
 @property(nonatomic, readonly, assign) const GURL& externalURL;
 
-// Boolean to track if a voice search is requested at startup.
-@property(nonatomic, readwrite, assign) BOOL launchVoiceSearch;
+//// Boolean to track if a voice search is requested at startup.
+//@property(nonatomic, readwrite, assign) BOOL launchVoiceSearch;
 // Boolean to track if the app should launch in incognito mode.
 @property(nonatomic, readwrite, assign) BOOL launchInIncognito;
-// Boolean to track if the omnibox should be focused on startup.
-@property(nonatomic, readwrite, assign) BOOL launchFocusOmnibox;
-// Boolean to track if a QR scanner is requested at startup.
-@property(nonatomic, readwrite, assign) BOOL launchQRScanner;
+//// Boolean to track if the omnibox should be focused on startup.
+//@property(nonatomic, readwrite, assign) BOOL launchFocusOmnibox;
+//// Boolean to track if a QR scanner is requested at startup.
+//@property(nonatomic, readwrite, assign) BOOL launchQRScanner;
+@property(nonatomic, readwrite, assign)
+    NTPTabOpeningPostOpeningAction postOpeningAction;
 
 - (instancetype)init NS_UNAVAILABLE;
 
diff --git a/ios/chrome/browser/app_startup_parameters.mm b/ios/chrome/browser/app_startup_parameters.mm
index 54e2ec7..742ca53 100644
--- a/ios/chrome/browser/app_startup_parameters.mm
+++ b/ios/chrome/browser/app_startup_parameters.mm
@@ -14,10 +14,8 @@
   GURL _externalURL;
 }
 
-@synthesize launchVoiceSearch = _launchVoiceSearch;
+@synthesize postOpeningAction = _postOpeningAction;
 @synthesize launchInIncognito = _launchInIncognito;
-@synthesize launchFocusOmnibox = _launchFocusOmnibox;
-@synthesize launchQRScanner = _launchQRScanner;
 
 - (const GURL&)externalURL {
   return _externalURL;
@@ -35,21 +33,22 @@
   NSMutableString* description =
       [NSMutableString stringWithFormat:@"AppStartupParameters: %s",
                                         _externalURL.spec().c_str()];
-
-  if (self.launchQRScanner) {
-    [description appendString:@", should launch QR scanner"];
-  }
-
   if (self.launchInIncognito) {
     [description appendString:@", should launch in incognito"];
   }
 
-  if (self.launchFocusOmnibox) {
-    [description appendString:@", should focus omnibox"];
-  }
-
-  if (self.launchVoiceSearch) {
-    [description appendString:@", should launch voice search"];
+  switch (self.postOpeningAction) {
+    case START_QR_CODE_SCANNER:
+      [description appendString:@", should launch QR scanner"];
+      break;
+    case START_VOICE_SEARCH:
+      [description appendString:@", should launch voice search"];
+      break;
+    case FOCUS_OMNIBOX:
+      [description appendString:@", should focus omnibox"];
+      break;
+    default:
+      break;
   }
 
   return description;
diff --git a/ios/chrome/browser/chrome_url_util.h b/ios/chrome/browser/chrome_url_util.h
index 6d24765..4579acf 100644
--- a/ios/chrome/browser/chrome_url_util.h
+++ b/ios/chrome/browser/chrome_url_util.h
@@ -18,6 +18,9 @@
 bool UrlHasChromeScheme(const GURL& url);
 bool UrlHasChromeScheme(NSURL* url);
 
+// Returns YES if |url| matches chrome://newtab.
+bool IsURLNtp(const GURL& url);
+
 // Returns true if |scheme| is handled in Chrome, or by default handlers in
 // net::URLRequest.
 bool IsHandledProtocol(const std::string& scheme);
diff --git a/ios/chrome/browser/chrome_url_util.mm b/ios/chrome/browser/chrome_url_util.mm
index fa95738..583bc16 100644
--- a/ios/chrome/browser/chrome_url_util.mm
+++ b/ios/chrome/browser/chrome_url_util.mm
@@ -34,6 +34,10 @@
   return net::UrlSchemeIs(url, base::SysUTF8ToNSString(kChromeUIScheme));
 }
 
+bool IsURLNtp(const GURL& url) {
+  return UrlHasChromeScheme(url) && url.host() == kChromeUINewTabHost;
+}
+
 bool IsHandledProtocol(const std::string& scheme) {
   DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
   if (scheme == url::kAboutScheme)
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
index 3fc7f03..f404699d9 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -15,6 +15,7 @@
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
+#import "ios/chrome/browser/ui/commands/reading_list_add_command.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
 #include "ios/chrome/browser/ui/ui_util.h"
@@ -37,6 +38,7 @@
 #import "ios/web/public/test/http_server/http_server.h"
 #include "ios/web/public/test/http_server/http_server_util.h"
 #import "ios/web/public/test/web_view_content_test_util.h"
+#import "ios/web/public/web_state/web_state.h"
 #include "net/base/network_change_notifier.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -237,8 +239,20 @@
 // Adds the current page to the Reading List.
 void AddCurrentPageToReadingList() {
   // Add the page to the reading list.
-  [ChromeEarlGreyUI openShareMenu];
-  TapButtonWithID(IDS_IOS_SHARE_MENU_READING_LIST_ACTION);
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    // On iOS 11, it is not possible to interact with the share menu in EG.
+    // Send directly the command instead. This is the closest behavior we can
+    // have from the normal behavior.
+    web::WebState* web_state = chrome_test_util::GetCurrentWebState();
+    ReadingListAddCommand* command = [[ReadingListAddCommand alloc]
+        initWithURL:web_state->GetVisibleURL()
+              title:base::SysUTF16ToNSString(web_state->GetTitle())];
+    [chrome_test_util::DispatcherForActiveViewController()
+        addToReadingList:command];
+  } else {
+    [ChromeEarlGreyUI openShareMenu];
+    TapButtonWithID(IDS_IOS_SHARE_MENU_READING_LIST_ACTION);
+  }
 
   // Wait for the snackbar to appear.
   id<GREYMatcher> snackbar_matcher =
@@ -398,12 +412,6 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads offline version via context menu.
 - (void)testSavingToReadingListAndLoadDistilled {
-  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
-  // interact with the share menu.
-  if (base::ios::IsRunningOnIOS11OrLater()) {
-    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
-  }
-
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
@@ -452,12 +460,6 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads online version by tapping on entry.
 - (void)testSavingToReadingListAndLoadNormal {
-  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
-  // interact with the share menu.
-  if (base::ios::IsRunningOnIOS11OrLater()) {
-    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
-  }
-
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
@@ -497,12 +499,6 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads offline version by tapping on entry without web server.
 - (void)testSavingToReadingListAndLoadNoNetwork {
-  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
-  // interact with the share menu.
-  if (base::ios::IsRunningOnIOS11OrLater()) {
-    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
-  }
-
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
@@ -547,12 +543,6 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads offline version by tapping on entry with delayed web server.
 - (void)testSavingToReadingListAndLoadBadNetwork {
-  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
-  // interact with the share menu.
-  if (base::ios::IsRunningOnIOS11OrLater()) {
-    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
-  }
-
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
diff --git a/media/base/media_observer.h b/media/base/media_observer.h
index f82c387..5037c853 100644
--- a/media/base/media_observer.h
+++ b/media/base/media_observer.h
@@ -27,6 +27,11 @@
   // Reports the latest compatibility state of the element's source for remote
   // playback.
   virtual void UpdateRemotePlaybackCompatibility(bool is_compatible) = 0;
+
+  // Gets the number of audio/video bytes decoded so far from media pipeline.
+  // The count keeps increasing and will not be reset during seek.
+  virtual size_t AudioDecodedByteCount() const = 0;
+  virtual size_t VideoDecodedByteCount() const = 0;
 };
 
 // This class is an observer of media player events.
diff --git a/media/remoting/metrics.cc b/media/remoting/metrics.cc
index 2320f4b..566fc2f 100644
--- a/media/remoting/metrics.cc
+++ b/media/remoting/metrics.cc
@@ -137,18 +137,21 @@
   remote_playback_is_disabled_ = disabled;
 }
 
-void SessionMetricsRecorder::OnPosterImageDownloaded(
-    base::TimeDelta download_duration,
-    bool success) {
-  const std::string name = success
-                               ? "Media.Remoting.PosterDownloadDuration.Success"
-                               : "Media.Remoting.PosterDownloadDuration.Fail";
-  // Note: Not using UMA_HISTOGRAM_CUSTOM_TIMES because |name| is a variable in
-  // in this instance; and so the "one histogram" static local should not be
-  // created.
-  base::UmaHistogramCustomTimes(name, download_duration,
-                                base::TimeDelta::FromMilliseconds(10),
-                                base::TimeDelta::FromSeconds(30), 50);
+void SessionMetricsRecorder::RecordMediaBitrateVersusCapacity(
+    double kilobits_per_second,
+    double capacity) {
+  UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.StartMediaBitrate",
+                              kilobits_per_second, 1, 16 * 1024, 50);
+  UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.TransmissionCapacity", capacity,
+                              1, 16 * 1024, 50);
+  double remaining = capacity - kilobits_per_second;
+  if (remaining >= 0) {
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.CapacityOverMediaBitrate",
+                                remaining, 1, 16 * 1024, 50);
+  } else {
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.MediaBitrateOverCapacity",
+                                -remaining, 1, 16 * 1024, 50);
+  }
 }
 
 void SessionMetricsRecorder::RecordAudioConfiguration() {
diff --git a/media/remoting/metrics.h b/media/remoting/metrics.h
index 6da6bf0..e52b2ae 100644
--- a/media/remoting/metrics.h
+++ b/media/remoting/metrics.h
@@ -31,8 +31,8 @@
   // These may be called before, during, or after a remoting session.
   void OnPipelineMetadataChanged(const PipelineMetadata& metadata);
   void OnRemotePlaybackDisabled(bool disabled);
-  void OnPosterImageDownloaded(const base::TimeDelta download_duration,
-                               bool success);
+  void RecordMediaBitrateVersusCapacity(double kilobits_per_second,
+                                        double capacity);
 
  private:
   // Whether audio only, video only, or both were played during the session.
diff --git a/media/remoting/renderer_controller.cc b/media/remoting/renderer_controller.cc
index 2e26ecfeb..8b3dd5ee 100644
--- a/media/remoting/renderer_controller.cc
+++ b/media/remoting/renderer_controller.cc
@@ -7,6 +7,8 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/threading/thread_checker.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "media/remoting/remoting_cdm.h"
@@ -20,13 +22,21 @@
 namespace remoting {
 
 namespace {
+
 // The duration to delay the start of media remoting to ensure all preconditions
 // are held stable before switching to media remoting.
 constexpr base::TimeDelta kDelayedStart = base::TimeDelta::FromSeconds(5);
+
+// The maximum fraction of the transmission capacity that can safely be used by
+// Media Remoting to deliver the media contents.
+constexpr double kMaxMediaBitrateCapacityFraction = 0.9;
+
 }  // namespace
 
 RendererController::RendererController(scoped_refptr<SharedSession> session)
-    : session_(std::move(session)), weak_factory_(this) {
+    : session_(std::move(session)),
+      clock_(new base::DefaultTickClock()),
+      weak_factory_(this) {
   session_->AddClient(this);
 }
 
@@ -401,27 +411,44 @@
   DCHECK(!is_encrypted_);
   delayed_start_stability_timer_.Start(
       FROM_HERE, kDelayedStart,
-      base::Bind(&RendererController::OnDelayedStartTimerFired,
-                 base::Unretained(this), start_trigger));
-
-  // TODO(xjz): Start content bitrate estimation.
+      base::Bind(
+          &RendererController::OnDelayedStartTimerFired, base::Unretained(this),
+          start_trigger,
+          client_->AudioDecodedByteCount() + client_->VideoDecodedByteCount(),
+          clock_->NowTicks()));
 }
 
 void RendererController::CancelDelayedStart() {
   delayed_start_stability_timer_.Stop();
-
-  // TODO(xjz): Stop content bitrate estimation.
 }
 
-void RendererController::OnDelayedStartTimerFired(StartTrigger start_trigger) {
+void RendererController::OnDelayedStartTimerFired(
+    StartTrigger start_trigger,
+    size_t decoded_bytes_before_delay,
+    base::TimeTicks delayed_start_time) {
   DCHECK(is_dominant_content_);
   DCHECK(!remote_rendering_started_);
   DCHECK(!is_encrypted_);
 
-  // TODO(xjz): Stop content bitrate estimation and evaluate whether the
-  // estimated bitrate is supported by remoting.
-
-  StartRemoting(start_trigger);
+  base::TimeDelta elapsed = clock_->NowTicks() - delayed_start_time;
+  DCHECK(!elapsed.is_zero());
+  double kilobits_per_second =
+      (client_->AudioDecodedByteCount() + client_->VideoDecodedByteCount() -
+       decoded_bytes_before_delay) *
+      8.0 / elapsed.InSecondsF() / 1000.0;
+  DCHECK_GE(kilobits_per_second, 0);
+  // TODO(xjz): Gets the estimated transmission capacity (kbps) from Remoter.
+  const double capacity = 10000.0;
+  metrics_recorder_.RecordMediaBitrateVersusCapacity(kilobits_per_second,
+                                                     capacity);
+  if (kilobits_per_second <= kMaxMediaBitrateCapacityFraction * capacity) {
+    StartRemoting(start_trigger);
+  } else {
+    VLOG(1) << "Media remoting is not supported: bitrate(kbps)="
+            << kilobits_per_second
+            << " transmission_capacity(kbps)=" << capacity;
+    encountered_renderer_fatal_error_ = true;
+  }
 }
 
 void RendererController::StartRemoting(StartTrigger start_trigger) {
diff --git a/media/remoting/renderer_controller.h b/media/remoting/renderer_controller.h
index 4b3cf03..40d93cd 100644
--- a/media/remoting/renderer_controller.h
+++ b/media/remoting/renderer_controller.h
@@ -15,6 +15,10 @@
 #include "media/remoting/metrics.h"
 #include "media/remoting/shared_session.h"
 
+namespace base {
+class TickClock;
+}
+
 namespace media {
 
 namespace remoting {
@@ -117,8 +121,12 @@
   void WaitForStabilityBeforeStart(StartTrigger start_trigger);
   // Cancel the start of remoting.
   void CancelDelayedStart();
-  // Called when |delayed_start_stability_timer_| is fired.
-  void OnDelayedStartTimerFired(StartTrigger start_trigger);
+  // Called when the delayed start ends. |decoded_bytes_before_delay| is the
+  // total number of audio and video bytes decoded before the delayed start
+  // began. |delayed_start_time| is the time that the delayed start began.
+  void OnDelayedStartTimerFired(StartTrigger start_trigger,
+                                size_t decoded_bytes_before_delay,
+                                base::TimeTicks delayed_start_time);
 
   // Helper to request the media pipeline switch to the remoting renderer.
   void StartRemoting(StartTrigger start_trigger);
@@ -180,6 +188,8 @@
   // remote the content while this timer is running.
   base::OneShotTimer delayed_start_stability_timer_;
 
+  std::unique_ptr<base::TickClock> clock_;
+
   base::WeakPtrFactory<RendererController> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RendererController);
diff --git a/media/remoting/renderer_controller_unittest.cc b/media/remoting/renderer_controller_unittest.cc
index 39f44e0..417c5a6 100644
--- a/media/remoting/renderer_controller_unittest.cc
+++ b/media/remoting/renderer_controller_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/simple_test_tick_clock.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/cdm_config.h"
 #include "media/base/limits.h"
@@ -56,6 +57,11 @@
   return metadata;
 }
 
+constexpr base::TimeDelta kDelayedStartDuration =
+    base::TimeDelta::FromSeconds(5);
+constexpr double kNormalSpeedBitsPerSecond = 5000000;
+constexpr double kHighSpeedBitsPerSecond = 15000000;
+
 }  // namespace
 
 class RendererControllerTest : public ::testing::Test,
@@ -72,12 +78,17 @@
   void SwitchRenderer(bool disable_pipeline_auto_suspend) override {
     is_rendering_remotely_ = disable_pipeline_auto_suspend;
     disable_pipeline_suspend_ = disable_pipeline_auto_suspend;
+    decoded_bytes_ = 0;
   }
 
   void ActivateViewportIntersectionMonitoring(bool activate) override {
     activate_viewport_intersection_monitoring_ = activate;
   }
 
+  size_t VideoDecodedByteCount() const override { return decoded_bytes_; }
+
+  size_t AudioDecodedByteCount() const override { return 0; }
+
   void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
 
   void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
@@ -88,6 +99,9 @@
       const mojom::RemotingSinkMetadata& sink_metadata) {
     EXPECT_FALSE(is_rendering_remotely_);
     controller_ = base::MakeUnique<RendererController>(shared_session);
+    clock_ = new base::SimpleTestTickClock();
+    controller_->clock_.reset(clock_);
+    clock_->Advance(base::TimeDelta::FromSeconds(1));
     controller_->SetClient(this);
     RunUntilIdle();
     EXPECT_FALSE(is_rendering_remotely_);
@@ -117,8 +131,17 @@
     return controller_->delayed_start_stability_timer_.IsRunning();
   }
 
-  void DelayedStartEnds() {
+  void DelayedStartEnds(bool too_high_bitrate) {
     EXPECT_TRUE(IsInDelayedStart());
+    if (too_high_bitrate) {
+      decoded_bytes_ =
+          kHighSpeedBitsPerSecond * kDelayedStartDuration.InSeconds() / 8.0;
+    } else {
+      decoded_bytes_ =
+          kNormalSpeedBitsPerSecond * kDelayedStartDuration.InSeconds() / 8.0;
+    }
+    clock_->Advance(kDelayedStartDuration);
+    RunUntilIdle();
     const base::Closure callback =
         controller_->delayed_start_stability_timer_.user_task();
     callback.Run();
@@ -133,6 +156,8 @@
   bool is_remoting_cdm_ = false;
   bool activate_viewport_intersection_monitoring_ = false;
   bool disable_pipeline_suspend_ = false;
+  size_t decoded_bytes_ = 0;
+  base::SimpleTestTickClock* clock_;  // Own by |controller_|;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
@@ -146,7 +171,7 @@
                                         GetDefaultSinkMetadata(true));
   EXPECT_FALSE(is_rendering_remotely_);
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);  // All requirements now satisfied.
   EXPECT_TRUE(disable_pipeline_suspend_);
@@ -159,6 +184,21 @@
   EXPECT_FALSE(activate_viewport_intersection_monitoring_);
 }
 
+TEST_F(RendererControllerTest, StartFailedWithTooHighBitrate) {
+  const scoped_refptr<SharedSession> shared_session =
+      FakeRemoterFactory::CreateSharedSession(false);
+  InitializeControllerAndBecomeDominant(shared_session,
+                                        DefaultMetadata(VideoCodec::kCodecVP8),
+                                        GetDefaultSinkMetadata(true));
+  EXPECT_FALSE(is_rendering_remotely_);
+  EXPECT_TRUE(IsInDelayedStart());
+  DelayedStartEnds(true);
+  RunUntilIdle();
+  EXPECT_TRUE(activate_viewport_intersection_monitoring_);
+  EXPECT_FALSE(is_rendering_remotely_);
+  EXPECT_FALSE(disable_pipeline_suspend_);
+}
+
 TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
   EXPECT_FALSE(is_rendering_remotely_);
   const scoped_refptr<SharedSession> shared_session =
@@ -186,7 +226,7 @@
   EXPECT_FALSE(is_rendering_remotely_);
   EXPECT_FALSE(disable_pipeline_suspend_);
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);
   EXPECT_TRUE(disable_pipeline_suspend_);
@@ -201,7 +241,7 @@
                                         GetDefaultSinkMetadata(true));
   EXPECT_TRUE(activate_viewport_intersection_monitoring_);
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);  // All requirements now satisfied.
   EXPECT_TRUE(disable_pipeline_suspend_);
@@ -236,7 +276,7 @@
   shared_session->OnSinkAvailable(sink_metadata.Clone());
   RunUntilIdle();
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);  // All requirements now satisfied.
   EXPECT_TRUE(activate_viewport_intersection_monitoring_);
@@ -268,7 +308,7 @@
   shared_session->OnSinkAvailable(sink_metadata.Clone());
   RunUntilIdle();
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);  // All requirements now satisfied.
   EXPECT_TRUE(activate_viewport_intersection_monitoring_);
@@ -303,7 +343,7 @@
   shared_session->OnSinkAvailable(sink_metadata.Clone());
   RunUntilIdle();
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);  // All requirements now satisfied.
   EXPECT_TRUE(activate_viewport_intersection_monitoring_);
@@ -336,7 +376,7 @@
   shared_session->OnSinkAvailable(sink_metadata.Clone());
   RunUntilIdle();
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_TRUE(is_rendering_remotely_);  // All requirements now satisfied.
   EXPECT_TRUE(activate_viewport_intersection_monitoring_);
@@ -351,7 +391,7 @@
                                         GetDefaultSinkMetadata(true));
   RunUntilIdle();
   EXPECT_TRUE(IsInDelayedStart());
-  DelayedStartEnds();
+  DelayedStartEnds(false);
   RunUntilIdle();
   EXPECT_FALSE(is_rendering_remotely_);
   EXPECT_FALSE(disable_pipeline_suspend_);
diff --git a/third_party/WebKit/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt
index a444a97..5d16c5c 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/MutationObserver/mutation-observer-constructor-expected.txt
@@ -8,10 +8,10 @@
 PASS typeof WebKitMutationObserver.prototype.disconnect is "function"
 PASS typeof observer.observe is "function"
 PASS typeof observer.disconnect is "function"
-PASS new MutationObserver({ handleEvent: function() {} }) threw exception TypeError: Failed to construct 'MutationObserver': Callback argument must be a function.
-PASS new MutationObserver({}) threw exception TypeError: Failed to construct 'MutationObserver': Callback argument must be a function.
-PASS new MutationObserver(42) threw exception TypeError: Failed to construct 'MutationObserver': Callback argument must be a function.
-PASS new MutationObserver("foo") threw exception TypeError: Failed to construct 'MutationObserver': Callback argument must be a function.
+PASS new MutationObserver({ handleEvent: function() {} }) threw exception TypeError: Failed to construct 'MutationObserver': The callback provided as parameter 1 is not a function..
+PASS new MutationObserver({}) threw exception TypeError: Failed to construct 'MutationObserver': The callback provided as parameter 1 is not a function..
+PASS new MutationObserver(42) threw exception TypeError: Failed to construct 'MutationObserver': The callback provided as parameter 1 is not a function..
+PASS new MutationObserver("foo") threw exception TypeError: Failed to construct 'MutationObserver': The callback provided as parameter 1 is not a function..
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-toString-using-defineGetter.html b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-toString-using-defineGetter.html
index d299c7d..5bd4273f 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-toString-using-defineGetter.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-toString-using-defineGetter.html
@@ -5,9 +5,11 @@
 </head>
 <body>
 <script>
-    window.location.__defineGetter__("toString", function () {
-        return function() { return "haxored"; }
-    });
+    try {
+        window.location.__defineGetter__("toString", function () {
+            return function() { return "haxored"; }
+        });
+    } catch (e) { }
 
     var result = normalizeURL(String(window.location));
     var correctValue = normalizeURL(document.URL);
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-valueOf-using-defineGetter.html b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-valueOf-using-defineGetter.html
index ed38c92b..52dc3fa 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-valueOf-using-defineGetter.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/location-override-valueOf-using-defineGetter.html
@@ -5,13 +5,15 @@
 </head>
 <body>
 <script>
-    window.location.__defineGetter__("valueOf", function () {
-        return function() { return "haxored"; }
-    });
+    try {
+        window.location.__defineGetter__("valueOf", function () {
+            return function() { return "haxored"; }
+        });
+    } catch (e) { }
 
     var result = normalizeURL(String(window.location));
     var correctValue = normalizeURL(document.URL);
     shouldBe("result", "correctValue");
 </script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-location-using-defineGetter.html b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-location-using-defineGetter.html
index da994b3..5c45513 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-location-using-defineGetter.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-location-using-defineGetter.html
@@ -5,11 +5,13 @@
 </head>
 <body>
 <script>
-    window.__defineGetter__("location", function() { return "haxored"; });
+    try {
+        window.__defineGetter__("location", function() { return "haxored"; });
+    } catch (e) { }
 
     var result = normalizeURL(String(window.location));
     var correctValue = normalizeURL(document.URL);
     shouldBe("result", "correctValue");
 </script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-window-using-defineGetter.html b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-window-using-defineGetter.html
index 4b0f51d7..ca72223 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-window-using-defineGetter.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/Location/window-override-window-using-defineGetter.html
@@ -5,9 +5,11 @@
 </head>
 <body>
 <script>
-    window.__defineGetter__("window", function() {
-        return { location: "haxored" };
-    });
+    try {
+        window.__defineGetter__("window", function() {
+            return { location: "haxored" };
+        });
+    } catch (e) { }
 
     var result = normalizeURL(String(window.location));
     var correctValue = normalizeURL(document.URL);
diff --git a/third_party/WebKit/LayoutTests/fast/dom/getter-on-window-object2.html b/third_party/WebKit/LayoutTests/fast/dom/getter-on-window-object2.html
index 67d3fc05..2e7b2216f 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/getter-on-window-object2.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/getter-on-window-object2.html
@@ -6,7 +6,7 @@
 var x = 1;
 try {
     window.__defineGetter__("x", function() { return "window.x __getter__"; });
-} catch(e) { debug(e); }
+} catch(e) { }
 
 shouldBe("window.x", "1");
 shouldBe("typeof window.__lookupGetter__('x')", "'undefined'");
@@ -16,7 +16,7 @@
 
 try {
 window.__defineSetter__("x", function() { debug("window.x __setter__ called"); });
-} catch(e) { debug(e); }
+} catch(e) { }
 x = 2;
 
 shouldBe("window.x", "2");
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_fixed-bg-table-expected.txt b/third_party/WebKit/LayoutTests/fast/table/backgr_fixed-bg-table-expected.txt
new file mode 100644
index 0000000..63245c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_fixed-bg-table-expected.txt
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x162
+  LayoutBlockFlow {HTML} at (0,0) size 800x162
+    LayoutBlockFlow {BODY} at (8,16) size 784x138
+      LayoutBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 508x19
+          text run at (0,0) width 508: "crbug.com/35697: The coloured bands show flow seamlessly in the background."
+      LayoutTable {TABLE} at (0,36) size 228x102
+        LayoutTableSection {THEAD} at (0,0) size 228x102
+          LayoutTableRow {TR} at (0,2) size 228x98
+            LayoutTableCell {TH} at (2,50) size 111x2 [r=0 c=0 rs=1 cs=1]
+            LayoutTableCell {TH} at (115,50) size 111x2 [r=0 c=1 rs=1 cs=1]
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_fixed-bg-table.html b/third_party/WebKit/LayoutTests/fast/table/backgr_fixed-bg-table.html
new file mode 100644
index 0000000..7a5e83cd0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_fixed-bg-table.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<style>
+.d {width: 109px}
+.d {height: 96px}
+thead{background:url(resources/rainbowh.gif) fixed;}
+</style>
+<p>crbug.com/35697: The coloured bands show flow seamlessly in the background.</p>
+<table>
+  <thead>
+    <tr class="th-row-1">
+      <th class="d"></th>
+      <th class="d"></th>
+    </tr>
+  </thead>
+</table>
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/permissions/resources/test-query.js b/third_party/WebKit/LayoutTests/http/tests/permissions/resources/test-query.js
index fe16ccd5..5bdec40 100644
--- a/third_party/WebKit/LayoutTests/http/tests/permissions/resources/test-query.js
+++ b/third_party/WebKit/LayoutTests/http/tests/permissions/resources/test-query.js
@@ -25,6 +25,42 @@
 }, 'Test PermissionDescription WebIDL rules in ' + get_current_scope() + ' scope.');
 
 async_test(function(test) {
+    navigator.permissions.query({name:'ambient-light-sensor'}).then(function(result) {
+        assert_true(result instanceof PermissionStatus);
+        test.done();
+    }).catch(function() {
+        assert_unreached('querying ambient-light-sensor permission should not fail.')
+    });
+}, 'Test ambient-light-sensor permission in ' + get_current_scope() + ' scope.');
+
+async_test(function(test) {
+    navigator.permissions.query({name:'accelerometer'}).then(function(result) {
+        assert_true(result instanceof PermissionStatus);
+        test.done();
+    }).catch(function() {
+        assert_unreached('querying accelerometer permission should not fail.')
+    });
+}, 'Test accelerometer permission in ' + get_current_scope() + ' scope.');
+
+async_test(function(test) {
+    navigator.permissions.query({name:'gyroscope'}).then(function(result) {
+        assert_true(result instanceof PermissionStatus);
+        test.done();
+    }).catch(function() {
+        assert_unreached('querying gyroscope permission should not fail.')
+    });
+}, 'Test gyroscope permission in ' + get_current_scope() + ' scope.');
+
+async_test(function(test) {
+    navigator.permissions.query({name:'magnetometer'}).then(function(result) {
+        assert_true(result instanceof PermissionStatus);
+        test.done();
+    }).catch(function() {
+        assert_unreached('querying magnetometer permission should not fail.')
+    });
+}, 'Test magnetometer permission in ' + get_current_scope() + ' scope.');
+
+async_test(function(test) {
     navigator.permissions.query({name:'geolocation'}).then(function(result) {
         assert_true(result instanceof PermissionStatus);
         assert_equals(result.state, 'denied');
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_fixed-bg-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_fixed-bg-table-expected.png
new file mode 100644
index 0000000..2a64b9c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index 0f1ffde9..f1013426 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png
new file mode 100644
index 0000000..2a64b9c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index 413c4cb9..bdaed8e3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index e5ba809..c7184cb 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index 53b04934..71f84e7d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index e5ba809..c7184cb 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png
new file mode 100644
index 0000000..b4b0eb0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index ab523a4..188fe28d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png
new file mode 100644
index 0000000..b4b0eb0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_fixed-bg-table-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_fixed-bg-table-expected.png
new file mode 100644
index 0000000..de7b12a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index 251d2e0..fdb3af9a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png
new file mode 100644
index 0000000..de7b12a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/WebKit/LayoutTests/platform/win7/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index c1f4c6c..70765b0 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioNode/tail-processing.html b/third_party/WebKit/LayoutTests/webaudio/AudioNode/tail-processing.html
deleted file mode 100644
index e04d781..0000000
--- a/third_party/WebKit/LayoutTests/webaudio/AudioNode/tail-processing.html
+++ /dev/null
@@ -1,328 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <title>Test Handling of Tail Processing</title>
-    <script src="../../resources/testharness.js"></script>
-    <script src="../../resources/testharnessreport.js"></script>
-    <script src="../resources/audit.js"></script>
-    <script src="../resources/audit-util.js"></script>
-  </head>
-
-  <body>
-    <script>
-      let audit = Audit.createTaskRunner();
-
-      // Fairly arbitrary but must be a power of two to eliminate roundoff when
-      // we compute times from sample frames
-      const sampleRate = 32768;
-
-      // Fairly arbitrary duration
-      const renderDuration = 0.25;
-      const renderFrames = renderDuration * sampleRate;
-
-      audit.define('hrtf-panner-tail', (task, should) => {
-        runTest('PannerNode', {panningModel: 'HRTF', distanceMode: 'linear'})
-            .then(renderedBuffer => {
-              let prefix = 'HRTF PannerNode';
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let latencyFrame = findLatencyFrame(response);
-              let tailFrame = findTailFrame(response);
-
-              // The HRTF panner has both a latency component and a tail
-              // component.  Make sure both are non-zero.
-              should(latencyFrame, `${prefix} latency frame (${latencyFrame})`)
-                  .beGreaterThan(0);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              // Because of the latency, the output is zero at the beginning.
-              // Make sure this is true.
-              should(
-                  output.slice(0, latencyFrame),
-                  `${prefix} Latency output[0:` + (latencyFrame - 1) + ']')
-                  .beConstantValueOf(0);
-
-              // Verify the rest of the output matches the expected values.  The
-              // output should be non-zero from latencyFrame to tailFrame and
-              // zero after tailFrame.
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: latencyFrame,
-                nonZeroEndFrame: Math.min(tailFrame, output.length),
-                zeroStartFrame: roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-            })
-            .then(() => task.done());
-      });
-
-      audit.define('biquad-tail', (task, should) => {
-        runTest('BiquadFilterNode', {Q: 20, frequency: 100})
-            .then(renderedBuffer => {
-              let prefix = 'BiquadFilter'
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let tailFrame = findTailFrame(response);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              // Verify biquad output which should be non-zero up to tailFrame
-              // and zero afterwards.  However, the actual output isn't after
-              // tailFrame because the internal biquad tail time uses an
-              // approximation.  That's why zeroStartFrame is 128 frames after
-              // tailFrame.
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: 0,
-                nonZeroEndFrame: Math.min(tailFrame + 128, output.length),
-                zeroStartFrame: 128 + roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-            })
-            .then(() => task.done());
-      });
-
-      audit.define('iir-tail', (task, should) => {
-        runTest('IIRFilterNode', {feedforward: [1], feedback: [1, -.99]})
-            .then(renderedBuffer => {
-              let prefix = 'IIRFilter';
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let tailFrame = findTailFrame(response);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: 0,
-                nonZeroEndFrame: Math.min(tailFrame + 128, output.length),
-                zeroStartFrame: 256 + roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-            })
-            .then(() => task.done());
-      });
-
-      audit.define('delay-tail', (task, should) => {
-        // For the test, make sure the delay is greater than one render
-        // quantum.  If it's less we won't be able to tell if tail processing
-        // worked because the input signal is an impulse.
-        let delayFrames = RENDER_QUANTUM_FRAMES + 64;
-        runTest('DelayNode', {delayTime: delayFrames / sampleRate})
-            .then(renderedBuffer => {
-              let prefix = 'Delay';
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let tailFrame = findTailFrame(response);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              // As a delay node with delay time greater than one render
-              // quantum, the first render quantum must be 0.
-              should(output.slice(0, RENDER_QUANTUM_FRAMES),
-                  `${prefix} output[0:` + (RENDER_QUANTUM_FRAMES - 1) + ']')
-                  .beConstantValueOf(0);
-
-              // The output of the delay node should be nonzero in the second
-              // render quantum and zero forever after.
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: RENDER_QUANTUM_FRAMES,
-                nonZeroEndFrame: Math.min(tailFrame, output.length),
-                zeroStartFrame: roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-
-            })
-            .then(() => task.done());
-      });
-
-      audit.define('convolver-tail', (task, should) => {
-        // The convolver response.  It needs to be longer than one render
-        // quantum to show the tail processing.
-        let response = new AudioBuffer({length: RENDER_QUANTUM_FRAMES + 64,
-        sampleRate: sampleRate});
-        // For simplicity, just make the response all ones.
-        response.getChannelData(0).fill(1);
-
-        runTest('ConvolverNode', {disableNormalization: true, buffer: response})
-            .then(renderedBuffer => {
-              let prefix = 'Convolver';
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let tailFrame = findTailFrame(response);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: 0,
-                nonZeroEndFrame: Math.min(tailFrame + 128, output.length),
-                zeroStartFrame: 128 + roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-            })
-            .then(() => task.done());
-      });
-
-      audit.define('dynamics-compressor-tail', (task, should) => {
-        runTest('DynamicsCompressorNode', {})
-            .then(renderedBuffer => {
-              let prefix = 'DyamicsCompressor';
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let tailFrame = findTailFrame(response);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              let latencyFrame = roundDown(tailFrame - 1);
-              should(
-                  output.slice(0, latencyFrame),
-                  `${prefix} output[0:` + (latencyFrame - 1) + ']')
-                  .beConstantValueOf(0);
-
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: latencyFrame,
-                nonZeroEndFrame: Math.min(tailFrame, output.length),
-                zeroStartFrame: roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-
-            })
-            .then(() => task.done());
-      });
-
-      audit.define('waveshaper-tail', (task, should) => {
-        // Fairly arbitrary curve for the WaveShaper
-        let curve = Float32Array.from([-1, -.5, 0, 0.5, 1]);
-
-        runTest('WaveShaperNode', {curve: curve, oversample: '2x'})
-            .then(renderedBuffer => {
-              let prefix = 'WaveShaper';
-              let output = renderedBuffer.getChannelData(0);
-              let response = renderedBuffer.getChannelData(1);
-              let tailFrame = findTailFrame(response);
-
-              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
-                  .beGreaterThan(0);
-
-              verifyOutput(should, output, {
-                prefix: prefix,
-                startFrame: 0,
-                nonZeroEndFrame: Math.min(tailFrame, output.length),
-                zeroStartFrame: roundUp(tailFrame),
-                tailFrame: tailFrame,
-                reference: response
-              });
-            })
-            .then(() => task.done());
-      });
-
-      audit.run();
-
-      function runTest(nodeName, nodeOptions) {
-        // Two-channel output.  Channel 0 is the test result; channel 1 is the
-        // impulse response that is used to figure out when the tail should
-        // start.
-        let context = new OfflineAudioContext(2, sampleRate, sampleRate);
-
-        // Merge channels for the destination.
-        let merger = new ChannelMergerNode(context, {numberOfInputs: 2});
-        merger.connect(context.destination);
-
-        let src = new ConstantSourceNode(context, {offset: 1});
-
-        // Impulse for testing.  We want a full buffer so as not to worry about
-        // the source disconnecting prematurely from the filter.
-        let b = new AudioBuffer(
-            {length: context.length, sampleRate: context.sampleRate});
-        b.getChannelData(0)[0] = 1;
-        let impulse = new AudioBufferSourceNode(context, {buffer: b});
-
-        let testNode = new window[nodeName](context, nodeOptions);
-        let refNode = new window[nodeName](context, nodeOptions);
-
-        src.connect(testNode).connect(merger, 0, 0);
-        impulse.connect(refNode).connect(merger, 0, 1);
-
-        src.start();
-        src.stop(1 / context.sampleRate);
-        impulse.start();
-
-        return context.startRendering();
-      }
-
-      function findTailFrame(response) {
-        let tailFrame = response.length;
-
-        for (let k = response.length - 1; k >= 0; --k) {
-          if (Math.abs(response[k]) > 1 / 32768) {
-            tailFrame = k + 1;
-            break;
-          }
-        }
-
-        return tailFrame;
-      }
-
-      function findLatencyFrame(response) {
-        for (let k = 0; k < response.length; ++k) {
-          if (response[k] != 0)
-            return k;
-        }
-
-        return response.length;
-      }
-
-      function verifyOutput(should, output, options) {
-        let prefix = options.prefix || '';
-        if (options.tailFrame && options.reference) {
-          should(
-              output.slice(0, options.tailFrame),
-              `${prefix} Tail output[0:` + (options.tailFrame - 1) + ']')
-              .beEqualToArray(options.reference.slice(0, options.tailFrame));
-        }
-
-        // Verify that |output| is non-zero between |startFrame| and
-        // |nonZeroEndFrame|.
-        for (let k = options.startFrame; k < options.nonZeroEndFrame;
-             k += 128) {
-          should(
-              output.slice(k, k + 128),
-              `${prefix} output[` + k + ':' + (k + 127) + ']')
-              .notBeConstantValueOf(0);
-        }
-
-        // Verify |output| is zero starting at frame |zeroStartFrame|, inclusive
-        if (options.zeroStartFrame < output.length) {
-          should(
-              output.slice(options.zeroStartFrame),
-              `${prefix} output[` + options.zeroStartFrame + ':]')
-              .beConstantValueOf(0);
-        }
-      }
-
-      function roundDown(frame) {
-        return 128 * Math.floor(frame / 128);
-      }
-
-      function roundUp(frame) {
-        return 128 * Math.ceil(frame / 128);
-      }
-    </script>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/DynamicsCompressor/dynamicscompressor-clear-internal-state.html b/third_party/WebKit/LayoutTests/webaudio/DynamicsCompressor/dynamicscompressor-clear-internal-state.html
index 9c5ae95..34f5cd2 100644
--- a/third_party/WebKit/LayoutTests/webaudio/DynamicsCompressor/dynamicscompressor-clear-internal-state.html
+++ b/third_party/WebKit/LayoutTests/webaudio/DynamicsCompressor/dynamicscompressor-clear-internal-state.html
@@ -17,10 +17,8 @@
       let source;
       let compressor;
 
-      // Use a low sample rate to reduce complexity because we need to run for
-      // quite a few seconds to get the reduction to converge.
-      let sampleRate = 8192;
-      let testDurationSamples = 10 * 8192;
+      let sampleRate = 44100;
+      let testDurationSamples = 44100;
 
       audit.define(
           {
@@ -48,12 +46,8 @@
 
             // Render it!
             context.startRendering().then(() => {
-              // Check that the reduction value sufficiently close to 0.
-              // Threshold experimentally determined.
-              should(
-                  Math.abs(compressor.reduction),
-                  'Math.abs(compressor.reduction)')
-                  .beLessThanOrEqualTo(4.8223e-2);
+              // Check that the reduction value is 0.0.
+              should(compressor.reduction, 'compressor.reduction').beEqualTo(0);
               task.done();
             });
           });
diff --git a/third_party/WebKit/LayoutTests/webaudio/internals/cycle-connection-gc.html b/third_party/WebKit/LayoutTests/webaudio/internals/cycle-connection-gc.html
index 98655e6..caa12aad 100644
--- a/third_party/WebKit/LayoutTests/webaudio/internals/cycle-connection-gc.html
+++ b/third_party/WebKit/LayoutTests/webaudio/internals/cycle-connection-gc.html
@@ -21,16 +21,12 @@
 
       function createCycle() {
         let source = context.createBufferSource();
-        // Can't use DelayNode here because they now have a tail time that keeps
-        // the node handler alive to process the tail.  Use GainNodes instead
-        // because they have no tail time.  (Strictly speaking, there should be
-        // a delay node in the cycle, but we don't enforce this.)
-        let gain1 = context.createGain();
-        let gain2 = context.createGain();
-        source.connect(gain1);
-        gain1.connect(gain2);
-        gain2.connect(gain1);
-        gain1.connect(context.destination);
+        let delay1 = context.createDelay();
+        let delay2 = context.createDelay();
+        source.connect(delay1);
+        delay1.connect(delay2);
+        delay2.connect(delay1);
+        delay1.connect(context.destination);
       }
     </script>
   </body>
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/note-grain-on-testing.js b/third_party/WebKit/LayoutTests/webaudio/resources/note-grain-on-testing.js
index 1e941897..6c948f7 100644
--- a/third_party/WebKit/LayoutTests/webaudio/resources/note-grain-on-testing.js
+++ b/third_party/WebKit/LayoutTests/webaudio/resources/note-grain-on-testing.js
@@ -1,5 +1,11 @@
 let sampleRate = 44100.0;
 
+// HRTF extra frames.  This is a magic constant currently in
+// AudioBufferSourceNode::process that always extends the
+// duration by this number of samples.  See bug 77224
+// (https://bugs.webkit.org/show_bug.cgi?id=77224).
+let extraFramesHRTF = 512;
+
 // How many grains to play.
 let numberOfTests = 100;
 
@@ -7,8 +13,9 @@
 let duration = 0.01;
 
 // Time step between the start of each grain.  We need to add a little
-// bit of silence so we can detect grain boundaries
-let timeStep = duration + .005;
+// bit of silence so we can detect grain boundaries and also account
+// for the extra frames for HRTF.
+let timeStep = duration + .005 + extraFramesHRTF / sampleRate;
 
 // Time step between the start for each grain.
 let grainOffsetStep = 0.001;
@@ -23,10 +30,11 @@
 // returns the desired value at sample frame k.
 function createSignalBuffer(context, f) {
   // Make sure the buffer has enough data for all of the possible
-  // grain offsets and durations.  The additional 1 is for any
-  // round-off errors.
-  let signalLength =
-      Math.floor(1 + sampleRate * (numberOfTests * grainOffsetStep + duration));
+  // grain offsets and durations.  Need to include the extra frames
+  // for HRTF.  The additional 1 is for any round-off errors.
+  let signalLength = Math.floor(
+      1 + extraFramesHRTF +
+      sampleRate * (numberOfTests * grainOffsetStep + duration));
 
   let buffer = context.createBuffer(2, signalLength, sampleRate);
   let data = buffer.getChannelData(0);
@@ -120,8 +128,9 @@
   // expectations.
   for (let k = 0; k < startFrames.length; ++k) {
     let expectedStart = timeToSampleFrame(k * timeStep, sampleRate);
-    // The end point is the duration.
-    let expectedEnd = expectedStart +
+    // The end point is the duration, plus the extra frames
+    // for HRTF.
+    let expectedEnd = extraFramesHRTF + expectedStart +
         grainLengthInSampleFrames(k * grainOffsetStep, duration, sampleRate);
 
     if (startFrames[k] != expectedStart)
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni
index c30bf1f..7b1137f 100644
--- a/third_party/WebKit/Source/bindings/bindings.gni
+++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -21,7 +21,6 @@
                     "core/v8/custom/V8MediaQueryListCustom.cpp",
                     "core/v8/custom/V8MessageChannelCustom.cpp",
                     "core/v8/custom/V8MessageEventCustom.cpp",
-                    "core/v8/custom/V8MutationObserverCustom.cpp",
                     "core/v8/custom/V8PopStateEventCustom.cpp",
                     "core/v8/custom/V8PromiseRejectionEventCustom.cpp",
                     "core/v8/custom/V8WindowCustom.cpp",
@@ -137,8 +136,6 @@
                     "core/v8/V8IteratorResultValue.h",
                     "core/v8/V8LazyEventListener.cpp",
                     "core/v8/V8LazyEventListener.h",
-                    "core/v8/V8MutationCallback.cpp",
-                    "core/v8/V8MutationCallback.h",
                     "core/v8/V8NodeFilterCondition.cpp",
                     "core/v8/V8NodeFilterCondition.h",
                     "core/v8/V8ObjectBuilder.cpp",
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index 3a7fccf..fdb8500 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -109,6 +109,8 @@
   "$bindings_core_v8_output_dir/IntersectionObserverCallback.h",
   "$bindings_core_v8_output_dir/MojoWatchCallback.cpp",
   "$bindings_core_v8_output_dir/MojoWatchCallback.h",
+  "$bindings_core_v8_output_dir/MutationCallback.cpp",
+  "$bindings_core_v8_output_dir/MutationCallback.h",
   "$bindings_core_v8_output_dir/PerformanceObserverCallback.cpp",
   "$bindings_core_v8_output_dir/PerformanceObserverCallback.h",
   "$bindings_core_v8_output_dir/ReportingObserverCallback.cpp",
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8MutationCallback.cpp b/third_party/WebKit/Source/bindings/core/v8/V8MutationCallback.cpp
deleted file mode 100644
index 938a83a6..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/V8MutationCallback.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "bindings/core/v8/V8MutationCallback.h"
-
-#include "bindings/core/v8/ScriptController.h"
-#include "bindings/core/v8/V8BindingForCore.h"
-#include "bindings/core/v8/V8MutationObserver.h"
-#include "bindings/core/v8/V8MutationRecord.h"
-#include "core/dom/ExecutionContext.h"
-#include "platform/bindings/ScriptState.h"
-#include "platform/bindings/V8PrivateProperty.h"
-#include "platform/wtf/Assertions.h"
-
-namespace blink {
-
-V8MutationCallback::V8MutationCallback(v8::Local<v8::Function> callback,
-                                       v8::Local<v8::Object> owner,
-                                       ScriptState* script_state)
-    : callback_(script_state->GetIsolate(), this, callback),
-      script_state_(script_state) {
-  V8PrivateProperty::GetMutationObserverCallback(script_state->GetIsolate())
-      .Set(owner, callback);
-}
-
-V8MutationCallback::~V8MutationCallback() {}
-
-void V8MutationCallback::Call(
-    const HeapVector<Member<MutationRecord>>& mutations,
-    MutationObserver* observer) {
-  if (callback_.IsEmpty())
-    return;
-
-  if (!script_state_->ContextIsValid())
-    return;
-
-  v8::Isolate* isolate = script_state_->GetIsolate();
-  ExecutionContext* execution_context =
-      ExecutionContext::From(script_state_.Get());
-  if (!execution_context || execution_context->IsContextSuspended() ||
-      execution_context->IsContextDestroyed())
-    return;
-  ScriptState::Scope scope(script_state_.Get());
-
-  v8::Local<v8::Value> observer_handle =
-      ToV8(observer, script_state_->GetContext()->Global(), isolate);
-  if (!observer_handle->IsObject())
-    return;
-
-  v8::Local<v8::Object> this_object =
-      v8::Local<v8::Object>::Cast(observer_handle);
-  v8::Local<v8::Value> v8_mutations =
-      ToV8(mutations, script_state_->GetContext()->Global(), isolate);
-  if (v8_mutations.IsEmpty())
-    return;
-  v8::Local<v8::Value> argv[] = {v8_mutations, observer_handle};
-
-  v8::TryCatch exception_catcher(isolate);
-  exception_catcher.SetVerbose(true);
-  V8ScriptRunner::CallFunction(callback_.NewLocal(isolate),
-                               GetExecutionContext(), this_object,
-                               WTF_ARRAY_LENGTH(argv), argv, isolate);
-}
-
-DEFINE_TRACE(V8MutationCallback) {
-  MutationCallback::Trace(visitor);
-}
-
-DEFINE_TRACE_WRAPPERS(V8MutationCallback) {
-  visitor->TraceWrappers(callback_.Cast<v8::Value>());
-  MutationCallback::TraceWrappers(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8MutationCallback.h b/third_party/WebKit/Source/bindings/core/v8/V8MutationCallback.h
deleted file mode 100644
index 9174ede..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/V8MutationCallback.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef V8MutationCallback_h
-#define V8MutationCallback_h
-
-#include "core/dom/ExecutionContext.h"
-#include "core/dom/MutationCallback.h"
-#include "platform/bindings/ScopedPersistent.h"
-#include "platform/bindings/ScriptState.h"
-#include "platform/bindings/TraceWrapperV8Reference.h"
-#include "platform/wtf/RefPtr.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-class ExecutionContext;
-
-class V8MutationCallback final : public MutationCallback {
- public:
-  static V8MutationCallback* Create(v8::Local<v8::Function> callback,
-                                    v8::Local<v8::Object> owner,
-                                    ScriptState* script_state) {
-    return new V8MutationCallback(callback, owner, script_state);
-  }
-  ~V8MutationCallback() override;
-
-  void Call(const HeapVector<Member<MutationRecord>>&,
-            MutationObserver*) override;
-
-  ExecutionContext* GetExecutionContext() const override {
-    // The context might have navigated away or closed because this is an async
-    // call.  Check if the context is still alive.
-    // TODO(yukishiino): Make (V8?)MutationCallback inherit from ContextClient.
-    v8::HandleScope scope(script_state_->GetIsolate());
-    if (script_state_->GetContext().IsEmpty())
-      return nullptr;
-    return ExecutionContext::From(script_state_.Get());
-  }
-
-  DECLARE_VIRTUAL_TRACE();
-  DECLARE_VIRTUAL_TRACE_WRAPPERS();
-
- private:
-  V8MutationCallback(v8::Local<v8::Function>,
-                     v8::Local<v8::Object>,
-                     ScriptState*);
-
-  TraceWrapperV8Reference<v8::Function> callback_;
-  RefPtr<ScriptState> script_state_;
-};
-
-}  // namespace blink
-
-#endif  // V8MutationCallback_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8MutationObserverCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8MutationObserverCustom.cpp
deleted file mode 100644
index 69a6c953..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8MutationObserverCustom.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "bindings/core/v8/V8MutationObserver.h"
-
-#include "bindings/core/v8/ExceptionMessages.h"
-#include "bindings/core/v8/ExceptionState.h"
-#include "bindings/core/v8/V8BindingForCore.h"
-#include "bindings/core/v8/V8GCController.h"
-#include "bindings/core/v8/V8MutationCallback.h"
-#include "core/dom/MutationObserver.h"
-#include "core/dom/Node.h"
-#include "platform/bindings/V8DOMWrapper.h"
-
-namespace blink {
-
-void V8MutationObserver::constructorCustom(
-    const v8::FunctionCallbackInfo<v8::Value>& info) {
-  ExceptionState exception_state(info.GetIsolate(),
-                                 ExceptionState::kConstructionContext,
-                                 "MutationObserver");
-  if (info.Length() < 1) {
-    exception_state.ThrowTypeError(
-        ExceptionMessages::NotEnoughArguments(1, info.Length()));
-    return;
-  }
-
-  v8::Local<v8::Value> arg = info[0];
-  if (!arg->IsFunction()) {
-    exception_state.ThrowTypeError("Callback argument must be a function");
-    return;
-  }
-
-  v8::Local<v8::Object> wrapper = info.Holder();
-
-  MutationCallback* callback =
-      V8MutationCallback::Create(v8::Local<v8::Function>::Cast(arg), wrapper,
-                                 ScriptState::Current(info.GetIsolate()));
-  MutationObserver* observer = MutationObserver::Create(callback);
-
-  V8SetReturnValue(info,
-                   V8DOMWrapper::AssociateObjectWithWrapper(
-                       info.GetIsolate(), observer, &wrapperTypeInfo, wrapper));
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 3d6ac574..ad04141 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -486,6 +486,8 @@
     "$blink_core_output_dir/css/properties/CSSPropertyAPIAutoOrString.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIBackgroundAttachment.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIBackgroundBlendMode.h",
+    "$blink_core_output_dir/css/properties/CSSPropertyAPIBackgroundBox.h",
+    "$blink_core_output_dir/css/properties/CSSPropertyAPIBackgroundOrMaskImage.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIBaselineShift.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIBorderColor.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIBorderImageOutset.h",
@@ -511,6 +513,8 @@
     "$blink_core_output_dir/css/properties/CSSPropertyAPICounterReset.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPICursor.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPID.h",
+    "$blink_core_output_dir/css/properties/CSSPropertyAPIDelay.h",
+    "$blink_core_output_dir/css/properties/CSSPropertyAPIDuration.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIFilter.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIFlexBasis.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIFlexGrowOrShrink.h",
@@ -527,6 +531,7 @@
     "$blink_core_output_dir/css/properties/CSSPropertyAPIFragmentation.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIGridAutoFlow.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIGridAutoLine.h",
+    "$blink_core_output_dir/css/properties/CSSPropertyAPIGridGap.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIGridLine.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIGridTemplateAreas.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPIGridTemplateLine.h",
@@ -579,6 +584,7 @@
     "$blink_core_output_dir/css/properties/CSSPropertyAPITextShadow.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPITextSizeAdjust.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPITextUnderlinePosition.h",
+    "$blink_core_output_dir/css/properties/CSSPropertyAPITimingFunction.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPITouchAction.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPITransform.h",
     "$blink_core_output_dir/css/properties/CSSPropertyAPITransformOrigin.h",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index 1b9a0e4..850f2460 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -383,6 +383,8 @@
     "properties/CSSPropertyAPIAutoOrString.cpp",
     "properties/CSSPropertyAPIBackgroundAttachment.cpp",
     "properties/CSSPropertyAPIBackgroundBlendMode.cpp",
+    "properties/CSSPropertyAPIBackgroundBox.cpp",
+    "properties/CSSPropertyAPIBackgroundOrMaskImage.cpp",
     "properties/CSSPropertyAPIBaselineShift.cpp",
     "properties/CSSPropertyAPIBorderColor.cpp",
     "properties/CSSPropertyAPIBorderImageOutset.cpp",
@@ -408,6 +410,8 @@
     "properties/CSSPropertyAPICounterReset.cpp",
     "properties/CSSPropertyAPICursor.cpp",
     "properties/CSSPropertyAPID.cpp",
+    "properties/CSSPropertyAPIDelay.cpp",
+    "properties/CSSPropertyAPIDuration.cpp",
     "properties/CSSPropertyAPIFilter.cpp",
     "properties/CSSPropertyAPIFlexBasis.cpp",
     "properties/CSSPropertyAPIFlexGrowOrShrink.cpp",
@@ -425,6 +429,7 @@
     "properties/CSSPropertyAPIFragmentation.cpp",
     "properties/CSSPropertyAPIGridAutoFlow.cpp",
     "properties/CSSPropertyAPIGridAutoLine.cpp",
+    "properties/CSSPropertyAPIGridGap.cpp",
     "properties/CSSPropertyAPIGridLine.cpp",
     "properties/CSSPropertyAPIGridTemplateAreas.cpp",
     "properties/CSSPropertyAPIGridTemplateLine.cpp",
@@ -477,6 +482,7 @@
     "properties/CSSPropertyAPITextShadow.cpp",
     "properties/CSSPropertyAPITextSizeAdjust.cpp",
     "properties/CSSPropertyAPITextUnderlinePosition.cpp",
+    "properties/CSSPropertyAPITimingFunction.cpp",
     "properties/CSSPropertyAPITouchAction.cpp",
     "properties/CSSPropertyAPITransform.cpp",
     "properties/CSSPropertyAPITransformOrigin.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index e4caa11f..02aa490 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -319,6 +319,8 @@
     // Animation Priority properties
     {
       name: "animation-delay",
+      api_class: "CSSPropertyAPIDelay",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       priority: "Animation",
     },
@@ -333,6 +335,8 @@
     },
     {
       name: "animation-duration",
+      api_class: "CSSPropertyAPIDuration",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       priority: "Animation",
     },
@@ -368,16 +372,22 @@
     },
     {
       name: "animation-timing-function",
+      api_class: "CSSPropertyAPITimingFunction",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       priority: "Animation",
     },
     {
       name: "transition-delay",
+      api_class: "CSSPropertyAPIDelay",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       priority: "Animation",
     },
     {
       name: "transition-duration",
+      api_class: "CSSPropertyAPIDuration",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       priority: "Animation",
     },
@@ -390,6 +400,8 @@
     },
     {
       name: "transition-timing-function",
+      api_class: "CSSPropertyAPITimingFunction",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       priority: "Animation",
     },
@@ -698,6 +710,8 @@
     },
     {
       name: "background-clip",
+      api_class: "CSSPropertyAPIBackgroundBox",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
     },
     {
@@ -715,6 +729,8 @@
     },
     {
       name: "background-image",
+      api_class: "CSSPropertyAPIBackgroundOrMaskImage",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
       keywords: ["auto", "none"],
@@ -722,6 +738,8 @@
     },
     {
       name: "background-origin",
+      api_class: "CSSPropertyAPIBackgroundBox",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
     },
     {
@@ -826,17 +844,20 @@
     {
       name: "border-image-outset",
       api_class: "CSSPropertyAPIBorderImageOutset",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
     {
       name: "border-image-repeat",
       api_class: "CSSPropertyAPIBorderImageRepeat",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
     },
     {
       name: "border-image-slice",
       api_class: "CSSPropertyAPIBorderImageSlice",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
@@ -852,6 +873,7 @@
     {
       name: "border-image-width",
       api_class: "CSSPropertyAPIBorderImageWidth",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
@@ -1390,6 +1412,8 @@
     },
     {
       name: "grid-column-gap",
+      api_class: "CSSPropertyAPIGridGap",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       runtime_flag: "CSSGridLayout",
       field_template: "<length>",
@@ -1420,6 +1444,8 @@
     },
     {
       name: "grid-row-gap",
+      api_class: "CSSPropertyAPIGridGap",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       runtime_flag: "CSSGridLayout",
       field_template: "<length>",
@@ -3136,17 +3162,20 @@
     {
       name: "-webkit-mask-box-image-outset",
       api_class: "CSSPropertyAPIBorderImageOutset",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
     {
       name: "-webkit-mask-box-image-repeat",
       api_class: "CSSPropertyAPIBorderImageRepeat",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
     },
     {
       name: "-webkit-mask-box-image-slice",
       api_class: "CSSPropertyAPIBorderImageSlice",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
@@ -3160,6 +3189,7 @@
     {
       name: "-webkit-mask-box-image-width",
       api_class: "CSSPropertyAPIBorderImageWidth",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
@@ -3175,6 +3205,8 @@
     },
     {
       name: "-webkit-mask-image",
+      api_class: "CSSPropertyAPIBackgroundOrMaskImage",
+      api_methods: ["parseSingleValue"],
       custom_all: true,
       interpolable: true,
     },
@@ -3210,12 +3242,14 @@
     {
       name: "-webkit-perspective-origin-x",
       api_class: "CSSPropertyAPIWebkitOriginX",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
     },
     {
       name: "-webkit-perspective-origin-y",
       api_class: "CSSPropertyAPIWebkitOriginY",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
     },
@@ -3339,12 +3373,14 @@
     {
       name: "-webkit-transform-origin-x",
       api_class: "CSSPropertyAPIWebkitOriginX",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
     },
     {
       name: "-webkit-transform-origin-y",
       api_class: "CSSPropertyAPIWebkitOriginY",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
     },
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 7d55803b..4986186 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -304,11 +304,6 @@
   return nullptr;
 }
 
-static CSSValue* ConsumeBackgroundBox(CSSParserTokenRange& range) {
-  return ConsumeIdent<CSSValueBorderBox, CSSValuePaddingBox,
-                      CSSValueContentBox>(range);
-}
-
 static CSSValue* ConsumePrefixedBackgroundBox(CSSParserTokenRange& range,
                                               const CSSParserContext* context,
                                               bool allow_text_value) {
@@ -356,13 +351,13 @@
                                             const CSSParserContext* context) {
   switch (unresolved_property) {
     case CSSPropertyBackgroundClip:
-      return ConsumeBackgroundBox(range);
+      return CSSPropertyBackgroundUtils::ConsumeBackgroundBox(range);
     case CSSPropertyBackgroundBlendMode:
       return CSSPropertyBackgroundUtils::ConsumeBackgroundBlendMode(range);
     case CSSPropertyBackgroundAttachment:
       return CSSPropertyBackgroundUtils::ConsumeBackgroundAttachment(range);
     case CSSPropertyBackgroundOrigin:
-      return ConsumeBackgroundBox(range);
+      return CSSPropertyBackgroundUtils::ConsumeBackgroundBox(range);
     case CSSPropertyWebkitMaskComposite:
       return CSSPropertyBackgroundUtils::ConsumeBackgroundComposite(range);
     case CSSPropertyMaskSourceType:
@@ -672,55 +667,10 @@
     case CSSPropertyWebkitLogicalWidth:
     case CSSPropertyWebkitLogicalHeight:
       return CSSPropertyLengthUtils::ConsumeWidthOrHeight(range_, *context_);
-    case CSSPropertyAnimationDelay:
-    case CSSPropertyTransitionDelay:
-      return ConsumeCommaSeparatedList(ConsumeTime, range_, kValueRangeAll);
-    case CSSPropertyAnimationDuration:
-    case CSSPropertyTransitionDuration:
-      return ConsumeCommaSeparatedList(ConsumeTime, range_,
-                                       kValueRangeNonNegative);
-    case CSSPropertyAnimationTimingFunction:
-    case CSSPropertyTransitionTimingFunction:
-      return ConsumeCommaSeparatedList(CSSPropertyAnimationTimingFunctionUtils::
-                                           ConsumeAnimationTimingFunction,
-                                       range_);
-    case CSSPropertyGridColumnGap:
-    case CSSPropertyGridRowGap:
-      return ConsumeLengthOrPercent(range_, context_->Mode(),
-                                    kValueRangeNonNegative);
     case CSSPropertyTextDecoration:
       DCHECK(!RuntimeEnabledFeatures::CSS3TextDecorationsEnabled());
       return CSSPropertyTextDecorationLineUtils::ConsumeTextDecorationLine(
           range_);
-    case CSSPropertyWebkitTransformOriginX:
-    case CSSPropertyWebkitPerspectiveOriginX:
-      return CSSPropertyPositionUtils::ConsumePositionLonghand<CSSValueLeft,
-                                                               CSSValueRight>(
-          range_, context_->Mode());
-    case CSSPropertyWebkitTransformOriginY:
-    case CSSPropertyWebkitPerspectiveOriginY:
-      return CSSPropertyPositionUtils::ConsumePositionLonghand<CSSValueTop,
-                                                               CSSValueBottom>(
-          range_, context_->Mode());
-    case CSSPropertyBorderImageRepeat:
-    case CSSPropertyWebkitMaskBoxImageRepeat:
-      return CSSPropertyBorderImageUtils::ConsumeBorderImageRepeat(range_);
-    case CSSPropertyBorderImageSlice:
-    case CSSPropertyWebkitMaskBoxImageSlice:
-      return CSSPropertyBorderImageUtils::ConsumeBorderImageSlice(
-          range_, false /* default_fill */);
-    case CSSPropertyBorderImageOutset:
-    case CSSPropertyWebkitMaskBoxImageOutset:
-      return CSSPropertyBorderImageUtils::ConsumeBorderImageOutset(range_);
-    case CSSPropertyBorderImageWidth:
-    case CSSPropertyWebkitMaskBoxImageWidth:
-      return CSSPropertyBorderImageUtils::ConsumeBorderImageWidth(range_);
-    case CSSPropertyBackgroundClip:
-    case CSSPropertyBackgroundOrigin:
-      return ConsumeCommaSeparatedList(ConsumeBackgroundBox, range_);
-    case CSSPropertyBackgroundImage:
-    case CSSPropertyWebkitMaskImage:
-      return ConsumeCommaSeparatedList(ConsumeImageOrNone, range_, context_);
     case CSSPropertyBackgroundPositionX:
     case CSSPropertyWebkitMaskPositionX:
       return ConsumeCommaSeparatedList(
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBackgroundBox.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBackgroundBox.cpp
new file mode 100644
index 0000000..6f768fc
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBackgroundBox.cpp
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIBackgroundBox.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "core/css/properties/CSSPropertyBackgroundUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIBackgroundBox::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeCommaSeparatedList(
+      CSSPropertyBackgroundUtils::ConsumeBackgroundBox, range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBackgroundOrMaskImage.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBackgroundOrMaskImage.cpp
new file mode 100644
index 0000000..fc421a0
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBackgroundOrMaskImage.cpp
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIBackgroundOrMaskImage.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIBackgroundOrMaskImage::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeCommaSeparatedList(
+      CSSPropertyParserHelpers::ConsumeImageOrNone, range, &context);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageOutset.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageOutset.cpp
index 8836bd0..ec4e37fc 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageOutset.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageOutset.cpp
@@ -4,4 +4,15 @@
 
 #include "core/css/properties/CSSPropertyAPIBorderImageOutset.h"
 
-namespace blink {}  // namespace blink
+#include "core/css/properties/CSSPropertyBorderImageUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIBorderImageOutset::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyBorderImageUtils::ConsumeBorderImageOutset(range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageRepeat.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageRepeat.cpp
index e7b74980..ba6846e 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageRepeat.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageRepeat.cpp
@@ -4,4 +4,15 @@
 
 #include "core/css/properties/CSSPropertyAPIBorderImageRepeat.h"
 
-namespace blink {}  // namespace blink
+#include "core/css/properties/CSSPropertyBorderImageUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIBorderImageRepeat::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyBorderImageUtils::ConsumeBorderImageRepeat(range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageSlice.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageSlice.cpp
index 6d6a7eb1..13fc7e6b 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageSlice.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageSlice.cpp
@@ -4,4 +4,16 @@
 
 #include "core/css/properties/CSSPropertyAPIBorderImageSlice.h"
 
-namespace blink {}  // namespace blink
+#include "core/css/properties/CSSPropertyBorderImageUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIBorderImageSlice::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyBorderImageUtils::ConsumeBorderImageSlice(
+      range, DefaultFill::kNoFill);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageWidth.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageWidth.cpp
index bcc64fa..ec6b4782 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageWidth.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderImageWidth.cpp
@@ -4,4 +4,15 @@
 
 #include "core/css/properties/CSSPropertyAPIBorderImageWidth.h"
 
-namespace blink {}  // namespace blink
+#include "core/css/properties/CSSPropertyBorderImageUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIBorderImageWidth::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyBorderImageUtils::ConsumeBorderImageWidth(range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIDelay.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIDelay.cpp
new file mode 100644
index 0000000..e0c153a
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIDelay.cpp
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIDelay.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "platform/Length.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIDelay::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeCommaSeparatedList(
+      CSSPropertyParserHelpers::ConsumeTime, range, kValueRangeAll);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIDuration.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIDuration.cpp
new file mode 100644
index 0000000..c8121ac
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIDuration.cpp
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIDuration.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "platform/Length.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIDuration::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeCommaSeparatedList(
+      CSSPropertyParserHelpers::ConsumeTime, range, kValueRangeNonNegative);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridGap.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridGap.cpp
new file mode 100644
index 0000000..81ac4c9
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridGap.cpp
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIGridGap.h"
+
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "platform/Length.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIGridGap::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeLengthOrPercent(
+      range, context.Mode(), kValueRangeNonNegative);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITimingFunction.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITimingFunction.cpp
new file mode 100644
index 0000000..c8e71935
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITimingFunction.cpp
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPITimingFunction.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "core/css/properties/CSSPropertyAnimationTimingFunctionUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPITimingFunction::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeCommaSeparatedList(
+      CSSPropertyAnimationTimingFunctionUtils::ConsumeAnimationTimingFunction,
+      range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginX.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginX.cpp
index 24ecc2c2..be6ce92 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginX.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginX.cpp
@@ -4,4 +4,19 @@
 
 #include "core/css/properties/CSSPropertyAPIWebkitOriginX.h"
 
-namespace blink {}  // namespace blink
+#include "core/CSSValueKeywords.h"
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/properties/CSSPropertyPositionUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIWebkitOriginX::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&) {
+  return CSSPropertyPositionUtils::ConsumePositionLonghand<CSSValueLeft,
+                                                           CSSValueRight>(
+      range, context.Mode());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginY.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginY.cpp
index 08483ce..d080353 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginY.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitOriginY.cpp
@@ -4,4 +4,19 @@
 
 #include "core/css/properties/CSSPropertyAPIWebkitOriginY.h"
 
-namespace blink {}  // namespace blink
+#include "core/CSSValueKeywords.h"
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/properties/CSSPropertyPositionUtils.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIWebkitOriginY::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&) {
+  return CSSPropertyPositionUtils::ConsumePositionLonghand<CSSValueTop,
+                                                           CSSValueBottom>(
+      range, context.Mode());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.cpp
index 16bfeeb..b993d52 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.cpp
@@ -43,6 +43,12 @@
   return nullptr;
 }
 
+CSSValue* CSSPropertyBackgroundUtils::ConsumeBackgroundBox(
+    CSSParserTokenRange& range) {
+  return CSSPropertyParserHelpers::ConsumeIdent<
+      CSSValueBorderBox, CSSValuePaddingBox, CSSValueContentBox>(range);
+}
+
 CSSValue* CSSPropertyBackgroundUtils::ConsumeBackgroundComposite(
     CSSParserTokenRange& range) {
   return CSSPropertyParserHelpers::ConsumeIdentRange(range, CSSValueClear,
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.h
index 6511178..7885bf73c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.h
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyBackgroundUtils.h
@@ -24,6 +24,7 @@
 
   static CSSValue* ConsumeBackgroundAttachment(CSSParserTokenRange&);
   static CSSValue* ConsumeBackgroundBlendMode(CSSParserTokenRange&);
+  static CSSValue* ConsumeBackgroundBox(CSSParserTokenRange&);
   static CSSValue* ConsumeBackgroundComposite(CSSParserTokenRange&);
   static CSSValue* ConsumeMaskSourceType(CSSParserTokenRange&);
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.cpp
index 4905104..98ec279 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.cpp
@@ -34,7 +34,7 @@
   CSSValue* outset = nullptr;
   CSSValue* repeat = nullptr;
   if (ConsumeBorderImageComponents(range, context, source, slice, width, outset,
-                                   repeat, true /* default_fill */))
+                                   repeat, DefaultFill::kFill))
     return CreateBorderImageValue(source, slice, width, outset, repeat);
   return nullptr;
 }
@@ -47,7 +47,7 @@
     CSSValue*& width,
     CSSValue*& outset,
     CSSValue*& repeat,
-    bool default_fill) {
+    DefaultFill default_fill) {
   do {
     if (!source) {
       source = CSSPropertyParserHelpers::ConsumeImageOrNone(range, &context);
@@ -99,7 +99,7 @@
 
 CSSValue* CSSPropertyBorderImageUtils::ConsumeBorderImageSlice(
     CSSParserTokenRange& range,
-    bool default_fill) {
+    DefaultFill default_fill) {
   bool fill = CSSPropertyParserHelpers::ConsumeIdent<CSSValueFill>(range);
   CSSValue* slices[4] = {0};
 
@@ -122,7 +122,7 @@
     fill = true;
   }
   CSSPropertyParserHelpers::Complete4Sides(slices);
-  if (default_fill)
+  if (default_fill == DefaultFill::kFill)
     fill = true;
   return CSSBorderImageSliceValue::Create(
       CSSQuadValue::Create(slices[0], slices[1], slices[2], slices[3],
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.h
index 20a6182..b00b5ba9 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.h
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyBorderImageUtils.h
@@ -13,6 +13,8 @@
 class CSSParserTokenRange;
 class CSSValue;
 
+enum class DefaultFill { kFill, kNoFill };
+
 class CSSPropertyBorderImageUtils {
   STATIC_ONLY(CSSPropertyBorderImageUtils);
 
@@ -26,10 +28,9 @@
                                            CSSValue*& width,
                                            CSSValue*& outset,
                                            CSSValue*& repeat,
-                                           bool default_fill);
+                                           DefaultFill);
   static CSSValue* ConsumeBorderImageRepeat(CSSParserTokenRange&);
-  static CSSValue* ConsumeBorderImageSlice(CSSParserTokenRange&,
-                                           bool default_fill);
+  static CSSValue* ConsumeBorderImageSlice(CSSParserTokenRange&, DefaultFill);
   static CSSValue* ConsumeBorderImageWidth(CSSParserTokenRange&);
   static CSSValue* ConsumeBorderImageOutset(CSSParserTokenRange&);
 };
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyPositionUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyPositionUtils.h
index d3e3cb6..4cf4137 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyPositionUtils.h
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyPositionUtils.h
@@ -6,6 +6,8 @@
 
 #include "core/CSSValueKeywords.h"
 #include "core/css/parser/CSSParserMode.h"
+#include "core/css/parser/CSSParserTokenRange.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
 
 #include "platform/wtf/Allocator.h"
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderImage.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderImage.cpp
index b17bf4f..32c44f6 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderImage.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderImage.cpp
@@ -24,7 +24,8 @@
   CSSValue* repeat = nullptr;
 
   if (!CSSPropertyBorderImageUtils::ConsumeBorderImageComponents(
-          range, context, source, slice, width, outset, repeat, false)) {
+          range, context, source, slice, width, outset, repeat,
+          DefaultFill::kNoFill)) {
     return false;
   }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMaskBoxImage.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMaskBoxImage.cpp
index b4f49c9..031deba 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMaskBoxImage.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMaskBoxImage.cpp
@@ -24,7 +24,8 @@
   CSSValue* repeat = nullptr;
 
   if (!CSSPropertyBorderImageUtils::ConsumeBorderImageComponents(
-          range, context, source, slice, width, outset, repeat, true)) {
+          range, context, source, slice, width, outset, repeat,
+          DefaultFill::kFill)) {
     return false;
   }
 
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn
index b68f5073..b70eb48 100644
--- a/third_party/WebKit/Source/core/dom/BUILD.gn
+++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -172,7 +172,6 @@
     "ModulePendingScript.h",
     "ModuleScript.cpp",
     "ModuleScript.h",
-    "MutationCallback.h",
     "MutationObserver.cpp",
     "MutationObserver.h",
     "MutationObserverInterestGroup.cpp",
diff --git a/third_party/WebKit/Source/core/dom/IconURL.cpp b/third_party/WebKit/Source/core/dom/IconURL.cpp
index 84cf1b1..bc0b99fa 100644
--- a/third_party/WebKit/Source/core/dom/IconURL.cpp
+++ b/third_party/WebKit/Source/core/dom/IconURL.cpp
@@ -29,6 +29,8 @@
  */
 
 #include "core/dom/IconURL.h"
+#include "platform/wtf/Assertions.h"
+#include "public/web/WebIconURL.h"
 
 namespace blink {
 
@@ -54,4 +56,9 @@
          lhs.mime_type_ == rhs.mime_type_;
 }
 
+STATIC_ASSERT_ENUM(WebIconURL::kTypeInvalid, kInvalidIcon);
+STATIC_ASSERT_ENUM(WebIconURL::kTypeFavicon, kFavicon);
+STATIC_ASSERT_ENUM(WebIconURL::kTypeTouch, kTouchIcon);
+STATIC_ASSERT_ENUM(WebIconURL::kTypeTouchPrecomposed, kTouchPrecomposedIcon);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/MutationCallback.h b/third_party/WebKit/Source/core/dom/MutationCallback.h
deleted file mode 100644
index 942752c..0000000
--- a/third_party/WebKit/Source/core/dom/MutationCallback.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef MutationCallback_h
-#define MutationCallback_h
-
-#include "platform/bindings/ScriptWrappable.h"
-#include "platform/heap/Handle.h"
-#include "platform/wtf/Vector.h"
-
-namespace blink {
-
-class ExecutionContext;
-class MutationRecord;
-class MutationObserver;
-
-class MutationCallback : public GarbageCollectedFinalized<MutationCallback>,
-                         public TraceWrapperBase {
- public:
-  virtual ~MutationCallback() {}
-
-  virtual void Call(const HeapVector<Member<MutationRecord>>&,
-                    MutationObserver*) = 0;
-  virtual ExecutionContext* GetExecutionContext() const = 0;
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {}
-};
-
-}  // namespace blink
-
-#endif  // MutationCallback_h
diff --git a/third_party/WebKit/Source/core/dom/MutationObserver.cpp b/third_party/WebKit/Source/core/dom/MutationObserver.cpp
index 98c3103..666801df 100644
--- a/third_party/WebKit/Source/core/dom/MutationObserver.cpp
+++ b/third_party/WebKit/Source/core/dom/MutationObserver.cpp
@@ -31,8 +31,11 @@
 #include "core/dom/MutationObserver.h"
 
 #include <algorithm>
+
 #include "bindings/core/v8/ExceptionState.h"
-#include "core/dom/MutationCallback.h"
+#include "bindings/core/v8/MutationCallback.h"
+#include "bindings/core/v8/V8BindingForCore.h"
+#include "core/dom/ExecutionContext.h"
 #include "core/dom/MutationObserverInit.h"
 #include "core/dom/MutationObserverRegistration.h"
 #include "core/dom/MutationRecord.h"
@@ -43,6 +46,47 @@
 
 namespace blink {
 
+class MutationObserver::V8DelegateImpl final
+    : public MutationObserver::Delegate,
+      public ContextClient {
+  USING_GARBAGE_COLLECTED_MIXIN(V8DelegateImpl);
+
+ public:
+  static V8DelegateImpl* Create(v8::Isolate* isolate,
+                                MutationCallback* callback) {
+    ExecutionContext* execution_context =
+        ToExecutionContext(callback->v8Value(isolate)->CreationContext());
+
+    return new V8DelegateImpl(callback, execution_context);
+  }
+
+  ExecutionContext* GetExecutionContext() const override {
+    return ContextClient::GetExecutionContext();
+  }
+
+  void Deliver(const MutationRecordVector& records,
+               MutationObserver& observer) override {
+    // https://dom.spec.whatwg.org/#notify-mutation-observers
+    // step 5-4. specifies that the callback this value is a MutationObserver.
+    callback_->call(&observer, records, &observer);
+  }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(callback_);
+    MutationObserver::Delegate::Trace(visitor);
+    ContextClient::Trace(visitor);
+  }
+
+  DEFINE_INLINE_VIRTUAL_TRACE_WRAPPERS() { visitor->TraceWrappers(callback_); }
+
+ private:
+  V8DelegateImpl(MutationCallback* callback,
+                 ExecutionContext* execution_context)
+      : ContextClient(execution_context), callback_(this, callback) {}
+
+  TraceWrapperMember<MutationCallback> callback_;
+};
+
 static unsigned g_observer_priority = 0;
 
 struct MutationObserver::ObserverLessThan {
@@ -52,13 +96,24 @@
   }
 };
 
-MutationObserver* MutationObserver::Create(MutationCallback* callback) {
+MutationObserver* MutationObserver::Create(Delegate* delegate) {
   DCHECK(IsMainThread());
-  return new MutationObserver(callback);
+  return new MutationObserver(delegate->GetExecutionContext(), delegate);
 }
 
-MutationObserver::MutationObserver(MutationCallback* callback)
-    : callback_(this, callback), priority_(g_observer_priority++) {}
+MutationObserver* MutationObserver::Create(ScriptState* script_state,
+                                           MutationCallback* callback) {
+  DCHECK(IsMainThread());
+  return new MutationObserver(
+      ExecutionContext::From(script_state),
+      V8DelegateImpl::Create(script_state->GetIsolate(), callback));
+}
+
+MutationObserver::MutationObserver(ExecutionContext* execution_context,
+                                   Delegate* delegate)
+    : ContextClient(execution_context),
+      delegate_(this, delegate),
+      priority_(g_observer_priority++) {}
 
 MutationObserver::~MutationObserver() {
   CancelInspectorAsyncTasks();
@@ -218,7 +273,7 @@
   DCHECK(IsMainThread());
   records_.push_back(TraceWrapperMember<MutationRecord>(this, mutation));
   ActivateObserver(this);
-  probe::AsyncTaskScheduled(callback_->GetExecutionContext(), mutation->type(),
+  probe::AsyncTaskScheduled(delegate_->GetExecutionContext(), mutation->type(),
                             mutation);
 }
 
@@ -235,13 +290,13 @@
 }
 
 bool MutationObserver::ShouldBeSuspended() const {
-  return callback_->GetExecutionContext() &&
-         callback_->GetExecutionContext()->IsContextSuspended();
+  const ExecutionContext* execution_context = delegate_->GetExecutionContext();
+  return execution_context && execution_context->IsContextSuspended();
 }
 
 void MutationObserver::CancelInspectorAsyncTasks() {
   for (auto& record : records_)
-    probe::AsyncTaskCanceled(callback_->GetExecutionContext(), record);
+    probe::AsyncTaskCanceled(delegate_->GetExecutionContext(), record);
 }
 
 void MutationObserver::Deliver() {
@@ -265,9 +320,9 @@
   swap(records_, records, this);
 
   // Report the first (earliest) stack as the async cause.
-  probe::AsyncTask async_task(callback_->GetExecutionContext(),
+  probe::AsyncTask async_task(delegate_->GetExecutionContext(),
                               records.front());
-  callback_->Call(records, this);
+  delegate_->Deliver(records, *this);
 }
 
 void MutationObserver::ResumeSuspendedObservers() {
@@ -310,19 +365,15 @@
     slot->DispatchSlotChangeEvent();
 }
 
-ExecutionContext* MutationObserver::GetExecutionContext() const {
-  return callback_->GetExecutionContext();
-}
-
 DEFINE_TRACE(MutationObserver) {
-  visitor->Trace(callback_);
+  visitor->Trace(delegate_);
   visitor->Trace(records_);
   visitor->Trace(registrations_);
-  visitor->Trace(callback_);
+  ContextClient::Trace(visitor);
 }
 
 DEFINE_TRACE_WRAPPERS(MutationObserver) {
-  visitor->TraceWrappers(callback_);
+  visitor->TraceWrappers(delegate_);
   for (auto record : records_)
     visitor->TraceWrappers(record);
 }
diff --git a/third_party/WebKit/Source/core/dom/MutationObserver.h b/third_party/WebKit/Source/core/dom/MutationObserver.h
index 8ca75eb..103393d 100644
--- a/third_party/WebKit/Source/core/dom/MutationObserver.h
+++ b/third_party/WebKit/Source/core/dom/MutationObserver.h
@@ -33,6 +33,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "core/CoreExport.h"
+#include "core/dom/ContextLifecycleObserver.h"
 #include "core/dom/ExecutionContext.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/bindings/TraceWrapperMember.h"
@@ -51,6 +52,7 @@
 class MutationObserverRegistration;
 class MutationRecord;
 class Node;
+class ScriptState;
 
 typedef unsigned char MutationObserverOptions;
 typedef unsigned char MutationRecordDeliveryOptions;
@@ -64,7 +66,8 @@
 class CORE_EXPORT MutationObserver final
     : public GarbageCollectedFinalized<MutationObserver>,
       public ActiveScriptWrappable<MutationObserver>,
-      public ScriptWrappable {
+      public ScriptWrappable,
+      public ContextClient {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(MutationObserver);
 
@@ -84,7 +87,21 @@
     kCharacterDataOldValue = 1 << 6,
   };
 
-  static MutationObserver* Create(MutationCallback*);
+  class CORE_EXPORT Delegate : public GarbageCollectedFinalized<Delegate>,
+                               public TraceWrapperBase {
+   public:
+    virtual ~Delegate() = default;
+    virtual ExecutionContext* GetExecutionContext() const = 0;
+    virtual void Deliver(const MutationRecordVector& records,
+                         MutationObserver&) = 0;
+    DEFINE_INLINE_VIRTUAL_TRACE() {}
+    DEFINE_INLINE_VIRTUAL_TRACE_WRAPPERS() {}
+  };
+
+  class CORE_EXPORT V8DelegateImpl;
+
+  static MutationObserver* Create(Delegate*);
+  static MutationObserver* Create(ScriptState*, MutationCallback*);
   static void ResumeSuspendedObservers();
   static void DeliverMutations();
   static void EnqueueSlotChange(HTMLSlotElement&);
@@ -103,7 +120,6 @@
   HeapHashSet<Member<Node>> GetObservedNodes() const;
 
   bool HasPendingActivity() const override { return !records_.IsEmpty(); }
-  ExecutionContext* GetExecutionContext() const;
 
   // Eagerly finalized as destructor accesses heap object members.
   EAGERLY_FINALIZE();
@@ -114,12 +130,12 @@
  private:
   struct ObserverLessThan;
 
-  explicit MutationObserver(MutationCallback*);
+  MutationObserver(ExecutionContext*, Delegate*);
   void Deliver();
   bool ShouldBeSuspended() const;
   void CancelInspectorAsyncTasks();
 
-  TraceWrapperMember<MutationCallback> callback_;
+  TraceWrapperMember<Delegate> delegate_;
   HeapVector<TraceWrapperMember<MutationRecord>> records_;
   MutationObserverRegistrationSet registrations_;
   unsigned priority_;
diff --git a/third_party/WebKit/Source/core/dom/MutationObserver.idl b/third_party/WebKit/Source/core/dom/MutationObserver.idl
index f1bc1a9e..e266d489 100644
--- a/third_party/WebKit/Source/core/dom/MutationObserver.idl
+++ b/third_party/WebKit/Source/core/dom/MutationObserver.idl
@@ -30,8 +30,12 @@
 
 // https://dom.spec.whatwg.org/#interface-mutationobserver
 
+callback MutationCallback = void (sequence<MutationRecord> mutations,
+                                  MutationObserver observer);
+
 [
-    CustomConstructor(MutationCallback callback),
+    ConstructorCallWith=ScriptState,
+    Constructor(MutationCallback callback),
     ActiveScriptWrappable,
     DependentLifetime
 ] interface MutationObserver {
diff --git a/third_party/WebKit/Source/core/dom/MutationObserverTest.cpp b/third_party/WebKit/Source/core/dom/MutationObserverTest.cpp
index 60d64d25..ef48c7f4 100644
--- a/third_party/WebKit/Source/core/dom/MutationObserverTest.cpp
+++ b/third_party/WebKit/Source/core/dom/MutationObserverTest.cpp
@@ -4,7 +4,6 @@
 
 #include "core/dom/MutationObserver.h"
 
-#include "core/dom/MutationCallback.h"
 #include "core/dom/MutationObserverInit.h"
 #include "core/dom/MutationObserverRegistration.h"
 #include "core/html/HTMLDocument.h"
@@ -15,22 +14,24 @@
 
 namespace {
 
-class EmptyMutationCallback : public MutationCallback {
+class EmptyMutationCallback : public MutationObserver::Delegate {
  public:
   explicit EmptyMutationCallback(Document& document) : document_(document) {}
+
+  ExecutionContext* GetExecutionContext() const override { return document_; }
+
+  void Deliver(const MutationRecordVector&, MutationObserver&) override {}
+
   DEFINE_INLINE_VIRTUAL_TRACE() {
     visitor->Trace(document_);
-    MutationCallback::Trace(visitor);
+    MutationObserver::Delegate::Trace(visitor);
   }
 
  private:
-  void Call(const HeapVector<Member<MutationRecord>>&,
-            MutationObserver*) override {}
-  ExecutionContext* GetExecutionContext() const override { return document_; }
-
   Member<Document> document_;
 };
-}
+
+}  // namespace
 
 TEST(MutationObserverTest, DisconnectCrash) {
   Persistent<Document> document = HTMLDocument::CreateForTest();
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index 5c81057..b26cfe22 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -49,22 +49,22 @@
 class Element;
 class ElementShadow;
 class Event;
+class EventDispatchHandlingState;
 class ExceptionState;
 class GetRootNodeOptions;
 class HTMLQualifiedName;
 class HTMLSlotElement;
 class IntRect;
-class EventDispatchHandlingState;
+class KURL;
+class LayoutBox;
+class LayoutBoxModelObject;
+class LayoutObject;
 class NodeList;
 class NodeListsNodeData;
 class NodeOrString;
 class NodeRareData;
 class QualifiedName;
 class RegisteredEventListener;
-class LayoutBox;
-class LayoutBoxModelObject;
-class LayoutObject;
-class ComputedStyle;
 class SVGQualifiedName;
 class ShadowRoot;
 template <typename NodeType>
diff --git a/third_party/WebKit/Source/core/editing/EditingBehavior.cpp b/third_party/WebKit/Source/core/editing/EditingBehavior.cpp
index 659069be..e8c9e12 100644
--- a/third_party/WebKit/Source/core/editing/EditingBehavior.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingBehavior.cpp
@@ -29,7 +29,9 @@
 #include "build/build_config.h"
 #include "core/events/KeyboardEvent.h"
 #include "platform/KeyboardCodes.h"
+#include "platform/wtf/Assertions.h"
 #include "public/platform/WebInputEvent.h"
+#include "public/web/WebSettings.h"
 
 namespace blink {
 
@@ -289,4 +291,11 @@
 
   return true;
 }
+
+STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorMac, kEditingMacBehavior);
+STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorWin, kEditingWindowsBehavior);
+STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorUnix, kEditingUnixBehavior);
+STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorAndroid,
+                   kEditingAndroidBehavior);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
index 17456b3..9e5f4db 100644
--- a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
@@ -113,8 +113,7 @@
 
 void SelectionEditor::SetSelection(const SelectionInDOMTree& new_selection) {
   new_selection.AssertValidFor(GetDocument());
-  if (selection_ == new_selection)
-    return;
+  DCHECK_NE(selection_, new_selection);
   ClearDocumentCachedRange();
   MarkCacheDirty();
   selection_ = new_selection;
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp
index ae790945..dc60878 100644
--- a/third_party/WebKit/Source/core/events/EventTarget.cpp
+++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -52,10 +52,12 @@
 #include "core/probe/CoreProbes.h"
 #include "platform/EventDispatchForbiddenScope.h"
 #include "platform/Histogram.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/StdLibExtras.h"
 #include "platform/wtf/Threading.h"
 #include "platform/wtf/Vector.h"
+#include "public/web/WebSettings.h"
 
 namespace blink {
 namespace {
@@ -834,4 +836,11 @@
   }
 }
 
+STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kFalse,
+                   PassiveListenerDefault::kFalse);
+STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kTrue,
+                   PassiveListenerDefault::kTrue);
+STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kForceAllTrue,
+                   PassiveListenerDefault::kForceAllTrue);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp b/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp
index 9c06a9f..bd8564be 100644
--- a/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFormElementObserverImpl.cpp
@@ -5,7 +5,6 @@
 #include "core/exported/WebFormElementObserverImpl.h"
 
 #include "core/css/CSSComputedStyleDeclaration.h"
-#include "core/dom/MutationCallback.h"
 #include "core/dom/MutationObserver.h"
 #include "core/dom/MutationObserverInit.h"
 #include "core/dom/MutationRecord.h"
@@ -19,20 +18,21 @@
 
 namespace blink {
 
-class WebFormElementObserverImpl::ObserverCallback : public MutationCallback {
+class WebFormElementObserverImpl::ObserverCallback
+    : public MutationObserver::Delegate {
  public:
   ObserverCallback(HTMLElement&,
                    std::unique_ptr<WebFormElementObserverCallback>);
-  DECLARE_VIRTUAL_TRACE();
 
   ExecutionContext* GetExecutionContext() const override;
 
+  void Deliver(const MutationRecordVector& records, MutationObserver&) override;
+
   void Disconnect();
 
- private:
-  void Call(const HeapVector<Member<MutationRecord>>& records,
-            MutationObserver*) override;
+  DECLARE_VIRTUAL_TRACE();
 
+ private:
   Member<HTMLElement> element_;
   Member<MutationObserver> mutation_observer_;
   std::unique_ptr<WebFormElementObserverCallback> callback_;
@@ -41,19 +41,13 @@
 WebFormElementObserverImpl::ObserverCallback::ObserverCallback(
     HTMLElement& element,
     std::unique_ptr<WebFormElementObserverCallback> callback)
-    : element_(&element), callback_(std::move(callback)) {
-  DCHECK(element.ownerDocument());
-  mutation_observer_ = MutationObserver::Create(this);
-
+    : element_(element),
+      mutation_observer_(MutationObserver::Create(this)),
+      callback_(std::move(callback)) {
   {
-    Vector<String> filter;
-    filter.ReserveCapacity(3);
-    filter.push_back(String("action"));
-    filter.push_back(String("class"));
-    filter.push_back(String("style"));
     MutationObserverInit init;
     init.setAttributes(true);
-    init.setAttributeFilter(filter);
+    init.setAttributeFilter({"action", "class", "style"});
     mutation_observer_->observe(element_, init, ASSERT_NO_EXCEPTION);
   }
   if (element_->parentElement()) {
@@ -66,17 +60,12 @@
 
 ExecutionContext*
 WebFormElementObserverImpl::ObserverCallback::GetExecutionContext() const {
-  return element_->ownerDocument();
+  return &element_->GetDocument();
 }
 
-void WebFormElementObserverImpl::ObserverCallback::Disconnect() {
-  mutation_observer_->disconnect();
-  callback_.reset();
-}
-
-void WebFormElementObserverImpl::ObserverCallback::Call(
-    const HeapVector<Member<MutationRecord>>& records,
-    MutationObserver*) {
+void WebFormElementObserverImpl::ObserverCallback::Deliver(
+    const MutationRecordVector& records,
+    MutationObserver&) {
   for (const auto& record : records) {
     if (record->type() == "childList") {
       for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
@@ -108,10 +97,15 @@
   }
 }
 
+void WebFormElementObserverImpl::ObserverCallback::Disconnect() {
+  mutation_observer_->disconnect();
+  callback_.reset();
+}
+
 DEFINE_TRACE(WebFormElementObserverImpl::ObserverCallback) {
   visitor->Trace(element_);
   visitor->Trace(mutation_observer_);
-  MutationCallback::Trace(visitor);
+  MutationObserver::Delegate::Trace(visitor);
 }
 
 WebFormElementObserver* WebFormElementObserver::Create(
diff --git a/third_party/WebKit/Source/core/fileapi/FileError.cpp b/third_party/WebKit/Source/core/fileapi/FileError.cpp
index 52bb582d..42a068d3 100644
--- a/third_party/WebKit/Source/core/fileapi/FileError.cpp
+++ b/third_party/WebKit/Source/core/fileapi/FileError.cpp
@@ -33,6 +33,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
+#include "platform/wtf/Assertions.h"
+#include "public/platform/WebFileError.h"
 
 namespace blink {
 
@@ -165,6 +167,20 @@
                               ErrorCodeToMessage(code));
 }
 
+STATIC_ASSERT_ENUM(kWebFileErrorNotFound, kNotFoundErr);
+STATIC_ASSERT_ENUM(kWebFileErrorSecurity, kSecurityErr);
+STATIC_ASSERT_ENUM(kWebFileErrorAbort, kAbortErr);
+STATIC_ASSERT_ENUM(kWebFileErrorNotReadable, kNotReadableErr);
+STATIC_ASSERT_ENUM(kWebFileErrorEncoding, kEncodingErr);
+STATIC_ASSERT_ENUM(kWebFileErrorNoModificationAllowed,
+                   kNoModificationAllowedErr);
+STATIC_ASSERT_ENUM(kWebFileErrorInvalidState, kInvalidStateErr);
+STATIC_ASSERT_ENUM(kWebFileErrorSyntax, kSyntaxErr);
+STATIC_ASSERT_ENUM(kWebFileErrorInvalidModification, kInvalidModificationErr);
+STATIC_ASSERT_ENUM(kWebFileErrorQuotaExceeded, kQuotaExceededErr);
+STATIC_ASSERT_ENUM(kWebFileErrorTypeMismatch, kTypeMismatchErr);
+STATIC_ASSERT_ENUM(kWebFileErrorPathExists, kPathExistsErr);
+
 }  // namespace FileError
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp
index eaf559f..095a49e7 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp
@@ -9,7 +9,9 @@
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/KnownPorts.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/text/WTFString.h"
+#include "public/platform/WebContentSecurityPolicyStruct.h"
 
 namespace blink {
 
@@ -273,4 +275,7 @@
   visitor->Trace(policy_);
 }
 
+STATIC_ASSERT_ENUM(kWebWildcardDispositionNoWildcard, CSPSource::kNoWildcard);
+STATIC_ASSERT_ENUM(kWebWildcardDispositionHasWildcard, CSPSource::kHasWildcard);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp b/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
index 1843083..b0397b3 100644
--- a/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
+++ b/third_party/WebKit/Source/core/geometry/DOMMatrix.cpp
@@ -4,6 +4,8 @@
 
 #include "core/geometry/DOMMatrix.h"
 
+#include "core/dom/ExecutionContext.h"
+
 namespace blink {
 
 DOMMatrix* DOMMatrix::Create() {
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index f1a43450..5021887 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -93,6 +93,7 @@
 #include "public/platform/WebAudioSourceProvider.h"
 #include "public/platform/WebContentDecryptionModule.h"
 #include "public/platform/WebInbandTextTrack.h"
+#include "public/platform/WebMediaPlayer.h"
 #include "public/platform/WebMediaPlayerSource.h"
 #include "public/platform/WebMediaStream.h"
 #include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h"
@@ -4119,4 +4120,15 @@
     web_media_player_->BecameDominantVisibleContent(mostly_filling_viewport_);
 }
 
+STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveNothing,
+                   HTMLMediaElement::kHaveNothing);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveMetadata,
+                   HTMLMediaElement::kHaveMetadata);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveCurrentData,
+                   HTMLMediaElement::kHaveCurrentData);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveFutureData,
+                   HTMLMediaElement::kHaveFutureData);
+STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveEnoughData,
+                   HTMLMediaElement::kHaveEnoughData);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index 4569815..10cb9ef9 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -38,7 +38,6 @@
 #include "core/dom/AXObjectCache.h"
 #include "core/dom/Attribute.h"
 #include "core/dom/ElementTraversal.h"
-#include "core/dom/MutationCallback.h"
 #include "core/dom/MutationObserver.h"
 #include "core/dom/MutationObserverInit.h"
 #include "core/dom/MutationRecord.h"
@@ -2003,17 +2002,29 @@
 
 // PopupUpdater notifies updates of the specified SELECT element subtree to
 // a PopupMenu object.
-class HTMLSelectElement::PopupUpdater : public MutationCallback {
+class HTMLSelectElement::PopupUpdater : public MutationObserver::Delegate {
  public:
-  explicit PopupUpdater(HTMLSelectElement&);
-  DECLARE_VIRTUAL_TRACE();
+  explicit PopupUpdater(HTMLSelectElement& select)
+      : select_(select), observer_(MutationObserver::Create(this)) {
+    MutationObserverInit init;
+    init.setAttributeOldValue(true);
+    init.setAttributes(true);
+    // Observe only attributes which affect popup content.
+    init.setAttributeFilter({"disabled", "label", "selected", "value"});
+    init.setCharacterData(true);
+    init.setCharacterDataOldValue(true);
+    init.setChildList(true);
+    init.setSubtree(true);
+    observer_->observe(select_, init, ASSERT_NO_EXCEPTION);
+  }
 
-  void Dispose() { observer_->disconnect(); }
+  ExecutionContext* GetExecutionContext() const override {
+    return &select_->GetDocument();
+  }
 
- private:
-  void Call(const HeapVector<Member<MutationRecord>>& records,
-            MutationObserver*) override {
-    // We disconnect the MutationObserver when a popuup is closed.  However
+  void Deliver(const MutationRecordVector& records,
+               MutationObserver&) override {
+    // We disconnect the MutationObserver when a popup is closed.  However
     // MutationObserver can call back after disconnection.
     if (!select_->PopupIsVisible())
       return;
@@ -2031,41 +2042,19 @@
     }
   }
 
-  ExecutionContext* GetExecutionContext() const override {
-    return &select_->GetDocument();
+  void Dispose() { observer_->disconnect(); }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(select_);
+    visitor->Trace(observer_);
+    MutationObserver::Delegate::Trace(visitor);
   }
 
+ private:
   Member<HTMLSelectElement> select_;
   Member<MutationObserver> observer_;
 };
 
-HTMLSelectElement::PopupUpdater::PopupUpdater(HTMLSelectElement& select)
-    : select_(select) {
-  observer_ = MutationObserver::Create(this);
-  Vector<String> filter;
-  filter.ReserveCapacity(4);
-  // Observe only attributes which affect popup content.
-  filter.push_back(String("disabled"));
-  filter.push_back(String("label"));
-  filter.push_back(String("selected"));
-  filter.push_back(String("value"));
-  MutationObserverInit init;
-  init.setAttributeOldValue(true);
-  init.setAttributes(true);
-  init.setAttributeFilter(filter);
-  init.setCharacterData(true);
-  init.setCharacterDataOldValue(true);
-  init.setChildList(true);
-  init.setSubtree(true);
-  observer_->observe(&select, init, ASSERT_NO_EXCEPTION);
-}
-
-DEFINE_TRACE(HTMLSelectElement::PopupUpdater) {
-  visitor->Trace(select_);
-  visitor->Trace(observer_);
-  MutationCallback::Trace(visitor);
-}
-
 void HTMLSelectElement::ObserveTreeMutation() {
   DCHECK(!popup_updater_);
   popup_updater_ = new PopupUpdater(*this);
diff --git a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.h b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.h
index c630cfa..2a556b7 100644
--- a/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.h
+++ b/third_party/WebKit/Source/core/html/forms/ExternalPopupMenu.h
@@ -49,8 +49,8 @@
 class WebView;
 struct WebPopupMenuInfo;
 
-// The ExternalPopupMenu connects the actual implementation of the popup menu
-// to the WebCore popup menu.
+// The ExternalPopupMenu is a PopupMenu implementation for macOS and Android.
+// It uses a OS-native menu implementation.
 class CORE_EXPORT ExternalPopupMenu final : NON_EXPORTED_BASE(public PopupMenu),
                                             public WebExternalPopupMenuClient {
  public:
diff --git a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.h b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.h
index 81a7932d..56072f8 100644
--- a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.h
+++ b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.h
@@ -19,6 +19,8 @@
 class HTMLOptionElement;
 class HTMLSelectElement;
 
+// InternalPopupMenu is a PopupMenu implementation for platforms other than
+// macOS and Android. The UI is built with an HTML page inside a PagePopup.
 class CORE_EXPORT InternalPopupMenu final : NON_EXPORTED_BASE(public PopupMenu),
                                             public PagePopupClient {
  public:
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
index 0040a2e..422006a5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
@@ -60,6 +60,7 @@
     : LayoutBlockFlow(element),
       absolute_column_index_(kUnsetColumnIndex),
       cell_width_changed_(false),
+      is_spanning_collapsed_row_(false),
       collapsed_border_values_valid_(false),
       intrinsic_padding_before_(0),
       intrinsic_padding_after_(0) {
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
index 802b883..121c96e3 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
@@ -206,12 +206,14 @@
       break;
   }
 
+  WebURLRequest::RequestContext request_context =
+      resource_request.GetRequestContext();
+
   // We check the 'report-only' headers before upgrading the request (in
   // populateResourceRequest). We check the enforced headers here to ensure we
   // block things we ought to block.
   if (CheckCSPForRequestInternal(
-          resource_request.GetRequestContext(), url, options, reporting_policy,
-          redirect_status,
+          request_context, url, options, reporting_policy, redirect_status,
           ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
       ResourceRequestBlockedReason::kCSP) {
     return ResourceRequestBlockedReason::kCSP;
@@ -231,10 +233,11 @@
       !url.ProtocolIsData())
     return ResourceRequestBlockedReason::kOrigin;
 
+  WebURLRequest::FrameType frame_type = resource_request.GetFrameType();
+
   // Measure the number of legacy URL schemes ('ftp://') and the number of
   // embedded-credential ('http://user:password@...') resources embedded as
   // subresources.
-  WebURLRequest::FrameType frame_type = resource_request.GetFrameType();
   if (frame_type != WebURLRequest::kFrameTypeTopLevel) {
     bool is_subresource = frame_type == WebURLRequest::kFrameTypeNone;
     const SecurityOrigin* embedding_origin =
@@ -258,8 +261,9 @@
   // Check for mixed content. We do this second-to-last so that when folks block
   // mixed content via CSP, they don't get a mixed content warning, but a CSP
   // warning instead.
-  if (ShouldBlockFetchByMixedContentCheck(resource_request, url,
-                                          reporting_policy))
+  if (ShouldBlockFetchByMixedContentCheck(request_context, frame_type,
+                                          resource_request.GetRedirectStatus(),
+                                          url, reporting_policy))
     return ResourceRequestBlockedReason::kMixedContent;
 
   if (url.PotentiallyDanglingMarkup() && url.ProtocolIsInHTTPFamily()) {
@@ -272,8 +276,8 @@
   // proceed.
   if (GetSubresourceFilter() && type != Resource::kMainResource &&
       type != Resource::kImportResource) {
-    if (!GetSubresourceFilter()->AllowLoad(
-            url, resource_request.GetRequestContext(), reporting_policy)) {
+    if (!GetSubresourceFilter()->AllowLoad(url, request_context,
+                                           reporting_policy)) {
       return ResourceRequestBlockedReason::kSubresourceFilter;
     }
   }
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.h b/third_party/WebKit/Source/core/loader/BaseFetchContext.h
index 6187355..254de8e3 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.h
@@ -14,6 +14,7 @@
 #include "platform/weborigin/ReferrerPolicy.h"
 #include "platform/wtf/Optional.h"
 #include "public/platform/WebAddressSpace.h"
+#include "public/platform/WebURLRequest.h"
 
 namespace blink {
 
@@ -67,7 +68,9 @@
   virtual bool ShouldBypassMainWorldCSP() const = 0;
   virtual bool IsSVGImageChromeClient() const = 0;
   virtual bool ShouldBlockFetchByMixedContentCheck(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
+      WebURLRequest::FrameType,
+      ResourceRequest::RedirectStatus,
       const KURL&,
       SecurityViolationReportingPolicy) const = 0;
   virtual bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
@@ -85,6 +88,7 @@
   void PrintAccessDeniedMessage(const KURL&) const;
   void AddCSPHeaderIfNecessary(Resource::Type, ResourceRequest&);
 
+ private:
   // Utility methods that are used in default implement for CanRequest,
   // CanFollowRedirect and AllowResponse.
   ResourceRequestBlockedReason CanRequestInternal(
@@ -96,7 +100,6 @@
       FetchParameters::OriginRestriction,
       ResourceRequest::RedirectStatus) const;
 
- private:
   ResourceRequestBlockedReason CheckCSPForRequestInternal(
       WebURLRequest::RequestContext,
       const KURL&,
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
index 59066120..728a560 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
@@ -58,7 +58,9 @@
   void CountUsage(WebFeature) const override {}
   void CountDeprecation(WebFeature) const override {}
   bool ShouldBlockFetchByMixedContentCheck(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
+      WebURLRequest::FrameType,
+      ResourceRequest::RedirectStatus,
       const KURL&,
       SecurityViolationReportingPolicy) const override {
     return false;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index f8f8767..deb4331 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -940,15 +940,18 @@
 }
 
 bool FrameFetchContext::ShouldBlockFetchByMixedContentCheck(
-    const ResourceRequest& resource_request,
+    WebURLRequest::RequestContext request_context,
+    WebURLRequest::FrameType frame_type,
+    ResourceRequest::RedirectStatus redirect_status,
     const KURL& url,
     SecurityViolationReportingPolicy reporting_policy) const {
   if (IsDetached()) {
     // TODO(yhirano): Implement the detached case.
     return false;
   }
-  return MixedContentChecker::ShouldBlockFetch(GetFrame(), resource_request,
-                                               url, reporting_policy);
+  return MixedContentChecker::ShouldBlockFetch(GetFrame(), request_context,
+                                               frame_type, redirect_status, url,
+                                               reporting_policy);
 }
 
 bool FrameFetchContext::ShouldBlockFetchAsCredentialedSubresource(
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index 2d178dfd..89bfdf9 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -193,7 +193,9 @@
   void CountUsage(WebFeature) const override;
   void CountDeprecation(WebFeature) const override;
   bool ShouldBlockFetchByMixedContentCheck(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
+      WebURLRequest::FrameType,
+      ResourceRequest::RedirectStatus,
       const KURL&,
       SecurityViolationReportingPolicy) const override;
   bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
diff --git a/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp b/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
index 9c81160..0451738 100644
--- a/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
+++ b/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
@@ -426,7 +426,9 @@
 bool MixedContentChecker::ShouldBlockFetchOnWorker(
     WorkerOrWorkletGlobalScope* global_scope,
     WebWorkerFetchContext* worker_fetch_context,
-    const ResourceRequest& request,
+    WebURLRequest::RequestContext request_context,
+    WebURLRequest::FrameType frame_type,
+    ResourceRequest::RedirectStatus redirect_status,
     const KURL& url,
     SecurityViolationReportingPolicy reporting_policy) {
   if (!MixedContentChecker::IsMixedContent(global_scope->GetSecurityOrigin(),
@@ -437,7 +439,7 @@
   UseCounter::Count(global_scope, WebFeature::kMixedContentPresent);
   UseCounter::Count(global_scope, WebFeature::kMixedContentBlockable);
   if (ContentSecurityPolicy* policy = global_scope->GetContentSecurityPolicy())
-    policy->ReportMixedContent(url, request.GetRedirectStatus());
+    policy->ReportMixedContent(url, redirect_status);
 
   // Blocks all mixed content request from worklets.
   // TODO(horo): Revise this when the spec is updated.
@@ -477,7 +479,7 @@
 
   if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
     LogToConsoleAboutFetch(global_scope, global_scope->Url(), url,
-                           request.GetRequestContext(), allowed, nullptr);
+                           request_context, allowed, nullptr);
   }
   return !allowed;
 }
@@ -691,7 +693,7 @@
   if (!mixed_frame)
     return WebMixedContentContextType::kNotMixedContent;
 
-  // See comment in shouldBlockFetch() about loading the main resource of a
+  // See comment in ShouldBlockFetch() about loading the main resource of a
   // subframe.
   if (request.GetFrameType() == WebURLRequest::kFrameTypeNested &&
       !SchemeRegistry::ShouldTreatURLSchemeAsCORSEnabled(
diff --git a/third_party/WebKit/Source/core/loader/MixedContentChecker.h b/third_party/WebKit/Source/core/loader/MixedContentChecker.h
index 0720856e..40ea9a44 100644
--- a/third_party/WebKit/Source/core/loader/MixedContentChecker.h
+++ b/third_party/WebKit/Source/core/loader/MixedContentChecker.h
@@ -72,20 +72,12 @@
                                const KURL&,
                                SecurityViolationReportingPolicy =
                                    SecurityViolationReportingPolicy::kReport);
-  static bool ShouldBlockFetch(
-      LocalFrame* frame,
-      const ResourceRequest& request,
-      const KURL& url,
-      SecurityViolationReportingPolicy reporting_policy =
-          SecurityViolationReportingPolicy::kReport) {
-    return ShouldBlockFetch(frame, request.GetRequestContext(),
-                            request.GetFrameType(), request.GetRedirectStatus(),
-                            url, reporting_policy);
-  }
 
   static bool ShouldBlockFetchOnWorker(WorkerOrWorkletGlobalScope*,
                                        WebWorkerFetchContext*,
-                                       const ResourceRequest&,
+                                       WebURLRequest::RequestContext,
+                                       WebURLRequest::FrameType,
+                                       ResourceRequest::RedirectStatus,
                                        const KURL&,
                                        SecurityViolationReportingPolicy);
 
diff --git a/third_party/WebKit/Source/core/loader/NavigationPolicy.cpp b/third_party/WebKit/Source/core/loader/NavigationPolicy.cpp
index 88dabaa15..3650c84 100644
--- a/third_party/WebKit/Source/core/loader/NavigationPolicy.cpp
+++ b/third_party/WebKit/Source/core/loader/NavigationPolicy.cpp
@@ -32,6 +32,7 @@
 
 #include "build/build_config.h"
 #include "platform/wtf/Assertions.h"
+#include "public/web/WebNavigationPolicy.h"
 
 namespace blink {
 
@@ -64,4 +65,14 @@
   return true;
 }
 
+STATIC_ASSERT_ENUM(kWebNavigationPolicyIgnore, kNavigationPolicyIgnore);
+STATIC_ASSERT_ENUM(kWebNavigationPolicyDownload, kNavigationPolicyDownload);
+STATIC_ASSERT_ENUM(kWebNavigationPolicyCurrentTab, kNavigationPolicyCurrentTab);
+STATIC_ASSERT_ENUM(kWebNavigationPolicyNewBackgroundTab,
+                   kNavigationPolicyNewBackgroundTab);
+STATIC_ASSERT_ENUM(kWebNavigationPolicyNewForegroundTab,
+                   kNavigationPolicyNewForegroundTab);
+STATIC_ASSERT_ENUM(kWebNavigationPolicyNewWindow, kNavigationPolicyNewWindow);
+STATIC_ASSERT_ENUM(kWebNavigationPolicyNewPopup, kNavigationPolicyNewPopup);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
index 0f7fbbd..2c8de51f 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -148,12 +148,14 @@
 }
 
 bool WorkerFetchContext::ShouldBlockFetchByMixedContentCheck(
-    const ResourceRequest& resource_request,
+    WebURLRequest::RequestContext request_context,
+    WebURLRequest::FrameType frame_type,
+    ResourceRequest::RedirectStatus redirect_status,
     const KURL& url,
     SecurityViolationReportingPolicy reporting_policy) const {
   return MixedContentChecker::ShouldBlockFetchOnWorker(
-      global_scope_, web_context_.get(), resource_request, url,
-      reporting_policy);
+      global_scope_, web_context_.get(), request_context, frame_type,
+      redirect_status, url, reporting_policy);
 }
 
 bool WorkerFetchContext::ShouldBlockFetchAsCredentialedSubresource(
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
index 36671224..3eb9b34 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
@@ -49,7 +49,9 @@
   void CountUsage(WebFeature) const override;
   void CountDeprecation(WebFeature) const override;
   bool ShouldBlockFetchByMixedContentCheck(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
+      WebURLRequest::FrameType,
+      ResourceRequest::RedirectStatus,
       const KURL&,
       SecurityViolationReportingPolicy) const override;
   bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
diff --git a/third_party/WebKit/Source/core/page/PageVisibilityState.cpp b/third_party/WebKit/Source/core/page/PageVisibilityState.cpp
index 7af36ff..087558b 100644
--- a/third_party/WebKit/Source/core/page/PageVisibilityState.cpp
+++ b/third_party/WebKit/Source/core/page/PageVisibilityState.cpp
@@ -29,6 +29,8 @@
  */
 
 #include "core/page/PageVisibilityState.h"
+#include "platform/wtf/Assertions.h"
+#include "public/platform/WebPageVisibilityState.h"
 
 namespace blink {
 
@@ -46,4 +48,9 @@
   return String();
 }
 
+STATIC_ASSERT_ENUM(kWebPageVisibilityStateVisible, kPageVisibilityStateVisible);
+STATIC_ASSERT_ENUM(kWebPageVisibilityStateHidden, kPageVisibilityStateHidden);
+STATIC_ASSERT_ENUM(kWebPageVisibilityStatePrerender,
+                   kPageVisibilityStatePrerender);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
index d50de163..043ff16 100644
--- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
+++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
@@ -518,6 +518,7 @@
     }
   } else {
     SetHasNonLocalGeometry();
+    offset_in_background_ = LayoutPoint();
     positioning_area = FixedAttachmentPositioningArea(box_, container, flags);
     SetDestRect(positioning_area);
   }
diff --git a/third_party/WebKit/Source/core/streams/CommonOperations.js b/third_party/WebKit/Source/core/streams/CommonOperations.js
index 24ed070..ac6e3106 100644
--- a/third_party/WebKit/Source/core/streams/CommonOperations.js
+++ b/third_party/WebKit/Source/core/streams/CommonOperations.js
@@ -35,6 +35,23 @@
   }
 
   //
+  // Assert is not normally enabled, to avoid the space and time overhead. To
+  // enable, uncomment this definition and then in the file you wish to enable
+  // asserts for, uncomment the assert statements and add this definition:
+  // const assert = pred => binding.SimpleAssert(pred);
+  //
+  // binding.SimpleAssert = pred => {
+  //   if (pred) {
+  //     return;
+  //   }
+  //   v8.log('\n\n\n  *** ASSERTION FAILURE ***\n\n');
+  //   v8.logStackTrace();
+  //   v8.log('**************************************************\n\n');
+  //   class StreamsAssertionError extends Error {}
+  //   throw new StreamsAssertionError('Streams Assertion Failure');
+  // }
+
+  //
   // Promise-manipulation functions
   //
 
diff --git a/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp b/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp
index ad694a0..708b2b99 100644
--- a/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp
+++ b/third_party/WebKit/Source/modules/filesystem/DOMFileSystemBase.cpp
@@ -45,11 +45,13 @@
 #include "modules/filesystem/FileSystemCallbacks.h"
 #include "modules/filesystem/MetadataCallback.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/text/StringBuilder.h"
 #include "platform/wtf/text/TextEncoding.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebFileSystem.h"
 #include "public/platform/WebFileSystemCallbacks.h"
+#include "public/platform/WebSecurityOrigin.h"
 
 namespace blink {
 
@@ -467,4 +469,9 @@
   return FileSystem()->WaitForAdditionalResult(callbacks_id);
 }
 
+STATIC_ASSERT_ENUM(WebFileSystem::kTypeTemporary, kFileSystemTypeTemporary);
+STATIC_ASSERT_ENUM(WebFileSystem::kTypePersistent, kFileSystemTypePersistent);
+STATIC_ASSERT_ENUM(WebFileSystem::kTypeExternal, kFileSystemTypeExternal);
+STATIC_ASSERT_ENUM(WebFileSystem::kTypeIsolated, kFileSystemTypeIsolated);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
index b6396a0..6e6a7a1 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -27,7 +27,6 @@
 #include "modules/media_controls/MediaControlsImpl.h"
 
 #include "bindings/core/v8/ExceptionState.h"
-#include "core/dom/MutationCallback.h"
 #include "core/dom/MutationObserver.h"
 #include "core/dom/MutationObserverInit.h"
 #include "core/dom/MutationRecord.h"
@@ -152,7 +151,7 @@
          document.GetSettings()->GetPreferHiddenVolumeControls();
 }
 
-}  // anonymous namespace
+}  // namespace
 
 class MediaControlsImpl::BatchedControlUpdate {
   WTF_MAKE_NONCOPYABLE(BatchedControlUpdate);
@@ -208,31 +207,23 @@
 // Observes changes to the HTMLMediaElement attributes that affect controls.
 // Currently only observes the disableRemotePlayback attribute.
 class MediaControlsImpl::MediaElementMutationCallback
-    : public MutationCallback {
+    : public MutationObserver::Delegate {
  public:
   explicit MediaElementMutationCallback(MediaControlsImpl* controls)
-      : controls_(controls) {
-    observer_ = MutationObserver::Create(this);
-    Vector<String> filter;
-    filter.push_back(HTMLNames::disableremoteplaybackAttr.ToString());
+      : controls_(controls), observer_(MutationObserver::Create(this)) {
     MutationObserverInit init;
     init.setAttributeOldValue(true);
     init.setAttributes(true);
-    init.setAttributeFilter(filter);
+    init.setAttributeFilter({HTMLNames::disableremoteplaybackAttr.ToString()});
     observer_->observe(&controls_->MediaElement(), init, ASSERT_NO_EXCEPTION);
   }
 
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    visitor->Trace(controls_);
-    visitor->Trace(observer_);
-    MutationCallback::Trace(visitor);
+  ExecutionContext* GetExecutionContext() const override {
+    return &controls_->GetDocument();
   }
 
-  void Disconnect() { observer_->disconnect(); }
-
- private:
-  void Call(const HeapVector<Member<MutationRecord>>& records,
-            MutationObserver*) override {
+  void Deliver(const MutationRecordVector& records,
+               MutationObserver&) override {
     for (const auto& record : records) {
       if (record->type() != "attributes")
         continue;
@@ -248,10 +239,15 @@
     }
   }
 
-  ExecutionContext* GetExecutionContext() const override {
-    return &controls_->GetDocument();
+  void Disconnect() { observer_->disconnect(); }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(controls_);
+    visitor->Trace(observer_);
+    MutationObserver::Delegate::Trace(visitor);
   }
 
+ private:
   Member<MediaControlsImpl> controls_;
   Member<MutationObserver> observer_;
 };
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionDescriptor.idl b/third_party/WebKit/Source/modules/permissions/PermissionDescriptor.idl
index 37cfa865..80735f0 100644
--- a/third_party/WebKit/Source/modules/permissions/PermissionDescriptor.idl
+++ b/third_party/WebKit/Source/modules/permissions/PermissionDescriptor.idl
@@ -7,7 +7,11 @@
     "midi",
     "notifications",
     "push",
-    "background-sync"
+    "background-sync",
+    "ambient-light-sensor",
+    "accelerometer",
+    "gyroscope",
+    "magnetometer",
 };
 
 // The PermissionDescriptor dictionary is a base to describe permissions. Some
diff --git a/third_party/WebKit/Source/modules/permissions/Permissions.cpp b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
index 986ce16e..1f19645 100644
--- a/third_party/WebKit/Source/modules/permissions/Permissions.cpp
+++ b/third_party/WebKit/Source/modules/permissions/Permissions.cpp
@@ -21,6 +21,7 @@
 #include "modules/permissions/PermissionDescriptor.h"
 #include "modules/permissions/PermissionStatus.h"
 #include "modules/permissions/PermissionUtils.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/wtf/Functional.h"
 #include "platform/wtf/NotFound.h"
 #include "platform/wtf/PtrUtil.h"
@@ -91,6 +92,16 @@
   }
   if (name == "background-sync")
     return CreatePermissionDescriptor(PermissionName::BACKGROUND_SYNC);
+  // TODO(riju): Remove runtime flag check when Generic Sensor feature is
+  // stable.
+  if (name == "ambient-light-sensor" || name == "accelerometer" ||
+      name == "gyroscope" || name == "magnetometer") {
+    if (!RuntimeEnabledFeatures::SensorEnabled()) {
+      exception_state.ThrowTypeError("GenericSensor flag is not enabled.");
+      return nullptr;
+    }
+    return CreatePermissionDescriptor(PermissionName::SENSORS);
+  }
 
   return nullptr;
 }
diff --git a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
index 90c86fe9..5a7a79b 100644
--- a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
+++ b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
@@ -114,4 +114,9 @@
                        success_callback, error_callback);
 }
 
+STATIC_ASSERT_ENUM(kWebStorageQuotaTypeTemporary,
+                   DeprecatedStorageQuota::kTemporary);
+STATIC_ASSERT_ENUM(kWebStorageQuotaTypePersistent,
+                   DeprecatedStorageQuota::kPersistent);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/quota/StorageManager.cpp b/third_party/WebKit/Source/modules/quota/StorageManager.cpp
index 56ca095..98c6bd4 100644
--- a/third_party/WebKit/Source/modules/quota/StorageManager.cpp
+++ b/third_party/WebKit/Source/modules/quota/StorageManager.cpp
@@ -14,8 +14,10 @@
 #include "modules/permissions/PermissionUtils.h"
 #include "modules/quota/StorageEstimate.h"
 #include "platform/StorageQuotaCallbacks.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/Functional.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebStorageQuotaError.h"
 
 namespace blink {
 
@@ -166,4 +168,10 @@
   resolver->Resolve(status == PermissionStatus::GRANTED);
 }
 
+STATIC_ASSERT_ENUM(kWebStorageQuotaErrorNotSupported, kNotSupportedError);
+STATIC_ASSERT_ENUM(kWebStorageQuotaErrorInvalidModification,
+                   kInvalidModificationError);
+STATIC_ASSERT_ENUM(kWebStorageQuotaErrorInvalidAccess, kInvalidAccessError);
+STATIC_ASSERT_ENUM(kWebStorageQuotaErrorAbort, kAbortError);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp b/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp
index 3491497..438f9ed 100644
--- a/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp
+++ b/third_party/WebKit/Source/modules/speech/SpeechRecognitionError.cpp
@@ -24,6 +24,8 @@
  */
 
 #include "modules/speech/SpeechRecognitionError.h"
+#include "platform/wtf/Assertions.h"
+#include "public/web/WebSpeechRecognizerClient.h"
 
 namespace blink {
 
@@ -84,4 +86,23 @@
   return EventNames::SpeechRecognitionError;
 }
 
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kOtherError,
+                   SpeechRecognitionError::kErrorCodeOther);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNoSpeechError,
+                   SpeechRecognitionError::kErrorCodeNoSpeech);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kAbortedError,
+                   SpeechRecognitionError::kErrorCodeAborted);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kAudioCaptureError,
+                   SpeechRecognitionError::kErrorCodeAudioCapture);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNetworkError,
+                   SpeechRecognitionError::kErrorCodeNetwork);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNotAllowedError,
+                   SpeechRecognitionError::kErrorCodeNotAllowed);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kServiceNotAllowedError,
+                   SpeechRecognitionError::kErrorCodeServiceNotAllowed);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kBadGrammarError,
+                   SpeechRecognitionError::kErrorCodeBadGrammar);
+STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kLanguageNotSupportedError,
+                   SpeechRecognitionError::kErrorCodeLanguageNotSupported);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp
index 580753a..dddafd5 100644
--- a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp
@@ -172,15 +172,6 @@
     }
   }
 }
-
-bool AnalyserHandler::RequiresTailProcessing() const {
-  // Tail time is always non-zero so tail processing is required.
-  return true;
-}
-
-double AnalyserHandler::TailTime() const {
-  return 32768 / static_cast<double>(Context()->sampleRate());
-};
 // ----------------------------------------------------------------
 
 AnalyserNode::AnalyserNode(BaseAudioContext& context)
diff --git a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h
index 11765f5..3684eb91 100644
--- a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h
@@ -82,9 +82,6 @@
   // correct time data.
   void UpdatePullStatus() override;
 
-  bool RequiresTailProcessing() const final;
-  double TailTime() const final;
-
  private:
   AnalyserHandler(AudioNode&, float sample_rate);
   bool PropagatesSilence() const {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.cpp
index 14b313df..b763cde4 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.cpp
@@ -151,10 +151,6 @@
   return Output(0).NumberOfChannels();
 }
 
-bool AudioBasicProcessorHandler::RequiresTailProcessing() const {
-  return processor_->RequiresTailProcessing();
-}
-
 double AudioBasicProcessorHandler::TailTime() const {
   return processor_->TailTime();
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.h b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.h
index 9afb9f99..ae145b8 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandler.h
@@ -67,7 +67,6 @@
                              AudioNode&,
                              float sample_rate,
                              std::unique_ptr<AudioProcessor>);
-  bool RequiresTailProcessing() const final;
   double TailTime() const final;
   double LatencyTime() const final;
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp
index 4079341..2c47c71 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp
@@ -21,7 +21,6 @@
   void Reset() override {}
   void SetNumberOfChannels(unsigned) override {}
   unsigned NumberOfChannels() const override { return number_of_channels_; }
-  bool RequiresTailProcessing() const override { return true; }
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
 };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
index d40130e9..2289766 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
@@ -231,6 +231,12 @@
                       grain_offset_ + grain_duration_, buffer_sample_rate)
                 : buffer_length;
 
+  // This is a HACK to allow for HRTF tail-time - avoids glitch at end.
+  // FIXME: implement tailTime for each AudioNode for a more general solution to
+  // this problem, https://bugs.webkit.org/show_bug.cgi?id=77224
+  if (is_grain_)
+    end_frame += 512;
+
   // Do some sanity checking.
   if (end_frame > buffer_length)
     end_frame = buffer_length;
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
index 0e2c92e4..64cc1d5 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
@@ -90,6 +90,8 @@
   is_initialized_ = false;
 }
 
+void AudioHandler::ClearInternalStateWhenDisabled() {}
+
 void AudioHandler::Dispose() {
   DCHECK(IsMainThread());
   DCHECK(Context()->IsGraphOwner());
@@ -323,6 +325,12 @@
     PullInputs(frames_to_process);
 
     bool silent_inputs = InputsAreSilent();
+    if (!silent_inputs) {
+      last_non_silent_time_ =
+          (Context()->CurrentSampleFrame() + frames_to_process) /
+          static_cast<double>(Context()->sampleRate());
+    }
+
     if (silent_inputs && PropagatesSilence()) {
       SilenceOutputs();
       // AudioParams still need to be processed so that the value can be updated
@@ -337,15 +345,6 @@
       UnsilenceOutputs();
       Process(frames_to_process);
     }
-
-    if (!silent_inputs) {
-      // Update |last_non_silent_time| AFTER processing this block.
-      // Doing it before causes |PropagateSilence()| to be one render
-      // quantum longer than necessary.
-      last_non_silent_time_ =
-          (Context()->CurrentSampleFrame() + frames_to_process) /
-          static_cast<double>(Context()->sampleRate());
-    }
   }
 }
 
@@ -403,10 +402,6 @@
 }
 
 void AudioHandler::DisableOutputsIfNecessary() {
-  // This function calls other functions that require graph ownership,
-  // so assert that this needs graph ownership too.
-  DCHECK(Context()->IsGraphOwner());
-
   // Disable outputs if appropriate. We do this if the number of connections is
   // 0 or 1. The case of 0 is from deref() where there are no connections left.
   // The case of 1 is from AudioNodeInput::disable() where we want to disable
@@ -423,35 +418,36 @@
     // they're connected to.  disable() can recursively deref connections (and
     // call disable()) down a whole chain of connected nodes.
 
-    // If a node requires tail processing, we defer the disabling of
-    // the outputs so that the tail for the node can be output.
-    // Otherwise, we can disable the outputs right away.
-    if (RequiresTailProcessing()) {
-      if (Context()->ContextState() !=
-          BaseAudioContext::AudioContextState::kClosed) {
-        Context()->GetDeferredTaskHandler().AddTailProcessingHandler(this);
-      }
-    } else {
-      DisableOutputs();
+    // TODO(rtoy,hongchan): we need special cases the convolver, delay, biquad,
+    // and IIR since they have a significant tail-time and shouldn't be
+    // disconnected simply because they no longer have any input connections.
+    // This needs to be handled more generally where AudioNodes have a tailTime
+    // attribute. Then the AudioNode only needs to remain "active" for tailTime
+    // seconds after there are no longer any active connections.
+    //
+    // The analyser node also requires special handling because we
+    // need the internal state to be updated for the time and FFT data
+    // even if it has no connections.
+    if (GetNodeType() != kNodeTypeConvolver &&
+        GetNodeType() != kNodeTypeDelay &&
+        GetNodeType() != kNodeTypeBiquadFilter &&
+        GetNodeType() != kNodeTypeIIRFilter &&
+        GetNodeType() != kNodeTypeAnalyser) {
+      is_disabled_ = true;
+      ClearInternalStateWhenDisabled();
+      for (auto& output : outputs_)
+        output->Disable();
     }
   }
 }
 
-void AudioHandler::DisableOutputs() {
-  is_disabled_ = true;
-  for (auto& output : outputs_)
-    output->Disable();
-}
-
 void AudioHandler::MakeConnection() {
   AtomicIncrement(&connection_ref_count_);
 
-  Context()->GetDeferredTaskHandler().RemoveTailProcessingHandler(this);
-
 #if DEBUG_AUDIONODE_REFERENCES
-  fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::ref   %3d [%3d] @%.15g\n",
+  fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::ref   %3d [%3d]\n",
           Context(), this, GetNodeType(), connection_ref_count_,
-          node_count_[GetNodeType()], Context()->currentTime());
+          node_count_[GetNodeType()]);
 #endif
   // See the disabling code in disableOutputsIfNecessary(). This handles
   // the case where a node is being re-connected after being used at least
@@ -487,9 +483,9 @@
   AtomicDecrement(&connection_ref_count_);
 
 #if DEBUG_AUDIONODE_REFERENCES
-  fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::deref %3d [%3d] @%.15g\n",
+  fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::deref %3d [%3d]\n",
           Context(), this, GetNodeType(), connection_ref_count_,
-          node_count_[GetNodeType()], Context()->currentTime());
+          node_count_[GetNodeType()]);
 #endif
 
   if (!connection_ref_count_)
@@ -515,31 +511,6 @@
 
 #endif  // DEBUG_AUDIONODE_REFERENCES
 
-#if DEBUG_AUDIONODE_REFERENCES > 1
-void AudioHandler::TailProcessingDebug(const char* note) {
-  fprintf(stderr, "[%16p]: %16p: %2d: %s %d @%.15g", Context(), this,
-          GetNodeType(), note, connection_ref_count_, Context()->currentTime());
-
-  // If we're on the audio thread, we can print out the tail and
-  // latency times (because these methods can only be called from the
-  // audio thread.)
-  if (Context()->IsAudioThread()) {
-    fprintf(stderr, ", tail=%.15g + %.15g, last=%.15g\n", TailTime(),
-            LatencyTime(), last_non_silent_time_);
-  }
-
-  fprintf(stderr, "\n");
-}
-
-void AudioHandler::AddTailProcessingDebug() {
-  TailProcessingDebug("addTail");
-}
-
-void AudioHandler::RemoveTailProcessingDebug() {
-  TailProcessingDebug("remTail");
-}
-#endif  // DEBUG_AUDIONODE_REFERENCES > 1
-
 void AudioHandler::UpdateChannelCountMode() {
   channel_count_mode_ = new_channel_count_mode_;
   UpdateChannelsForInputs();
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
index cb3d77ce..581e30d2 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
@@ -36,7 +36,6 @@
 #include "platform/wtf/ThreadSafeRefCounted.h"
 #include "platform/wtf/Vector.h"
 
-// Higher values produce more debugging output.
 #define DEBUG_AUDIONODE_REFERENCES 0
 
 namespace blink {
@@ -152,6 +151,14 @@
   virtual void Initialize();
   virtual void Uninitialize();
 
+  // Clear internal state when the node is disabled. When a node is disabled,
+  // it is no longer pulled so any internal state is never updated. But some
+  // nodes (DynamicsCompressorNode) have internal state that is still
+  // accessible by the user. Update the internal state as if the node were
+  // still connected but processing all zeroes. This gives a consistent view
+  // to the user.
+  virtual void ClearInternalStateWhenDisabled();
+
   bool IsInitialized() const { return is_initialized_; }
 
   unsigned NumberOfInputs() const { return inputs_.size(); }
@@ -181,18 +188,6 @@
 #if DEBUG_AUDIONODE_REFERENCES
   static void PrintNodeCounts();
 #endif
-#if DEBUG_AUDIONODE_REFERENCES > 1
-  void TailProcessingDebug(const char* note);
-  void AddTailProcessingDebug();
-  void RemoveTailProcessingDebug();
-#endif
-
-  // True if the node has a tail time or latency time that requires
-  // special tail processing to behave properly.  Ideally, this can be
-  // checked using TailTime and LatencyTime, but these aren't
-  // available on the main thread, and the tail processing check can
-  // happen on the main thread.
-  virtual bool RequiresTailProcessing() const = 0;
 
   // TailTime() is the length of time (not counting latency time) where
   // non-zero output may occur after continuous silent input.
@@ -217,7 +212,6 @@
 
   void EnableOutputsIfNecessary();
   void DisableOutputsIfNecessary();
-  void DisableOutputs();
 
   unsigned long ChannelCount();
   virtual void SetChannelCount(unsigned long, ExceptionState&);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h
index a9fa24e..7c515ba 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h
@@ -81,10 +81,6 @@
 
   bool HasFinished() const { return GetPlaybackState() == FINISHED_STATE; }
 
-  // Source nodes don't have tail or latency times so no tail
-  // processing needed.
-  bool RequiresTailProcessing() const final { return false; }
-
  protected:
   // Get frame information for the current time quantum.
   // We handle the transition into PLAYING_STATE and FINISHED_STATE here,
diff --git a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp
index ae6a35bc..1b2c73d 100644
--- a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.cpp
@@ -208,15 +208,6 @@
                                phase_response);
 }
 
-bool BiquadDSPKernel::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero. This is for simplicity and because TailTime() is 0
-  // basically only when the filter response H(z) = 0 or H(z) = 1. And
-  // it's ok to return true. It just means the node lives a little
-  // longer than strictly necessary.
-  return true;
-}
-
 double BiquadDSPKernel::TailTime() const {
   return tail_time_;
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h
index f29535e..915bf2e 100644
--- a/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h
+++ b/third_party/WebKit/Source/modules/webaudio/BiquadDSPKernel.h
@@ -56,7 +56,6 @@
                             float* mag_response,
                             float* phase_response);
 
-  bool RequiresTailProcessing() const final;
   double TailTime() const override;
   double LatencyTime() const override;
 
diff --git a/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h b/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h
index 0b64650e..3eadaafd 100644
--- a/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h
@@ -47,9 +47,9 @@
   void SetChannelCount(unsigned long, ExceptionState&) final;
   void SetChannelCountMode(const String&, ExceptionState&) final;
 
+  // AudioNode
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
-  bool RequiresTailProcessing() const final { return false; }
 
  private:
   ChannelMergerHandler(AudioNode&,
diff --git a/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h b/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h
index 9f32478..f0bd795 100644
--- a/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h
@@ -45,9 +45,9 @@
   void SetChannelCount(unsigned long, ExceptionState&) final;
   void SetChannelCountMode(const String&, ExceptionState&) final;
 
+  // AudioNode
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
-  bool RequiresTailProcessing() const final { return false; }
 
  private:
   ChannelSplitterHandler(AudioNode&,
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
index 11934f1..c59976b 100644
--- a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
@@ -164,12 +164,6 @@
   return buffer_.Get();
 }
 
-bool ConvolverHandler::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero.
-  return true;
-}
-
 double ConvolverHandler::TailTime() const {
   MutexTryLocker try_locker(process_lock_);
   if (try_locker.Locked())
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h
index c717658..400387a9 100644
--- a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h
@@ -64,7 +64,6 @@
   ConvolverHandler(AudioNode&, float sample_rate);
   double TailTime() const override;
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const final;
 
   // Determine how many output channels to use from the number of
   // input channels and the number of channels in the impulse response
diff --git a/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h
index ece6145..a7ceeb8c 100644
--- a/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h
@@ -59,9 +59,9 @@
   double SampleRate() const override;
   int FramesPerBuffer() const override;
 
+  // AudioNode
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
-  bool RequiresTailProcessing() const final { return false; }
 
  private:
   explicit DefaultAudioDestinationHandler(AudioNode&,
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
index 0f1dedc..88ad88cc 100644
--- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
@@ -169,48 +169,6 @@
     rendering_automatic_pull_nodes_[i]->ProcessIfNecessary(frames_to_process);
 }
 
-void DeferredTaskHandler::AddTailProcessingHandler(
-    RefPtr<AudioHandler> handler) {
-  DCHECK(IsGraphOwner());
-
-  if (!tail_processing_handlers_.Contains(handler)) {
-#if DEBUG_AUDIONODE_REFERENCES > 1
-    handler->AddTailProcessingDebug();
-#endif
-    tail_processing_handlers_.push_back(std::move(handler));
-  }
-}
-
-void DeferredTaskHandler::RemoveTailProcessingHandler(
-    RefPtr<AudioHandler> handler) {
-  DCHECK(IsGraphOwner());
-
-  size_t index = tail_processing_handlers_.Find(handler);
-  if (index != kNotFound) {
-#if DEBUG_AUDIONODE_REFERENCES > 1
-    handler->RemoveTailProcessingDebug();
-#endif
-    handler->DisableOutputs();
-    tail_processing_handlers_.erase(index);
-  }
-}
-
-void DeferredTaskHandler::UpdateTailProcessingHandlers() {
-  DCHECK(IsAudioThread());
-
-  for (unsigned k = tail_processing_handlers_.size(); k > 0; --k) {
-    RefPtr<AudioHandler> handler = tail_processing_handlers_[k - 1];
-    if (handler->PropagatesSilence()) {
-#if DEBUG_AUDIONODE_REFERENCES
-      fprintf(stderr, "[%16p]: %16p: %2d: updateTail @%.15g\n",
-              handler->Context(), handler.Get(), handler->GetNodeType(),
-              handler->Context()->currentTime());
-#endif
-      RemoveTailProcessingHandler(handler);
-    }
-  }
-}
-
 void DeferredTaskHandler::AddChangedChannelCountMode(AudioHandler* node) {
   DCHECK(IsGraphOwner());
   DCHECK(IsMainThread());
@@ -272,7 +230,6 @@
   HandleDirtyAudioSummingJunctions();
   HandleDirtyAudioNodeOutputs();
   UpdateAutomaticPullNodes();
-  UpdateTailProcessingHandlers();
 }
 
 void DeferredTaskHandler::ContextWillBeDestroyed() {
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h
index e24714b..8249f6b 100644
--- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h
+++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h
@@ -104,14 +104,6 @@
   void RequestToDeleteHandlersOnMainThread();
   void ClearHandlersToBeDeleted();
 
-  // If |node| requires tail processing, add it to the list of tail
-  // nodes so the tail is processed.
-  void AddTailProcessingHandler(RefPtr<AudioHandler>);
-
-  // Remove |node| from the list of tail nodes (because the tail
-  // processing is complete).
-  void RemoveTailProcessingHandler(RefPtr<AudioHandler>);
-
   //
   // Thread Safety and Graph Locking:
   //
@@ -178,10 +170,6 @@
   void HandleDirtyAudioNodeOutputs();
   void DeleteHandlersOnMainThread();
 
-  // Check tail processing handlers and remove any handler if the tail
-  // has been processed.
-  void UpdateTailProcessingHandlers();
-
   // For the sake of thread safety, we maintain a seperate Vector of automatic
   // pull nodes for rendering in m_renderingAutomaticPullNodes.  It will be
   // copied from m_automaticPullNodes by updateAutomaticPullNodes() at the
@@ -210,9 +198,6 @@
   Vector<RefPtr<AudioHandler>> rendering_orphan_handlers_;
   Vector<RefPtr<AudioHandler>> deletable_orphan_handlers_;
 
-  // Nodes that are processing its tail.
-  Vector<RefPtr<AudioHandler>> tail_processing_handlers_;
-
   // Graph locking.
   RecursiveMutex context_graph_mutex_;
   volatile ThreadIdentifier audio_thread_;
diff --git a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp
index 6b1ae74b..031b484 100644
--- a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp
@@ -121,10 +121,8 @@
       Context()->sampleRate(), defaultNumberOfOutputChannels));
 }
 
-bool DynamicsCompressorHandler::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero.
-  return true;
+void DynamicsCompressorHandler::ClearInternalStateWhenDisabled() {
+  reduction_ = 0;
 }
 
 double DynamicsCompressorHandler::TailTime() const {
diff --git a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h
index dcbcdf4..f488178 100644
--- a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h
@@ -55,6 +55,7 @@
   void Process(size_t frames_to_process) override;
   void ProcessOnlyAudioParams(size_t frames_to_process) override;
   void Initialize() override;
+  void ClearInternalStateWhenDisabled() override;
 
   float ReductionValue() const { return reduction_; }
 
@@ -66,7 +67,6 @@
                             AudioParamHandler& ratio,
                             AudioParamHandler& attack,
                             AudioParamHandler& release);
-  bool RequiresTailProcessing() const final;
   double TailTime() const override;
   double LatencyTime() const override;
 
diff --git a/third_party/WebKit/Source/modules/webaudio/GainNode.h b/third_party/WebKit/Source/modules/webaudio/GainNode.h
index b4f20ed..bbda915 100644
--- a/third_party/WebKit/Source/modules/webaudio/GainNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/GainNode.h
@@ -57,7 +57,6 @@
   // AudioNode
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
-  bool RequiresTailProcessing() const final { return false; }
 
  private:
   GainHandler(AudioNode&, float sample_rate, AudioParamHandler& gain);
diff --git a/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.cpp b/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.cpp
index c6c1ee4..bffebbd 100644
--- a/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.cpp
@@ -46,12 +46,6 @@
                             phase_response);
 }
 
-bool IIRDSPKernel::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero.
-  return true;
-}
-
 double IIRDSPKernel::TailTime() const {
   return tail_time_;
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.h b/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.h
index 4583ac7..b8119fb 100644
--- a/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.h
+++ b/third_party/WebKit/Source/modules/webaudio/IIRDSPKernel.h
@@ -32,7 +32,6 @@
 
   double TailTime() const override;
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const final;
 
  protected:
   IIRFilter iir_;
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h
index dfbdabc..0c853b4 100644
--- a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h
@@ -62,8 +62,6 @@
   void lock();
   void unlock();
 
-  bool RequiresTailProcessing() const final { return false; }
-
  private:
   MediaElementAudioSourceHandler(AudioNode&, HTMLMediaElement&);
   // As an audio source, we will never propagate silence.
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h
index fda3321..6bbc8ed 100644
--- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h
@@ -51,8 +51,6 @@
 
   unsigned long MaxChannelCount() const;
 
-  bool RequiresTailProcessing() const final { return false; }
-
  private:
   MediaStreamAudioDestinationHandler(AudioNode&, size_t number_of_channels);
   // As an audio source, we will never propagate silence.
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h
index 003ccaa7..6d2bc0a 100644
--- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h
@@ -57,8 +57,6 @@
   // MediaStreamAudioSourceNode.
   void SetFormat(size_t number_of_channels, float sample_rate);
 
-  bool RequiresTailProcessing() const final { return false; }
-
  private:
   MediaStreamAudioSourceHandler(AudioNode&,
                                 std::unique_ptr<AudioSourceProvider>);
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h
index c466fb9..03e10e0 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h
@@ -88,8 +88,6 @@
 
   unsigned NumberOfChannels() const { return number_of_channels_; }
 
-  bool RequiresTailProcessing() const final { return false; }
-
  private:
   OfflineAudioDestinationHandler(AudioNode&,
                                  unsigned number_of_channels,
diff --git a/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp b/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
index 218057ee..373f4e6 100644
--- a/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
@@ -103,7 +103,7 @@
 void PannerHandler::Process(size_t frames_to_process) {
   AudioBus* destination = Output(0).Bus();
 
-  if (!IsInitialized() || !panner_.get()) {
+  if (!IsInitialized() || !Input(0).IsConnected() || !panner_.get()) {
     destination->Zero();
     return;
   }
@@ -643,14 +643,6 @@
                       PannerHandler::kDistanceConeGainDirty);
   }
 }
-
-bool PannerHandler::RequiresTailProcessing() const {
-  // If there's no panner set up yet, assume we require tail
-  // processing in case the HRTF panner is set later, which does
-  // require tail processing.
-  return panner_ ? panner_->RequiresTailProcessing() : true;
-}
-
 // ----------------------------------------------------------------
 
 PannerNode::PannerNode(BaseAudioContext& context)
diff --git a/third_party/WebKit/Source/modules/webaudio/PannerNode.h b/third_party/WebKit/Source/modules/webaudio/PannerNode.h
index 141c7244..f9ca870 100644
--- a/third_party/WebKit/Source/modules/webaudio/PannerNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/PannerNode.h
@@ -116,7 +116,6 @@
   double LatencyTime() const override {
     return panner_ ? panner_->LatencyTime() : 0;
   }
-  bool RequiresTailProcessing() const final;
 
   void SetChannelCount(unsigned long, ExceptionState&) final;
   void SetChannelCountMode(const String&, ExceptionState&) final;
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
index 8baa91b..67804eed 100644
--- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
@@ -307,11 +307,6 @@
   waitable_event->Signal();
 }
 
-bool ScriptProcessorHandler::RequiresTailProcessing() const {
-  // Always return true since the tail and latency are never zero.
-  return true;
-}
-
 double ScriptProcessorHandler::TailTime() const {
   return std::numeric_limits<double>::infinity();
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h
index 1d66907..9e0bd41 100644
--- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h
@@ -80,7 +80,6 @@
                          unsigned number_of_output_channels);
   double TailTime() const override;
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const final;
 
   void FireProcessEvent(unsigned);
   void FireProcessEventForOfflineAudioContext(unsigned, WaitableEvent*);
diff --git a/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h b/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h
index c075bc8..d8fb897 100644
--- a/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h
@@ -33,9 +33,9 @@
   void SetChannelCount(unsigned long, ExceptionState&) final;
   void SetChannelCountMode(const String&, ExceptionState&) final;
 
+  // AudioNode
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
-  bool RequiresTailProcessing() const final { return false; }
 
  private:
   StereoPannerHandler(AudioNode&, float sample_rate, AudioParamHandler& pan);
diff --git a/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp b/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp
index 4221179..f9e2cef 100644
--- a/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.cpp
@@ -180,12 +180,6 @@
   }
 }
 
-bool WaveShaperDSPKernel::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero.
-  return true;
-}
-
 double WaveShaperDSPKernel::LatencyTime() const {
   size_t latency_frames = 0;
   WaveShaperDSPKernel* kernel = const_cast<WaveShaperDSPKernel*>(this);
diff --git a/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h b/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h
index 93401e2..301a477 100644
--- a/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h
+++ b/third_party/WebKit/Source/modules/webaudio/WaveShaperDSPKernel.h
@@ -51,7 +51,6 @@
   void Reset() override;
   double TailTime() const override { return 0; }
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const final;
 
   // Oversampling requires more resources, so let's only allocate them if
   // needed.
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index 3d487fd..ed81f39f 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -404,7 +404,7 @@
     return;
 
   DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer emulation(
-      GetDrawingBuffer());
+      GetDrawingBuffer(), !!GetFramebufferBinding(GL_DRAW_FRAMEBUFFER));
   ContextGL()->BlitFramebufferCHROMIUM(src_x0, src_y0, src_x1, src_y1, dst_x0,
                                        dst_y0, dst_x1, dst_y1, mask, filter);
 }
diff --git a/third_party/WebKit/Source/platform/FileMetadata.cpp b/third_party/WebKit/Source/platform/FileMetadata.cpp
index 1ab02fb..70207ff 100644
--- a/third_party/WebKit/Source/platform/FileMetadata.cpp
+++ b/third_party/WebKit/Source/platform/FileMetadata.cpp
@@ -71,4 +71,8 @@
   return Platform::Current()->GetFileUtilities()->FilePathToURL(path);
 }
 
+STATIC_ASSERT_ENUM(WebFileInfo::kTypeUnknown, FileMetadata::kTypeUnknown);
+STATIC_ASSERT_ENUM(WebFileInfo::kTypeFile, FileMetadata::kTypeFile);
+STATIC_ASSERT_ENUM(WebFileInfo::kTypeDirectory, FileMetadata::kTypeDirectory);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/AudioDSPKernel.h b/third_party/WebKit/Source/platform/audio/AudioDSPKernel.h
index 5e494c57..5d573dc0 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDSPKernel.h
+++ b/third_party/WebKit/Source/platform/audio/AudioDSPKernel.h
@@ -70,7 +70,6 @@
 
   virtual double TailTime() const = 0;
   virtual double LatencyTime() const = 0;
-  virtual bool RequiresTailProcessing() const = 0;
 
  protected:
   // This raw pointer is safe because the AudioDSPKernelProcessor object is
diff --git a/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.cpp b/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.cpp
index 7ff00d9..63d81a30 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.cpp
@@ -136,12 +136,6 @@
     number_of_channels_ = number_of_channels;
 }
 
-bool AudioDSPKernelProcessor::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero.
-  return true;
-}
-
 double AudioDSPKernelProcessor::TailTime() const {
   DCHECK(!IsMainThread());
   MutexTryLocker try_locker(process_lock_);
diff --git a/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.h b/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.h
index cc76d49..e593fbb 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.h
+++ b/third_party/WebKit/Source/platform/audio/AudioDSPKernelProcessor.h
@@ -71,7 +71,6 @@
 
   double TailTime() const override;
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const override;
 
  protected:
   Vector<std::unique_ptr<AudioDSPKernel>> kernels_;
diff --git a/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.cpp b/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.cpp
index ca4b3475..91f3d44 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.cpp
@@ -163,15 +163,6 @@
   buffer_.Zero();
 }
 
-bool AudioDelayDSPKernel::RequiresTailProcessing() const {
-  // Always return true even if the tail time and latency might both
-  // be zero. This is for simplicity; most interesting delay nodes
-  // have non-zero delay times anyway.  And it's ok to return true. It
-  // just means the node lives a little longer than strictly
-  // necessary.
-  return true;
-}
-
 double AudioDelayDSPKernel::TailTime() const {
   // Account for worst case delay.
   // Don't try to track actual delay time which can change dynamically.
diff --git a/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.h b/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.h
index c28e4360..57a560f1 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.h
+++ b/third_party/WebKit/Source/platform/audio/AudioDelayDSPKernel.h
@@ -48,7 +48,6 @@
 
   double TailTime() const override;
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const override;
 
  protected:
   AudioDelayDSPKernel(AudioDSPKernelProcessor*,
diff --git a/third_party/WebKit/Source/platform/audio/AudioProcessor.h b/third_party/WebKit/Source/platform/audio/AudioProcessor.h
index c48058b5..1abbb6e 100644
--- a/third_party/WebKit/Source/platform/audio/AudioProcessor.h
+++ b/third_party/WebKit/Source/platform/audio/AudioProcessor.h
@@ -82,7 +82,6 @@
 
   virtual double TailTime() const = 0;
   virtual double LatencyTime() const = 0;
-  virtual bool RequiresTailProcessing() const = 0;
 
  protected:
   bool initialized_;
diff --git a/third_party/WebKit/Source/platform/audio/DynamicsCompressor.cpp b/third_party/WebKit/Source/platform/audio/DynamicsCompressor.cpp
index 343760d..cf1a056 100644
--- a/third_party/WebKit/Source/platform/audio/DynamicsCompressor.cpp
+++ b/third_party/WebKit/Source/platform/audio/DynamicsCompressor.cpp
@@ -193,8 +193,4 @@
   number_of_channels_ = number_of_channels;
 }
 
-double DynamicsCompressor::TailTime() const {
-  return compressor_.TailTime();
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/DynamicsCompressor.h b/third_party/WebKit/Source/platform/audio/DynamicsCompressor.h
index 119b6da..13f0a875 100644
--- a/third_party/WebKit/Source/platform/audio/DynamicsCompressor.h
+++ b/third_party/WebKit/Source/platform/audio/DynamicsCompressor.h
@@ -83,15 +83,10 @@
   float SampleRate() const { return sample_rate_; }
   float Nyquist() const { return sample_rate_ / 2; }
 
-  double TailTime() const;
+  double TailTime() const { return 0; }
   double LatencyTime() const {
     return compressor_.LatencyFrames() / static_cast<double>(SampleRate());
   }
-  bool RequiresTailProcessing() const {
-    // Always return true even if the tail time and latency might both
-    // be zero.
-    return true;
-  }
 
  protected:
   unsigned number_of_channels_;
diff --git a/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp b/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp
index 59bbacdf..ce9bd1c0 100644
--- a/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp
+++ b/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.cpp
@@ -495,16 +495,4 @@
   max_attack_compression_diff_db_ = -1;  // uninitialized state
 }
 
-double DynamicsCompressorKernel::TailTime() const {
-  // The reduction value of the compressor is computed from the gain
-  // using an exponential filter with a time constant of
-  // |kMeteringReleaseTimeConstant|.  We need to keep he compressor
-  // running for some time after the inputs go away so that the
-  // reduction value approaches 0.  This is a tradeoff between how
-  // long we keep the node alive and how close we approach the final
-  // value.  A value of 5 to 10 times the time constant is a
-  // reasonable trade-off.
-  return 5 * kMeteringReleaseTimeConstant;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.h b/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.h
index 80095a5..4e3afbd 100644
--- a/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.h
+++ b/third_party/WebKit/Source/platform/audio/DynamicsCompressorKernel.h
@@ -74,8 +74,6 @@
 
   float MeteringGain() const { return metering_gain_; }
 
-  double TailTime() const;
-
  protected:
   float sample_rate_;
 
diff --git a/third_party/WebKit/Source/platform/audio/EqualPowerPanner.h b/third_party/WebKit/Source/platform/audio/EqualPowerPanner.h
index d8fdfc0..36803823 100644
--- a/third_party/WebKit/Source/platform/audio/EqualPowerPanner.h
+++ b/third_party/WebKit/Source/platform/audio/EqualPowerPanner.h
@@ -53,7 +53,6 @@
 
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
-  bool RequiresTailProcessing() const override { return false; }
 
  private:
   void CalculateDesiredGain(double& desired_gain_l,
diff --git a/third_party/WebKit/Source/platform/audio/HRTFPanner.cpp b/third_party/WebKit/Source/platform/audio/HRTFPanner.cpp
index 0177f6834..1e2f146 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFPanner.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFPanner.cpp
@@ -350,11 +350,6 @@
       frames_to_process, channel_interpretation);
 }
 
-bool HRTFPanner::RequiresTailProcessing() const {
-  // Always return true since the tail and latency are never zero.
-  return true;
-}
-
 double HRTFPanner::TailTime() const {
   // Because HRTFPanner is implemented with a DelayKernel and a FFTConvolver,
   // the tailTime of the HRTFPanner is the sum of the tailTime of the
diff --git a/third_party/WebKit/Source/platform/audio/HRTFPanner.h b/third_party/WebKit/Source/platform/audio/HRTFPanner.h
index 8eacb45..f0d32cb 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFPanner.h
+++ b/third_party/WebKit/Source/platform/audio/HRTFPanner.h
@@ -61,7 +61,6 @@
 
   double TailTime() const override;
   double LatencyTime() const override;
-  bool RequiresTailProcessing() const override;
 
  private:
   // Given an azimuth angle in the range -180 -> +180, returns the corresponding
diff --git a/third_party/WebKit/Source/platform/audio/Panner.h b/third_party/WebKit/Source/platform/audio/Panner.h
index 9552f1f..cfe5be6 100644
--- a/third_party/WebKit/Source/platform/audio/Panner.h
+++ b/third_party/WebKit/Source/platform/audio/Panner.h
@@ -74,7 +74,6 @@
 
   virtual double TailTime() const = 0;
   virtual double LatencyTime() const = 0;
-  virtual bool RequiresTailProcessing() const = 0;
 
  protected:
   Panner(PanningModel model) : panning_model_(model) {}
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index b791187..d1cfe6a 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -580,9 +580,11 @@
 }
 
 DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer::
-    ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer* drawing_buffer)
+    ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer* drawing_buffer,
+                                         bool is_user_draw_framebuffer_bound)
     : drawing_buffer_(drawing_buffer) {
-  doing_work_ = drawing_buffer->SetupRGBEmulationForBlitFramebuffer();
+  doing_work_ = drawing_buffer->SetupRGBEmulationForBlitFramebuffer(
+      is_user_draw_framebuffer_bound);
 }
 
 DrawingBuffer::ScopedRGBEmulationForBlitFramebuffer::
@@ -1295,14 +1297,21 @@
   return GL_RGB8_OES;
 }
 
-bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer() {
+bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer(
+    bool is_user_draw_framebuffer_bound) {
   // We only need to do this work if:
+  //  - We are blitting to the default framebuffer
   //  - The user has selected alpha:false and antialias:false
   //  - We are using CHROMIUM_image with RGB emulation
   // macOS is the only platform on which this is necessary.
 
-  if (want_alpha_channel_ || anti_aliasing_mode_ != kNone)
+  if (is_user_draw_framebuffer_bound) {
     return false;
+  }
+
+  if (want_alpha_channel_ || anti_aliasing_mode_ != kNone) {
+    return false;
+  }
 
   if (!(ShouldUseChromiumImage() &&
         ContextProvider()->GetCapabilities().chromium_image_rgb_emulation))
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
index c58e72f69..f78bacf 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -236,7 +236,8 @@
   // store and RGB emulation is in use (basically, macOS only).
   class PLATFORM_EXPORT ScopedRGBEmulationForBlitFramebuffer {
    public:
-    ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer*);
+    ScopedRGBEmulationForBlitFramebuffer(DrawingBuffer*,
+                                         bool is_user_draw_framebuffer_bound);
     ~ScopedRGBEmulationForBlitFramebuffer();
 
    private:
@@ -457,7 +458,7 @@
 
   // Helpers to ensure correct behavior of BlitFramebuffer when using
   // an emulated RGB CHROMIUM_image back buffer.
-  bool SetupRGBEmulationForBlitFramebuffer();
+  bool SetupRGBEmulationForBlitFramebuffer(bool is_user_draw_framebuffer_bound);
   void CleanupRGBEmulationForBlitFramebuffer();
 
   // Weak, reset by beginDestruction.
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index 1cdec0e..d1635d27 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -49,6 +49,7 @@
 #include "platform/weborigin/SecurityOrigin.h"
 #include "platform/weborigin/SecurityPolicy.h"
 #include "platform/weborigin/SecurityViolationReportingPolicy.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/text/CString.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/Platform.h"
@@ -1670,4 +1671,14 @@
   visitor->Trace(resource_timing_info_map_);
 }
 
+STATIC_ASSERT_ENUM(WebURLRequest::kPriorityUnresolved,
+                   kResourceLoadPriorityUnresolved);
+STATIC_ASSERT_ENUM(WebURLRequest::kPriorityVeryLow,
+                   kResourceLoadPriorityVeryLow);
+STATIC_ASSERT_ENUM(WebURLRequest::kPriorityLow, kResourceLoadPriorityLow);
+STATIC_ASSERT_ENUM(WebURLRequest::kPriorityMedium, kResourceLoadPriorityMedium);
+STATIC_ASSERT_ENUM(WebURLRequest::kPriorityHigh, kResourceLoadPriorityHigh);
+STATIC_ASSERT_ENUM(WebURLRequest::kPriorityVeryHigh,
+                   kResourceLoadPriorityVeryHigh);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
index 34ec3a3..e7baa40 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
@@ -28,9 +28,11 @@
 
 #include "platform/HTTPNames.h"
 #include "platform/network/HTTPParsers.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/CurrentTime.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/StdLibExtras.h"
+#include "public/platform/WebURLResponse.h"
 
 #include <memory>
 
@@ -641,4 +643,14 @@
   return true;
 }
 
+STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersionUnknown,
+                   ResourceResponse::kHTTPVersionUnknown);
+STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_0_9,
+                   ResourceResponse::kHTTPVersion_0_9);
+STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_1_0,
+                   ResourceResponse::kHTTPVersion_1_0);
+STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_1_1,
+                   ResourceResponse::kHTTPVersion_1_1);
+STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_2_0,
+                   ResourceResponse::kHTTPVersion_2_0);
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp
index 7f5ab9c..d67e50a 100644
--- a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp
+++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp
@@ -29,6 +29,8 @@
  */
 
 #include "platform/mediastream/MediaStreamSource.h"
+#include "platform/wtf/Assertions.h"
+#include "public/platform/WebMediaStreamSource.h"
 
 namespace blink {
 
@@ -132,4 +134,15 @@
   visitor->Trace(observers_);
 }
 
+STATIC_ASSERT_ENUM(WebMediaStreamSource::kTypeAudio,
+                   MediaStreamSource::kTypeAudio);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::kTypeVideo,
+                   MediaStreamSource::kTypeVideo);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateLive,
+                   MediaStreamSource::kReadyStateLive);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateMuted,
+                   MediaStreamSource::kReadyStateMuted);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateEnded,
+                   MediaStreamSource::kReadyStateEnded);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/network/ContentSecurityPolicyParsers.cpp b/third_party/WebKit/Source/platform/network/ContentSecurityPolicyParsers.cpp
index cdb25be7..0d3dedc 100644
--- a/third_party/WebKit/Source/platform/network/ContentSecurityPolicyParsers.cpp
+++ b/third_party/WebKit/Source/platform/network/ContentSecurityPolicyParsers.cpp
@@ -5,7 +5,9 @@
 #include "platform/network/ContentSecurityPolicyParsers.h"
 
 #include "platform/wtf/ASCIICType.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/text/StringUTF8Adaptor.h"
+#include "public/platform/WebContentSecurityPolicy.h"
 
 namespace blink {
 
@@ -55,4 +57,13 @@
   return !IsASCIISpace(c) && c != '/';
 }
 
+STATIC_ASSERT_ENUM(kWebContentSecurityPolicyTypeReport,
+                   kContentSecurityPolicyHeaderTypeReport);
+STATIC_ASSERT_ENUM(kWebContentSecurityPolicyTypeEnforce,
+                   kContentSecurityPolicyHeaderTypeEnforce);
+
+STATIC_ASSERT_ENUM(kWebContentSecurityPolicySourceHTTP,
+                   kContentSecurityPolicyHeaderSourceHTTP);
+STATIC_ASSERT_ENUM(kWebContentSecurityPolicySourceMeta,
+                   kContentSecurityPolicyHeaderSourceMeta);
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
index 4a2cfd11..27a8b80 100644
--- a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
+++ b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
@@ -34,6 +34,7 @@
 #include "platform/scroll/ScrollbarTheme.h"
 #include "public/platform/WebGestureEvent.h"
 #include "public/platform/WebMouseEvent.h"
+#include "public/platform/WebScrollbar.h"
 
 namespace blink {
 
@@ -645,4 +646,36 @@
     scrollable_area_->SetScrollbarNeedsPaintInvalidation(Orientation());
 }
 
+STATIC_ASSERT_ENUM(WebScrollbar::ScrollingMode::kAuto, kScrollbarAuto);
+STATIC_ASSERT_ENUM(WebScrollbar::ScrollingMode::kAlwaysOff,
+                   kScrollbarAlwaysOff);
+STATIC_ASSERT_ENUM(WebScrollbar::ScrollingMode::kAlwaysOn, kScrollbarAlwaysOn);
+
+STATIC_ASSERT_ENUM(WebScrollbar::kHorizontal, kHorizontalScrollbar);
+STATIC_ASSERT_ENUM(WebScrollbar::kVertical, kVerticalScrollbar);
+
+STATIC_ASSERT_ENUM(WebScrollbar::kScrollByLine, kScrollByLine);
+STATIC_ASSERT_ENUM(WebScrollbar::kScrollByPage, kScrollByPage);
+STATIC_ASSERT_ENUM(WebScrollbar::kScrollByDocument, kScrollByDocument);
+STATIC_ASSERT_ENUM(WebScrollbar::kScrollByPixel, kScrollByPixel);
+
+STATIC_ASSERT_ENUM(WebScrollbar::kRegularScrollbar, kRegularScrollbar);
+STATIC_ASSERT_ENUM(WebScrollbar::kSmallScrollbar, kSmallScrollbar);
+STATIC_ASSERT_ENUM(WebScrollbar::kNoPart, kNoPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kBackButtonStartPart, kBackButtonStartPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kForwardButtonStartPart,
+                   kForwardButtonStartPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kBackTrackPart, kBackTrackPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kThumbPart, kThumbPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kForwardTrackPart, kForwardTrackPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kBackButtonEndPart, kBackButtonEndPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kForwardButtonEndPart, kForwardButtonEndPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kScrollbarBGPart, kScrollbarBGPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kTrackBGPart, kTrackBGPart);
+STATIC_ASSERT_ENUM(WebScrollbar::kAllParts, kAllParts);
+STATIC_ASSERT_ENUM(kWebScrollbarOverlayColorThemeDark,
+                   kScrollbarOverlayColorThemeDark);
+STATIC_ASSERT_ENUM(kWebScrollbarOverlayColorThemeLight,
+                   kScrollbarOverlayColorThemeLight);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
index 27d32e1..6fac7e2 100644
--- a/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
+++ b/third_party/WebKit/Source/platform/weborigin/SecurityPolicy.cpp
@@ -34,11 +34,13 @@
 #include "platform/weborigin/OriginAccessEntry.h"
 #include "platform/weborigin/SchemeRegistry.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "platform/wtf/Assertions.h"
 #include "platform/wtf/HashMap.h"
 #include "platform/wtf/HashSet.h"
 #include "platform/wtf/PtrUtil.h"
 #include "platform/wtf/Threading.h"
 #include "platform/wtf/text/StringHash.h"
+#include "public/platform/WebReferrerPolicy.h"
 
 namespace blink {
 
@@ -344,4 +346,18 @@
   return true;
 }
 
+STATIC_ASSERT_ENUM(kWebReferrerPolicyAlways, kReferrerPolicyAlways);
+STATIC_ASSERT_ENUM(kWebReferrerPolicyDefault, kReferrerPolicyDefault);
+STATIC_ASSERT_ENUM(kWebReferrerPolicyNoReferrerWhenDowngrade,
+                   kReferrerPolicyNoReferrerWhenDowngrade);
+STATIC_ASSERT_ENUM(kWebReferrerPolicyNever, kReferrerPolicyNever);
+STATIC_ASSERT_ENUM(kWebReferrerPolicyOrigin, kReferrerPolicyOrigin);
+STATIC_ASSERT_ENUM(kWebReferrerPolicyOriginWhenCrossOrigin,
+                   kReferrerPolicyOriginWhenCrossOrigin);
+STATIC_ASSERT_ENUM(kWebReferrerPolicySameOrigin, kReferrerPolicySameOrigin);
+STATIC_ASSERT_ENUM(kWebReferrerPolicyStrictOrigin, kReferrerPolicyStrictOrigin);
+STATIC_ASSERT_ENUM(
+    kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
+    kReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
index a981dbdd..0b467f7 100644
--- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
+++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -77,28 +77,17 @@
 #include "platform/wtf/Assertions.h"
 #include "platform/wtf/text/StringImpl.h"
 #include "public/platform/WebClipboard.h"
-#include "public/platform/WebContentSecurityPolicy.h"
-#include "public/platform/WebContentSecurityPolicyStruct.h"
-#include "public/platform/WebFileError.h"
 #include "public/platform/WebFileInfo.h"
 #include "public/platform/WebFileSystem.h"
 #include "public/platform/WebHistoryScrollRestorationType.h"
 #include "public/platform/WebInputEvent.h"
-#include "public/platform/WebMediaPlayer.h"
 #include "public/platform/WebMediaPlayerClient.h"
 #include "public/platform/WebMediaSource.h"
-#include "public/platform/WebMediaStreamSource.h"
 #include "public/platform/WebMouseWheelEvent.h"
-#include "public/platform/WebPageVisibilityState.h"
-#include "public/platform/WebReferrerPolicy.h"
 #include "public/platform/WebScrollBoundaryBehavior.h"
 #include "public/platform/WebScrollbar.h"
 #include "public/platform/WebScrollbarBehavior.h"
 #include "public/platform/WebSelectionBound.h"
-#include "public/platform/WebStorageQuotaError.h"
-#include "public/platform/WebStorageQuotaType.h"
-#include "public/platform/WebURLRequest.h"
-#include "public/platform/WebURLResponse.h"
 #include "public/platform/modules/indexeddb/WebIDBCursor.h"
 #include "public/platform/modules/indexeddb/WebIDBDatabase.h"
 #include "public/platform/modules/indexeddb/WebIDBDatabaseException.h"
@@ -112,9 +101,7 @@
 #include "public/web/WebFrameLoadType.h"
 #include "public/web/WebHistoryCommitType.h"
 #include "public/web/WebHistoryItem.h"
-#include "public/web/WebIconURL.h"
 #include "public/web/WebInputElement.h"
-#include "public/web/WebNavigationPolicy.h"
 #include "public/web/WebNavigatorContentUtilsClient.h"
 #include "public/web/WebRemoteFrameClient.h"
 #include "public/web/WebSandboxFlags.h"
@@ -122,76 +109,12 @@
 #include "public/web/WebSelection.h"
 #include "public/web/WebSerializedScriptValueVersion.h"
 #include "public/web/WebSettings.h"
-#include "public/web/WebSpeechRecognizerClient.h"
 #include "public/web/WebTextCheckingResult.h"
 #include "public/web/WebTextDecorationType.h"
 #include "public/web/WebView.h"
 
 namespace blink {
 
-STATIC_ASSERT_ENUM(WebFrameOwnerProperties::ScrollingMode::kAuto,
-                   kScrollbarAuto);
-STATIC_ASSERT_ENUM(WebFrameOwnerProperties::ScrollingMode::kAlwaysOff,
-                   kScrollbarAlwaysOff);
-STATIC_ASSERT_ENUM(WebFrameOwnerProperties::ScrollingMode::kAlwaysOn,
-                   kScrollbarAlwaysOn);
-
-STATIC_ASSERT_ENUM(WebIconURL::kTypeInvalid, kInvalidIcon);
-STATIC_ASSERT_ENUM(WebIconURL::kTypeFavicon, kFavicon);
-STATIC_ASSERT_ENUM(WebIconURL::kTypeTouch, kTouchIcon);
-STATIC_ASSERT_ENUM(WebIconURL::kTypeTouchPrecomposed, kTouchPrecomposedIcon);
-
-STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveNothing,
-                   HTMLMediaElement::kHaveNothing);
-STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveMetadata,
-                   HTMLMediaElement::kHaveMetadata);
-STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveCurrentData,
-                   HTMLMediaElement::kHaveCurrentData);
-STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveFutureData,
-                   HTMLMediaElement::kHaveFutureData);
-STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveEnoughData,
-                   HTMLMediaElement::kHaveEnoughData);
-
-STATIC_ASSERT_ENUM(WebScrollbar::kHorizontal, kHorizontalScrollbar);
-STATIC_ASSERT_ENUM(WebScrollbar::kVertical, kVerticalScrollbar);
-
-STATIC_ASSERT_ENUM(WebScrollbar::kScrollByLine, kScrollByLine);
-STATIC_ASSERT_ENUM(WebScrollbar::kScrollByPage, kScrollByPage);
-STATIC_ASSERT_ENUM(WebScrollbar::kScrollByDocument, kScrollByDocument);
-STATIC_ASSERT_ENUM(WebScrollbar::kScrollByPixel, kScrollByPixel);
-
-STATIC_ASSERT_ENUM(WebScrollbar::kRegularScrollbar, kRegularScrollbar);
-STATIC_ASSERT_ENUM(WebScrollbar::kSmallScrollbar, kSmallScrollbar);
-STATIC_ASSERT_ENUM(WebScrollbar::kNoPart, kNoPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kBackButtonStartPart, kBackButtonStartPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kForwardButtonStartPart,
-                   kForwardButtonStartPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kBackTrackPart, kBackTrackPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kThumbPart, kThumbPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kForwardTrackPart, kForwardTrackPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kBackButtonEndPart, kBackButtonEndPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kForwardButtonEndPart, kForwardButtonEndPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kScrollbarBGPart, kScrollbarBGPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kTrackBGPart, kTrackBGPart);
-STATIC_ASSERT_ENUM(WebScrollbar::kAllParts, kAllParts);
-STATIC_ASSERT_ENUM(kWebScrollbarOverlayColorThemeDark,
-                   kScrollbarOverlayColorThemeDark);
-STATIC_ASSERT_ENUM(kWebScrollbarOverlayColorThemeLight,
-                   kScrollbarOverlayColorThemeLight);
-
-STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorMac, kEditingMacBehavior);
-STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorWin, kEditingWindowsBehavior);
-STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorUnix, kEditingUnixBehavior);
-STATIC_ASSERT_ENUM(WebSettings::kEditingBehaviorAndroid,
-                   kEditingAndroidBehavior);
-
-STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kFalse,
-                   PassiveListenerDefault::kFalse);
-STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kTrue,
-                   PassiveListenerDefault::kTrue);
-STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kForceAllTrue,
-                   PassiveListenerDefault::kForceAllTrue);
-
 STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionUnknownError, kUnknownError);
 STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionConstraintError, kConstraintError);
 STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionDataError, kDataError);
@@ -213,136 +136,10 @@
 
 STATIC_ASSERT_ENUM(WebIDBMetadata::kNoVersion, IDBDatabaseMetadata::kNoVersion);
 
-STATIC_ASSERT_ENUM(WebFileSystem::kTypeTemporary, kFileSystemTypeTemporary);
-STATIC_ASSERT_ENUM(WebFileSystem::kTypePersistent, kFileSystemTypePersistent);
-STATIC_ASSERT_ENUM(WebFileSystem::kTypeExternal, kFileSystemTypeExternal);
-STATIC_ASSERT_ENUM(WebFileSystem::kTypeIsolated, kFileSystemTypeIsolated);
-STATIC_ASSERT_ENUM(WebFileInfo::kTypeUnknown, FileMetadata::kTypeUnknown);
-STATIC_ASSERT_ENUM(WebFileInfo::kTypeFile, FileMetadata::kTypeFile);
-STATIC_ASSERT_ENUM(WebFileInfo::kTypeDirectory, FileMetadata::kTypeDirectory);
-
-STATIC_ASSERT_ENUM(kWebFileErrorNotFound, FileError::kNotFoundErr);
-STATIC_ASSERT_ENUM(kWebFileErrorSecurity, FileError::kSecurityErr);
-STATIC_ASSERT_ENUM(kWebFileErrorAbort, FileError::kAbortErr);
-STATIC_ASSERT_ENUM(kWebFileErrorNotReadable, FileError::kNotReadableErr);
-STATIC_ASSERT_ENUM(kWebFileErrorEncoding, FileError::kEncodingErr);
-STATIC_ASSERT_ENUM(kWebFileErrorNoModificationAllowed,
-                   FileError::kNoModificationAllowedErr);
-STATIC_ASSERT_ENUM(kWebFileErrorInvalidState, FileError::kInvalidStateErr);
-STATIC_ASSERT_ENUM(kWebFileErrorSyntax, FileError::kSyntaxErr);
-STATIC_ASSERT_ENUM(kWebFileErrorInvalidModification,
-                   FileError::kInvalidModificationErr);
-STATIC_ASSERT_ENUM(kWebFileErrorQuotaExceeded, FileError::kQuotaExceededErr);
-STATIC_ASSERT_ENUM(kWebFileErrorTypeMismatch, FileError::kTypeMismatchErr);
-STATIC_ASSERT_ENUM(kWebFileErrorPathExists, FileError::kPathExistsErr);
 
 STATIC_ASSERT_ENUM(kWebTextDecorationTypeSpelling, kTextDecorationTypeSpelling);
 STATIC_ASSERT_ENUM(kWebTextDecorationTypeGrammar, kTextDecorationTypeGrammar);
 
-STATIC_ASSERT_ENUM(kWebStorageQuotaErrorNotSupported, kNotSupportedError);
-STATIC_ASSERT_ENUM(kWebStorageQuotaErrorInvalidModification,
-                   kInvalidModificationError);
-STATIC_ASSERT_ENUM(kWebStorageQuotaErrorInvalidAccess, kInvalidAccessError);
-STATIC_ASSERT_ENUM(kWebStorageQuotaErrorAbort, kAbortError);
-
-STATIC_ASSERT_ENUM(kWebStorageQuotaTypeTemporary,
-                   DeprecatedStorageQuota::kTemporary);
-STATIC_ASSERT_ENUM(kWebStorageQuotaTypePersistent,
-                   DeprecatedStorageQuota::kPersistent);
-
-STATIC_ASSERT_ENUM(kWebPageVisibilityStateVisible, kPageVisibilityStateVisible);
-STATIC_ASSERT_ENUM(kWebPageVisibilityStateHidden, kPageVisibilityStateHidden);
-STATIC_ASSERT_ENUM(kWebPageVisibilityStatePrerender,
-                   kPageVisibilityStatePrerender);
-
-STATIC_ASSERT_ENUM(WebMediaStreamSource::kTypeAudio,
-                   MediaStreamSource::kTypeAudio);
-STATIC_ASSERT_ENUM(WebMediaStreamSource::kTypeVideo,
-                   MediaStreamSource::kTypeVideo);
-STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateLive,
-                   MediaStreamSource::kReadyStateLive);
-STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateMuted,
-                   MediaStreamSource::kReadyStateMuted);
-STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateEnded,
-                   MediaStreamSource::kReadyStateEnded);
-
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kOtherError,
-                   SpeechRecognitionError::kErrorCodeOther);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNoSpeechError,
-                   SpeechRecognitionError::kErrorCodeNoSpeech);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kAbortedError,
-                   SpeechRecognitionError::kErrorCodeAborted);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kAudioCaptureError,
-                   SpeechRecognitionError::kErrorCodeAudioCapture);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNetworkError,
-                   SpeechRecognitionError::kErrorCodeNetwork);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNotAllowedError,
-                   SpeechRecognitionError::kErrorCodeNotAllowed);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kServiceNotAllowedError,
-                   SpeechRecognitionError::kErrorCodeServiceNotAllowed);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kBadGrammarError,
-                   SpeechRecognitionError::kErrorCodeBadGrammar);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kLanguageNotSupportedError,
-                   SpeechRecognitionError::kErrorCodeLanguageNotSupported);
-
-STATIC_ASSERT_ENUM(kWebReferrerPolicyAlways, kReferrerPolicyAlways);
-STATIC_ASSERT_ENUM(kWebReferrerPolicyDefault, kReferrerPolicyDefault);
-STATIC_ASSERT_ENUM(kWebReferrerPolicyNoReferrerWhenDowngrade,
-                   kReferrerPolicyNoReferrerWhenDowngrade);
-STATIC_ASSERT_ENUM(kWebReferrerPolicyNever, kReferrerPolicyNever);
-STATIC_ASSERT_ENUM(kWebReferrerPolicyOrigin, kReferrerPolicyOrigin);
-STATIC_ASSERT_ENUM(kWebReferrerPolicyOriginWhenCrossOrigin,
-                   kReferrerPolicyOriginWhenCrossOrigin);
-STATIC_ASSERT_ENUM(kWebReferrerPolicySameOrigin, kReferrerPolicySameOrigin);
-STATIC_ASSERT_ENUM(kWebReferrerPolicyStrictOrigin, kReferrerPolicyStrictOrigin);
-STATIC_ASSERT_ENUM(
-    kWebReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin,
-    kReferrerPolicyNoReferrerWhenDowngradeOriginWhenCrossOrigin);
-
-STATIC_ASSERT_ENUM(kWebContentSecurityPolicyTypeReport,
-                   kContentSecurityPolicyHeaderTypeReport);
-STATIC_ASSERT_ENUM(kWebContentSecurityPolicyTypeEnforce,
-                   kContentSecurityPolicyHeaderTypeEnforce);
-
-STATIC_ASSERT_ENUM(kWebContentSecurityPolicySourceHTTP,
-                   kContentSecurityPolicyHeaderSourceHTTP);
-STATIC_ASSERT_ENUM(kWebContentSecurityPolicySourceMeta,
-                   kContentSecurityPolicyHeaderSourceMeta);
-
-STATIC_ASSERT_ENUM(kWebWildcardDispositionNoWildcard, CSPSource::kNoWildcard);
-STATIC_ASSERT_ENUM(kWebWildcardDispositionHasWildcard, CSPSource::kHasWildcard);
-
-STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersionUnknown,
-                   ResourceResponse::kHTTPVersionUnknown);
-STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_0_9,
-                   ResourceResponse::kHTTPVersion_0_9);
-STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_1_0,
-                   ResourceResponse::kHTTPVersion_1_0);
-STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_1_1,
-                   ResourceResponse::kHTTPVersion_1_1);
-STATIC_ASSERT_ENUM(WebURLResponse::kHTTPVersion_2_0,
-                   ResourceResponse::kHTTPVersion_2_0);
-
-STATIC_ASSERT_ENUM(WebURLRequest::kPriorityUnresolved,
-                   kResourceLoadPriorityUnresolved);
-STATIC_ASSERT_ENUM(WebURLRequest::kPriorityVeryLow,
-                   kResourceLoadPriorityVeryLow);
-STATIC_ASSERT_ENUM(WebURLRequest::kPriorityLow, kResourceLoadPriorityLow);
-STATIC_ASSERT_ENUM(WebURLRequest::kPriorityMedium, kResourceLoadPriorityMedium);
-STATIC_ASSERT_ENUM(WebURLRequest::kPriorityHigh, kResourceLoadPriorityHigh);
-STATIC_ASSERT_ENUM(WebURLRequest::kPriorityVeryHigh,
-                   kResourceLoadPriorityVeryHigh);
-
-STATIC_ASSERT_ENUM(kWebNavigationPolicyIgnore, kNavigationPolicyIgnore);
-STATIC_ASSERT_ENUM(kWebNavigationPolicyDownload, kNavigationPolicyDownload);
-STATIC_ASSERT_ENUM(kWebNavigationPolicyCurrentTab, kNavigationPolicyCurrentTab);
-STATIC_ASSERT_ENUM(kWebNavigationPolicyNewBackgroundTab,
-                   kNavigationPolicyNewBackgroundTab);
-STATIC_ASSERT_ENUM(kWebNavigationPolicyNewForegroundTab,
-                   kNavigationPolicyNewForegroundTab);
-STATIC_ASSERT_ENUM(kWebNavigationPolicyNewWindow, kNavigationPolicyNewWindow);
-STATIC_ASSERT_ENUM(kWebNavigationPolicyNewPopup, kNavigationPolicyNewPopup);
-
 STATIC_ASSERT_ENUM(kWebStandardCommit, kStandardCommit);
 STATIC_ASSERT_ENUM(kWebBackForwardCommit, kBackForwardCommit);
 STATIC_ASSERT_ENUM(kWebInitialCommitInChildFrame, kInitialCommitInChildFrame);
diff --git a/third_party/WebKit/public/README b/third_party/WebKit/public/README.md
similarity index 93%
rename from third_party/WebKit/public/README
rename to third_party/WebKit/public/README.md
index 4e07a86a..13569c5a 100644
--- a/third_party/WebKit/public/README
+++ b/third_party/WebKit/public/README.md
@@ -2,7 +2,7 @@
 ================
 
 This directory contains the public API for Blink. The API consists of a number
-of C++ header files, scripts, and GYP build files. We consider all other files
+of C++ header files, scripts, and GN build files. We consider all other files
 in Blink to be implementation details, which are subject to change at any time
 without notice.
 
@@ -47,7 +47,7 @@
 used internally by Blink (e.g., std::pair). Instead, we use WTF containers to
 implement the API.
 
-The API uses some internal types (e.g., WebCore::Node). Typically, these types
+The API uses some internal types (e.g., blink::Node). Typically, these types
 are forward declared and are opaque to consumers of the API. In other cases,
 the full definitions are available behind the BLINK_IMPLEMENTATION
 preprocessor macro. In both cases, we continue to regard these internal types
diff --git a/third_party/WebKit/public/platform/DEPS b/third_party/WebKit/public/platform/DEPS
index 33ab0a6..91b2265 100644
--- a/third_party/WebKit/public/platform/DEPS
+++ b/third_party/WebKit/public/platform/DEPS
@@ -12,16 +12,8 @@
     "+cc",
     "-cc/blink",
     "+components/viz/common",
-    "-core",
-    "-modules",
-    # TODO(toyoshim): Remove following media/midi direct dependency in public
-    # interface once Web MIDI starts calling the Mojo service inside Blink.
-    # http://crbug.com/582327
-    "+media/midi/midi_service.mojom-shared.h",
     "+mojo/public",
     "+net/http",
-    "+platform",
-    "+platform/weborigin",
     "+public/platform",
     "-public/web",
     "+services/service_manager/public/interfaces",
@@ -30,4 +22,7 @@
     "+ui/gfx",
     "+url",
     "-web",
+
+    # Allowed only inside INSIDE_BLINK
+    "+platform",
 ]
diff --git a/third_party/WebKit/public/platform/WebScrollbar.h b/third_party/WebKit/public/platform/WebScrollbar.h
index 8d15d9c..6e20b09 100644
--- a/third_party/WebKit/public/platform/WebScrollbar.h
+++ b/third_party/WebKit/public/platform/WebScrollbar.h
@@ -63,6 +63,8 @@
     kAllParts = 0xffffffff
   };
 
+  enum class ScrollingMode { kAuto, kAlwaysOff, kAlwaysOn, kLast = kAlwaysOn };
+
   virtual ~WebScrollbar() {}
 
   // Return true if this is an overlay scrollbar.
diff --git a/third_party/WebKit/public/platform/modules/permissions/permission.mojom b/third_party/WebKit/public/platform/modules/permissions/permission.mojom
index 97387f98..7f23845 100644
--- a/third_party/WebKit/public/platform/modules/permissions/permission.mojom
+++ b/third_party/WebKit/public/platform/modules/permissions/permission.mojom
@@ -17,6 +17,7 @@
   AUDIO_CAPTURE,
   VIDEO_CAPTURE,
   BACKGROUND_SYNC,
+  SENSORS,
 };
 
 struct MidiPermissionDescriptor {
diff --git a/third_party/WebKit/public/platform/modules/webmidi/DEPS b/third_party/WebKit/public/platform/modules/webmidi/DEPS
new file mode 100644
index 0000000..dcd5e5b
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/webmidi/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+    # TODO(toyoshim): Remove following media/midi direct dependency in public
+    # interface once Web MIDI starts calling the Mojo service inside Blink.
+    # http://crbug.com/582327
+    "+media/midi/midi_service.mojom-shared.h",
+]
diff --git a/third_party/WebKit/public/web/WebFrameOwnerProperties.h b/third_party/WebKit/public/web/WebFrameOwnerProperties.h
index 4be92a9..64e9916 100644
--- a/third_party/WebKit/public/web/WebFrameOwnerProperties.h
+++ b/third_party/WebKit/public/web/WebFrameOwnerProperties.h
@@ -6,6 +6,7 @@
 #define WebFrameOwnerProperties_h
 
 #include "public/platform/WebFeaturePolicy.h"
+#include "public/platform/WebScrollbar.h"
 #include "public/platform/WebString.h"
 #include "public/platform/WebVector.h"
 
@@ -14,7 +15,7 @@
 namespace blink {
 
 struct WebFrameOwnerProperties {
-  enum class ScrollingMode { kAuto, kAlwaysOff, kAlwaysOn, kLast = kAlwaysOn };
+  using ScrollingMode = WebScrollbar::ScrollingMode;
 
   WebString name;  // browsing context container's name
   ScrollingMode scrolling_mode;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 82a00e8..17cdf19 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -31024,7 +31024,27 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Remoting.CapacityOverMediaBitrate" units="kbps">
+  <owner>miu@chromium.org</owner>
+  <summary>
+    The difference between the estimated transmission capacity and the media
+    bitrate when capacity is higher.
+  </summary>
+</histogram>
+
+<histogram name="Media.Remoting.MediaBitrateOverCapacity" units="kbps">
+  <owner>miu@chromium.org</owner>
+  <summary>
+    The difference between the media bitrate and the estimated transmission
+    capacity when media bitrate is higher.
+  </summary>
+</histogram>
+
 <histogram name="Media.Remoting.PosterDownloadDuration.Fail" units="ms">
+  <obsolete>
+    Deprecated as no more poster image is being downloaded while remoting
+    content.
+  </obsolete>
   <owner>miu@chromium.org</owner>
   <summary>
     Measures the amount of time it took to ultimately fail to download a poster
@@ -31033,6 +31053,10 @@
 </histogram>
 
 <histogram name="Media.Remoting.PosterDownloadDuration.Success" units="ms">
+  <obsolete>
+    Deprecated as no more poster image is being downloaded while remoting
+    content.
+  </obsolete>
   <owner>miu@chromium.org</owner>
   <summary>
     Measures the amount of time it took to successfully download a poster image
@@ -31056,6 +31080,14 @@
   <summary>Tracks the trigger for stopping a remoting session.</summary>
 </histogram>
 
+<histogram name="Media.Remoting.StartMediaBitrate" units="kbps">
+  <owner>miu@chromium.org</owner>
+  <summary>
+    The estimated content bitrate (including both audio and video) when starting
+    a remoting session.
+  </summary>
+</histogram>
+
 <histogram name="Media.Remoting.TimeUntilFirstPlayout" units="ms">
   <owner>miu@chromium.org</owner>
   <summary>
@@ -31078,6 +31110,13 @@
   <summary>Tracks whether audio or video or both are remoted.</summary>
 </histogram>
 
+<histogram name="Media.Remoting.TransmissionCapacity" units="kbps">
+  <owner>miu@chromium.org</owner>
+  <summary>
+    The estimated transmission capacity when starting a remoting session.
+  </summary>
+</histogram>
+
 <histogram name="Media.Remoting.VideoAspectRatio" units="%">
   <owner>miu@chromium.org</owner>
   <summary>Aspect ratio of video while remoting content.</summary>
diff --git a/tools/perf/benchmarks/tab_switching.py b/tools/perf/benchmarks/tab_switching.py
index 0b8fd8b..6fb4e741 100644
--- a/tools/perf/benchmarks/tab_switching.py
+++ b/tools/perf/benchmarks/tab_switching.py
@@ -48,4 +48,6 @@
       def SetExpectations(self):
         self.PermanentlyDisableBenchmark([story.expectations.ALL_MOBILE],
                                          'Desktop benchmark.')
+        self.DisableStory('multitab:misc:typical24',
+                          [story.expectations.ALL_MAC], 'crbug.com/747026')
     return StoryExpectations()
diff --git a/ui/aura/mus/drag_drop_controller_mus.cc b/ui/aura/mus/drag_drop_controller_mus.cc
index 1cc2a11..fea4fc0 100644
--- a/ui/aura/mus/drag_drop_controller_mus.cc
+++ b/ui/aura/mus/drag_drop_controller_mus.cc
@@ -236,6 +236,7 @@
                               : *(os_exchange_data_.get()),
           location, root_location, effect_bitmask);
   event->set_flags(event_flags);
+  ui::Event::DispatcherApi(event.get()).set_target(window);
   return event;
 }
 
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index d1275d8..7824691 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1041,7 +1041,7 @@
 });
 
 /**
- * Displays "open with"/"more actions" dialog for current selection.
+ * Displays "open with" dialog for current selection.
  * @type {Command}
  */
 CommandHandler.COMMANDS_['open-with'] = /** @type {Command} */ ({
@@ -1050,19 +1050,52 @@
    * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
    */
   execute: function(event, fileManager) {
-    fileManager.taskController.getFileTasks().then(function(tasks) {
-      tasks.showTaskPicker(fileManager.ui.defaultTaskPicker,
-          str('MORE_ACTIONS_BUTTON_LABEL'),
-          '',
-          function(task) {
-            tasks.execute(task.taskId);
-          },
-          false);
-    })
-    .catch(function(error) {
-      if (error)
-        console.error(error.stack || error);
-    });
+    fileManager.taskController.getFileTasks()
+        .then(function(tasks) {
+          tasks.showTaskPicker(
+              fileManager.ui.defaultTaskPicker, str('OPEN_WITH_BUTTON_LABEL'),
+              '', function(task) {
+                tasks.execute(task.taskId);
+              }, FileTasks.TaskPickerType.OpenWith);
+        })
+        .catch(function(error) {
+          if (error)
+            console.error(error.stack || error);
+        });
+  },
+  /**
+   * @param {!Event} event Command event.
+   * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
+   */
+  canExecute: function(event, fileManager) {
+    var canExecute = fileManager.taskController.canExecuteOpenActions();
+    event.canExecute = canExecute;
+    event.command.setHidden(!canExecute);
+  }
+});
+
+/**
+ * Displays "More actions" dialog for current selection.
+ * @type {Command}
+ */
+CommandHandler.COMMANDS_['more-actions'] = /** @type {Command} */ ({
+  /**
+   * @param {!Event} event Command event.
+   * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
+   */
+  execute: function(event, fileManager) {
+    fileManager.taskController.getFileTasks()
+        .then(function(tasks) {
+          tasks.showTaskPicker(
+              fileManager.ui.defaultTaskPicker,
+              str('MORE_ACTIONS_BUTTON_LABEL'), '', function(task) {
+                tasks.execute(task.taskId);
+              }, FileTasks.TaskPickerType.MoreActions);
+        })
+        .catch(function(error) {
+          if (error)
+            console.error(error.stack || error);
+        });
   },
   /**
    * @param {!Event} event Command event.
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js
index 5b83189..6014c84c 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.js
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -110,6 +110,16 @@
 };
 
 /**
+ * Dialog types to show a task picker.
+ * @enum {string}
+ */
+FileTasks.TaskPickerType = {
+  ChangeDefault: 'ChangeDefault',
+  OpenWith: 'OpenWith',
+  MoreActions: 'MoreActions'
+};
+
+/**
  * Creates an instance of FileTasks for the specified list of entries with mime
  * types.
  *
@@ -154,13 +164,29 @@
 
 /**
  * Obtains the task items.
- * @return {Array<!Object>}
+ * @return {!Array<!Object>}
  */
 FileTasks.prototype.getTaskItems = function() {
   return this.tasks_;
 };
 
 /**
+ * Obtain tasks which are categorized as OPEN tasks.
+ * @return {!Array<!Object>}
+ */
+FileTasks.prototype.getOpenTaskItems = function() {
+  return this.tasks_.filter(FileTasks.isOpenTask);
+};
+
+/**
+ * Obtain tasks which are not categorized as OPEN tasks.
+ * @return {!Array<!Object>}
+ */
+FileTasks.prototype.getNonOpenTaskItems = function() {
+  return this.tasks_.filter(task => !FileTasks.isOpenTask(task));
+};
+
+/**
  * Opens the suggest file dialog.
  *
  * @param {function()} onSuccess Success callback.
@@ -873,17 +899,16 @@
  * @param {string} title Title to use.
  * @param {string} message Message to use.
  * @param {function(Object)} onSuccess Callback to pass selected task.
- * @param {boolean=} opt_forChangeDefault Whether to return items which are for
- *     change-default dialog.
+ * @param {FileTasks.TaskPickerType} pickerType Task picker type.
  */
 FileTasks.prototype.showTaskPicker = function(
-    taskDialog, title, message, onSuccess, opt_forChangeDefault) {
-  var items = !opt_forChangeDefault ?
-      this.createItems_(this.tasks_) :
-      this.createItems_(this.tasks_.filter(FileTasks.isOpenTask))
-          .filter(function(item) {
-            return !item.isGenericFileHandler;
-          });
+    taskDialog, title, message, onSuccess, pickerType) {
+  var tasks = pickerType == FileTasks.TaskPickerType.MoreActions ?
+      this.getNonOpenTaskItems() :
+      this.getOpenTaskItems();
+  var items = this.createItems_(tasks);
+  if (pickerType == FileTasks.TaskPickerType.ChangeDefault)
+    items = items.filter(item => !item.isGenericFileHandler);
 
   var defaultIdx = 0;
   for (var j = 0; j < items.length; j++) {
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller.js b/ui/file_manager/file_manager/foreground/js/task_controller.js
index 54c4ca62..24efae7 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/task_controller.js
@@ -74,6 +74,11 @@
   /**
    * @private {boolean}
    */
+  this.canExecuteOpenActions_ = false;
+
+  /**
+   * @private {boolean}
+   */
   this.canExecuteMoreActions_ = false;
 
   /**
@@ -89,10 +94,19 @@
    * @private {!cr.ui.Command}
    * @const
    */
-  this.moreActionsCommand_ =
+  this.openWithCommand_ =
       assertInstanceof(document.querySelector('#open-with'), cr.ui.Command);
 
   /**
+   * More actions command that uses #open-with as selector due to the open-with
+   * command used previously for the same task.
+   * @private {!cr.ui.Command}
+   * @const
+   */
+  this.moreActionsCommand_ =
+      assertInstanceof(document.querySelector('#more-actions'), cr.ui.Command);
+
+  /**
    * @private {Promise<!FileTasks>}
    */
   this.tasks_ = null;
@@ -200,7 +214,8 @@
                 this.ui_.defaultTaskPicker,
                 loadTimeData.getString('CHANGE_DEFAULT_MENU_ITEM'),
                 strf('CHANGE_DEFAULT_CAPTION', format),
-                this.changeDefaultTask_.bind(this, selection), true);
+                this.changeDefaultTask_.bind(this, selection),
+                FileTasks.TaskPickerType.ChangeDefault);
             break;
           default:
             assertNotReached('Unknown task.');
@@ -303,11 +318,12 @@
       // Show disabled items for position calculation of the menu. They will be
       // overridden in this.updateTasks_().
       this.updateContextMenuTaskItems_(
+          [TaskController.createTemporaryDisabledTaskItem_()],
           [TaskController.createTemporaryDisabledTaskItem_()]);
     }
   } else {
     // Update context menu.
-    this.updateContextMenuTaskItems_([]);
+    this.updateContextMenuTaskItems_([], []);
   }
   this.lastSelectedEntries_ = selection.entries;
 };
@@ -323,7 +339,8 @@
     this.getFileTasks()
         .then(function(tasks) {
           tasks.display(this.ui_.taskMenuButton, this.ui_.shareMenuButton);
-          this.updateContextMenuTaskItems_(tasks.getTaskItems());
+          this.updateContextMenuTaskItems_(
+              tasks.getOpenTaskItems(), tasks.getNonOpenTaskItems());
         }.bind(this))
         .catch(function(error) {
           if (error)
@@ -380,6 +397,14 @@
  * Returns whether open with command can be executed or not.
  * @return {boolean} True if open with command is executable.
  */
+TaskController.prototype.canExecuteOpenActions = function() {
+  return this.canExecuteOpenActions_;
+};
+
+/**
+ * Returns whether open with command can be executed or not.
+ * @return {boolean} True if open with command is executable.
+ */
 TaskController.prototype.canExecuteMoreActions = function() {
   return this.canExecuteMoreActions_;
 };
@@ -387,16 +412,18 @@
 /**
  * Updates tasks menu item to match passed task items.
  *
- * @param {!Array<!Object>} items List of items.
+ * @param {!Array<!Object>} openTasks List of OPEN tasks.
+ * @param {!Array<!Object>} nonOpenTasks List of non-OPEN tasks.
  * @private
  */
-TaskController.prototype.updateContextMenuTaskItems_ = function(items) {
+TaskController.prototype.updateContextMenuTaskItems_ = function(
+    openTasks, nonOpenTasks) {
   // Always show a default item in case at least one task is available, even
   // if there is no corresponding default task (i.e. the available task is
   // a generic handler).
-  if (items.length >= 1) {
+  if (openTasks.length >= 1) {
     var defaultTask = FileTasks.getDefaultTask(
-        items, items[0] /* task to use in case of no default */);
+        openTasks, openTasks[0] /* task to use in case of no default */);
 
     if (defaultTask.iconType) {
       this.ui_.fileContextMenu.defaultTaskMenuItem.style.backgroundImage = '';
@@ -417,13 +444,17 @@
     this.ui_.fileContextMenu.defaultTaskMenuItem.taskId = defaultTask.taskId;
   }
 
-  this.canExecuteDefaultTask_ = items.length >= 1;
+  this.canExecuteDefaultTask_ = openTasks.length >= 1;
   this.defaultTaskCommand_.canExecuteChange(this.ui_.listContainer.element);
 
-  this.canExecuteMoreActions_ = items.length > 1;
+  this.canExecuteOpenActions_ = openTasks.length > 1;
+  this.openWithCommand_.canExecuteChange(this.ui_.listContainer.element);
+
+  this.canExecuteMoreActions_ = nonOpenTasks.length >= 1;
   this.moreActionsCommand_.canExecuteChange(this.ui_.listContainer.element);
 
-  this.ui_.fileContextMenu.tasksSeparator.hidden = items.length === 0;
+  this.ui_.fileContextMenu.tasksSeparator.hidden =
+      openTasks.length === 0 && nonOpenTasks.length == 0;
 };
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html
index e3d00339..aaf52f2 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html
+++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.html
@@ -5,6 +5,7 @@
   -->
 <command id="default-task">
 <command id="open-with">
+<command id="more-actions">
 
 <script src="../../../../../ui/webui/resources/js/assert.js"></script>
 <script src="../../../../../ui/webui/resources/js/cr.js"></script>
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index 9de8440..d5c219e 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -141,7 +141,8 @@
                shortcut=".|Ctrl" hide-shortcut-text>
 
       <command id="default-task">
-      <command id="open-with" i18n-values="label:MORE_ACTIONS_BUTTON_LABEL">
+      <command id="open-with" i18n-values="label:OPEN_WITH_BUTTON_LABEL">
+      <command id="more-actions" i18n-values="label:MORE_ACTIONS_BUTTON_LABEL">
       <command id="zip-selection"
                i18n-values="label:ZIP_SELECTION_BUTTON_LABEL">
       <command id="set-wallpaper"
@@ -176,6 +177,8 @@
                 visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
       <cr-menu-item command="#open-with"
                 visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
+      <cr-menu-item command="#more-actions"
+                visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
       <hr id="tasks-separator" visibleif="full-page" class="hide-on-toolbar" hidden>
       <hr id="actions-separator" hidden>
       <cr-menu-item command="#cut" visibleif="full-page"></cr-menu-item>