diff --git a/DEPS b/DEPS
index 47edf0a..b9a11b24 100644
--- a/DEPS
+++ b/DEPS
@@ -78,7 +78,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'c95f446a72b54bea1aedf0b9404c224a52cd7d7f',
+  'v8_revision': '731ae996267793630be9d181e28c19c7a517579f',
   # 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.
@@ -130,7 +130,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'c68d77210850701f125f85e73c80f85946e9c5a0',
+  'catapult_revision': '6abc09e80f31d1761009c10abcc3e21198cfa669',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc
index 28f9232..2fb8cee8 100644
--- a/android_webview/common/crash_reporter/crash_keys.cc
+++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -15,30 +15,16 @@
 
 const char kActiveURL[] = "url-chunk";
 
-const char kShutdownType[] = "shutdown-type";
-const char kBrowserUnpinTrace[] = "browser-unpin-trace";
-
 const char kAppPackageName[] = "app-package-name";
 const char kAppPackageVersionCode[] = "app-package-version-code";
 
 const char kAndroidSdkInt[] = "android-sdk-int";
 
-const char kViewCount[] = "view-count";
-
-const char kZeroEncodeDetails[] = "zero-encode-details";
-
 size_t RegisterWebViewCrashKeys() {
   base::debug::CrashKey fixed_keys[] = {
       {kActiveURL, kLargeSize},
       {kNumVariations, kSmallSize},
       {kVariations, kHugeSize},
-      {kShutdownType, kSmallSize},
-      {kBrowserUnpinTrace, kMediumSize},
-
-      {kViewCount, kSmallSize},
-
-      // media/:
-      {kZeroEncodeDetails, kSmallSize},
 
       // TODO(sunnyps): Remove after fixing crbug.com/724999.
       {"gl-context-set-current-stack-trace", kMediumSize},
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 74b2529..be2d29e 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -402,7 +402,11 @@
           rebase_path("//build/toolchain/gcc_solink_wrapper.py", root_build_dir)
       command = "$python_path \"$solink_wrapper\" --readelf=\"$readelf\" --nm=\"$nm\" $strip_switch--sofile=\"$unstripped_sofile\" --tocfile=\"$tocfile\"$map_switch --output=\"$sofile\"$whitelist_flag -- $link_command"
 
-      rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix"
+      if (target_cpu == "mipsel" && is_component_build && is_android) {
+        rspfile_content = "-Wl,--start-group -Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix -Wl,--end-group"
+      } else {
+        rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix"
+      }
 
       description = "SOLINK $sofile"
 
diff --git a/chrome/app/chrome_crash_reporter_client_win.cc b/chrome/app/chrome_crash_reporter_client_win.cc
index 825220c..c520371 100644
--- a/chrome/app/chrome_crash_reporter_client_win.cc
+++ b/chrome/app/chrome_crash_reporter_client_win.cc
@@ -37,36 +37,8 @@
 // and the snprintf function defined here.
 constexpr char kActiveURL[] = "url-chunk";
 
-// Installed extensions. |kExtensionID| should be formatted with an integer,
-// in the range [0, kExtensionIDMaxCount).
-constexpr char kNumExtensionsCount[] = "num-extensions";
-constexpr size_t kExtensionIDMaxCount = 10;
-constexpr char kExtensionID[] = "extension-%" PRIuS;
-
-constexpr char kShutdownType[] = "shutdown-type";
-constexpr char kBrowserUnpinTrace[] = "browser-unpin-trace";
-
-constexpr char kViewCount[] = "view-count";
-constexpr char kZeroEncodeDetails[] = "zero-encode-details";
-
-// The user's printers, up to kPrinterInfoCount. Should be set with
-// ScopedPrinterInfo.
-constexpr size_t kPrinterInfoCount = 4;
-constexpr char kPrinterInfo[] = "prn-info-%" PRIuS;
-
 using namespace crash_keys;
 
-int snprintf(char* buffer,
-             size_t size,
-             _Printf_format_string_ const char* format,
-             ...) {
-  va_list arguments;
-  va_start(arguments, format);
-  int result = vsnprintf(buffer, size, format, arguments);
-  va_end(arguments);
-  return result;
-}
-
 size_t RegisterCrashKeysHelper() {
   // The following keys may be chunked by the underlying crash logging system,
   // but ultimately constitute a single key-value pair.
@@ -77,14 +49,6 @@
       {kActiveURL, kLargeSize},
       {kNumVariations, kSmallSize},
       {kVariations, kHugeSize},
-      {kNumExtensionsCount, kSmallSize},
-      {kShutdownType, kSmallSize},
-      {kBrowserUnpinTrace, kMediumSize},
-
-      {kViewCount, kSmallSize},
-
-      // media/:
-      {kZeroEncodeDetails, kSmallSize},
 
       // TODO(sunnyps): Remove after fixing crbug.com/724999.
       {"gl-context-set-current-stack-trace", kMediumSize},
@@ -95,31 +59,6 @@
   std::vector<base::debug::CrashKey> keys(std::begin(kFixedKeys),
                                           std::end(kFixedKeys));
 
-  // Register the extension IDs.
-  {
-    static char formatted_keys[kExtensionIDMaxCount]
-                              [sizeof(kExtensionID) + 1] = {{0}};
-    const size_t formatted_key_len = sizeof(formatted_keys[0]);
-    for (size_t i = 0; i < kExtensionIDMaxCount; ++i) {
-      snprintf(formatted_keys[i], formatted_key_len, kExtensionID, i + 1);
-      base::debug::CrashKey crash_key = {formatted_keys[i], kSmallSize};
-      keys.push_back(crash_key);
-    }
-  }
-
-  // Register the printer info.
-  {
-    static char formatted_keys[kPrinterInfoCount]
-                              [sizeof(kPrinterInfo) + 1] = {{0}};
-    const size_t formatted_key_len = sizeof(formatted_keys[0]);
-    for (size_t i = 0; i < kPrinterInfoCount; ++i) {
-      // Key names are 1-indexed.
-      snprintf(formatted_keys[i], formatted_key_len, kPrinterInfo, i + 1);
-      base::debug::CrashKey crash_key = {formatted_keys[i], kSmallSize};
-      keys.push_back(crash_key);
-    }
-  }
-
   return base::debug::InitCrashKeys(&keys[0], keys.size(), kChunkMaxLength);
 }
 
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 74517519..106a6ea9 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3670,7 +3670,13 @@
 
 // Tests that a webview inside an iframe can load and that it is destroyed when
 // the iframe is detached.
-IN_PROC_BROWSER_TEST_P(WebViewTest, LoadWebviewInsideIframe) {
+// Flakily times out under MSan. crbug.com/793422
+#if defined(MEMORY_SANITIZER)
+#define MAYBE_LoadWebviewInsideIframe DISABLED_LoadWebviewInsideIframe
+#else
+#define MAYBE_LoadWebviewInsideIframe LoadWebviewInsideIframe
+#endif
+IN_PROC_BROWSER_TEST_P(WebViewTest, MAYBE_LoadWebviewInsideIframe) {
   TestHelper("testLoadWebviewInsideIframe",
              "web_view/load_webview_inside_iframe", NEEDS_TEST_SERVER);
 
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 8002e031..5ff8817 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -15,7 +15,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
-#include "base/debug/crash_logging.h"
 #include "base/debug/leak_annotations.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
@@ -81,13 +80,13 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/crash_keys.h"
 #include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "components/component_updater/component_updater_service.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/gcm_driver/gcm_driver.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/metrics/metrics_service.h"
@@ -1366,9 +1365,13 @@
 
   // CHECK(!IsShuttingDown());
   if (IsShuttingDown()) {
-    // TODO(crbug.com/113031, crbug.com/625646): Temporary instrumentation.
-    base::debug::SetCrashKeyToStackTrace(crash_keys::kBrowserUnpinTrace,
-                                         release_last_reference_callstack_);
+    // TODO(rsesek): Consider removing this trace, but it has been helpful
+    // in debugging several shutdown crashes (https://crbug.com/113031,
+    // https://crbug.com/625646, and https://crbug.com/779829).
+    static crash_reporter::CrashKeyString<1024> browser_unpin_trace(
+        "browser-unpin-trace");
+    crash_reporter::SetCrashKeyStringToStackTrace(
+        &browser_unpin_trace, release_last_reference_callstack_);
     CHECK(false);
   }
 }
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index 2fb4f81..25acca55 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -30,8 +30,8 @@
 #include "chrome/browser/profiles/profile_metrics.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/crash_keys.h"
 #include "chrome/common/pref_names.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/metrics/metrics_service.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
@@ -120,8 +120,10 @@
 void OnShutdownStarting(ShutdownType type) {
   if (g_shutdown_type != NOT_VALID)
     return;
-  base::debug::SetCrashKeyValue(crash_keys::kShutdownType,
-                                ToShutdownTypeString(type));
+
+  static crash_reporter::CrashKeyString<8> shutdown_type_key("shutdown-type");
+  shutdown_type_key.Set(ToShutdownTypeString(type));
+
 #if !defined(OS_CHROMEOS)
   // Start the shutdown tracing. Note that On ChromeOS this has already been
   // called in AttemptUserExit().
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc
index a611c1c..f5468575 100644
--- a/chrome/common/crash_keys.cc
+++ b/chrome/common/crash_keys.cc
@@ -6,14 +6,14 @@
 
 #include "base/base_switches.h"
 #include "base/command_line.h"
-#include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/flags_ui/flags_ui_switches.h"
 #include "content/public/common/content_switches.h"
 
@@ -27,16 +27,6 @@
 
 const char kActiveURL[] = "url-chunk";
 
-const char kExtensionID[] = "extension-%" PRIuS;
-const char kNumExtensionsCount[] = "num-extensions";
-
-const char kShutdownType[] = "shutdown-type";
-const char kBrowserUnpinTrace[] = "browser-unpin-trace";
-
-const char kPrinterInfo[] = "prn-info-%" PRIuS;
-
-const char kViewCount[] = "view-count";
-
 size_t RegisterChromeCrashKeys() {
   // The following keys may be chunked by the underlying crash logging system,
   // but ultimately constitute a single key-value pair.
@@ -50,11 +40,6 @@
     {kActiveURL, kLargeSize},
     {kNumVariations, kSmallSize},
     {kVariations, kHugeSize},
-    {kNumExtensionsCount, kSmallSize},
-    {kShutdownType, kSmallSize},
-    {kBrowserUnpinTrace, kMediumSize},
-
-    {kViewCount, kSmallSize},
 
     // TODO(sunnyps): Remove after fixing crbug.com/724999.
     {"gl-context-set-current-stack-trace", kMediumSize},
@@ -65,35 +50,6 @@
   std::vector<base::debug::CrashKey> keys(
       fixed_keys, fixed_keys + arraysize(fixed_keys));
 
-  // Register the extension IDs.
-  {
-    static char formatted_keys[kExtensionIDMaxCount][sizeof(kExtensionID) + 1] =
-        {{ 0 }};
-    const size_t formatted_key_len = sizeof(formatted_keys[0]);
-    for (size_t i = 0; i < kExtensionIDMaxCount; ++i) {
-      int n = base::snprintf(
-          formatted_keys[i], formatted_key_len, kExtensionID, i + 1);
-      DCHECK_GT(n, 0);
-      base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
-      keys.push_back(crash_key);
-    }
-  }
-
-  // Register the printer info.
-  {
-    static char formatted_keys[kPrinterInfoCount][sizeof(kPrinterInfo) + 1] =
-        {{ 0 }};
-    const size_t formatted_key_len = sizeof(formatted_keys[0]);
-    for (size_t i = 0; i < kPrinterInfoCount; ++i) {
-      // Key names are 1-indexed.
-      int n = base::snprintf(
-          formatted_keys[i], formatted_key_len, kPrinterInfo, i + 1);
-      DCHECK_GT(n, 0);
-      base::debug::CrashKey crash_key = { formatted_keys[i], kSmallSize };
-      keys.push_back(crash_key);
-    }
-  }
-
   return base::debug::InitCrashKeys(&keys.at(0), keys.size(), kChunkMaxLength);
 }
 
@@ -156,37 +112,56 @@
 }
 
 void SetActiveExtensions(const std::set<std::string>& extensions) {
-  base::debug::SetCrashKeyValue(kNumExtensionsCount,
-      base::StringPrintf("%" PRIuS, extensions.size()));
+  static crash_reporter::CrashKeyString<4> num_extensions("num-extensions");
+  num_extensions.Set(base::NumberToString(extensions.size()));
+
+  using ExtensionIDKey = crash_reporter::CrashKeyString<64>;
+  static ExtensionIDKey extension_ids[] = {
+      {"extension-1", ExtensionIDKey::Tag::kArray},
+      {"extension-2", ExtensionIDKey::Tag::kArray},
+      {"extension-3", ExtensionIDKey::Tag::kArray},
+      {"extension-4", ExtensionIDKey::Tag::kArray},
+      {"extension-5", ExtensionIDKey::Tag::kArray},
+      {"extension-6", ExtensionIDKey::Tag::kArray},
+      {"extension-7", ExtensionIDKey::Tag::kArray},
+      {"extension-8", ExtensionIDKey::Tag::kArray},
+      {"extension-9", ExtensionIDKey::Tag::kArray},
+      {"extension-10", ExtensionIDKey::Tag::kArray},
+  };
 
   std::set<std::string>::const_iterator it = extensions.begin();
-  for (size_t i = 0; i < kExtensionIDMaxCount; ++i) {
-    std::string key = base::StringPrintf(kExtensionID, i + 1);
+  for (size_t i = 0; i < arraysize(extension_ids); ++i) {
     if (it == extensions.end()) {
-      base::debug::ClearCrashKey(key);
+      extension_ids[i].Clear();
     } else {
-      base::debug::SetCrashKeyValue(key, *it);
+      extension_ids[i].Set(*it);
       ++it;
     }
   }
 }
 
+using PrinterInfoKey = crash_reporter::CrashKeyString<64>;
+static PrinterInfoKey printer_info_keys[] = {
+    {"prn-info-1", PrinterInfoKey::Tag::kArray},
+    {"prn-info-2", PrinterInfoKey::Tag::kArray},
+    {"prn-info-3", PrinterInfoKey::Tag::kArray},
+    {"prn-info-4", PrinterInfoKey::Tag::kArray},
+};
+
 ScopedPrinterInfo::ScopedPrinterInfo(const base::StringPiece& data) {
   std::vector<std::string> info = base::SplitString(
       data.as_string(), ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-  for (size_t i = 0; i < kPrinterInfoCount; ++i) {
-    std::string key = base::StringPrintf(kPrinterInfo, i + 1);
+  for (size_t i = 0; i < arraysize(printer_info_keys); ++i) {
     std::string value;
     if (i < info.size())
       value = info[i];
-    base::debug::SetCrashKeyValue(key, value);
+    printer_info_keys[i].Set(value);
   }
 }
 
 ScopedPrinterInfo::~ScopedPrinterInfo() {
-  for (size_t i = 0; i < kPrinterInfoCount; ++i) {
-    std::string key = base::StringPrintf(kPrinterInfo, i + 1);
-    base::debug::ClearCrashKey(key);
+  for (auto& crash_key : printer_info_keys) {
+    crash_key.Clear();
   }
 }
 
diff --git a/chrome/common/crash_keys.h b/chrome/common/crash_keys.h
index 90837a0d8..ea9b80aa 100644
--- a/chrome/common/crash_keys.h
+++ b/chrome/common/crash_keys.h
@@ -54,32 +54,6 @@
 // The URL actively being processed in some way.
 extern const char kActiveURL[];
 
-// Installed extensions. |kExtensionID| should be formatted with an integer,
-// in the range [0, kExtensionIDMaxCount).
-const size_t kExtensionIDMaxCount = 10;
-extern const char kExtensionID[];
-// The total number of installed extensions, recorded in case it exceeds
-// kExtensionIDMaxCount. Also used in chrome/app, but defined here to avoid
-// a common->app dependency.
-extern const char kNumExtensionsCount[];
-
-// Type of shutdown. The value is one of "close" for WINDOW_CLOSE,
-// "exit" for BROWSER_EXIT, or "end" for END_SESSION.
-extern const char kShutdownType[];
-
-// Stack trace associated to the browser being unpinned and starting the
-// shutdown sequence. The value is set when we trigger a browser crash due to an
-// invalid attempt to Pin the browser process after that.
-extern const char kBrowserUnpinTrace[];
-
-// The user's printers, up to kPrinterInfoCount. Should be set with
-// ScopedPrinterInfo.
-const size_t kPrinterInfoCount = 4;
-extern const char kPrinterInfo[];
-
-// Numbers of active views.
-extern const char kViewCount[];
-
 }  // namespace crash_keys
 
 #endif  // CHROME_COMMON_CRASH_KEYS_H_
diff --git a/chrome/common/crash_keys_unittest.cc b/chrome/common/crash_keys_unittest.cc
index 5d88b0d..80b1781 100644
--- a/chrome/common/crash_keys_unittest.cc
+++ b/chrome/common/crash_keys_unittest.cc
@@ -4,14 +4,10 @@
 
 #include "chrome/common/crash_keys.h"
 
-#include <map>
 #include <set>
 #include <string>
 
 #include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/debug/crash_logging.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "components/crash/core/common/crash_key.h"
@@ -24,46 +20,13 @@
   void SetUp() override {
     crash_reporter::ResetCrashKeysForTesting();
     crash_reporter::InitializeCrashKeys();
-    self_ = this;
-    base::debug::SetCrashKeyReportingFunctions(
-        &SetCrashKeyValue, &ClearCrashKey);
-    crash_keys::RegisterChromeCrashKeys();
   }
 
   void TearDown() override {
-    base::debug::ResetCrashLoggingForTesting();
     crash_reporter::ResetCrashKeysForTesting();
-    self_ = NULL;
   }
-
-  bool HasCrashKey(const std::string& key) {
-    return keys_.find(key) != keys_.end();
-  }
-
-  std::string GetKeyValue(const std::string& key) {
-    std::map<std::string, std::string>::const_iterator it = keys_.find(key);
-    if (it == keys_.end())
-      return std::string();
-    return it->second;
-  }
-
- private:
-  static void SetCrashKeyValue(const base::StringPiece& key,
-                               const base::StringPiece& value) {
-    self_->keys_[key.as_string()] = value.as_string();
-  }
-
-  static void ClearCrashKey(const base::StringPiece& key) {
-    self_->keys_.erase(key.as_string());
-  }
-
-  static CrashKeysTest* self_;
-
-  std::map<std::string, std::string> keys_;
 };
 
-CrashKeysTest* CrashKeysTest::self_ = NULL;
-
 TEST_F(CrashKeysTest, Extensions) {
   // Set three extensions.
   {
@@ -74,33 +37,31 @@
 
     crash_keys::SetActiveExtensions(extensions);
 
-    extensions.erase(GetKeyValue("extension-1"));
-    extensions.erase(GetKeyValue("extension-2"));
-    extensions.erase(GetKeyValue("extension-3"));
+    extensions.erase(GetCrashKeyValue("extension-1"));
+    extensions.erase(GetCrashKeyValue("extension-2"));
+    extensions.erase(GetCrashKeyValue("extension-3"));
     EXPECT_EQ(0u, extensions.size());
 
-    EXPECT_EQ("3", GetKeyValue("num-extensions"));
-    EXPECT_FALSE(HasCrashKey("extension-4"));
+    EXPECT_EQ("3", GetCrashKeyValue("num-extensions"));
+    EXPECT_TRUE(GetCrashKeyValue("extension-4").empty());
   }
 
   // Set more than the max switches.
   {
     std::set<std::string> extensions;
-    const int kMax = crash_keys::kExtensionIDMaxCount + 2;
-    EXPECT_GT(kMax, 10);
+    const int kMax = 12;
     for (int i = 1; i <= kMax; ++i)
       extensions.insert(base::StringPrintf("ext.%d", i));
     crash_keys::SetActiveExtensions(extensions);
 
     for (int i = 1; i <= kMax; ++i) {
-      extensions.erase(
-          GetKeyValue(base::StringPrintf(crash_keys::kExtensionID, i)));
+      extensions.erase(GetCrashKeyValue(base::StringPrintf("extension-%d", i)));
     }
     EXPECT_EQ(2u, extensions.size());
 
-    EXPECT_EQ("12", GetKeyValue("num-extensions"));
-    EXPECT_FALSE(HasCrashKey("extension-13"));
-    EXPECT_FALSE(HasCrashKey("extension-14"));
+    EXPECT_EQ("12", GetCrashKeyValue("num-extensions"));
+    EXPECT_TRUE(GetCrashKeyValue("extension-13").empty());
+    EXPECT_TRUE(GetCrashKeyValue("extension-14").empty());
   }
 
   // Set fewer to ensure that old ones are erased.
@@ -110,17 +71,17 @@
       extensions.insert(base::StringPrintf("ext.%d", i));
     crash_keys::SetActiveExtensions(extensions);
 
-    extensions.erase(GetKeyValue("extension-1"));
-    extensions.erase(GetKeyValue("extension-2"));
-    extensions.erase(GetKeyValue("extension-3"));
-    extensions.erase(GetKeyValue("extension-4"));
-    extensions.erase(GetKeyValue("extension-5"));
+    extensions.erase(GetCrashKeyValue("extension-1"));
+    extensions.erase(GetCrashKeyValue("extension-2"));
+    extensions.erase(GetCrashKeyValue("extension-3"));
+    extensions.erase(GetCrashKeyValue("extension-4"));
+    extensions.erase(GetCrashKeyValue("extension-5"));
     EXPECT_EQ(0u, extensions.size());
 
-    EXPECT_EQ("5", GetKeyValue("num-extensions"));
+    EXPECT_EQ("5", GetCrashKeyValue("num-extensions"));
     for (int i = 6; i < 20; ++i) {
-      std::string key = base::StringPrintf(crash_keys::kExtensionID, i);
-      EXPECT_FALSE(HasCrashKey(key)) << key;
+      std::string key = base::StringPrintf("extension-%d", i);
+      EXPECT_TRUE(GetCrashKeyValue(key).empty()) << key;
     }
   }
 }
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index 8b88a94..84c43812 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -6,6 +6,7 @@
   "+components/cdm/renderer",
   "+components/content_settings/core/common",
   "+components/contextual_search/renderer",
+  "+components/crash/core/common/crash_key.h",
   "+components/crx_file",
   "+components/data_reduction_proxy/content/renderer",
   "+components/data_reduction_proxy/core/common",
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index 77ff544..1884521 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -20,13 +20,13 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_isolated_world_ids.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/crash_keys.h"
 #include "chrome/common/open_search_description_document_handler.mojom.h"
 #include "chrome/common/prerender_messages.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
 #include "chrome/renderer/web_apps.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/translate/content/renderer/translate_helper.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/renderer/render_frame.h"
@@ -355,8 +355,8 @@
   if (frame->Parent())
     return;
 
-  base::debug::SetCrashKeyValue(
-      crash_keys::kViewCount,
+  static crash_reporter::CrashKeyString<8> view_count_key("view-count");
+  view_count_key.Set(
       base::NumberToString(content::RenderView::GetRenderViewCount()));
 
 #if !defined(OS_ANDROID)
diff --git a/chromecast/crash/cast_crash_keys.cc b/chromecast/crash/cast_crash_keys.cc
index b2d513ff..b00d4b3 100644
--- a/chromecast/crash/cast_crash_keys.cc
+++ b/chromecast/crash/cast_crash_keys.cc
@@ -19,14 +19,6 @@
       {"url-chunk", ::crash_keys::kLargeSize},
       {::crash_keys::kNumVariations, ::crash_keys::kSmallSize},
       {::crash_keys::kVariations, ::crash_keys::kHugeSize},
-      {"num-extensions", ::crash_keys::kSmallSize},
-      {"shutdown-type", ::crash_keys::kSmallSize},
-      {"browser-unpin-trace", ::crash_keys::kMediumSize},
-
-      {"view-count", ::crash_keys::kSmallSize},
-
-      // media/:
-      {"zero-encode-details", ::crash_keys::kSmallSize},
 
       // TODO(sunnyps): Remove after fixing crbug.com/724999.
       {"gl-context-set-current-stack-trace", ::crash_keys::kMediumSize},
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc
index 284f477..f9b0251 100644
--- a/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -283,9 +283,10 @@
 
   if (should_cvc_be_requested_) {
     // If we're requesting CVC from the user, it should be because the CVC field
-    // was not found or it was found but empty or with an invalid value.
+    // was not found or it was found but empty or with an invalid value. In any
+    // of those cases, CVC will not have been set on the card in the request.
+    DCHECK(upload_request_.cvc.empty());
     upload_decision_metrics_ |= GetCVCCardUploadDecisionMetric();
-    DCHECK(!found_cvc_field_ || !found_value_in_cvc_field_);
   } else {
     // If we're not requesting CVC from the user, assert that we've either
     // detected the CVC or the send detected values experiment is enabled.
@@ -515,6 +516,7 @@
 
 AutofillMetrics::CardUploadDecisionMetric
 CreditCardSaveManager::GetCVCCardUploadDecisionMetric() const {
+  // This function assumes a valid CVC was not found.
   if (found_cvc_field_) {
     return found_value_in_cvc_field_ ? AutofillMetrics::INVALID_CVC_VALUE
                                      : AutofillMetrics::CVC_VALUE_NOT_FOUND;
diff --git a/components/autofill/core/browser/credit_card_save_manager.h b/components/autofill/core/browser/credit_card_save_manager.h
index d65b625..973a687f 100644
--- a/components/autofill/core/browser/credit_card_save_manager.h
+++ b/components/autofill/core/browser/credit_card_save_manager.h
@@ -119,7 +119,8 @@
 
   // Returns metric relevant to the CVC field based on values in
   // |found_cvc_field_|, |found_value_in_cvc_field_| and
-  // |found_cvc_value_in_non_cvc_field_|.
+  // |found_cvc_value_in_non_cvc_field_|. Only called when a valid CVC was NOT
+  // found.
   AutofillMetrics::CardUploadDecisionMetric GetCVCCardUploadDecisionMetric()
       const;
 
diff --git a/content/browser/webrtc/webrtc_pause_play_browsertest.cc b/content/browser/webrtc/webrtc_stress_pause_browsertest.cc
similarity index 83%
rename from content/browser/webrtc/webrtc_pause_play_browsertest.cc
rename to content/browser/webrtc/webrtc_stress_pause_browsertest.cc
index 3a386edb..e95a00a 100644
--- a/content/browser/webrtc/webrtc_pause_play_browsertest.cc
+++ b/content/browser/webrtc/webrtc_stress_pause_browsertest.cc
@@ -28,15 +28,15 @@
 
 #if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
 // Renderer crashes under Android ASAN: https://crbug.com/408496.
-#define MAYBE_WebRtcPausePlayBrowserTest DISABLED_WebRtcPausePlayBrowserTest
+#define MAYBE_WebRtcStressPauseBrowserTest DISABLED_WebRtcStressPauseBrowserTest
 #else
-#define MAYBE_WebRtcPausePlayBrowserTest WebRtcPausePlayBrowserTest
+#define MAYBE_WebRtcStressPauseBrowserTest WebRtcStressPauseBrowserTest
 #endif
 
-class MAYBE_WebRtcPausePlayBrowserTest : public WebRtcContentBrowserTestBase {
+class MAYBE_WebRtcStressPauseBrowserTest : public WebRtcContentBrowserTestBase {
  public:
-  MAYBE_WebRtcPausePlayBrowserTest() {}
-  ~MAYBE_WebRtcPausePlayBrowserTest() override {}
+  MAYBE_WebRtcStressPauseBrowserTest() {}
+  ~MAYBE_WebRtcStressPauseBrowserTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     WebRtcContentBrowserTestBase::SetUpCommandLine(command_line);
@@ -50,7 +50,7 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcPausePlayBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcStressPauseBrowserTest,
                        MANUAL_SurvivesPeerConnectionVideoPausePlaying) {
   // Args: runtimeSeconds, numPeerConnections, pausePlayIterationDelayMillis,
   // elementType.
@@ -59,7 +59,7 @@
                          kTestDurationSecs, kNumPeerConnections));
 }
 
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcPausePlayBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcStressPauseBrowserTest,
                        MANUAL_SurvivesPeerConnectionAudioPausePlaying) {
   // Args: runtimeSeconds, numPeerConnections, pausePlayIterationDelayMillis,
   // elementType.
diff --git a/content/browser/webrtc/webrtc_resolution_switch_browsertest.cc b/content/browser/webrtc/webrtc_stress_resolution_switch_browsertest.cc
similarity index 80%
rename from content/browser/webrtc/webrtc_resolution_switch_browsertest.cc
rename to content/browser/webrtc/webrtc_stress_resolution_switch_browsertest.cc
index 31ff75d..1494d11 100644
--- a/content/browser/webrtc/webrtc_resolution_switch_browsertest.cc
+++ b/content/browser/webrtc/webrtc_stress_resolution_switch_browsertest.cc
@@ -28,18 +28,18 @@
 
 #if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
 // Renderer crashes under Android ASAN: https://crbug.com/408496.
-#define MAYBE_WebRtcResolutionSwitchBrowserTest \
-  DISABLED_WebRtcResolutionSwitchBrowserTest
+#define MAYBE_WebRtcStressResolutionSwitchBrowserTest \
+  DISABLED_WebRtcStressResolutionSwitchBrowserTest
 #else
-#define MAYBE_WebRtcResolutionSwitchBrowserTest \
-  WebRtcResolutionSwitchBrowserTest
+#define MAYBE_WebRtcStressResolutionSwitchBrowserTest \
+  WebRtcStressResolutionSwitchBrowserTest
 #endif
 
-class MAYBE_WebRtcResolutionSwitchBrowserTest
+class MAYBE_WebRtcStressResolutionSwitchBrowserTest
     : public WebRtcContentBrowserTestBase {
  public:
-  MAYBE_WebRtcResolutionSwitchBrowserTest() {}
-  ~MAYBE_WebRtcResolutionSwitchBrowserTest() override {}
+  MAYBE_WebRtcStressResolutionSwitchBrowserTest() {}
+  ~MAYBE_WebRtcStressResolutionSwitchBrowserTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     WebRtcContentBrowserTestBase::SetUpCommandLine(command_line);
@@ -53,7 +53,7 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcResolutionSwitchBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcStressResolutionSwitchBrowserTest,
                        MANUAL_SurvivesPeerConnectionResolutionSwitching) {
   // Args: runtimeSeconds, numPeerConnections, iterationDelayMillis.
   MakeTypicalPeerConnectionCall(base::StringPrintf(
diff --git a/content/browser/webrtc/webrtc_source_feed_switch_browsertest.cc b/content/browser/webrtc/webrtc_stress_source_switch_browsertest.cc
similarity index 82%
rename from content/browser/webrtc/webrtc_source_feed_switch_browsertest.cc
rename to content/browser/webrtc/webrtc_stress_source_switch_browsertest.cc
index 224c37a..0924d9ec 100644
--- a/content/browser/webrtc/webrtc_source_feed_switch_browsertest.cc
+++ b/content/browser/webrtc/webrtc_stress_source_switch_browsertest.cc
@@ -30,18 +30,18 @@
 
 #if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
 // Renderer crashes under Android ASAN: https://crbug.com/408496.
-#define MAYBE_WebRtcSourceFeedSwitchBrowserTest \
-  DISABLED_WebRtcSourceFeedSwitchBrowserTest
+#define MAYBE_WebRtcStressSourceSwitchBrowserTest \
+  DISABLED_WebRtcStressSourceSwitchBrowserTest
 #else
-#define MAYBE_WebRtcSourceFeedSwitchBrowserTest \
-  WebRtcSourceFeedSwitchBrowserTest
+#define MAYBE_WebRtcStressSourceSwitchBrowserTest \
+  WebRtcStressSourceSwitchBrowserTest
 #endif
 
-class MAYBE_WebRtcSourceFeedSwitchBrowserTest
+class MAYBE_WebRtcStressSourceSwitchBrowserTest
     : public WebRtcContentBrowserTestBase {
  public:
-  MAYBE_WebRtcSourceFeedSwitchBrowserTest() {}
-  ~MAYBE_WebRtcSourceFeedSwitchBrowserTest() override {}
+  MAYBE_WebRtcStressSourceSwitchBrowserTest() {}
+  ~MAYBE_WebRtcStressSourceSwitchBrowserTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     WebRtcContentBrowserTestBase::SetUpCommandLine(command_line);
@@ -56,7 +56,7 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcSourceFeedSwitchBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcStressSourceSwitchBrowserTest,
                        MANUAL_SurvivesPeerConnectionSrcFeedSwitching) {
   // Args: runtimeSeconds, numPeerConnections, iterationDelayMillis.
   MakeTypicalPeerConnectionCall(base::StringPrintf(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index c41b13a..b341260 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1063,9 +1063,9 @@
       "../browser/webrtc/webrtc_internals_browsertest.cc",
       "../browser/webrtc/webrtc_ip_permissions_browsertest.cc",
       "../browser/webrtc/webrtc_media_recorder_browsertest.cc",
-      "../browser/webrtc/webrtc_pause_play_browsertest.cc",
-      "../browser/webrtc/webrtc_resolution_switch_browsertest.cc",
-      "../browser/webrtc/webrtc_source_feed_switch_browsertest.cc",
+      "../browser/webrtc/webrtc_stress_pause_browsertest.cc",
+      "../browser/webrtc/webrtc_stress_resolution_switch_browsertest.cc",
+      "../browser/webrtc/webrtc_stress_source_switch_browsertest.cc",
       "../browser/webrtc/webrtc_video_capture_browsertest.cc",
       "../browser/webrtc/webrtc_webcam_browsertest.cc",
       "../browser/webrtc/webrtc_webcam_browsertest.h",
diff --git a/ios/third_party/material_internationalization_ios/BUILD.gn b/ios/third_party/material_internationalization_ios/BUILD.gn
index 30058798..9e52ad5 100644
--- a/ios/third_party/material_internationalization_ios/BUILD.gn
+++ b/ios/third_party/material_internationalization_ios/BUILD.gn
@@ -45,14 +45,3 @@
     "//build/config/gcc:symbol_visibility_default",
   ]
 }
-
-# TODO(crbug.com/785248): remove those targets when downstream has been fixed
-# to no longer use it but instead depend on :material_internationalization_ios.
-group("material_internationalization_ios+link") {
-  public_deps = [
-    ":material_internationalization_ios",
-  ]
-}
-
-group("material_internationalization_ios:bundle") {
-}
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/clipboard-event-targets-visible-unfocused-selection.html b/third_party/WebKit/LayoutTests/editing/pasteboard/clipboard-event-targets-visible-unfocused-selection.html
new file mode 100644
index 0000000..f5af3fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/clipboard-event-targets-visible-unfocused-selection.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<title>A visible but unfocused selection should receive ClipboardEvent</title>
+<link rel="help" href="https://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<input type="checkbox" id="checkbox">
+<p contenteditable id="ce">HEY</p>
+
+<script>
+resetSelection = function(selectedElement) {
+  selectedElement.innerHTML = "SOMETEXT"
+  let range = document.createRange();
+  range.selectNodeContents(selectedElement);
+  window.getSelection().removeAllRanges();
+  window.getSelection().addRange(range);
+}
+
+// We use testRunner.execCommand() to test user-triggered (not scripted) clipboard events.
+testClipboardEvent = function(eventName, selectedElement) {
+  let selectionHitCount = 0;
+  let documentHitCount = 0;
+  let lastTarget;
+  selectionLog = function(e) {
+    selectionHitCount++;
+    lastTarget = e.target;
+  }
+  documentLog = function(e) {
+    documentHitCount++;
+    lastTarget = e.target;
+  }
+  selectedElement.addEventListener(eventName, selectionLog);
+  document.addEventListener(eventName, documentLog);
+
+  selectedElement.focus();
+  resetSelection(selectedElement);
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 1, `The selection should receive a ${eventName}-event.`)
+  assert_equals(documentHitCount, 1, `The document should receive a bubbled ${eventName}-event.`)
+  assert_equals(lastTarget, selectedElement, `The selection should be the ${eventName}-event's target.`)
+  resetSelection(selectedElement);
+
+  checkbox.focus();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 2, `The selection should receive a ${eventName}-event.`)
+  assert_equals(documentHitCount, 2, `The document should receive a bubbled ${eventName}-event.`)
+  assert_equals(lastTarget, selectedElement, `The selection should be the ${eventName}-event's target.`)
+  resetSelection(selectedElement);
+
+  checkbox.blur();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 3, `The selection should receive a ${eventName}-event.`)
+  assert_equals(documentHitCount, 3, `The document should receive a bubbled ${eventName}-event.`)
+  assert_equals(lastTarget, selectedElement, `The selection should be the ${eventName}-event's target.`)
+  resetSelection(selectedElement);
+
+  document.body.focus();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 4, `The selection should receive a ${eventName}-event.`)
+  assert_equals(documentHitCount, 4, `The document should receive a bubbled ${eventName}-event.`)
+  assert_equals(lastTarget, selectedElement, `The selection should be the ${eventName}-event's target.`)
+  resetSelection(selectedElement);
+}
+
+test(() => testClipboardEvent('copy', ce),  'Visible but unfocused selections are targeted by copy-events.');
+test(() => testClipboardEvent('paste', ce), 'Visible but unfocused selections are targeted by paste-events.');
+test(() => testClipboardEvent('cut', ce),   'Visible but unfocused selections are targeted by cut-events.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/no-clipboard-event-to-hidden-selection.html b/third_party/WebKit/LayoutTests/editing/pasteboard/no-clipboard-event-to-hidden-selection.html
new file mode 100644
index 0000000..1cf78003
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/no-clipboard-event-to-hidden-selection.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<title>A hidden carret should not receive ClipboardEvent</title>
+<link rel="help" href="https://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event">
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<input type="checkbox" id="checkbox">
+<textarea id="textcontrol">HEY</textarea>
+
+<script>
+// We use testRunner.execCommand() to test user-triggered (not scripted) clipboard events.
+testClipboardEvent = function(eventName, selectedElement) {
+  let selectionHitCount = 0;
+  let documentHitCount = 0;
+  let lastTarget;
+  selectionLog = function(e) {
+    selectionHitCount++;
+    lastTarget = e.target;
+  }
+  documentLog = function(e) {
+    documentHitCount++;
+    lastTarget = e.target;
+  }
+  selectedElement.addEventListener(eventName, selectionLog);
+  document.addEventListener(eventName, documentLog);
+
+  selectedElement.focus();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 1, `The <textarea> should receive one ${eventName}-event.`)
+  assert_equals(documentHitCount, 1, `The document should receive one bubbled ${eventName}-event.`)
+  assert_equals(lastTarget, selectedElement, `The <textarea> should be the ${eventName}-event's target.`)
+
+  checkbox.focus();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 1, `The carret is hidden in the <textarea> so the <textarea> should not receive an ${eventName}-event.`)
+  assert_equals(documentHitCount, 2, `The document should receive one ${eventName}-event.`)
+  assert_equals(lastTarget, document.body, `The document should be the ${eventName}-event's target.`)
+
+  checkbox.blur();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 1, `The carret is hidden in the <textarea> so the <textarea> should not receive an ${eventName}-event.`)
+  assert_equals(documentHitCount, 3, `The document should receive one ${eventName}-event.`)
+  assert_equals(lastTarget, document.body, `The document should be the ${eventName}-event's target.`)
+
+  document.body.focus();
+  testRunner.execCommand(eventName);
+  assert_equals(selectionHitCount, 1, `The carret is hidden in the <textarea> so the <textarea> should not receive an ${eventName}-event.`)
+  assert_equals(documentHitCount, 4, `The document should receive another ${eventName}-event.`)
+  assert_equals(lastTarget, document.body, `The document should be the ${eventName}-event's target.`)
+}
+
+test(() => testClipboardEvent('copy', textcontrol),  'Hidden carrets in textcontrols are not targeted by copy-events.');
+test(() => testClipboardEvent('paste', textcontrol), 'Hidden carrets in textcontrols are not targeted by paste-events.');
+test(() => testClipboardEvent('cut', textcontrol),   'Hidden carrets in textcontrols are not targeted by cut-events.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/OWNERS
index 59d0694..3aa8367 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/OWNERS
@@ -1,3 +1,4 @@
 # TEAM: layout-dev@chromium.org
 # COMPONENT: Blink>Layout>Flexbox
+# WPT-NOTIFY: true
 cbiesinger@chromium.org
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/OWNERS
index 51c6a57d..3aa8367 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/OWNERS
@@ -1 +1,4 @@
+# TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Flexbox
+# WPT-NOTIFY: true
 cbiesinger@chromium.org
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index cbe6380..cb0a70a 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -309,18 +309,19 @@
 // because we allow elements that are not normally selectable to implement
 // copy/paste (like divs, or a document body).
 
-bool Editor::CanDHTMLCut() {
-  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
+bool Editor::CanDHTMLCut(EditorCommandSource source) {
+  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
   return !IsInPasswordField(GetFrame()
                                 .Selection()
                                 .ComputeVisibleSelectionInDOMTree()
                                 .Start()) &&
-         !DispatchClipboardEvent(EventTypeNames::beforecut, kDataTransferNumb);
+         !DispatchClipboardEvent(EventTypeNames::beforecut, kDataTransferNumb,
+                                 source);
 }
 
-bool Editor::CanDHTMLCopy() {
+bool Editor::CanDHTMLCopy(EditorCommandSource source) {
   // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
@@ -328,7 +329,8 @@
                                 .Selection()
                                 .ComputeVisibleSelectionInDOMTree()
                                 .Start()) &&
-         !DispatchClipboardEvent(EventTypeNames::beforecopy, kDataTransferNumb);
+         !DispatchClipboardEvent(EventTypeNames::beforecopy, kDataTransferNumb,
+                                 source);
 }
 
 bool Editor::CanCut() const {
@@ -466,8 +468,10 @@
       ->Apply();
 }
 
-void Editor::PasteAsPlainText(const String& pasting_text, bool smart_replace) {
-  Element* target = FindEventTargetFromSelection();
+void Editor::PasteAsPlainText(const String& pasting_text,
+                              bool smart_replace,
+                              EditorCommandSource source) {
+  Element* target = FindEventTargetForClipboardEvent(source);
   if (!target)
     return;
   target->DispatchEvent(TextEvent::CreateForPlainTextPaste(
@@ -476,15 +480,16 @@
 
 void Editor::PasteAsFragment(DocumentFragment* pasting_fragment,
                              bool smart_replace,
-                             bool match_style) {
-  Element* target = FindEventTargetFromSelection();
+                             bool match_style,
+                             EditorCommandSource source) {
+  Element* target = FindEventTargetForClipboardEvent(source);
   if (!target)
     return;
   target->DispatchEvent(TextEvent::CreateForFragmentPaste(
       GetFrame().DomWindow(), pasting_fragment, smart_replace, match_style));
 }
 
-bool Editor::DispatchCopyEvent() {
+bool Editor::DispatchCopyEvent(EditorCommandSource source) {
   // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
@@ -492,10 +497,11 @@
           GetFrameSelection().ComputeVisibleSelectionInDOMTree().Start()))
     return true;
 
-  return DispatchClipboardEvent(EventTypeNames::copy, kDataTransferWritable);
+  return DispatchClipboardEvent(EventTypeNames::copy, kDataTransferWritable,
+                                source);
 }
 
-bool Editor::DispatchCutEvent() {
+bool Editor::DispatchCutEvent(EditorCommandSource source) {
   // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
@@ -503,20 +509,24 @@
           GetFrameSelection().ComputeVisibleSelectionInDOMTree().Start()))
     return true;
 
-  return DispatchClipboardEvent(EventTypeNames::cut, kDataTransferWritable);
+  return DispatchClipboardEvent(EventTypeNames::cut, kDataTransferWritable,
+                                source);
 }
 
-bool Editor::DispatchPasteEvent(PasteMode paste_mode) {
+bool Editor::DispatchPasteEvent(PasteMode paste_mode,
+                                EditorCommandSource source) {
   return DispatchClipboardEvent(EventTypeNames::paste, kDataTransferReadable,
-                                paste_mode);
+                                source, paste_mode);
 }
 
-void Editor::PasteAsPlainTextWithPasteboard(Pasteboard* pasteboard) {
+void Editor::PasteAsPlainTextWithPasteboard(Pasteboard* pasteboard,
+                                            EditorCommandSource source) {
   String text = pasteboard->PlainText();
-  PasteAsPlainText(text, CanSmartReplaceWithPasteboard(pasteboard));
+  PasteAsPlainText(text, CanSmartReplaceWithPasteboard(pasteboard), source);
 }
 
-void Editor::PasteWithPasteboard(Pasteboard* pasteboard) {
+void Editor::PasteWithPasteboard(Pasteboard* pasteboard,
+                                 EditorCommandSource source) {
   DocumentFragment* fragment = nullptr;
   bool chose_plain_text = false;
 
@@ -548,9 +558,10 @@
     }
   }
 
-  if (fragment)
+  if (fragment) {
     PasteAsFragment(fragment, CanSmartReplaceWithPasteboard(pasteboard),
-                    chose_plain_text);
+                    chose_plain_text, source);
+  }
 }
 
 void Editor::WriteSelectionToPasteboard() {
@@ -620,8 +631,9 @@
 
 bool Editor::DispatchClipboardEvent(const AtomicString& event_type,
                                     DataTransferAccessPolicy policy,
+                                    EditorCommandSource source,
                                     PasteMode paste_mode) {
-  Element* target = FindEventTargetFromSelection();
+  Element* target = FindEventTargetForClipboardEvent(source);
   if (!target)
     return true;
 
@@ -814,6 +826,18 @@
       GetFrameSelection().ComputeVisibleSelectionInDOMTreeDeprecated());
 }
 
+Element* Editor::FindEventTargetForClipboardEvent(
+    EditorCommandSource source) const {
+  // https://www.w3.org/TR/clipboard-apis/#fire-a-clipboard-event says:
+  //  "Set target to be the element that contains the start of the selection in
+  //   document order, or the body element if there is no selection or cursor."
+  // We treat hidden selections as "no selection or cursor".
+  if (source == kCommandFromMenuOrKeyBinding && GetFrameSelection().IsHidden())
+    return GetFrameSelection().GetDocument().body();
+
+  return FindEventTargetFromSelection();
+}
+
 void Editor::ApplyStyle(CSSPropertyValueSet* style,
                         InputEvent::InputType input_type) {
   const VisibleSelection& selection =
@@ -1124,7 +1148,7 @@
 }
 
 void Editor::Cut(EditorCommandSource source) {
-  if (!DispatchCutEvent())
+  if (!DispatchCutEvent(source))
     return;
   if (!CanCut())
     return;
@@ -1154,10 +1178,10 @@
     }
 
     if (source == kCommandFromMenuOrKeyBinding) {
-      if (DispatchBeforeInputDataTransfer(FindEventTargetFromSelection(),
-                                          InputEvent::InputType::kDeleteByCut,
-                                          nullptr) !=
-          DispatchEventResult::kNotCanceled)
+      if (DispatchBeforeInputDataTransfer(
+              FindEventTargetForClipboardEvent(source),
+              InputEvent::InputType::kDeleteByCut,
+              nullptr) != DispatchEventResult::kNotCanceled)
         return;
       // 'beforeinput' event handler may destroy target frame.
       if (frame_->GetDocument()->GetFrame() != frame_)
@@ -1169,8 +1193,8 @@
   }
 }
 
-void Editor::Copy(EditorCommandSource) {
-  if (!DispatchCopyEvent())
+void Editor::Copy(EditorCommandSource source) {
+  if (!DispatchCopyEvent(source))
     return;
   if (!CanCopy())
     return;
@@ -1200,7 +1224,7 @@
 
 void Editor::Paste(EditorCommandSource source) {
   DCHECK(GetFrame().GetDocument());
-  if (!DispatchPasteEvent(kAllMimeTypes))
+  if (!DispatchPasteEvent(kAllMimeTypes, source))
     return;
   if (!CanPaste())
     return;
@@ -1225,10 +1249,10 @@
         DataTransfer::Create(DataTransfer::kCopyAndPaste, kDataTransferReadable,
                              DataObject::CreateFromPasteboard(paste_mode));
 
-    if (DispatchBeforeInputDataTransfer(FindEventTargetFromSelection(),
-                                        InputEvent::InputType::kInsertFromPaste,
-                                        data_transfer) !=
-        DispatchEventResult::kNotCanceled)
+    if (DispatchBeforeInputDataTransfer(
+            FindEventTargetForClipboardEvent(source),
+            InputEvent::InputType::kInsertFromPaste,
+            data_transfer) != DispatchEventResult::kNotCanceled)
       return;
     // 'beforeinput' event handler may destroy target frame.
     if (frame_->GetDocument()->GetFrame() != frame_)
@@ -1236,13 +1260,13 @@
   }
 
   if (paste_mode == kAllMimeTypes)
-    PasteWithPasteboard(Pasteboard::GeneralPasteboard());
+    PasteWithPasteboard(Pasteboard::GeneralPasteboard(), source);
   else
-    PasteAsPlainTextWithPasteboard(Pasteboard::GeneralPasteboard());
+    PasteAsPlainTextWithPasteboard(Pasteboard::GeneralPasteboard(), source);
 }
 
 void Editor::PasteAsPlainText(EditorCommandSource source) {
-  if (!DispatchPasteEvent(kPlainTextOnly))
+  if (!DispatchPasteEvent(kPlainTextOnly, source))
     return;
   if (!CanPaste())
     return;
@@ -1257,7 +1281,7 @@
       !GetFrameSelection().SelectionHasFocus())
     return;
 
-  PasteAsPlainTextWithPasteboard(Pasteboard::GeneralPasteboard());
+  PasteAsPlainTextWithPasteboard(Pasteboard::GeneralPasteboard(), source);
 }
 
 void Editor::PerformDelete() {
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h
index 542b71b..0d0324b2 100644
--- a/third_party/WebKit/Source/core/editing/Editor.h
+++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -87,8 +87,8 @@
   bool CanEdit() const;
   bool CanEditRichly() const;
 
-  bool CanDHTMLCut();
-  bool CanDHTMLCopy();
+  bool CanDHTMLCut(EditorCommandSource);
+  bool CanDHTMLCopy(EditorCommandSource);
 
   bool CanCut() const;
   bool CanCopy() const;
@@ -227,11 +227,15 @@
 
   void AddToKillRing(const EphemeralRange&);
 
-  void PasteAsFragment(DocumentFragment*, bool smart_replace, bool match_style);
-  void PasteAsPlainText(const String&, bool smart_replace);
+  void PasteAsFragment(DocumentFragment*,
+                       bool smart_replace,
+                       bool match_style,
+                       EditorCommandSource);
+  void PasteAsPlainText(const String&, bool smart_replace, EditorCommandSource);
 
   Element* FindEventTargetFrom(const VisibleSelection&) const;
   Element* FindEventTargetFromSelection() const;
+  Element* FindEventTargetForClipboardEvent(EditorCommandSource) const;
 
   bool FindString(const String&, FindOptions);
 
@@ -340,16 +344,17 @@
   bool CanDeleteRange(const EphemeralRange&) const;
 
   // Returns true if Editor should continue with default processing.
-  bool DispatchCopyEvent();
-  bool DispatchCutEvent();
-  bool DispatchPasteEvent(PasteMode);
+  bool DispatchCopyEvent(EditorCommandSource);
+  bool DispatchCutEvent(EditorCommandSource);
+  bool DispatchPasteEvent(PasteMode, EditorCommandSource);
   bool DispatchClipboardEvent(const AtomicString&,
                               DataTransferAccessPolicy,
+                              EditorCommandSource,
                               PasteMode = kAllMimeTypes);
 
   bool CanSmartReplaceWithPasteboard(Pasteboard*);
-  void PasteAsPlainTextWithPasteboard(Pasteboard*);
-  void PasteWithPasteboard(Pasteboard*);
+  void PasteAsPlainTextWithPasteboard(Pasteboard*, EditorCommandSource);
+  void PasteWithPasteboard(Pasteboard*, EditorCommandSource);
   void WriteSelectionToPasteboard();
 
   void RevealSelectionAfterEditingOperation(
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index 8292ea8..73a3c6f 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -2138,7 +2138,7 @@
 static bool EnabledCopy(LocalFrame& frame, Event*, EditorCommandSource source) {
   if (!CanWriteClipboard(frame, source))
     return false;
-  return frame.GetEditor().CanDHTMLCopy() || frame.GetEditor().CanCopy();
+  return frame.GetEditor().CanDHTMLCopy(source) || frame.GetEditor().CanCopy();
 }
 
 static bool EnabledCut(LocalFrame& frame, Event*, EditorCommandSource source) {
@@ -2147,7 +2147,7 @@
   if (source == kCommandFromMenuOrKeyBinding &&
       !frame.Selection().SelectionHasFocus())
     return false;
-  return frame.GetEditor().CanDHTMLCut() || frame.GetEditor().CanCut();
+  return frame.GetEditor().CanDHTMLCut(source) || frame.GetEditor().CanCut();
 }
 
 static bool EnabledInEditableText(LocalFrame& frame,
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp
index 1532b0a..7b498d2 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp
@@ -63,6 +63,7 @@
 #define HTML_BEGIN_STATE(stateName) BEGIN_STATE(HTMLTokenizer, stateName)
 #define HTML_RECONSUME_IN(stateName) RECONSUME_IN(HTMLTokenizer, stateName)
 #define HTML_ADVANCE_TO(stateName) ADVANCE_TO(HTMLTokenizer, stateName)
+#define HTML_CONSUME(stateName) CONSUME(HTMLTokenizer, stateName)
 #define HTML_SWITCH_TO(stateName) SWITCH_TO(HTMLTokenizer, stateName)
 
 HTMLTokenizer::HTMLTokenizer(const HTMLParserOptions& options)
@@ -168,7 +169,7 @@
         return EmitEndOfFile(source);
       else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kDataState);
+        HTML_CONSUME(kDataState);
       }
     }
     END_STATE()
@@ -189,7 +190,7 @@
         return EmitEndOfFile(source);
       else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kRCDATAState);
+        HTML_CONSUME(kRCDATAState);
       }
     }
     END_STATE()
@@ -208,7 +209,7 @@
         return EmitEndOfFile(source);
       else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kRAWTEXTState);
+        HTML_CONSUME(kRAWTEXTState);
       }
     }
     END_STATE()
@@ -220,7 +221,7 @@
         return EmitEndOfFile(source);
       else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kScriptDataState);
+        HTML_CONSUME(kScriptDataState);
       }
     }
     END_STATE()
@@ -229,7 +230,7 @@
       if (cc == kEndOfFileMarker)
         return EmitEndOfFile(source);
       BufferCharacter(cc);
-      HTML_ADVANCE_TO(kPLAINTEXTState);
+      HTML_CONSUME(kPLAINTEXTState);
     }
     END_STATE()
 
@@ -287,7 +288,7 @@
         HTML_RECONSUME_IN(kDataState);
       } else {
         token_->AppendToName(ToLowerCaseIfAlpha(cc));
-        HTML_ADVANCE_TO(kTagNameState);
+        HTML_CONSUME(kTagNameState);
       }
     }
     END_STATE()
@@ -321,7 +322,7 @@
       if (IsASCIIAlpha(cc)) {
         temporary_buffer_.push_back(static_cast<LChar>(cc));
         AddToPossibleEndTag(static_cast<LChar>(ToLowerCase(cc)));
-        HTML_ADVANCE_TO(kRCDATAEndTagNameState);
+        HTML_CONSUME(kRCDATAEndTagNameState);
       } else {
         if (IsTokenizerWhitespace(cc)) {
           if (IsAppropriateEndTag()) {
@@ -378,7 +379,7 @@
       if (IsASCIIAlpha(cc)) {
         temporary_buffer_.push_back(static_cast<LChar>(cc));
         AddToPossibleEndTag(static_cast<LChar>(ToLowerCase(cc)));
-        HTML_ADVANCE_TO(kRAWTEXTEndTagNameState);
+        HTML_CONSUME(kRAWTEXTEndTagNameState);
       } else {
         if (IsTokenizerWhitespace(cc)) {
           if (IsAppropriateEndTag()) {
@@ -439,7 +440,7 @@
       if (IsASCIIAlpha(cc)) {
         temporary_buffer_.push_back(static_cast<LChar>(cc));
         AddToPossibleEndTag(static_cast<LChar>(ToLowerCase(cc)));
-        HTML_ADVANCE_TO(kScriptDataEndTagNameState);
+        HTML_CONSUME(kScriptDataEndTagNameState);
       } else {
         if (IsTokenizerWhitespace(cc)) {
           if (IsAppropriateEndTag()) {
@@ -496,7 +497,7 @@
         HTML_RECONSUME_IN(kDataState);
       } else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kScriptDataEscapedState);
+        HTML_CONSUME(kScriptDataEscapedState);
       }
     }
     END_STATE()
@@ -520,7 +521,7 @@
     HTML_BEGIN_STATE(kScriptDataEscapedDashDashState) {
       if (cc == '-') {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kScriptDataEscapedDashDashState);
+        HTML_CONSUME(kScriptDataEscapedDashDashState);
       } else if (cc == '<')
         HTML_ADVANCE_TO(kScriptDataEscapedLessThanSignState);
       else if (cc == '>') {
@@ -571,7 +572,7 @@
       if (IsASCIIAlpha(cc)) {
         temporary_buffer_.push_back(static_cast<LChar>(cc));
         AddToPossibleEndTag(static_cast<LChar>(ToLowerCase(cc)));
-        HTML_ADVANCE_TO(kScriptDataEscapedEndTagNameState);
+        HTML_CONSUME(kScriptDataEscapedEndTagNameState);
       } else {
         if (IsTokenizerWhitespace(cc)) {
           if (IsAppropriateEndTag()) {
@@ -609,7 +610,7 @@
       } else if (IsASCIIAlpha(cc)) {
         BufferCharacter(cc);
         temporary_buffer_.push_back(static_cast<LChar>(ToLowerCase(cc)));
-        HTML_ADVANCE_TO(kScriptDataDoubleEscapeStartState);
+        HTML_CONSUME(kScriptDataDoubleEscapeStartState);
       } else
         HTML_RECONSUME_IN(kScriptDataEscapedState);
     }
@@ -627,7 +628,7 @@
         HTML_RECONSUME_IN(kDataState);
       } else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kScriptDataDoubleEscapedState);
+        HTML_CONSUME(kScriptDataDoubleEscapedState);
       }
     }
     END_STATE()
@@ -652,7 +653,7 @@
     HTML_BEGIN_STATE(kScriptDataDoubleEscapedDashDashState) {
       if (cc == '-') {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kScriptDataDoubleEscapedDashDashState);
+        HTML_CONSUME(kScriptDataDoubleEscapedDashDashState);
       } else if (cc == '<') {
         BufferCharacter(cc);
         HTML_ADVANCE_TO(kScriptDataDoubleEscapedLessThanSignState);
@@ -689,7 +690,7 @@
       } else if (IsASCIIAlpha(cc)) {
         BufferCharacter(cc);
         temporary_buffer_.push_back(static_cast<LChar>(ToLowerCase(cc)));
-        HTML_ADVANCE_TO(kScriptDataDoubleEscapeEndState);
+        HTML_CONSUME(kScriptDataDoubleEscapeEndState);
       } else
         HTML_RECONSUME_IN(kScriptDataDoubleEscapedState);
     }
@@ -697,7 +698,7 @@
 
     HTML_BEGIN_STATE(kBeforeAttributeNameState) {
       if (IsTokenizerWhitespace(cc)) {
-        HTML_ADVANCE_TO(kBeforeAttributeNameState);
+        HTML_CONSUME(kBeforeAttributeNameState);
       } else if (cc == '/') {
         HTML_ADVANCE_TO(kSelfClosingStartTagState);
       } else if (cc == '>') {
@@ -737,14 +738,14 @@
         if (cc == '"' || cc == '\'' || cc == '<' || cc == '=')
           ParseError();
         token_->AppendToAttributeName(ToLowerCaseIfAlpha(cc));
-        HTML_ADVANCE_TO(kAttributeNameState);
+        HTML_CONSUME(kAttributeNameState);
       }
     }
     END_STATE()
 
     HTML_BEGIN_STATE(kAfterAttributeNameState) {
       if (IsTokenizerWhitespace(cc)) {
-        HTML_ADVANCE_TO(kAfterAttributeNameState);
+        HTML_CONSUME(kAfterAttributeNameState);
       } else if (cc == '/') {
         HTML_ADVANCE_TO(kSelfClosingStartTagState);
       } else if (cc == '=') {
@@ -767,7 +768,7 @@
 
     HTML_BEGIN_STATE(kBeforeAttributeValueState) {
       if (IsTokenizerWhitespace(cc))
-        HTML_ADVANCE_TO(kBeforeAttributeValueState);
+        HTML_CONSUME(kBeforeAttributeValueState);
       else if (cc == '"') {
         token_->BeginAttributeValue(source.NumberOfCharactersConsumed() + 1);
         HTML_ADVANCE_TO(kAttributeValueDoubleQuotedState);
@@ -806,7 +807,7 @@
         HTML_RECONSUME_IN(kDataState);
       } else {
         token_->AppendToAttributeValue(cc);
-        HTML_ADVANCE_TO(kAttributeValueDoubleQuotedState);
+        HTML_CONSUME(kAttributeValueDoubleQuotedState);
       }
     }
     END_STATE()
@@ -824,7 +825,7 @@
         HTML_RECONSUME_IN(kDataState);
       } else {
         token_->AppendToAttributeValue(cc);
-        HTML_ADVANCE_TO(kAttributeValueSingleQuotedState);
+        HTML_CONSUME(kAttributeValueSingleQuotedState);
       }
     }
     END_STATE()
@@ -847,7 +848,7 @@
         if (cc == '"' || cc == '\'' || cc == '<' || cc == '=' || cc == '`')
           ParseError();
         token_->AppendToAttributeValue(cc);
-        HTML_ADVANCE_TO(kAttributeValueUnquotedState);
+        HTML_CONSUME(kAttributeValueUnquotedState);
       }
     }
     END_STATE()
@@ -926,7 +927,7 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       else {
         token_->AppendToComment(cc);
-        HTML_ADVANCE_TO(kContinueBogusCommentState);
+        HTML_CONSUME(kContinueBogusCommentState);
       }
     }
     END_STATE()
@@ -1005,7 +1006,7 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       } else {
         token_->AppendToComment(cc);
-        HTML_ADVANCE_TO(kCommentState);
+        HTML_CONSUME(kCommentState);
       }
     }
     END_STATE()
@@ -1033,7 +1034,7 @@
       } else if (cc == '-') {
         ParseError();
         token_->AppendToComment('-');
-        HTML_ADVANCE_TO(kCommentEndState);
+        HTML_CONSUME(kCommentEndState);
       } else if (cc == kEndOfFileMarker) {
         ParseError();
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
@@ -1085,7 +1086,7 @@
 
     HTML_BEGIN_STATE(kBeforeDOCTYPENameState) {
       if (IsTokenizerWhitespace(cc)) {
-        HTML_ADVANCE_TO(kBeforeDOCTYPENameState);
+        HTML_CONSUME(kBeforeDOCTYPENameState);
       } else if (cc == '>') {
         ParseError();
         token_->BeginDOCTYPE();
@@ -1114,14 +1115,14 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       } else {
         token_->AppendToName(ToLowerCaseIfAlpha(cc));
-        HTML_ADVANCE_TO(kDOCTYPENameState);
+        HTML_CONSUME(kDOCTYPENameState);
       }
     }
     END_STATE()
 
     HTML_BEGIN_STATE(kAfterDOCTYPENameState) {
       if (IsTokenizerWhitespace(cc))
-        HTML_ADVANCE_TO(kAfterDOCTYPENameState);
+        HTML_CONSUME(kAfterDOCTYPENameState);
       if (cc == '>')
         return EmitAndResumeIn(source, HTMLTokenizer::kDataState);
       else if (cc == kEndOfFileMarker) {
@@ -1182,7 +1183,7 @@
 
     HTML_BEGIN_STATE(kBeforeDOCTYPEPublicIdentifierState) {
       if (IsTokenizerWhitespace(cc))
-        HTML_ADVANCE_TO(kBeforeDOCTYPEPublicIdentifierState);
+        HTML_CONSUME(kBeforeDOCTYPEPublicIdentifierState);
       else if (cc == '"') {
         token_->SetPublicIdentifierToEmptyString();
         HTML_ADVANCE_TO(kDOCTYPEPublicIdentifierDoubleQuotedState);
@@ -1218,7 +1219,7 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       } else {
         token_->AppendToPublicIdentifier(cc);
-        HTML_ADVANCE_TO(kDOCTYPEPublicIdentifierDoubleQuotedState);
+        HTML_CONSUME(kDOCTYPEPublicIdentifierDoubleQuotedState);
       }
     }
     END_STATE()
@@ -1236,7 +1237,7 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       } else {
         token_->AppendToPublicIdentifier(cc);
-        HTML_ADVANCE_TO(kDOCTYPEPublicIdentifierSingleQuotedState);
+        HTML_CONSUME(kDOCTYPEPublicIdentifierSingleQuotedState);
       }
     }
     END_STATE()
@@ -1268,7 +1269,7 @@
 
     HTML_BEGIN_STATE(kBetweenDOCTYPEPublicAndSystemIdentifiersState) {
       if (IsTokenizerWhitespace(cc))
-        HTML_ADVANCE_TO(kBetweenDOCTYPEPublicAndSystemIdentifiersState);
+        HTML_CONSUME(kBetweenDOCTYPEPublicAndSystemIdentifiersState);
       else if (cc == '>')
         return EmitAndResumeIn(source, HTMLTokenizer::kDataState);
       else if (cc == '"') {
@@ -1318,7 +1319,7 @@
 
     HTML_BEGIN_STATE(kBeforeDOCTYPESystemIdentifierState) {
       if (IsTokenizerWhitespace(cc))
-        HTML_ADVANCE_TO(kBeforeDOCTYPESystemIdentifierState);
+        HTML_CONSUME(kBeforeDOCTYPESystemIdentifierState);
       if (cc == '"') {
         token_->SetSystemIdentifierToEmptyString();
         HTML_ADVANCE_TO(kDOCTYPESystemIdentifierDoubleQuotedState);
@@ -1354,7 +1355,7 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       } else {
         token_->AppendToSystemIdentifier(cc);
-        HTML_ADVANCE_TO(kDOCTYPESystemIdentifierDoubleQuotedState);
+        HTML_CONSUME(kDOCTYPESystemIdentifierDoubleQuotedState);
       }
     }
     END_STATE()
@@ -1372,14 +1373,14 @@
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
       } else {
         token_->AppendToSystemIdentifier(cc);
-        HTML_ADVANCE_TO(kDOCTYPESystemIdentifierSingleQuotedState);
+        HTML_CONSUME(kDOCTYPESystemIdentifierSingleQuotedState);
       }
     }
     END_STATE()
 
     HTML_BEGIN_STATE(kAfterDOCTYPESystemIdentifierState) {
       if (IsTokenizerWhitespace(cc))
-        HTML_ADVANCE_TO(kAfterDOCTYPESystemIdentifierState);
+        HTML_CONSUME(kAfterDOCTYPESystemIdentifierState);
       else if (cc == '>')
         return EmitAndResumeIn(source, HTMLTokenizer::kDataState);
       else if (cc == kEndOfFileMarker) {
@@ -1398,7 +1399,7 @@
         return EmitAndResumeIn(source, HTMLTokenizer::kDataState);
       else if (cc == kEndOfFileMarker)
         return EmitAndReconsumeIn(source, HTMLTokenizer::kDataState);
-      HTML_ADVANCE_TO(kBogusDOCTYPEState);
+      HTML_CONSUME(kBogusDOCTYPEState);
     }
     END_STATE()
 
@@ -1409,7 +1410,7 @@
         HTML_RECONSUME_IN(kDataState);
       else {
         BufferCharacter(cc);
-        HTML_ADVANCE_TO(kCDATASectionState);
+        HTML_CONSUME(kCDATASectionState);
       }
     }
     END_STATE()
@@ -1426,7 +1427,7 @@
     HTML_BEGIN_STATE(kCDATASectionEndState) {
       if (cc == ']') {
         BufferCharacter(']');
-        HTML_ADVANCE_TO(kCDATASectionEndState);
+        HTML_CONSUME(kCDATASectionEndState);
       } else if (cc == '>') {
         HTML_ADVANCE_TO(kDataState);
       } else {
diff --git a/third_party/WebKit/Source/core/html/parser/MarkupTokenizerInlines.h b/third_party/WebKit/Source/core/html/parser/MarkupTokenizerInlines.h
index 78f93779..1ae699c3 100644
--- a/third_party/WebKit/Source/core/html/parser/MarkupTokenizerInlines.h
+++ b/third_party/WebKit/Source/core/html/parser/MarkupTokenizerInlines.h
@@ -65,16 +65,18 @@
 
 // We use this macro when the HTML5 spec says "reconsume the current input
 // character in the <mumble> state."
-#define RECONSUME_IN(prefix, stateName) \
-  do {                                  \
-    state_ = prefix::stateName;         \
-    goto stateName;                     \
+#define RECONSUME_IN(prefix, stateName)   \
+  do {                                    \
+    DCHECK_NE(state_, prefix::stateName); \
+    state_ = prefix::stateName;           \
+    goto stateName;                       \
   } while (false)
 
 // We use this macro when the HTML5 spec says "consume the next input
 // character ... and switch to the <mumble> state."
 #define ADVANCE_TO(prefix, stateName)                     \
   do {                                                    \
+    DCHECK_NE(state_, prefix::stateName);                 \
     state_ = prefix::stateName;                           \
     if (!input_stream_preprocessor_.Advance(source))      \
       return HaveBufferedCharacterToken();                \
@@ -82,12 +84,24 @@
     goto stateName;                                       \
   } while (false)
 
+// We use this macro when the HTML5 spec says "consume the next input
+// character" and it doesn't say "switch to ... state".
+#define CONSUME(prefix, stateName)                        \
+  do {                                                    \
+    DCHECK_EQ(state_, prefix::stateName);                 \
+    if (!input_stream_preprocessor_.Advance(source))      \
+      return HaveBufferedCharacterToken();                \
+    cc = input_stream_preprocessor_.NextInputCharacter(); \
+    goto stateName;                                       \
+  } while (false)
+
 // Sometimes there's more complicated logic in the spec that separates when
 // we consume the next input character and when we switch to a particular
 // state. We handle those cases by advancing the source directly and using
 // this macro to switch to the indicated state.
 #define SWITCH_TO(prefix, stateName)                                  \
   do {                                                                \
+    DCHECK_NE(state_, prefix::stateName);                             \
     state_ = prefix::stateName;                                       \
     if (source.IsEmpty() || !input_stream_preprocessor_.Peek(source)) \
       return HaveBufferedCharacterToken();                            \
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py
index 4ac5fca..bd5c394c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier.py
@@ -205,16 +205,18 @@
 
         Args:
             imported_commits: A list of (SHA, commit subject) pairs.
-            directory: The directory for which the list is formatted (a path
-                relative to the root of Chromium repo).
+            directory: An absolute path of a directory in the Chromium repo, for
+                which the list is formatted.
 
         Returns:
             A multi-line string.
         """
+        path_from_wpt = self.host.filesystem.relpath(
+            directory, self.finder.path_from_layout_tests('external', 'wpt'))
         commit_list = ''
         for sha, subject in imported_commits:
             line = '{}: {}'.format(subject, GITHUB_COMMIT_PREFIX + sha)
-            if self.local_wpt.is_commit_affecting_directory(sha, directory):
+            if self.local_wpt.is_commit_affecting_directory(sha, path_from_wpt):
                 line += ' [affecting this directory]'
             commit_list += line + '\n'
         return commit_list
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py
index 8d1f220..5c2c8da 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/import_notifier_unittest.py
@@ -134,12 +134,12 @@
 
         def _is_commit_affecting_directory(commit, directory):
             self.assertIn(commit, ('SHA1', 'SHA2'))
-            self.assertEqual(directory, 'directory')
+            self.assertEqual(directory, 'foo')
             return commit == 'SHA1'
 
         self.local_wpt.is_commit_affecting_directory = _is_commit_affecting_directory
         self.assertEqual(
-            self.notifier.format_commit_list(imported_commits, 'directory'),
+            self.notifier.format_commit_list(imported_commits, '/mock-checkout/third_party/WebKit/LayoutTests/external/wpt/foo'),
             'Subject 1: https://github.com/w3c/web-platform-tests/commit/SHA1 [affecting this directory]\n'
             'Subject 2: https://github.com/w3c/web-platform-tests/commit/SHA2\n'
         )
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 5d8865b8..9819614 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -347,12 +347,6 @@
 crbug.com/788976 [ Cherry_Mobile_Android_One ] wasm/WasmSpaceBuggy [ Skip ]
 crbug.com/788976 [ Android_Webview ] wasm/WasmSpaceBuggy [ Skip ]
 
-# Benchmark: webrtc
-crbug.com/468732 [ All ] webrtc/audio_call_opus_10s [ Skip ]
-crbug.com/468732 [ All ] webrtc/audio_call_g772_10s [ Skip ]
-crbug.com/468732 [ All ] webrtc/audio_call_isac/1600_10s [ Skip ]
-crbug.com/468732 [ All ] webrtc/audio_call_pcmu_10s [ Skip ]
-
 ##### Perf FYI benchmarks go after here #####
 # Benchmark: loading.desktop.network_service
 crbug.com/723783 [ Win ] loading.desktop.network_service/Orange [ Skip ]
diff --git a/tools/perf/page_sets/webrtc_cases.py b/tools/perf/page_sets/webrtc_cases.py
index e462cb8..3ff08d1 100644
--- a/tools/perf/page_sets/webrtc_cases.py
+++ b/tools/perf/page_sets/webrtc_cases.py
@@ -142,10 +142,6 @@
     self.AddStory(DataChannel(self, tags=['datachannel']))
     self.AddStory(GetUserMedia(self, tags=['getusermedia']))
     self.AddStory(CanvasCapturePeerConnection(self, tags=['smoothness']))
-    self.AddStory(AudioCall(self, 'OPUS', tags=['audio']))
-    self.AddStory(AudioCall(self, 'G772', tags=['audio']))
-    self.AddStory(AudioCall(self, 'PCMU', tags=['audio']))
-    self.AddStory(AudioCall(self, 'ISAC/1600', tags=['audio']))
     self.AddStory(VideoCodecConstraints(self, 'H264', tags=['videoConstraints']))
     self.AddStory(VideoCodecConstraints(self, 'VP8', tags=['videoConstraints']))
     self.AddStory(VideoCodecConstraints(self, 'VP9', tags=['videoConstraints']))
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc
index 74c8902..8061e693 100644
--- a/ui/message_center/views/message_popup_collection.cc
+++ b/ui/message_center/views/message_popup_collection.cc
@@ -127,6 +127,26 @@
       alignment_delegate_->IsPrimaryDisplayForNotification();
 #endif
 
+  // Check if the popups contain a new notification.
+  bool has_new_toasts = false;
+  for (auto* popup : popups) {
+    if (!FindToast(popup->id())) {
+      has_new_toasts = true;
+      break;
+    }
+  }
+
+  // If a new notification is found, collapse all existing notifications
+  // beforehand.
+  if (has_new_toasts) {
+    for (auto* toast : toasts_) {
+      if (toast->message_view()->IsMouseHovered() ||
+          toast->message_view()->manually_expanded_or_collapsed())
+        continue;
+      toast->message_view()->SetExpanded(false);
+    }
+  }
+
   // Iterate in the reverse order to keep the oldest toasts on screen. Newer
   // items may be ignored if there are no room to place them.
   for (NotificationList::PopupNotifications::const_reverse_iterator iter =
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h
index 48d4d5a3..f899d64d 100644
--- a/ui/message_center/views/message_view.h
+++ b/ui/message_center/views/message_view.h
@@ -99,6 +99,10 @@
   void set_force_disable_pinned() { force_disable_pinned_ = true; }
 #endif
 
+  bool manually_expanded_or_collapsed() const {
+    return manually_expanded_or_collapsed_;
+  }
+
  protected:
   // Creates and add close button to view hierarchy when necessary. Derived
   // classes should call this after its view hierarchy is populated to ensure
@@ -112,6 +116,10 @@
   views::View* background_view() { return background_view_; }
   views::ScrollView* scroller() { return scroller_; }
 
+  void set_manually_expanded_or_collapsed() {
+    manually_expanded_or_collapsed_ = true;
+  }
+
  private:
   std::string notification_id_;
   views::View* background_view_ = nullptr;  // Owned by views hierarchy.
@@ -125,6 +133,10 @@
   // pinned regardless of the value of |pinned_|.
   bool force_disable_pinned_ = false;
 
+  // True if the notification is expanded/collapsed by user interaction.
+  // If true, MessagePopupCollection will not auto-collapse the notification.
+  bool manually_expanded_or_collapsed_ = false;
+
   std::unique_ptr<views::Painter> focus_painter_;
 
   views::SlideOutController slide_out_controller_;
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc
index a5bb0478..149080c 100644
--- a/ui/message_center/views/notification_view_md.cc
+++ b/ui/message_center/views/notification_view_md.cc
@@ -655,6 +655,7 @@
   // |expand_button| can be focused by TAB.
   if (sender == header_row_) {
     if (IsExpandable()) {
+      set_manually_expanded_or_collapsed();
       ToggleExpanded();
       Layout();
       SchedulePaint();
diff --git a/ui/message_center/views/notification_view_md_unittest.cc b/ui/message_center/views/notification_view_md_unittest.cc
index b1e4f05..97257d4 100644
--- a/ui/message_center/views/notification_view_md_unittest.cc
+++ b/ui/message_center/views/notification_view_md_unittest.cc
@@ -637,6 +637,20 @@
   EXPECT_EQ(collapsed_height, notification_view()->message_view_->height());
   EXPECT_EQ(collapsed_preferred_height,
             notification_view()->GetPreferredSize().height());
+
+  // Test |manually_expanded_or_collapsed| being set when the toggle is done by
+  // user interaction.
+  EXPECT_FALSE(notification_view()->manually_expanded_or_collapsed());
+
+  // Construct a mouse click event 1 pixel inside the header.
+  gfx::Point done_cursor_location(1, 1);
+  views::View::ConvertPointToScreen(notification_view()->header_row_,
+                                    &done_cursor_location);
+  ui::test::EventGenerator generator(widget()->GetNativeWindow());
+  generator.MoveMouseTo(done_cursor_location);
+  generator.ClickLeftButton();
+
+  EXPECT_TRUE(notification_view()->manually_expanded_or_collapsed());
 }
 
 TEST_F(NotificationViewMDTest, TestAccentColor) {
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc
index 1517157..ab73e0a1 100644
--- a/ui/message_center/views/toast_contents_view.cc
+++ b/ui/message_center/views/toast_contents_view.cc
@@ -83,6 +83,7 @@
 
 void ToastContentsView::SetContents(MessageView* view,
                                     bool a11y_feedback_for_updates) {
+  message_view_ = view;
   bool already_has_contents = child_count() > 0;
   RemoveAllChildViews(true);
   AddChildView(view);
diff --git a/ui/message_center/views/toast_contents_view.h b/ui/message_center/views/toast_contents_view.h
index 8322754..87c0aa9b 100644
--- a/ui/message_center/views/toast_contents_view.h
+++ b/ui/message_center/views/toast_contents_view.h
@@ -80,6 +80,8 @@
 
   const std::string& id() const { return id_; }
 
+  MessageView* message_view() { return message_view_; }
+
   // Overridden from views::View:
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
@@ -141,6 +143,9 @@
   gfx::Point origin_;
   gfx::Size preferred_size_;
 
+  // Weak reference to the MessageView.
+  MessageView* message_view_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(ToastContentsView);
 };