diff --git a/DEPS b/DEPS
index a9060d8..fd67a9a 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': '7fa5c31c2c9af834bee66d5fcf476e250076c8d6',
+  'skia_revision': 'df07ddd1f05bf8905b9edd41d309badc8f3a131b',
   # 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': '207d5c39e9c289fc91d8344f32f6b0820001f557',
+  'v8_revision': '888f7dad7620bffd7929f257272a424a652ee5eb',
   # 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/base/BUILD.gn b/base/BUILD.gn
index 78953be..7714190 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -741,6 +741,7 @@
     "strings/string_number_conversions.h",
     "strings/string_piece.cc",
     "strings/string_piece.h",
+    "strings/string_piece_forward.h",
     "strings/string_split.cc",
     "strings/string_split.h",
     "strings/string_tokenizer.h",
diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc
index 36736cd..41adbf8 100644
--- a/base/allocator/allocator_shim.cc
+++ b/base/allocator/allocator_shim.cc
@@ -58,9 +58,12 @@
 #if defined(OS_WIN)
   return base::allocator::WinCallNewHandler(size);
 #else
-  // TODO(primiano): C++11 has introduced ::get_new_handler() which is supposed
-  // to be thread safe and would avoid the spinlock boilerplate here. However
-  // it doesn't seem to be available yet in the Linux chroot headers yet.
+  // TODO(primiano): C++11 has introduced std::get_new_handler() which is
+  // supposed to be thread safe and would avoid the spinlock boilerplate here.
+  // However, it is not available in the headers in the current Debian Jessie
+  // sysroot, which has libstdc++ 4.8. The function is available in libstdc++
+  // 4.9 and newer, but it will be a few more years before a newer sysroot
+  // becomes available.
   std::new_handler nh;
   {
     while (subtle::Acquire_CompareAndSwap(&g_new_handler_lock, 0, 1))
diff --git a/base/logging.cc b/base/logging.cc
index cea6edae..cce9c72 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -7,12 +7,12 @@
 #include <limits.h>
 #include <stdint.h>
 
-#include "base/debug/activity_tracker.h"
 #include "base/macros.h"
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
 #include <io.h>
+#include <windows.h>
 typedef HANDLE FileHandle;
 typedef HANDLE MutexHandle;
 // Windows warns on using write().  It prefers _write().
@@ -51,13 +51,18 @@
 #include <ctime>
 #include <iomanip>
 #include <ostream>
+#include <stack>
 #include <string>
+#include <utility>
 
 #include "base/base_switches.h"
+#include "base/callback.h"
 #include "base/command_line.h"
+#include "base/debug/activity_tracker.h"
 #include "base/debug/alias.h"
 #include "base/debug/debugger.h"
 #include "base/debug/stack_trace.h"
+#include "base/lazy_instance.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -121,8 +126,11 @@
 bool show_error_dialogs = false;
 
 // An assert handler override specified by the client to be called instead of
-// the debug message dialog and process termination.
-LogAssertHandlerFunction log_assert_handler = nullptr;
+// the debug message dialog and process termination. Assert handlers are stored
+// in stack to allow overriding and restoring.
+base::LazyInstance<std::stack<LogAssertHandlerFunction>>::Leaky
+    log_assert_handler_stack = LAZY_INSTANCE_INITIALIZER;
+
 // A log message handler that gets notified of every log message we process.
 LogMessageHandlerFunction log_message_handler = nullptr;
 
@@ -444,8 +452,13 @@
   show_error_dialogs = enable_dialogs;
 }
 
-void SetLogAssertHandler(LogAssertHandlerFunction handler) {
-  log_assert_handler = handler;
+ScopedLogAssertHandler::ScopedLogAssertHandler(
+    LogAssertHandlerFunction handler) {
+  log_assert_handler_stack.Get().push(std::move(handler));
+}
+
+ScopedLogAssertHandler::~ScopedLogAssertHandler() {
+  log_assert_handler_stack.Get().pop();
 }
 
 void SetLogMessageHandler(LogMessageHandlerFunction handler) {
@@ -531,6 +544,7 @@
 }
 
 LogMessage::~LogMessage() {
+  size_t stack_start = stream_.tellp();
 #if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && !defined(__UCLIBC__)
   if (severity_ == LOG_FATAL && !base::debug::BeingDebugged()) {
     // Include a stack trace on a fatal, unless a debugger is attached.
@@ -739,9 +753,18 @@
     str_newline.copy(str_stack, arraysize(str_stack));
     base::debug::Alias(str_stack);
 
-    if (log_assert_handler) {
-      // Make a copy of the string for the handler out of paranoia.
-      log_assert_handler(std::string(stream_.str()));
+    if (!(log_assert_handler_stack == nullptr) &&
+        !log_assert_handler_stack.Get().empty()) {
+      LogAssertHandlerFunction log_assert_handler =
+          log_assert_handler_stack.Get().top();
+
+      if (log_assert_handler) {
+        log_assert_handler.Run(
+            file_, line_,
+            base::StringPiece(str_newline.c_str() + message_start_,
+                              stack_start - message_start_),
+            base::StringPiece(str_newline.c_str() + stack_start));
+      }
     } else {
       // Don't use the string with the newline, get a fresh version to send to
       // the debug message process. We also don't display assertions to the
diff --git a/base/logging.h b/base/logging.h
index 1dcb0f71..bf41527 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -15,9 +15,11 @@
 #include <utility>
 
 #include "base/base_export.h"
+#include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/debug/debugger.h"
 #include "base/macros.h"
+#include "base/strings/string_piece_forward.h"
 #include "base/template_util.h"
 #include "build/build_config.h"
 
@@ -274,11 +276,24 @@
 BASE_EXPORT void SetShowErrorDialogs(bool enable_dialogs);
 
 // Sets the Log Assert Handler that will be used to notify of check failures.
+// Resets Log Assert Handler on object destruction.
 // The default handler shows a dialog box and then terminate the process,
 // however clients can use this function to override with their own handling
 // (e.g. a silent one for Unit Tests)
-typedef void (*LogAssertHandlerFunction)(const std::string& str);
-BASE_EXPORT void SetLogAssertHandler(LogAssertHandlerFunction handler);
+using LogAssertHandlerFunction =
+    base::Callback<void(const char* file,
+                        int line,
+                        const base::StringPiece message,
+                        const base::StringPiece stack_trace)>;
+
+class BASE_EXPORT ScopedLogAssertHandler {
+ public:
+  explicit ScopedLogAssertHandler(LogAssertHandlerFunction handler);
+  ~ScopedLogAssertHandler();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedLogAssertHandler);
+};
 
 // Sets the Log Message Handler that gets passed every log message before
 // it's sent to other log destinations (if any).
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 62323972..6ae965f7 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/compiler_specific.h"
 #include "base/logging.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/strings/string_piece.h"
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -29,12 +32,16 @@
 namespace {
 
 using ::testing::Return;
+using ::testing::_;
 
 // Needs to be global since log assert handlers can't maintain state.
 int log_sink_call_count = 0;
 
 #if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG)
-void LogSink(const std::string& str) {
+void LogSink(const char* file,
+             int line,
+             const base::StringPiece message,
+             const base::StringPiece stack_trace) {
   ++log_sink_call_count;
 }
 #endif
@@ -47,7 +54,6 @@
 
   ~LogStateSaver() {
     SetMinLogLevel(old_min_log_level_);
-    SetLogAssertHandler(NULL);
     log_sink_call_count = 0;
   }
 
@@ -67,6 +73,13 @@
   MOCK_METHOD0(Log, const char*());
 };
 
+class MockLogAssertHandler {
+ public:
+  MOCK_METHOD4(
+      HandleLogAssert,
+      void(const char*, int, const base::StringPiece, const base::StringPiece));
+};
+
 TEST_F(LoggingTest, BasicLogging) {
   MockLogSource mock_log_source;
   EXPECT_CALL(mock_log_source, Log())
@@ -197,7 +210,7 @@
       WillRepeatedly(Return("check message"));
   EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0);
 
-  SetLogAssertHandler(&LogSink);
+  ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
 
   CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log();
   PCHECK(!mock_log_source.Log()) << mock_log_source.Log();
@@ -405,12 +418,12 @@
   EXPECT_FALSE(DLOG_IS_ON(DCHECK));
 #elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
   // Release build with real DCHECKS.
-  SetLogAssertHandler(&LogSink);
+  ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
   EXPECT_TRUE(DCHECK_IS_ON());
   EXPECT_TRUE(DLOG_IS_ON(DCHECK));
 #else
   // Debug build.
-  SetLogAssertHandler(&LogSink);
+  ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
   EXPECT_TRUE(DCHECK_IS_ON());
   EXPECT_TRUE(DLOG_IS_ON(DCHECK));
 #endif
@@ -499,6 +512,44 @@
     CHECK_EQ(false, true);           // Unreached.
 }
 
+TEST_F(LoggingTest, NestedLogAssertHandlers) {
+  ::testing::InSequence dummy;
+  ::testing::StrictMock<MockLogAssertHandler> handler_a, handler_b;
+
+  EXPECT_CALL(
+      handler_a,
+      HandleLogAssert(
+          _, _,
+          base::StringPiece(
+              "Check failed: false. First assert must be catched by handler_a"),
+          _));
+  EXPECT_CALL(
+      handler_b,
+      HandleLogAssert(_, _,
+                      base::StringPiece("Check failed: false. Second assert "
+                                        "must be catched by handler_b"),
+                      _));
+  EXPECT_CALL(
+      handler_a,
+      HandleLogAssert(_, _,
+                      base::StringPiece("Check failed: false. Last assert "
+                                        "must be catched by handler_a again"),
+                      _));
+
+  logging::ScopedLogAssertHandler scoped_handler_a(base::Bind(
+      &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler_a)));
+
+  CHECK(false) << "First assert must be catched by handler_a";
+
+  {
+    logging::ScopedLogAssertHandler scoped_handler_b(base::Bind(
+        &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler_b)));
+    CHECK(false) << "Second assert must be catched by handler_b";
+  }
+
+  CHECK(false) << "Last assert must be catched by handler_a again";
+}
+
 // Test that defining an operator<< for a type in a namespace doesn't prevent
 // other code in that namespace from calling the operator<<(ostream, wstring)
 // defined by logging.h. This can fail if operator<<(ostream, wstring) can't be
diff --git a/base/metrics/statistics_recorder_unittest.cc b/base/metrics/statistics_recorder_unittest.cc
index 48b6df3..c581f15 100644
--- a/base/metrics/statistics_recorder_unittest.cc
+++ b/base/metrics/statistics_recorder_unittest.cc
@@ -29,7 +29,6 @@
 
   ~LogStateSaver() {
     logging::SetMinLogLevel(old_min_log_level_);
-    logging::SetLogAssertHandler(nullptr);
   }
 
  private:
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h
index 5333640f..08feb60 100644
--- a/base/strings/string_piece.h
+++ b/base/strings/string_piece.h
@@ -30,13 +30,10 @@
 #include "base/base_export.h"
 #include "base/logging.h"
 #include "base/strings/string16.h"
+#include "base/strings/string_piece_forward.h"
 
 namespace base {
 
-template <typename STRING_TYPE> class BasicStringPiece;
-typedef BasicStringPiece<std::string> StringPiece;
-typedef BasicStringPiece<string16> StringPiece16;
-
 // internal --------------------------------------------------------------------
 
 // Many of the StringPiece functions use different implementations for the
diff --git a/base/strings/string_piece_forward.h b/base/strings/string_piece_forward.h
new file mode 100644
index 0000000..86c1d5fbd
--- /dev/null
+++ b/base/strings/string_piece_forward.h
@@ -0,0 +1,23 @@
+// 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.
+
+// Forward declaration of StringPiece types from base/strings/string_piece.h
+
+#ifndef BASE_STRINGS_STRING_PIECE_FORWARD_H_
+#define BASE_STRINGS_STRING_PIECE_FORWARD_H_
+
+#include <string>
+
+#include "base/strings/string16.h"
+
+namespace base {
+
+template <typename STRING_TYPE>
+class BasicStringPiece;
+typedef BasicStringPiece<std::string> StringPiece;
+typedef BasicStringPiece<string16> StringPiece16;
+
+}  // namespace base
+
+#endif  // BASE_STRINGS_STRING_PIECE_FORWARD_H_
diff --git a/base/test/gtest_xml_unittest_result_printer.cc b/base/test/gtest_xml_unittest_result_printer.cc
index 6ce4fde..31ac4ad 100644
--- a/base/test/gtest_xml_unittest_result_printer.cc
+++ b/base/test/gtest_xml_unittest_result_printer.cc
@@ -35,6 +35,14 @@
   return true;
 }
 
+void XmlUnitTestResultPrinter::OnAssert(const char* file,
+                                        int line,
+                                        const std::string& summary,
+                                        const std::string& message) {
+  WriteTestPartResult(file, line, testing::TestPartResult::kFatalFailure,
+                      summary, message);
+}
+
 void XmlUnitTestResultPrinter::OnTestCaseStart(
     const testing::TestCase& test_case) {
   fprintf(output_file_, "  <testsuite>\n");
@@ -66,7 +74,10 @@
             "      <failure message=\"\" type=\"\"></failure>\n");
   }
   for (int i = 0; i < test_info.result()->total_part_count(); ++i) {
-    WriteTestPartResult(test_info.result()->GetTestPartResult(i));
+    const auto& test_part_result = test_info.result()->GetTestPartResult(i);
+    WriteTestPartResult(test_part_result.file_name(),
+                        test_part_result.line_number(), test_part_result.type(),
+                        test_part_result.summary(), test_part_result.message());
   }
   fprintf(output_file_, "    </testcase>\n");
   fflush(output_file_);
@@ -79,9 +90,13 @@
 }
 
 void XmlUnitTestResultPrinter::WriteTestPartResult(
-    const testing::TestPartResult& test_part_result) {
+    const char* file,
+    int line,
+    testing::TestPartResult::Type result_type,
+    const std::string& summary,
+    const std::string& message) {
   const char* type = "unknown";
-  switch (test_part_result.type()) {
+  switch (result_type) {
     case testing::TestPartResult::kSuccess:
       type = "success";
       break;
@@ -92,10 +107,8 @@
       type = "fatal_failure";
       break;
   }
-  std::string summary = test_part_result.summary();
   std::string summary_encoded;
   Base64Encode(summary, &summary_encoded);
-  std::string message = test_part_result.message();
   std::string message_encoded;
   Base64Encode(message, &message_encoded);
   fprintf(output_file_,
@@ -103,8 +116,7 @@
           "        <summary>%s</summary>\n"
           "        <message>%s</message>\n"
           "      </x-test-result-part>\n",
-          type, test_part_result.file_name(), test_part_result.line_number(),
-          summary_encoded.c_str(), message_encoded.c_str());
+          type, file, line, summary_encoded.c_str(), message_encoded.c_str());
   fflush(output_file_);
 }
 
diff --git a/base/test/gtest_xml_unittest_result_printer.h b/base/test/gtest_xml_unittest_result_printer.h
index c7fb88f3..cce5e880 100644
--- a/base/test/gtest_xml_unittest_result_printer.h
+++ b/base/test/gtest_xml_unittest_result_printer.h
@@ -25,6 +25,12 @@
   // Must be called before adding as a listener. Returns true on success.
   bool Initialize(const FilePath& output_file_path) WARN_UNUSED_RESULT;
 
+  // CHECK/DCHECK failed. Print file/line and message to the xml.
+  void OnAssert(const char* file,
+                int line,
+                const std::string& summary,
+                const std::string& message);
+
  private:
   // testing::EmptyTestEventListener:
   void OnTestCaseStart(const testing::TestCase& test_case) override;
@@ -32,7 +38,11 @@
   void OnTestEnd(const testing::TestInfo& test_info) override;
   void OnTestCaseEnd(const testing::TestCase& test_case) override;
 
-  void WriteTestPartResult(const testing::TestPartResult& test_part_result);
+  void WriteTestPartResult(const char* file,
+                           int line,
+                           testing::TestPartResult::Type type,
+                           const std::string& summary,
+                           const std::string& message);
 
   FILE* output_file_;
 
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index 6f4cc37..c9bfe9e 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -238,11 +238,11 @@
     return;
   }
 
-  XmlUnitTestResultPrinter* printer = new XmlUnitTestResultPrinter;
-  CHECK(printer->Initialize(output_path));
+  printer_ = new XmlUnitTestResultPrinter;
+  CHECK(printer_->Initialize(output_path));
   testing::TestEventListeners& listeners =
       testing::UnitTest::GetInstance()->listeners();
-  listeners.Append(printer);
+  listeners.Append(printer_);
 }
 
 // Don't add additional code to this method.  Instead add it to
@@ -282,8 +282,10 @@
   return result;
 }
 
-// static
-void TestSuite::UnitTestAssertHandler(const std::string& str) {
+void TestSuite::UnitTestAssertHandler(const char* file,
+                                      int line,
+                                      const base::StringPiece summary,
+                                      const base::StringPiece stack_trace) {
 #if defined(OS_ANDROID)
   // Correlating test stdio with logcat can be difficult, so we emit this
   // helpful little hint about what was running.  Only do this for Android
@@ -298,6 +300,16 @@
   }
 #endif  // defined(OS_ANDROID)
 
+  // XmlUnitTestResultPrinter inherits gtest format, where assert has summary
+  // and message. In GTest, summary is just a logged text, and message is a
+  // logged text, concatenated with stack trace of assert.
+  // Concatenate summary and stack_trace here, to pass it as a message.
+  if (printer_) {
+    const std::string summary_str = summary.as_string();
+    const std::string stack_trace_str = summary_str + stack_trace.as_string();
+    printer_->OnAssert(file, line, summary_str, stack_trace_str);
+  }
+
   // The logging system actually prints the message before calling the assert
   // handler. Just exit now to avoid printing too many stack traces.
   _exit(1);
@@ -359,7 +371,8 @@
       !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) {
     SuppressErrorDialogs();
     debug::SetSuppressDebugUI(true);
-    logging::SetLogAssertHandler(UnitTestAssertHandler);
+    assert_handler_ = base::MakeUnique<logging::ScopedLogAssertHandler>(
+        base::Bind(&TestSuite::UnitTestAssertHandler, base::Unretained(this)));
   }
 
   base::test::InitializeICUForTesting();
diff --git a/base/test/test_suite.h b/base/test/test_suite.h
index 590a18c..82c746e 100644
--- a/base/test/test_suite.h
+++ b/base/test/test_suite.h
@@ -13,6 +13,7 @@
 #include <string>
 
 #include "base/at_exit.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/test/trace_to_file.h"
 #include "build/build_config.h"
@@ -23,6 +24,8 @@
 
 namespace base {
 
+class XmlUnitTestResultPrinter;
+
 // Instantiates TestSuite, runs it and returns exit code.
 int RunUnitTestsUsingBaseTestSuite(int argc, char **argv);
 
@@ -54,7 +57,10 @@
   // By default fatal log messages (e.g. from DCHECKs) result in error dialogs
   // which gum up buildbots. Use a minimalistic assert handler which just
   // terminates the process.
-  static void UnitTestAssertHandler(const std::string& str);
+  void UnitTestAssertHandler(const char* file,
+                             int line,
+                             const base::StringPiece summary,
+                             const base::StringPiece stack_trace);
 
   // Disable crash dialogs so that it doesn't gum up the buildbot
   virtual void SuppressErrorDialogs();
@@ -84,6 +90,10 @@
 
   bool created_feature_list_;
 
+  XmlUnitTestResultPrinter* printer_ = nullptr;
+
+  std::unique_ptr<logging::ScopedLogAssertHandler> assert_handler_;
+
   DISALLOW_COPY_AND_ASSIGN(TestSuite);
 };
 
diff --git a/base/values.cc b/base/values.cc
index 72f6185..f24646cb 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -32,17 +32,14 @@
 // Make a deep copy of |node|, but don't include empty lists or dictionaries
 // in the copy. It's possible for this function to return NULL and it
 // expects |node| to always be non-NULL.
-std::unique_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) {
-  std::unique_ptr<ListValue> copy;
-  for (const auto& entry : list) {
+std::unique_ptr<Value> CopyListWithoutEmptyChildren(const Value& list) {
+  Value copy(Value::Type::LIST);
+  for (const auto& entry : list.GetList()) {
     std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(entry);
-    if (child_copy) {
-      if (!copy)
-        copy.reset(new ListValue);
-      copy->Append(std::move(child_copy));
-    }
+    if (child_copy)
+      copy.GetList().push_back(std::move(*child_copy));
   }
-  return copy;
+  return copy.GetList().empty() ? nullptr : MakeUnique<Value>(std::move(copy));
 }
 
 std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren(
@@ -170,6 +167,14 @@
   dict_.Init(std::move(in_dict));
 }
 
+Value::Value(const ListStorage& in_list) : type_(Type::LIST) {
+  list_.Init(in_list);
+}
+
+Value::Value(ListStorage&& in_list) noexcept : type_(Type::LIST) {
+  list_.Init(std::move(in_list));
+}
+
 Value& Value::operator=(const Value& that) {
   if (type_ == that.type_) {
     InternalCopyAssignFromSameType(that);
@@ -229,6 +234,16 @@
   return *binary_value_;
 }
 
+Value::ListStorage& Value::GetList() {
+  CHECK(is_list());
+  return *list_;
+}
+
+const Value::ListStorage& Value::GetList() const {
+  CHECK(is_list());
+  return *list_;
+}
+
 size_t Value::GetSize() const {
   return GetBlob().size();
 }
diff --git a/base/values.h b/base/values.h
index badf118..2bab074 100644
--- a/base/values.h
+++ b/base/values.h
@@ -98,6 +98,9 @@
 
   explicit Value(DictStorage&& in_dict) noexcept;
 
+  explicit Value(const ListStorage& in_list);
+  explicit Value(ListStorage&& in_list) noexcept;
+
   Value& operator=(const Value& that);
   Value& operator=(Value&& that) noexcept;
 
@@ -131,6 +134,9 @@
   const std::string& GetString() const;
   const BlobStorage& GetBlob() const;
 
+  ListStorage& GetList();
+  const ListStorage& GetList() const;
+
   size_t GetSize() const;         // DEPRECATED, use GetBlob().size() instead.
   const char* GetBuffer() const;  // DEPRECATED, use GetBlob().data() instead.
 
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index be1e4d8..7f871123 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -30,6 +30,9 @@
   static_assert(
       std::is_nothrow_constructible<Value, Value::BlobStorage&&>::value,
       "IsNothrowMoveConstructibleFromBlob");
+  static_assert(
+      std::is_nothrow_constructible<Value, Value::ListStorage&&>::value,
+      "IsNothrowMoveConstructibleFromList");
   static_assert(std::is_nothrow_move_assignable<Value>::value,
                 "IsNothrowMoveAssignable");
 }
@@ -224,25 +227,14 @@
 }
 
 TEST(ValuesTest, CopyList) {
-  // TODO(crbug.com/646113): Clean this up once ListValue switched to
-  // value semantics.
-  int copy;
-  ListValue value;
-  value.AppendInteger(123);
+  Value value(Value::ListStorage{Value(123)});
 
-  ListValue copied_value(value);
-  copied_value.GetInteger(0, &copy);
+  Value copied_value(value);
+  EXPECT_EQ(value, copied_value);
 
-  EXPECT_EQ(value.type(), copied_value.type());
-  EXPECT_EQ(123, copy);
-
-  auto blank = MakeUnique<Value>();
-
-  *blank = value;
-  EXPECT_EQ(Value::Type::LIST, blank->type());
-
-  static_cast<ListValue*>(blank.get())->GetInteger(0, &copy);
-  EXPECT_EQ(123, copy);
+  Value blank;
+  blank = value;
+  EXPECT_EQ(value, blank);
 }
 
 // Group of tests for the move constructors and move-assigmnent.
@@ -341,22 +333,17 @@
 }
 
 TEST(ValuesTest, MoveList) {
-  // TODO(crbug.com/646113): Clean this up once ListValue switched to
-  // value semantics.
-  int move;
-  ListValue value;
-  value.AppendInteger(123);
-
-  ListValue moved_value(std::move(value));
-  moved_value.GetInteger(0, &move);
-
+  const Value::ListStorage list = {Value(123)};
+  Value value(list);
+  Value moved_value(std::move(value));
   EXPECT_EQ(Value::Type::LIST, moved_value.type());
-  EXPECT_EQ(123, move);
+  EXPECT_EQ(123, moved_value.GetList().back().GetInt());
 
   Value blank;
 
-  blank = ListValue();
+  blank = Value(list);
   EXPECT_EQ(Value::Type::LIST, blank.type());
+  EXPECT_EQ(123, blank.GetList().back().GetInt());
 }
 
 TEST(ValuesTest, Basic) {
diff --git a/cc/raster/staging_buffer_pool.cc b/cc/raster/staging_buffer_pool.cc
index 526e864e..3cb4b14d 100644
--- a/cc/raster/staging_buffer_pool.cc
+++ b/cc/raster/staging_buffer_pool.cc
@@ -114,8 +114,8 @@
   const uint64_t tracing_process_id =
       base::trace_event::MemoryDumpManager::GetInstance()
           ->GetTracingProcessId();
-  MemoryAllocatorDumpGuid shared_buffer_guid =
-      gfx::GetGpuMemoryBufferGUIDForTracing(tracing_process_id, buffer_id);
+  auto shared_buffer_guid =
+      gpu_memory_buffer->GetGUIDForTracing(tracing_process_id);
   pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
 
   // By creating an edge with a higher |importance| (w.r.t. browser-side dumps)
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 86fd5ae..8d5a3fc 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -2174,8 +2174,8 @@
     base::trace_event::MemoryAllocatorDumpGuid guid;
     switch (resource.type) {
       case RESOURCE_TYPE_GPU_MEMORY_BUFFER:
-        guid = gfx::GetGpuMemoryBufferGUIDForTracing(
-            tracing_process_id, resource.gpu_memory_buffer->GetHandle().id);
+        guid =
+            resource.gpu_memory_buffer->GetGUIDForTracing(tracing_process_id);
         break;
       case RESOURCE_TYPE_GL_TEXTURE:
         DCHECK(resource.gl_id);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 9cf35a8d..cfb412e 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -465,7 +465,6 @@
     "//third_party/WebKit/public:mojo_bindings_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
-    "//third_party/android_tools:android_support_annotations_java",
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_transition_java",
     "//third_party/android_tools:android_support_v7_appcompat_java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
index 5c55ae4..4560a32 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.offlinepages;
 
 import android.content.Context;
-import android.support.annotation.MainThread;
 import android.support.test.filters.MediumTest;
 
 import org.chromium.base.Callback;
@@ -31,13 +30,11 @@
 @CommandLineFlags.Add("enable-features=OfflineRecentPages")
 public class RecentTabsTest extends ChromeTabbedActivityTestBase {
     private static final String TEST_PAGE = "/chrome/test/data/android/about.html";
-    private static final String TEST_PAGE_2 = "/chrome/test/data/android/simple.html";
     private static final int TIMEOUT_MS = 5000;
 
     private OfflinePageBridge mOfflinePageBridge;
     private EmbeddedTestServer mTestServer;
     private String mTestPage;
-    private String mTestPage2;
 
     private void initializeBridgeForProfile(final boolean incognitoProfile)
             throws InterruptedException {
@@ -87,7 +84,6 @@
 
         mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
         mTestPage = mTestServer.getURL(TEST_PAGE);
-        mTestPage2 = mTestServer.getURL(TEST_PAGE_2);
     }
 
     @Override
@@ -113,9 +109,9 @@
         // The tab should be foreground and so no snapshot should exist.
         assertNull(getPageByClientId(firstTabClientId));
 
-        // Note: switching to a new tab must occur after the SnapshotController believes the page
-        // quality is good enough.  With the debug flag, the delay after DomContentLoaded is 0 so we
-        // can definitely snapshot after onload (which is what |loadUrlInNewTab| waits for).
+        // Note, that switching to a new tab must occur after the SnapshotController believes the
+        // page quality is good enough.  With the debug flag, the delay after DomContentLoaded is 0
+        // so we can definitely snapshot after onload (which is what |loadUrlInNewTab| waits for).
 
         // Switch to a new tab to cause the WebContents hidden event.
         loadUrlInNewTab("about:blank");
@@ -124,10 +120,10 @@
     }
 
     /**
-     * Note: this test relies on a sleeping period because some of the monitored actions are
-     * difficult to track deterministically. A sleep time of 100 ms was chosen based on local
-     * testing and is expected to be "safe". Nevertheless if flakiness is detected it might have to
-     * be further increased.
+     * Note: this test relies on a sleeping period because some of the taking actions are
+     * complicated to track otherwise, so there is the possibility of flakiness. I chose 100ms from
+     * local testing and I expect it to be "safe" but it flakiness is detected it might have to be
+     * further increased.
      */
     @CommandLineFlags.Add("short-offline-page-snapshot-delay-for-test")
     @MediumTest
@@ -182,83 +178,6 @@
         waitForPageWithClientId(firstTabClientId);
     }
 
-    /**
-     * Verifies that a snapshot created by last_n is properly deleted when the tab is navigated to
-     * another page. The deletion of snapshots for pages that should not be available anymore is a
-     * privacy requirement for last_n.
-     */
-    @CommandLineFlags.Add("short-offline-page-snapshot-delay-for-test")
-    @MediumTest
-    public void testLastNPageIsDeletedUponNavigation() throws Exception {
-        // The tab of interest.
-        final Tab tab = loadUrlInNewTab(mTestPage);
-        final TabModelSelector tabModelSelector = tab.getTabModelSelector();
-
-        final ClientId firstTabClientId =
-                new ClientId(OfflinePageBridge.LAST_N_NAMESPACE, Integer.toString(tab.getId()));
-
-        // Switch to a new tab and wait for the snapshot to be created.
-        loadUrlInNewTab("about:blank");
-        waitForPageWithClientId(firstTabClientId);
-        OfflinePageItem offlinePage = getPageByClientId(firstTabClientId);
-        assertFalse(tab.equals(tabModelSelector.getCurrentTab()));
-
-        // Switch back to the initial tab and install the page deletion monitor for later usage.
-        final OfflinePageDeletionMonitor deletionMonitor =
-                new OfflinePageDeletionMonitor(offlinePage.getOfflineId());
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                TabModel tabModel = tabModelSelector.getModelForTabId(tab.getId());
-                int tabIndex = TabModelUtils.getTabIndexById(tabModel, tab.getId());
-                TabModelUtils.setIndex(tabModel, tabIndex);
-                deletionMonitor.installObserver();
-            }
-        });
-        assertEquals(tabModelSelector.getCurrentTab(), tab);
-
-        // Navigate to a new page and confirm the previously created snapshot has been deleted.
-        loadUrl(mTestPage2);
-        deletionMonitor.assertDeleted();
-    }
-
-    /**
-     * Verifies that a snapshot created by last_n is properly deleted when the tab is closed. The
-     * deletion of snapshots for pages that should not be available anymore is a privacy requirement
-     * for last_n.
-     */
-    @CommandLineFlags.Add("short-offline-page-snapshot-delay-for-test")
-    @MediumTest
-    public void testLastNPageIsDeletedUponClosure() throws Exception {
-        // The tab of interest.
-        final Tab tab = loadUrlInNewTab(mTestPage);
-        final TabModelSelector tabModelSelector = tab.getTabModelSelector();
-
-        final ClientId firstTabClientId =
-                new ClientId(OfflinePageBridge.LAST_N_NAMESPACE, Integer.toString(tab.getId()));
-
-        // Switch to a new tab and wait for the snapshot to be created.
-        loadUrlInNewTab("about:blank");
-        waitForPageWithClientId(firstTabClientId);
-        OfflinePageItem offlinePage = getPageByClientId(firstTabClientId);
-
-        // Requests closing of the tab allowing for closure undo and checks it's actually closing.
-        final int tabId = tab.getId();
-        final OfflinePageDeletionMonitor deletionMonitor =
-                new OfflinePageDeletionMonitor(offlinePage.getOfflineId());
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                deletionMonitor.installObserver();
-                TabModel tabModel = tabModelSelector.getModelForTabId(tabId);
-                tabModel.closeTab(tab, false, false, true);
-                tabModel.commitTabClosure(tabId);
-            }
-        });
-        assertNull(tabModelSelector.getTabById(tabId));
-        deletionMonitor.assertDeleted();
-    }
-
     private void waitForPageWithClientId(final ClientId clientId) throws InterruptedException {
         if (getPageByClientId(clientId) != null) return;
 
@@ -280,32 +199,6 @@
         assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
     }
 
-    private class OfflinePageDeletionMonitor {
-        private final Semaphore mSemaphore = new Semaphore(0);
-        private final long mOfflineId;
-
-        public OfflinePageDeletionMonitor(long offlineId) {
-            mOfflineId = offlineId;
-        }
-
-        @MainThread
-        public void installObserver() {
-            mOfflinePageBridge.addObserver(new OfflinePageModelObserver() {
-                @Override
-                public void offlinePageDeleted(long offlineId, ClientId clientId) {
-                    if (offlineId == mOfflineId) {
-                        mOfflinePageBridge.removeObserver(this);
-                        mSemaphore.release();
-                    }
-                }
-            });
-        }
-
-        public void assertDeleted() throws InterruptedException {
-            assertTrue(mSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        }
-    }
-
     private OfflinePageItem getPageByClientId(ClientId clientId) throws InterruptedException {
         final OfflinePageItem[] result = {null};
         final Semaphore semaphore = new Semaphore(0);
@@ -330,24 +223,4 @@
         assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         return result[0];
     }
-
-    private OfflinePageItem getPageByOfflineId(final long offlineId) throws InterruptedException {
-        final OfflinePageItem[] result = {null};
-        final Semaphore semaphore = new Semaphore(0);
-
-        ThreadUtils.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mOfflinePageBridge.getPageByOfflineId(offlineId, new Callback<OfflinePageItem>() {
-                    @Override
-                    public void onResult(OfflinePageItem item) {
-                        result[0] = item;
-                        semaphore.release();
-                    }
-                });
-            }
-        });
-        assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        return result[0];
-    }
 }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index a387ef7..0918bf45 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -278,15 +278,6 @@
       <message name="IDS_PAGE_INFO_PERMISSION_ASK" desc="The label used in the permissions dropdowns for the option that makes the browser asks for permission. ">
         ask
       </message>
-      <message name="IDS_PAGE_INFO_PERMISSION_SET_BY_POLICY" desc="The label used underneath a permission listed in the Website Settings popup if the permission was explicitly set by the user's enterprise policy.">
-        Controlled by enterprise policy
-      </message>
-      <message name="IDS_PAGE_INFO_PERMISSION_SET_BY_EXTENSION" desc="The label used underneath a permission listed in the Website Settings popup if the permission was explicitly set by one of the user's extensions.">
-        Controlled by an extension
-      </message>
-      <message name="IDS_PAGE_INFO_PERMISSION_AUTOMATICALLY_BLOCKED" desc="The label used underneath a permission listed in the Website Settings popup if the permission was blocked by Chrome on behalf of the user.">
-        Automatically blocked
-      </message>
       <message name="IDS_PAGE_INFO_TYPE_AUTOPLAY" desc="The label used for the autoplay permission controls in the Website Settings popup.">
         Autoplay
       </message>
diff --git a/chrome/browser/android/locale/special_locale_handler.cc b/chrome/browser/android/locale/special_locale_handler.cc
index 0f3271f..e1f55b6 100644
--- a/chrome/browser/android/locale/special_locale_handler.cc
+++ b/chrome/browser/android/locale/special_locale_handler.cc
@@ -65,8 +65,9 @@
     return false;
 
   for (const auto& data_url : prepopulated_list) {
-    TemplateURL* existing = template_url_service_->GetTemplateURLForKeyword(
-        data_url.get()->keyword());
+    const TemplateURL* existing =
+        template_url_service_->GetTemplateURLForKeyword(
+            data_url.get()->keyword());
     // Do not add local engines if there is already one.
     if (existing)
       continue;
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
index db41ab6..cc3ce6a8 100644
--- a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
+++ b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
@@ -451,7 +451,9 @@
   EXPECT_EQ(Offliner::RequestStatus::FOREGROUND_CANCELED, request_status());
 }
 
-TEST_F(PrerenderingOfflinerTest, ForegroundTransitionIgnoredOnHighEndDevice) {
+// TODO(crbug.com/712941): Flaky test.
+TEST_F(PrerenderingOfflinerTest,
+       DISABLED_ForegroundTransitionIgnoredOnHighEndDevice) {
   offliner()->SetLowEndDeviceForTesting(false);
 
   base::Time creation_time = base::Time::Now();
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.cc b/chrome/browser/android/offline_pages/recent_tab_helper.cc
index 308afd1..f248220 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper.cc
+++ b/chrome/browser/android/offline_pages/recent_tab_helper.cc
@@ -212,27 +212,18 @@
         downloads_ongoing_snapshot_info_.get(), false);
   }
 
-  // If the previous page was saved, delete it now.
-  if (last_n_latest_saved_snapshot_info_) {
-    std::vector<int64_t> id{last_n_latest_saved_snapshot_info_->request_id};
-    page_model_->DeletePagesByOfflineId(id, DeletePageCallback());
-  }
-
   // Cancel any and all in flight snapshot tasks from the previous page.
+  DVLOG_IF(1, last_n_ongoing_snapshot_info_)
+      << " - Canceling ongoing last_n snapshot";
   CancelInFlightSnapshots();
   downloads_snapshot_on_hold_ = false;
 
   // Always reset so that posted tasks get canceled.
   snapshot_controller_->Reset();
 
-  // Check for conditions that should stop last_n from creating snapshots of
-  // this page:
-  // - It is an error page.
-  // - The navigation is a POST as offline pages are never loaded for them.
-  // - The navigated URL is not supported.
-  // - The page being loaded is already an offline page.
+  // Check for conditions that would cause us not to snapshot.
   bool can_save =
-      !navigation_handle->IsErrorPage() && !navigation_handle->IsPost() &&
+      !navigation_handle->IsErrorPage() &&
       OfflinePageModel::CanSaveURL(web_contents()->GetLastCommittedURL()) &&
       OfflinePageUtils::GetOfflinePageFromWebContents(web_contents()) ==
           nullptr;
@@ -428,12 +419,8 @@
 void RecentTabHelper::SavePageCallback(SnapshotProgressInfo* snapshot_info,
                                        OfflinePageModel::SavePageResult result,
                                        int64_t offline_id) {
-  DCHECK((snapshot_info->IsForLastN() &&
-          snapshot_info->request_id == OfflinePageModel::kInvalidOfflineId) ||
+  DCHECK(snapshot_info->IsForLastN() ||
          snapshot_info->request_id == offline_id);
-  // Store the assigned offline_id (for downloads case it will already contain
-  // the same value).
-  snapshot_info->request_id = offline_id;
   ReportSnapshotCompleted(snapshot_info, result == SavePageResult::SUCCESS);
 }
 
@@ -447,12 +434,7 @@
            << " for: " << web_contents()->GetLastCommittedURL().spec();
   if (snapshot_info->IsForLastN()) {
     DCHECK_EQ(snapshot_info, last_n_ongoing_snapshot_info_.get());
-    if (success) {
-      last_n_latest_saved_snapshot_info_ =
-          std::move(last_n_ongoing_snapshot_info_);
-    } else {
-      last_n_ongoing_snapshot_info_.reset();
-    }
+    last_n_ongoing_snapshot_info_.reset();
     return;
   }
 
@@ -499,15 +481,10 @@
 }
 
 void RecentTabHelper::CancelInFlightSnapshots() {
-  DVLOG_IF(1, last_n_ongoing_snapshot_info_)
-      << " - Canceling ongoing last_n snapshot";
-  DVLOG_IF(1, downloads_ongoing_snapshot_info_)
-      << " - Canceling ongoing downloads snapshot";
   weak_ptr_factory_.InvalidateWeakPtrs();
   downloads_ongoing_snapshot_info_.reset();
   downloads_latest_saved_snapshot_info_.reset();
   last_n_ongoing_snapshot_info_.reset();
-  last_n_latest_saved_snapshot_info_.reset();
 }
 
 }  // namespace offline_pages
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper.h b/chrome/browser/android/offline_pages/recent_tab_helper.h
index c61fbd74..b547240 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper.h
+++ b/chrome/browser/android/offline_pages/recent_tab_helper.h
@@ -128,18 +128,13 @@
   bool downloads_snapshot_on_hold_ = false;
 
   // Snapshot information for the last successful snapshot requested by
-  // downloads. Null if no successful one has ever completed for the current
-  // page.
+  // downloads. Null if no successful one has ever completed.
   std::unique_ptr<SnapshotProgressInfo> downloads_latest_saved_snapshot_info_;
 
   // Snapshot progress information for a last_n triggered request. Null if
   // last_n is not currently capturing the current page.
   std::unique_ptr<SnapshotProgressInfo> last_n_ongoing_snapshot_info_;
 
-  // Snapshot information for the last successful snapshot requested by
-  // last_n. Null if no successful one has ever completed for the current page.
-  std::unique_ptr<SnapshotProgressInfo> last_n_latest_saved_snapshot_info_;
-
   // If empty, the tab does not have AndroidId and can not capture pages.
   std::string tab_id_;
 
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
index 3e4c535..7f97d15f 100644
--- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
+++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -375,8 +375,8 @@
   ASSERT_EQ(1U, GetAllPages().size());
 }
 
-// Checks that last_n will not save a snapshot while the tab is being presented
-// as a custom tab. Download requests should be unaffected though.
+// Checks that last_n will not save a snapshot if the tab while the tab is
+// presented as a custom tab. Download requests should be unaffected though.
 TEST_F(RecentTabHelperTest, LastNWontSaveCustomTab) {
   // Simulates the tab running as a custom tab.
   default_test_delegate()->set_is_custom_tab(true);
@@ -500,16 +500,15 @@
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
   int64_t first_offline_id = GetAllPages()[0].offline_id;
 
-  // Reload the same URL until the page is minimally loaded. The previous
-  // snapshot should have been removed.
+  // Navigate with the same URL until the page is minimally loaded then hide the
+  // tab. The previous snapshot should be removed and a new one taken.
   NavigateAndCommitTyped(kTestPageUrl);
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
   EXPECT_EQ(1U, page_added_count());
-  EXPECT_EQ(1U, model_removed_count());
-  ASSERT_EQ(0U, GetAllPages().size());
+  EXPECT_EQ(0U, model_removed_count());
+  ASSERT_EQ(1U, GetAllPages().size());
 
-  // Hide the tab and a new snapshot should be taken.
   recent_tab_helper()->WasHidden();
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
@@ -566,15 +565,15 @@
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
 
-  // Fully load the second URL. The previous snapshot should have been deleted.
+  // Fully load the second URL then hide the tab and check for a single snapshot
+  // of the new page.
   NavigateAndCommitTyped(kTestPageUrlOther);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   EXPECT_EQ(1U, page_added_count());
-  EXPECT_EQ(1U, model_removed_count());
-  ASSERT_EQ(0U, GetAllPages().size());
+  EXPECT_EQ(0U, model_removed_count());
+  ASSERT_EQ(1U, GetAllPages().size());
 
-  // Then hide the tab and check for a single snapshot of the new page.
   recent_tab_helper()->WasHidden();
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
@@ -732,7 +731,7 @@
 }
 
 // Simulates a download request to offline the current page made after loading
-// is completed. Should end up with one offline page.
+// is completed. Should end up with one offline pages.
 TEST_F(RecentTabHelperTest, DownloadRequestAfterFullyLoad) {
   NavigateAndCommit(kTestPageUrl);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
@@ -898,8 +897,7 @@
   RunUntilIdle();
   ASSERT_EQ(1U, GetAllPages().size());
 
-  // Starts a reload and hides the tab before it minimally load. The previous
-  // snapshot should be removed.
+  // Starts a reload and hides the tab. No new snapshot should be saved.
   controller().Reload(content::ReloadType::NORMAL, false);
   content::WebContentsTester* web_contents_tester =
       content::WebContentsTester::For(web_contents());
@@ -907,8 +905,8 @@
   recent_tab_helper()->WasHidden();
   RunUntilIdle();
   EXPECT_EQ(1U, page_added_count());
-  EXPECT_EQ(1U, model_removed_count());
-  ASSERT_EQ(0U, GetAllPages().size());
+  EXPECT_EQ(0U, model_removed_count());
+  ASSERT_EQ(1U, GetAllPages().size());
 
   // Finish loading and hide the tab. A new snapshot should be created.
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
index ff5bd80..68f9806e 100644
--- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
+++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -37,10 +37,11 @@
 using device::UsbDevice;
 using device::UsbDeviceHandle;
 using device::UsbEndpointDescriptor;
-using device::UsbEndpointDirection;
 using device::UsbInterfaceDescriptor;
 using device::UsbService;
 using device::UsbSynchronizationType;
+using device::UsbTransferDirection;
+using device::UsbTransferStatus;
 using device::UsbTransferType;
 using device::UsbUsageType;
 
@@ -183,9 +184,9 @@
   }
 
   // Async IO. Can be called on any thread.
-  void ControlTransfer(UsbEndpointDirection direction,
-                       TransferRequestType request_type,
-                       TransferRecipient recipient,
+  void ControlTransfer(UsbTransferDirection direction,
+                       device::UsbControlTransferType request_type,
+                       device::UsbControlTransferRecipient recipient,
                        uint8_t request,
                        uint16_t value,
                        uint16_t index,
@@ -194,13 +195,13 @@
                        unsigned int timeout,
                        const TransferCallback& callback) override {}
 
-  void GenericTransfer(UsbEndpointDirection direction,
+  void GenericTransfer(UsbTransferDirection direction,
                        uint8_t endpoint,
                        scoped_refptr<net::IOBuffer> buffer,
                        size_t length,
                        unsigned int timeout,
                        const TransferCallback& callback) override {
-    if (direction == device::USB_DIRECTION_OUTBOUND) {
+    if (direction == device::UsbTransferDirection::OUTBOUND) {
       if (remaining_body_length_ == 0) {
         std::vector<uint32_t> header(6);
         memcpy(&header[0], buffer->data(), length);
@@ -222,12 +223,13 @@
         ProcessIncoming();
       }
 
-      device::UsbTransferStatus status =
-          broken_ ? device::USB_TRANSFER_ERROR : device::USB_TRANSFER_COMPLETED;
+      device::UsbTransferStatus status = broken_
+                                             ? UsbTransferStatus::TRANSFER_ERROR
+                                             : UsbTransferStatus::COMPLETED;
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::Bind(callback, status, nullptr, 0));
       ProcessQueries();
-    } else if (direction == device::USB_DIRECTION_INBOUND) {
+    } else if (direction == device::UsbTransferDirection::INBOUND) {
       queries_.push(Query(callback, buffer, length));
       ProcessQueries();
     }
@@ -337,8 +339,8 @@
     Query query = queries_.front();
     if (broken_) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::Bind(query.callback, device::USB_TRANSFER_ERROR, nullptr, 0));
+          FROM_HERE, base::Bind(query.callback,
+                                UsbTransferStatus::TRANSFER_ERROR, nullptr, 0));
     }
 
     if (query.size > output_buffer_.size())
@@ -351,7 +353,7 @@
     output_buffer_.erase(output_buffer_.begin(),
                          output_buffer_.begin() + query.size);
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(query.callback, device::USB_TRANSFER_COMPLETED,
+        FROM_HERE, base::Bind(query.callback, UsbTransferStatus::COMPLETED,
                               query.buffer, query.size));
   }
 
diff --git a/chrome/browser/devtools/device/usb/android_usb_device.cc b/chrome/browser/devtools/device/usb/android_usb_device.cc
index 5b37f88..e8754bd2c 100644
--- a/chrome/browser/devtools/device/usb/android_usb_device.cc
+++ b/chrome/browser/devtools/device/usb/android_usb_device.cc
@@ -36,7 +36,9 @@
 using device::UsbInterfaceDescriptor;
 using device::UsbEndpointDescriptor;
 using device::UsbService;
+using device::UsbTransferDirection;
 using device::UsbTransferStatus;
+using device::UsbTransferType;
 
 namespace {
 
@@ -227,9 +229,9 @@
   int zero_mask = 0;
 
   for (const UsbEndpointDescriptor& endpoint : interface.endpoints) {
-    if (endpoint.transfer_type != device::USB_TRANSFER_BULK)
+    if (endpoint.transfer_type != UsbTransferType::BULK)
       continue;
-    if (endpoint.direction == device::USB_DIRECTION_INBOUND)
+    if (endpoint.direction == UsbTransferDirection::INBOUND)
       inbound_address = endpoint.address;
     else
       outbound_address = endpoint.address;
@@ -446,7 +448,7 @@
   DumpMessage(true, message->data(), message->size());
 
   usb_handle_->GenericTransfer(
-      device::USB_DIRECTION_OUTBOUND, outbound_address_, message,
+      UsbTransferDirection::OUTBOUND, outbound_address_, message,
       message->size(), kUsbTimeout,
       base::Bind(&AndroidUsbDevice::OutgoingMessageSent,
                  weak_factory_.GetWeakPtr()));
@@ -455,7 +457,7 @@
 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status,
                                            scoped_refptr<net::IOBuffer> buffer,
                                            size_t result) {
-  if (status != device::USB_TRANSFER_COMPLETED) {
+  if (status != UsbTransferStatus::COMPLETED) {
     return;
   }
 
@@ -472,7 +474,7 @@
 
   scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize);
   usb_handle_->GenericTransfer(
-      device::USB_DIRECTION_INBOUND, inbound_address_, buffer, kHeaderSize,
+      UsbTransferDirection::INBOUND, inbound_address_, buffer, kHeaderSize,
       kUsbTimeout,
       base::Bind(&AndroidUsbDevice::ParseHeader, weak_factory_.GetWeakPtr()));
 }
@@ -482,13 +484,13 @@
                                    size_t result) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  if (status == device::USB_TRANSFER_TIMEOUT) {
+  if (status == UsbTransferStatus::TIMEOUT) {
     task_runner_->PostTask(FROM_HERE,
                            base::Bind(&AndroidUsbDevice::ReadHeader, this));
     return;
   }
 
-  if (status != device::USB_TRANSFER_COMPLETED || result != kHeaderSize) {
+  if (status != UsbTransferStatus::COMPLETED || result != kHeaderSize) {
     TransferError(status);
     return;
   }
@@ -502,7 +504,7 @@
   uint32_t data_check = header[4];
   uint32_t magic = header[5];
   if ((message->command ^ 0xffffffff) != magic) {
-    TransferError(device::USB_TRANSFER_ERROR);
+    TransferError(UsbTransferStatus::TRANSFER_ERROR);
     return;
   }
 
@@ -529,7 +531,7 @@
   scoped_refptr<net::IOBuffer> buffer =
       new net::IOBuffer(static_cast<size_t>(data_length));
   usb_handle_->GenericTransfer(
-      device::USB_DIRECTION_INBOUND, inbound_address_, buffer, data_length,
+      UsbTransferDirection::INBOUND, inbound_address_, buffer, data_length,
       kUsbTimeout,
       base::Bind(&AndroidUsbDevice::ParseBody, weak_factory_.GetWeakPtr(),
                  base::Passed(&message), data_length, data_check));
@@ -543,14 +545,14 @@
                                  size_t result) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  if (status == device::USB_TRANSFER_TIMEOUT) {
+  if (status == UsbTransferStatus::TIMEOUT) {
     task_runner_->PostTask(
         FROM_HERE, base::Bind(&AndroidUsbDevice::ReadBody, this,
                               base::Passed(&message), data_length, data_check));
     return;
   }
 
-  if (status != device::USB_TRANSFER_COMPLETED ||
+  if (status != UsbTransferStatus::COMPLETED ||
       static_cast<uint32_t>(result) != data_length) {
     TransferError(status);
     return;
@@ -559,7 +561,7 @@
   DumpMessage(false, buffer->data(), data_length);
   message->body = std::string(buffer->data(), result);
   if (Checksum(message->body) != data_check) {
-    TransferError(device::USB_TRANSFER_ERROR);
+    TransferError(UsbTransferStatus::TRANSFER_ERROR);
     return;
   }
 
diff --git a/chrome/browser/extensions/app_data_migrator_unittest.cc b/chrome/browser/extensions/app_data_migrator_unittest.cc
index ac2610d..0bea1900 100644
--- a/chrome/browser/extensions/app_data_migrator_unittest.cc
+++ b/chrome/browser/extensions/app_data_migrator_unittest.cc
@@ -17,7 +17,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/indexed_db_context.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/test/mock_blob_url_request_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
@@ -26,6 +25,7 @@
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_operation_runner.h"
 #include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader.cc b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
index 24a0642..83e3cb4 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
@@ -23,6 +23,7 @@
 #include "chrome/common/partial_circular_buffer.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/base/load_flags.h"
 #include "net/base/mime_util.h"
 #include "net/url_request/url_fetcher.h"
 #include "third_party/zlib/zlib.h"
@@ -449,6 +450,8 @@
   std::unique_ptr<net::URLFetcher> url_fetcher(net::URLFetcher::Create(
       GURL(chrome::kUploadURL), net::URLFetcher::POST, this));
   url_fetcher->SetUploadData(content_type, *post_data);
+  url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+                            net::LOAD_DO_NOT_SAVE_COOKIES);
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&WebRtcLogUploader::SetRequestContextOnUIThread,
           base::Unretained(this), base::Unretained(url_fetcher.release()),
diff --git a/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc b/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
index f7931d25..5f10376 100644
--- a/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
@@ -344,11 +344,19 @@
 
 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
                        MANUAL_TestVideoQualityVp8) {
+// Disable these tests until crbug.com/711400 is addressed.
+#if defined(OS_MACOSX)
+  return;
+#endif  // defined(OS_MACOSX)
   TestVideoQuality("VP8");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
                        MANUAL_TestVideoQualityVp9) {
+// Disable these tests until crbug.com/711400 is addressed.
+#if defined(OS_MACOSX)
+  return;
+#endif  // defined(OS_MACOSX)
   TestVideoQuality("VP9");
 }
 
@@ -356,6 +364,10 @@
 
 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
                        MANUAL_TestVideoQualityH264) {
+// Disable these tests until crbug.com/711400 is addressed.
+#if defined(OS_MACOSX)
+  return;
+#endif  // defined(OS_MACOSX)
   // Only run test if run-time feature corresponding to |rtc_use_h264| is on.
   if (!base::FeatureList::IsEnabled(content::kWebRtcH264WithOpenH264FFmpeg)) {
     LOG(WARNING) << "Run-time feature WebRTC-H264WithOpenH264FFmpeg disabled. "
diff --git a/chrome/browser/resources/md_bookmarks/actions.js b/chrome/browser/resources/md_bookmarks/actions.js
index 9f6a63d..11fd96e 100644
--- a/chrome/browser/resources/md_bookmarks/actions.js
+++ b/chrome/browser/resources/md_bookmarks/actions.js
@@ -70,7 +70,7 @@
    * @param {string} id
    * @param {string} parentId
    * @param {number} index
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @return {!Action}
    */
   function removeBookmark(id, parentId, index, nodes) {
@@ -85,7 +85,7 @@
   }
 
   /**
-   * @param {NodeList} nodeMap
+   * @param {NodeMap} nodeMap
    * @return {!Action}
    */
   function refreshNodes(nodeMap) {
diff --git a/chrome/browser/resources/md_bookmarks/app.js b/chrome/browser/resources/md_bookmarks/app.js
index ed59f5e..c7a396a1 100644
--- a/chrome/browser/resources/md_bookmarks/app.js
+++ b/chrome/browser/resources/md_bookmarks/app.js
@@ -43,10 +43,10 @@
     });
 
     chrome.bookmarks.getTree(function(results) {
-      var nodeList = bookmarks.util.normalizeNodes(results[0]);
+      var nodeMap = bookmarks.util.normalizeNodes(results[0]);
       var initialState = bookmarks.util.createEmptyState();
-      initialState.nodes = nodeList;
-      initialState.selectedFolder = nodeList[ROOT_NODE_ID].children[0];
+      initialState.nodes = nodeMap;
+      initialState.selectedFolder = nodeMap[ROOT_NODE_ID].children[0];
       var closedFoldersString =
           window.localStorage[LOCAL_STORAGE_CLOSED_FOLDERS_KEY];
       initialState.closedFolders = closedFoldersString ?
diff --git a/chrome/browser/resources/md_bookmarks/reducers.js b/chrome/browser/resources/md_bookmarks/reducers.js
index b0d0a926..6ad7193 100644
--- a/chrome/browser/resources/md_bookmarks/reducers.js
+++ b/chrome/browser/resources/md_bookmarks/reducers.js
@@ -153,10 +153,10 @@
   var NodeState = {};
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {string} id
    * @param {function(BookmarkNode):BookmarkNode} callback
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.modifyNode_ = function(nodes, id, callback) {
     var nodeModification = {};
@@ -165,9 +165,9 @@
   };
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {Action} action
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.createBookmark = function(nodes, action) {
     var nodeModifications = {};
@@ -184,9 +184,9 @@
   };
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {Action} action
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.editBookmark = function(nodes, action) {
     // Do not allow folders to change URL (making them no longer folders).
@@ -200,9 +200,9 @@
   };
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {Action} action
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.moveBookmark = function(nodes, action) {
     var nodeModifications = {};
@@ -232,9 +232,9 @@
   };
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {Action} action
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.removeBookmark = function(nodes, action) {
     var newState =
@@ -249,9 +249,9 @@
   };
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {Action} action
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.reorderChildren = function(nodes, action) {
     return NodeState.modifyNode_(nodes, action.id, function(node) {
@@ -261,9 +261,9 @@
   };
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {Action} action
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   NodeState.updateNodes = function(nodes, action) {
     switch (action.name) {
@@ -287,7 +287,7 @@
   var SelectedFolderState = {};
 
   /**
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {string} ancestorId
    * @param {string} childId
    * @return {boolean}
@@ -306,7 +306,7 @@
   /**
    * @param {string} selectedFolder
    * @param {Action} action
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @return {string}
    */
   SelectedFolderState.updateSelectedFolder = function(
@@ -341,7 +341,7 @@
   /**
    * @param {ClosedFolderState} closedFolders
    * @param {string|undefined} id
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @return {ClosedFolderState}
    */
   ClosedFolderState.openFolderAndAncestors = function(
@@ -377,7 +377,7 @@
   /**
    * @param {ClosedFolderState} closedFolders
    * @param {Action} action
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @return {ClosedFolderState}
    */
   ClosedFolderState.updateClosedFolders = function(
diff --git a/chrome/browser/resources/md_bookmarks/types.js b/chrome/browser/resources/md_bookmarks/types.js
index 8eb1a37..6043c006 100644
--- a/chrome/browser/resources/md_bookmarks/types.js
+++ b/chrome/browser/resources/md_bookmarks/types.js
@@ -24,7 +24,7 @@
 /**
  * @typedef {!Object<string, BookmarkNode>}
  */
-var NodeList;
+var NodeMap;
 
 /**
  * @typedef {{
@@ -50,7 +50,7 @@
 
 /**
  * @typedef {{
- *   nodes: NodeList,
+ *   nodes: NodeMap,
  *   selectedFolder: string,
  *   closedFolders: ClosedFolderState,
  *   search: SearchState,
diff --git a/chrome/browser/resources/md_bookmarks/util.js b/chrome/browser/resources/md_bookmarks/util.js
index c6e4c00..a660add7 100644
--- a/chrome/browser/resources/md_bookmarks/util.js
+++ b/chrome/browser/resources/md_bookmarks/util.js
@@ -42,17 +42,17 @@
 
   /**
    * @param {BookmarkTreeNode} rootNode
-   * @return {NodeList}
+   * @return {NodeMap}
    */
   function normalizeNodes(rootNode) {
-    /** @type {NodeList} */
-    var nodeList = {};
+    /** @type {NodeMap} */
+    var nodeMap = {};
     var stack = [];
     stack.push(rootNode);
 
     while (stack.length > 0) {
       var node = stack.pop();
-      nodeList[node.id] = normalizeNode(node);
+      nodeMap[node.id] = normalizeNode(node);
       if (!node.children)
         continue;
 
@@ -61,7 +61,7 @@
       });
     }
 
-    return nodeList;
+    return nodeMap;
   }
 
   /** @return {!BookmarksPageState} */
@@ -92,7 +92,7 @@
 
   /**
    * @param {string} id
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @return {boolean}
    */
   function hasChildFolders(id, nodes) {
@@ -106,7 +106,7 @@
 
   /**
    * Get all descendants of a node, including the node itself.
-   * @param {NodeList} nodes
+   * @param {NodeMap} nodes
    * @param {string} baseId
    * @return {!Set<string>}
    */
diff --git a/chrome/browser/safe_browsing/client_side_model_loader.cc b/chrome/browser/safe_browsing/client_side_model_loader.cc
index bd2418b..fd52174 100644
--- a/chrome/browser/safe_browsing/client_side_model_loader.cc
+++ b/chrome/browser/safe_browsing/client_side_model_loader.cc
@@ -22,6 +22,7 @@
 #include "components/safe_browsing/common/safebrowsing_switches.h"
 #include "components/safe_browsing/csd.pb.h"
 #include "components/variations/variations_associated_data.h"
+#include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_fetcher.h"
@@ -121,6 +122,8 @@
   data_use_measurement::DataUseUserData::AttachToFetcher(
       fetcher_.get(), data_use_measurement::DataUseUserData::SAFE_BROWSING);
   fetcher_->SetRequestContext(request_context_getter_);
+  fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
+                         net::LOAD_DO_NOT_SEND_COOKIES);
   fetcher_->Start();
 }
 
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
index 9b53439..e22924b 100644
--- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
+++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "content/public/test/mock_blob_url_request_context.h"
 #include "storage/browser/blob/shareable_file_reference.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "storage/browser/fileapi/file_system_backend.h"
@@ -33,6 +32,7 @@
 #include "storage/browser/fileapi/file_system_operation_context.h"
 #include "storage/browser/fileapi/file_system_operation_runner.h"
 #include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "storage/browser/test/test_file_system_options.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
index 7ace915f..36044a0 100644
--- a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
@@ -20,10 +20,10 @@
 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
 #include "chrome/browser/sync_file_system/sync_status_code.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "content/public/test/mock_blob_url_request_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
 #include "third_party/leveldatabase/src/include/leveldb/env.h"
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
index 1df82ae..1fc9024 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
@@ -26,12 +26,12 @@
 #include "chrome/browser/sync_file_system/sync_status_code.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/test/mock_blob_url_request_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "storage/browser/blob/scoped_file.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_operation_runner.h"
 #include "storage/browser/fileapi/isolated_context.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
 #include "third_party/leveldatabase/src/include/leveldb/env.h"
diff --git a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
index 1193a9f..8e513f0 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
@@ -24,10 +24,10 @@
 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
 #include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "content/public/test/mock_blob_url_request_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
 #include "third_party/leveldatabase/src/include/leveldb/env.h"
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index 6646e6b3..c6f224e 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -223,7 +223,7 @@
 }
 
 bool ChromeOmniboxClient::ProcessExtensionKeyword(
-    TemplateURL* template_url,
+    const TemplateURL* template_url,
     const AutocompleteMatch& match,
     WindowOpenDisposition disposition,
     OmniboxNavigationObserver* observer) {
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.h b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
index 3c23dfb4..ac7d14e 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.h
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
@@ -45,7 +45,7 @@
   AutocompleteClassifier* GetAutocompleteClassifier() override;
   gfx::Image GetIconIfExtensionMatch(
       const AutocompleteMatch& match) const override;
-  bool ProcessExtensionKeyword(TemplateURL* template_url,
+  bool ProcessExtensionKeyword(const TemplateURL* template_url,
                                const AutocompleteMatch& match,
                                WindowOpenDisposition disposition,
                                OmniboxNavigationObserver* observer) override;
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/chrome/browser/ui/page_info/page_info_ui.cc
index 34a289b..2ff9c63 100644
--- a/chrome/browser/ui/page_info/page_info_ui.cc
+++ b/chrome/browser/ui/page_info/page_info_ui.cc
@@ -28,6 +28,33 @@
 const int kInvalidResourceID = -1;
 
 // The resource IDs for the strings that are displayed on the permissions
+// button if the permission setting is managed by policy.
+const int kPermissionButtonTextIDPolicyManaged[] = {
+    kInvalidResourceID,
+    IDS_PAGE_INFO_PERMISSION_ALLOWED_BY_POLICY,
+    IDS_PAGE_INFO_PERMISSION_BLOCKED_BY_POLICY,
+    IDS_PAGE_INFO_PERMISSION_ASK_BY_POLICY,
+    kInvalidResourceID,
+    kInvalidResourceID};
+static_assert(arraysize(kPermissionButtonTextIDPolicyManaged) ==
+                  CONTENT_SETTING_NUM_SETTINGS,
+              "kPermissionButtonTextIDPolicyManaged array size is incorrect");
+
+// The resource IDs for the strings that are displayed on the permissions
+// button if the permission setting is managed by an extension.
+const int kPermissionButtonTextIDExtensionManaged[] = {
+    kInvalidResourceID,
+    IDS_PAGE_INFO_PERMISSION_ALLOWED_BY_EXTENSION,
+    IDS_PAGE_INFO_PERMISSION_BLOCKED_BY_EXTENSION,
+    IDS_PAGE_INFO_PERMISSION_ASK_BY_EXTENSION,
+    kInvalidResourceID,
+    kInvalidResourceID};
+static_assert(arraysize(kPermissionButtonTextIDExtensionManaged) ==
+                  CONTENT_SETTING_NUM_SETTINGS,
+              "kPermissionButtonTextIDExtensionManaged array size is "
+              "incorrect");
+
+// The resource IDs for the strings that are displayed on the permissions
 // button if the permission setting is managed by the user.
 const int kPermissionButtonTextIDUserManaged[] = {
     kInvalidResourceID,
@@ -104,6 +131,34 @@
   security_description->details = l10n_util::GetStringUTF16(details_id);
   return security_description;
 }
+
+// Gets the actual setting for a ContentSettingType, taking into account what
+// the default setting value is and whether Html5ByDefault is enabled.
+ContentSetting GetEffectiveSetting(Profile* profile,
+                                   ContentSettingsType type,
+                                   ContentSetting setting,
+                                   ContentSetting default_setting) {
+  ContentSetting effective_setting = setting;
+  if (effective_setting == CONTENT_SETTING_DEFAULT)
+    effective_setting = default_setting;
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+  HostContentSettingsMap* host_content_settings_map =
+      HostContentSettingsMapFactory::GetForProfile(profile);
+  effective_setting = PluginsFieldTrial::EffectiveContentSetting(
+      host_content_settings_map, type, effective_setting);
+
+  // Display the UI string for ASK instead of DETECT for HTML5 by Default.
+  // TODO(tommycli): Once HTML5 by Default is shipped and the feature flag
+  // is removed, just migrate the actual content setting to ASK.
+  if (PluginUtils::ShouldPreferHtmlOverPlugins(host_content_settings_map) &&
+      effective_setting == CONTENT_SETTING_DETECT_IMPORTANT_CONTENT) {
+    effective_setting = CONTENT_SETTING_ASK;
+  }
+#endif
+  return effective_setting;
+}
+
 }  // namespace
 
 PageInfoUI::CookieInfo::CookieInfo() : allowed(-1), blocked(-1) {}
@@ -215,25 +270,8 @@
     ContentSetting setting,
     ContentSetting default_setting,
     content_settings::SettingSource source) {
-  ContentSetting effective_setting = setting;
-  if (effective_setting == CONTENT_SETTING_DEFAULT)
-    effective_setting = default_setting;
-
-#if BUILDFLAG(ENABLE_PLUGINS)
-  HostContentSettingsMap* host_content_settings_map =
-      HostContentSettingsMapFactory::GetForProfile(profile);
-  effective_setting = PluginsFieldTrial::EffectiveContentSetting(
-      host_content_settings_map, type, effective_setting);
-
-  // Display the UI string for ASK instead of DETECT for HTML5 by Default.
-  // TODO(tommycli): Once HTML5 by Default is shipped and the feature flag
-  // is removed, just migrate the actual content setting to ASK.
-  if (PluginUtils::ShouldPreferHtmlOverPlugins(host_content_settings_map) &&
-      effective_setting == CONTENT_SETTING_DETECT_IMPORTANT_CONTENT) {
-    effective_setting = CONTENT_SETTING_ASK;
-  }
-#endif
-
+  ContentSetting effective_setting =
+      GetEffectiveSetting(profile, type, setting, default_setting);
   const int* button_text_ids = NULL;
   switch (source) {
     case content_settings::SETTING_SOURCE_USER:
@@ -274,13 +312,15 @@
     Profile* profile,
     const PageInfoUI::PermissionInfo& permission,
     const GURL& url) {
+  ContentSetting effective_setting = GetEffectiveSetting(
+      profile, permission.type, permission.setting, permission.default_setting);
   int message_id = kInvalidResourceID;
   switch (permission.source) {
     case content_settings::SettingSource::SETTING_SOURCE_POLICY:
-      message_id = IDS_PAGE_INFO_PERMISSION_SET_BY_POLICY;
+      message_id = kPermissionButtonTextIDPolicyManaged[effective_setting];
       break;
     case content_settings::SettingSource::SETTING_SOURCE_EXTENSION:
-      message_id = IDS_PAGE_INFO_PERMISSION_SET_BY_EXTENSION;
+      message_id = kPermissionButtonTextIDExtensionManaged[effective_setting];
       break;
     default:
       break;
diff --git a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
index 5d18b07..b731c917 100644
--- a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
+++ b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
@@ -355,7 +355,7 @@
   custom_search_type_match.keyword = ASCIIToUTF16("k");
   custom_search_type_match.destination_url =
       GURL("https://www.dummyurl.com/search?q=fan&img=1");
-  TemplateURL* template_url =
+  const TemplateURL* template_url =
       custom_search_type_match.GetTemplateURL(service, false);
   EXPECT_TRUE(template_url);
   EXPECT_TRUE(AutocompleteMatch::IsSearchType(custom_search_type_match.type));
diff --git a/chrome/browser/ui/search_engines/edit_search_engine_controller.cc b/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
index 9fa6623..d61e7e2 100644
--- a/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
+++ b/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
@@ -88,7 +88,7 @@
 
   TemplateURLService* template_url_service =
       TemplateURLServiceFactory::GetForProfile(profile_);
-  TemplateURL* existing =
+  const TemplateURL* existing =
       template_url_service->GetTemplateURLForKeyword(keyword_input);
   if (existing && (!edit_keyword_delegate_ || existing != template_url_)) {
     // An entry may have been added with the same keyword string while the
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index e9e51b13..6a5d7f8 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -69,6 +69,7 @@
 
 // When true, this means that error dialogs should not be shown.
 bool dialogs_are_suppressed_ = false;
+logging::ScopedLogAssertHandler* assert_handler_ = nullptr;
 
 // This should be true for exactly the period between the end of
 // InitChromeLogging() and the beginning of CleanupChromeLogging().
@@ -92,7 +93,10 @@
 // silenced.  To record a new error, pass the log string associated
 // with that error in the str parameter.
 MSVC_DISABLE_OPTIMIZE();
-void SilentRuntimeAssertHandler(const std::string& str) {
+void SilentRuntimeAssertHandler(const char* file,
+                                int line,
+                                const base::StringPiece message,
+                                const base::StringPiece stack_trace) {
   base::debug::BreakDebugger();
 }
 MSVC_ENABLE_OPTIMIZE();
@@ -103,7 +107,8 @@
   if (dialogs_are_suppressed_)
     return;
 
-  logging::SetLogAssertHandler(SilentRuntimeAssertHandler);
+  assert_handler_ = new logging::ScopedLogAssertHandler(
+      base::Bind(SilentRuntimeAssertHandler));
 
 #if defined(OS_WIN)
   UINT new_flags = SEM_FAILCRITICALERRORS |
diff --git a/chrome/test/data/webui/md_bookmarks/reducers_test.js b/chrome/test/data/webui/md_bookmarks/reducers_test.js
index fe66d9b3..1eb6e77 100644
--- a/chrome/test/data/webui/md_bookmarks/reducers_test.js
+++ b/chrome/test/data/webui/md_bookmarks/reducers_test.js
@@ -89,7 +89,7 @@
   });
 
   test('deselects items when they are deleted', function() {
-    var nodeList = testTree(createFolder('0', [
+    var nodeMap = testTree(createFolder('0', [
       createFolder(
           '1',
           [
@@ -103,7 +103,7 @@
     action = select(['2', '4', '5'], '4', false);
     selection = bookmarks.SelectionState.updateSelection(selection, action);
 
-    action = bookmarks.actions.removeBookmark('1', '0', 0, nodeList);
+    action = bookmarks.actions.removeBookmark('1', '0', 0, nodeMap);
     selection = bookmarks.SelectionState.updateSelection(selection, action);
 
     assertDeepEquals(['5'], normalizeSet(selection.items));
diff --git a/components/cdm/browser/media_drm_storage_impl.cc b/components/cdm/browser/media_drm_storage_impl.cc
index bcebc5a..800c6275 100644
--- a/components/cdm/browser/media_drm_storage_impl.cc
+++ b/components/cdm/browser/media_drm_storage_impl.cc
@@ -167,12 +167,18 @@
   base::DictionaryValue* origin_dict = nullptr;
   // The origin string may contain dots. Do not use path expansion.
   storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
+
+  // This could happen if the profile is removed, but the device is still
+  // provisioned for the origin. In this case, just create a new entry.
   if (!origin_dict) {
-    DVLOG(1) << __func__
-             << ": Failed to save persistent session data; entry for origin "
-             << origin_string_ << " does not exist.";
-    callback.Run(false);
-    return;
+
+    DVLOG(1) << __func__ << ": Entry for origin " << origin_string_
+             << " does not exist; create a new one.";
+    storage_dict->SetWithoutPathExpansion(origin_string_,
+                                          CreateOriginDictionary());
+    storage_dict->GetDictionaryWithoutPathExpansion(origin_string_,
+                                                    &origin_dict);
+    DCHECK(origin_dict);
   }
 
   base::DictionaryValue* sessions_dict = nullptr;
diff --git a/components/cdm/browser/media_drm_storage_impl_unittest.cc b/components/cdm/browser/media_drm_storage_impl_unittest.cc
index 6a1610e..daf0c8f6 100644
--- a/components/cdm/browser/media_drm_storage_impl_unittest.cc
+++ b/components/cdm/browser/media_drm_storage_impl_unittest.cc
@@ -143,7 +143,7 @@
 }
 
 TEST_F(MediaDrmStorageImplTest, SaveSession_Unprovisioned) {
-  SavePersistentSession("session_id", {1, 0}, "mime/type", false);
+  SaveAndLoadPersistentSession("session_id", {1, 0}, "mime/type1");
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
index 4e5dcf9c..3bbfb38c 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -33,6 +33,7 @@
 #include "net/proxy/proxy_info.h"
 #include "net/proxy/proxy_retry_info.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_test_util.h"
@@ -110,8 +111,9 @@
   std::unique_ptr<net::URLRequest> CreateRequest(
       bool is_main_frame,
       content::PreviewsState previews_state) {
-    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
-        GURL("http://www.google.com/"), net::IDLE, &delegate_);
+    std::unique_ptr<net::URLRequest> request =
+        context_.CreateRequest(GURL("http://www.google.com/"), net::IDLE,
+                               &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
     AllocateRequestInfoForTesting(
         request.get(),
         (is_main_frame ? content::RESOURCE_TYPE_MAIN_FRAME
@@ -124,10 +126,10 @@
       content::ResourceType resource_type,
       bool scheme_is_https,
       content::PreviewsState previews_state) {
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(GURL(scheme_is_https ? "https://www.google.com/"
-                                                    : "http://www.google.com/"),
-                               net::IDLE, &delegate_);
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        GURL(scheme_is_https ? "https://www.google.com/"
+                             : "http://www.google.com/"),
+        net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
     AllocateRequestInfoForTesting(request.get(), resource_type, previews_state);
     return request;
   }
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_ui_service_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_ui_service_unittest.cc
index e42be3d..52d6503 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_ui_service_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_ui_service_unittest.cc
@@ -20,6 +20,7 @@
 #include "content/public/common/previews_state.h"
 #include "content/public/test/test_renderer_host.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -66,8 +67,9 @@
     EXPECT_TRUE(
         content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
 
-    std::unique_ptr<net::URLRequest> request = context.CreateRequest(
-        GURL("http://www.google.com/"), net::IDLE, delegate);
+    std::unique_ptr<net::URLRequest> request =
+        context.CreateRequest(GURL("http://www.google.com/"), net::IDLE,
+                              delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
 
     content::ResourceRequestInfo::AllocateForTesting(
         request.get(), content::RESOURCE_TYPE_SUB_FRAME, NULL,
diff --git a/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc b/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc
index 099aab5..1c65f26 100644
--- a/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/common/previews_state.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_test_util.h"
@@ -109,8 +110,8 @@
   std::unique_ptr<net::URLRequest> CreateRequestByType(
       const GURL& gurl,
       content::ResourceType resource_type) {
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(gurl, net::IDLE, &delegate_);
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        gurl, net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
     AllocateRequestInfoForTesting(request.get(), resource_type);
     return request;
   }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
index e44a9c2..f083a5b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -37,6 +37,7 @@
 #include "net/proxy/proxy_server.h"
 #include "net/proxy/proxy_service.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/static_http_user_agent_settings.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
@@ -237,7 +238,8 @@
         network_delegate_->headers_received_count();
     TestDelegate d;
     std::unique_ptr<URLRequest> r(context_->CreateRequest(
-        GURL("http://www.google.com/"), net::DEFAULT_PRIORITY, &d));
+        GURL("http://www.google.com/"), net::DEFAULT_PRIORITY, &d,
+        TRAFFIC_ANNOTATION_FOR_TESTS));
     r->set_method(method);
     r->SetLoadFlags(net::LOAD_NORMAL);
 
@@ -340,7 +342,8 @@
   };
   for (size_t i = 0; i < arraysize(tests); ++i) {
     std::unique_ptr<net::URLRequest> request(context.CreateRequest(
-        GURL("http://www.google.com/"), net::DEFAULT_PRIORITY, NULL));
+        GURL("http://www.google.com/"), net::DEFAULT_PRIORITY, NULL,
+        TRAFFIC_ANNOTATION_FOR_TESTS));
     request->set_method(tests[i].method);
     EXPECT_EQ(tests[i].expected_result,
               util::IsMethodIdempotent(request->method()));
@@ -876,8 +879,9 @@
       mock_socket_factory()->AddSocketDataProvider(&retry_socket);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> url_request(context()->CreateRequest(
-        GURL("http://www.google.com"), net::IDLE, &delegate));
+    std::unique_ptr<net::URLRequest> url_request(
+        context()->CreateRequest(GURL("http://www.google.com"), net::IDLE,
+                                 &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
     url_request->Start();
     drp_test_context()->RunUntilIdle();
 
@@ -935,8 +939,9 @@
 
     base::HistogramTester histogram_tester;
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request(context()->CreateRequest(
-        GURL("http://google.com"), net::IDLE, &delegate));
+    std::unique_ptr<net::URLRequest> request(
+        context()->CreateRequest(GURL("http://google.com"), net::IDLE,
+                                 &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
     request->Start();
     drp_test_context()->RunUntilIdle();
 
@@ -971,7 +976,8 @@
 
   TestDelegate d;
   std::unique_ptr<URLRequest> r(context_->CreateRequest(
-      GURL("http://www.google.com/"), net::DEFAULT_PRIORITY, &d));
+      GURL("http://www.google.com/"), net::DEFAULT_PRIORITY, &d,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
   r->set_method("GET");
   r->SetLoadFlags(net::LOAD_NORMAL);
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
index cd7ddb4..c8922c5 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -40,6 +40,7 @@
 #include "net/http/http_util.h"
 #include "net/proxy/proxy_server.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_context_storage.h"
@@ -80,14 +81,15 @@
 
     test_context_ =
         DataReductionProxyTestContext::Builder().WithMockConfig().Build();
-    mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_);
+    mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_,
+                                               TRAFFIC_ANNOTATION_FOR_TESTS);
   }
 
   std::unique_ptr<net::URLRequest> CreateURLRequestWithResponseHeaders(
       const GURL& url,
       const std::string& response_headers) {
-    std::unique_ptr<net::URLRequest> fake_request =
-        context_.CreateRequest(url, net::IDLE, &delegate_);
+    std::unique_ptr<net::URLRequest> fake_request = context_.CreateRequest(
+        url, net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
 
     // Create a test job that will fill in the given response headers for the
     // |fake_request|.
@@ -326,8 +328,8 @@
           retry_socket_data_provider.get());
     }
 
-    std::unique_ptr<net::URLRequest> request(
-        context_.CreateRequest(url, net::IDLE, &delegate_));
+    std::unique_ptr<net::URLRequest> request(context_.CreateRequest(
+        url, net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
     request->set_method("GET");
     request->SetLoadFlags(load_flags);
     request->Start();
@@ -385,7 +387,8 @@
     mock_socket_factory_.AddSocketDataProvider(&response_socket_data_provider);
 
     std::unique_ptr<net::URLRequest> request(
-        context_.CreateRequest(GURL("http://foo.com"), net::IDLE, &delegate_));
+        context_.CreateRequest(GURL("http://foo.com"), net::IDLE, &delegate_,
+                               TRAFFIC_ANNOTATION_FOR_TESTS));
     request->set_method("GET");
     request->Start();
     drp_test_context_->RunUntilIdle();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index 1a5cffc..f301943 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -35,6 +35,7 @@
 #include "net/http/http_response_headers.h"
 #include "net/proxy/proxy_server.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request_context_storage.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -1091,8 +1092,9 @@
     net::TestDelegate test_delegate;
 
     std::unique_ptr<net::URLRequest> request(
-        test_url_request_context()->CreateRequest(GURL(tests[i].url), net::IDLE,
-                                                  &test_delegate));
+        test_url_request_context()->CreateRequest(
+            GURL(tests[i].url), net::IDLE, &test_delegate,
+            TRAFFIC_ANNOTATION_FOR_TESTS));
     request->Start();
     RunUntilIdle();
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index f70b5e70..2b55df8b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -49,6 +49,7 @@
 #include "net/nqe/network_quality_estimator_test_util.h"
 #include "net/proxy/proxy_server.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request.h"
@@ -916,8 +917,8 @@
     base::HistogramTester histogram_tester;
     net::TestURLRequestContext context_;
     net::TestDelegate delegate_;
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(GURL(), net::IDLE, &delegate_);
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        GURL(), net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
     request->SetLoadFlags(request->load_flags() |
                           net::LOAD_MAIN_FRAME_DEPRECATED);
     bool should_enable_lofi = config()->ShouldEnableLoFi(*request.get());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
index 4ace1e8..5ee76c7 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/message_loop/message_loop.h"
 #include "net/base/request_priority.h"
 #include "net/nqe/effective_connection_type.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -65,7 +66,8 @@
 TEST_F(DataReductionProxyDataTest, AddToURLRequest) {
   std::unique_ptr<net::URLRequestContext> context(new net::URLRequestContext());
   std::unique_ptr<net::URLRequest> fake_request(context->CreateRequest(
-      GURL("http://www.google.com"), net::RequestPriority::IDLE, nullptr));
+      GURL("http://www.google.com"), net::RequestPriority::IDLE, nullptr,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
   DataReductionProxyData* data =
       DataReductionProxyData::GetData(*fake_request.get());
   EXPECT_FALSE(data);
@@ -122,7 +124,8 @@
 TEST_F(DataReductionProxyDataTest, ClearData) {
   std::unique_ptr<net::URLRequestContext> context(new net::URLRequestContext());
   std::unique_ptr<net::URLRequest> fake_request(context->CreateRequest(
-      GURL("http://www.google.com"), net::RequestPriority::IDLE, nullptr));
+      GURL("http://www.google.com"), net::RequestPriority::IDLE, nullptr,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
 
   DataReductionProxyData* data =
       DataReductionProxyData::GetDataAndCreateIfNecessary(fake_request.get());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
index f7a2306..0969234 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -51,6 +51,7 @@
 #include "net/proxy/proxy_config.h"
 #include "net/proxy/proxy_server.h"
 #include "net/socket/socket_test_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -658,8 +659,8 @@
     mock_socket_factory_.AddSocketDataProvider(&socket);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(url, net::IDLE, &delegate);
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        url, net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     if (request_headers)
       request->SetExtraRequestHeaders(*request_headers);
 
@@ -1037,8 +1038,9 @@
   mock_socket_factory()->AddSocketDataProvider(&socket);
 
   net::TestDelegate delegate;
-  std::unique_ptr<net::URLRequest> request = context()->CreateRequest(
-      GURL("http://example.com/path/"), net::IDLE, &delegate);
+  std::unique_ptr<net::URLRequest> request =
+      context()->CreateRequest(GURL("http://example.com/path/"), net::IDLE,
+                               &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
   request->Start();
   base::RunLoop().RunUntilIdle();
 
@@ -1058,8 +1060,9 @@
   mock_socket_factory()->AddSocketDataProvider(&socket);
 
   net::TestDelegate delegate;
-  std::unique_ptr<net::URLRequest> request = context()->CreateRequest(
-      GURL("http://example.com/path/"), net::IDLE, &delegate);
+  std::unique_ptr<net::URLRequest> request =
+      context()->CreateRequest(GURL("http://example.com/path/"), net::IDLE,
+                               &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
   request->Start();
   base::RunLoop().RunUntilIdle();
 
@@ -1150,8 +1153,9 @@
     mock_socket_factory()->AddSocketDataProvider(&socket);
 
     net::TestDelegate test_delegate;
-    std::unique_ptr<net::URLRequest> request = context()->CreateRequest(
-        GURL("http://example.com"), net::IDLE, &test_delegate);
+    std::unique_ptr<net::URLRequest> request =
+        context()->CreateRequest(GURL("http://example.com"), net::IDLE,
+                                 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     request->Start();
 
     base::RunLoop().RunUntilIdle();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
index 4d8f088..4497aeb 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -32,6 +32,7 @@
 #include "net/proxy/proxy_server.h"
 #include "net/socket/socket_test_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context_storage.h"
 #include "net/url_request/url_request_intercepting_job_factory.h"
@@ -172,8 +173,9 @@
   Init(std::move(factory1));
 
   net::TestDelegate d;
-  std::unique_ptr<net::URLRequest> req(default_context_->CreateRequest(
-      GURL("http://foo"), net::DEFAULT_PRIORITY, &d));
+  std::unique_ptr<net::URLRequest> req(
+      default_context_->CreateRequest(GURL("http://foo"), net::DEFAULT_PRIORITY,
+                                      &d, TRAFFIC_ANNOTATION_FOR_TESTS));
 
   req->Start();
   base::RunLoop().Run();
@@ -262,7 +264,8 @@
   // DataReductionProxyProtocolTest.
   net::TestDelegate delegate;
   std::unique_ptr<net::URLRequest> request(context().CreateRequest(
-      direct().GetURL("/block10.html"), net::DEFAULT_PRIORITY, &delegate));
+      direct().GetURL("/block10.html"), net::DEFAULT_PRIORITY, &delegate,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
   request->Start();
   EXPECT_TRUE(request->is_pending());
   base::RunLoop().Run();
@@ -274,7 +277,8 @@
 TEST_F(DataReductionProxyInterceptorWithServerTest, TestNoBypass) {
   net::TestDelegate delegate;
   std::unique_ptr<net::URLRequest> request(context().CreateRequest(
-      direct().GetURL("/noblock.html"), net::DEFAULT_PRIORITY, &delegate));
+      direct().GetURL("/noblock.html"), net::DEFAULT_PRIORITY, &delegate,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
   request->Start();
   EXPECT_TRUE(request->is_pending());
   base::RunLoop().Run();
@@ -312,8 +316,8 @@
   // Creates a URLRequest using the test's TestURLRequestContext and executes
   // it. Returns the created URLRequest.
   std::unique_ptr<net::URLRequest> CreateAndExecuteRequest(const GURL& url) {
-    std::unique_ptr<net::URLRequest> request(
-        context_.CreateRequest(url, net::IDLE, &delegate_));
+    std::unique_ptr<net::URLRequest> request(context_.CreateRequest(
+        url, net::IDLE, &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
     request->Start();
     drp_test_context_->RunUntilIdle();
     return request;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index 7b09403..67deac59 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -27,6 +27,7 @@
 #include "net/log/net_log_with_source.h"
 #include "net/proxy/proxy_info.h"
 #include "net/proxy/proxy_service.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_interceptor.h"
@@ -123,8 +124,9 @@
   // When creating a network delegate, expect that it properly wraps a
   // network delegate. Such a network delegate is thoroughly tested by
   // DataReductionProxyNetworkDelegateTest.
-  std::unique_ptr<net::URLRequest> fake_request = context().CreateRequest(
-      GURL("http://www.foo.com/"), net::IDLE, delegate());
+  std::unique_ptr<net::URLRequest> fake_request =
+      context().CreateRequest(GURL("http://www.foo.com/"), net::IDLE,
+                              delegate(), TRAFFIC_ANNOTATION_FOR_TESTS);
   CountingNetworkDelegate* wrapped_network_delegate =
       new CountingNetworkDelegate();
   std::unique_ptr<DataReductionProxyNetworkDelegate> network_delegate =
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 756102e..00a4da1f 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -57,6 +57,7 @@
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_data_directory.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job_factory_impl.h"
 #include "net/url_request/url_request_status.h"
@@ -320,8 +321,8 @@
     mock_socket_factory_.AddSocketDataProvider(&socket);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(url, net::IDLE, &delegate);
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        url, net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     if (request_headers)
       request->SetExtraRequestHeaders(*request_headers);
     request->SetLoadFlags(request->load_flags() | load_flags);
@@ -429,8 +430,8 @@
     mock_socket_factory_.AddSocketDataProvider(&socket);
 
     net::TestDelegate delegate;
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(url, net::IDLE, &delegate);
+    std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+        url, net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
     if (request_headers)
       request->SetExtraRequestHeaders(*request_headers);
 
@@ -706,8 +707,8 @@
       net::ProxyRetryInfoMap proxy_retry_info;
 
       net::TestDelegate delegate;
-      std::unique_ptr<net::URLRequest> fake_request =
-          context()->CreateRequest(GURL(kTestURL), net::IDLE, &delegate);
+      std::unique_ptr<net::URLRequest> fake_request = context()->CreateRequest(
+          GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
       fake_request->SetLoadFlags(net::LOAD_MAIN_FRAME_DEPRECATED);
       lofi_decider()->SetIsUsingLoFi(
           config()->ShouldEnableLoFi(*fake_request.get()));
@@ -725,8 +726,8 @@
       net::HttpRequestHeaders headers;
       net::ProxyRetryInfoMap proxy_retry_info;
       net::TestDelegate delegate;
-      std::unique_ptr<net::URLRequest> fake_request =
-          context()->CreateRequest(GURL(kTestURL), net::IDLE, &delegate);
+      std::unique_ptr<net::URLRequest> fake_request = context()->CreateRequest(
+          GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
       lofi_decider()->SetIsUsingLoFi(false);
       NotifyNetworkDelegate(fake_request.get(), data_reduction_proxy_info,
                             proxy_retry_info, &headers);
@@ -740,8 +741,8 @@
       net::HttpRequestHeaders headers;
       net::ProxyRetryInfoMap proxy_retry_info;
       net::TestDelegate delegate;
-      std::unique_ptr<net::URLRequest> fake_request =
-          context()->CreateRequest(GURL(kTestURL), net::IDLE, &delegate);
+      std::unique_ptr<net::URLRequest> fake_request = context()->CreateRequest(
+          GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
 
       lofi_decider()->SetIsUsingLoFi(true);
       NotifyNetworkDelegate(fake_request.get(), data_reduction_proxy_info,
@@ -757,8 +758,8 @@
       net::HttpRequestHeaders headers;
       net::ProxyRetryInfoMap proxy_retry_info;
       net::TestDelegate delegate;
-      std::unique_ptr<net::URLRequest> fake_request =
-          context()->CreateRequest(GURL(kTestURL), net::IDLE, &delegate);
+      std::unique_ptr<net::URLRequest> fake_request = context()->CreateRequest(
+          GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
       fake_request->SetLoadFlags(net::LOAD_MAIN_FRAME_DEPRECATED);
       lofi_decider()->SetIsUsingLoFi(false);
       NotifyNetworkDelegate(fake_request.get(), data_reduction_proxy_info,
@@ -773,8 +774,8 @@
       net::HttpRequestHeaders headers;
       net::ProxyRetryInfoMap proxy_retry_info;
       net::TestDelegate delegate;
-      std::unique_ptr<net::URLRequest> fake_request =
-          context()->CreateRequest(GURL(kTestURL), net::IDLE, &delegate);
+      std::unique_ptr<net::URLRequest> fake_request = context()->CreateRequest(
+          GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
       lofi_decider()->SetIsUsingLoFi(false);
       NotifyNetworkDelegate(fake_request.get(), data_reduction_proxy_info,
                             proxy_retry_info, &headers);
@@ -788,8 +789,8 @@
       net::HttpRequestHeaders headers;
       net::ProxyRetryInfoMap proxy_retry_info;
       net::TestDelegate delegate;
-      std::unique_ptr<net::URLRequest> fake_request =
-          context()->CreateRequest(GURL(kTestURL), net::IDLE, &delegate);
+      std::unique_ptr<net::URLRequest> fake_request = context()->CreateRequest(
+          GURL(kTestURL), net::IDLE, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
       fake_request->SetLoadFlags(net::LOAD_MAIN_FRAME_DEPRECATED);
       lofi_decider()->SetIsUsingLoFi(
           config()->ShouldEnableLoFi(*fake_request.get()));
@@ -844,8 +845,9 @@
     test_network_quality_estimator()->set_effective_connection_type(
         net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
 
-    std::unique_ptr<net::URLRequest> request = context()->CreateRequest(
-        GURL(kTestURL), net::RequestPriority::IDLE, nullptr);
+    std::unique_ptr<net::URLRequest> request =
+        context()->CreateRequest(GURL(kTestURL), net::RequestPriority::IDLE,
+                                 nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
     request->SetLoadFlags(test.main_frame ? net::LOAD_MAIN_FRAME_DEPRECATED
                                           : 0);
     lofi_decider()->SetIsUsingLoFi(test.lofi_on);
@@ -907,8 +909,9 @@
     else
       data_reduction_proxy_info.UseNamedProxy("some.other.proxy");
     config()->UpdateConfigForTesting(test.data_reduction_proxy_enabled, true);
-    std::unique_ptr<net::URLRequest> request = context()->CreateRequest(
-        GURL(kTestURL), net::RequestPriority::IDLE, nullptr);
+    std::unique_ptr<net::URLRequest> request =
+        context()->CreateRequest(GURL(kTestURL), net::RequestPriority::IDLE,
+                                 nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
     request->set_method("GET");
     net::HttpRequestHeaders headers;
     net::ProxyRetryInfoMap proxy_retry_info;
@@ -939,8 +942,9 @@
   test_network_quality_estimator()->set_effective_connection_type(
       net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
 
-  std::unique_ptr<net::URLRequest> request = context()->CreateRequest(
-      GURL(kTestURL), net::RequestPriority::IDLE, nullptr);
+  std::unique_ptr<net::URLRequest> request =
+      context()->CreateRequest(GURL(kTestURL), net::RequestPriority::IDLE,
+                               nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
   request->SetLoadFlags(net::LOAD_MAIN_FRAME_DEPRECATED);
   lofi_decider()->SetIsUsingLoFi(true);
   io_data()->request_options()->SetSecureSession("fake-session");
diff --git a/components/favicon/core/favicon_handler.cc b/components/favicon/core/favicon_handler.cc
index 9ecda9b5..99c97ab7 100644
--- a/components/favicon/core/favicon_handler.cc
+++ b/components/favicon/core/favicon_handler.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "components/favicon/core/favicon_service.h"
 #include "components/favicon_base/favicon_util.h"
@@ -59,6 +60,30 @@
   return bitmap_result.is_valid();
 }
 
+void RecordDownloadAttemptsForHandlerType(
+    FaviconDriverObserver::NotificationIconType handler_type,
+    int attempts) {
+  // If not at least one attempts was recorded or more than 15 attempts were
+  // registered, something went wrong. Underflows are stored in bucket 0 and
+  // overflows in bucket 16.
+  attempts = std::max(0, std::min(attempts, 16));
+  switch (handler_type) {
+    case FaviconDriverObserver::NON_TOUCH_16_DIP:
+      UMA_HISTOGRAM_SPARSE_SLOWLY("Favicons.DownloadAttempts.Favicons",
+                                  attempts);
+      return;
+    case FaviconDriverObserver::NON_TOUCH_LARGEST:
+      UMA_HISTOGRAM_SPARSE_SLOWLY("Favicons.DownloadAttempts.LargeIcons",
+                                  attempts);
+      return;
+    case FaviconDriverObserver::TOUCH_LARGEST:
+      UMA_HISTOGRAM_SPARSE_SLOWLY("Favicons.DownloadAttempts.TouchIcons",
+                                  attempts);
+      return;
+  }
+  NOTREACHED();
+}
+
 // Returns true if |bitmap_results| is non-empty and:
 // - At least one of the bitmaps in |bitmap_results| is expired
 // OR
@@ -167,6 +192,7 @@
       notification_icon_type_(favicon_base::INVALID_ICON),
       service_(service),
       delegate_(delegate),
+      num_download_requests_(0),
       current_candidate_index_(0u) {
   DCHECK(delegate_);
 }
@@ -199,6 +225,7 @@
   candidates_.clear();
   notification_icon_url_ = GURL();
   notification_icon_type_ = favicon_base::INVALID_ICON;
+  num_download_requests_ = 0;
   current_candidate_index_ = 0u;
   best_favicon_ = DownloadedFavicon();
 
@@ -308,6 +335,7 @@
 
   download_request_.Cancel();
   candidates_ = std::move(sorted_candidates);
+  num_download_requests_ = 0;
   current_candidate_index_ = 0u;
   best_favicon_ = DownloadedFavicon();
 
@@ -395,6 +423,9 @@
     ++current_candidate_index_;
     DownloadCurrentCandidateOrAskFaviconService();
   } else {
+    // OnDidDownloadFavicon() can only be called after requesting a download, so
+    // |num_download_requests_| can never be 0.
+    RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_);
     // We have either found the ideal candidate or run out of candidates.
     if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) {
       // No more icons to request, set the favicon from the candidate.
@@ -403,6 +434,7 @@
     }
     // Clear download related state.
     current_candidate_index_ = candidates_.size();
+    num_download_requests_ = 0;
     best_favicon_ = DownloadedFavicon();
   }
 }
@@ -513,6 +545,8 @@
   if (has_expired_or_incomplete_result) {
     ScheduleDownload(current_candidate()->icon_url,
                      current_candidate()->icon_type);
+  } else if (num_download_requests_ > 0) {
+    RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_);
   }
 }
 
@@ -527,6 +561,7 @@
                          std::vector<gfx::Size>());
     return;
   }
+  ++num_download_requests_;
   download_request_.Reset(base::Bind(&FaviconHandler::OnDidDownloadFavicon,
                                      base::Unretained(this), icon_type));
   // A max bitmap size is specified to avoid receiving huge bitmaps in
diff --git a/components/favicon/core/favicon_handler.h b/components/favicon/core/favicon_handler.h
index 9105723c..24d849e0 100644
--- a/components/favicon/core/favicon_handler.h
+++ b/components/favicon/core/favicon_handler.h
@@ -290,6 +290,10 @@
   // This handler's delegate.
   Delegate* delegate_;
 
+  // Captures the number of download requests that were initiated for the
+  // current url_.
+  int num_download_requests_;
+
   // The index of the favicon URL in |image_urls_| which is currently being
   // requested from history or downloaded.
   size_t current_candidate_index_;
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc
index 5e651a64..e855508 100644
--- a/components/favicon/core/favicon_handler_unittest.cc
+++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/histogram_tester.h"
 #include "components/favicon/core/favicon_driver.h"
 #include "components/favicon/core/test/mock_favicon_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -78,20 +79,21 @@
 std::vector<FaviconRawBitmapResult> CreateRawBitmapResult(
     const GURL& icon_url,
     favicon_base::IconType icon_type = FAVICON,
-    bool expired = false) {
+    bool expired = false,
+    int edge_size = gfx::kFaviconSize) {
   scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
-  data->data() = FillBitmapWithEdgeSize(gfx::kFaviconSize);
+  data->data() = FillBitmapWithEdgeSize(edge_size);
   FaviconRawBitmapResult bitmap_result;
   bitmap_result.expired = expired;
   bitmap_result.bitmap_data = data;
   // Use a pixel size other than (0,0) as (0,0) has a special meaning.
-  bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
+  bitmap_result.pixel_size = gfx::Size(edge_size, edge_size);
   bitmap_result.icon_type = icon_type;
   bitmap_result.icon_url = icon_url;
   return {bitmap_result};
 }
 
-// Fake that implements the calls to FaviconHalder::Delegate's DownloadImage(),
+// Fake that implements the calls to FaviconHandler::Delegate's DownloadImage(),
 // delegated to this class through MockDelegate.
 class FakeImageDownloader {
  public:
@@ -382,6 +384,7 @@
 };
 
 TEST_F(FaviconHandlerTest, GetFaviconFromHistory) {
+  base::HistogramTester histogram_tester;
   const GURL kIconURL("http://www.google.com/favicon");
 
   favicon_service_.fake()->Store(kPageURL, kIconURL,
@@ -393,6 +396,12 @@
 
   RunHandlerWithSimpleFaviconCandidates({kIconURL});
   EXPECT_THAT(delegate_.downloads(), IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.LargeIcons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      IsEmpty());
 }
 
 // Test that UpdateFaviconsAndFetch() is called with the appropriate parameters
@@ -535,15 +544,12 @@
 // - The icon is redownloaded.
 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) {
   // Set non empty but invalid data.
-  FaviconRawBitmapResult bitmap_result;
-  bitmap_result.expired = false;
+  std::vector<FaviconRawBitmapResult> bitmap_result =
+      CreateRawBitmapResult(kIconURL16x16);
   // Empty bitmap data is invalid.
-  bitmap_result.bitmap_data = new base::RefCountedBytes();
-  bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
-  bitmap_result.icon_type = FAVICON;
-  bitmap_result.icon_url = kIconURL16x16;
+  bitmap_result[0].bitmap_data = new base::RefCountedBytes();
 
-  favicon_service_.fake()->Store(kPageURL, kIconURL16x16, {bitmap_result});
+  favicon_service_.fake()->Store(kPageURL, kIconURL16x16, bitmap_result);
 
   // TODO(crbug.com/700811): It would be nice if we could check the image
   // being published to rule out invalid data.
@@ -1031,5 +1037,116 @@
        FaviconURL(kIconURL16x16, FAVICON, kEmptySizes)});
 }
 
+TEST_F(FaviconHandlerTest, TestRecordMultipleDownloadAttempts) {
+  base::HistogramTester histogram_tester;
+
+  // Try to download the three failing icons and end up logging three attempts.
+  RunHandlerWithCandidates(
+      FaviconDriverObserver::NON_TOUCH_LARGEST,
+      {FaviconURL(GURL("http://www.google.com/a"), FAVICON, kEmptySizes),
+       FaviconURL(GURL("http://www.google.com/b"), FAVICON, kEmptySizes),
+       FaviconURL(GURL("http://www.google.com/c"), FAVICON, kEmptySizes)});
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.LargeIcons"),
+      ElementsAre(base::Bucket(/*sample=*/3, /*expected_count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.TouchIcons"),
+      IsEmpty());
+}
+
+TEST_F(FaviconHandlerTest, TestRecordSingleFaviconDownloadAttempt) {
+  base::HistogramTester histogram_tester;
+
+  RunHandlerWithSimpleFaviconCandidates({kIconURL16x16});
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      ElementsAre(base::Bucket(/*sample=*/1, /*expected_count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.LargeIcons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.TouchIcons"),
+      IsEmpty());
+}
+
+TEST_F(FaviconHandlerTest, TestRecordSingleLargeIconDownloadAttempt) {
+  base::HistogramTester histogram_tester;
+
+  RunHandlerWithCandidates(FaviconDriverObserver::NON_TOUCH_LARGEST,
+                           {FaviconURL(kIconURL64x64, FAVICON, kEmptySizes)});
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.LargeIcons"),
+      ElementsAre(base::Bucket(/*sample=*/1, /*expected_count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.TouchIcons"),
+      IsEmpty());
+}
+
+TEST_F(FaviconHandlerTest, TestRecordSingleTouchIconDownloadAttempt) {
+  base::HistogramTester histogram_tester;
+  RunHandlerWithCandidates(
+      FaviconDriverObserver::TOUCH_LARGEST,
+      {FaviconURL(kIconURL64x64, TOUCH_ICON, kEmptySizes)});
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.LargeIcons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.TouchIcons"),
+      ElementsAre(base::Bucket(/*sample=*/1, /*expected_count=*/1)));
+}
+
+TEST_F(FaviconHandlerTest, TestRecordDownloadAttemptsFinishedByCache) {
+  const GURL kIconURL1024x1024("http://www.google.com/a-404-ing-icon");
+  base::HistogramTester histogram_tester;
+  favicon_service_.fake()->Store(
+      GURL("http://so.de"), kIconURL64x64,
+      CreateRawBitmapResult(kIconURL64x64, FAVICON, /*expired=*/false, 64));
+
+  RunHandlerWithCandidates(
+      FaviconDriverObserver::NON_TOUCH_LARGEST,
+      {FaviconURL(kIconURL1024x1024, FAVICON, {gfx::Size(1024, 1024)}),
+       FaviconURL(kIconURL12x12, FAVICON, {gfx::Size(12, 12)}),
+       FaviconURL(kIconURL64x64, FAVICON, {gfx::Size(64, 64)})});
+
+  // Should try only the first (receive 404) and get second icon from cache.
+  EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL1024x1024));
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.LargeIcons"),
+      ElementsAre(base::Bucket(/*sample=*/1, /*expected_count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      IsEmpty());
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.TouchIcons"),
+      IsEmpty());
+}
+
+TEST_F(FaviconHandlerTest, TestRecordSingleDownloadAttemptForRefreshingIcons) {
+  base::HistogramTester histogram_tester;
+  favicon_service_.fake()->Store(
+      GURL("http://www.google.com/ps"), kIconURL16x16,
+      CreateRawBitmapResult(kIconURL16x16, FAVICON, /*expired=*/true));
+
+  RunHandlerWithSimpleFaviconCandidates({kIconURL16x16});
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("Favicons.DownloadAttempts.Favicons"),
+      ElementsAre(base::Bucket(/*sample=*/1, /*expected_count=*/1)));
+}
+
 }  // namespace
 }  // namespace favicon
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc
index a0432839..4bb6f77 100644
--- a/components/network_session_configurator/network_session_configurator.cc
+++ b/components/network_session_configurator/network_session_configurator.cc
@@ -134,12 +134,34 @@
   return net::ParseQuicConnectionOptions(it->second);
 }
 
+float GetQuicLoadServerInfoTimeoutSrttMultiplier(
+    const VariationParameters& quic_trial_params) {
+  double value;
+  if (base::StringToDouble(
+          GetVariationParam(quic_trial_params, "load_server_info_time_to_srtt"),
+          &value)) {
+    return static_cast<float>(value);
+  }
+  return 0.0f;
+}
+
+bool ShouldQuicEnableConnectionRacing(
+    const VariationParameters& quic_trial_params) {
+  return base::LowerCaseEqualsASCII(
+      GetVariationParam(quic_trial_params, "enable_connection_racing"), "true");
+}
+
 bool ShouldQuicEnableNonBlockingIO(
     const VariationParameters& quic_trial_params) {
   return base::LowerCaseEqualsASCII(
       GetVariationParam(quic_trial_params, "enable_non_blocking_io"), "true");
 }
 
+bool ShouldQuicDisableDiskCache(const VariationParameters& quic_trial_params) {
+  return base::LowerCaseEqualsASCII(
+      GetVariationParam(quic_trial_params, "disable_disk_cache"), "true");
+}
+
 bool ShouldForceHolBlocking(const VariationParameters& quic_trial_params) {
   return base::LowerCaseEqualsASCII(
       GetVariationParam(quic_trial_params, "force_hol_blocking"), "true");
@@ -273,8 +295,18 @@
       ShouldRetryWithoutAltSvcOnQuicErrors(quic_trial_params);
 
   if (params->enable_quic) {
+    float load_server_info_timeout_srtt_multiplier =
+        GetQuicLoadServerInfoTimeoutSrttMultiplier(quic_trial_params);
+    if (load_server_info_timeout_srtt_multiplier != 0) {
+      params->quic_load_server_info_timeout_srtt_multiplier =
+          load_server_info_timeout_srtt_multiplier;
+    }
+    params->quic_enable_connection_racing =
+        ShouldQuicEnableConnectionRacing(quic_trial_params);
     params->quic_enable_non_blocking_io =
         ShouldQuicEnableNonBlockingIO(quic_trial_params);
+    params->quic_disable_disk_cache =
+        ShouldQuicDisableDiskCache(quic_trial_params);
     params->quic_force_hol_blocking = ShouldForceHolBlocking(quic_trial_params);
     params->quic_connection_options =
         GetQuicConnectionOptions(quic_trial_params);
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc
index b9a21af..0a52ae01 100644
--- a/components/network_session_configurator/network_session_configurator_unittest.cc
+++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -70,8 +70,11 @@
   EXPECT_FALSE(params_.retry_without_alt_svc_on_quic_errors);
   EXPECT_EQ(1350u, params_.quic_max_packet_length);
   EXPECT_EQ(net::QuicTagVector(), params_.quic_connection_options);
+  EXPECT_EQ(0.25f, params_.quic_load_server_info_timeout_srtt_multiplier);
+  EXPECT_FALSE(params_.quic_enable_connection_racing);
   EXPECT_FALSE(params_.enable_server_push_cancellation);
   EXPECT_FALSE(params_.quic_enable_non_blocking_io);
+  EXPECT_FALSE(params_.quic_disable_disk_cache);
   EXPECT_FALSE(params_.quic_close_sessions_on_ip_change);
   EXPECT_EQ(net::kIdleConnectionTimeoutSeconds,
             params_.quic_idle_connection_timeout_seconds);
@@ -336,6 +339,29 @@
   EXPECT_EQ(expected_settings, params_.http2_settings);
 }
 
+TEST_F(NetworkSessionConfiguratorTest,
+       QuicLoadServerInfoTimeToSmoothedRttFromFieldTrialParams) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["load_server_info_time_to_srtt"] = "0.5";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  EXPECT_EQ(0.5f, params_.quic_load_server_info_timeout_srtt_multiplier);
+}
+
+TEST_F(NetworkSessionConfiguratorTest, QuicEnableConnectionRacing) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["enable_connection_racing"] = "true";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  EXPECT_TRUE(params_.quic_enable_connection_racing);
+}
+
 TEST_F(NetworkSessionConfiguratorTest, QuicEnableNonBlockingIO) {
   std::map<std::string, std::string> field_trial_params;
   field_trial_params["enable_non_blocking_io"] = "true";
@@ -347,6 +373,17 @@
   EXPECT_TRUE(params_.quic_enable_non_blocking_io);
 }
 
+TEST_F(NetworkSessionConfiguratorTest, QuicDisableDiskCache) {
+  std::map<std::string, std::string> field_trial_params;
+  field_trial_params["disable_disk_cache"] = "true";
+  variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+  base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+  ParseFieldTrials();
+
+  EXPECT_TRUE(params_.quic_disable_disk_cache);
+}
+
 TEST_F(NetworkSessionConfiguratorTest, TCPFastOpenHttpsEnabled) {
   base::FieldTrialList::CreateFieldTrial("TCPFastOpen", "HttpsEnabled");
 
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index bfc64f94..d251027 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -430,7 +430,7 @@
 void AutocompleteController::UpdateMatchDestinationURL(
     const TemplateURLRef::SearchTermsArgs& search_terms_args,
     AutocompleteMatch* match) const {
-  TemplateURL* template_url = match->GetTemplateURL(
+  const TemplateURL* template_url = match->GetTemplateURL(
       template_url_service_, false);
   if (!template_url)
     return;
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index 801b0d7..0056537 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -435,7 +435,7 @@
   // to eliminate cases like past search URLs from history that differ only
   // by some obscure query param from each other or from the search/keyword
   // provider matches.
-  TemplateURL* template_url = GetTemplateURLWithKeyword(
+  const TemplateURL* template_url = GetTemplateURLWithKeyword(
       template_url_service, keyword, stripped_destination_url.host());
   if (template_url != NULL &&
       template_url->SupportsReplacement(
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc
index 618c483..8a331e7 100644
--- a/components/omnibox/browser/base_search_provider.cc
+++ b/components/omnibox/browser/base_search_provider.cc
@@ -133,7 +133,7 @@
                    base::Unretained(this))));
   }
 
-  TemplateURL* template_url =
+  const TemplateURL* template_url =
       match.GetTemplateURL(client_->GetTemplateURLService(), false);
   // This may be NULL if the template corresponding to the keyword has been
   // deleted or there is no keyword set.
diff --git a/components/omnibox/browser/omnibox_client.cc b/components/omnibox/browser/omnibox_client.cc
index 7f85f44..0a9a332 100644
--- a/components/omnibox/browser/omnibox_client.cc
+++ b/components/omnibox/browser/omnibox_client.cc
@@ -73,7 +73,7 @@
 }
 
 bool OmniboxClient::ProcessExtensionKeyword(
-    TemplateURL* template_url,
+    const TemplateURL* template_url,
     const AutocompleteMatch& match,
     WindowOpenDisposition disposition,
     OmniboxNavigationObserver* observer) {
diff --git a/components/omnibox/browser/omnibox_client.h b/components/omnibox/browser/omnibox_client.h
index 4d8cf2b..6b516e95 100644
--- a/components/omnibox/browser/omnibox_client.h
+++ b/components/omnibox/browser/omnibox_client.h
@@ -97,7 +97,7 @@
   // that was created by CreateOmniboxNavigationObserver() for |match|; in some
   // embedding contexts, processing an extension keyword involves invoking
   // action on this observer.
-  virtual bool ProcessExtensionKeyword(TemplateURL* template_url,
+  virtual bool ProcessExtensionKeyword(const TemplateURL* template_url,
                                        const AutocompleteMatch& match,
                                        WindowOpenDisposition disposition,
                                        OmniboxNavigationObserver* observer);
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp
index 54e8336..f90b393d 100644
--- a/components/page_info_strings.grdp
+++ b/components/page_info_strings.grdp
@@ -111,4 +111,27 @@
       Certificate Information
     </message>
   </if>
+
+  <!-- Content settings strings -->
+  <message name="IDS_PAGE_INFO_PERMISSION_ALLOWED_BY_POLICY" desc="The label used underneath a permission listed in the Page Info bubble if the permission was explicitly allowed by the user's enterprise policy.">
+    Allowed by your administrator
+  </message>
+  <message name="IDS_PAGE_INFO_PERMISSION_BLOCKED_BY_POLICY" desc="The label used underneath a permission listed in the Page Info bubble if the permission was explicitly blocked by the user's enterprise policy.">
+    Blocked by your administrator
+  </message>
+  <message name="IDS_PAGE_INFO_PERMISSION_ASK_BY_POLICY" desc="The label used underneath a permission listed in the Page Info bubble if the permission was explicitly set to 'Ask' by the user's enterprise policy.">
+    Setting controlled by your administrator
+  </message>
+  <message name="IDS_PAGE_INFO_PERMISSION_ALLOWED_BY_EXTENSION" desc="The label used underneath a permission listed in the Page Info bubble if the permission was explicitly allowed by one of the user's extensions.">
+    Allowed by an extension
+  </message>
+  <message name="IDS_PAGE_INFO_PERMISSION_BLOCKED_BY_EXTENSION" desc="The label used underneath a permission listed in the Page Info bubble if the permission was explicitly blocked by one of the user's extensions.">
+    Blocked by an extension
+  </message>
+  <message name="IDS_PAGE_INFO_PERMISSION_ASK_BY_EXTENSION" desc="The label used underneath a permission listed in the Page Info bubble if the permission was explicitly set to 'Ask' by one of the user's extensions.">
+    Setting controlled by an extension
+  </message>
+  <message name="IDS_PAGE_INFO_PERMISSION_AUTOMATICALLY_BLOCKED" desc="The label used underneath a permission listed in the Page Info bubble if the permission was blocked by Chrome on behalf of the user.">
+    Automatically blocked
+  </message>
 </grit-part>
diff --git a/components/precache/core/precache_manifest_util.cc b/components/precache/core/precache_manifest_util.cc
index 668a77f..ab801f6 100644
--- a/components/precache/core/precache_manifest_util.cc
+++ b/components/precache/core/precache_manifest_util.cc
@@ -36,19 +36,26 @@
     if (it != resource_bitset_map.end()) {
       if (it->second.has_bitset()) {
         const std::string& bitset = it->second.bitset();
-        ret.emplace(bitset.size() * 8);
-        for (size_t i = 0; i < bitset.size(); ++i) {
-          for (size_t j = 0; j < 8; ++j) {
-            if ((1 << j) & bitset[i])
-              ret.value()[i * 8 + j] = true;
+        const int bitset_size = bitset.size() * 8;
+        DCHECK_GE(bitset_size, manifest.resource_size());
+        if (bitset_size >= manifest.resource_size()) {
+          ret.emplace(bitset_size);
+          for (size_t i = 0; i < bitset.size(); ++i) {
+            for (size_t j = 0; j < 8; ++j) {
+              if ((1 << j) & bitset[i])
+                ret.value()[i * 8 + j] = true;
+            }
           }
         }
       } else if (it->second.has_deprecated_bitset()) {
         uint64_t bitset = it->second.deprecated_bitset();
-        ret.emplace(64);
-        for (int i = 0; i < 64; ++i) {
-          if ((0x1ULL << i) & bitset)
-            ret.value()[i] = true;
+        DCHECK_GE(64, manifest.resource_size());
+        if (64 >= manifest.resource_size()) {
+          ret.emplace(64);
+          for (int i = 0; i < 64; ++i) {
+            if ((0x1ULL << i) & bitset)
+              ret.value()[i] = true;
+          }
         }
       }
     }
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index 1f687bf..dfce55d 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -396,6 +396,13 @@
 
 TemplateURL* TemplateURLService::GetTemplateURLForKeyword(
     const base::string16& keyword) {
+  return const_cast<TemplateURL*>(
+      static_cast<const TemplateURLService*>(this)->
+          GetTemplateURLForKeyword(keyword));
+}
+
+const TemplateURL* TemplateURLService::GetTemplateURLForKeyword(
+    const base::string16& keyword) const {
   KeywordToTURLAndMeaningfulLength::const_iterator elem(
       keyword_to_turl_and_length_.find(keyword));
   if (elem != keyword_to_turl_and_length_.end())
@@ -408,6 +415,13 @@
 
 TemplateURL* TemplateURLService::GetTemplateURLForGUID(
     const std::string& sync_guid) {
+return const_cast<TemplateURL*>(
+      static_cast<const TemplateURLService*>(this)->
+          GetTemplateURLForGUID(sync_guid));
+}
+
+const TemplateURL* TemplateURLService::GetTemplateURLForGUID(
+    const std::string& sync_guid) const {
   GUIDToTURL::const_iterator elem(guid_to_turl_.find(sync_guid));
   if (elem != guid_to_turl_.end())
     return elem->second;
@@ -419,6 +433,13 @@
 
 TemplateURL* TemplateURLService::GetTemplateURLForHost(
     const std::string& host) {
+  return const_cast<TemplateURL*>(
+      static_cast<const TemplateURLService*>(this)->
+          GetTemplateURLForHost(host));
+}
+
+const TemplateURL* TemplateURLService::GetTemplateURLForHost(
+    const std::string& host) const {
   if (loaded_)
     return provider_map_->GetTemplateURLForHost(host);
   TemplateURL* initial_dsp = initial_default_search_provider_.get();
@@ -840,10 +861,7 @@
 base::string16 TemplateURLService::GetKeywordShortName(
     const base::string16& keyword,
     bool* is_omnibox_api_extension_keyword) const {
-  // TODO(jeffschiller): Make GetTemplateURLForKeyword const and remove the
-  // const_cast.
-  const TemplateURL* template_url =
-      const_cast<TemplateURLService*>(this)->GetTemplateURLForKeyword(keyword);
+  const TemplateURL* template_url = GetTemplateURLForKeyword(keyword);
 
   // TODO(sky): Once LocationBarView adds a listener to the TemplateURLService
   // to track changes to the model, this should become a DCHECK.
@@ -1253,7 +1271,7 @@
     TemplateURLServiceClient* client,
     PrefService* prefs,
     const SearchTermsData& search_terms_data,
-    TemplateURL* existing_turl,
+    const TemplateURL* existing_turl,
     const syncer::SyncData& sync_data,
     syncer::SyncChangeList* change_list) {
   DCHECK(change_list);
@@ -2220,10 +2238,7 @@
     const TemplateURL* local_turl,
     const TemplateURL* sync_turl,
     bool prefer_local_default) const {
-  // TODO(jeffschiller): Make GetTemplateURLForKeyword const and remove the
-  // const_cast.
-  DCHECK(const_cast<TemplateURLService*>(this)->GetTemplateURLForGUID(
-          local_turl->sync_guid()));
+  DCHECK(GetTemplateURLForGUID(local_turl->sync_guid()));
   return local_turl->last_modified() > sync_turl->last_modified() ||
          local_turl->created_by_policy() ||
          (prefer_local_default && local_turl == GetDefaultSearchProvider());
@@ -2401,7 +2416,7 @@
     return;
   }
 
-  TemplateURL* turl = GetTemplateURLForGUID(new_guid);
+  const TemplateURL* turl = GetTemplateURLForGUID(new_guid);
   if (turl)
     default_search_manager_.SetUserSelectedDefaultSearchEngine(turl->data());
 }
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h
index 7e57b2b..7698f8fd 100644
--- a/components/search_engines/template_url_service.h
+++ b/components/search_engines/template_url_service.h
@@ -167,15 +167,19 @@
   // The caller should not try to delete the returned pointer; the data store
   // retains ownership of it.
   TemplateURL* GetTemplateURLForKeyword(const base::string16& keyword);
+  const TemplateURL* GetTemplateURLForKeyword(
+      const base::string16& keyword) const;
 
   // Returns that TemplateURL with the specified GUID, or NULL if not found.
   // The caller should not try to delete the returned pointer; the data store
   // retains ownership of it.
   TemplateURL* GetTemplateURLForGUID(const std::string& sync_guid);
+  const TemplateURL* GetTemplateURLForGUID(const std::string& sync_guid) const;
 
   // Returns the first TemplateURL found with a URL using the specified |host|,
   // or NULL if there are no such TemplateURLs
   TemplateURL* GetTemplateURLForHost(const std::string& host);
+  const TemplateURL* GetTemplateURLForHost(const std::string& host) const;
 
   // Adds |template_url| to this model.  Returns a raw pointer to |template_url|
   // if the addition succeeded, or null on failure.  (Many callers need still
@@ -388,7 +392,7 @@
       TemplateURLServiceClient* client,
       PrefService* prefs,
       const SearchTermsData& search_terms_data,
-      TemplateURL* existing_turl,
+      const TemplateURL* existing_turl,
       const syncer::SyncData& sync_data,
       syncer::SyncChangeList* change_list);
 
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc
index 34e79b1..34be8222 100644
--- a/components/variations/service/variations_service.cc
+++ b/components/variations/service/variations_service.cc
@@ -41,6 +41,7 @@
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "ui/base/device_form_factor.h"
@@ -531,8 +532,27 @@
   if (pending_seed_request_)
     return;
 
-  pending_seed_request_ = net::URLFetcher::Create(0, variations_server_url_,
-                                                  net::URLFetcher::GET, this);
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("chrome_variations_service", R"(
+        semantics {
+          sender: "Chrome Variations Service"
+          description:
+            "Retrieves the list of Google Chrome's Variations from the server, "
+            "which will apply to the next Chrome session upon a restart."
+          trigger:
+            "Requests are made periodically while Google Chrome is running."
+          data: "The operating system name."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: false
+          setting: "This feature cannot be disabled by settings."
+          policy_exception_justification:
+            "Not implemented, considered not required."
+        })");
+  pending_seed_request_ =
+      net::URLFetcher::Create(0, variations_server_url_, net::URLFetcher::GET,
+                              this, traffic_annotation);
   data_use_measurement::DataUseUserData::AttachToFetcher(
       pending_seed_request_.get(),
       data_use_measurement::DataUseUserData::VARIATIONS);
diff --git a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
index 3cb728df..3dbea50 100644
--- a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -172,9 +172,14 @@
       uint64_t client_tracing_process_id =
           ClientIdToTracingProcessId(client_id);
 
-      base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid =
-          gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id,
-                                                buffer_id);
+      base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid;
+      if (buffer.second.type == gfx::SHARED_MEMORY_BUFFER) {
+        shared_buffer_guid = gfx::GetSharedMemoryGUIDForTracing(
+            client_tracing_process_id, buffer_id);
+      } else {
+        shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing(
+            client_tracing_process_id, buffer_id);
+      }
       pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
       pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid);
     }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 486b536..b752011 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -929,8 +929,8 @@
   // If a browser-based widget consumes the touch event, it's critical that
   // touch event interception be disabled. This avoids issues with
   // double-handling for embedder-detected gestures like side swipe.
-  if (selection_controller_ &&
-      selection_controller_->WillHandleTouchEvent(event)) {
+  if (touch_selection_controller_ &&
+      touch_selection_controller_->WillHandleTouchEvent(event)) {
     RequestDisallowInterceptTouchEvent();
     return true;
   }
@@ -969,8 +969,8 @@
 
 bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
     const ui::MotionEvent& event) {
-  return selection_controller_ &&
-         selection_controller_->WillHandleTouchEvent(event);
+  return touch_selection_controller_ &&
+         touch_selection_controller_->WillHandleTouchEvent(event);
 }
 
 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
@@ -1300,7 +1300,7 @@
 void RenderWidgetHostViewAndroid::OnSelectionEvent(
     ui::SelectionEventType event) {
   DCHECK(content_view_core_);
-  DCHECK(selection_controller_);
+  DCHECK(touch_selection_controller_);
   // If a selection drag has started, it has taken over the active touch
   // sequence. Immediately cancel gesture detection and any downstream touch
   // listeners (e.g., web content) to communicate this transfer.
@@ -1309,8 +1309,8 @@
     ResetGestureDetection();
   }
   content_view_core_->OnSelectionEvent(
-      event, selection_controller_->GetStartPosition(),
-      GetSelectionRect(*selection_controller_));
+      event, touch_selection_controller_->GetStartPosition(),
+      GetSelectionRect(*touch_selection_controller_));
 }
 
 std::unique_ptr<ui::TouchHandleDrawable>
@@ -1381,8 +1381,8 @@
   if (overscroll_controller_)
     overscroll_controller_->OnFrameMetadataUpdated(frame_metadata);
 
-  if (selection_controller_) {
-    selection_controller_->OnSelectionBoundsChanged(
+  if (touch_selection_controller_) {
+    touch_selection_controller_->OnSelectionBoundsChanged(
         frame_metadata.selection.start, frame_metadata.selection.end);
 
     // Set parameters for adaptive handle orientation.
@@ -1391,7 +1391,7 @@
     gfx::RectF viewport_rect(0.0f, frame_metadata.top_controls_height *
                                        frame_metadata.top_controls_shown_ratio,
                              viewport_size.width(), viewport_size.height());
-    selection_controller_->OnViewportChanged(viewport_rect);
+    touch_selection_controller_->OnViewportChanged(viewport_rect);
   }
 
   UpdateBackgroundColor(is_transparent ? SK_ColorTRANSPARENT
@@ -1600,8 +1600,8 @@
     needs_animate |= overscroll_controller_->Animate(
         frame_time, content_view_core_->GetViewAndroid()->GetLayer());
   }
-  if (selection_controller_)
-    needs_animate |= selection_controller_->Animate(frame_time);
+  if (touch_selection_controller_)
+    needs_animate |= touch_selection_controller_->Animate(frame_time);
   return needs_animate;
 }
 
@@ -1645,26 +1645,26 @@
 
 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
     const blink::WebInputEvent& input_event) {
-  if (selection_controller_ &&
+  if (touch_selection_controller_ &&
       blink::WebInputEvent::IsGestureEventType(input_event.GetType())) {
     const blink::WebGestureEvent& gesture_event =
         static_cast<const blink::WebGestureEvent&>(input_event);
     switch (gesture_event.GetType()) {
       case blink::WebInputEvent::kGestureLongPress:
-        selection_controller_->HandleLongPressEvent(
+        touch_selection_controller_->HandleLongPressEvent(
             base::TimeTicks() +
                 base::TimeDelta::FromSecondsD(input_event.TimeStampSeconds()),
             gfx::PointF(gesture_event.x, gesture_event.y));
         break;
 
       case blink::WebInputEvent::kGestureTap:
-        selection_controller_->HandleTapEvent(
+        touch_selection_controller_->HandleTapEvent(
             gfx::PointF(gesture_event.x, gesture_event.y),
             gesture_event.data.tap.tap_count);
         break;
 
       case blink::WebInputEvent::kGestureScrollBegin:
-        selection_controller_->OnScrollBeginEvent();
+        touch_selection_controller_->OnScrollBeginEvent();
         break;
 
       default:
@@ -1831,13 +1831,13 @@
 }
 
 void RenderWidgetHostViewAndroid::DismissTextHandles() {
-  if (selection_controller_)
-    selection_controller_->HideAndDisallowShowingAutomatically();
+  if (touch_selection_controller_)
+    touch_selection_controller_->HideAndDisallowShowingAutomatically();
 }
 
 void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
-  if (selection_controller_)
-    selection_controller_->SetTemporarilyHidden(hidden);
+  if (touch_selection_controller_)
+    touch_selection_controller_->SetTemporarilyHidden(hidden);
 }
 
 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
@@ -1884,7 +1884,7 @@
 
   bool resize = false;
   if (content_view_core != content_view_core_) {
-    selection_controller_.reset();
+    touch_selection_controller_.reset();
     RunAckCallbacks();
     // TODO(yusufo) : Get rid of the below conditions and have a better handling
     // for resizing after crbug.com/628302 is handled.
@@ -1928,8 +1928,9 @@
   if (resize)
     WasResized();
 
-  if (!selection_controller_)
-    selection_controller_ = CreateSelectionController(this, content_view_core_);
+  if (!touch_selection_controller_)
+    touch_selection_controller_ =
+        CreateSelectionController(this, content_view_core_);
 
   if (content_view_core_)
     CreateOverscrollControllerIfPossible();
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 704204f..bbfa9fc8 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -394,7 +394,7 @@
 
   // Manages selection handle rendering and manipulation.
   // This will always be NULL if |content_view_core_| is NULL.
-  std::unique_ptr<ui::TouchSelectionController> selection_controller_;
+  std::unique_ptr<ui::TouchSelectionController> touch_selection_controller_;
 
   // Bounds to use if we have no backing ContentViewCore
   gfx::Rect default_bounds_;
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 93aaf34..e130e4b9 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/threading/non_thread_safe.h"
 #include "base/trace_event/trace_event.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/devtools/service_worker_devtools_manager.h"
@@ -80,9 +79,11 @@
     const GURL& scope,
     bool is_installed,
     mojom::EmbeddedWorkerInstanceClientRequest request,
-    const base::Callback<void(int worker_devtools_agent_route_id,
-                              bool wait_for_debugger)>& callback) {
+    const base::Callback<
+        void(std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy>,
+             bool wait_for_debugger)>& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy;
   int worker_devtools_agent_route_id = MSG_ROUTING_NONE;
   bool wait_for_debugger = false;
   if (RenderProcessHost* rph = RenderProcessHost::FromID(process_id)) {
@@ -97,11 +98,12 @@
             is_installed);
     if (request.is_pending())
       BindInterface(rph, std::move(request));
+    devtools_proxy = base::MakeUnique<EmbeddedWorkerInstance::DevToolsProxy>(
+        process_id, worker_devtools_agent_route_id);
   }
   BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(callback, worker_devtools_agent_route_id, wait_for_debugger));
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(callback, base::Passed(&devtools_proxy), wait_for_debugger));
 }
 
 void CallDetach(EmbeddedWorkerInstance* instance) {
@@ -137,15 +139,16 @@
 
 }  // namespace
 
-// Lives on IO thread, proxies notifications to DevToolsManager that lives on
-// UI thread. Owned by EmbeddedWorkerInstance.
-class EmbeddedWorkerInstance::DevToolsProxy : public base::NonThreadSafe {
+// Created on UI thread and moved to IO thread. Proxies notifications to
+// DevToolsManager that lives on UI thread. Owned by EmbeddedWorkerInstance.
+class EmbeddedWorkerInstance::DevToolsProxy {
  public:
   DevToolsProxy(int process_id, int agent_route_id)
       : process_id_(process_id),
         agent_route_id_(agent_route_id) {}
 
   ~DevToolsProxy() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
@@ -154,21 +157,21 @@
   }
 
   void NotifyWorkerReadyForInspection() {
-    DCHECK(CalledOnValidThread());
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                             base::Bind(NotifyWorkerReadyForInspectionOnUI,
                                        process_id_, agent_route_id_));
   }
 
   void NotifyWorkerVersionInstalled() {
-    DCHECK(CalledOnValidThread());
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                             base::Bind(NotifyWorkerVersionInstalledOnUI,
                                        process_id_, agent_route_id_));
   }
 
   void NotifyWorkerVersionDoomed() {
-    DCHECK(CalledOnValidThread());
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                             base::Bind(NotifyWorkerVersionDoomedOnUI,
                                        process_id_, agent_route_id_));
@@ -186,6 +189,7 @@
   const int process_id_;
   const int agent_route_id_;
   bool worker_stop_ignored_notified_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(DevToolsProxy);
 };
 
@@ -248,7 +252,6 @@
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     TRACE_EVENT_ASYNC_END0("ServiceWorker", "EmbeddedWorkerInstance::Start",
                            this);
-
     if (!instance_->context_)
       return;
 
@@ -372,21 +375,22 @@
                               is_new_process)));
   }
 
-  void OnSetupOnUICompleted(std::unique_ptr<EmbeddedWorkerStartParams> params,
-                            bool is_new_process,
-                            int worker_devtools_agent_route_id,
-                            bool wait_for_debugger) {
+  void OnSetupOnUICompleted(
+      std::unique_ptr<EmbeddedWorkerStartParams> params,
+      bool is_new_process,
+      std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy,
+      bool wait_for_debugger) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker",
                                  "EmbeddedWorkerInstance::Start", this,
                                  "OnSetupOnUICompleted");
 
+    params->worker_devtools_agent_route_id = devtools_proxy->agent_route_id();
+    params->wait_for_debugger = wait_for_debugger;
+
     // Notify the instance that it is registered to the devtools manager.
     instance_->OnRegisteredToDevToolsManager(
-        is_new_process, worker_devtools_agent_route_id, wait_for_debugger);
-
-    params->worker_devtools_agent_route_id = worker_devtools_agent_route_id;
-    params->wait_for_debugger = wait_for_debugger;
+        is_new_process, std::move(devtools_proxy), wait_for_debugger);
 
     ServiceWorkerStatusCode status =
         instance_->SendStartWorker(std::move(params));
@@ -478,21 +482,21 @@
   // Abort an inflight start task.
   inflight_start_task_.reset();
 
-    if (status_ == EmbeddedWorkerStatus::STARTING &&
-        !HasSentStartWorker(starting_phase())) {
-      // Don't send the StopWorker message when the StartWorker message hasn't
-      // been sent.
-      // TODO(shimazu): Invoke OnStopping/OnStopped after the legacy IPC path is
-      // removed.
-      OnDetached();
-      return false;
-    }
-    client_->StopWorker();
+  if (status_ == EmbeddedWorkerStatus::STARTING &&
+      !HasSentStartWorker(starting_phase())) {
+    // Don't send the StopWorker message when the StartWorker message hasn't
+    // been sent.
+    // TODO(shimazu): Invoke OnStopping/OnStopped after the legacy IPC path is
+    // removed.
+    OnDetached();
+    return false;
+  }
+  client_->StopWorker();
 
-    status_ = EmbeddedWorkerStatus::STOPPING;
-    for (auto& observer : listener_list_)
-      observer.OnStopping();
-    return true;
+  status_ = EmbeddedWorkerStatus::STOPPING;
+  for (auto& observer : listener_list_)
+    observer.OnStopping();
+  return true;
 }
 
 void EmbeddedWorkerInstance::StopIfIdle() {
@@ -562,12 +566,11 @@
 
 void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager(
     bool is_new_process,
-    int worker_devtools_agent_route_id,
+    std::unique_ptr<DevToolsProxy> devtools_proxy,
     bool wait_for_debugger) {
-  if (worker_devtools_agent_route_id != MSG_ROUTING_NONE) {
+  if (devtools_proxy) {
     DCHECK(!devtools_proxy_);
-    devtools_proxy_.reset(
-        new DevToolsProxy(process_id(), worker_devtools_agent_route_id));
+    devtools_proxy_ = std::move(devtools_proxy);
   }
   if (wait_for_debugger) {
     // We don't measure the start time when wait_for_debugger flag is set. So
@@ -627,7 +630,6 @@
 
 void EmbeddedWorkerInstance::OnScriptLoaded() {
   using LoadSource = ServiceWorkerMetrics::LoadSource;
-
   TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerInstance::OnScriptLoaded");
 
   if (!inflight_start_task_)
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h
index 71ed5e6c..737417c8 100644
--- a/content/browser/service_worker/embedded_worker_instance.h
+++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -50,6 +50,7 @@
 class CONTENT_EXPORT EmbeddedWorkerInstance
     : NON_EXPORTED_BASE(public mojom::EmbeddedWorkerInstanceHost) {
  public:
+  class DevToolsProxy;
   typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
 
   // This enum is used in UMA histograms. Append-only.
@@ -191,7 +192,6 @@
 
  private:
   typedef base::ObserverList<Listener> ListenerList;
-  class DevToolsProxy;
   class StartTask;
   class WorkerProcessHandle;
   friend class EmbeddedWorkerRegistry;
@@ -210,9 +210,10 @@
 
   // Called back from StartTask after the worker is registered to
   // WorkerDevToolsManager.
-  void OnRegisteredToDevToolsManager(bool is_new_process,
-                                     int worker_devtools_agent_route_id,
-                                     bool wait_for_debugger);
+  void OnRegisteredToDevToolsManager(
+      bool is_new_process,
+      std::unique_ptr<DevToolsProxy> devtools_proxy,
+      bool wait_for_debugger);
 
   // Sends StartWorker message via Mojo.
   ServiceWorkerStatusCode SendStartWorker(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index c4c8faae..d7a1a5e 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -72,8 +72,6 @@
     "../public/test/javascript_test_observer.h",
     "../public/test/memory_coordinator_test_utils.cc",
     "../public/test/memory_coordinator_test_utils.h",
-    "../public/test/mock_blob_url_request_context.cc",
-    "../public/test/mock_blob_url_request_context.h",
     "../public/test/mock_download_item.cc",
     "../public/test/mock_download_item.h",
     "../public/test/mock_download_manager.cc",
@@ -1059,7 +1057,6 @@
     "../browser/compositor/reflector_impl_unittest.cc",
     "../browser/compositor/software_browser_compositor_output_surface_unittest.cc",
     "../browser/compositor/software_output_device_ozone_unittest.cc",
-    "../browser/database_tracker_unittest.cc",
     "../browser/devtools/devtools_http_handler_unittest.cc",
     "../browser/devtools/devtools_manager_unittest.cc",
     "../browser/devtools/protocol/tracing_handler_unittest.cc",
@@ -1080,13 +1077,8 @@
     "../browser/download/parallel_download_utils_unittest.cc",
     "../browser/download/rate_estimator_unittest.cc",
     "../browser/download/save_package_unittest.cc",
-    "../browser/fileapi/file_system_operation_impl_write_unittest.cc",
     "../browser/fileapi/file_system_operation_runner_unittest.cc",
     "../browser/fileapi/fileapi_message_filter_unittest.cc",
-    "../browser/fileapi/sandbox_database_test_helper.cc",
-    "../browser/fileapi/sandbox_database_test_helper.h",
-    "../browser/fileapi/sandbox_directory_database_unittest.cc",
-    "../browser/fileapi/sandbox_origin_database_unittest.cc",
     "../browser/fileapi/upload_file_system_file_element_reader_unittest.cc",
     "../browser/frame_host/ancestor_throttle_unittest.cc",
     "../browser/frame_host/frame_tree_node_blame_context_unittest.cc",
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn
index 76fa59e..83ff8c11 100644
--- a/device/usb/BUILD.gn
+++ b/device/usb/BUILD.gn
@@ -57,13 +57,22 @@
 
   deps = [
     ":usb_device_ids",
-    "//base",
     "//base/third_party/dynamic_annotations",
     "//components/device_event_log",
     "//device/base",
     "//net",
   ]
 
+  public_deps = [
+    "//base",
+    "//url",
+
+    # Depend on the header generation target only to avoid the circular
+    # dependency caused by both using enums defined in the mojom headers and
+    # typemappings linking against this target.
+    "public/interfaces:interfaces__generator",
+  ]
+
   if (use_udev) {
     sources += [
       "usb_service_linux.cc",
diff --git a/device/usb/fake_usb_device_handle.cc b/device/usb/fake_usb_device_handle.cc
index 27ddfb3..78c0134 100644
--- a/device/usb/fake_usb_device_handle.cc
+++ b/device/usb/fake_usb_device_handle.cc
@@ -55,9 +55,9 @@
 }
 
 void FakeUsbDeviceHandle::ControlTransfer(
-    UsbEndpointDirection direction,
-    UsbDeviceHandle::TransferRequestType request_type,
-    UsbDeviceHandle::TransferRecipient recipient,
+    UsbTransferDirection direction,
+    UsbControlTransferType request_type,
+    UsbControlTransferRecipient recipient,
     uint8_t request,
     uint16_t value,
     uint16_t index,
@@ -66,7 +66,7 @@
     unsigned int timeout,
     const UsbDeviceHandle::TransferCallback& callback) {
   if (position_ == size_) {
-    callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+    callback.Run(UsbTransferStatus::DISCONNECT, buffer, 0);
     return;
   }
 
@@ -79,14 +79,14 @@
       bytes_transferred = std::min(bytes_transferred, size_ - position_);
     }
 
-    if (direction == USB_DIRECTION_INBOUND) {
+    if (direction == UsbTransferDirection::INBOUND) {
       memcpy(buffer->data(), &data_[position_], bytes_transferred);
       position_ += bytes_transferred;
     }
 
-    callback.Run(USB_TRANSFER_COMPLETED, buffer, bytes_transferred);
+    callback.Run(UsbTransferStatus::COMPLETED, buffer, bytes_transferred);
   } else {
-    callback.Run(USB_TRANSFER_ERROR, buffer, 0);
+    callback.Run(UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
   }
 }
 
@@ -107,7 +107,7 @@
   NOTIMPLEMENTED();
 }
 
-void FakeUsbDeviceHandle::GenericTransfer(UsbEndpointDirection direction,
+void FakeUsbDeviceHandle::GenericTransfer(UsbTransferDirection direction,
                                           uint8_t endpoint_number,
                                           scoped_refptr<net::IOBuffer> buffer,
                                           size_t length,
diff --git a/device/usb/fake_usb_device_handle.h b/device/usb/fake_usb_device_handle.h
index 121a287..aa48ad7 100644
--- a/device/usb/fake_usb_device_handle.h
+++ b/device/usb/fake_usb_device_handle.h
@@ -37,9 +37,9 @@
   void ResetDevice(const ResultCallback& callback) override;
   void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override;
 
-  void ControlTransfer(UsbEndpointDirection direction,
-                       TransferRequestType request_type,
-                       TransferRecipient recipient,
+  void ControlTransfer(UsbTransferDirection direction,
+                       UsbControlTransferType request_type,
+                       UsbControlTransferRecipient recipient,
                        uint8_t request,
                        uint16_t value,
                        uint16_t index,
@@ -61,7 +61,7 @@
       unsigned int timeout,
       const IsochronousTransferCallback& callback) override;
 
-  void GenericTransfer(UsbEndpointDirection direction,
+  void GenericTransfer(UsbTransferDirection direction,
                        uint8_t endpoint_number,
                        scoped_refptr<net::IOBuffer> buffer,
                        size_t length,
diff --git a/device/usb/mock_usb_device_handle.h b/device/usb/mock_usb_device_handle.h
index 5e2a3c2..15e6974f 100644
--- a/device/usb/mock_usb_device_handle.h
+++ b/device/usb/mock_usb_device_handle.h
@@ -36,9 +36,9 @@
   MOCK_METHOD2(ClearHalt,
                void(uint8_t endpoint, const ResultCallback& callback));
   MOCK_METHOD10(ControlTransfer,
-                void(UsbEndpointDirection direction,
-                     TransferRequestType request_type,
-                     TransferRecipient recipient,
+                void(UsbTransferDirection direction,
+                     UsbControlTransferType request_type,
+                     UsbControlTransferRecipient recipient,
                      uint8_t request,
                      uint16_t value,
                      uint16_t index,
@@ -58,7 +58,7 @@
                     unsigned int timeout,
                     const IsochronousTransferCallback& callback));
   MOCK_METHOD6(GenericTransfer,
-               void(UsbEndpointDirection direction,
+               void(UsbTransferDirection direction,
                     uint8_t endpoint,
                     scoped_refptr<net::IOBuffer> buffer,
                     size_t length,
diff --git a/device/usb/mojo/device_impl.cc b/device/usb/mojo/device_impl.cc
index 574cb90d..2d8f7c4 100644
--- a/device/usb/mojo/device_impl.cc
+++ b/device/usb/mojo/device_impl.cc
@@ -334,9 +334,7 @@
   if (HasControlTransferPermission(params->recipient, params->index)) {
     scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
     device_handle_->ControlTransfer(
-        USB_DIRECTION_INBOUND,
-        mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
-        mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
+        UsbTransferDirection::INBOUND, params->type, params->recipient,
         params->request, params->value, params->index, buffer, length, timeout,
         base::Bind(&OnTransferIn, callback));
   } else {
@@ -358,9 +356,7 @@
     scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
     std::copy(data.begin(), data.end(), buffer->data());
     device_handle_->ControlTransfer(
-        USB_DIRECTION_OUTBOUND,
-        mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
-        mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
+        UsbTransferDirection::OUTBOUND, params->type, params->recipient,
         params->request, params->value, params->index, buffer, data.size(),
         timeout, base::Bind(&OnTransferOut, callback));
   } else {
@@ -379,8 +375,8 @@
 
   uint8_t endpoint_address = endpoint_number | 0x80;
   scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
-  device_handle_->GenericTransfer(USB_DIRECTION_INBOUND, endpoint_address,
-                                  buffer, length, timeout,
+  device_handle_->GenericTransfer(UsbTransferDirection::INBOUND,
+                                  endpoint_address, buffer, length, timeout,
                                   base::Bind(&OnTransferIn, callback));
 }
 
@@ -397,9 +393,9 @@
   uint8_t endpoint_address = endpoint_number;
   scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
   std::copy(data.begin(), data.end(), buffer->data());
-  device_handle_->GenericTransfer(USB_DIRECTION_OUTBOUND, endpoint_address,
-                                  buffer, data.size(), timeout,
-                                  base::Bind(&OnTransferOut, callback));
+  device_handle_->GenericTransfer(
+      UsbTransferDirection::OUTBOUND, endpoint_address, buffer, data.size(),
+      timeout, base::Bind(&OnTransferOut, callback));
 }
 
 void DeviceImpl::IsochronousTransferIn(
diff --git a/device/usb/mojo/device_impl_unittest.cc b/device/usb/mojo/device_impl_unittest.cc
index a077a81..68362907 100644
--- a/device/usb/mojo/device_impl_unittest.cc
+++ b/device/usb/mojo/device_impl_unittest.cc
@@ -307,7 +307,7 @@
     scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(length);
     std::copy(bytes.begin(), bytes.end(), buffer->data());
     mock_inbound_data_.pop();
-    callback.Run(USB_TRANSFER_COMPLETED, buffer, length);
+    callback.Run(UsbTransferStatus::COMPLETED, buffer, length);
   }
 
   void OutboundTransfer(scoped_refptr<net::IOBuffer> buffer,
@@ -321,12 +321,12 @@
                                              << i;
     }
     mock_outbound_data_.pop();
-    callback.Run(USB_TRANSFER_COMPLETED, buffer, length);
+    callback.Run(UsbTransferStatus::COMPLETED, buffer, length);
   }
 
-  void ControlTransfer(UsbEndpointDirection direction,
-                       UsbDeviceHandle::TransferRequestType request_type,
-                       UsbDeviceHandle::TransferRecipient recipient,
+  void ControlTransfer(UsbTransferDirection direction,
+                       UsbControlTransferType request_type,
+                       UsbControlTransferRecipient recipient,
                        uint8_t request,
                        uint16_t value,
                        uint16_t index,
@@ -334,19 +334,19 @@
                        size_t length,
                        unsigned int timeout,
                        const UsbDeviceHandle::TransferCallback& callback) {
-    if (direction == USB_DIRECTION_INBOUND)
+    if (direction == UsbTransferDirection::INBOUND)
       InboundTransfer(callback);
     else
       OutboundTransfer(buffer, length, callback);
   }
 
-  void GenericTransfer(UsbEndpointDirection direction,
+  void GenericTransfer(UsbTransferDirection direction,
                        uint8_t endpoint,
                        scoped_refptr<net::IOBuffer> buffer,
                        size_t length,
                        unsigned int timeout,
                        const UsbDeviceHandle::TransferCallback& callback) {
-    if (direction == USB_DIRECTION_INBOUND)
+    if (direction == UsbTransferDirection::INBOUND)
       InboundTransfer(callback);
     else
       OutboundTransfer(buffer, length, callback);
@@ -718,8 +718,10 @@
   AddMockInboundData(fake_data);
 
   EXPECT_CALL(mock_handle(),
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 5, 6, 7, _, _, 0, _));
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 5, 6, 7, _,
+                              _, 0, _));
   EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _));
 
   {
@@ -741,8 +743,10 @@
   AddMockOutboundData(fake_data);
 
   EXPECT_CALL(mock_handle(),
-              ControlTransfer(USB_DIRECTION_OUTBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::INTERFACE, 5, 6, 7, _, _, 0, _));
+              ControlTransfer(UsbTransferDirection::OUTBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::INTERFACE, 5, 6, 7,
+                              _, _, 0, _));
   EXPECT_CALL(permission_provider(), HasFunctionPermission(7, 1, _));
 
   {
@@ -787,8 +791,9 @@
   AddMockOutboundData(fake_outbound_data);
   AddMockInboundData(fake_inbound_data);
 
-  EXPECT_CALL(mock_handle(), GenericTransfer(USB_DIRECTION_OUTBOUND, 0x01, _,
-                                             fake_outbound_data.size(), 0, _));
+  EXPECT_CALL(mock_handle(),
+              GenericTransfer(UsbTransferDirection::OUTBOUND, 0x01, _,
+                              fake_outbound_data.size(), 0, _));
 
   {
     base::RunLoop loop;
@@ -799,8 +804,9 @@
     loop.Run();
   }
 
-  EXPECT_CALL(mock_handle(), GenericTransfer(USB_DIRECTION_INBOUND, 0x81, _,
-                                             fake_inbound_data.size(), 0, _));
+  EXPECT_CALL(mock_handle(),
+              GenericTransfer(UsbTransferDirection::INBOUND, 0x81, _,
+                              fake_inbound_data.size(), 0, _));
 
   {
     base::RunLoop loop;
@@ -831,7 +837,7 @@
   for (size_t i = 0; i < fake_packets.size(); ++i) {
     fake_packets[i].length = 8;
     fake_packets[i].transferred_length = 8;
-    fake_packets[i].status = USB_TRANSFER_COMPLETED;
+    fake_packets[i].status = UsbTransferStatus::COMPLETED;
   }
   std::vector<uint32_t> fake_packet_lengths(4, 8);
 
diff --git a/device/usb/mojo/type_converters.cc b/device/usb/mojo/type_converters.cc
index da85613..fbe17d8 100644
--- a/device/usb/mojo/type_converters.cc
+++ b/device/usb/mojo/type_converters.cc
@@ -17,114 +17,14 @@
 namespace mojo {
 
 // static
-device::mojom::UsbTransferDirection TypeConverter<
-    device::mojom::UsbTransferDirection,
-    device::UsbEndpointDirection>::Convert(const device::UsbEndpointDirection&
-                                               direction) {
-  if (direction == device::USB_DIRECTION_INBOUND)
-    return device::mojom::UsbTransferDirection::INBOUND;
-  DCHECK(direction == device::USB_DIRECTION_OUTBOUND);
-  return device::mojom::UsbTransferDirection::OUTBOUND;
-}
-
-// static
-device::mojom::UsbTransferStatus
-TypeConverter<device::mojom::UsbTransferStatus, device::UsbTransferStatus>::
-    Convert(const device::UsbTransferStatus& status) {
-  switch (status) {
-    case device::USB_TRANSFER_COMPLETED:
-      return device::mojom::UsbTransferStatus::COMPLETED;
-    case device::USB_TRANSFER_ERROR:
-      return device::mojom::UsbTransferStatus::TRANSFER_ERROR;
-    case device::USB_TRANSFER_TIMEOUT:
-      return device::mojom::UsbTransferStatus::TIMEOUT;
-    case device::USB_TRANSFER_CANCELLED:
-      return device::mojom::UsbTransferStatus::CANCELLED;
-    case device::USB_TRANSFER_STALLED:
-      return device::mojom::UsbTransferStatus::STALLED;
-    case device::USB_TRANSFER_DISCONNECT:
-      return device::mojom::UsbTransferStatus::DISCONNECT;
-    case device::USB_TRANSFER_OVERFLOW:
-      return device::mojom::UsbTransferStatus::BABBLE;
-    case device::USB_TRANSFER_LENGTH_SHORT:
-      return device::mojom::UsbTransferStatus::SHORT_PACKET;
-    default:
-      NOTREACHED();
-      return device::mojom::UsbTransferStatus::TRANSFER_ERROR;
-  }
-}
-
-// static
-device::UsbDeviceHandle::TransferRequestType
-TypeConverter<device::UsbDeviceHandle::TransferRequestType,
-              device::mojom::UsbControlTransferType>::
-    Convert(const device::mojom::UsbControlTransferType& type) {
-  switch (type) {
-    case device::mojom::UsbControlTransferType::STANDARD:
-      return device::UsbDeviceHandle::STANDARD;
-    case device::mojom::UsbControlTransferType::CLASS:
-      return device::UsbDeviceHandle::CLASS;
-    case device::mojom::UsbControlTransferType::VENDOR:
-      return device::UsbDeviceHandle::VENDOR;
-    case device::mojom::UsbControlTransferType::RESERVED:
-      return device::UsbDeviceHandle::RESERVED;
-    default:
-      NOTREACHED();
-      return device::UsbDeviceHandle::RESERVED;
-  }
-}
-
-// static
-device::UsbDeviceHandle::TransferRecipient
-TypeConverter<device::UsbDeviceHandle::TransferRecipient,
-              device::mojom::UsbControlTransferRecipient>::
-    Convert(const device::mojom::UsbControlTransferRecipient& recipient) {
-  switch (recipient) {
-    case device::mojom::UsbControlTransferRecipient::DEVICE:
-      return device::UsbDeviceHandle::DEVICE;
-    case device::mojom::UsbControlTransferRecipient::INTERFACE:
-      return device::UsbDeviceHandle::INTERFACE;
-    case device::mojom::UsbControlTransferRecipient::ENDPOINT:
-      return device::UsbDeviceHandle::ENDPOINT;
-    case device::mojom::UsbControlTransferRecipient::OTHER:
-      return device::UsbDeviceHandle::OTHER;
-    default:
-      NOTREACHED();
-      return device::UsbDeviceHandle::OTHER;
-  }
-}
-
-// static
-device::mojom::UsbEndpointType
-TypeConverter<device::mojom::UsbEndpointType, device::UsbTransferType>::Convert(
-    const device::UsbTransferType& type) {
-  switch (type) {
-    case device::USB_TRANSFER_ISOCHRONOUS:
-      return device::mojom::UsbEndpointType::ISOCHRONOUS;
-    case device::USB_TRANSFER_BULK:
-      return device::mojom::UsbEndpointType::BULK;
-    case device::USB_TRANSFER_INTERRUPT:
-      return device::mojom::UsbEndpointType::INTERRUPT;
-    // Note that we do not expose control transfer in the public interface
-    // because control endpoints are implied rather than explicitly enumerated
-    // there.
-    default:
-      NOTREACHED();
-      return device::mojom::UsbEndpointType::BULK;
-  }
-}
-
-// static
 device::mojom::UsbEndpointInfoPtr TypeConverter<
     device::mojom::UsbEndpointInfoPtr,
     device::UsbEndpointDescriptor>::Convert(const device::UsbEndpointDescriptor&
                                                 endpoint) {
   auto info = device::mojom::UsbEndpointInfo::New();
   info->endpoint_number = endpoint.address & 0xf;
-  info->direction =
-      ConvertTo<device::mojom::UsbTransferDirection>(endpoint.direction);
-  info->type =
-      ConvertTo<device::mojom::UsbEndpointType>(endpoint.transfer_type);
+  info->direction = endpoint.direction;
+  info->type = endpoint.transfer_type;
   info->packet_size = static_cast<uint32_t>(endpoint.maximum_packet_size);
   return info;
 }
@@ -143,7 +43,7 @@
   // Filter out control endpoints for the public interface.
   info->endpoints.reserve(interface.endpoints.size());
   for (const auto& endpoint : interface.endpoints) {
-    if (endpoint.transfer_type != device::USB_TRANSFER_CONTROL)
+    if (endpoint.transfer_type != device::UsbTransferType::CONTROL)
       info->endpoints.push_back(device::mojom::UsbEndpointInfo::From(endpoint));
   }
 
diff --git a/device/usb/mojo/type_converters.h b/device/usb/mojo/type_converters.h
index 4cee02c..cb9514c 100644
--- a/device/usb/mojo/type_converters.h
+++ b/device/usb/mojo/type_converters.h
@@ -25,40 +25,6 @@
 namespace mojo {
 
 template <>
-struct TypeConverter<device::mojom::UsbTransferDirection,
-                     device::UsbEndpointDirection> {
-  static device::mojom::UsbTransferDirection Convert(
-      const device::UsbEndpointDirection& direction);
-};
-
-template <>
-struct TypeConverter<device::mojom::UsbTransferStatus,
-                     device::UsbTransferStatus> {
-  static device::mojom::UsbTransferStatus Convert(
-      const device::UsbTransferStatus& status);
-};
-
-template <>
-struct TypeConverter<device::UsbDeviceHandle::TransferRequestType,
-                     device::mojom::UsbControlTransferType> {
-  static device::UsbDeviceHandle::TransferRequestType Convert(
-      const device::mojom::UsbControlTransferType& type);
-};
-
-template <>
-struct TypeConverter<device::UsbDeviceHandle::TransferRecipient,
-                     device::mojom::UsbControlTransferRecipient> {
-  static device::UsbDeviceHandle::TransferRecipient Convert(
-      const device::mojom::UsbControlTransferRecipient& recipient);
-};
-
-template <>
-struct TypeConverter<device::mojom::UsbEndpointType, device::UsbTransferType> {
-  static device::mojom::UsbEndpointType Convert(
-      const device::UsbTransferType& type);
-};
-
-template <>
 struct TypeConverter<device::mojom::UsbEndpointInfoPtr,
                      device::UsbEndpointDescriptor> {
   static device::mojom::UsbEndpointInfoPtr Convert(
diff --git a/device/usb/public/interfaces/device.mojom b/device/usb/public/interfaces/device.mojom
index e23406a..d1c139a 100644
--- a/device/usb/public/interfaces/device.mojom
+++ b/device/usb/public/interfaces/device.mojom
@@ -15,8 +15,9 @@
   ALREADY_OPEN,
 };
 
+// Corresponds to the USBDirection WebIDL type.
 enum UsbTransferDirection {
-  INBOUND,
+  INBOUND = 0,
   OUTBOUND,
 };
 
@@ -27,6 +28,7 @@
   RESERVED
 };
 
+// Corresponds to the USBRecipient WebIDL type.
 enum UsbControlTransferRecipient {
   DEVICE,
   INTERFACE,
@@ -34,16 +36,17 @@
   OTHER
 };
 
-enum UsbEndpointType {
+enum UsbTransferType {
+  CONTROL = 0,
+  ISOCHRONOUS,
   BULK,
   INTERRUPT,
-  ISOCHRONOUS,
 };
 
 struct UsbEndpointInfo {
   uint8 endpoint_number;
   UsbTransferDirection direction;
-  UsbEndpointType type;
+  UsbTransferType type;
   uint32 packet_size;
 };
 
@@ -95,16 +98,15 @@
   uint16 index;
 };
 
+// This enum is exposed through the chrome.usb extension API so existing values
+// should not be changed or reordered.
 enum UsbTransferStatus {
   // The transfer completed successfully.
-  COMPLETED,
+  COMPLETED = 0,
 
   // The transfer failed due to a non-specific error.
   TRANSFER_ERROR,
 
-  // The transfer was not allowed.
-  PERMISSION_DENIED,
-
   // The transfer timed out.
   TIMEOUT,
 
@@ -124,6 +126,9 @@
   // The transfer succeeded, but the device sent less data than was requested.
   // This applies only to inbound transfers.
   SHORT_PACKET,
+
+  // The transfer was not allowed.
+  PERMISSION_DENIED,
 };
 
 struct UsbIsochronousPacket {
diff --git a/device/usb/usb_descriptors.cc b/device/usb/usb_descriptors.cc
index 5ad332b..645ee56 100644
--- a/device/usb/usb_descriptors.cc
+++ b/device/usb/usb_descriptors.cc
@@ -97,7 +97,7 @@
                             UsbTransferStatus status,
                             scoped_refptr<IOBuffer> buffer,
                             size_t length) {
-  if (status == USB_TRANSFER_COMPLETED) {
+  if (status == UsbTransferStatus::COMPLETED) {
     if (!desc->Parse(
             std::vector<uint8_t>(buffer->data(), buffer->data() + length))) {
       LOG(ERROR) << "Failed to parse configuration descriptor.";
@@ -115,13 +115,13 @@
                                   UsbTransferStatus status,
                                   scoped_refptr<IOBuffer> header,
                                   size_t length) {
-  if (status == USB_TRANSFER_COMPLETED && length == 4) {
+  if (status == UsbTransferStatus::COMPLETED && length == 4) {
     const uint8_t* data = reinterpret_cast<const uint8_t*>(header->data());
     uint16_t total_length = data[2] | data[3] << 8;
     scoped_refptr<IOBuffer> buffer = new IOBuffer(total_length);
     device_handle->ControlTransfer(
-        USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-        UsbDeviceHandle::DEVICE, kGetDescriptorRequest,
+        UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+        UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
         kConfigurationDescriptorType << 8 | index, 0, buffer, total_length,
         kControlTransferTimeout,
         base::Bind(&OnReadConfigDescriptor, desc, closure));
@@ -138,7 +138,7 @@
     UsbTransferStatus status,
     scoped_refptr<IOBuffer> buffer,
     size_t length) {
-  if (status != USB_TRANSFER_COMPLETED) {
+  if (status != UsbTransferStatus::COMPLETED) {
     LOG(ERROR) << "Failed to read device descriptor.";
     callback.Run(nullptr);
     return;
@@ -166,8 +166,8 @@
   for (uint8_t i = 0; i < num_configurations; ++i) {
     scoped_refptr<IOBufferWithSize> header = new IOBufferWithSize(4);
     device_handle->ControlTransfer(
-        USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-        UsbDeviceHandle::DEVICE, kGetDescriptorRequest,
+        UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+        UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
         kConfigurationDescriptorType << 8 | i, 0, header, header->size(),
         kControlTransferTimeout,
         base::Bind(&OnReadConfigDescriptorHeader, device_handle, desc_ptr, i,
@@ -188,7 +188,7 @@
     scoped_refptr<IOBuffer> buffer,
     size_t length) {
   base::string16 string;
-  if (status == USB_TRANSFER_COMPLETED &&
+  if (status == UsbTransferStatus::COMPLETED &&
       ParseUsbStringDescriptor(
           std::vector<uint8_t>(buffer->data(), buffer->data() + length),
           &string)) {
@@ -205,10 +205,10 @@
     const base::Callback<void(const base::string16&)>& callback) {
   scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(255);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE,
-      kGetDescriptorRequest, kStringDescriptorType << 8 | index, language_id,
-      buffer, buffer->size(), kControlTransferTimeout,
-      base::Bind(&OnReadStringDescriptor, callback));
+      UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+      UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
+      kStringDescriptorType << 8 | index, language_id, buffer, buffer->size(),
+      kControlTransferTimeout, base::Bind(&OnReadStringDescriptor, callback));
 }
 
 void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle,
@@ -254,24 +254,24 @@
   // These fields are defined in Table 9-24 of the USB 3.1 Specification.
   switch (address & 0x80) {
     case 0x00:
-      direction = USB_DIRECTION_OUTBOUND;
+      direction = UsbTransferDirection::OUTBOUND;
       break;
     case 0x80:
-      direction = USB_DIRECTION_INBOUND;
+      direction = UsbTransferDirection::INBOUND;
       break;
   }
   switch (attributes & 0x03) {
     case 0x00:
-      transfer_type = USB_TRANSFER_CONTROL;
+      transfer_type = UsbTransferType::CONTROL;
       break;
     case 0x01:
-      transfer_type = USB_TRANSFER_ISOCHRONOUS;
+      transfer_type = UsbTransferType::ISOCHRONOUS;
       break;
     case 0x02:
-      transfer_type = USB_TRANSFER_BULK;
+      transfer_type = UsbTransferType::BULK;
       break;
     case 0x03:
-      transfer_type = USB_TRANSFER_INTERRUPT;
+      transfer_type = UsbTransferType::INTERRUPT;
       break;
   }
   switch (attributes & 0x0F) {
@@ -500,9 +500,10 @@
   scoped_refptr<IOBufferWithSize> buffer =
       new IOBufferWithSize(kDeviceDescriptorLength);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE,
-      kGetDescriptorRequest, kDeviceDescriptorType << 8, 0, buffer,
-      buffer->size(), kControlTransferTimeout,
+      UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+      UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
+      kDeviceDescriptorType << 8, 0, buffer, buffer->size(),
+      kControlTransferTimeout,
       base::Bind(&OnReadDeviceDescriptor, device_handle, callback));
 }
 
diff --git a/device/usb/usb_descriptors.h b/device/usb/usb_descriptors.h
index 9039c95..b0f5be6 100644
--- a/device/usb/usb_descriptors.h
+++ b/device/usb/usb_descriptors.h
@@ -14,22 +14,14 @@
 #include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
+#include "device/usb/public/interfaces/device.mojom.h"
 
 namespace device {
 
 class UsbDeviceHandle;
 
-enum UsbTransferType {
-  USB_TRANSFER_CONTROL = 0,
-  USB_TRANSFER_ISOCHRONOUS,
-  USB_TRANSFER_BULK,
-  USB_TRANSFER_INTERRUPT,
-};
-
-enum UsbEndpointDirection {
-  USB_DIRECTION_INBOUND = 0,
-  USB_DIRECTION_OUTBOUND,
-};
+using UsbTransferType = mojom::UsbTransferType;
+using UsbTransferDirection = mojom::UsbTransferDirection;
 
 enum UsbSynchronizationType {
   USB_SYNCHRONIZATION_NONE = 0,
@@ -61,7 +53,7 @@
   ~UsbEndpointDescriptor();
 
   uint8_t address;
-  UsbEndpointDirection direction;
+  UsbTransferDirection direction;
   uint16_t maximum_packet_size;
   UsbSynchronizationType synchronization_type;
   UsbTransferType transfer_type;
diff --git a/device/usb/usb_descriptors_unittest.cc b/device/usb/usb_descriptors_unittest.cc
index 195b01b..06cc6824 100644
--- a/device/usb/usb_descriptors_unittest.cc
+++ b/device/usb/usb_descriptors_unittest.cc
@@ -22,7 +22,7 @@
 ACTION_P2(InvokeCallback, data, length) {
   size_t transferred_length = std::min(length, arg7);
   memcpy(arg6->data(), data, transferred_length);
-  arg9.Run(USB_TRANSFER_COMPLETED, arg6, transferred_length);
+  arg9.Run(UsbTransferStatus::COMPLETED, arg6, transferred_length);
 }
 
 void ExpectStringDescriptors(
@@ -86,33 +86,36 @@
   EXPECT_EQ(0, config.interfaces[0].first_interface);
   // Endpoint 1 IN
   EXPECT_EQ(0x81, config.interfaces[0].endpoints[0].address);
-  EXPECT_EQ(USB_DIRECTION_INBOUND, config.interfaces[0].endpoints[0].direction);
+  EXPECT_EQ(UsbTransferDirection::INBOUND,
+            config.interfaces[0].endpoints[0].direction);
   EXPECT_EQ(512, config.interfaces[0].endpoints[0].maximum_packet_size);
   EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
             config.interfaces[0].endpoints[0].synchronization_type);
-  EXPECT_EQ(USB_TRANSFER_BULK, config.interfaces[0].endpoints[0].transfer_type);
+  EXPECT_EQ(UsbTransferType::BULK,
+            config.interfaces[0].endpoints[0].transfer_type);
   EXPECT_EQ(USB_USAGE_RESERVED, config.interfaces[0].endpoints[0].usage_type);
   EXPECT_EQ(0, config.interfaces[0].endpoints[0].polling_interval);
   EXPECT_EQ(0u, config.interfaces[0].endpoints[0].extra_data.size());
   // Endpoint 2 IN
   EXPECT_EQ(0x82, config.interfaces[0].endpoints[1].address);
-  EXPECT_EQ(USB_DIRECTION_INBOUND, config.interfaces[0].endpoints[1].direction);
+  EXPECT_EQ(UsbTransferDirection::INBOUND,
+            config.interfaces[0].endpoints[1].direction);
   EXPECT_EQ(512, config.interfaces[0].endpoints[1].maximum_packet_size);
   EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
             config.interfaces[0].endpoints[1].synchronization_type);
-  EXPECT_EQ(USB_TRANSFER_INTERRUPT,
+  EXPECT_EQ(UsbTransferType::INTERRUPT,
             config.interfaces[0].endpoints[1].transfer_type);
   EXPECT_EQ(USB_USAGE_PERIODIC, config.interfaces[0].endpoints[1].usage_type);
   EXPECT_EQ(4, config.interfaces[0].endpoints[1].polling_interval);
   EXPECT_EQ(0u, config.interfaces[0].endpoints[1].extra_data.size());
   // Endpoint 3 OUT
   EXPECT_EQ(0x03, config.interfaces[0].endpoints[2].address);
-  EXPECT_EQ(USB_DIRECTION_OUTBOUND,
+  EXPECT_EQ(UsbTransferDirection::OUTBOUND,
             config.interfaces[0].endpoints[2].direction);
   EXPECT_EQ(512, config.interfaces[0].endpoints[2].maximum_packet_size);
   EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
             config.interfaces[0].endpoints[2].synchronization_type);
-  EXPECT_EQ(USB_TRANSFER_INTERRUPT,
+  EXPECT_EQ(UsbTransferType::INTERRUPT,
             config.interfaces[0].endpoints[2].transfer_type);
   EXPECT_EQ(USB_USAGE_NOTIFICATION,
             config.interfaces[0].endpoints[2].usage_type);
@@ -157,23 +160,24 @@
   EXPECT_EQ(0, config.interfaces[1].first_interface);
   // Endpoint 1 IN
   EXPECT_EQ(0x81, config.interfaces[1].endpoints[0].address);
-  EXPECT_EQ(USB_DIRECTION_INBOUND, config.interfaces[1].endpoints[0].direction);
+  EXPECT_EQ(UsbTransferDirection::INBOUND,
+            config.interfaces[1].endpoints[0].direction);
   EXPECT_EQ(1024, config.interfaces[1].endpoints[0].maximum_packet_size);
   EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
             config.interfaces[1].endpoints[0].synchronization_type);
-  EXPECT_EQ(USB_TRANSFER_ISOCHRONOUS,
+  EXPECT_EQ(UsbTransferType::ISOCHRONOUS,
             config.interfaces[1].endpoints[0].transfer_type);
   EXPECT_EQ(USB_USAGE_DATA, config.interfaces[1].endpoints[0].usage_type);
   EXPECT_EQ(8, config.interfaces[1].endpoints[0].polling_interval);
   EXPECT_EQ(0u, config.interfaces[1].endpoints[0].extra_data.size());
   // Endpoint 2 OUT
   EXPECT_EQ(0x02, config.interfaces[1].endpoints[1].address);
-  EXPECT_EQ(USB_DIRECTION_OUTBOUND,
+  EXPECT_EQ(UsbTransferDirection::OUTBOUND,
             config.interfaces[1].endpoints[1].direction);
   EXPECT_EQ(1024, config.interfaces[1].endpoints[1].maximum_packet_size);
   EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
             config.interfaces[1].endpoints[1].synchronization_type);
-  EXPECT_EQ(USB_TRANSFER_ISOCHRONOUS,
+  EXPECT_EQ(UsbTransferType::ISOCHRONOUS,
             config.interfaces[1].endpoints[1].transfer_type);
   EXPECT_EQ(USB_USAGE_FEEDBACK, config.interfaces[1].endpoints[1].usage_type);
   EXPECT_EQ(8, config.interfaces[1].endpoints[1].polling_interval);
@@ -219,21 +223,24 @@
   scoped_refptr<MockUsbDeviceHandle> device_handle(
       new MockUsbDeviceHandle(nullptr));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0100, 0x0000, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0100,
+                              0x0000, _, _, _, _))
       .WillOnce(InvokeCallback(kDeviceDescriptor, sizeof(kDeviceDescriptor)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0200, 0x0000, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0200,
+                              0x0000, _, _, _, _))
       .Times(2)
       .WillRepeatedly(
           InvokeCallback(kConfig1Descriptor, sizeof(kConfig1Descriptor)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0201, 0x0000, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0201,
+                              0x0000, _, _, _, _))
       .Times(2)
       .WillRepeatedly(
           InvokeCallback(kConfig2Descriptor, sizeof(kConfig2Descriptor)));
@@ -400,33 +407,37 @@
       new MockUsbDeviceHandle(nullptr));
   static const uint8_t kStringDescriptor0[] = {0x04, 0x03, 0x21, 0x43};
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0300, 0x0000, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0300,
+                              0x0000, _, _, _, _))
       .WillOnce(InvokeCallback(kStringDescriptor0, sizeof(kStringDescriptor0)));
   static const uint8_t kStringDescriptor1[] = {0x12, 0x03, 'S', 0, 't', 0,
                                                'r',  0,    'i', 0, 'n', 0,
                                                'g',  0,    ' ', 0, '1', 0};
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0301, 0x4321, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0301,
+                              0x4321, _, _, _, _))
       .WillOnce(InvokeCallback(kStringDescriptor1, sizeof(kStringDescriptor1)));
   static const uint8_t kStringDescriptor2[] = {0x12, 0x03, 'S', 0, 't', 0,
                                                'r',  0,    'i', 0, 'n', 0,
                                                'g',  0,    ' ', 0, '2', 0};
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0302, 0x4321, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0302,
+                              0x4321, _, _, _, _))
       .WillOnce(InvokeCallback(kStringDescriptor2, sizeof(kStringDescriptor2)));
   static const uint8_t kStringDescriptor3[] = {0x12, 0x03, 'S', 0, 't', 0,
                                                'r',  0,    'i', 0, 'n', 0,
                                                'g',  0,    ' ', 0, '3', 0};
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0303, 0x4321, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0303,
+                              0x4321, _, _, _, _))
       .WillOnce(InvokeCallback(kStringDescriptor3, sizeof(kStringDescriptor3)));
 
   ReadUsbStringDescriptors(device_handle, std::move(string_map),
diff --git a/device/usb/usb_device_handle.h b/device/usb/usb_device_handle.h
index 32d25f3..d592a8d4 100644
--- a/device/usb/usb_device_handle.h
+++ b/device/usb/usb_device_handle.h
@@ -16,6 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "base/threading/thread_checker.h"
+#include "device/usb/public/interfaces/device.mojom.h"
 #include "device/usb/usb_descriptors.h"
 
 namespace net {
@@ -26,16 +27,9 @@
 
 class UsbDevice;
 
-enum UsbTransferStatus {
-  USB_TRANSFER_COMPLETED = 0,
-  USB_TRANSFER_ERROR,
-  USB_TRANSFER_TIMEOUT,
-  USB_TRANSFER_CANCELLED,
-  USB_TRANSFER_STALLED,
-  USB_TRANSFER_DISCONNECT,
-  USB_TRANSFER_OVERFLOW,
-  USB_TRANSFER_LENGTH_SHORT,
-};
+using UsbTransferStatus = mojom::UsbTransferStatus;
+using UsbControlTransferType = mojom::UsbControlTransferType;
+using UsbControlTransferRecipient = mojom::UsbControlTransferRecipient;
 
 // UsbDeviceHandle class provides basic I/O related functionalities.
 class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
@@ -53,9 +47,6 @@
       base::Callback<void(scoped_refptr<net::IOBuffer>,
                           const std::vector<IsochronousPacket>& packets)>;
 
-  enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED };
-  enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER };
-
   virtual scoped_refptr<UsbDevice> GetDevice() const = 0;
 
   // Notifies UsbDevice to drop the reference of this object; cancels all the
@@ -80,9 +71,9 @@
 
   // The transfer functions may be called from any thread. The provided callback
   // will be run on the caller's thread.
-  virtual void ControlTransfer(UsbEndpointDirection direction,
-                               TransferRequestType request_type,
-                               TransferRecipient recipient,
+  virtual void ControlTransfer(UsbTransferDirection direction,
+                               UsbControlTransferType request_type,
+                               UsbControlTransferRecipient recipient,
                                uint8_t request,
                                uint16_t value,
                                uint16_t index,
@@ -104,7 +95,7 @@
       unsigned int timeout,
       const IsochronousTransferCallback& callback) = 0;
 
-  virtual void GenericTransfer(UsbEndpointDirection direction,
+  virtual void GenericTransfer(UsbTransferDirection direction,
                                uint8_t endpoint_number,
                                scoped_refptr<net::IOBuffer> buffer,
                                size_t length,
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
index d8b28a9..ee398ed 100644
--- a/device/usb/usb_device_handle_impl.cc
+++ b/device/usb/usb_device_handle_impl.cc
@@ -35,49 +35,48 @@
 
 namespace {
 
-uint8_t ConvertTransferDirection(UsbEndpointDirection direction) {
+uint8_t ConvertTransferDirection(UsbTransferDirection direction) {
   switch (direction) {
-    case USB_DIRECTION_INBOUND:
+    case UsbTransferDirection::INBOUND:
       return LIBUSB_ENDPOINT_IN;
-    case USB_DIRECTION_OUTBOUND:
+    case UsbTransferDirection::OUTBOUND:
       return LIBUSB_ENDPOINT_OUT;
-    default:
-      NOTREACHED();
-      return LIBUSB_ENDPOINT_IN;
   }
+  NOTREACHED();
+  return 0;
 }
 
-uint8_t CreateRequestType(UsbEndpointDirection direction,
-                          UsbDeviceHandle::TransferRequestType request_type,
-                          UsbDeviceHandle::TransferRecipient recipient) {
+uint8_t CreateRequestType(UsbTransferDirection direction,
+                          UsbControlTransferType request_type,
+                          UsbControlTransferRecipient recipient) {
   uint8_t result = ConvertTransferDirection(direction);
 
   switch (request_type) {
-    case UsbDeviceHandle::STANDARD:
+    case UsbControlTransferType::STANDARD:
       result |= LIBUSB_REQUEST_TYPE_STANDARD;
       break;
-    case UsbDeviceHandle::CLASS:
+    case UsbControlTransferType::CLASS:
       result |= LIBUSB_REQUEST_TYPE_CLASS;
       break;
-    case UsbDeviceHandle::VENDOR:
+    case UsbControlTransferType::VENDOR:
       result |= LIBUSB_REQUEST_TYPE_VENDOR;
       break;
-    case UsbDeviceHandle::RESERVED:
+    case UsbControlTransferType::RESERVED:
       result |= LIBUSB_REQUEST_TYPE_RESERVED;
       break;
   }
 
   switch (recipient) {
-    case UsbDeviceHandle::DEVICE:
+    case UsbControlTransferRecipient::DEVICE:
       result |= LIBUSB_RECIPIENT_DEVICE;
       break;
-    case UsbDeviceHandle::INTERFACE:
+    case UsbControlTransferRecipient::INTERFACE:
       result |= LIBUSB_RECIPIENT_INTERFACE;
       break;
-    case UsbDeviceHandle::ENDPOINT:
+    case UsbControlTransferRecipient::ENDPOINT:
       result |= LIBUSB_RECIPIENT_ENDPOINT;
       break;
-    case UsbDeviceHandle::OTHER:
+    case UsbControlTransferRecipient::OTHER:
       result |= LIBUSB_RECIPIENT_OTHER;
       break;
   }
@@ -89,23 +88,22 @@
     const libusb_transfer_status status) {
   switch (status) {
     case LIBUSB_TRANSFER_COMPLETED:
-      return USB_TRANSFER_COMPLETED;
+      return UsbTransferStatus::COMPLETED;
     case LIBUSB_TRANSFER_ERROR:
-      return USB_TRANSFER_ERROR;
+      return UsbTransferStatus::TRANSFER_ERROR;
     case LIBUSB_TRANSFER_TIMED_OUT:
-      return USB_TRANSFER_TIMEOUT;
+      return UsbTransferStatus::TIMEOUT;
     case LIBUSB_TRANSFER_STALL:
-      return USB_TRANSFER_STALLED;
+      return UsbTransferStatus::STALLED;
     case LIBUSB_TRANSFER_NO_DEVICE:
-      return USB_TRANSFER_DISCONNECT;
+      return UsbTransferStatus::DISCONNECT;
     case LIBUSB_TRANSFER_OVERFLOW:
-      return USB_TRANSFER_OVERFLOW;
+      return UsbTransferStatus::BABBLE;
     case LIBUSB_TRANSFER_CANCELLED:
-      return USB_TRANSFER_CANCELLED;
-    default:
-      NOTREACHED();
-      return USB_TRANSFER_ERROR;
+      return UsbTransferStatus::CANCELLED;
   }
+  NOTREACHED();
+  return UsbTransferStatus::TRANSFER_ERROR;
 }
 
 static void RunTransferCallback(
@@ -298,7 +296,7 @@
     scoped_refptr<base::TaskRunner> callback_task_runner,
     const TransferCallback& callback) {
   std::unique_ptr<Transfer> transfer(new Transfer(
-      device_handle, nullptr, USB_TRANSFER_CONTROL, buffer,
+      device_handle, nullptr, UsbTransferType::CONTROL, buffer,
       length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, callback));
 
   transfer->platform_transfer_ = libusb_alloc_transfer(0);
@@ -330,7 +328,7 @@
     const TransferCallback& callback) {
   std::unique_ptr<Transfer> transfer(new Transfer(
       device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
-      USB_TRANSFER_BULK, buffer, length, callback_task_runner, callback));
+      UsbTransferType::BULK, buffer, length, callback_task_runner, callback));
 
   transfer->platform_transfer_ = libusb_alloc_transfer(0);
   if (!transfer->platform_transfer_) {
@@ -359,7 +357,8 @@
     const TransferCallback& callback) {
   std::unique_ptr<Transfer> transfer(new Transfer(
       device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
-      USB_TRANSFER_INTERRUPT, buffer, length, callback_task_runner, callback));
+      UsbTransferType::INTERRUPT, buffer, length, callback_task_runner,
+      callback));
 
   transfer->platform_transfer_ = libusb_alloc_transfer(0);
   if (!transfer->platform_transfer_) {
@@ -433,7 +432,7 @@
     scoped_refptr<net::IOBuffer> buffer,
     scoped_refptr<base::TaskRunner> callback_task_runner,
     const IsochronousTransferCallback& callback)
-    : transfer_type_(USB_TRANSFER_ISOCHRONOUS),
+    : transfer_type_(UsbTransferType::ISOCHRONOUS),
       device_handle_(device_handle),
       buffer_(buffer),
       claimed_interface_(claimed_interface),
@@ -453,7 +452,7 @@
   if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to submit transfer: "
                    << ConvertPlatformUsbErrorToString(rv);
-    TransferComplete(USB_TRANSFER_ERROR, 0);
+    TransferComplete(UsbTransferStatus::TRANSFER_ERROR, 0);
   }
 }
 
@@ -475,7 +474,7 @@
       << "data too big for our buffer (libusb failure?)";
 
   switch (transfer_type_) {
-    case USB_TRANSFER_CONTROL:
+    case UsbTransferType::CONTROL:
       // If the transfer is a control transfer we do not expose the control
       // setup header to the caller. This logic strips off the header if
       // present before invoking the callback provided with the transfer.
@@ -495,13 +494,13 @@
       }
     // Fall through!
 
-    case USB_TRANSFER_BULK:
-    case USB_TRANSFER_INTERRUPT:
+    case UsbTransferType::BULK:
+    case UsbTransferType::INTERRUPT:
       TransferComplete(ConvertTransferStatus(platform_transfer_->status),
                        actual_length);
       break;
 
-    case USB_TRANSFER_ISOCHRONOUS:
+    case UsbTransferType::ISOCHRONOUS:
       IsochronousTransferComplete();
       break;
 
@@ -523,7 +522,7 @@
 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
                                                      size_t bytes_transferred) {
   base::Closure closure;
-  if (transfer_type_ == USB_TRANSFER_ISOCHRONOUS) {
+  if (transfer_type_ == UsbTransferType::ISOCHRONOUS) {
     DCHECK_NE(LIBUSB_TRANSFER_COMPLETED, platform_transfer_->status);
     std::vector<IsochronousPacket> packets(platform_transfer_->num_iso_packets);
     for (size_t i = 0; i < packets.size(); ++i) {
@@ -697,9 +696,9 @@
                             this, endpoint, callback));
 }
 
-void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
-                                          TransferRequestType request_type,
-                                          TransferRecipient recipient,
+void UsbDeviceHandleImpl::ControlTransfer(UsbTransferDirection direction,
+                                          UsbControlTransferType request_type,
+                                          UsbControlTransferRecipient recipient,
                                           uint8_t request,
                                           uint16_t value,
                                           uint16_t index,
@@ -726,7 +725,7 @@
     unsigned int timeout,
     const IsochronousTransferCallback& callback) {
   uint8_t endpoint_address =
-      ConvertTransferDirection(USB_DIRECTION_INBOUND) | endpoint_number;
+      ConvertTransferDirection(UsbTransferDirection::INBOUND) | endpoint_number;
   if (task_runner_->BelongsToCurrentThread()) {
     IsochronousTransferInInternal(endpoint_address, packet_lengths, timeout,
                                   task_runner_, callback);
@@ -746,7 +745,8 @@
     unsigned int timeout,
     const IsochronousTransferCallback& callback) {
   uint8_t endpoint_address =
-      ConvertTransferDirection(USB_DIRECTION_OUTBOUND) | endpoint_number;
+      ConvertTransferDirection(UsbTransferDirection::OUTBOUND) |
+      endpoint_number;
   if (task_runner_->BelongsToCurrentThread()) {
     IsochronousTransferOutInternal(endpoint_address, buffer, packet_lengths,
                                    timeout, task_runner_, callback);
@@ -759,7 +759,7 @@
   }
 }
 
-void UsbDeviceHandleImpl::GenericTransfer(UsbEndpointDirection direction,
+void UsbDeviceHandleImpl::GenericTransfer(UsbTransferDirection direction,
                                           uint8_t endpoint_number,
                                           scoped_refptr<net::IOBuffer> buffer,
                                           size_t length,
@@ -969,9 +969,9 @@
 }
 
 void UsbDeviceHandleImpl::ControlTransferInternal(
-    UsbEndpointDirection direction,
-    TransferRequestType request_type,
-    TransferRecipient recipient,
+    UsbTransferDirection direction,
+    UsbControlTransferType request_type,
+    UsbControlTransferRecipient recipient,
     uint8_t request,
     uint16_t value,
     uint16_t index,
@@ -983,15 +983,15 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (!device_) {
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::DISCONNECT, buffer, 0);
     return;
   }
 
   if (!base::IsValueInRangeForNumericType<uint16_t>(length)) {
     USB_LOG(USER) << "Transfer too long.";
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
     return;
   }
 
@@ -999,8 +999,8 @@
   scoped_refptr<net::IOBuffer> resized_buffer =
       new net::IOBufferWithSize(resized_length);
   if (!resized_buffer.get()) {
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
     return;
   }
   memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
@@ -1011,8 +1011,8 @@
       value, index, static_cast<uint16_t>(length), resized_buffer, timeout,
       callback_task_runner, callback);
   if (!transfer) {
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
     return;
   }
 
@@ -1029,7 +1029,8 @@
 
   if (!device_) {
     ReportIsochronousTransferError(callback_task_runner, callback,
-                                   packet_lengths, USB_TRANSFER_DISCONNECT);
+                                   packet_lengths,
+                                   UsbTransferStatus::DISCONNECT);
     return;
   }
 
@@ -1054,7 +1055,8 @@
 
   if (!device_) {
     ReportIsochronousTransferError(callback_task_runner, callback,
-                                   packet_lengths, USB_TRANSFER_DISCONNECT);
+                                   packet_lengths,
+                                   UsbTransferStatus::DISCONNECT);
     return;
   }
 
@@ -1077,8 +1079,8 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (!device_) {
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::DISCONNECT, buffer, 0);
     return;
   }
 
@@ -1087,33 +1089,33 @@
     USB_LOG(DEBUG) << "Failed to submit transfer because endpoint "
                    << static_cast<int>(endpoint_address)
                    << " not part of a claimed interface.";
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
     return;
   }
 
   if (!base::IsValueInRangeForNumericType<int>(length)) {
     USB_LOG(DEBUG) << "Transfer too long.";
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
     return;
   }
 
   std::unique_ptr<Transfer> transfer;
   UsbTransferType transfer_type = endpoint_it->second.endpoint->transfer_type;
-  if (transfer_type == USB_TRANSFER_BULK) {
+  if (transfer_type == UsbTransferType::BULK) {
     transfer = Transfer::CreateBulkTransfer(this, endpoint_address, buffer,
                                             static_cast<int>(length), timeout,
                                             callback_task_runner, callback);
-  } else if (transfer_type == USB_TRANSFER_INTERRUPT) {
+  } else if (transfer_type == UsbTransferType::INTERRUPT) {
     transfer = Transfer::CreateInterruptTransfer(
         this, endpoint_address, buffer, static_cast<int>(length), timeout,
         callback_task_runner, callback);
   } else {
     USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address)
                    << " is not a bulk or interrupt endpoint.";
-    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
-                        buffer, 0);
+    RunTransferCallback(callback_task_runner, callback,
+                        UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
     return;
   }
 
diff --git a/device/usb/usb_device_handle_impl.h b/device/usb/usb_device_handle_impl.h
index 4d3401a..1322e19 100644
--- a/device/usb/usb_device_handle_impl.h
+++ b/device/usb/usb_device_handle_impl.h
@@ -61,9 +61,9 @@
   void ResetDevice(const ResultCallback& callback) override;
   void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override;
 
-  void ControlTransfer(UsbEndpointDirection direction,
-                       TransferRequestType request_type,
-                       TransferRecipient recipient,
+  void ControlTransfer(UsbTransferDirection direction,
+                       UsbControlTransferType request_type,
+                       UsbControlTransferRecipient recipient,
                        uint8_t request,
                        uint16_t value,
                        uint16_t index,
@@ -85,7 +85,7 @@
       unsigned int timeout,
       const IsochronousTransferCallback& callback) override;
 
-  void GenericTransfer(UsbEndpointDirection direction,
+  void GenericTransfer(UsbTransferDirection direction,
                        uint8_t endpoint_number,
                        scoped_refptr<net::IOBuffer> buffer,
                        size_t length,
@@ -141,9 +141,9 @@
       uint8_t endpoint);
 
   void ControlTransferInternal(
-      UsbEndpointDirection direction,
-      TransferRequestType request_type,
-      TransferRecipient recipient,
+      UsbTransferDirection direction,
+      UsbControlTransferType request_type,
+      UsbControlTransferRecipient recipient,
       uint8_t request,
       uint16_t value,
       uint16_t index,
diff --git a/device/usb/usb_device_handle_unittest.cc b/device/usb/usb_device_handle_unittest.cc
index ab20c41..20a76e4f 100644
--- a/device/usb/usb_device_handle_unittest.cc
+++ b/device/usb/usb_device_handle_unittest.cc
@@ -147,7 +147,7 @@
 
   scoped_refptr<net::IOBufferWithSize> in_buffer(new net::IOBufferWithSize(64));
   TestCompletionCallback in_completion;
-  handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x81, in_buffer.get(),
+  handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x81, in_buffer.get(),
                           in_buffer->size(),
                           5000,  // 5 second timeout
                           in_completion.callback());
@@ -159,17 +159,17 @@
     out_buffer->data()[i] = i;
   }
 
-  handle->GenericTransfer(USB_DIRECTION_OUTBOUND, 0x01, out_buffer.get(),
-                          out_buffer->size(),
+  handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x01,
+                          out_buffer.get(), out_buffer->size(),
                           5000,  // 5 second timeout
                           out_completion.callback());
   out_completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_COMPLETED, out_completion.status());
+  ASSERT_EQ(UsbTransferStatus::COMPLETED, out_completion.status());
   EXPECT_EQ(static_cast<size_t>(out_buffer->size()),
             out_completion.transferred());
 
   in_completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_COMPLETED, in_completion.status());
+  ASSERT_EQ(UsbTransferStatus::COMPLETED, in_completion.status());
   EXPECT_EQ(static_cast<size_t>(in_buffer->size()),
             in_completion.transferred());
   for (size_t i = 0; i < in_completion.transferred(); ++i) {
@@ -216,7 +216,7 @@
   scoped_refptr<net::IOBufferWithSize> in_buffer(
       new net::IOBufferWithSize(512));
   TestCompletionCallback in_completion;
-  handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, in_buffer.get(),
+  handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, in_buffer.get(),
                           in_buffer->size(),
                           5000,  // 5 second timeout
                           in_completion.callback());
@@ -228,17 +228,17 @@
     out_buffer->data()[i] = i;
   }
 
-  handle->GenericTransfer(USB_DIRECTION_OUTBOUND, 0x02, out_buffer.get(),
-                          out_buffer->size(),
+  handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x02,
+                          out_buffer.get(), out_buffer->size(),
                           5000,  // 5 second timeout
                           out_completion.callback());
   out_completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_COMPLETED, out_completion.status());
+  ASSERT_EQ(UsbTransferStatus::COMPLETED, out_completion.status());
   EXPECT_EQ(static_cast<size_t>(out_buffer->size()),
             out_completion.transferred());
 
   in_completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_COMPLETED, in_completion.status());
+  ASSERT_EQ(UsbTransferStatus::COMPLETED, in_completion.status());
   EXPECT_EQ(static_cast<size_t>(in_buffer->size()),
             in_completion.transferred());
   for (size_t i = 0; i < in_completion.transferred(); ++i) {
@@ -268,11 +268,12 @@
 
   scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(255));
   TestCompletionCallback completion;
-  handle->ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                          UsbDeviceHandle::DEVICE, 0x06, 0x0301, 0x0409, buffer,
-                          buffer->size(), 0, completion.callback());
+  handle->ControlTransfer(
+      UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+      UsbControlTransferRecipient::DEVICE, 0x06, 0x0301, 0x0409, buffer,
+      buffer->size(), 0, completion.callback());
   completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_COMPLETED, completion.status());
+  ASSERT_EQ(UsbTransferStatus::COMPLETED, completion.status());
   const char expected_str[] = "\x18\x03G\0o\0o\0g\0l\0e\0 \0I\0n\0c\0.\0";
   EXPECT_EQ(sizeof(expected_str) - 1, completion.transferred());
   for (size_t i = 0; i < completion.transferred(); ++i) {
@@ -334,14 +335,14 @@
 
   scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(512));
   TestCompletionCallback completion;
-  handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, buffer.get(),
+  handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer.get(),
                           buffer->size(),
                           5000,  // 5 second timeout
                           completion.callback());
 
   handle->Close();
   completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_CANCELLED, completion.status());
+  ASSERT_EQ(UsbTransferStatus::CANCELLED, completion.status());
 }
 
 TEST_F(UsbDeviceHandleTest, CancelOnDisconnect) {
@@ -365,14 +366,14 @@
 
   scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(512));
   TestCompletionCallback completion;
-  handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, buffer.get(),
+  handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer.get(),
                           buffer->size(),
                           5000,  // 5 second timeout
                           completion.callback());
 
   ASSERT_TRUE(gadget->Disconnect());
   completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_DISCONNECT, completion.status());
+  ASSERT_EQ(UsbTransferStatus::DISCONNECT, completion.status());
 
   handle->Close();
 }
@@ -398,13 +399,13 @@
 
   scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(512));
   TestCompletionCallback completion;
-  handle->GenericTransfer(USB_DIRECTION_INBOUND, 0x82, buffer.get(),
+  handle->GenericTransfer(UsbTransferDirection::INBOUND, 0x82, buffer.get(),
                           buffer->size(),
                           10,  // 10 millisecond timeout
                           completion.callback());
 
   completion.WaitForResult();
-  ASSERT_EQ(USB_TRANSFER_TIMEOUT, completion.status());
+  ASSERT_EQ(UsbTransferStatus::TIMEOUT, completion.status());
 
   handle->Close();
 }
diff --git a/device/usb/usb_device_handle_usbfs.cc b/device/usb/usb_device_handle_usbfs.cc
index 6871cdc..d168e2f 100644
--- a/device/usb/usb_device_handle_usbfs.cc
+++ b/device/usb/usb_device_handle_usbfs.cc
@@ -32,41 +32,41 @@
 
 namespace {
 
-uint8_t ConvertEndpointDirection(UsbEndpointDirection direction) {
+uint8_t ConvertEndpointDirection(UsbTransferDirection direction) {
   switch (direction) {
-    case USB_DIRECTION_INBOUND:
+    case UsbTransferDirection::INBOUND:
       return USB_DIR_IN;
-    case USB_DIRECTION_OUTBOUND:
+    case UsbTransferDirection::OUTBOUND:
       return USB_DIR_OUT;
   }
   NOTREACHED();
   return 0;
 }
 
-uint8_t ConvertRequestType(UsbDeviceHandle::TransferRequestType request_type) {
+uint8_t ConvertRequestType(UsbControlTransferType request_type) {
   switch (request_type) {
-    case UsbDeviceHandle::STANDARD:
+    case UsbControlTransferType::STANDARD:
       return USB_TYPE_STANDARD;
-    case UsbDeviceHandle::CLASS:
+    case UsbControlTransferType::CLASS:
       return USB_TYPE_CLASS;
-    case UsbDeviceHandle::VENDOR:
+    case UsbControlTransferType::VENDOR:
       return USB_TYPE_VENDOR;
-    case UsbDeviceHandle::RESERVED:
+    case UsbControlTransferType::RESERVED:
       return USB_TYPE_RESERVED;
   }
   NOTREACHED();
   return 0;
 }
 
-uint8_t ConvertRecipient(UsbDeviceHandle::TransferRecipient recipient) {
+uint8_t ConvertRecipient(UsbControlTransferRecipient recipient) {
   switch (recipient) {
-    case UsbDeviceHandle::DEVICE:
+    case UsbControlTransferRecipient::DEVICE:
       return USB_RECIP_DEVICE;
-    case UsbDeviceHandle::INTERFACE:
+    case UsbControlTransferRecipient::INTERFACE:
       return USB_RECIP_INTERFACE;
-    case UsbDeviceHandle::ENDPOINT:
+    case UsbControlTransferRecipient::ENDPOINT:
       return USB_RECIP_ENDPOINT;
-    case UsbDeviceHandle::OTHER:
+    case UsbControlTransferRecipient::OTHER:
       return USB_RECIP_OTHER;
   }
   NOTREACHED();
@@ -74,9 +74,9 @@
 }
 
 scoped_refptr<net::IOBuffer> BuildControlTransferBuffer(
-    UsbEndpointDirection direction,
-    UsbDeviceHandle::TransferRequestType request_type,
-    UsbDeviceHandle::TransferRecipient recipient,
+    UsbTransferDirection direction,
+    UsbControlTransferType request_type,
+    UsbControlTransferRecipient recipient,
     uint8_t request,
     uint16_t value,
     uint16_t index,
@@ -100,13 +100,13 @@
 
 uint8_t ConvertTransferType(UsbTransferType type) {
   switch (type) {
-    case USB_TRANSFER_CONTROL:
+    case UsbTransferType::CONTROL:
       return USBDEVFS_URB_TYPE_CONTROL;
-    case USB_TRANSFER_ISOCHRONOUS:
+    case UsbTransferType::ISOCHRONOUS:
       return USBDEVFS_URB_TYPE_ISO;
-    case USB_TRANSFER_BULK:
+    case UsbTransferType::BULK:
       return USBDEVFS_URB_TYPE_BULK;
-    case USB_TRANSFER_INTERRUPT:
+    case UsbTransferType::INTERRUPT:
       return USBDEVFS_URB_TYPE_INTERRUPT;
   }
   NOTREACHED();
@@ -116,19 +116,19 @@
 UsbTransferStatus ConvertTransferResult(int rc) {
   switch (rc) {
     case 0:
-      return USB_TRANSFER_COMPLETED;
+      return UsbTransferStatus::COMPLETED;
     case EPIPE:
-      return USB_TRANSFER_STALLED;
+      return UsbTransferStatus::STALLED;
     case ENODEV:
     case ESHUTDOWN:
     case EPROTO:
-      return USB_TRANSFER_DISCONNECT;
+      return UsbTransferStatus::DISCONNECT;
     default:
       // TODO(reillyg): Add a specific error message whenever one of the cases
       // above fails to match.
       USB_LOG(ERROR) << "Unknown system error: "
                      << logging::SystemErrorCodeToString(rc);
-      return USB_TRANSFER_ERROR;
+      return UsbTransferStatus::TRANSFER_ERROR;
   }
 }
 
@@ -437,7 +437,7 @@
   device_ = nullptr;
 
   for (const auto& transfer : transfers_)
-    CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED);
+    CancelTransfer(transfer.get(), UsbTransferStatus::CANCELLED);
 
   // Releases |helper_|.
   blocking_task_runner_->PostTask(
@@ -551,19 +551,21 @@
                  base::Unretained(helper_.get()), endpoint_address, callback));
 }
 
-void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction,
-                                           TransferRequestType request_type,
-                                           TransferRecipient recipient,
-                                           uint8_t request,
-                                           uint16_t value,
-                                           uint16_t index,
-                                           scoped_refptr<net::IOBuffer> buffer,
-                                           size_t length,
-                                           unsigned int timeout,
-                                           const TransferCallback& callback) {
+void UsbDeviceHandleUsbfs::ControlTransfer(
+    UsbTransferDirection direction,
+    UsbControlTransferType request_type,
+    UsbControlTransferRecipient recipient,
+    uint8_t request,
+    uint16_t value,
+    uint16_t index,
+    scoped_refptr<net::IOBuffer> buffer,
+    size_t length,
+    unsigned int timeout,
+    const TransferCallback& callback) {
   if (!device_) {
     task_runner_->PostTask(
-        FROM_HERE, base::Bind(callback, USB_TRANSFER_DISCONNECT, nullptr, 0));
+        FROM_HERE,
+        base::Bind(callback, UsbTransferStatus::DISCONNECT, nullptr, 0));
     return;
   }
 
@@ -617,7 +619,7 @@
                               packet_lengths, timeout, callback);
 }
 
-void UsbDeviceHandleUsbfs::GenericTransfer(UsbEndpointDirection direction,
+void UsbDeviceHandleUsbfs::GenericTransfer(UsbTransferDirection direction,
                                            uint8_t endpoint_number,
                                            scoped_refptr<net::IOBuffer> buffer,
                                            size_t length,
@@ -689,7 +691,8 @@
     unsigned int timeout,
     const IsochronousTransferCallback& callback) {
   if (!device_) {
-    ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT);
+    ReportIsochronousError(packet_lengths, callback,
+                           UsbTransferStatus::DISCONNECT);
     return;
   }
 
@@ -697,7 +700,8 @@
   if (it == endpoints_.end()) {
     USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address)
                   << " is not part of a claimed interface.";
-    ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_ERROR);
+    ReportIsochronousError(packet_lengths, callback,
+                           UsbTransferStatus::TRANSFER_ERROR);
     return;
   }
 
@@ -726,7 +730,7 @@
 }
 
 void UsbDeviceHandleUsbfs::GenericTransferInternal(
-    UsbEndpointDirection direction,
+    UsbTransferDirection direction,
     uint8_t endpoint_number,
     scoped_refptr<net::IOBuffer> buffer,
     size_t length,
@@ -735,7 +739,8 @@
     scoped_refptr<base::SingleThreadTaskRunner> callback_runner) {
   if (!device_) {
     callback_runner->PostTask(
-        FROM_HERE, base::Bind(callback, USB_TRANSFER_DISCONNECT, nullptr, 0));
+        FROM_HERE,
+        base::Bind(callback, UsbTransferStatus::DISCONNECT, nullptr, 0));
     return;
   }
 
@@ -746,7 +751,8 @@
     USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address)
                   << " is not part of a claimed interface.";
     callback_runner->PostTask(
-        FROM_HERE, base::Bind(callback, USB_TRANSFER_ERROR, nullptr, 0));
+        FROM_HERE,
+        base::Bind(callback, UsbTransferStatus::TRANSFER_ERROR, nullptr, 0));
     return;
   }
 
@@ -867,7 +873,7 @@
   if (timeout > 0) {
     transfer->timeout_closure.Reset(
         base::Bind(&UsbDeviceHandleUsbfs::CancelTransfer, this, transfer,
-                   USB_TRANSFER_TIMEOUT));
+                   UsbTransferStatus::TIMEOUT));
     task_runner_->PostDelayedTask(FROM_HERE,
                                   transfer->timeout_closure.callback(),
                                   base::TimeDelta::FromMilliseconds(timeout));
diff --git a/device/usb/usb_device_handle_usbfs.h b/device/usb/usb_device_handle_usbfs.h
index e49de9b..a9bf1e27 100644
--- a/device/usb/usb_device_handle_usbfs.h
+++ b/device/usb/usb_device_handle_usbfs.h
@@ -50,9 +50,9 @@
                                     const ResultCallback& callback) override;
   void ResetDevice(const ResultCallback& callback) override;
   void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override;
-  void ControlTransfer(UsbEndpointDirection direction,
-                       TransferRequestType request_type,
-                       TransferRecipient recipient,
+  void ControlTransfer(UsbTransferDirection direction,
+                       UsbControlTransferType request_type,
+                       UsbControlTransferRecipient recipient,
                        uint8_t request,
                        uint16_t value,
                        uint16_t index,
@@ -73,7 +73,7 @@
       const IsochronousTransferCallback& callback) override;
   // To support DevTools this function may be called from any thread and on
   // completion |callback| will be run on that thread.
-  void GenericTransfer(UsbEndpointDirection direction,
+  void GenericTransfer(UsbTransferDirection direction,
                        uint8_t endpoint_number,
                        scoped_refptr<net::IOBuffer> buffer,
                        size_t length,
@@ -119,7 +119,7 @@
                                    unsigned int timeout,
                                    const IsochronousTransferCallback& callback);
   void GenericTransferInternal(
-      UsbEndpointDirection direction,
+      UsbTransferDirection direction,
       uint8_t endpoint_number,
       scoped_refptr<net::IOBuffer> buffer,
       size_t length,
diff --git a/device/usb/usb_device_handle_win.cc b/device/usb/usb_device_handle_win.cc
index 74a7de6..f8a54a2 100644
--- a/device/usb/usb_device_handle_win.cc
+++ b/device/usb/usb_device_handle_win.cc
@@ -158,9 +158,9 @@
   }
 }
 
-void UsbDeviceHandleWin::ControlTransfer(UsbEndpointDirection direction,
-                                         TransferRequestType request_type,
-                                         TransferRecipient recipient,
+void UsbDeviceHandleWin::ControlTransfer(UsbTransferDirection direction,
+                                         UsbControlTransferType request_type,
+                                         UsbControlTransferRecipient recipient,
                                          uint8_t request,
                                          uint16_t value,
                                          uint16_t index,
@@ -172,14 +172,15 @@
 
   if (!device_) {
     task_runner_->PostTask(
-        FROM_HERE, base::Bind(callback, USB_TRANSFER_DISCONNECT, nullptr, 0));
+        FROM_HERE,
+        base::Bind(callback, UsbTransferStatus::DISCONNECT, nullptr, 0));
     return;
   }
 
   if (hub_handle_.IsValid()) {
-    if (direction == USB_DIRECTION_INBOUND &&
-        request_type == TransferRequestType::STANDARD &&
-        recipient == TransferRecipient::DEVICE &&
+    if (direction == UsbTransferDirection::INBOUND &&
+        request_type == UsbControlTransferType::STANDARD &&
+        recipient == UsbControlTransferRecipient::DEVICE &&
         request == USB_REQUEST_GET_DESCRIPTOR) {
       if ((value >> 8) == USB_DEVICE_DESCRIPTOR_TYPE) {
         auto* node_connection_info = new USB_NODE_CONNECTION_INFORMATION_EX;
@@ -225,13 +226,15 @@
 
     // Unsupported transfer for hub.
     task_runner_->PostTask(
-        FROM_HERE, base::Bind(callback, USB_TRANSFER_ERROR, nullptr, 0));
+        FROM_HERE,
+        base::Bind(callback, UsbTransferStatus::TRANSFER_ERROR, nullptr, 0));
     return;
   }
 
   // Regular control transfers unimplemented.
-  task_runner_->PostTask(FROM_HERE,
-                         base::Bind(callback, USB_TRANSFER_ERROR, nullptr, 0));
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(callback, UsbTransferStatus::TRANSFER_ERROR, nullptr, 0));
 }
 
 void UsbDeviceHandleWin::IsochronousTransferIn(
@@ -251,7 +254,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 }
 
-void UsbDeviceHandleWin::GenericTransfer(UsbEndpointDirection direction,
+void UsbDeviceHandleWin::GenericTransfer(UsbTransferDirection direction,
                                          uint8_t endpoint_number,
                                          scoped_refptr<net::IOBuffer> buffer,
                                          size_t length,
@@ -310,7 +313,7 @@
   if (win32_result != ERROR_SUCCESS) {
     SetLastError(win32_result);
     USB_PLOG(ERROR) << "Failed to get node connection information";
-    callback.Run(USB_TRANSFER_ERROR, nullptr, 0);
+    callback.Run(UsbTransferStatus::TRANSFER_ERROR, nullptr, 0);
     return;
   }
 
@@ -318,7 +321,7 @@
   bytes_transferred = std::min(sizeof(USB_DEVICE_DESCRIPTOR), buffer_length);
   memcpy(buffer->data(), &node_connection_info->DeviceDescriptor,
          bytes_transferred);
-  callback.Run(USB_TRANSFER_COMPLETED, buffer, bytes_transferred);
+  callback.Run(UsbTransferStatus::COMPLETED, buffer, bytes_transferred);
 }
 
 void UsbDeviceHandleWin::GotDescriptorFromNodeConnection(
@@ -334,7 +337,7 @@
   if (win32_result != ERROR_SUCCESS) {
     SetLastError(win32_result);
     USB_PLOG(ERROR) << "Failed to read descriptor from node connection";
-    callback.Run(USB_TRANSFER_ERROR, nullptr, 0);
+    callback.Run(UsbTransferStatus::TRANSFER_ERROR, nullptr, 0);
     return;
   }
 
@@ -343,7 +346,8 @@
   memcpy(original_buffer->data(),
          request_buffer->data() + sizeof(USB_DESCRIPTOR_REQUEST),
          bytes_transferred);
-  callback.Run(USB_TRANSFER_COMPLETED, original_buffer, bytes_transferred);
+  callback.Run(UsbTransferStatus::COMPLETED, original_buffer,
+               bytes_transferred);
 }
 
 }  // namespace device
diff --git a/device/usb/usb_device_handle_win.h b/device/usb/usb_device_handle_win.h
index 69e6e28..75b65f6 100644
--- a/device/usb/usb_device_handle_win.h
+++ b/device/usb/usb_device_handle_win.h
@@ -46,9 +46,9 @@
   void ResetDevice(const ResultCallback& callback) override;
   void ClearHalt(uint8_t endpoint, const ResultCallback& callback) override;
 
-  void ControlTransfer(UsbEndpointDirection direction,
-                       TransferRequestType request_type,
-                       TransferRecipient recipient,
+  void ControlTransfer(UsbTransferDirection direction,
+                       UsbControlTransferType request_type,
+                       UsbControlTransferRecipient recipient,
                        uint8_t request,
                        uint16_t value,
                        uint16_t index,
@@ -70,7 +70,7 @@
       unsigned int timeout,
       const IsochronousTransferCallback& callback) override;
 
-  void GenericTransfer(UsbEndpointDirection direction,
+  void GenericTransfer(UsbTransferDirection direction,
                        uint8_t endpoint_number,
                        scoped_refptr<net::IOBuffer> buffer,
                        size_t length,
diff --git a/device/usb/webusb_descriptors.cc b/device/usb/webusb_descriptors.cc
index 1bc243d..e2ebc14 100644
--- a/device/usb/webusb_descriptors.cc
+++ b/device/usb/webusb_descriptors.cc
@@ -192,7 +192,7 @@
                          UsbTransferStatus status,
                          scoped_refptr<net::IOBuffer> buffer,
                          size_t length) {
-  if (status != USB_TRANSFER_COMPLETED) {
+  if (status != UsbTransferStatus::COMPLETED) {
     USB_LOG(EVENT) << "Failed to read WebUSB URL descriptor: " << index;
     callback.Run();
     return;
@@ -216,9 +216,9 @@
                        const base::Closure& callback) {
   scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(255);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE,
-      vendor_code, index, kGetUrlRequest, buffer, buffer->size(),
-      kControlTransferTimeout,
+      UsbTransferDirection::INBOUND, UsbControlTransferType::VENDOR,
+      UsbControlTransferRecipient::DEVICE, vendor_code, index, kGetUrlRequest,
+      buffer, buffer->size(), kControlTransferTimeout,
       base::Bind(&OnReadUrlDescriptor, url_map, index, callback));
 }
 
@@ -265,7 +265,7 @@
     UsbTransferStatus status,
     scoped_refptr<net::IOBuffer> buffer,
     size_t length) {
-  if (status != USB_TRANSFER_COMPLETED) {
+  if (status != UsbTransferStatus::COMPLETED) {
     USB_LOG(EVENT) << "Failed to read WebUSB allowed origins.";
     callback.Run(nullptr);
     return;
@@ -288,7 +288,7 @@
     UsbTransferStatus status,
     scoped_refptr<net::IOBuffer> buffer,
     size_t length) {
-  if (status != USB_TRANSFER_COMPLETED || length != 4) {
+  if (status != UsbTransferStatus::COMPLETED || length != 4) {
     USB_LOG(EVENT) << "Failed to read WebUSB allowed origins header.";
     callback.Run(nullptr);
     return;
@@ -298,8 +298,9 @@
   uint16_t new_length = data[2] | (data[3] << 8);
   scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE,
-      vendor_code, 0, kGetAllowedOriginsRequest, new_buffer, new_buffer->size(),
+      UsbTransferDirection::INBOUND, UsbControlTransferType::VENDOR,
+      UsbControlTransferRecipient::DEVICE, vendor_code, 0,
+      kGetAllowedOriginsRequest, new_buffer, new_buffer->size(),
       kControlTransferTimeout,
       base::Bind(&OnReadWebUsbAllowedOrigins, callback));
 }
@@ -310,8 +311,9 @@
     const ReadWebUsbAllowedOriginsCallback& callback) {
   scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(4);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR, UsbDeviceHandle::DEVICE,
-      vendor_code, 0, kGetAllowedOriginsRequest, buffer, buffer->size(),
+      UsbTransferDirection::INBOUND, UsbControlTransferType::VENDOR,
+      UsbControlTransferRecipient::DEVICE, vendor_code, 0,
+      kGetAllowedOriginsRequest, buffer, buffer->size(),
       kControlTransferTimeout,
       base::Bind(&OnReadWebUsbAllowedOriginsHeader, device_handle, callback,
                  vendor_code));
@@ -322,7 +324,7 @@
                          UsbTransferStatus status,
                          scoped_refptr<net::IOBuffer> buffer,
                          size_t length) {
-  if (status != USB_TRANSFER_COMPLETED) {
+  if (status != UsbTransferStatus::COMPLETED) {
     USB_LOG(EVENT) << "Failed to read BOS descriptor.";
     callback.Run(nullptr, GURL());
     return;
@@ -346,7 +348,7 @@
                                UsbTransferStatus status,
                                scoped_refptr<net::IOBuffer> buffer,
                                size_t length) {
-  if (status != USB_TRANSFER_COMPLETED || length != 5) {
+  if (status != UsbTransferStatus::COMPLETED || length != 5) {
     USB_LOG(EVENT) << "Failed to read BOS descriptor header.";
     callback.Run(nullptr, GURL());
     return;
@@ -356,9 +358,10 @@
   uint16_t new_length = data[2] | (data[3] << 8);
   scoped_refptr<IOBufferWithSize> new_buffer = new IOBufferWithSize(new_length);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE,
-      kGetDescriptorRequest, kBosDescriptorType << 8, 0, new_buffer,
-      new_buffer->size(), kControlTransferTimeout,
+      UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+      UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
+      kBosDescriptorType << 8, 0, new_buffer, new_buffer->size(),
+      kControlTransferTimeout,
       base::Bind(&OnReadBosDescriptor, device_handle, callback));
 }
 
@@ -568,8 +571,9 @@
                            const ReadWebUsbDescriptorsCallback& callback) {
   scoped_refptr<IOBufferWithSize> buffer = new IOBufferWithSize(5);
   device_handle->ControlTransfer(
-      USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, UsbDeviceHandle::DEVICE,
-      kGetDescriptorRequest, kBosDescriptorType << 8, 0, buffer, buffer->size(),
+      UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
+      UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
+      kBosDescriptorType << 8, 0, buffer, buffer->size(),
       kControlTransferTimeout,
       base::Bind(&OnReadBosDescriptorHeader, device_handle, callback));
 }
diff --git a/device/usb/webusb_descriptors_unittest.cc b/device/usb/webusb_descriptors_unittest.cc
index 8350a6d..d0fd216 100644
--- a/device/usb/webusb_descriptors_unittest.cc
+++ b/device/usb/webusb_descriptors_unittest.cc
@@ -75,7 +75,7 @@
 ACTION_P2(InvokeCallback, data, length) {
   size_t transferred_length = std::min(length, arg7);
   memcpy(arg6->data(), data, transferred_length);
-  arg9.Run(USB_TRANSFER_COMPLETED, arg6, transferred_length);
+  arg9.Run(UsbTransferStatus::COMPLETED, arg6, transferred_length);
 }
 
 void ExpectAllowedOriginsAndLandingPage(
@@ -407,53 +407,61 @@
       new MockUsbDeviceHandle(nullptr));
 
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD,
-                              UsbDeviceHandle::DEVICE, 0x06, 0x0F00, 0x0000, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::STANDARD,
+                              UsbControlTransferRecipient::DEVICE, 0x06, 0x0F00,
+                              0x0000, _, _, _, _))
       .Times(2)
       .WillRepeatedly(
           InvokeCallback(kExampleBosDescriptor, sizeof(kExampleBosDescriptor)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0000, 0x0001, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0000,
+                              0x0001, _, _, _, _))
       .Times(2)
       .WillRepeatedly(InvokeCallback(kExampleAllowedOrigins,
                                      sizeof(kExampleAllowedOrigins)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0001, 0x0002, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0001,
+                              0x0002, _, _, _, _))
       .WillOnce(InvokeCallback(kExampleUrlDescriptor1,
                                sizeof(kExampleUrlDescriptor1)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0002, 0x0002, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0002,
+                              0x0002, _, _, _, _))
       .WillOnce(InvokeCallback(kExampleUrlDescriptor2,
                                sizeof(kExampleUrlDescriptor2)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0003, 0x0002, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0003,
+                              0x0002, _, _, _, _))
       .WillOnce(InvokeCallback(kExampleUrlDescriptor3,
                                sizeof(kExampleUrlDescriptor3)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0004, 0x0002, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0004,
+                              0x0002, _, _, _, _))
       .WillOnce(InvokeCallback(kExampleUrlDescriptor4,
                                sizeof(kExampleUrlDescriptor4)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0005, 0x0002, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0005,
+                              0x0002, _, _, _, _))
       .WillOnce(InvokeCallback(kExampleUrlDescriptor5,
                                sizeof(kExampleUrlDescriptor5)));
   EXPECT_CALL(*device_handle,
-              ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::VENDOR,
-                              UsbDeviceHandle::DEVICE, 0x42, 0x0006, 0x0002, _,
-                              _, _, _))
+              ControlTransfer(UsbTransferDirection::INBOUND,
+                              UsbControlTransferType::VENDOR,
+                              UsbControlTransferRecipient::DEVICE, 0x42, 0x0006,
+                              0x0002, _, _, _, _))
       .WillOnce(InvokeCallback(kExampleUrlDescriptor6,
                                sizeof(kExampleUrlDescriptor6)));
 
diff --git a/extensions/browser/api/BUILD.gn b/extensions/browser/api/BUILD.gn
index 05a3377..5392ebd 100644
--- a/extensions/browser/api/BUILD.gn
+++ b/extensions/browser/api/BUILD.gn
@@ -102,7 +102,6 @@
     "//device/hid",
     "//device/power_save_blocker",
     "//device/serial",
-    "//device/usb",
   ]
 
   if (is_chromeos) {
diff --git a/extensions/browser/api/printer_provider/BUILD.gn b/extensions/browser/api/printer_provider/BUILD.gn
index 0b242a0..b730331 100644
--- a/extensions/browser/api/printer_provider/BUILD.gn
+++ b/extensions/browser/api/printer_provider/BUILD.gn
@@ -13,6 +13,7 @@
   ]
 
   deps = [
+    "//device/usb",
     "//extensions/common/api",
   ]
 }
diff --git a/extensions/browser/api/usb/BUILD.gn b/extensions/browser/api/usb/BUILD.gn
index ceb5094..925e761 100644
--- a/extensions/browser/api/usb/BUILD.gn
+++ b/extensions/browser/api/usb/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     "//content/public/browser",
     "//content/public/common",
+    "//device/usb",
     "//extensions/common/api",
   ]
 }
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
index 6006dfb..8280a63 100644
--- a/extensions/browser/api/usb/usb_api.cc
+++ b/extensions/browser/api/usb/usb_api.cc
@@ -51,14 +51,16 @@
 
 using content::BrowserThread;
 using device::UsbConfigDescriptor;
+using device::UsbControlTransferRecipient;
+using device::UsbControlTransferType;
 using device::UsbDevice;
 using device::UsbDeviceFilter;
 using device::UsbDeviceHandle;
 using device::UsbEndpointDescriptor;
-using device::UsbEndpointDirection;
 using device::UsbInterfaceDescriptor;
 using device::UsbService;
 using device::UsbSynchronizationType;
+using device::UsbTransferDirection;
 using device::UsbTransferStatus;
 using device::UsbTransferType;
 using device::UsbUsageType;
@@ -127,13 +129,13 @@
 const int kMaxPacketLength = 64 * 1024;
 
 bool ConvertDirectionFromApi(const Direction& input,
-                             UsbEndpointDirection* output) {
+                             UsbTransferDirection* output) {
   switch (input) {
     case usb::DIRECTION_IN:
-      *output = device::USB_DIRECTION_INBOUND;
+      *output = UsbTransferDirection::INBOUND;
       return true;
     case usb::DIRECTION_OUT:
-      *output = device::USB_DIRECTION_OUTBOUND;
+      *output = UsbTransferDirection::OUTBOUND;
       return true;
     default:
       NOTREACHED();
@@ -142,19 +144,19 @@
 }
 
 bool ConvertRequestTypeFromApi(const RequestType& input,
-                               UsbDeviceHandle::TransferRequestType* output) {
+                               UsbControlTransferType* output) {
   switch (input) {
     case usb::REQUEST_TYPE_STANDARD:
-      *output = UsbDeviceHandle::STANDARD;
+      *output = UsbControlTransferType::STANDARD;
       return true;
     case usb::REQUEST_TYPE_CLASS:
-      *output = UsbDeviceHandle::CLASS;
+      *output = UsbControlTransferType::CLASS;
       return true;
     case usb::REQUEST_TYPE_VENDOR:
-      *output = UsbDeviceHandle::VENDOR;
+      *output = UsbControlTransferType::VENDOR;
       return true;
     case usb::REQUEST_TYPE_RESERVED:
-      *output = UsbDeviceHandle::RESERVED;
+      *output = UsbControlTransferType::RESERVED;
       return true;
     default:
       NOTREACHED();
@@ -163,19 +165,19 @@
 }
 
 bool ConvertRecipientFromApi(const Recipient& input,
-                             UsbDeviceHandle::TransferRecipient* output) {
+                             UsbControlTransferRecipient* output) {
   switch (input) {
     case usb::RECIPIENT_DEVICE:
-      *output = UsbDeviceHandle::DEVICE;
+      *output = UsbControlTransferRecipient::DEVICE;
       return true;
     case usb::RECIPIENT_INTERFACE:
-      *output = UsbDeviceHandle::INTERFACE;
+      *output = UsbControlTransferRecipient::INTERFACE;
       return true;
     case usb::RECIPIENT_ENDPOINT:
-      *output = UsbDeviceHandle::ENDPOINT;
+      *output = UsbControlTransferRecipient::ENDPOINT;
       return true;
     case usb::RECIPIENT_OTHER:
-      *output = UsbDeviceHandle::OTHER;
+      *output = UsbControlTransferRecipient::OTHER;
       return true;
     default:
       NOTREACHED();
@@ -204,7 +206,7 @@
 template <class T>
 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
     const T& input,
-    UsbEndpointDirection direction,
+    UsbTransferDirection direction,
     size_t size) {
   if (size >= kMaxTransferLength)
     return NULL;
@@ -215,9 +217,9 @@
   scoped_refptr<net::IOBuffer> buffer =
       new net::IOBuffer(std::max(static_cast<size_t>(1), size));
 
-  if (direction == device::USB_DIRECTION_INBOUND) {
+  if (direction == UsbTransferDirection::INBOUND) {
     return buffer;
-  } else if (direction == device::USB_DIRECTION_OUTBOUND) {
+  } else if (direction == UsbTransferDirection::OUTBOUND) {
     if (input.data.get() && size <= input.data->size()) {
       memcpy(buffer->data(), input.data->data(), size);
       return buffer;
@@ -229,21 +231,21 @@
 
 const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
   switch (status) {
-    case device::USB_TRANSFER_COMPLETED:
+    case UsbTransferStatus::COMPLETED:
       return "";
-    case device::USB_TRANSFER_ERROR:
+    case UsbTransferStatus::TRANSFER_ERROR:
       return kErrorGeneric;
-    case device::USB_TRANSFER_TIMEOUT:
+    case UsbTransferStatus::TIMEOUT:
       return kErrorTimeout;
-    case device::USB_TRANSFER_CANCELLED:
+    case UsbTransferStatus::CANCELLED:
       return kErrorCancelled;
-    case device::USB_TRANSFER_STALLED:
+    case UsbTransferStatus::STALLED:
       return kErrorStalled;
-    case device::USB_TRANSFER_DISCONNECT:
+    case UsbTransferStatus::DISCONNECT:
       return kErrorDisconnect;
-    case device::USB_TRANSFER_OVERFLOW:
+    case UsbTransferStatus::BABBLE:
       return kErrorOverflow;
-    case device::USB_TRANSFER_LENGTH_SHORT:
+    case UsbTransferStatus::SHORT_PACKET:
       return kErrorTransferLength;
     default:
       NOTREACHED();
@@ -263,13 +265,13 @@
 
 TransferType ConvertTransferTypeToApi(const UsbTransferType& input) {
   switch (input) {
-    case device::USB_TRANSFER_CONTROL:
+    case UsbTransferType::CONTROL:
       return usb::TRANSFER_TYPE_CONTROL;
-    case device::USB_TRANSFER_INTERRUPT:
+    case UsbTransferType::INTERRUPT:
       return usb::TRANSFER_TYPE_INTERRUPT;
-    case device::USB_TRANSFER_ISOCHRONOUS:
+    case UsbTransferType::ISOCHRONOUS:
       return usb::TRANSFER_TYPE_ISOCHRONOUS;
-    case device::USB_TRANSFER_BULK:
+    case UsbTransferType::BULK:
       return usb::TRANSFER_TYPE_BULK;
     default:
       NOTREACHED();
@@ -277,11 +279,11 @@
   }
 }
 
-Direction ConvertDirectionToApi(const UsbEndpointDirection& input) {
+Direction ConvertDirectionToApi(const UsbTransferDirection& input) {
   switch (input) {
-    case device::USB_DIRECTION_INBOUND:
+    case UsbTransferDirection::INBOUND:
       return usb::DIRECTION_IN;
-    case device::USB_DIRECTION_OUTBOUND:
+    case UsbTransferDirection::OUTBOUND:
       return usb::DIRECTION_OUT;
     default:
       NOTREACHED();
@@ -463,7 +465,7 @@
                                       size_t length) {
   std::unique_ptr<base::DictionaryValue> transfer_info(
       new base::DictionaryValue());
-  transfer_info->SetInteger(kResultCodeKey, status);
+  transfer_info->SetInteger(kResultCodeKey, static_cast<int>(status));
 
   if (data) {
     transfer_info->Set(
@@ -472,7 +474,7 @@
     transfer_info->Set(kDataKey, new base::Value(base::Value::Type::BINARY));
   }
 
-  if (status == device::USB_TRANSFER_COMPLETED) {
+  if (status == UsbTransferStatus::COMPLETED) {
     Respond(OneArgument(std::move(transfer_info)));
   } else {
     std::unique_ptr<base::ListValue> error_args(new base::ListValue());
@@ -1016,9 +1018,9 @@
   }
 
   const ControlTransferInfo& transfer = parameters->transfer_info;
-  UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
-  UsbDeviceHandle::TransferRequestType request_type;
-  UsbDeviceHandle::TransferRecipient recipient;
+  UsbTransferDirection direction = UsbTransferDirection::INBOUND;
+  UsbControlTransferType request_type;
+  UsbControlTransferRecipient recipient;
   size_t size = 0;
 
   if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
@@ -1073,7 +1075,7 @@
   }
 
   const GenericTransferInfo& transfer = parameters->transfer_info;
-  UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
+  UsbTransferDirection direction = UsbTransferDirection::INBOUND;
   size_t size = 0;
 
   if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
@@ -1119,7 +1121,7 @@
   }
 
   const GenericTransferInfo& transfer = parameters->transfer_info;
-  UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
+  UsbTransferDirection direction = UsbTransferDirection::INBOUND;
   size_t size = 0;
 
   if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
@@ -1167,7 +1169,7 @@
   const IsochronousTransferInfo& transfer = parameters->transfer_info;
   const GenericTransferInfo& generic_transfer = transfer.transfer_info;
   size_t size = 0;
-  UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
+  UsbTransferDirection direction = UsbTransferDirection::INBOUND;
 
   if (!ConvertDirectionFromApi(generic_transfer.direction, &direction))
     return RespondNow(Error(kErrorConvertDirection));
@@ -1193,7 +1195,7 @@
   if (timeout < 0)
     return RespondNow(Error(kErrorInvalidTimeout));
 
-  if (direction == device::USB_DIRECTION_INBOUND) {
+  if (direction == UsbTransferDirection::INBOUND) {
     device_handle->IsochronousTransferIn(
         generic_transfer.endpoint, packet_lengths, timeout,
         base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
@@ -1221,12 +1223,12 @@
   std::vector<char> buffer;
   buffer.reserve(length);
 
-  UsbTransferStatus status = device::USB_TRANSFER_COMPLETED;
+  UsbTransferStatus status = UsbTransferStatus::COMPLETED;
   const char* data_ptr = data ? data->data() : nullptr;
   for (const auto& packet : packets) {
     // Capture the error status of the first unsuccessful packet.
-    if (status == device::USB_TRANSFER_COMPLETED &&
-        packet.status != device::USB_TRANSFER_COMPLETED) {
+    if (status == UsbTransferStatus::COMPLETED &&
+        packet.status != UsbTransferStatus::COMPLETED) {
       status = packet.status;
     }
 
@@ -1239,9 +1241,9 @@
 
   std::unique_ptr<base::DictionaryValue> transfer_info(
       new base::DictionaryValue());
-  transfer_info->SetInteger(kResultCodeKey, status);
+  transfer_info->SetInteger(kResultCodeKey, static_cast<int>(status));
   transfer_info->Set(kDataKey, new base::Value(std::move(buffer)));
-  if (status == device::USB_TRANSFER_COMPLETED) {
+  if (status == UsbTransferStatus::COMPLETED) {
     Respond(OneArgument(std::move(transfer_info)));
   } else {
     std::unique_ptr<base::ListValue> error_args(new base::ListValue());
diff --git a/extensions/browser/api/usb/usb_apitest.cc b/extensions/browser/api/usb/usb_apitest.cc
index 9057178f..313e0c74 100644
--- a/extensions/browser/api/usb/usb_apitest.cc
+++ b/extensions/browser/api/usb/usb_apitest.cc
@@ -28,9 +28,12 @@
 using device::MockUsbDevice;
 using device::MockUsbDeviceHandle;
 using device::UsbConfigDescriptor;
+using device::UsbControlTransferRecipient;
+using device::UsbControlTransferType;
 using device::UsbDeviceHandle;
-using device::UsbEndpointDirection;
 using device::UsbInterfaceDescriptor;
+using device::UsbTransferDirection;
+using device::UsbTransferStatus;
 
 namespace extensions {
 
@@ -47,7 +50,7 @@
                 AND_1_VALUE_PARAMS(p1)) {
   net::IOBuffer* io_buffer = nullptr;
   size_t length = 0;
-  if (p1 != device::USB_TRANSFER_ERROR) {
+  if (p1 != UsbTransferStatus::TRANSFER_ERROR) {
     length = 1;
     io_buffer = new net::IOBuffer(length);
     memset(io_buffer->data(), 0, length);  // Avoid uninitialized reads.
@@ -63,10 +66,10 @@
     packets[i].length = arg2[i];
     if (i < success_packets) {
       packets[i].transferred_length = transferred_length;
-      packets[i].status = device::USB_TRANSFER_COMPLETED;
+      packets[i].status = UsbTransferStatus::COMPLETED;
     } else {
       packets[i].transferred_length = 0;
-      packets[i].status = device::USB_TRANSFER_ERROR;
+      packets[i].status = UsbTransferStatus::TRANSFER_ERROR;
     }
   }
   arg4.Run(arg1, packets);
@@ -84,10 +87,10 @@
     packets[i].transferred_length = transferred_length;
     if (i < success_packets) {
       packets[i].transferred_length = transferred_length;
-      packets[i].status = device::USB_TRANSFER_COMPLETED;
+      packets[i].status = UsbTransferStatus::COMPLETED;
     } else {
       packets[i].transferred_length = 0;
-      packets[i].status = device::USB_TRANSFER_ERROR;
+      packets[i].status = UsbTransferStatus::TRANSFER_ERROR;
     }
   }
   arg3.Run(io_buffer, packets);
@@ -178,8 +181,8 @@
       .WillOnce(InvokeCallback<0>(true))
       .WillOnce(InvokeCallback<0>(false));
   EXPECT_CALL(*mock_device_handle_,
-              GenericTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
+              GenericTransfer(UsbTransferDirection::OUTBOUND, 2, _, 1, _, _))
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::COMPLETED));
   ASSERT_TRUE(RunAppTest("api_test/usb/reset_device"));
 }
 
@@ -199,15 +202,16 @@
 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) {
   EXPECT_CALL(
       *mock_device_handle_,
-      ControlTransfer(device::USB_DIRECTION_OUTBOUND, UsbDeviceHandle::STANDARD,
-                      UsbDeviceHandle::DEVICE, 1, 2, 3, _, 1, _, _))
-      .WillOnce(InvokeUsbTransferCallback<9>(device::USB_TRANSFER_COMPLETED));
+      ControlTransfer(UsbTransferDirection::OUTBOUND,
+                      UsbControlTransferType::STANDARD,
+                      UsbControlTransferRecipient::DEVICE, 1, 2, 3, _, 1, _, _))
+      .WillOnce(InvokeUsbTransferCallback<9>(UsbTransferStatus::COMPLETED));
   EXPECT_CALL(*mock_device_handle_,
-              GenericTransfer(device::USB_DIRECTION_OUTBOUND, 1, _, 1, _, _))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
+              GenericTransfer(UsbTransferDirection::OUTBOUND, 1, _, 1, _, _))
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::COMPLETED));
   EXPECT_CALL(*mock_device_handle_,
-              GenericTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
+              GenericTransfer(UsbTransferDirection::OUTBOUND, 2, _, 1, _, _))
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::COMPLETED));
   EXPECT_CALL(*mock_device_handle_, IsochronousTransferOut(3, _, _, _, _))
       .WillOnce(InvokeUsbIsochronousTransferOutCallback(1, 1u));
   EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber());
@@ -216,17 +220,17 @@
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) {
   EXPECT_CALL(*mock_device_handle_, GenericTransfer(_, _, _, 0, _, _))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::COMPLETED));
   EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber());
   ASSERT_TRUE(RunAppTest("api_test/usb/zero_length_transfer"));
 }
 
 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) {
   EXPECT_CALL(*mock_device_handle_,
-              GenericTransfer(device::USB_DIRECTION_OUTBOUND, 1, _, _, _, _))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_ERROR))
-      .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_TIMEOUT));
+              GenericTransfer(UsbTransferDirection::OUTBOUND, 1, _, _, _, _))
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::COMPLETED))
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::TRANSFER_ERROR))
+      .WillOnce(InvokeUsbTransferCallback<5>(UsbTransferStatus::TIMEOUT));
   EXPECT_CALL(*mock_device_handle_, IsochronousTransferIn(2, _, _, _))
       .WillOnce(InvokeUsbIsochronousTransferInCallback(8, 10u))
       .WillOnce(InvokeUsbIsochronousTransferInCallback(8, 5u));
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc
index 0d0e85f0..54423d5 100644
--- a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc
+++ b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.cc
@@ -12,6 +12,7 @@
 #include "base/numerics/safe_math.h"
 #include "base/process/memory.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/gpu_memory_buffer_tracing.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace gpu {
@@ -211,4 +212,10 @@
   return handle;
 }
 
+base::trace_event::MemoryAllocatorDumpGuid
+GpuMemoryBufferImplSharedMemory::GetGUIDForTracing(
+    uint64_t tracing_process_id) const {
+  return gfx::GetSharedMemoryGUIDForTracing(tracing_process_id, id_);
+}
+
 }  // namespace gpu
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h
index 243d3d5..47577fa 100644
--- a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h
+++ b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h
@@ -55,6 +55,8 @@
   void Unmap() override;
   int stride(size_t plane) const override;
   gfx::GpuMemoryBufferHandle GetHandle() const override;
+  base::trace_event::MemoryAllocatorDumpGuid GetGUIDForTracing(
+      uint64_t tracing_process_id) const override;
 
  private:
   GpuMemoryBufferImplSharedMemory(
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm b/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm
index ae764af..0ae51f2 100644
--- a/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm
+++ b/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm
@@ -4,7 +4,10 @@
 
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 
+#include "base/bind.h"
+#include "base/logging.h"
 #include "base/mac/foundation_util.h"
+#include "base/strings/string_piece.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
@@ -54,7 +57,10 @@
   ItemTypeWeasleyFooter,
 };
 
-void LogSink(const std::string& str) {
+void LogSink(const char* file,
+             int line,
+             const base::StringPiece message,
+             const base::StringPiece stack_trace) {
   // No-op.
 }
 
@@ -312,7 +318,7 @@
   CollectionViewModel* model = [[CollectionViewModel alloc] init];
   [model addSectionWithIdentifier:SectionIdentifierCheese];
 
-  logging::SetLogAssertHandler(&LogSink);
+  logging::ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
   bool out_of_bounds_exception_thrown = false;
   @try {
     [model indexInItemTypeForIndexPath:[NSIndexPath indexPathForItem:0
@@ -323,7 +329,6 @@
     }
   }
   EXPECT_TRUE(out_of_bounds_exception_thrown);
-  logging::SetLogAssertHandler(nullptr);
 }
 
 TEST(CollectionViewModelTest, RemoveItems) {
diff --git a/ios/chrome/browser/ui/dialogs/BUILD.gn b/ios/chrome/browser/ui/dialogs/BUILD.gn
index f28a15c..d28a3a5 100644
--- a/ios/chrome/browser/ui/dialogs/BUILD.gn
+++ b/ios/chrome/browser/ui/dialogs/BUILD.gn
@@ -34,6 +34,7 @@
 }
 
 source_set("dialogs_internal") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "dialog_presenter.h",
     "dialog_presenter.mm",
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
index 55282667..5be1336d 100644
--- a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
+++ b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
@@ -8,7 +8,6 @@
 #include <map>
 
 #import "base/ios/block_types.h"
-#import "base/ios/weak_nsobject.h"
 #include "base/logging.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
@@ -24,6 +23,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // Externed accessibility identifier.
 NSString* const kJavaScriptDialogTextFieldAccessibiltyIdentifier =
     @"JavaScriptDialogTextFieldAccessibiltyIdentifier";
@@ -35,26 +38,19 @@
 }  // namespace
 
 @interface DialogPresenter () {
-  // Backing objects for properties of the same name.
-  base::WeakNSProtocol<id<DialogPresenterDelegate>> _delegate;
-  base::WeakNSObject<UIViewController> _viewController;
   // Queue of WebStates which correspond to the keys in
   // |_dialogCoordinatorsForWebStates|.
   std::deque<web::WebState*> _queuedWebStates;
   // A map associating queued webStates with their coordinators.
   std::map<web::WebState*, base::scoped_nsobject<AlertCoordinator>>
       _dialogCoordinatorsForWebStates;
-  web::WebState* _presentedDialogWebState;
-  base::scoped_nsobject<AlertCoordinator> _presentedDialogCoordinator;
-  base::scoped_nsobject<ActionSheetCoordinator>
-      _blockingConfirmationCoordinator;
 }
 
 // The delegate passed on initialization.
-@property(nonatomic, readonly) id<DialogPresenterDelegate> delegate;
+@property(weak, nonatomic, readonly) id<DialogPresenterDelegate> delegate;
 
 // The presenting view controller passed on initialization.
-@property(nonatomic, readonly) UIViewController* viewController;
+@property(weak, nonatomic, readonly) UIViewController* viewController;
 
 // Whether a modal dialog is currently being shown.
 @property(nonatomic, readonly, getter=isShowingDialog) BOOL showingDialog;
@@ -63,10 +59,10 @@
 @property(nonatomic) web::WebState* presentedDialogWebState;
 
 // The dialog that's currently being shown, if any.
-@property(nonatomic, retain) AlertCoordinator* presentedDialogCoordinator;
+@property(nonatomic, strong) AlertCoordinator* presentedDialogCoordinator;
 
 // The JavaScript dialog blocking confirmation action sheet being shown, if any.
-@property(nonatomic, retain) AlertCoordinator* blockingConfirmationCoordinator;
+@property(nonatomic, strong) AlertCoordinator* blockingConfirmationCoordinator;
 
 // Adds |context| and |coordinator| to the queue.  If a dialog is not already
 // being shown, |coordinator| will be presented.  Otherwise, |coordinator| will
@@ -106,14 +102,19 @@
 @implementation DialogPresenter
 
 @synthesize active = _active;
+@synthesize delegate = _delegate;
+@synthesize viewController = _viewController;
+@synthesize presentedDialogCoordinator = _presentedDialogCoordinator;
+@synthesize blockingConfirmationCoordinator = _blockingConfirmationCoordinator;
+@synthesize presentedDialogWebState = _presentedDialogWebState;
 
 - (instancetype)initWithDelegate:(id<DialogPresenterDelegate>)delegate
         presentingViewController:(UIViewController*)viewController {
   if ((self = [super init])) {
     DCHECK(delegate);
     DCHECK(viewController);
-    _delegate.reset(delegate);
-    _viewController.reset(viewController);
+    _delegate = delegate;
+    _viewController = viewController;
   }
   return self;
 }
@@ -127,47 +128,12 @@
   }
 }
 
-- (id<DialogPresenterDelegate>)delegate {
-  return _delegate;
-}
-
-- (UIViewController*)viewController {
-  return _viewController;
-}
-
 - (BOOL)isShowingDialog {
   DCHECK_EQ(self.presentedDialogWebState != nullptr,
             self.presentedDialogCoordinator != nil);
   return self.presentedDialogCoordinator != nil;
 }
 
-- (web::WebState*)presentedDialogWebState {
-  return _presentedDialogWebState;
-}
-
-- (void)setPresentedDialogWebState:(web::WebState*)presentedDialogWebState {
-  _presentedDialogWebState = presentedDialogWebState;
-}
-
-- (AlertCoordinator*)presentedDialogCoordinator {
-  return _presentedDialogCoordinator;
-}
-
-- (void)setPresentedDialogCoordinator:
-    (AlertCoordinator*)presentedDialogCoordinator {
-  _presentedDialogCoordinator.reset([presentedDialogCoordinator retain]);
-}
-
-- (ActionSheetCoordinator*)blockingConfirmationCoordinator {
-  return _blockingConfirmationCoordinator;
-}
-
-- (void)setBlockingConfirmationCoordinator:
-    (ActionSheetCoordinator*)blockingConfirmationActionSheetCoordinator {
-  _blockingConfirmationCoordinator.reset(
-      [blockingConfirmationActionSheetCoordinator retain]);
-}
-
 #pragma mark - Public
 
 - (void)runJavaScriptAlertPanelWithMessage:(NSString*)message
@@ -176,14 +142,14 @@
                          completionHandler:(void (^)(void))completionHandler {
   NSString* title =
       [DialogPresenter localizedTitleForJavaScriptAlertFromPage:requestURL];
-  AlertCoordinator* alertCoordinator = [[[AlertCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                           title:title
-                         message:message] autorelease];
+  AlertCoordinator* alertCoordinator =
+      [[AlertCoordinator alloc] initWithBaseViewController:self.viewController
+                                                     title:title
+                                                   message:message];
 
   // Handler.
-  base::WeakNSObject<DialogPresenter> weakSelf(self);
-  base::WeakNSObject<AlertCoordinator> weakCoordinator(alertCoordinator);
+  __weak DialogPresenter* weakSelf = self;
+  __weak AlertCoordinator* weakCoordinator = alertCoordinator;
   ProceduralBlock OKHandler = ^{
     if (completionHandler)
       completionHandler();
@@ -212,10 +178,10 @@
                                (void (^)(BOOL isConfirmed))completionHandler {
   NSString* title =
       [DialogPresenter localizedTitleForJavaScriptAlertFromPage:requestURL];
-  AlertCoordinator* alertCoordinator = [[[AlertCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                           title:title
-                         message:message] autorelease];
+  AlertCoordinator* alertCoordinator =
+      [[AlertCoordinator alloc] initWithBaseViewController:self.viewController
+                                                     title:title
+                                                   message:message];
 
   // Actions.
   ProceduralBlock confirmAction = ^{
@@ -249,13 +215,13 @@
                                 (void (^)(NSString* input))completionHandler {
   NSString* title =
       [DialogPresenter localizedTitleForJavaScriptAlertFromPage:requestURL];
-  InputAlertCoordinator* alertCoordinator = [[[InputAlertCoordinator alloc]
+  InputAlertCoordinator* alertCoordinator = [[InputAlertCoordinator alloc]
       initWithBaseViewController:self.viewController
                            title:title
-                         message:message] autorelease];
+                         message:message];
 
   // Actions.
-  base::WeakNSObject<InputAlertCoordinator> weakCoordinator(alertCoordinator);
+  __weak InputAlertCoordinator* weakCoordinator = alertCoordinator;
   ProceduralBlock confirmAction = ^{
     if (completionHandler) {
       NSString* textInput = [weakCoordinator textFields].firstObject.text;
@@ -299,13 +265,13 @@
       ios_internal::nsurlprotectionspace_util::MessageForHTTPAuth(
           protectionSpace);
 
-  InputAlertCoordinator* alertCoordinator = [[[InputAlertCoordinator alloc]
+  InputAlertCoordinator* alertCoordinator = [[InputAlertCoordinator alloc]
       initWithBaseViewController:self.viewController
                            title:title
-                         message:message] autorelease];
+                         message:message];
 
   // Actions.
-  base::WeakNSObject<InputAlertCoordinator> weakCoordinator(alertCoordinator);
+  __weak InputAlertCoordinator* weakCoordinator = alertCoordinator;
   ProceduralBlock confirmAction = ^{
     if (handler) {
       NSString* username = [[weakCoordinator textFields] objectAtIndex:0].text;
@@ -398,7 +364,7 @@
   DCHECK(!_dialogCoordinatorsForWebStates[webState]);
   _queuedWebStates.push_back(webState);
   _dialogCoordinatorsForWebStates[webState] =
-      base::scoped_nsobject<AlertCoordinator>([coordinator retain]);
+      base::scoped_nsobject<AlertCoordinator>(coordinator);
 
   if (self.active && !self.showingDialog && !self.delegate.presenting)
     [self showNextDialog];
@@ -435,8 +401,8 @@
                  cancelAction:(ProceduralBlock)cancelAction
                       OKLabel:(NSString*)label {
   // Handlers.
-  base::WeakNSObject<DialogPresenter> weakSelf(self);
-  base::WeakNSObject<AlertCoordinator> weakCoordinator(alertCoordinator);
+  __weak DialogPresenter* weakSelf = self;
+  __weak AlertCoordinator* weakCoordinator = alertCoordinator;
 
   ProceduralBlock confirmHandler = ^{
     if (confirmAction)
@@ -469,8 +435,6 @@
   DCHECK(webState);
 
   // Set up the start action.
-  base::WeakNSObject<DialogPresenter> weakSelf(self);
-  base::WeakNSObject<AlertCoordinator> weakCoordinator(alertCoordinator);
   ProceduralBlock originalStartAction = alertCoordinator.startAction;
   alertCoordinator.startAction = ^{
     if (originalStartAction)
@@ -492,33 +456,32 @@
 }
 
 - (ProceduralBlock)blockingActionForCoordinator:(AlertCoordinator*)coordinator {
-  base::WeakNSObject<DialogPresenter> weakSelf(self);
-  base::WeakNSObject<AlertCoordinator> weakCoordinator(coordinator);
-  base::WeakNSObject<UIViewController> weakBaseViewController(
-      coordinator.baseViewController);
+  __weak DialogPresenter* weakSelf = self;
+  __weak AlertCoordinator* weakCoordinator = coordinator;
+  __weak UIViewController* weakBaseViewController =
+      coordinator.baseViewController;
   ProceduralBlock cancelAction = coordinator.cancelAction;
-  return [[^{
+  return [^{
     // Create the confirmation coordinator.  Use an action sheet on iPhone and
     // an alert on iPhone.
     NSString* confirmMessage =
         l10n_util::GetNSString(IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION);
     AlertCoordinator* confirmationCoordinator =
-        IsIPadIdiom()
-            ? [[[AlertCoordinator alloc]
-                  initWithBaseViewController:weakBaseViewController
-                                       title:nil
-                                     message:confirmMessage] autorelease]
-            : [[[ActionSheetCoordinator alloc]
-                  initWithBaseViewController:weakBaseViewController
-                                       title:nil
-                                     message:confirmMessage
-                                        rect:CGRectZero
-                                        view:nil] autorelease];
+        IsIPadIdiom() ? [[AlertCoordinator alloc]
+                            initWithBaseViewController:weakBaseViewController
+                                                 title:nil
+                                               message:confirmMessage]
+                      : [[ActionSheetCoordinator alloc]
+                            initWithBaseViewController:weakBaseViewController
+                                                 title:nil
+                                               message:confirmMessage
+                                                  rect:CGRectZero
+                                                  view:nil];
     // Set up button actions.
     ProceduralBlock confirmHandler = ^{
       if (cancelAction)
         cancelAction();
-      base::scoped_nsobject<DialogPresenter> strongSelf([weakSelf retain]);
+      DialogPresenter* strongSelf = weakSelf;
       if (!strongSelf)
         return;
       DialogBlockingOptionSelected([strongSelf presentedDialogWebState]);
@@ -539,7 +502,7 @@
                                         style:UIAlertActionStyleCancel];
     [weakSelf setBlockingConfirmationCoordinator:confirmationCoordinator];
     [[weakSelf blockingConfirmationCoordinator] start];
-  } copy] autorelease];
+  } copy];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm b/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm
index 5e463062..951911f 100644
--- a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm
+++ b/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm
@@ -7,9 +7,13 @@
 #import "ios/chrome/browser/ui/dialogs/dialog_presenter.h"
 #import "ios/chrome/browser/ui/dialogs/javascript_dialog_blocking_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 JavaScriptDialogPresenterImpl::JavaScriptDialogPresenterImpl(
     DialogPresenter* dialogPresenter)
-    : dialog_presenter_([dialogPresenter retain]) {}
+    : dialog_presenter_(dialogPresenter) {}
 
 JavaScriptDialogPresenterImpl::~JavaScriptDialogPresenterImpl() {}
 
diff --git a/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.mm b/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.mm
index b3f7562..0ffb4d3 100644
--- a/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.mm
+++ b/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.mm
@@ -4,7 +4,6 @@
 
 #import "ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.h"
 
-#import "base/mac/scoped_nsobject.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/strings/grit/components_strings.h"
@@ -13,6 +12,10 @@
 #include "url/gurl.h"
 #include "url/scheme_host_port.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace ios_internal {
 namespace nsurlprotectionspace_util {
 
diff --git a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h
index 38f1e99..5cd1181 100644
--- a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h
+++ b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.h
@@ -45,7 +45,7 @@
   AutocompleteClassifier* GetAutocompleteClassifier() override;
   gfx::Image GetIconIfExtensionMatch(
       const AutocompleteMatch& match) const override;
-  bool ProcessExtensionKeyword(TemplateURL* template_url,
+  bool ProcessExtensionKeyword(const TemplateURL* template_url,
                                const AutocompleteMatch& match,
                                WindowOpenDisposition disposition,
                                OmniboxNavigationObserver* observer) override;
diff --git a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
index 03e42e0..ce9a40b 100644
--- a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
@@ -123,7 +123,7 @@
 }
 
 bool ChromeOmniboxClientIOS::ProcessExtensionKeyword(
-    TemplateURL* template_url,
+    const TemplateURL* template_url,
     const AutocompleteMatch& match,
     WindowOpenDisposition disposition,
     OmniboxNavigationObserver* observer) {
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 2037334..d3fc692 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -207,6 +207,7 @@
     "//ios/chrome/browser/content_settings",
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/ssl",
+    "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/overscroll_actions",
     "//ios/chrome/browser/ui/static_content",
diff --git a/ios/chrome/browser/web/auto_reload_bridge.mm b/ios/chrome/browser/web/auto_reload_bridge.mm
index 817f740..1d968f2 100644
--- a/ios/chrome/browser/web/auto_reload_bridge.mm
+++ b/ios/chrome/browser/web/auto_reload_bridge.mm
@@ -8,6 +8,8 @@
 
 #include "base/ios/weak_nsobject.h"
 #include "base/mac/scoped_nsobject.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/web/public/navigation_manager.h"
 #include "net/base/network_change_notifier.h"
 
 namespace {
@@ -80,7 +82,8 @@
 #pragma mark AutoReloadDelegate methods
 
 - (void)reload {
-  [_tab reload];
+  [_tab navigationManager]->Reload(web::ReloadType::NORMAL,
+                                   false /* check_for_repost */);
 }
 
 @end
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index cd1569a..9b79fba 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1406,21 +1406,19 @@
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
 
+  TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
+
   // The input |size| is from the decoded video frame, which is the original
   // natural size and need to be rotated accordingly.
   gfx::Size rotated_size =
       GetRotatedVideoSize(pipeline_metadata_.video_rotation, size);
 
-  if (rotated_size == pipeline_metadata_.natural_size)
+  RecordVideoNaturalSize(rotated_size);
+
+  gfx::Size old_size = pipeline_metadata_.natural_size;
+  if (rotated_size == old_size)
     return;
 
-  TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
-  media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
-      rotated_size.width(), rotated_size.height()));
-
-  if (overlay_enabled_ && surface_manager_)
-    surface_manager_->NaturalSizeChanged(rotated_size);
-
   pipeline_metadata_.natural_size = rotated_size;
 
   // Re-create |watch_time_reporter_| if we didn't originally know the video
@@ -1428,6 +1426,9 @@
   if (!watch_time_reporter_->IsSizeLargeEnoughToReportWatchTime())
     CreateWatchTimeReporter();
 
+  if (overlay_enabled_ && surface_manager_)
+    surface_manager_->NaturalSizeChanged(rotated_size);
+
   client_->SizeChanged();
 
   if (observer_)
@@ -2372,4 +2373,32 @@
     UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration);
 }
 
+#define UMA_HISTOGRAM_VIDEO_HEIGHT(name, sample) \
+  UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 100, 10000, 50)
+
+void WebMediaPlayerImpl::RecordVideoNaturalSize(const gfx::Size& natural_size) {
+  // Always report video natural size to MediaLog.
+  media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
+      natural_size.width(), natural_size.height()));
+
+  if (initial_video_height_recorded_)
+    return;
+
+  initial_video_height_recorded_ = true;
+
+  int height = natural_size.height();
+
+  if (load_type_ == kLoadTypeURL)
+    UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.SRC", height);
+  else if (load_type_ == kLoadTypeMediaSource)
+    UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.MSE", height);
+
+  if (is_encrypted_)
+    UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.EME", height);
+
+  UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.All", height);
+}
+
+#undef UMA_HISTOGRAM_VIDEO_HEIGHT
+
 }  // namespace media
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index a7382f8..0d932b3 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -457,6 +457,9 @@
   // handling a src= or MSE based playback.
   void RecordUnderflowDuration(base::TimeDelta duration);
 
+  // Records |natural_size| to MediaLog and video height to UMA.
+  void RecordVideoNaturalSize(const gfx::Size& natural_size);
+
   blink::WebLocalFrame* frame_;
 
   // The playback state last reported to |delegate_|, to avoid setting duplicate
@@ -720,6 +723,8 @@
 
   base::CancelableCallback<void(base::TimeTicks)> frame_time_report_cb_;
 
+  bool initial_video_height_recorded_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl);
 };
 
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index d75f7aa..1994492 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -472,9 +472,9 @@
         dump->AddScalar("free_size",
                         base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                         frame_resources->IsInUse() ? 0 : buffer_size_in_bytes);
-        base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid =
-            gfx::GetGpuMemoryBufferGUIDForTracing(tracing_process_id,
-                                                  buffer_id);
+        auto shared_buffer_guid =
+            plane_resource.gpu_memory_buffer->GetGUIDForTracing(
+                tracing_process_id);
         pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
         pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid, kImportance);
       }
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 0c33989d..1c06639 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -788,6 +788,8 @@
       "http/bidirectional_stream_request_info.h",
       "http/des.cc",
       "http/des.h",
+      "http/disk_cache_based_quic_server_info.cc",
+      "http/disk_cache_based_quic_server_info.h",
       "http/failing_http_transaction_factory.cc",
       "http/failing_http_transaction_factory.h",
       "http/http_auth.cc",
@@ -4323,6 +4325,7 @@
     "ftp/ftp_util_unittest.cc",
     "http/bidirectional_stream_unittest.cc",
     "http/des_unittest.cc",
+    "http/disk_cache_based_quic_server_info_unittest.cc",
     "http/http_auth_cache_unittest.cc",
     "http/http_auth_challenge_tokenizer_unittest.cc",
     "http/http_auth_controller_unittest.cc",
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc
new file mode 100644
index 0000000..b149fc9
--- /dev/null
+++ b/net/http/disk_cache_based_quic_server_info.cc
@@ -0,0 +1,450 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/http/disk_cache_based_quic_server_info.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
+#include "base/trace_event/memory_usage_estimator.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_network_session.h"
+#include "net/quic/core/quic_server_id.h"
+
+namespace net {
+
+// Some APIs inside disk_cache take a handle that the caller must keep alive
+// until the API has finished its asynchronous execution.
+//
+// Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the
+// operation completes causing a use-after-free.
+//
+// This data shim struct is meant to provide a location for the disk_cache
+// APIs to write into even if the originating DiskCacheBasedQuicServerInfo
+// object has been deleted.  The lifetime for instances of this struct
+// should be bound to the CompletionCallback that is passed to the disk_cache
+// API.  We do this by binding an instance of this struct to an unused
+// parameter for OnIOComplete() using base::Owned().
+//
+// This is a hack. A better fix is to make it so that the disk_cache APIs
+// take a Callback to a mutator for setting the output value rather than
+// writing into a raw handle. Then the caller can just pass in a Callback
+// bound to WeakPtr for itself. This callback would correctly "no-op" itself
+// when the DiskCacheBasedQuicServerInfo object is deleted.
+//
+// TODO(ajwong): Change disk_cache's API to return results via Callback.
+struct DiskCacheBasedQuicServerInfo::CacheOperationDataShim {
+  CacheOperationDataShim() : backend(NULL), entry(NULL) {}
+
+  disk_cache::Backend* backend;
+  disk_cache::Entry* entry;
+};
+
+DiskCacheBasedQuicServerInfo::DiskCacheBasedQuicServerInfo(
+    const QuicServerId& server_id,
+    HttpCache* http_cache)
+    : QuicServerInfo(server_id),
+      data_shim_(new CacheOperationDataShim()),
+      state_(GET_BACKEND),
+      ready_(false),
+      found_entry_(false),
+      server_id_(server_id),
+      http_cache_(http_cache),
+      backend_(NULL),
+      entry_(NULL),
+      last_failure_(NO_FAILURE),
+      weak_factory_(this) {
+      io_callback_ =
+          base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete,
+                     weak_factory_.GetWeakPtr(),
+                     base::Owned(data_shim_));  // Ownership assigned.
+}
+
+DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() {
+  DCHECK(wait_for_ready_callback_.is_null());
+  if (entry_)
+    entry_->Close();
+}
+
+void DiskCacheBasedQuicServerInfo::Start() {
+  DCHECK(CalledOnValidThread());
+  DCHECK_EQ(GET_BACKEND, state_);
+  DCHECK_EQ(last_failure_, NO_FAILURE);
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START);
+  load_start_time_ = base::TimeTicks::Now();
+  DoLoop(OK);
+}
+
+int DiskCacheBasedQuicServerInfo::WaitForDataReady(
+    const CompletionCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  DCHECK_NE(GET_BACKEND, state_);
+  wait_for_data_start_time_ = base::TimeTicks::Now();
+
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY);
+  if (ready_) {
+    wait_for_data_end_time_ = base::TimeTicks::Now();
+    RecordLastFailure();
+    return OK;
+  }
+
+  if (!callback.is_null()) {
+    // Prevent a new callback for WaitForDataReady overwriting an existing
+    // pending callback (|wait_for_ready_callback_|).
+    if (!wait_for_ready_callback_.is_null()) {
+      RecordQuicServerInfoFailure(WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE);
+      return ERR_INVALID_ARGUMENT;
+    }
+    wait_for_ready_callback_ = callback;
+  }
+
+  return ERR_IO_PENDING;
+}
+
+void DiskCacheBasedQuicServerInfo::ResetWaitForDataReadyCallback() {
+  DCHECK(CalledOnValidThread());
+  wait_for_ready_callback_.Reset();
+}
+
+void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() {
+  DCHECK(CalledOnValidThread());
+
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL);
+  if (!wait_for_ready_callback_.is_null()) {
+    RecordLastFailure();
+    wait_for_ready_callback_.Reset();
+  }
+}
+
+bool DiskCacheBasedQuicServerInfo::IsDataReady() {
+  return ready_;
+}
+
+bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() {
+  // The data can be persisted if it has been loaded from the disk cache
+  // and there are no pending writes.
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST);
+  if (ready_ && new_data_.empty())
+    return true;
+  RecordQuicServerInfoFailure(READY_TO_PERSIST_FAILURE);
+  return false;
+}
+
+void DiskCacheBasedQuicServerInfo::Persist() {
+  DCHECK(CalledOnValidThread());
+  if (!IsReadyToPersist()) {
+    // Handle updates while a write is pending or if we haven't loaded from disk
+    // cache. Save the data to be written into a temporary buffer and then
+    // persist that data when we are ready to persist.
+    pending_write_data_ = Serialize();
+    return;
+  }
+  PersistInternal();
+}
+
+void DiskCacheBasedQuicServerInfo::PersistInternal() {
+  DCHECK(CalledOnValidThread());
+  DCHECK_NE(GET_BACKEND, state_);
+  DCHECK(new_data_.empty());
+  CHECK(ready_);
+  DCHECK(wait_for_ready_callback_.is_null());
+
+  if (pending_write_data_.empty()) {
+    new_data_ = Serialize();
+  } else {
+    new_data_ = pending_write_data_;
+    base::STLClearObject(&pending_write_data_);
+  }
+
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST);
+  if (!backend_) {
+    RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE);
+    return;
+  }
+
+  state_ = CREATE_OR_OPEN;
+  DoLoop(OK);
+}
+
+void DiskCacheBasedQuicServerInfo::OnExternalCacheHit() {
+  DCHECK(CalledOnValidThread());
+  DCHECK_NE(GET_BACKEND, state_);
+
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT);
+  if (!backend_) {
+    RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE);
+    return;
+  }
+
+  backend_->OnExternalCacheHit(key());
+}
+
+size_t DiskCacheBasedQuicServerInfo::EstimateMemoryUsage() const {
+  return base::trace_event::EstimateMemoryUsage(new_data_) +
+         base::trace_event::EstimateMemoryUsage(pending_write_data_) +
+         base::trace_event::EstimateMemoryUsage(server_id_) +
+         (read_buffer_ == nullptr ? 0 : read_buffer_->size()) +
+         (write_buffer_ == nullptr ? 0 : write_buffer_->size()) +
+         base::trace_event::EstimateMemoryUsage(data_);
+}
+
+std::string DiskCacheBasedQuicServerInfo::key() const {
+  return "quicserverinfo:" + server_id_.ToString();
+}
+
+void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused,
+                                                int rv) {
+  DCHECK_NE(NONE, state_);
+  rv = DoLoop(rv);
+  if (rv == ERR_IO_PENDING)
+    return;
+
+  base::WeakPtr<DiskCacheBasedQuicServerInfo> weak_this =
+      weak_factory_.GetWeakPtr();
+
+  if (!wait_for_ready_callback_.is_null()) {
+    wait_for_data_end_time_ = base::TimeTicks::Now();
+    RecordLastFailure();
+    base::ResetAndReturn(&wait_for_ready_callback_).Run(rv);
+  }
+  // |wait_for_ready_callback_| could delete the object if there is an error.
+  // Check if |weak_this| still exists before accessing it.
+  if (weak_this.get() && ready_ && !pending_write_data_.empty()) {
+    DCHECK_EQ(NONE, state_);
+    PersistInternal();
+  }
+}
+
+int DiskCacheBasedQuicServerInfo::DoLoop(int rv) {
+  do {
+    switch (state_) {
+      case GET_BACKEND:
+        rv = DoGetBackend();
+        break;
+      case GET_BACKEND_COMPLETE:
+        rv = DoGetBackendComplete(rv);
+        break;
+      case OPEN:
+        rv = DoOpen();
+        break;
+      case OPEN_COMPLETE:
+        rv = DoOpenComplete(rv);
+        break;
+      case READ:
+        rv = DoRead();
+        break;
+      case READ_COMPLETE:
+        rv = DoReadComplete(rv);
+        break;
+      case WAIT_FOR_DATA_READY_DONE:
+        rv = DoWaitForDataReadyDone();
+        break;
+      case CREATE_OR_OPEN:
+        rv = DoCreateOrOpen();
+        break;
+      case CREATE_OR_OPEN_COMPLETE:
+        rv = DoCreateOrOpenComplete(rv);
+        break;
+      case WRITE:
+        rv = DoWrite();
+        break;
+      case WRITE_COMPLETE:
+        rv = DoWriteComplete(rv);
+        break;
+      case SET_DONE:
+        rv = DoSetDone();
+        break;
+      default:
+        rv = OK;
+        NOTREACHED();
+    }
+  } while (rv != ERR_IO_PENDING && state_ != NONE);
+
+  return rv;
+}
+
+int DiskCacheBasedQuicServerInfo::DoGetBackendComplete(int rv) {
+  if (rv == OK) {
+    backend_ = data_shim_->backend;
+    state_ = OPEN;
+  } else {
+    RecordQuicServerInfoFailure(GET_BACKEND_FAILURE);
+    state_ = WAIT_FOR_DATA_READY_DONE;
+  }
+  return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoOpenComplete(int rv) {
+  if (rv == OK) {
+    entry_ = data_shim_->entry;
+    state_ = READ;
+    found_entry_ = true;
+  } else {
+    RecordQuicServerInfoFailure(OPEN_FAILURE);
+    state_ = WAIT_FOR_DATA_READY_DONE;
+  }
+
+  return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) {
+  if (rv > 0)
+    data_.assign(read_buffer_->data(), rv);
+  else if (rv < 0)
+    RecordQuicServerInfoFailure(READ_FAILURE);
+
+  read_buffer_ = nullptr;
+  state_ = WAIT_FOR_DATA_READY_DONE;
+  return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) {
+  if (rv < 0)
+    RecordQuicServerInfoFailure(WRITE_FAILURE);
+  write_buffer_ = nullptr;
+  state_ = SET_DONE;
+  return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) {
+  if (rv != OK) {
+    RecordQuicServerInfoFailure(CREATE_OR_OPEN_FAILURE);
+    state_ = SET_DONE;
+  } else {
+    if (!entry_) {
+      entry_ = data_shim_->entry;
+      found_entry_ = true;
+    }
+    DCHECK(entry_);
+    state_ = WRITE;
+  }
+  return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoGetBackend() {
+  state_ = GET_BACKEND_COMPLETE;
+  return http_cache_->GetBackend(&data_shim_->backend, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoOpen() {
+  state_ = OPEN_COMPLETE;
+  return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoRead() {
+  const int32_t size = entry_->GetDataSize(0 /* index */);
+  if (!size) {
+    state_ = WAIT_FOR_DATA_READY_DONE;
+    return OK;
+  }
+
+  read_buffer_ = new IOBufferWithSize(size);
+  state_ = READ_COMPLETE;
+  return entry_->ReadData(
+      0 /* index */, 0 /* offset */, read_buffer_.get(), size, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoWrite() {
+  write_buffer_ = new IOBufferWithSize(new_data_.size());
+  memcpy(write_buffer_->data(), new_data_.data(), new_data_.size());
+  state_ = WRITE_COMPLETE;
+
+  return entry_->WriteData(0 /* index */,
+                           0 /* offset */,
+                           write_buffer_.get(),
+                           new_data_.size(),
+                           io_callback_,
+                           true /* truncate */);
+}
+
+int DiskCacheBasedQuicServerInfo::DoCreateOrOpen() {
+  state_ = CREATE_OR_OPEN_COMPLETE;
+  if (entry_)
+    return OK;
+
+  if (found_entry_) {
+    return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_);
+  }
+
+  return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_);
+}
+
+int DiskCacheBasedQuicServerInfo::DoWaitForDataReadyDone() {
+  DCHECK(!ready_);
+  state_ = NONE;
+  ready_ = true;
+  // We close the entry because, if we shutdown before ::Persist is called,
+  // then we might leak a cache reference, which causes a DCHECK on shutdown.
+  if (entry_)
+    entry_->Close();
+  entry_ = NULL;
+
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PARSE);
+  if (!Parse(data_)) {
+    if (data_.empty())
+      RecordQuicServerInfoFailure(PARSE_NO_DATA_FAILURE);
+    else
+      RecordQuicServerInfoFailure(PARSE_FAILURE);
+  }
+
+  UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheLoadTime",
+                      base::TimeTicks::Now() - load_start_time_);
+  return OK;
+}
+
+int DiskCacheBasedQuicServerInfo::DoSetDone() {
+  if (entry_)
+    entry_->Close();
+  entry_ = NULL;
+  base::STLClearObject(&new_data_);
+  state_ = NONE;
+  return OK;
+}
+
+void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoStatus(
+    QuicServerInfoAPICall call) {
+  if (!backend_) {
+    UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.NoBackend", call,
+                              QUIC_SERVER_INFO_NUM_OF_API_CALLS);
+  } else if (backend_->GetCacheType() == MEMORY_CACHE) {
+    UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.MemoryCache", call,
+                              QUIC_SERVER_INFO_NUM_OF_API_CALLS);
+  } else {
+    UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.DiskCache", call,
+                              QUIC_SERVER_INFO_NUM_OF_API_CALLS);
+  }
+}
+
+void DiskCacheBasedQuicServerInfo::RecordLastFailure() {
+  if (last_failure_ != NO_FAILURE) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "Net.QuicDiskCache.FailureReason.WaitForDataReady",
+        last_failure_, NUM_OF_FAILURES);
+  }
+  last_failure_ = NO_FAILURE;
+}
+
+void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoFailure(
+    FailureReason failure) {
+  last_failure_ = failure;
+
+  if (!backend_) {
+    UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.NoBackend",
+                              failure, NUM_OF_FAILURES);
+  } else if (backend_->GetCacheType() == MEMORY_CACHE) {
+    UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.MemoryCache",
+                              failure, NUM_OF_FAILURES);
+  } else {
+    UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.DiskCache",
+                              failure, NUM_OF_FAILURES);
+  }
+}
+
+}  // namespace net
diff --git a/net/http/disk_cache_based_quic_server_info.h b/net/http/disk_cache_based_quic_server_info.h
new file mode 100644
index 0000000..2396f8c
--- /dev/null
+++ b/net/http/disk_cache_based_quic_server_info.h
@@ -0,0 +1,135 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
+#define NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/time/time.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_export.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/quic/chromium/quic_server_info.h"
+
+namespace net {
+
+class HttpCache;
+class IOBufferWithSize;
+class QuicServerId;
+
+// DiskCacheBasedQuicServerInfo fetches information about a QUIC server from
+// our standard disk cache. Since the information is defined to be
+// non-sensitive, it's ok for us to keep it on disk.
+class NET_EXPORT_PRIVATE DiskCacheBasedQuicServerInfo
+    : public QuicServerInfo,
+      public NON_EXPORTED_BASE(base::NonThreadSafe) {
+ public:
+  DiskCacheBasedQuicServerInfo(const QuicServerId& server_id,
+                               HttpCache* http_cache);
+  ~DiskCacheBasedQuicServerInfo() override;
+
+  // QuicServerInfo implementation.
+  void Start() override;
+  int WaitForDataReady(const CompletionCallback& callback) override;
+  void ResetWaitForDataReadyCallback() override;
+  void CancelWaitForDataReadyCallback() override;
+  bool IsDataReady() override;
+  bool IsReadyToPersist() override;
+  void Persist() override;
+  void OnExternalCacheHit() override;
+  size_t EstimateMemoryUsage() const override;
+
+ private:
+  struct CacheOperationDataShim;
+
+  enum State {
+    GET_BACKEND,
+    GET_BACKEND_COMPLETE,
+    OPEN,
+    OPEN_COMPLETE,
+    READ,
+    READ_COMPLETE,
+    WAIT_FOR_DATA_READY_DONE,
+    CREATE_OR_OPEN,
+    CREATE_OR_OPEN_COMPLETE,
+    WRITE,
+    WRITE_COMPLETE,
+    SET_DONE,
+    NONE,
+  };
+
+  // Persists |pending_write_data_| if it is not empty, otherwise serializes the
+  // data and pesists it.
+  void PersistInternal();
+
+  std::string key() const;
+
+  // The |unused| parameter is a small hack so that we can have the
+  // CacheOperationDataShim object owned by the Callback that is created for
+  // this method.  See comment above CacheOperationDataShim for details.
+  void OnIOComplete(CacheOperationDataShim* unused, int rv);
+
+  int DoLoop(int rv);
+
+  int DoGetBackendComplete(int rv);
+  int DoOpenComplete(int rv);
+  int DoReadComplete(int rv);
+  int DoWriteComplete(int rv);
+  int DoCreateOrOpenComplete(int rv);
+
+  int DoGetBackend();
+  int DoOpen();
+  int DoRead();
+  int DoWrite();
+  int DoCreateOrOpen();
+
+  // DoWaitForDataReadyDone is the terminal state of the read operation.
+  int DoWaitForDataReadyDone();
+
+  // DoSetDone is the terminal state of the write operation.
+  int DoSetDone();
+
+  // Tracks in a histogram the number of times data read/parse/write API calls
+  // of QuicServerInfo to and from disk cache is called.
+  void RecordQuicServerInfoStatus(QuicServerInfoAPICall call);
+
+  // Tracks in a histogram the failure reasons to read/load/write of
+  // QuicServerInfo to and from disk cache. It also saves the |failure| in
+  // |last_failure_|.
+  void RecordQuicServerInfoFailure(FailureReason failure);
+
+  // Tracks in a histogram if |last_failure_| is not NO_FAILURE.
+  void RecordLastFailure();
+
+  CacheOperationDataShim* data_shim_;  // Owned by |io_callback_|.
+  CompletionCallback io_callback_;
+  State state_;
+  bool ready_;
+  bool found_entry_;  // Controls the behavior of DoCreateOrOpen.
+  std::string new_data_;
+  std::string pending_write_data_;
+  const QuicServerId server_id_;
+  HttpCache* const http_cache_;
+  disk_cache::Backend* backend_;
+  disk_cache::Entry* entry_;
+  CompletionCallback wait_for_ready_callback_;
+  scoped_refptr<IOBufferWithSize> read_buffer_;
+  scoped_refptr<IOBufferWithSize> write_buffer_;
+  std::string data_;
+  base::TimeTicks load_start_time_;
+  FailureReason last_failure_;
+
+  base::WeakPtrFactory<DiskCacheBasedQuicServerInfo> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DiskCacheBasedQuicServerInfo);
+};
+
+}  // namespace net
+
+#endif  // NET_HTTP_DISK_CACHE_BASED_QUIC_SERVER_INFO_H_
diff --git a/net/http/disk_cache_based_quic_server_info_unittest.cc b/net/http/disk_cache_based_quic_server_info_unittest.cc
new file mode 100644
index 0000000..55f5835
--- /dev/null
+++ b/net/http/disk_cache_based_quic_server_info_unittest.cc
@@ -0,0 +1,721 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/http/disk_cache_based_quic_server_info.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "net/base/net_errors.h"
+#include "net/http/mock_http_cache.h"
+#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/core/quic_server_id.h"
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using net::test::IsError;
+using net::test::IsOk;
+
+using std::string;
+
+namespace net {
+namespace {
+
+// This is an empty transaction, needed to register the URL and the test mode.
+const MockTransaction kHostInfoTransaction1 = {
+    "quicserverinfo:https://www.google.com:443",
+    "",
+    base::Time(),
+    "",
+    LOAD_NORMAL,
+    "",
+    "",
+    base::Time(),
+    "",
+    TEST_MODE_NORMAL,
+    nullptr,
+    nullptr,
+    nullptr,
+    0,
+    0,
+    OK,
+};
+
+const MockTransaction kHostInfoTransaction2 = {
+    "quicserverinfo:https://www.google.com:80",
+    "",
+    base::Time(),
+    "",
+    LOAD_NORMAL,
+    "",
+    "",
+    base::Time(),
+    "",
+    TEST_MODE_NORMAL,
+    nullptr,
+    nullptr,
+    nullptr,
+    0,
+    0,
+    OK,
+};
+
+class DeleteCacheCompletionCallback : public TestCompletionCallbackBase {
+ public:
+  explicit DeleteCacheCompletionCallback(QuicServerInfo* server_info)
+      : server_info_(server_info),
+        callback_(base::Bind(&DeleteCacheCompletionCallback::OnComplete,
+                             base::Unretained(this))) {}
+
+  const CompletionCallback& callback() const { return callback_; }
+
+ private:
+  void OnComplete(int result) {
+    delete server_info_;
+    SetResult(result);
+  }
+
+  QuicServerInfo* server_info_;
+  CompletionCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeleteCacheCompletionCallback);
+};
+
+}  // namespace
+
+// Tests that we can delete a DiskCacheBasedQuicServerInfo object in a
+// completion callback for DiskCacheBasedQuicServerInfo::WaitForDataReady.
+TEST(DiskCacheBasedQuicServerInfo, DeleteInCallback) {
+  // Use the blocking mock backend factory to force asynchronous completion
+  // of quic_server_info->WaitForDataReady(), so that the callback will run.
+  MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
+  MockHttpCache cache(base::WrapUnique(factory), true);
+  QuicServerId server_id("www.verisign.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  TestCompletionCallback callback;
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  // Now complete the backend creation and let the callback run.
+  factory->FinishCreation();
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+}
+
+// Tests the basic logic of storing, retrieving and updating data.
+TEST(DiskCacheBasedQuicServerInfo, Update) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  TestCompletionCallback callback;
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
+  EXPECT_TRUE(state->certs.empty());
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+  const string cert_b = "cert_b";
+
+  state->server_config = server_config_a;
+  state->source_address_token = source_address_token_a;
+  state->cert_sct = cert_sct_a;
+  state->chlo_hash = chlo_hash_a;
+  state->server_config_sig = server_config_sig_a;
+  state->certs.push_back(cert_a);
+  quic_server_info->Persist();
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  // Open the stored QuicServerInfo.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+
+  // And now update the data.
+  state = quic_server_info->mutable_state();
+  state->certs.push_back(cert_b);
+
+  // Fail instead of DCHECKing double creates.
+  cache.disk_cache()->set_double_create_check(false);
+  quic_server_info->Persist();
+  base::RunLoop().RunUntilIdle();
+
+  // Verify that the state was updated.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state1 = quic_server_info->state();
+  EXPECT_EQ(server_config_a, state1.server_config);
+  EXPECT_EQ(source_address_token_a, state1.source_address_token);
+  EXPECT_EQ(cert_sct_a, state1.cert_sct);
+  EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
+  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+  EXPECT_EQ(2U, state1.certs.size());
+  EXPECT_EQ(cert_a, state1.certs[0]);
+  EXPECT_EQ(cert_b, state1.certs[1]);
+
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test that demonstrates different info is returned when the ports differ.
+TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  AddMockTransaction(&kHostInfoTransaction2);
+  TestCompletionCallback callback;
+
+  // Persist data for port 443.
+  QuicServerId server_id1("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info1(
+      new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache()));
+  quic_server_info1->Start();
+  int rv = quic_server_info1->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+
+  QuicServerInfo::State* state1 = quic_server_info1->mutable_state();
+  EXPECT_TRUE(state1->certs.empty());
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+
+  state1->server_config = server_config_a;
+  state1->source_address_token = source_address_token_a;
+  state1->cert_sct = cert_sct_a;
+  state1->chlo_hash = chlo_hash_a;
+  state1->server_config_sig = server_config_sig_a;
+  state1->certs.push_back(cert_a);
+  quic_server_info1->Persist();
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  // Persist data for port 80.
+  QuicServerId server_id2("www.google.com", 80, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info2(
+      new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache()));
+  quic_server_info2->Start();
+  rv = quic_server_info2->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+
+  QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
+  EXPECT_TRUE(state2->certs.empty());
+  const string server_config_b = "server_config_b";
+  const string source_address_token_b = "source_address_token_b";
+  const string cert_sct_b = "cert_sct_b";
+  const string chlo_hash_b = "chlo_hash_b";
+  const string server_config_sig_b = "server_config_sig_b";
+  const string cert_b = "cert_b";
+
+  state2->server_config = server_config_b;
+  state2->source_address_token = source_address_token_b;
+  state2->cert_sct = cert_sct_b;
+  state2->chlo_hash = chlo_hash_b;
+  state2->server_config_sig = server_config_sig_b;
+  state2->certs.push_back(cert_b);
+  quic_server_info2->Persist();
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  // Verify the stored QuicServerInfo for port 443.
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state_a = quic_server_info->state();
+  EXPECT_EQ(server_config_a, state_a.server_config);
+  EXPECT_EQ(source_address_token_a, state_a.source_address_token);
+  EXPECT_EQ(cert_sct_a, state_a.cert_sct);
+  EXPECT_EQ(chlo_hash_a, state_a.chlo_hash);
+  EXPECT_EQ(server_config_sig_a, state_a.server_config_sig);
+  EXPECT_EQ(1U, state_a.certs.size());
+  EXPECT_EQ(cert_a, state_a.certs[0]);
+
+  // Verify the stored QuicServerInfo for port 80.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state_b = quic_server_info->state();
+  EXPECT_EQ(server_config_b, state_b.server_config);
+  EXPECT_EQ(source_address_token_b, state_b.source_address_token);
+  EXPECT_EQ(cert_sct_b, state_b.cert_sct);
+  EXPECT_EQ(chlo_hash_b, state_b.chlo_hash);
+  EXPECT_EQ(server_config_sig_b, state_b.server_config_sig);
+  EXPECT_EQ(1U, state_b.certs.size());
+  EXPECT_EQ(cert_b, state_b.certs[0]);
+
+  RemoveMockTransaction(&kHostInfoTransaction2);
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test IsReadyToPersist when there is a pending write.
+TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  TestCompletionCallback callback;
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
+  EXPECT_TRUE(state->certs.empty());
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+
+  state->server_config = server_config_a;
+  state->source_address_token = source_address_token_a;
+  state->cert_sct = cert_sct_a;
+  state->chlo_hash = chlo_hash_a;
+  state->server_config_sig = server_config_sig_a;
+  state->certs.push_back(cert_a);
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+
+  // Once we call Persist, IsReadyToPersist should return false until Persist
+  // has completed.
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+
+  // Verify that the state was updated.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state1 = quic_server_info->state();
+  EXPECT_EQ(server_config_a, state1.server_config);
+  EXPECT_EQ(source_address_token_a, state1.source_address_token);
+  EXPECT_EQ(cert_sct_a, state1.cert_sct);
+  EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
+  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+  EXPECT_EQ(1U, state1.certs.size());
+  EXPECT_EQ(cert_a, state1.certs[0]);
+
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test multiple calls to Persist.
+TEST(DiskCacheBasedQuicServerInfo, MultiplePersist) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  TestCompletionCallback callback;
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  // Persist data once.
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
+  EXPECT_TRUE(state->certs.empty());
+  const string server_config_init = "server_config_init";
+  const string source_address_token_init = "source_address_token_init";
+  const string cert_sct_init = "cert_sct_init";
+  const string chlo_hash_init = "chlo_hash_init";
+  const string server_config_sig_init = "server_config_sig_init";
+  const string cert_init = "cert_init";
+
+  state->server_config = server_config_init;
+  state->source_address_token = source_address_token_init;
+  state->cert_sct = cert_sct_init;
+  state->chlo_hash = chlo_hash_init;
+  state->server_config_sig = server_config_sig_init;
+  state->certs.push_back(cert_init);
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+
+  // Once we call Persist, IsReadyToPersist should return false until Persist
+  // has completed.
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+
+  // Persist one more time using the same |quic_server_info| object and without
+  // doing another Start() and WaitForDataReady.
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+
+  state->server_config = server_config_a;
+  state->source_address_token = source_address_token_a;
+  state->cert_sct = cert_sct_a;
+  state->chlo_hash = chlo_hash_a;
+  state->server_config_sig = server_config_sig_a;
+  state->certs.push_back(cert_a);
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+
+  // Once we call Persist, IsReadyToPersist should return false until Persist
+  // has completed.
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+
+  // Verify that the state was updated.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state1 = quic_server_info->state();
+  EXPECT_EQ(server_config_a, state1.server_config);
+  EXPECT_EQ(source_address_token_a, state1.source_address_token);
+  EXPECT_EQ(cert_sct_a, state1.cert_sct);
+  EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
+  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+  EXPECT_EQ(1U, state1.certs.size());
+  EXPECT_EQ(cert_a, state1.certs[0]);
+
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReady) {
+  MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
+  MockHttpCache cache(base::WrapUnique(factory), true);
+  TestCompletionCallback callback;
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  // Now cancel the callback.
+  quic_server_info->CancelWaitForDataReadyCallback();
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  // Now complete the backend creation and let the callback run.
+  factory->FinishCreation();
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+}
+
+TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReadyButDataIsReady) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  TestCompletionCallback callback;
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  quic_server_info->CancelWaitForDataReadyCallback();
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReadyAfterDeleteCache) {
+  std::unique_ptr<QuicServerInfo> quic_server_info;
+  {
+    MockHttpCache cache(true);
+    AddMockTransaction(&kHostInfoTransaction1);
+    TestCompletionCallback callback;
+
+    QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+    quic_server_info.reset(
+        new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+    EXPECT_FALSE(quic_server_info->IsDataReady());
+    quic_server_info->Start();
+    int rv = quic_server_info->WaitForDataReady(callback.callback());
+    quic_server_info->CancelWaitForDataReadyCallback();
+    EXPECT_THAT(callback.GetResult(rv), IsOk());
+    EXPECT_TRUE(quic_server_info->IsDataReady());
+    RemoveMockTransaction(&kHostInfoTransaction1);
+  }
+  // Cancel the callback after Cache is deleted.
+  quic_server_info->ResetWaitForDataReadyCallback();
+}
+
+// Test Start() followed by Persist() without calling WaitForDataReady.
+TEST(DiskCacheBasedQuicServerInfo, StartAndPersist) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  quic_server_info->Start();
+  // Wait until Start() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
+  EXPECT_TRUE(state->certs.empty());
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+
+  state->server_config = server_config_a;
+  state->source_address_token = source_address_token_a;
+  state->cert_sct = cert_sct_a;
+  state->chlo_hash = chlo_hash_a;
+  state->server_config_sig = server_config_sig_a;
+  state->certs.push_back(cert_a);
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+  quic_server_info->OnExternalCacheHit();
+
+  // Once we call Persist, IsReadyToPersist should return false until Persist
+  // has completed.
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+
+  // Verify that the state was updated.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  TestCompletionCallback callback;
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state1 = quic_server_info->state();
+  EXPECT_EQ(server_config_a, state1.server_config);
+  EXPECT_EQ(source_address_token_a, state1.source_address_token);
+  EXPECT_EQ(cert_sct_a, state1.cert_sct);
+  EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
+  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+  EXPECT_EQ(1U, state1.certs.size());
+  EXPECT_EQ(cert_a, state1.certs[0]);
+
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test Persisting data when we are not ready to persist and then verify it
+// persists the data when Start() finishes.
+TEST(DiskCacheBasedQuicServerInfo, PersistWhenNotReadyToPersist) {
+  MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
+  MockHttpCache cache(base::WrapUnique(factory), true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  TestCompletionCallback callback;
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  // We do a Start(), but don't call WaitForDataReady(). Because we haven't
+  // created the backend, we will wait and data wouldn't be ready.
+  quic_server_info->Start();
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+
+  // Persist data once, even though the backend is not ready.
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
+  EXPECT_TRUE(state->certs.empty());
+  const string server_config_init = "server_config_init";
+  const string source_address_token_init = "source_address_token_init";
+  const string cert_sct_init = "cert_sct_init";
+  const string chlo_hash_init = "chlo_hash_init";
+  const string server_config_sig_init = "server_config_sig_init";
+  const string cert_init = "cert_init";
+
+  state->server_config = server_config_init;
+  state->source_address_token = source_address_token_init;
+  state->cert_sct = cert_sct_init;
+  state->chlo_hash = chlo_hash_init;
+  state->server_config_sig = server_config_sig_init;
+  state->certs.push_back(cert_init);
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+  // Now complete the backend creation and let the callback run.
+  factory->FinishCreation();
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  // Verify that the state was updated.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  const QuicServerInfo::State& state1 = quic_server_info->state();
+  EXPECT_EQ(server_config_init, state1.server_config);
+  EXPECT_EQ(source_address_token_init, state1.source_address_token);
+  EXPECT_EQ(cert_sct_init, state1.cert_sct);
+  EXPECT_EQ(chlo_hash_init, state1.chlo_hash);
+  EXPECT_EQ(server_config_sig_init, state1.server_config_sig);
+  EXPECT_EQ(1U, state1.certs.size());
+  EXPECT_EQ(cert_init, state1.certs[0]);
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// Test multiple calls to Persist without waiting for the data to be written.
+TEST(DiskCacheBasedQuicServerInfo, MultiplePersistsWithoutWaiting) {
+  MockHttpCache cache(true);
+  AddMockTransaction(&kHostInfoTransaction1);
+  TestCompletionCallback callback;
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  std::unique_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  EXPECT_FALSE(quic_server_info->IsDataReady());
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  // Persist data once.
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
+  EXPECT_TRUE(state->certs.empty());
+  const string server_config_init = "server_config_init";
+  const string source_address_token_init = "source_address_token_init";
+  const string cert_sct_init = "cert_sct_init";
+  const string chlo_hash_init = "chlo_hash_init";
+  const string server_config_sig_init = "server_config_sig_init";
+  const string cert_init = "cert_init";
+
+  state->server_config = server_config_init;
+  state->source_address_token = source_address_token_init;
+  state->cert_sct = cert_sct_init;
+  state->chlo_hash = chlo_hash_init;
+  state->server_config_sig = server_config_sig_init;
+  state->certs.push_back(cert_init);
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+
+  // Once we call Persist, IsReadyToPersist should return false until Persist
+  // has completed.
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+
+  // Persist one more time using the same |quic_server_info| object and without
+  // doing another Start() and WaitForDataReady.
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+
+  state->server_config = server_config_a;
+  state->source_address_token = source_address_token_a;
+  state->cert_sct = cert_sct_a;
+  state->chlo_hash = chlo_hash_a;
+  state->server_config_sig = server_config_sig_a;
+  state->certs.push_back(cert_a);
+  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
+  quic_server_info->Persist();
+
+  // Wait until Persist() does the work.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
+
+  // Verify that the state was updated.
+  quic_server_info.reset(
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+  quic_server_info->Start();
+  rv = quic_server_info->WaitForDataReady(callback.callback());
+  EXPECT_THAT(callback.GetResult(rv), IsOk());
+  EXPECT_TRUE(quic_server_info->IsDataReady());
+
+  // Verify the second time persisted data is persisted.
+  const QuicServerInfo::State& state1 = quic_server_info->state();
+  EXPECT_EQ(server_config_a, state1.server_config);
+  EXPECT_EQ(source_address_token_a, state1.source_address_token);
+  EXPECT_EQ(cert_sct_a, state1.cert_sct);
+  EXPECT_EQ(chlo_hash_a, state1.chlo_hash);
+  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
+  EXPECT_EQ(1U, state1.certs.size());
+  EXPECT_EQ(cert_a, state1.certs[0]);
+
+  RemoveMockTransaction(&kHostInfoTransaction1);
+}
+
+// crbug.com/439209: test deletion of QuicServerInfo object in the callback
+// doesn't crash.
+TEST(DiskCacheBasedQuicServerInfo, DeleteServerInfoInCallback) {
+  // Use the blocking mock backend factory to force asynchronous completion
+  // of quic_server_info->WaitForDataReady(), so that the callback will run.
+  MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
+  MockHttpCache cache(base::WrapUnique(factory), true);
+  QuicServerId server_id("www.verisign.com", 443, PRIVACY_MODE_DISABLED);
+  QuicServerInfo* quic_server_info =
+      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache());
+  // |cb| takes owndership and deletes |quic_server_info| when it is called.
+  DeleteCacheCompletionCallback cb(quic_server_info);
+  quic_server_info->Start();
+  int rv = quic_server_info->WaitForDataReady(cb.callback());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  // Now complete the backend creation and let the callback run.
+  factory->FinishCreation();
+  EXPECT_THAT(cb.GetResult(rv), IsOk());
+}
+
+}  // namespace net
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 968cffa..93d39cc 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -37,6 +37,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/upload_data_stream.h"
 #include "net/disk_cache/disk_cache.h"
+#include "net/http/disk_cache_based_quic_server_info.h"
 #include "net/http/http_cache_lookup_manager.h"
 #include "net/http/http_cache_transaction.h"
 #include "net/http/http_network_layer.h"
@@ -302,6 +303,24 @@
 }
 
 //-----------------------------------------------------------------------------
+
+class HttpCache::QuicServerInfoFactoryAdaptor : public QuicServerInfoFactory {
+ public:
+  explicit QuicServerInfoFactoryAdaptor(HttpCache* http_cache)
+      : http_cache_(http_cache) {
+  }
+
+  std::unique_ptr<QuicServerInfo> GetForServer(
+      const QuicServerId& server_id) override {
+    return base::MakeUnique<DiskCacheBasedQuicServerInfo>(server_id,
+                                                          http_cache_);
+  }
+
+ private:
+  HttpCache* const http_cache_;
+};
+
+//-----------------------------------------------------------------------------
 HttpCache::HttpCache(HttpNetworkSession* session,
                      std::unique_ptr<BackendFactory> backend_factory,
                      bool is_main_cache)
@@ -334,6 +353,12 @@
 
   session->SetServerPushDelegate(
       base::MakeUnique<HttpCacheLookupManager>(this));
+
+  if (!session->quic_stream_factory()->has_quic_server_info_factory()) {
+    // QuicStreamFactory takes ownership of QuicServerInfoFactoryAdaptor.
+    session->quic_stream_factory()->set_quic_server_info_factory(
+        new QuicServerInfoFactoryAdaptor(this));
+  }
 }
 
 HttpCache::~HttpCache() {
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 30fa1a0..9fdfc05 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -123,7 +123,10 @@
       enable_quic(false),
       mark_quic_broken_when_network_blackholes(false),
       retry_without_alt_svc_on_quic_errors(false),
+      quic_load_server_info_timeout_srtt_multiplier(0.25f),
+      quic_enable_connection_racing(false),
       quic_enable_non_blocking_io(false),
+      quic_disable_disk_cache(false),
       quic_max_server_configs_stored_in_properties(0u),
       quic_clock(nullptr),
       quic_random(nullptr),
@@ -187,8 +190,11 @@
           params.quic_max_packet_length,
           params.quic_user_agent_id,
           params.quic_supported_versions,
+          params.quic_load_server_info_timeout_srtt_multiplier,
+          params.quic_enable_connection_racing,
           params.quic_enable_non_blocking_io,
-          params.quic_max_server_configs_stored_in_properties > 0,
+          params.quic_disable_disk_cache,
+          params.quic_max_server_configs_stored_in_properties,
           params.quic_close_sessions_on_ip_change,
           params.mark_quic_broken_when_network_blackholes,
           params.quic_idle_connection_timeout_seconds,
@@ -320,6 +326,11 @@
   }
   dict->Set("origins_to_force_quic_on", std::move(origins_to_force_quic_on));
 
+  dict->SetDouble("load_server_info_timeout_srtt_multiplier",
+                  params_.quic_load_server_info_timeout_srtt_multiplier);
+  dict->SetBoolean("enable_connection_racing",
+                   params_.quic_enable_connection_racing);
+  dict->SetBoolean("disable_disk_cache", params_.quic_disable_disk_cache);
   dict->SetInteger("max_server_configs_stored_in_properties",
                    params_.quic_max_server_configs_stored_in_properties);
   dict->SetInteger("idle_connection_timeout_seconds",
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index a2117e06..f9115f46 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -122,8 +122,17 @@
     // Retry requests which fail with QUIC_PROTOCOL_ERROR, and mark QUIC
     // broken if the retry succeeds.
     bool retry_without_alt_svc_on_quic_errors;
+    // If not zero, the task to load QUIC server configs from the disk cache
+    // will timeout after this value multiplied by the smoothed RTT for the
+    // server.
+    float quic_load_server_info_timeout_srtt_multiplier;
+    // Causes QUIC to race reading the server config from disk with
+    // sending an inchoate CHLO.
+    bool quic_enable_connection_racing;
     // Use non-blocking IO for UDP sockets.
     bool quic_enable_non_blocking_io;
+    // Disables using the disk cache to store QUIC server configs.
+    bool quic_disable_disk_cache;
     // Maximum number of server configs that are to be stored in
     // HttpServerProperties, instead of the disk cache.
     size_t quic_max_server_configs_stored_in_properties;
diff --git a/net/quic/chromium/properties_based_quic_server_info.cc b/net/quic/chromium/properties_based_quic_server_info.cc
index 54d1b6da..e90331f 100644
--- a/net/quic/chromium/properties_based_quic_server_info.cc
+++ b/net/quic/chromium/properties_based_quic_server_info.cc
@@ -14,6 +14,13 @@
 
 namespace {
 
+void RecordQuicServerInfoStatus(
+    net::QuicServerInfo::QuicServerInfoAPICall call) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "Net.QuicDiskCache.APICall.PropertiesBasedCache", call,
+      net::QuicServerInfo::QUIC_SERVER_INFO_NUM_OF_API_CALLS);
+}
+
 void RecordQuicServerInfoFailure(net::QuicServerInfo::FailureReason failure) {
   UMA_HISTOGRAM_ENUMERATION(
       "Net.QuicDiskCache.FailureReason.PropertiesBasedCache", failure,
@@ -34,33 +41,74 @@
 
 PropertiesBasedQuicServerInfo::~PropertiesBasedQuicServerInfo() {}
 
-bool PropertiesBasedQuicServerInfo::Load() {
+void PropertiesBasedQuicServerInfo::Start() {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START);
+}
+
+int PropertiesBasedQuicServerInfo::WaitForDataReady(
+    const CompletionCallback& callback) {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY);
   const string* data = http_server_properties_->GetQuicServerInfo(server_id_);
   string decoded;
   if (!data) {
     RecordQuicServerInfoFailure(PARSE_NO_DATA_FAILURE);
-    return false;
+    return ERR_FAILED;
   }
   if (!base::Base64Decode(*data, &decoded)) {
     RecordQuicServerInfoFailure(PARSE_DATA_DECODE_FAILURE);
-    return false;
+    return ERR_FAILED;
   }
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PARSE);
   if (!Parse(decoded)) {
     RecordQuicServerInfoFailure(PARSE_FAILURE);
-    return false;
+    return ERR_FAILED;
   }
+  return OK;
+}
+
+void PropertiesBasedQuicServerInfo::ResetWaitForDataReadyCallback() {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_RESET_WAIT_FOR_DATA_READY);
+}
+
+void PropertiesBasedQuicServerInfo::CancelWaitForDataReadyCallback() {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL);
+}
+
+bool PropertiesBasedQuicServerInfo::IsDataReady() {
   return true;
 }
 
+bool PropertiesBasedQuicServerInfo::IsReadyToPersist() {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST);
+  return true;
+}
 
 void PropertiesBasedQuicServerInfo::Persist() {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST);
   string encoded;
   base::Base64Encode(Serialize(), &encoded);
   http_server_properties_->SetQuicServerInfo(server_id_, encoded);
 }
 
+void PropertiesBasedQuicServerInfo::OnExternalCacheHit() {
+  RecordQuicServerInfoStatus(QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT);
+}
+
 size_t PropertiesBasedQuicServerInfo::EstimateMemoryUsage() const {
   return 0;
 }
 
+PropertiesBasedQuicServerInfoFactory::PropertiesBasedQuicServerInfoFactory(
+    HttpServerProperties* http_server_properties)
+    : http_server_properties_(http_server_properties) {}
+
+PropertiesBasedQuicServerInfoFactory::~PropertiesBasedQuicServerInfoFactory() {}
+
+std::unique_ptr<QuicServerInfo>
+PropertiesBasedQuicServerInfoFactory::GetForServer(
+    const QuicServerId& server_id) {
+  return base::MakeUnique<PropertiesBasedQuicServerInfo>(
+      server_id, http_server_properties_);
+}
+
 }  // namespace net
diff --git a/net/quic/chromium/properties_based_quic_server_info.h b/net/quic/chromium/properties_based_quic_server_info.h
index df85a9d8..35ebb9b7 100644
--- a/net/quic/chromium/properties_based_quic_server_info.h
+++ b/net/quic/chromium/properties_based_quic_server_info.h
@@ -30,8 +30,14 @@
   ~PropertiesBasedQuicServerInfo() override;
 
   // QuicServerInfo implementation.
-  bool Load() override;
+  void Start() override;
+  int WaitForDataReady(const CompletionCallback& callback) override;
+  void ResetWaitForDataReadyCallback() override;
+  void CancelWaitForDataReadyCallback() override;
+  bool IsDataReady() override;
+  bool IsReadyToPersist() override;
   void Persist() override;
+  void OnExternalCacheHit() override;
   size_t EstimateMemoryUsage() const override;
 
  private:
@@ -40,6 +46,22 @@
   DISALLOW_COPY_AND_ASSIGN(PropertiesBasedQuicServerInfo);
 };
 
+class QUIC_EXPORT_PRIVATE PropertiesBasedQuicServerInfoFactory
+    : public QuicServerInfoFactory {
+ public:
+  explicit PropertiesBasedQuicServerInfoFactory(
+      HttpServerProperties* http_server_properties);
+  ~PropertiesBasedQuicServerInfoFactory() override;
+
+  std::unique_ptr<QuicServerInfo> GetForServer(
+      const QuicServerId& server_id) override;
+
+ private:
+  HttpServerProperties* http_server_properties_;
+
+  DISALLOW_COPY_AND_ASSIGN(PropertiesBasedQuicServerInfoFactory);
+};
+
 }  // namespace net
 
 #endif  // NET_QUIC_CHROMIUM_PROPERTIES_BASED_QUIC_SERVER_INFO_H_
diff --git a/net/quic/chromium/properties_based_quic_server_info_test.cc b/net/quic/chromium/properties_based_quic_server_info_test.cc
index c4cc0638..aba7c635 100644
--- a/net/quic/chromium/properties_based_quic_server_info_test.cc
+++ b/net/quic/chromium/properties_based_quic_server_info_test.cc
@@ -34,6 +34,8 @@
 
   // Initialize |server_info_| object and persist it.
   void InitializeAndPersist() {
+    server_info_.Start();
+    EXPECT_TRUE(server_info_.IsDataReady());
     QuicServerInfo::State* state = server_info_.mutable_state();
     EXPECT_TRUE(state->certs.empty());
 
@@ -43,7 +45,11 @@
     state->cert_sct = kCertSCTA;
     state->chlo_hash = kChloHashA;
     state->certs.push_back(kCertA);
+    EXPECT_TRUE(server_info_.IsReadyToPersist());
     server_info_.Persist();
+    EXPECT_TRUE(server_info_.IsReadyToPersist());
+    EXPECT_TRUE(server_info_.IsDataReady());
+    server_info_.OnExternalCacheHit();
   }
 
   // Verify the data that is persisted in InitializeAndPersist().
@@ -69,7 +75,10 @@
   // Read the persisted data and verify we have read the data correctly.
   PropertiesBasedQuicServerInfo server_info1(server_id_,
                                              &http_server_properties_);
-  EXPECT_TRUE(server_info1.Load());
+  server_info1.Start();
+  EXPECT_THAT(server_info1.WaitForDataReady(callback_),
+              IsOk());  // Read the data.
+  EXPECT_TRUE(server_info1.IsDataReady());
 
   // Verify the data.
   const QuicServerInfo::State& state1 = server_info1.state();
@@ -79,12 +88,16 @@
   // Update the data, by adding another cert.
   QuicServerInfo::State* state2 = server_info1.mutable_state();
   state2->certs.push_back(kCertB);
+  EXPECT_TRUE(server_info_.IsReadyToPersist());
   server_info1.Persist();
 
   // Read the persisted data and verify we have read the data correctly.
   PropertiesBasedQuicServerInfo server_info2(server_id_,
                                              &http_server_properties_);
-  EXPECT_TRUE(server_info2.Load());
+  server_info2.Start();
+  EXPECT_THAT(server_info2.WaitForDataReady(callback_),
+              IsOk());  // Read the data.
+  EXPECT_TRUE(server_info1.IsDataReady());
 
   // Verify updated data.
   const QuicServerInfo::State& state3 = server_info2.state();
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 6913eb5..27818a5c 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -375,8 +375,24 @@
           round_trip_handshakes, 1, 3, 4);
     }
   }
-
   const QuicConnectionStats stats = connection()->GetStats();
+  if (server_info_ && stats.min_rtt_us > 0) {
+    base::TimeTicks wait_for_data_start_time =
+        server_info_->wait_for_data_start_time();
+    base::TimeTicks wait_for_data_end_time =
+        server_info_->wait_for_data_end_time();
+    if (!wait_for_data_start_time.is_null() &&
+        !wait_for_data_end_time.is_null()) {
+      base::TimeDelta wait_time =
+          wait_for_data_end_time - wait_for_data_start_time;
+      const base::HistogramBase::Sample kMaxWaitToRtt = 1000;
+      base::HistogramBase::Sample wait_to_rtt =
+          static_cast<base::HistogramBase::Sample>(
+              100 * wait_time.InMicroseconds() / stats.min_rtt_us);
+      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicServerInfo.WaitForDataReadyToRtt",
+                                  wait_to_rtt, 1, kMaxWaitToRtt, 50);
+    }
+  }
 
   // The MTU used by QUIC is limited to a fairly small set of predefined values
   // (initial values and MTU discovery values), but does not fare well when
@@ -846,6 +862,21 @@
     UMA_HISTOGRAM_TIMES(
         "Net.QuicSession.HandshakeConfirmedTime",
         connect_timing_.connect_end - connect_timing_.connect_start);
+
+    if (server_info_) {
+      // TODO(rtenneti): Should we delete this histogram?
+      // Track how long it has taken to finish handshake once we start waiting
+      // for reading of QUIC server information from disk cache. We could use
+      // this data to compare total time taken if we were to cancel the disk
+      // cache read vs waiting for the read to complete.
+      base::TimeTicks wait_for_data_start_time =
+          server_info_->wait_for_data_start_time();
+      if (!wait_for_data_start_time.is_null()) {
+        UMA_HISTOGRAM_TIMES(
+            "Net.QuicServerInfo.WaitForDataReady.HandshakeConfirmedTime",
+            base::TimeTicks::Now() - wait_for_data_start_time);
+      }
+    }
     // Track how long it has taken to finish handshake after we have finished
     // DNS host resolution.
     if (!connect_timing_.dns_end.is_null()) {
@@ -860,6 +891,8 @@
       ++it;
       observer->OnCryptoHandshakeConfirmed();
     }
+    if (server_info_)
+      server_info_->OnExternalCacheHit();
   }
   QuicSpdySession::OnCryptoHandshakeEvent(event);
 }
diff --git a/net/quic/chromium/quic_server_info.cc b/net/quic/chromium/quic_server_info.cc
index 3e53fa5..23f4cf8a 100644
--- a/net/quic/chromium/quic_server_info.cc
+++ b/net/quic/chromium/quic_server_info.cc
@@ -146,4 +146,6 @@
   return string(reinterpret_cast<const char*>(p.data()), p.size());
 }
 
+QuicServerInfoFactory::~QuicServerInfoFactory() {}
+
 }  // namespace net
diff --git a/net/quic/chromium/quic_server_info.h b/net/quic/chromium/quic_server_info.h
index a818576..eab5366 100644
--- a/net/quic/chromium/quic_server_info.h
+++ b/net/quic/chromium/quic_server_info.h
@@ -24,6 +24,20 @@
 // crypto config.
 class QUIC_EXPORT_PRIVATE QuicServerInfo {
  public:
+  // Enum to track number of times data read/parse/write API calls of
+  // QuicServerInfo to and from disk cache is called.
+  enum QuicServerInfoAPICall {
+    QUIC_SERVER_INFO_START = 0,
+    QUIC_SERVER_INFO_WAIT_FOR_DATA_READY = 1,
+    QUIC_SERVER_INFO_PARSE = 2,
+    QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL = 3,
+    QUIC_SERVER_INFO_READY_TO_PERSIST = 4,
+    QUIC_SERVER_INFO_PERSIST = 5,
+    QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT = 6,
+    QUIC_SERVER_INFO_RESET_WAIT_FOR_DATA_READY = 7,
+    QUIC_SERVER_INFO_NUM_OF_API_CALLS = 8,
+  };
+
   // Enum to track failure reasons to read/load/write of QuicServerInfo to
   // and from disk cache.
   enum FailureReason {
@@ -45,13 +59,49 @@
   explicit QuicServerInfo(const QuicServerId& server_id);
   virtual ~QuicServerInfo();
 
-  // Fetches the server config from the backing store, and returns true
-  // if the server config was found.
-  virtual bool Load() = 0;
+  // Start will commence the lookup. This must be called before any other
+  // methods. By opportunistically calling this early, it may be possible to
+  // overlap this object's lookup and reduce latency.
+  virtual void Start() = 0;
 
-  // Persist allows for the server information to be updated for future uses.
+  // WaitForDataReady returns OK if the fetch of the requested data has
+  // completed. Otherwise it returns ERR_IO_PENDING and will call |callback| on
+  // the current thread when ready.
+  //
+  // Only a single callback can be outstanding at a given time and, in the
+  // event that WaitForDataReady returns OK, it's the caller's responsibility
+  // to delete |callback|.
+  //
+  // |callback| may be NULL, in which case ERR_IO_PENDING may still be returned
+  // but, obviously, a callback will never be made.
+  virtual int WaitForDataReady(const CompletionCallback& callback) = 0;
+
+  // Reset's WaitForDataReady callback. This method shouldn't have any side
+  // effects (could be called even if HttpCache doesn't exist).
+  virtual void ResetWaitForDataReadyCallback() = 0;
+
+  // Cancel's WaitForDataReady callback. |callback| passed in WaitForDataReady
+  // will not be called.
+  virtual void CancelWaitForDataReadyCallback() = 0;
+
+  // Returns true if data is loaded from disk cache and ready (WaitForDataReady
+  // doesn't have a pending callback).
+  virtual bool IsDataReady() = 0;
+
+  // Returns true if the object is ready to persist data, in other words, if
+  // data is loaded from disk cache and ready and there are no pending writes.
+  virtual bool IsReadyToPersist() = 0;
+
+  // Persist allows for the server information to be updated for future users.
+  // This is a fire and forget operation: the caller may drop its reference
+  // from this object and the store operation will still complete. This can
+  // only be called once WaitForDataReady has returned OK or called its
+  // callback.
   virtual void Persist() = 0;
 
+  // Called whenever an external cache reuses quic server config.
+  virtual void OnExternalCacheHit() = 0;
+
   // Returns the size of dynamically allocated memory in bytes.
   virtual size_t EstimateMemoryUsage() const = 0;
 
@@ -79,6 +129,14 @@
   const State& state() const;
   State* mutable_state();
 
+  base::TimeTicks wait_for_data_start_time() const {
+    return wait_for_data_start_time_;
+  }
+
+  base::TimeTicks wait_for_data_end_time() const {
+    return wait_for_data_end_time_;
+  }
+
  protected:
   // Parse parses pickled data and fills out the public member fields of this
   // object. It returns true iff the parse was successful. The public member
@@ -88,6 +146,10 @@
 
   State state_;
 
+  // Time when WaitForDataReady was called and when it has finished.
+  base::TimeTicks wait_for_data_start_time_;
+  base::TimeTicks wait_for_data_end_time_;
+
   // This is the QUIC server (hostname, port, is_https, privacy_mode) tuple for
   // which we restore the crypto_config.
   const QuicServerId server_id_;
@@ -102,6 +164,20 @@
   DISALLOW_COPY_AND_ASSIGN(QuicServerInfo);
 };
 
+class QUIC_EXPORT_PRIVATE QuicServerInfoFactory {
+ public:
+  QuicServerInfoFactory() {}
+  virtual ~QuicServerInfoFactory();
+
+  // GetForServer returns a fresh, allocated QuicServerInfo for the given
+  // |server_id| or NULL on failure.
+  virtual std::unique_ptr<QuicServerInfo> GetForServer(
+      const QuicServerId& server_id) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QuicServerInfoFactory);
+};
+
 }  // namespace net
 
 #endif  // NET_QUIC_CHROMIUM_QUIC_SERVER_INFO_H_
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index e334ede4..ff9a91a 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -331,8 +331,16 @@
       const QuicSessionKey& key,
       bool was_alternative_service_recently_broken,
       int cert_verify_flags,
+      std::unique_ptr<QuicServerInfo> server_info,
       const NetLogWithSource& net_log);
 
+  // Creates a new job to handle the resumption of for connecting an
+  // existing session.
+  Job(QuicStreamFactory* factory,
+      HostResolver* host_resolver,
+      QuicChromiumClientSession* session,
+      const QuicSessionKey& key);
+
   ~Job();
 
   int Run(const CompletionCallback& callback);
@@ -340,13 +348,19 @@
   int DoLoop(int rv);
   int DoResolveHost();
   int DoResolveHostComplete(int rv);
+  int DoLoadServerInfo();
+  int DoLoadServerInfoComplete(int rv);
   int DoConnect();
   int DoConnectComplete(int rv);
 
   void OnIOComplete(int rv);
 
+  void RunAuxilaryJob();
+
   void Cancel();
 
+  void CancelWaitForDataReadyCallback();
+
   const QuicSessionKey& key() const { return key_; }
 
   const NetLogWithSource& net_log() const { return net_log_; }
@@ -361,6 +375,8 @@
     STATE_NONE,
     STATE_RESOLVE_HOST,
     STATE_RESOLVE_HOST_COMPLETE,
+    STATE_LOAD_SERVER_INFO,
+    STATE_LOAD_SERVER_INFO_COMPLETE,
     STATE_CONNECT,
     STATE_CONNECT_COMPLETE,
   };
@@ -372,6 +388,8 @@
   const QuicSessionKey key_;
   const int cert_verify_flags_;
   const bool was_alternative_service_recently_broken_;
+  std::unique_ptr<QuicServerInfo> server_info_;
+  bool started_another_job_;
   const NetLogWithSource net_log_;
   int num_sent_client_hellos_;
   QuicChromiumClientSession* session_;
@@ -388,6 +406,7 @@
                             const QuicSessionKey& key,
                             bool was_alternative_service_recently_broken,
                             int cert_verify_flags,
+                            std::unique_ptr<QuicServerInfo> server_info,
                             const NetLogWithSource& net_log)
     : io_state_(STATE_RESOLVE_HOST),
       factory_(factory),
@@ -396,6 +415,8 @@
       cert_verify_flags_(cert_verify_flags),
       was_alternative_service_recently_broken_(
           was_alternative_service_recently_broken),
+      server_info_(std::move(server_info)),
+      started_another_job_(false),
       net_log_(
           NetLogWithSource::Make(net_log.net_log(),
                                  NetLogSourceType::QUIC_STREAM_FACTORY_JOB)),
@@ -417,6 +438,10 @@
 QuicStreamFactory::Job::~Job() {
   net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB);
   DCHECK(callback_.is_null());
+
+  // If disk cache has a pending WaitForDataReadyCallback, cancel that callback.
+  if (server_info_)
+    server_info_->ResetWaitForDataReadyCallback();
 }
 
 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
@@ -440,6 +465,13 @@
       case STATE_RESOLVE_HOST_COMPLETE:
         rv = DoResolveHostComplete(rv);
         break;
+      case STATE_LOAD_SERVER_INFO:
+        CHECK_EQ(OK, rv);
+        rv = DoLoadServerInfo();
+        break;
+      case STATE_LOAD_SERVER_INFO_COMPLETE:
+        rv = DoLoadServerInfoComplete(rv);
+        break;
       case STATE_CONNECT:
         CHECK_EQ(OK, rv);
         rv = DoConnect();
@@ -461,6 +493,13 @@
     base::ResetAndReturn(&callback_).Run(rv);
 }
 
+void QuicStreamFactory::Job::RunAuxilaryJob() {
+  int rv = Run(base::Bind(&QuicStreamFactory::OnJobComplete,
+                          base::Unretained(factory_), this));
+  if (rv != ERR_IO_PENDING)
+    factory_->OnJobComplete(this, rv);
+}
+
 void QuicStreamFactory::Job::Cancel() {
   callback_.Reset();
   if (session_)
@@ -469,12 +508,24 @@
         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
 }
 
+void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() {
+  // If we are waiting for WaitForDataReadyCallback, then cancel the callback.
+  if (io_state_ != STATE_LOAD_SERVER_INFO_COMPLETE)
+    return;
+  server_info_->CancelWaitForDataReadyCallback();
+  OnIOComplete(OK);
+}
+
 size_t QuicStreamFactory::Job::EstimateMemoryUsage() const {
-  return base::trace_event::EstimateMemoryUsage(key_);
+  return base::trace_event::EstimateMemoryUsage(key_) +
+         base::trace_event::EstimateMemoryUsage(server_info_);
 }
 
 int QuicStreamFactory::Job::DoResolveHost() {
   dns_resolution_start_time_ = base::TimeTicks::Now();
+  // Start loading the data now, and wait for it after we resolve the host.
+  if (server_info_)
+    server_info_->Start();
 
   io_state_ = STATE_RESOLVE_HOST_COMPLETE;
   return host_resolver_->Resolve(
@@ -496,6 +547,71 @@
   if (factory_->OnResolution(key_, address_list_))
     return OK;
 
+  if (server_info_)
+    io_state_ = STATE_LOAD_SERVER_INFO;
+  else
+    io_state_ = STATE_CONNECT;
+  return OK;
+}
+
+int QuicStreamFactory::Job::DoLoadServerInfo() {
+  net_log_.BeginEvent(
+      NetLogEventType::QUIC_STREAM_FACTORY_JOB_LOAD_SERVER_INFO);
+
+  io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE;
+
+  DCHECK(server_info_);
+
+  // To mitigate the effects of disk cache taking too long to load QUIC server
+  // information, set up a timer to cancel WaitForDataReady's callback.
+  if (factory_->load_server_info_timeout_srtt_multiplier_ > 0) {
+    const int kMaxLoadServerInfoTimeoutMs = 50;
+    // Wait for DiskCache a maximum of 50ms.
+    int64_t load_server_info_timeout_ms =
+        std::min(static_cast<int>(
+                     (factory_->load_server_info_timeout_srtt_multiplier_ *
+                      factory_->GetServerNetworkStatsSmoothedRttInMicroseconds(
+                          key_.server_id())) /
+                     1000),
+                 kMaxLoadServerInfoTimeoutMs);
+    if (load_server_info_timeout_ms > 0) {
+      factory_->task_runner_->PostDelayedTask(
+          FROM_HERE,
+          base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback,
+                     GetWeakPtr()),
+          base::TimeDelta::FromMilliseconds(load_server_info_timeout_ms));
+    }
+  }
+
+  int rv = server_info_->WaitForDataReady(
+      base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
+  if (rv == ERR_IO_PENDING && factory_->enable_connection_racing()) {
+    // If we are waiting to load server config from the disk cache, then start
+    // another job.
+    started_another_job_ = true;
+    factory_->CreateAuxilaryJob(key_, cert_verify_flags_, net_log_);
+  }
+  return rv;
+}
+
+int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
+  net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB_LOAD_SERVER_INFO);
+  UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
+                      base::TimeTicks::Now() - dns_resolution_end_time_);
+
+  if (rv != OK)
+    server_info_.reset();
+
+  if (started_another_job_ &&
+      (!server_info_ || server_info_->state().server_config.empty() ||
+       !factory_->CryptoConfigCacheIsEmpty(key_.server_id()))) {
+    // If we have started another job and if we didn't load the server config
+    // from the disk cache or if we have received a new server config from the
+    // server, then cancel the current job.
+    io_state_ = STATE_NONE;
+    return ERR_CONNECTION_CLOSED;
+  }
+
   io_state_ = STATE_CONNECT;
   return OK;
 }
@@ -509,10 +625,10 @@
       NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT,
       NetLog::BoolCallback("require_confirmation", require_confirmation));
 
-  int rv =
-      factory_->CreateSession(key_, cert_verify_flags_, require_confirmation,
-                              address_list_, dns_resolution_start_time_,
-                              dns_resolution_end_time_, net_log_, &session_);
+  int rv = factory_->CreateSession(
+      key_, cert_verify_flags_, std::move(server_info_), require_confirmation,
+      address_list_, dns_resolution_start_time_, dns_resolution_end_time_,
+      net_log_, &session_);
   if (rv != OK) {
     DCHECK(rv != ERR_IO_PENDING);
     DCHECK(!session_);
@@ -655,8 +771,11 @@
     size_t max_packet_length,
     const std::string& user_agent_id,
     const QuicVersionVector& supported_versions,
+    float load_server_info_timeout_srtt_multiplier,
+    bool enable_connection_racing,
     bool enable_non_blocking_io,
-    bool store_server_configs_in_properties,
+    bool disable_disk_cache,
+    int max_server_configs_stored_in_properties,
     bool close_sessions_on_ip_change,
     bool mark_quic_broken_when_network_blackholes,
     int idle_connection_timeout_seconds,
@@ -694,10 +813,13 @@
                                     transport_security_state,
                                     cert_transparency_verifier))),
       supported_versions_(supported_versions),
+      load_server_info_timeout_srtt_multiplier_(
+          load_server_info_timeout_srtt_multiplier),
+      enable_connection_racing_(enable_connection_racing),
       enable_non_blocking_io_(enable_non_blocking_io),
+      disable_disk_cache_(disable_disk_cache),
       mark_quic_broken_when_network_blackholes_(
           mark_quic_broken_when_network_blackholes),
-      store_server_configs_in_properties_(store_server_configs_in_properties),
       ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)),
       reduced_ping_timeout_(
           QuicTime::Delta::FromSeconds(reduced_ping_timeout_seconds)),
@@ -716,6 +838,7 @@
       do_not_fragment_(do_not_fragment),
       estimate_initial_rtt(estimate_initial_rtt),
       check_persisted_supports_quic_(true),
+      has_initialized_data_(false),
       num_push_streams_created_(0),
       task_runner_(nullptr),
       ssl_config_service_(ssl_config_service),
@@ -743,6 +866,13 @@
                         has_aes_hardware_support);
   if (has_aes_hardware_support)
     crypto_config_.PreferAesGcm();
+  // When disk cache is used to store the server configs, HttpCache code calls
+  // |set_quic_server_info_factory| if |quic_server_info_factory_| wasn't
+  // created.
+  if (max_server_configs_stored_in_properties > 0) {
+    quic_server_info_factory_.reset(
+        new PropertiesBasedQuicServerInfoFactory(http_server_properties_));
+  }
 
   // migrate_sessions_early should only be set to true if
   // migrate_sessions_on_network_change is set to true.
@@ -800,6 +930,11 @@
   return base::TimeDelta::FromMicroseconds(srtt);
 }
 
+void QuicStreamFactory::set_quic_server_info_factory(
+    QuicServerInfoFactory* quic_server_info_factory) {
+  quic_server_info_factory_.reset(quic_server_info_factory);
+}
+
 void QuicStreamFactory::DumpMemoryStats(
     base::trace_event::ProcessMemoryDump* pmd,
     const std::string& parent_absolute_name) const {
@@ -934,12 +1069,25 @@
   if (!task_runner_)
     task_runner_ = base::ThreadTaskRunnerHandle::Get().get();
 
+  std::unique_ptr<QuicServerInfo> quic_server_info;
+  if (quic_server_info_factory_.get()) {
+    bool load_from_disk_cache = !disable_disk_cache_;
+    MaybeInitialize();
+    if (!base::ContainsKey(quic_supported_servers_at_startup_, destination)) {
+      // If there is no entry for QUIC, consider that as a new server and
+      // don't wait for Cache thread to load the data for that server.
+      load_from_disk_cache = false;
+    }
+    if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id))
+      quic_server_info = quic_server_info_factory_->GetForServer(server_id);
+  }
+
   ignore_result(StartCertVerifyJob(server_id, cert_verify_flags, net_log));
 
   QuicSessionKey key(destination, server_id);
   std::unique_ptr<Job> job = base::MakeUnique<Job>(
       this, host_resolver_, key, WasQuicRecentlyBroken(server_id),
-      cert_verify_flags, net_log);
+      cert_verify_flags, std::move(quic_server_info), net_log);
   int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
                                base::Unretained(this), job.get()));
   if (rv == ERR_IO_PENDING) {
@@ -985,6 +1133,18 @@
          EstimateServerIdMemoryUsage(server_id_);
 }
 
+void QuicStreamFactory::CreateAuxilaryJob(const QuicSessionKey& key,
+                                          int cert_verify_flags,
+                                          const NetLogWithSource& net_log) {
+  Job* aux_job =
+      new Job(this, host_resolver_, key, WasQuicRecentlyBroken(key.server_id()),
+              cert_verify_flags, nullptr, net_log);
+  active_jobs_[key.server_id()][aux_job] = base::WrapUnique(aux_job);
+  task_runner_->PostTask(FROM_HERE,
+                         base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob,
+                                    aux_job->GetWeakPtr()));
+}
+
 bool QuicStreamFactory::OnResolution(const QuicSessionKey& key,
                                      const AddressList& address_list) {
   const QuicServerId& server_id(key.server_id());
@@ -1483,6 +1643,7 @@
 int QuicStreamFactory::CreateSession(
     const QuicSessionKey& key,
     int cert_verify_flags,
+    std::unique_ptr<QuicServerInfo> server_info,
     bool require_confirmation,
     const AddressList& address_list,
     base::TimeTicks dns_resolution_start_time,
@@ -1511,13 +1672,7 @@
     alarm_factory_.reset(new QuicChromiumAlarmFactory(
         base::ThreadTaskRunnerHandle::Get().get(), clock_));
   }
-
   QuicConnectionId connection_id = random_generator_->RandUint64();
-  std::unique_ptr<QuicServerInfo> server_info;
-  if (store_server_configs_in_properties_) {
-    server_info = base::MakeUnique<PropertiesBasedQuicServerInfo>(
-        server_id, http_server_properties_);
-  }
   InitializeCachedStateInCryptoConfig(server_id, server_info, &connection_id);
 
   QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter(socket.get());
@@ -1539,6 +1694,14 @@
   if (force_hol_blocking_)
     config.SetForceHolBlocking();
 
+  if (quic_server_info_factory_.get() && !server_info) {
+    // Start the disk cache loading so that we can persist the newer QUIC server
+    // information and/or inform the disk cache that we have reused
+    // |server_info|.
+    server_info = quic_server_info_factory_->GetForServer(server_id);
+    server_info->Start();
+  }
+
   // Use the factory to create a new socket performance watcher, and pass the
   // ownership to QuicChromiumClientSession.
   std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher;
@@ -1681,9 +1844,20 @@
   if (!cached->IsEmpty())
     return;
 
-  if (!server_info || !server_info->Load())
+  // |server_info| will be NULL, if a non-empty server config already exists in
+  // the memory cache.
+  if (!server_info)
     return;
 
+  // TODO(rtenneti): Delete the following histogram after collecting stats.
+  // If the AlternativeServiceMap contained an entry for this host, check if
+  // the disk cache contained an entry for it.
+  if (base::ContainsKey(quic_supported_servers_at_startup_,
+                        server_id.host_port_pair())) {
+    UMA_HISTOGRAM_BOOLEAN("Net.QuicServerInfo.ExpectConfigMissingFromDiskCache",
+                          server_info->state().server_config.empty());
+  }
+
   cached->Initialize(server_info->state().server_config,
                      server_info->state().source_address_token,
                      server_info->state().certs, server_info->state().cert_sct,
@@ -1692,6 +1866,60 @@
                      QuicWallTime::Zero());
 }
 
+void QuicStreamFactory::MaybeInitialize() {
+  // We don't initialize data from HttpServerProperties in the constructor
+  // because HttpServerProperties has not yet initialized. We're guaranteed
+  // HttpServerProperties has been initialized by the first time a request is
+  // made.
+  if (has_initialized_data_)
+    return;
+
+  has_initialized_data_ = true;
+
+  // Query the proxy delegate for the default alternative proxy server.
+  ProxyServer default_alternative_proxy_server =
+      proxy_delegate_ ? proxy_delegate_->GetDefaultAlternativeProxy()
+                      : ProxyServer();
+  if (default_alternative_proxy_server.is_quic()) {
+    quic_supported_servers_at_startup_.insert(
+        default_alternative_proxy_server.host_port_pair());
+  }
+
+  for (const std::pair<const url::SchemeHostPort, AlternativeServiceInfoVector>&
+           key_value : http_server_properties_->alternative_service_map()) {
+    HostPortPair host_port_pair(key_value.first.host(), key_value.first.port());
+    for (const AlternativeServiceInfo& alternative_service_info :
+         key_value.second) {
+      if (alternative_service_info.alternative_service.protocol == kProtoQUIC) {
+        quic_supported_servers_at_startup_.insert(host_port_pair);
+        break;
+      }
+    }
+  }
+
+  if (http_server_properties_->max_server_configs_stored_in_properties() == 0)
+    return;
+  // Create a temporary QuicServerInfo object to deserialize and to populate the
+  // in-memory crypto server config cache in the MRU order.
+  std::unique_ptr<QuicServerInfo> server_info;
+  CompletionCallback callback;
+  // Get the list of servers to be deserialized first because WaitForDataReady
+  // touches quic_server_info_map.
+  const QuicServerInfoMap& quic_server_info_map =
+      http_server_properties_->quic_server_info_map();
+  std::vector<QuicServerId> server_list;
+  for (const auto& key_value : quic_server_info_map)
+    server_list.push_back(key_value.first);
+  for (auto it = server_list.rbegin(); it != server_list.rend(); ++it) {
+    const QuicServerId& server_id = *it;
+    server_info = quic_server_info_factory_->GetForServer(server_id);
+    if (server_info->WaitForDataReady(callback) == OK) {
+      DVLOG(1) << "Initialized server config for: " << server_id.ToString();
+      InitializeCachedStateInCryptoConfig(server_id, server_info, nullptr);
+    }
+  }
+}
+
 void QuicStreamFactory::ProcessGoingAwaySession(
     QuicChromiumClientSession* session,
     const QuicServerId& server_id,
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index 661cfeb..f0addeac 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -66,6 +66,7 @@
 class QuicCryptoClientStreamFactory;
 class QuicRandom;
 class QuicServerInfo;
+class QuicServerInfoFactory;
 class QuicStreamFactory;
 class SocketPerformanceWatcherFactory;
 class TransportSecurityState;
@@ -207,8 +208,11 @@
       size_t max_packet_length,
       const std::string& user_agent_id,
       const QuicVersionVector& supported_versions,
+      float load_server_info_timeout_srtt_multiplier,
+      bool enable_connection_racing,
       bool enable_non_blocking_io,
-      bool store_server_configs_in_properties,
+      bool disable_disk_cache,
+      int max_server_configs_stored_in_properties,
       bool close_sessions_on_ip_change,
       bool mark_quic_broken_when_network_blackholes,
       int idle_connection_timeout_seconds,
@@ -364,10 +368,26 @@
 
   QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
 
+  bool has_quic_server_info_factory() const {
+    return quic_server_info_factory_.get() != nullptr;
+  }
+
+  QuicServerInfoFactory* quic_server_info_factory() const {
+    return quic_server_info_factory_.get();
+  }
+
+  void set_quic_server_info_factory(
+      QuicServerInfoFactory* quic_server_info_factory);
+
   void set_server_push_delegate(ServerPushDelegate* push_delegate) {
     push_delegate_ = push_delegate;
   }
 
+  bool enable_connection_racing() const { return enable_connection_racing_; }
+  void set_enable_connection_racing(bool enable_connection_racing) {
+    enable_connection_racing_ = enable_connection_racing;
+  }
+
   bool migrate_sessions_on_network_change() const {
     return migrate_sessions_on_network_change_;
   }
@@ -400,6 +420,12 @@
   typedef std::map<QuicServerId, std::unique_ptr<CertVerifierJob>>
       CertVerifierJobMap;
 
+  // Creates a job which doesn't wait for server config to be loaded from the
+  // disk cache. This job is started via a PostTask.
+  void CreateAuxilaryJob(const QuicSessionKey& key,
+                         int cert_verify_flags,
+                         const NetLogWithSource& net_log);
+
   // Returns a newly created QuicHttpStream owned by the caller.
   std::unique_ptr<QuicHttpStream> CreateFromSession(
       QuicChromiumClientSession* session);
@@ -412,6 +438,7 @@
   bool HasActiveCertVerifierJob(const QuicServerId& server_id) const;
   int CreateSession(const QuicSessionKey& key,
                     int cert_verify_flags,
+                    std::unique_ptr<QuicServerInfo> quic_server_info,
                     bool require_confirmation,
                     const AddressList& address_list,
                     base::TimeTicks dns_resolution_start_time,
@@ -457,6 +484,11 @@
       const std::unique_ptr<QuicServerInfo>& server_info,
       QuicConnectionId* connection_id);
 
+  // Initialize |quic_supported_servers_at_startup_| with the list of servers
+  // that supported QUIC at start up and also initialize in-memory cache of
+  // QuicServerInfo objects from HttpServerProperties.
+  void MaybeInitialize();
+
   void ProcessGoingAwaySession(QuicChromiumClientSession* session,
                                const QuicServerId& server_id,
                                bool was_session_active);
@@ -481,6 +513,7 @@
   ProxyDelegate* proxy_delegate_;
   TransportSecurityState* transport_security_state_;
   CTVerifier* cert_transparency_verifier_;
+  std::unique_ptr<QuicServerInfoFactory> quic_server_info_factory_;
   QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_;
   QuicRandom* random_generator_;  // Unowned.
   QuicClock* clock_;              // Unowned.
@@ -525,16 +558,27 @@
 
   const QuicVersionVector supported_versions_;
 
+  // Specifies the ratio between time to load QUIC server information from disk
+  // cache to 'smoothed RTT'. This ratio is used to calculate the timeout in
+  // milliseconds to wait for loading of QUIC server information. If we don't
+  // want to timeout, set |load_server_info_timeout_srtt_multiplier_| to 0.
+  float load_server_info_timeout_srtt_multiplier_;
+
+  // Set if we want to race connections - one connection that sends
+  // INCHOATE_HELLO and another connection that sends CHLO after loading server
+  // config from the disk cache.
+  bool enable_connection_racing_;
+
   // Set if experimental non-blocking IO should be used on windows sockets.
   bool enable_non_blocking_io_;
 
+  // Set if we do not want to load server config from the disk cache.
+  bool disable_disk_cache_;
+
   // True if QUIC should be marked as broken when a connection blackholes after
   // the handshake is confirmed.
   bool mark_quic_broken_when_network_blackholes_;
 
-  // Set if QUIC server configs should be stored in HttpServerProperties.
-  bool store_server_configs_in_properties_;
-
   // PING timeout for connections.
   QuicTime::Delta ping_timeout_;
   QuicTime::Delta reduced_ping_timeout_;
@@ -575,6 +619,8 @@
   // Local address of socket that was created in CreateSession.
   IPEndPoint local_address_;
   bool check_persisted_supports_quic_;
+  bool has_initialized_data_;
+  std::set<HostPortPair> quic_supported_servers_at_startup_;
 
   NetworkConnection network_connection_;
 
diff --git a/net/quic/chromium/quic_stream_factory_peer.cc b/net/quic/chromium/quic_stream_factory_peer.cc
index d5f4b5c..ff05043 100644
--- a/net/quic/chromium/quic_stream_factory_peer.cc
+++ b/net/quic/chromium/quic_stream_factory_peer.cc
@@ -119,6 +119,20 @@
   return it->second.size();
 }
 
+void QuicStreamFactoryPeer::MaybeInitialize(QuicStreamFactory* factory) {
+  factory->MaybeInitialize();
+}
+
+bool QuicStreamFactoryPeer::HasInitializedData(QuicStreamFactory* factory) {
+  return factory->has_initialized_data_;
+}
+
+bool QuicStreamFactoryPeer::SupportsQuicAtStartUp(QuicStreamFactory* factory,
+                                                  HostPortPair host_port_pair) {
+  return base::ContainsKey(factory->quic_supported_servers_at_startup_,
+                           host_port_pair);
+}
+
 bool QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty(
     QuicStreamFactory* factory,
     const QuicServerId& quic_server_id) {
diff --git a/net/quic/chromium/quic_stream_factory_peer.h b/net/quic/chromium/quic_stream_factory_peer.h
index c2d3be9e..d9b8d1d 100644
--- a/net/quic/chromium/quic_stream_factory_peer.h
+++ b/net/quic/chromium/quic_stream_factory_peer.h
@@ -79,6 +79,13 @@
   static size_t GetNumberOfActiveJobs(QuicStreamFactory* factory,
                                       const QuicServerId& server_id);
 
+  static void MaybeInitialize(QuicStreamFactory* factory);
+
+  static bool HasInitializedData(QuicStreamFactory* factory);
+
+  static bool SupportsQuicAtStartUp(QuicStreamFactory* factory,
+                                    HostPortPair host_port_pair);
+
   static bool CryptoConfigCacheIsEmpty(QuicStreamFactory* factory,
                                        const QuicServerId& quic_server_id);
 
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index a426a10..f3acc60 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -101,18 +101,23 @@
 // and enable_connection_racting.
 struct TestParams {
   friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
-    os << "{ version: " << QuicVersionToString(p.version) << " }";
+    os << "{ version: " << QuicVersionToString(p.version)
+       << ", enable_connection_racing: "
+       << (p.enable_connection_racing ? "true" : "false") << " }";
     return os;
   }
 
   QuicVersion version;
+  bool enable_connection_racing;
 };
 
 std::vector<TestParams> GetTestParams() {
   std::vector<TestParams> params;
   QuicVersionVector all_supported_versions = AllSupportedVersions();
-  for (const auto& version : all_supported_versions)
-    params.push_back(TestParams{version});
+  for (const QuicVersion version : all_supported_versions) {
+    params.push_back(TestParams{version, false});
+    params.push_back(TestParams{version, true});
+  }
   return params;
 }
 
@@ -122,6 +127,8 @@
   friend std::ostream& operator<<(std::ostream& os,
                                   const PoolingTestParams& p) {
     os << "{ version: " << QuicVersionToString(p.version)
+       << ", enable_connection_racing: "
+       << (p.enable_connection_racing ? "true" : "false")
        << ", destination_type: ";
     switch (p.destination_type) {
       case SAME_AS_FIRST:
@@ -139,6 +146,7 @@
   }
 
   QuicVersion version;
+  bool enable_connection_racing;
   DestinationType destination_type;
 };
 
@@ -146,9 +154,12 @@
   std::vector<PoolingTestParams> params;
   QuicVersionVector all_supported_versions = AllSupportedVersions();
   for (const QuicVersion version : all_supported_versions) {
-    params.push_back(PoolingTestParams{version, SAME_AS_FIRST});
-    params.push_back(PoolingTestParams{version, SAME_AS_SECOND});
-    params.push_back(PoolingTestParams{version, DIFFERENT});
+    params.push_back(PoolingTestParams{version, false, SAME_AS_FIRST});
+    params.push_back(PoolingTestParams{version, false, SAME_AS_SECOND});
+    params.push_back(PoolingTestParams{version, false, DIFFERENT});
+    params.push_back(PoolingTestParams{version, true, SAME_AS_FIRST});
+    params.push_back(PoolingTestParams{version, true, SAME_AS_SECOND});
+    params.push_back(PoolingTestParams{version, true, DIFFERENT});
   }
   return params;
 }
@@ -162,9 +173,50 @@
   }
 };
 
+class MockQuicServerInfo : public QuicServerInfo {
+ public:
+  explicit MockQuicServerInfo(const QuicServerId& server_id)
+      : QuicServerInfo(server_id) {}
+  ~MockQuicServerInfo() override {}
+
+  void Start() override {}
+
+  int WaitForDataReady(const CompletionCallback& callback) override {
+    return ERR_IO_PENDING;
+  }
+
+  void ResetWaitForDataReadyCallback() override {}
+
+  void CancelWaitForDataReadyCallback() override {}
+
+  bool IsDataReady() override { return false; }
+
+  bool IsReadyToPersist() override { return false; }
+
+  void Persist() override {}
+
+  void OnExternalCacheHit() override {}
+
+  size_t EstimateMemoryUsage() const override {
+    NOTREACHED();
+    return 0;
+  }
+};
+
+class MockQuicServerInfoFactory : public QuicServerInfoFactory {
+ public:
+  MockQuicServerInfoFactory() {}
+  ~MockQuicServerInfoFactory() override {}
+
+  std::unique_ptr<QuicServerInfo> GetForServer(
+      const QuicServerId& server_id) override {
+    return base::MakeUnique<MockQuicServerInfo>(server_id);
+  }
+};
+
 class QuicStreamFactoryTestBase {
  protected:
-  explicit QuicStreamFactoryTestBase(QuicVersion version)
+  QuicStreamFactoryTestBase(QuicVersion version, bool enable_connection_racing)
       : ssl_config_service_(new MockSSLConfigService),
         random_generator_(0),
         runner_(new TestTaskRunner(&clock_)),
@@ -191,7 +243,10 @@
         url3_(kServer3Url),
         url4_(kServer4Url),
         privacy_mode_(PRIVACY_MODE_DISABLED),
+        load_server_info_timeout_srtt_multiplier_(0.0f),
+        enable_connection_racing_(enable_connection_racing),
         enable_non_blocking_io_(true),
+        disable_disk_cache_(false),
         close_sessions_on_ip_change_(false),
         idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds),
         reduced_ping_timeout_seconds_(kPingTimeoutSecs),
@@ -216,7 +271,9 @@
         /*SocketPerformanceWatcherFactory*/ nullptr,
         &crypto_client_stream_factory_, &random_generator_, &clock_,
         kDefaultMaxPacketSize, string(), SupportedVersions(version_),
-        enable_non_blocking_io_, store_server_configs_in_properties_,
+        load_server_info_timeout_srtt_multiplier_, enable_connection_racing_,
+        enable_non_blocking_io_, disable_disk_cache_,
+        /*max_server_configs_stored_in_properties*/ 0,
         close_sessions_on_ip_change_,
         /*mark_quic_broken_when_network_blackholes*/ false,
         idle_connection_timeout_seconds_, reduced_ping_timeout_seconds_,
@@ -226,6 +283,9 @@
         /*do_not_fragment*/ true, estimate_initial_rtt_, QuicTagVector(),
         /*enable_token_binding*/ false));
     factory_->set_require_confirmation(false);
+    EXPECT_FALSE(factory_->has_quic_server_info_factory());
+    factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory());
+    EXPECT_TRUE(factory_->has_quic_server_info_factory());
   }
 
   void InitializeConnectionMigrationTest(
@@ -481,14 +541,10 @@
   // a non proxy server that support alternative services is added to the
   // HttpServerProperties map.
   void VerifyInitialization(bool proxy_delegate_provides_quic_supported_proxy) {
-    store_server_configs_in_properties_ = true;
     idle_connection_timeout_seconds_ = 500;
     Initialize();
     ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
     crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-    crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-    crypto_client_stream_factory_.set_handshake_mode(
-        MockCryptoClientStream::ZERO_RTT);
     const QuicConfig* config = QuicStreamFactoryPeer::GetConfig(factory_.get());
     EXPECT_EQ(500, config->IdleNetworkTimeout().ToSeconds());
 
@@ -528,11 +584,14 @@
     http_server_properties_.SetMaxServerConfigsStoredInProperties(
         kMaxQuicServersToPersist);
 
-    QuicServerId quic_server_id(kDefaultServerHostName, 443,
+    QuicServerId quic_server_id(kDefaultServerHostName, 80,
                                 PRIVACY_MODE_DISABLED);
-    std::unique_ptr<QuicServerInfo> quic_server_info =
-        base::MakeUnique<PropertiesBasedQuicServerInfo>(
-            quic_server_id, &http_server_properties_);
+    QuicServerInfoFactory* quic_server_info_factory =
+        new PropertiesBasedQuicServerInfoFactory(&http_server_properties_);
+    factory_->set_quic_server_info_factory(quic_server_info_factory);
+
+    std::unique_ptr<QuicServerInfo> quic_server_info(
+        quic_server_info_factory->GetForServer(quic_server_id));
 
     // Update quic_server_info's server_config and persist it.
     QuicServerInfo::State* state = quic_server_info->mutable_state();
@@ -568,10 +627,10 @@
 
     quic_server_info->Persist();
 
-    QuicServerId quic_server_id2(kServer2HostName, 443, PRIVACY_MODE_DISABLED);
-    std::unique_ptr<QuicServerInfo> quic_server_info2 =
-        base::MakeUnique<PropertiesBasedQuicServerInfo>(
-            quic_server_id2, &http_server_properties_);
+    QuicServerId quic_server_id2(kServer2HostName, 80, PRIVACY_MODE_DISABLED);
+    std::unique_ptr<QuicServerInfo> quic_server_info2(
+        quic_server_info_factory->GetForServer(quic_server_id2));
+
     // Update quic_server_info2's server_config and persist it.
     QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
 
@@ -608,6 +667,9 @@
 
     quic_server_info2->Persist();
 
+    QuicStreamFactoryPeer::MaybeInitialize(factory_.get());
+    EXPECT_TRUE(QuicStreamFactoryPeer::HasInitializedData(factory_.get()));
+
     // Verify the MRU order is maintained.
     const QuicServerInfoMap& quic_server_info_map =
         http_server_properties_.quic_server_info_map();
@@ -618,21 +680,8 @@
     ++quic_server_info_map_it;
     EXPECT_EQ(quic_server_info_map_it->first, quic_server_id);
 
-    host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
-                                             "192.168.0.1", "");
-
-    // Create a session and verify that the cached state is loaded.
-    MockQuicData socket_data;
-    socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data.AddSocketDataToFactory(&socket_factory_);
-
-    QuicStreamRequest request(factory_.get(), &http_server_properties_);
-    EXPECT_EQ(ERR_IO_PENDING,
-              request.Request(quic_server_id.host_port_pair(), privacy_mode_,
-                              /*cert_verify_flags=*/0, url_, "GET", net_log_,
-                              callback_.callback()));
-    EXPECT_THAT(callback_.WaitForResult(), IsOk());
-
+    EXPECT_TRUE(QuicStreamFactoryPeer::SupportsQuicAtStartUp(factory_.get(),
+                                                             host_port_pair_));
     EXPECT_FALSE(QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty(
         factory_.get(), quic_server_id));
     QuicCryptoClientConfig* crypto_config =
@@ -649,24 +698,8 @@
     ASSERT_EQ(1U, cached->certs().size());
     EXPECT_EQ(test_cert, cached->certs()[0]);
 
-    EXPECT_TRUE(socket_data.AllWriteDataConsumed());
-
-    // Create a session and verify that the cached state is loaded.
-    MockQuicData socket_data2;
-    socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-    socket_data2.AddSocketDataToFactory(&socket_factory_);
-
-    host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
-                                             "192.168.0.2", "");
-
-    QuicStreamRequest request2(factory_.get(), &http_server_properties_);
-    EXPECT_EQ(ERR_IO_PENDING,
-              request2.Request(quic_server_id2.host_port_pair(), privacy_mode_,
-                               /*cert_verify_flags=*/0,
-                               GURL("https://mail.example.org/"), "GET",
-                               net_log_, callback_.callback()));
-    EXPECT_THAT(callback_.WaitForResult(), IsOk());
-
+    EXPECT_TRUE(QuicStreamFactoryPeer::SupportsQuicAtStartUp(factory_.get(),
+                                                             host_port_pair2));
     EXPECT_FALSE(QuicStreamFactoryPeer::CryptoConfigCacheIsEmpty(
         factory_.get(), quic_server_id2));
     QuicCryptoClientConfig::CachedState* cached2 =
@@ -736,8 +769,10 @@
   TestCompletionCallback callback_;
 
   // Variables to configure QuicStreamFactory.
+  double load_server_info_timeout_srtt_multiplier_;
+  bool enable_connection_racing_;
   bool enable_non_blocking_io_;
-  bool store_server_configs_in_properties_;
+  bool disable_disk_cache_;
   bool close_sessions_on_ip_change_;
   int idle_connection_timeout_seconds_;
   int reduced_ping_timeout_seconds_;
@@ -753,7 +788,9 @@
 class QuicStreamFactoryTest : public QuicStreamFactoryTestBase,
                               public ::testing::TestWithParam<TestParams> {
  protected:
-  QuicStreamFactoryTest() : QuicStreamFactoryTestBase(GetParam().version) {}
+  QuicStreamFactoryTest()
+      : QuicStreamFactoryTestBase(GetParam().version,
+                                  GetParam().enable_connection_racing) {}
 };
 
 INSTANTIATE_TEST_CASE_P(Version,
@@ -4380,7 +4417,62 @@
   }
 }
 
+TEST_P(QuicStreamFactoryTest, RacingConnections) {
+  disable_disk_cache_ = false;
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  if (!enable_connection_racing_)
+    return;
+
+  QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get());
+
+  MockQuicData socket_data;
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data.AddSocketDataToFactory(&socket_factory_);
+
+  MockQuicData socket_data2;
+  socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data2.AddSocketDataToFactory(&socket_factory_);
+
+  const AlternativeService alternative_service1(
+      kProtoQUIC, host_port_pair_.host(), host_port_pair_.port());
+  AlternativeServiceInfoVector alternative_service_info_vector;
+  base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
+  alternative_service_info_vector.push_back(
+      AlternativeServiceInfo(alternative_service1, expiration));
+
+  http_server_properties_.SetAlternativeServices(
+      url::SchemeHostPort(url_), alternative_service_info_vector);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  QuicStreamRequest request(factory_.get(), &http_server_properties_);
+  QuicServerId server_id(host_port_pair_, privacy_mode_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_, privacy_mode_,
+                            /*cert_verify_flags=*/0, url_, "GET", net_log_,
+                            callback_.callback()));
+  EXPECT_EQ(2u, QuicStreamFactoryPeer::GetNumberOfActiveJobs(factory_.get(),
+                                                             server_id));
+
+  runner_->RunNextTask();
+
+  std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+  EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumberOfActiveJobs(factory_.get(),
+                                                             server_id));
+}
+
 TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) {
+  disable_disk_cache_ = true;
   Initialize();
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -4414,6 +4506,7 @@
 
 TEST_P(QuicStreamFactoryTest, ReducePingTimeoutOnConnectionTimeOutOpenStreams) {
   reduced_ping_timeout_seconds_ = 10;
+  disable_disk_cache_ = true;
   Initialize();
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -4505,6 +4598,50 @@
   EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
 }
 
+TEST_P(QuicStreamFactoryTest, DelayTcpRace) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+  MockQuicData socket_data;
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data.AddWrite(
+      ConstructSettingsPacket(1, SETTINGS_MAX_HEADER_LIST_SIZE,
+                              kDefaultMaxUncompressedHeaderSize, nullptr));
+  socket_data.AddSocketDataToFactory(&socket_factory_);
+
+  ServerNetworkStats stats1;
+  stats1.srtt = base::TimeDelta::FromMicroseconds(10);
+  http_server_properties_.SetServerNetworkStats(url::SchemeHostPort(url_),
+                                                stats1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  QuicStreamRequest request(factory_.get(), &http_server_properties_);
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_, privacy_mode_,
+                            /*cert_verify_flags=*/0, url_, "POST", net_log_,
+                            callback_.callback()));
+
+  // Verify delay is one RTT and that server supports QUIC.
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(15),
+            request.GetTimeDelayForWaitingJob());
+
+  // Confirm the handshake and verify that the stream is created.
+  crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
+      QuicSession::HANDSHAKE_CONFIRMED);
+
+  EXPECT_THAT(callback_.WaitForResult(), IsOk());
+
+  std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
 // Verifies that the QUIC stream factory is initialized correctly.
 TEST_P(QuicStreamFactoryTest, MaybeInitialize) {
   VerifyInitialization(false);
@@ -4856,7 +4993,8 @@
       public ::testing::TestWithParam<PoolingTestParams> {
  protected:
   QuicStreamFactoryWithDestinationTest()
-      : QuicStreamFactoryTestBase(GetParam().version),
+      : QuicStreamFactoryTestBase(GetParam().version,
+                                  GetParam().enable_connection_racing),
         destination_type_(GetParam().destination_type),
         hanging_read_(SYNCHRONOUS, ERR_IO_PENDING, 0) {}
 
diff --git a/net/test/scoped_disable_exit_on_dfatal.cc b/net/test/scoped_disable_exit_on_dfatal.cc
index f909126..14821db 100644
--- a/net/test/scoped_disable_exit_on_dfatal.cc
+++ b/net/test/scoped_disable_exit_on_dfatal.cc
@@ -4,28 +4,24 @@
 
 #include "net/test/scoped_disable_exit_on_dfatal.h"
 
+#include "base/bind.h"
 #include "base/logging.h"
+#include "base/strings/string_piece.h"
 
 namespace net {
 namespace test {
 
-// static
-ScopedDisableExitOnDFatal* ScopedDisableExitOnDFatal::g_instance_ = NULL;
+ScopedDisableExitOnDFatal::ScopedDisableExitOnDFatal()
+    : assert_handler_(base::Bind(LogAssertHandler)) {}
 
-ScopedDisableExitOnDFatal::ScopedDisableExitOnDFatal() {
-  CHECK(!g_instance_);
-  g_instance_ = this;
-  logging::SetLogAssertHandler(LogAssertHandler);
-}
-
-ScopedDisableExitOnDFatal::~ScopedDisableExitOnDFatal() {
-  CHECK_EQ(g_instance_, this);
-  logging::SetLogAssertHandler(NULL);
-  g_instance_ = NULL;
-}
+ScopedDisableExitOnDFatal::~ScopedDisableExitOnDFatal() {}
 
 // static
-void ScopedDisableExitOnDFatal::LogAssertHandler(const std::string& str) {
+void ScopedDisableExitOnDFatal::LogAssertHandler(
+    const char* file,
+    int line,
+    const base::StringPiece message,
+    const base::StringPiece stack_trace) {
   // Simply swallow the assert.
 }
 
diff --git a/net/test/scoped_disable_exit_on_dfatal.h b/net/test/scoped_disable_exit_on_dfatal.h
index 33f06e3..5bb7643 100644
--- a/net/test/scoped_disable_exit_on_dfatal.h
+++ b/net/test/scoped_disable_exit_on_dfatal.h
@@ -23,12 +23,14 @@
   ~ScopedDisableExitOnDFatal();
 
  private:
-  // Currently active instance.
-  static ScopedDisableExitOnDFatal* g_instance_;
-
   // Static function which is set as the logging assert handler.
   // Called when there is a check failure.
-  static void LogAssertHandler(const std::string& msg);
+  static void LogAssertHandler(const char* file,
+                               int line,
+                               const base::StringPiece message,
+                               const base::StringPiece stack_trace);
+
+  logging::ScopedLogAssertHandler assert_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedDisableExitOnDFatal);
 };
diff --git a/net/tools/stress_cache/stress_cache.cc b/net/tools/stress_cache/stress_cache.cc
index fefcd72f..3d49fda 100644
--- a/net/tools/stress_cache/stress_cache.cc
+++ b/net/tools/stress_cache/stress_cache.cc
@@ -379,7 +379,10 @@
   return true;
 }
 
-void CrashHandler(const std::string& str) {
+void CrashHandler(const char* file,
+                  int line,
+                  const base::StringPiece str,
+                  const base::StringPiece stack_trace) {
   g_crashing = true;
   base::debug::BreakDebugger();
 }
@@ -414,7 +417,8 @@
   if (argc < 2)
     return MasterCode();
 
-  logging::SetLogAssertHandler(CrashHandler);
+  logging::ScopedLogAssertHandler scoped_assert_handler(
+      base::Bind(CrashHandler));
   logging::SetLogMessageHandler(MessageHandler);
 
 #if defined(OS_WIN)
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 7282a0e5..1eb9711 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -7868,6 +7868,127 @@
   EXPECT_EQ(LOW, job_priority);
 }
 
+TEST_F(URLRequestTest, QuicServerInfoFactoryTest) {
+  HttpNetworkSession::Params params;
+
+  MockClientSocketFactory socket_factory;
+  MockCryptoClientStreamFactory crypto_client_stream_factory;
+  MockHostResolver host_resolver;
+  MockCertVerifier cert_verifier;
+  CTPolicyEnforcer ct_policy_enforcer;
+  TransportSecurityState transport_security_state;
+  std::unique_ptr<CTVerifier> cert_transparency_verifier(
+      new MultiLogCTVerifier());
+  std::unique_ptr<ProxyService> proxy_service = ProxyService::CreateDirect();
+  scoped_refptr<SSLConfigServiceDefaults> ssl_config_service(
+      new SSLConfigServiceDefaults);
+  HttpServerPropertiesImpl http_server_properties;
+  // Set up the quic stream factory.
+  params.enable_quic = true;
+  params.client_socket_factory = &socket_factory;
+  params.quic_crypto_client_stream_factory = &crypto_client_stream_factory;
+  params.host_resolver = &host_resolver;
+  params.cert_verifier = &cert_verifier;
+  params.ct_policy_enforcer = &ct_policy_enforcer;
+  params.transport_security_state = &transport_security_state;
+  params.cert_transparency_verifier = cert_transparency_verifier.get();
+
+  params.proxy_service = proxy_service.get();
+  params.ssl_config_service = ssl_config_service.get();
+  params.http_server_properties = &http_server_properties;
+
+  HttpNetworkSession session(params);
+  DCHECK(session.quic_stream_factory());
+
+  std::unique_ptr<HttpNetworkLayer> network_layer1(
+      new HttpNetworkLayer(&session));
+
+  HttpCache main_cache(std::move(network_layer1),
+                       HttpCache::DefaultBackend::InMemory(0),
+                       true /* is_main_cache */);
+
+  EXPECT_TRUE(session.quic_stream_factory()->has_quic_server_info_factory());
+
+  default_context_.set_http_transaction_factory(&main_cache);
+
+  QuicServerInfoFactory* quic_server_info_factory =
+      session.quic_stream_factory()->quic_server_info_factory();
+  DCHECK(quic_server_info_factory);
+
+  QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED);
+  const string server_config_a = "server_config_a";
+  const string source_address_token_a = "source_address_token_a";
+  const string cert_sct_a = "cert_sct_a";
+  const string chlo_hash_a = "chlo_hash_a";
+  const string server_config_sig_a = "server_config_sig_a";
+  const string cert_a = "cert_a";
+  const string cert_b = "cert_b";
+
+  {
+    // Store a QuicServerInfo to the quic server info factory.
+    TestCompletionCallback cb;
+    std::unique_ptr<QuicServerInfo> quic_server_info =
+        quic_server_info_factory->GetForServer(server_id);
+    quic_server_info->Start();
+    int rv = quic_server_info->WaitForDataReady(cb.callback());
+    EXPECT_THAT(cb.GetResult(rv), IsOk());
+
+    QuicServerInfo::State* state = quic_server_info->mutable_state();
+    EXPECT_TRUE(state->certs.empty());
+
+    state->server_config = server_config_a;
+    state->source_address_token = source_address_token_a;
+    state->cert_sct = cert_sct_a;
+    state->chlo_hash = chlo_hash_a;
+    state->server_config_sig = server_config_sig_a;
+    state->certs.push_back(cert_a);
+    quic_server_info->Persist();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  // Retrieve the QuicServerInfo from the quic server info factory and verify
+  // the data is correct.
+  {
+    TestCompletionCallback cb;
+    std::unique_ptr<QuicServerInfo> quic_server_info =
+        quic_server_info_factory->GetForServer(server_id);
+    quic_server_info->Start();
+    int rv = quic_server_info->WaitForDataReady(cb.callback());
+    EXPECT_THAT(cb.GetResult(rv), IsOk());
+
+    QuicServerInfo::State* state = quic_server_info->mutable_state();
+    EXPECT_TRUE(quic_server_info->IsDataReady());
+    EXPECT_EQ(server_config_a, state->server_config);
+    EXPECT_EQ(source_address_token_a, state->source_address_token);
+    EXPECT_EQ(cert_sct_a, state->cert_sct);
+    EXPECT_EQ(chlo_hash_a, state->chlo_hash);
+    EXPECT_EQ(server_config_sig_a, state->server_config_sig);
+    EXPECT_EQ(1U, state->certs.size());
+    EXPECT_EQ(cert_a, state->certs[0]);
+
+    // Update the data.
+    state->certs.push_back(cert_b);
+    quic_server_info->Persist();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  {
+    // Verify data has been successfully updated.
+    TestCompletionCallback cb;
+    std::unique_ptr<QuicServerInfo> quic_server_info =
+        quic_server_info_factory->GetForServer(server_id);
+    quic_server_info->Start();
+    int rv = quic_server_info->WaitForDataReady(cb.callback());
+    EXPECT_THAT(cb.GetResult(rv), IsOk());
+
+    QuicServerInfo::State* state = quic_server_info->mutable_state();
+    EXPECT_TRUE(quic_server_info->IsDataReady());
+    EXPECT_EQ(2U, state->certs.size());
+    EXPECT_EQ(cert_a, state->certs[0]);
+    EXPECT_EQ(cert_b, state->certs[1]);
+  }
+}
+
 // Check that creating a network request while entering/exiting suspend mode
 // fails as it should.  This is the only case where an HttpTransactionFactory
 // does not return an HttpTransaction.
diff --git a/sandbox/linux/tests/main.cc b/sandbox/linux/tests/main.cc
index caeddee..223a320 100644
--- a/sandbox/linux/tests/main.cc
+++ b/sandbox/linux/tests/main.cc
@@ -4,6 +4,7 @@
 
 #include "base/at_exit.h"
 #include "base/base_switches.h"
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -37,7 +38,10 @@
 }  // namespace sandbox
 
 #if !defined(SANDBOX_USES_BASE_TEST_SUITE)
-void UnitTestAssertHandler(const std::string& str) {
+void UnitTestAssertHandler(const char* file,
+                           int line,
+                           const base::StringPiece message,
+                           const base::StringPiece stack_trace) {
   _exit(1);
 }
 #endif
@@ -64,7 +68,8 @@
   // Death tests rely on LOG(FATAL) triggering an exit (the default behavior is
   // SIGABRT).  The normal test launcher does this at initialization, but since
   // we still do not use this on Android, we must install the handler ourselves.
-  logging::SetLogAssertHandler(UnitTestAssertHandler);
+  logging::ScopedLogAssertHandler scoped_assert_handler(
+      base::Bind(UnitTestAssertHandler));
 #endif
   // Always go through re-execution for death tests.
   // This makes gtest only marginally slower for us and has the
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index 68537a8..b4658f9 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -236,16 +236,18 @@
     "blob/blob_transport_request_builder_unittest.cc",
     "blob/blob_url_request_job_unittest.cc",
     "database/database_quota_client_unittest.cc",
+    "database/database_tracker_unittest.cc",
     "database/database_util_unittest.cc",
     "database/databases_table_unittest.cc",
-    "fileapi/copy_or_move_operation_delegate_unittest.cc",
     "fileapi/copy_or_move_file_validator_unittest.cc",
+    "fileapi/copy_or_move_operation_delegate_unittest.cc",
     "fileapi/dragged_file_util_unittest.cc",
     "fileapi/external_mount_points_unittest.cc",
     "fileapi/file_system_context_unittest.cc",
     "fileapi/file_system_dir_url_request_job_unittest.cc",
     "fileapi/file_system_file_stream_reader_unittest.cc",
     "fileapi/file_system_operation_impl_unittest.cc",
+    "fileapi/file_system_operation_impl_write_unittest.cc",
     "fileapi/file_system_quota_client_unittest.cc",
     "fileapi/file_system_url_request_job_unittest.cc",
     "fileapi/file_system_url_unittest.cc",
@@ -257,13 +259,15 @@
     "fileapi/local_file_util_unittest.cc",
     "fileapi/native_file_util_unittest.cc",
     "fileapi/obfuscated_file_util_unittest.cc",
-    "fileapi/recursive_operation_delegate_unittest.cc",
     "fileapi/plugin_private_file_system_backend_unittest.cc",
     "fileapi/quota/quota_backend_impl_unittest.cc",
     "fileapi/quota/quota_reservation_manager_unittest.cc",
+    "fileapi/recursive_operation_delegate_unittest.cc",
+    "fileapi/sandbox_directory_database_unittest.cc",
     "fileapi/sandbox_file_system_backend_delegate_unittest.cc",
     "fileapi/sandbox_file_system_backend_unittest.cc",
     "fileapi/sandbox_isolated_origin_database_unittest.cc",
+    "fileapi/sandbox_origin_database_unittest.cc",
     "fileapi/sandbox_prioritized_origin_database_unittest.cc",
     "fileapi/timed_task_helper_unittest.cc",
     "fileapi/transient_file_util_unittest.cc",
@@ -295,6 +299,8 @@
     "test/async_file_test_helper.h",
     "test/fileapi_test_file_set.cc",
     "test/fileapi_test_file_set.h",
+    "test/mock_blob_url_request_context.cc",
+    "test/mock_blob_url_request_context.h",
     "test/mock_file_change_observer.cc",
     "test/mock_file_change_observer.h",
     "test/mock_file_update_observer.cc",
@@ -307,6 +313,8 @@
     "test/mock_special_storage_policy.h",
     "test/mock_storage_client.cc",
     "test/mock_storage_client.h",
+    "test/sandbox_database_test_helper.cc",
+    "test/sandbox_database_test_helper.h",
     "test/sandbox_file_system_test_helper.cc",
     "test/sandbox_file_system_test_helper.h",
     "test/test_file_system_backend.cc",
@@ -322,5 +330,6 @@
     "//base/test:test_support",
     "//net:test_support",
     "//testing/gtest",
+    "//third_party/leveldatabase",
   ]
 }
diff --git a/content/browser/database_tracker_unittest.cc b/storage/browser/database/database_tracker_unittest.cc
similarity index 86%
rename from content/browser/database_tracker_unittest.cc
rename to storage/browser/database/database_tracker_unittest.cc
index 0ff0208b..53e53f3d 100644
--- a/content/browser/database_tracker_unittest.cc
+++ b/storage/browser/database/database_tracker_unittest.cc
@@ -39,13 +39,11 @@
   TestObserver()
       : new_notification_received_(false),
         observe_size_changes_(true),
-        observe_scheduled_deletions_(true) {
-  }
+        observe_scheduled_deletions_(true) {}
   TestObserver(bool observe_size_changes, bool observe_scheduled_deletions)
       : new_notification_received_(false),
         observe_size_changes_(observe_size_changes),
-        observe_scheduled_deletions_(observe_scheduled_deletions) {
-  }
+        observe_scheduled_deletions_(observe_scheduled_deletions) {}
 
   ~TestObserver() override {}
   void OnDatabaseSizeChanged(const std::string& origin_identifier,
@@ -72,9 +70,7 @@
     new_notification_received_ = false;
     return temp_new_notification_received;
   }
-  std::string GetNotificationOriginIdentifier() {
-    return origin_identifier_;
-  }
+  std::string GetNotificationOriginIdentifier() { return origin_identifier_; }
   base::string16 GetNotificationDatabaseName() { return database_name_; }
   int64_t GetNotificationDatabaseSize() { return database_size_; }
 
@@ -94,18 +90,14 @@
   EXPECT_TRUE(observer->DidReceiveNewNotification());
   EXPECT_EQ(expected_origin_identifier,
             observer->GetNotificationOriginIdentifier());
-  EXPECT_EQ(expected_database_name,
-            observer->GetNotificationDatabaseName());
-  EXPECT_EQ(expected_database_size,
-            observer->GetNotificationDatabaseSize());
+  EXPECT_EQ(expected_database_name, observer->GetNotificationDatabaseName());
+  EXPECT_EQ(expected_database_size, observer->GetNotificationDatabaseSize());
 }
 
 class TestQuotaManagerProxy : public storage::QuotaManagerProxy {
  public:
   TestQuotaManagerProxy()
-      : QuotaManagerProxy(NULL, NULL),
-        registered_client_(NULL) {
-  }
+      : QuotaManagerProxy(NULL, NULL), registered_client_(NULL) {}
 
   void RegisterClient(storage::QuotaClient* client) override {
     EXPECT_FALSE(registered_client_);
@@ -149,9 +141,7 @@
     }
   }
 
-  bool WasAccessNotified(const GURL& origin) {
-    return accesses_[origin] != 0;
-  }
+  bool WasAccessNotified(const GURL& origin) { return accesses_[origin] != 0; }
 
   bool WasModificationNotified(const GURL& origin, int64_t amount) {
     return modifications_[origin].first != 0 &&
@@ -216,12 +206,9 @@
     const base::string16 kDB3 = ASCIIToUTF16("db3");
     const base::string16 kDescription = ASCIIToUTF16("database_description");
 
-    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                            &database_size);
-    tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
-                            &database_size);
-    tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
+    tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, &database_size);
+    tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0, &database_size);
 
     EXPECT_TRUE(base::CreateDirectory(
         tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
@@ -229,12 +216,12 @@
     EXPECT_TRUE(base::CreateDirectory(
         tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
             tracker->GetOriginDirectory(kOrigin2)))));
-    EXPECT_EQ(1, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
-    EXPECT_EQ(2, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2));
-    EXPECT_EQ(3, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin2, kDB3), "aaa", 3));
+    EXPECT_EQ(
+        1, base::WriteFile(tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
+    EXPECT_EQ(2, base::WriteFile(tracker->GetFullDBFilePath(kOrigin2, kDB2),
+                                 "aa", 2));
+    EXPECT_EQ(3, base::WriteFile(tracker->GetFullDBFilePath(kOrigin2, kDB3),
+                                 "aaa", 3));
     tracker->DatabaseModified(kOrigin1, kDB1);
     tracker->DatabaseModified(kOrigin2, kDB2);
     tracker->DatabaseModified(kOrigin2, kDB3);
@@ -252,26 +239,25 @@
     tracker->DatabaseClosed(kOrigin1, kDB1);
     result = callback.GetResult(result);
     EXPECT_EQ(net::OK, result);
-    EXPECT_FALSE(base::PathExists(
-          tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
+    EXPECT_FALSE(
+        base::PathExists(tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
 
     // Recreate db1.
-    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
     EXPECT_TRUE(base::CreateDirectory(
         tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
             tracker->GetOriginDirectory(kOrigin1)))));
-    EXPECT_EQ(1, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
+    EXPECT_EQ(
+        1, base::WriteFile(tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
     tracker->DatabaseModified(kOrigin1, kDB1);
 
     // Setup file modification times.  db1 and db2 are modified now, db3 three
     // days ago.
     base::Time now = base::Time::Now();
-    EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin1, kDB1),
-                                now, now));
-    EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB2),
-                                now, now));
+    EXPECT_TRUE(
+        base::TouchFile(tracker->GetFullDBFilePath(kOrigin1, kDB1), now, now));
+    EXPECT_TRUE(
+        base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB2), now, now));
     base::Time three_days_ago = now - base::TimeDelta::FromDays(3);
     EXPECT_TRUE(base::TouchFile(tracker->GetFullDBFilePath(kOrigin2, kDB3),
                                 three_days_ago, three_days_ago));
@@ -279,8 +265,7 @@
     // Delete databases modified since yesterday. db2 is whitelisted.
     base::Time yesterday = base::Time::Now();
     yesterday -= base::TimeDelta::FromDays(1);
-    result = tracker->DeleteDataModifiedSince(
-        yesterday, callback.callback());
+    result = tracker->DeleteDataModifiedSince(yesterday, callback.callback());
     EXPECT_EQ(net::ERR_IO_PENDING, result);
     ASSERT_FALSE(callback.have_result());
     EXPECT_TRUE(observer.DidReceiveNewNotification());
@@ -288,12 +273,10 @@
     tracker->DatabaseClosed(kOrigin2, kDB2);
     result = callback.GetResult(result);
     EXPECT_EQ(net::OK, result);
-    EXPECT_FALSE(base::PathExists(
-        tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
-    EXPECT_TRUE(
-        base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
-    EXPECT_TRUE(
-        base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB3)));
+    EXPECT_FALSE(
+        base::PathExists(tracker->DatabaseDirectory().AppendASCII(kOrigin1)));
+    EXPECT_TRUE(base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
+    EXPECT_TRUE(base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB3)));
 
     tracker->DatabaseClosed(kOrigin2, kDB3);
     tracker->RemoveObserver(&observer);
@@ -335,15 +318,11 @@
     EXPECT_TRUE(origin1_info);
     EXPECT_TRUE(origin2_info);
 
-
-    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
     EXPECT_EQ(0, database_size);
-    tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, &database_size);
     EXPECT_EQ(0, database_size);
-    tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0, &database_size);
     EXPECT_EQ(0, database_size);
 
     // Write some data to each file and check that the listeners are
@@ -354,12 +333,12 @@
     EXPECT_TRUE(base::CreateDirectory(
         tracker->DatabaseDirectory().Append(base::FilePath::FromUTF16Unsafe(
             tracker->GetOriginDirectory(kOrigin2)))));
-    EXPECT_EQ(1, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
-    EXPECT_EQ(2, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2));
-    EXPECT_EQ(4, base::WriteFile(
-        tracker->GetFullDBFilePath(kOrigin1, kDB3), "aaaa", 4));
+    EXPECT_EQ(
+        1, base::WriteFile(tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1));
+    EXPECT_EQ(2, base::WriteFile(tracker->GetFullDBFilePath(kOrigin2, kDB2),
+                                 "aa", 2));
+    EXPECT_EQ(4, base::WriteFile(tracker->GetFullDBFilePath(kOrigin1, kDB3),
+                                 "aaaa", 4));
     tracker->DatabaseModified(kOrigin1, kDB1);
     CheckNotificationReceived(&observer1, kOrigin1, kDB1, 1);
     CheckNotificationReceived(&observer2, kOrigin1, kDB1, 1);
@@ -376,8 +355,7 @@
     tracker->DatabaseClosed(kOrigin1, kDB3);
 
     // Open an existing database and check the reported size
-    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
     EXPECT_EQ(1, database_size);
     tracker->DatabaseClosed(kOrigin1, kDB1);
 
@@ -387,8 +365,7 @@
     // Close the tracker database and clear all caches.
     // Then make sure that DatabaseOpened() still returns the correct result.
     tracker->CloseTrackerDatabaseAndClearCaches();
-    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
     EXPECT_EQ(1, database_size);
     tracker->DatabaseClosed(kOrigin1, kDB1);
 
@@ -396,8 +373,7 @@
     tracker->RemoveObserver(&observer1);
 
     // Trying to delete a database in use should fail
-    tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0, &database_size);
     EXPECT_FALSE(tracker->DeleteClosedDatabase(kOrigin1, kDB3));
     origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
     EXPECT_TRUE(origin1_info);
@@ -424,8 +400,7 @@
     EXPECT_EQ(2, origins_info[1].TotalSize());
 
     // Trying to delete an origin with databases in use should fail
-    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
     EXPECT_FALSE(tracker->DeleteOrigin(kOrigin1, false));
     origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
     EXPECT_TRUE(origin1_info);
@@ -465,8 +440,7 @@
     // then delete it. Observe the tracker notifies accordingly.
 
     int64_t database_size = 0;
-    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0, &database_size);
     EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
     test_quota_proxy->reset();
 
@@ -484,8 +458,8 @@
 
     tracker->DatabaseClosed(kOriginId, kName);
     EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
-    EXPECT_EQ(net::OK, tracker->DeleteDatabase(
-        kOriginId, kName, net::CompletionCallback()));
+    EXPECT_EQ(net::OK, tracker->DeleteDatabase(kOriginId, kName,
+                                               net::CompletionCallback()));
     EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
     test_quota_proxy->reset();
 
@@ -493,8 +467,7 @@
     // then close it (at which time deletion will actually occur).
     // Observe the tracker notifies accordingly.
 
-    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0, &database_size);
     EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
     test_quota_proxy->reset();
 
@@ -505,9 +478,9 @@
     EXPECT_TRUE(test_quota_proxy->WasModificationNotified(kOrigin, 100));
     test_quota_proxy->reset();
 
-    EXPECT_EQ(net::ERR_IO_PENDING,
-              tracker->DeleteDatabase(kOriginId, kName,
-                                      net::CompletionCallback()));
+    EXPECT_EQ(
+        net::ERR_IO_PENDING,
+        tracker->DeleteDatabase(kOriginId, kName, net::CompletionCallback()));
     EXPECT_FALSE(test_quota_proxy->WasModificationNotified(kOrigin, -100));
 
     tracker->DatabaseClosed(kOriginId, kName);
@@ -520,8 +493,7 @@
     // a renderer crash.
     // Observe the tracker notifies accordingly.
 
-    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0, &database_size);
     EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
     test_quota_proxy->reset();
     db_file = tracker->GetFullDBFilePath(kOriginId, kName);
@@ -563,11 +535,9 @@
           base::ThreadTaskRunnerHandle::Get().get()));
 
       // Open two new databases.
-      tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                              &database_size);
+      tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
       EXPECT_EQ(0, database_size);
-      tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
-                              &database_size);
+      tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, &database_size);
       EXPECT_EQ(0, database_size);
 
       // Write some data to each file.
@@ -605,8 +575,7 @@
     // and it got deleted.
     EXPECT_EQ(size_t(1), origins_info.size());
     EXPECT_EQ(kOrigin1, origins_info[0].GetOriginIdentifier());
-    EXPECT_TRUE(
-        base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
+    EXPECT_TRUE(base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
     EXPECT_EQ(base::FilePath(), tracker->GetFullDBFilePath(kOrigin2, kDB2));
 
     // The origin directory of kOrigin1 remains, but the origin directory of
@@ -641,11 +610,9 @@
       tracker->SetForceKeepSessionState();
 
       // Open two new databases.
-      tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                              &database_size);
+      tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, &database_size);
       EXPECT_EQ(0, database_size);
-      tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
-                              &database_size);
+      tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, &database_size);
       EXPECT_EQ(0, database_size);
 
       // Write some data to each file.
@@ -681,10 +648,8 @@
     EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info));
     // No origins were deleted.
     EXPECT_EQ(size_t(2), origins_info.size());
-    EXPECT_TRUE(
-        base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
-    EXPECT_TRUE(
-        base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
+    EXPECT_TRUE(base::PathExists(tracker->GetFullDBFilePath(kOrigin1, kDB1)));
+    EXPECT_TRUE(base::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2)));
 
     EXPECT_TRUE(base::PathExists(origin1_db_dir));
     EXPECT_TRUE(base::PathExists(origin2_db_dir));
@@ -763,8 +728,7 @@
     // Create a record of a database in the tracker db and create
     // a spoof_db_file on disk in the expected location.
     int64_t database_size = 0;
-    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
-                            &database_size);
+    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0, &database_size);
     base::FilePath spoof_db_file = tracker->GetFullDBFilePath(kOriginId, kName);
     EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
     EXPECT_TRUE(base::CreateDirectory(spoof_db_file.DirName()));
@@ -791,10 +755,9 @@
     // --------------------------------------------------------
     // Create another record of a database in the tracker db and create
     // a spoof_db_file on disk in the expected location.
-    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
-        &database_size);
-    base::FilePath spoof_db_file2 = tracker->GetFullDBFilePath(kOriginId,
-        kName);
+    tracker->DatabaseOpened(kOriginId, kName, kDescription, 0, &database_size);
+    base::FilePath spoof_db_file2 =
+        tracker->GetFullDBFilePath(kOriginId, kName);
     EXPECT_FALSE(tracker->GetFullDBFilePath(kOriginId, kName).empty());
     EXPECT_NE(spoof_db_file, spoof_db_file2);
     EXPECT_TRUE(base::CreateDirectory(spoof_db_file2.DirName()));
diff --git a/content/browser/fileapi/file_system_operation_impl_write_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
similarity index 93%
rename from content/browser/fileapi/file_system_operation_impl_write_unittest.cc
rename to storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
index b3b255b..ebc48d74 100644
--- a/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "content/public/test/mock_blob_url_request_context.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_job.h"
@@ -25,6 +24,7 @@
 #include "storage/browser/fileapi/file_system_operation_context.h"
 #include "storage/browser/fileapi/file_system_operation_runner.h"
 #include "storage/browser/fileapi/local_file_util.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 #include "storage/browser/test/mock_file_change_observer.h"
 #include "storage/browser/test/mock_quota_manager.h"
 #include "storage/browser/test/test_file_system_backend.h"
@@ -46,15 +46,13 @@
 const GURL kOrigin("http://example.com");
 const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
 
-void AssertStatusEq(base::File::Error expected,
-                    base::File::Error actual) {
+void AssertStatusEq(base::File::Error expected, base::File::Error actual) {
   ASSERT_EQ(expected, actual);
 }
 
 }  // namespace
 
-class FileSystemOperationImplWriteTest
-    : public testing::Test {
+class FileSystemOperationImplWriteTest : public testing::Test {
  public:
   FileSystemOperationImplWriteTest()
       : status_(base::File::FILE_OK),
@@ -146,9 +144,7 @@
     }
   }
 
-  void DidCancel(base::File::Error status) {
-    cancel_status_ = status;
-  }
+  void DidCancel(base::File::Error status) { cancel_status_ = status; }
 
   const MockBlobURLRequestContext& url_request_context() const {
     return *url_request_context_;
@@ -179,13 +175,11 @@
 };
 
 TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) {
-  ScopedTextBlob blob(url_request_context(),
-                      "blob-id:success",
+  ScopedTextBlob blob(url_request_context(), "blob-id:success",
                       "Hello, world!\n");
   file_system_context_->operation_runner()->Write(
       &url_request_context(), URLForPath(virtual_path_),
-      blob.GetBlobDataHandle(),
-      0, RecordWriteCallback());
+      blob.GetBlobDataHandle(), 0, RecordWriteCallback());
   base::RunLoop().Run();
 
   EXPECT_EQ(14, bytes_written());
@@ -209,7 +203,6 @@
   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
 }
 
-
 TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
   std::unique_ptr<storage::BlobDataHandle> null_handle;
   file_system_context_->operation_runner()->Write(
@@ -243,15 +236,14 @@
 TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) {
   base::FilePath virtual_dir_path(FILE_PATH_LITERAL("d"));
   file_system_context_->operation_runner()->CreateDirectory(
-      URLForPath(virtual_dir_path),
-      true /* exclusive */, false /* recursive */,
+      URLForPath(virtual_dir_path), true /* exclusive */, false /* recursive */,
       base::Bind(&AssertStatusEq, base::File::FILE_OK));
 
   ScopedTextBlob blob(url_request_context(), "blob:writedir",
                       "It\'ll not be written, too.");
   file_system_context_->operation_runner()->Write(
       &url_request_context(), URLForPath(virtual_dir_path),
-      blob.GetBlobDataHandle(),  0, RecordWriteCallback());
+      blob.GetBlobDataHandle(), 0, RecordWriteCallback());
   base::RunLoop().Run();
 
   EXPECT_EQ(0, bytes_written());
@@ -266,8 +258,7 @@
 }
 
 TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) {
-  ScopedTextBlob blob(url_request_context(), "blob:success",
-                      "Hello, world!\n");
+  ScopedTextBlob blob(url_request_context(), "blob:success", "Hello, world!\n");
   quota_manager_->SetQuota(
       kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10);
   file_system_context_->operation_runner()->Write(
@@ -283,8 +274,7 @@
 }
 
 TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) {
-  ScopedTextBlob blob(url_request_context(), "blob:success",
-                      "Hello, world!\n");
+  ScopedTextBlob blob(url_request_context(), "blob:success", "Hello, world!\n");
   FileSystemOperationRunner::OperationID id =
       file_system_context_->operation_runner()->Write(
           &url_request_context(), URLForPath(virtual_path_),
diff --git a/content/browser/fileapi/sandbox_directory_database_unittest.cc b/storage/browser/fileapi/sandbox_directory_database_unittest.cc
similarity index 99%
rename from content/browser/fileapi/sandbox_directory_database_unittest.cc
rename to storage/browser/fileapi/sandbox_directory_database_unittest.cc
index 77525f2..30df665 100644
--- a/content/browser/fileapi/sandbox_directory_database_unittest.cc
+++ b/storage/browser/fileapi/sandbox_directory_database_unittest.cc
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "content/browser/fileapi/sandbox_database_test_helper.h"
+#include "storage/browser/test/sandbox_database_test_helper.h"
 #include "storage/common/fileapi/file_system_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
diff --git a/content/browser/fileapi/sandbox_origin_database_unittest.cc b/storage/browser/fileapi/sandbox_origin_database_unittest.cc
similarity index 99%
rename from content/browser/fileapi/sandbox_origin_database_unittest.cc
rename to storage/browser/fileapi/sandbox_origin_database_unittest.cc
index 8c92e4f..e2675a76 100644
--- a/content/browser/fileapi/sandbox_origin_database_unittest.cc
+++ b/storage/browser/fileapi/sandbox_origin_database_unittest.cc
@@ -17,8 +17,8 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
-#include "content/browser/fileapi/sandbox_database_test_helper.h"
 #include "storage/browser/fileapi/sandbox_origin_database.h"
+#include "storage/browser/test/sandbox_database_test_helper.h"
 #include "storage/common/fileapi/file_system_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/src/db/filename.h"
diff --git a/content/public/test/mock_blob_url_request_context.cc b/storage/browser/test/mock_blob_url_request_context.cc
similarity index 78%
rename from content/public/test/mock_blob_url_request_context.cc
rename to storage/browser/test/mock_blob_url_request_context.cc
index 515c1f3..0e4f67d 100644
--- a/content/public/test/mock_blob_url_request_context.cc
+++ b/storage/browser/test/mock_blob_url_request_context.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/public/test/mock_blob_url_request_context.h"
+#include "storage/browser/test/mock_blob_url_request_context.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -28,12 +28,10 @@
   AssertNoURLRequests();
 }
 
-ScopedTextBlob::ScopedTextBlob(
-    const MockBlobURLRequestContext& request_context,
-    const std::string& blob_id,
-    const std::string& data)
-    : blob_id_(blob_id),
-      context_(request_context.blob_storage_context()) {
+ScopedTextBlob::ScopedTextBlob(const MockBlobURLRequestContext& request_context,
+                               const std::string& blob_id,
+                               const std::string& data)
+    : blob_id_(blob_id), context_(request_context.blob_storage_context()) {
   DCHECK(context_);
   storage::BlobDataBuilder blob_builder(blob_id_);
   if (!data.empty())
@@ -41,8 +39,7 @@
   handle_ = context_->AddFinishedBlob(&blob_builder);
 }
 
-ScopedTextBlob::~ScopedTextBlob() {
-}
+ScopedTextBlob::~ScopedTextBlob() {}
 
 std::unique_ptr<storage::BlobDataHandle> ScopedTextBlob::GetBlobDataHandle() {
   return context_->GetBlobDataFromUUID(blob_id_);
diff --git a/content/public/test/mock_blob_url_request_context.h b/storage/browser/test/mock_blob_url_request_context.h
similarity index 100%
rename from content/public/test/mock_blob_url_request_context.h
rename to storage/browser/test/mock_blob_url_request_context.h
diff --git a/content/browser/fileapi/sandbox_database_test_helper.cc b/storage/browser/test/sandbox_database_test_helper.cc
similarity index 97%
rename from content/browser/fileapi/sandbox_database_test_helper.cc
rename to storage/browser/test/sandbox_database_test_helper.cc
index 45dbaff7..2371fb1 100644
--- a/content/browser/fileapi/sandbox_database_test_helper.cc
+++ b/storage/browser/test/sandbox_database_test_helper.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/fileapi/sandbox_database_test_helper.h"
+#include "storage/browser/test/sandbox_database_test_helper.h"
 
 #include <stdint.h>
 
diff --git a/content/browser/fileapi/sandbox_database_test_helper.h b/storage/browser/test/sandbox_database_test_helper.h
similarity index 100%
rename from content/browser/fileapi/sandbox_database_test_helper.h
rename to storage/browser/test/sandbox_database_test_helper.h
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index e5cb856..963eeca 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -901,57 +901,109 @@
 Bug(none) fast/sub-pixel/sub-pixel-composited-layer-with-transform.html [ Failure ]
 Bug(none) fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ Failure ]
 Bug(none) fast/table/023.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/023.html [ Failure ]
 Bug(none) fast/table/027-vertical.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/027-vertical.html [ Failure ]
 Bug(none) fast/table/040-vertical.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/040-vertical.html [ Failure ]
 Bug(none) fast/table/040.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/040.html [ Failure ]
 Bug(none) fast/table/border-collapsing/004.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/border-collapsing/004.html [ Failure ]
 Bug(none) fast/table/dynamic-caption-add-before-child.xhtml [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/dynamic-caption-add-before-child.xhtml [ Failure ]
 Bug(none) fast/table/empty-cells.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/empty-cells.html [ Failure ]
 Bug(none) fast/table/frame-and-rules.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/frame-and-rules.html [ Failure ]
 Bug(none) fast/table/height-percent-test.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/height-percent-test.html [ Failure ]
 Bug(none) fast/table/multiple-captions-display.xhtml [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/multiple-captions-display.xhtml [ Failure ]
 Bug(none) fast/table/overflowHidden.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/overflowHidden.html [ Failure ]
 Bug(none) fast/table/prepend-in-anonymous-table.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/prepend-in-anonymous-table.html [ Failure ]
 Bug(none) fast/table/table-display-types-vertical.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/table-display-types-vertical.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-cell-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-cell-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-cell.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-cell.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-column-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-column-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-column-group-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-column-group-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-column-group.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-column-group.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-column.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-column.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-row-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-row-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-row-group-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-row-group-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-row-group.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-row-group.html [ Failure ]
 Bug(none) fast/table/backgr_border-table-row.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table-row.html [ Failure ]
 Bug(none) fast/table/backgr_border-table.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_border-table.html [ Failure ]
 Bug(none) fast/table/backgr_layers-hide.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_layers-hide.html [ Failure ]
 Bug(none) fast/table/backgr_layers-opacity-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_layers-opacity-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_layers-opacity.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_layers-opacity.html [ Failure ]
 Bug(none) fast/table/backgr_layers-show-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_layers-show-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_layers-show.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_layers-show.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-cell-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-cell-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-cell.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-cell.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-column-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-column-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-column-group-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-column-group-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-column-group.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-column-group.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-column.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-column.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-row-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-row-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-row-group-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-row-group-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-row-group.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-row-group.html [ Failure ]
 Bug(none) fast/table/backgr_position-table-row.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table-row.html [ Failure ]
 Bug(none) fast/table/backgr_position-table.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_position-table.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-cell-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-cell-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-cell.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-cell.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-column-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-column-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-column-group-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-column-group-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-column-group.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-column-group.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-column.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-column.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-row-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-row-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-row-group-collapsed-border.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-row-group-collapsed-border.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-row-group.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-row-group.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table-row.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table-row.html [ Failure ]
 Bug(none) fast/table/backgr_simple-table.html [ Failure ]
+Bug(none) virtual/mojo-loading/fast/table/backgr_simple-table.html [ Failure ]
 Bug(none) fast/text-autosizing/hackernews-comments.html [ Failure ]
 Bug(none) fast/text/capitalize-boundaries.html [ Failure ]
 Bug(none) fast/text/descent-clip-in-scaled-page.html [ Crash Timeout ]
diff --git a/third_party/WebKit/LayoutTests/ImageFirstTests b/third_party/WebKit/LayoutTests/ImageFirstTests
index ab1c8c0..58d0727 100644
--- a/third_party/WebKit/LayoutTests/ImageFirstTests
+++ b/third_party/WebKit/LayoutTests/ImageFirstTests
@@ -78,3 +78,4 @@
 virtual/layout_ng/fast/block/margin-collapse
 virtual/layout_ng/fast/block/float
 virtual/layout_ng/external/wpt/css/CSS2/linebox
+virtual/mojo-loading/fast/table
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests
index 58e3340..af54bb9 100644
--- a/third_party/WebKit/LayoutTests/NeverFixTests
+++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -204,7 +204,9 @@
 crbug.com/606302 [ Win7 Debug ] transforms/3d/point-mapping/3d-point-mapping-preserve-3d.html [ WontFix ]
 crbug.com/606302 [ Win7 Debug ] transforms/3d/point-mapping/3d-point-mapping-deep.html [ WontFix ]
 crbug.com/702176 [ Win7 Debug ] fast/table/border-collapsing/001-vertical.html [ WontFix ]
+crbug.com/702176 [ Win7 Debug ] virtual/mojo-loading/fast/table/border-collapsing/001-vertical.html [ WontFix ]
 crbug.com/702176 [ Win7 Debug ] fast/table/border-collapsing/001.html [ WontFix ]
+crbug.com/702176 [ Win7 Debug ] virtual/mojo-loading/fast/table/border-collapsing/001.html [ WontFix ]
 
 # Rendering issue only seen in Layout Tests on Android.
 # R and B color channels switched on decoded images.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 7244db8f..c40c96b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -758,6 +758,8 @@
 crbug.com/636207 [ Win Debug ] fast/dom/HTMLImageElement/image-srcset-w-onerror.html [ Failure Pass ]
 crbug.com/636207 [ Win Debug ] virtual/sharedarraybuffer/fast/dom/HTMLImageElement/image-srcset-w-onerror.html [ Failure Pass ]
 
+crbug.com/v8/6206 fast/js/string-prototype-properties.html [ NeedsManualRebaseline ]
+
 crbug.com/569139 fast/js/string-replace-2.html [ Failure ]
 crbug.com/569139 fast/js/regexp-caching.html [ Failure ]
 crbug.com/597221 fast/dom/Window/window-postmessage-clone-deep-array.html [ Failure ]
@@ -787,6 +789,7 @@
 crbug.com/264138 dom/legacy_dom_conformance/xhtml/level3/core/nodecomparedocumentposition38.xhtml [ Failure ]
 
 crbug.com/410145 [ Win ] fast/table/column-in-inline.html [ Failure ]
+crbug.com/410145 [ Win ] virtual/mojo-loading/fast/table/column-in-inline.html [ Failure ]
 crbug.com/411164 [ Win ] http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Pass ]
 crbug.com/411164 [ Win ] virtual/mojo-loading/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Pass ]
 
@@ -1811,7 +1814,6 @@
 crbug.com/711529 virtual/mojo-loading/http/tests/notifications/update-shared-worker.html [ Timeout ]
 crbug.com/711529 virtual/mojo-loading/http/tests/notifications/close-shared-worker.html [ Timeout ]
 crbug.com/711529 virtual/mojo-loading/http/tests/notifications/click-shared-worker.html [ Timeout ]
-crbug.com/711529 virtual/mojo-loading/http/tests/streams/piping/multiple-propagation.https.html [ Timeout ]
 crbug.com/711529 virtual/mojo-loading/http/tests/permissions/test-api-surface.html [ Timeout ]
 crbug.com/711529 virtual/mojo-loading/http/tests/permissions/test-query.html [ Timeout ]
 crbug.com/711529 http/tests/origin_trials/sample-api-workers.html [ Timeout ]
@@ -1821,7 +1823,6 @@
 crbug.com/711529 http/tests/notifications/click-shared-worker.html [ Timeout ]
 crbug.com/711529 http/tests/permissions/test-api-surface.html [ Timeout ]
 crbug.com/711529 http/tests/permissions/test-query.html [ Timeout ]
-crbug.com/711529 http/tests/streams/piping/multiple-propagation.https.html [ Timeout ]
 
 # ====== New tests from wpt-importer added here ======
 crbug.com/626703 external/wpt/XMLHttpRequest/getresponseheader-chunked-trailer.htm [ Failure ]
@@ -1873,15 +1874,6 @@
 crbug.com/626703 external/wpt/streams/readable-streams/pipe-through.sharedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/readable-streams/tee.sharedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/readable-streams/templated.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/bad-strategies.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/bad-underlying-sinks.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/brand-checks.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/byte-length-queuing-strategy.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/count-queuing-strategy.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/general.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/reentrant-strategy.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/start.sharedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/write.sharedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/css/CSS2/linebox/inline-formatting-context-010b.xht [ Skip ]
 crbug.com/626703 external/wpt/css/CSS2/linebox/inline-formatting-context-012.xht [ Failure ]
 crbug.com/626703 [ Android Linux Win ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Failure ]
@@ -1993,8 +1985,6 @@
 crbug.com/626703 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/windows-1251.html [ Timeout ]
 crbug.com/626703 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/windows-1252.html [ Timeout ]
 crbug.com/626703 [ Android Mac ] external/wpt/pointerevents/pointerevent_disabled_form_control-manual.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/floating-point-total-queue-size.dedicatedworker.html [ Timeout ]
-crbug.com/626703 external/wpt/streams/writable-streams/floating-point-total-queue-size.sharedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/mediacapture-streams/MediaStreamTrack-end-manual.https.html [ Timeout ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html [ Failure ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html [ Failure ]
@@ -2558,6 +2548,7 @@
 
 crbug.com/652536 fast/events/mouse-cursor.html [ Pass Failure ]
 crbug.com/671478 fast/table/percent-height-replaced-content-in-cell.html [ Pass Failure ]
+crbug.com/671478 virtual/mojo-loading/fast/table/percent-height-replaced-content-in-cell.html [ Pass Failure ]
 crbug.com/663858 fast/text/emphasis.html [ Pass Failure ]
 crbug.com/663858 fast/text/emphasis-vertical.html [ Pass Failure ]
 crbug.com/663876 http/tests/loading/doc-write-sync-third-party-script-block-effectively-2g.html [ Pass Failure ]
@@ -2673,10 +2664,6 @@
 # Flaky on trybots
 crbug.com/688486 external/wpt/service-workers/service-worker/fetch-request-resources.https.html [ Failure Pass ]
 
-# Flaky when run in parallel
-crbug.com/712332 accessibility/aom.html [ Failure Pass ]
-crbug.com/712332 accessibility/aom-string-properties.html [ Failure Pass ]
-
 # Sheriff failures 2017-02-21
 crbug.com/73609 http/tests/media/video-play-stall.html [ Pass Timeout ]
 crbug.com/73609 virtual/mojo-loading/http/tests/media/video-play-stall.html [ Pass Timeout ]
@@ -2719,5 +2706,3 @@
 
 # Tests to be run only under virtual/experimental-canvas-features/
 crbug.com/682753 fast/canvas-experimental [ Skip ]
-
-crbug.com/712264 external/wpt/service-workers/service-worker/fetch-event.https.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index f018d97b..14cf539 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -408,6 +408,11 @@
     "args": ["--enable-blink-features=LoadingWithMojo"]
   },
   {
+    "prefix": "mojo-loading",
+    "base": "fast/table",
+    "args": ["--enable-blink-features=LoadingWithMojo"]
+  },
+  {
     "prefix": "scalefactor150",
     "base": "fast/events/synthetic-events",
     "args": ["--force-device-scale-factor=1.5"]
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html b/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html
index ea3fac33..3e17d31 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-string-properties.html
@@ -12,8 +12,9 @@
 -->
 
 <script>
-if (window.internals)
-    internals.runtimeFlags.accessibilityObjectModelEnabled = true;
+test(function(t) {
+    assert_true(internals.runtimeFlags.accessibilityObjectModelEnabled);
+}, "Make sure that Accessibility Object Model is enabled");
 </script>
 
 <div role="combobox" id="autocomplete"></div>
@@ -34,18 +35,22 @@
 test(function(t) {
     var node = document.getElementById("checked");
     var axNode = accessibilityController.accessibleElementById("checked");
-    assert_equals(axNode.checkedState, 0);
+    assert_equals(axNode.isChecked, false);
+    assert_equals(axNode.isButtonStateMixed, false);
     node.accessibleNode.checked = "true";
-    assert_equals(axNode.checkedState, 1);
+    assert_equals(axNode.isChecked, true);
+    assert_equals(axNode.isButtonStateMixed, false);
     node.accessibleNode.checked = "mixed";
-    assert_equals(axNode.checkedState, 2);
+    assert_equals(axNode.isChecked, true);
     assert_equals(axNode.isButtonStateMixed, true);
 
     // It also works to set it to just true or false (no quotes).
     node.accessibleNode.checked = true;
-    assert_equals(axNode.checkedState, 1);
+    assert_equals(axNode.isChecked, true);
+    assert_equals(axNode.isButtonStateMixed, false);
     node.accessibleNode.checked = false;
-    assert_equals(axNode.checkedState, 0);
+    assert_equals(axNode.isChecked, false);
+    assert_equals(axNode.isButtonStateMixed, false);
 
 }, "AccessibleNode.checked");
 </script>
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom.html b/third_party/WebKit/LayoutTests/accessibility/aom.html
index c77de58..bb19384 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom.html
@@ -14,8 +14,9 @@
 <button id="button">Click Me</button>
 
 <script>
-if (window.internals)
-    internals.runtimeFlags.accessibilityObjectModelEnabled = true;
+test(function(t) {
+    assert_true(internals.runtimeFlags.accessibilityObjectModelEnabled);
+}, "Make sure that Accessibility Object Model is enabled");
 
 test(function(t) {
     var button = document.getElementById("button");
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/combine-motion-translation-and-rotation-expected.html b/third_party/WebKit/LayoutTests/css3/motion-path/combine-motion-translation-and-rotation-expected.html
deleted file mode 100644
index 6743e04..0000000
--- a/third_party/WebKit/LayoutTests/css3/motion-path/combine-motion-translation-and-rotation-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-#div1 {
-    position: absolute;
-    left: 100;
-    top: 200;
-    transform-origin: 60% 20%;
-    transform: translate(70px, 80px) rotate(30deg) translate(80px, 60px) rotate(-90deg);
-    transform-origin: 0% 0%;
-}
-</style>
-</head>
-<body>
-<div id="div1">div1</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/combine-motion-translation-and-rotation.html b/third_party/WebKit/LayoutTests/css3/motion-path/combine-motion-translation-and-rotation.html
deleted file mode 100644
index 982e39e0..0000000
--- a/third_party/WebKit/LayoutTests/css3/motion-path/combine-motion-translation-and-rotation.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-#div1 {
-    position: absolute;
-    left: 100;
-    top: 200;
-    motion: path('M 20 30 l 100 100') auto -15deg 50%;
-    transform: translate(80px, 60px) rotate(-90deg);
-    transform-origin: 0% 0%;
-    offset-anchor: 0% 0%;
-}
-</style>
-</head>
-<body>
-<div id="div1">div1</div>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/motion-shorthand-deprecated-expected.txt b/third_party/WebKit/LayoutTests/css3/motion-path/motion-shorthand-deprecated-expected.txt
deleted file mode 100644
index 9aeb8308..0000000
--- a/third_party/WebKit/LayoutTests/css3/motion-path/motion-shorthand-deprecated-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CONSOLE WARNING: motion is deprecated and will be removed in M58, around April 2017. Please use offset instead. See https://www.chromestatus.com/features/6390764217040896 for more details.
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/motion-shorthand-deprecated.html b/third_party/WebKit/LayoutTests/css3/motion-path/motion-shorthand-deprecated.html
deleted file mode 100644
index 94f1572e..0000000
--- a/third_party/WebKit/LayoutTests/css3/motion-path/motion-shorthand-deprecated.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/js-test.js"></script>
-<style>
-.foo {
-  motion: path('m 0 0 v 1');
-}
-</style>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/motion.html b/third_party/WebKit/LayoutTests/css3/motion-path/motion.html
deleted file mode 100644
index 7d6a79b..0000000
--- a/third_party/WebKit/LayoutTests/css3/motion-path/motion.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<style>
-#div2 {
-    motion: none 50% auto 400grad;
-}
-#div3 {
-    motion: path('M 10 20 h 30 v 150') 0rad 70px;
-}
-#div4 {
-    motion: 10px 90deg reverse none;
-}
-</style>
-</head>
-<body>
-<div id="div1"></div>
-<div id="div2"></div>
-<div id="div3"></div>
-<div id="div4"></div>
-<span id="span1" style="motion: path('M 1 2 V 3') 4px 5deg"></span>
-<script>
-"use strict";
-
-test(function() {
-    assert_equals(getComputedStyle(div1, null).motionPath, 'none');
-    assert_equals(getComputedStyle(div1, null).motionOffset, '0px');
-    assert_equals(getComputedStyle(div1, null).motionRotation, 'auto 0deg');
-    assert_equals(getComputedStyle(div1, null).motion, 'none 0px auto 0deg');
-    assert_equals(getComputedStyle(div1, null).transform, 'none');
-}, 'motion default is none 0px auto 0deg');
-
-test(function() {
-    assert_equals(getComputedStyle(div2, null).motionPath, 'none');
-    assert_equals(getComputedStyle(div2, null).motionOffset, '50%');
-    assert_equals(getComputedStyle(div2, null).motionRotation, 'auto 360deg');
-    assert_equals(getComputedStyle(div2, null).motion, 'none 50% auto 360deg');
-    assert_equals(getComputedStyle(div2, null).transform, 'none');
-}, 'motion supports various angle units');
-
-test(function() {
-    assert_equals(getComputedStyle(div3, null).motionPath, "path('M 10 20 h 30 v 150')");
-    assert_equals(getComputedStyle(div3, null).motionOffset, '70px');
-    assert_equals(getComputedStyle(div3, null).motionRotation, '0deg');
-    assert_equals(getComputedStyle(div3, null).motion, "path('M 10 20 h 30 v 150') 70px 0deg");
-    assert_equals(getComputedStyle(div3, null).transform, 'matrix(1, 0, 0, 1, 0, 0)');
-}, 'motion supports SVG path data');
-
-test(function() {
-    assert_equals(getComputedStyle(div4, null).motionPath, 'none');
-    assert_equals(getComputedStyle(div4, null).motionOffset, '10px');
-    assert_equals(getComputedStyle(div4, null).motionRotation, 'auto 270deg');
-    assert_equals(getComputedStyle(div4, null).motion, 'none 10px auto 270deg');
-    assert_equals(getComputedStyle(div4, null).transform, 'none');
-}, 'motion property data can be supplied in any order');
-
-test(function() {
-    assert_equals(span1.style.motionPath, "path('M 1 2 V 3')");
-    assert_equals(span1.style.motionOffset, '4px');
-    assert_equals(span1.style.motionRotation, '5deg');
-    assert_equals(span1.style.motion, "path('M 1 2 V 3') 4px 5deg");
-    assert_equals(span1.style.transform, '');
-}, 'motion style can be set inline');
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/use-count-motion.html b/third_party/WebKit/LayoutTests/css3/motion-path/use-count-motion.html
deleted file mode 100644
index 51d63f3..0000000
--- a/third_party/WebKit/LayoutTests/css3/motion-path/use-count-motion.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<head>
-  <script src="../../resources/testharness.js"></script>
-  <script src="../../resources/testharnessreport.js"></script>
-  <style>
-  .n { motion: none; }
-  </style>
-</head>
-
-<div id="target"></div>
-<script>
-var CSSMotionInEffect = 1616; // From UseCounter.h
-var CSSOffsetInEffect = 1617; // From UseCounter.h
-
-test(function() {
-  assert_false(internals.isUseCounted(document, CSSMotionInEffect));
-
-  var styleElement = document.createElement('style');
-  styleElement.textContent = ".p { motion: path('m 0 0 h 1'); }";
-  document.head.appendChild(styleElement);
-
-  assert_true(internals.isUseCounted(document, CSSMotionInEffect));
-
-  assert_false(internals.isUseCounted(document, CSSOffsetInEffect));
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 0169b6d3..e174aae3 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -75715,6 +75715,11 @@
      {}
     ]
    ],
+   "html/browsers/the-window-object/window-indexed-properties-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/browsers/the-window-object/window-indexed-properties-strict-expected.txt": [
     [
      {}
@@ -176399,6 +176404,10 @@
    "d2821f3c4c01cb0dde1ec892d90e7309bbe842a7",
    "testharness"
   ],
+  "html/browsers/the-window-object/window-indexed-properties-expected.txt": [
+   "993d4ee44994a8a0d06d354abe3aa596946dd72a",
+   "support"
+  ],
   "html/browsers/the-window-object/window-indexed-properties-strict-expected.txt": [
    "624baff00a9efae0597ae657ed81dfd2403248d4",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-combine-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-combine-expected.txt
deleted file mode 100644
index 268727c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-combine-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-FAIL Create headers using same name for different values assert_equals: expected "doubleValue1, doubleValue2" but got "doubleValue1,doubleValue2"
-PASS Check delete and has methods when using same name for different values 
-PASS Check set methods when called with already used name 
-FAIL Check append methods when called with already used name assert_equals: expected "singleValue, newSingleValue" but got "singleValue,newSingleValue"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt
index 7d5a409..cb3a41bf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https-expected.txt
@@ -11,8 +11,8 @@
 PASS Multiple calls of respondWith must throw InvalidStateErrors 
 PASS Service Worker event.respondWith must set the used flag 
 PASS Service Worker should expose FetchEvent URL fragments. 
-FAIL Service Worker responds to fetch event with the correct cache types assert_unreached: unexpected rejection: assert_equals: expected "no-cache" but got "default" Reached unreachable code
+FAIL Service Worker responds to fetch event with the correct cache types assert_unreached: unexpected rejection: assert_equals: Service Worker should respond to fetch with the correct type expected "no-store" but got "default" Reached unreachable code
 FAIL Service Worker should intercept EventSource assert_unreached: unexpected rejection: assert_equals: EventSource should bypass the http cache. expected "no-store" but got "default" Reached unreachable code
-PASS Service Worker responds to fetch event with the correct integrity_metadata 
+FAIL Service Worker responds to fetch event with the correct integrity_metadata assert_unreached: unexpected rejection: assert_equals: integrity expected "gs0nqru8KbsrIt5YToQqS9fYao4GQJXtcId610g7cCU=" but got "" Reached unreachable code
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
index 8d0531e..062a41e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
@@ -516,6 +516,7 @@
         })
       .catch(unreached_rejection(t));
   }, 'Service Worker should expose FetchEvent URL fragments.');
+
 async_test(function(t) {
     var scope = 'resources/simple.html?cache';
     var frame;
@@ -549,6 +550,7 @@
                   .catch(reject);
               });
           });
+          return Promise.all(tests);
         })
       .then(function() {
           return new Promise(function(resolve, reject) {
@@ -639,25 +641,16 @@
           assert_equals(
             frame.contentDocument.body.textContent, '');
 
-          return new Promise(function(resolve, reject) {
-              return frame.contentWindow.fetch(scope,
-                {'integrity': integrity_metadata})
-                .then(function(response) {
-                    return response.text();
-                })
-                .then(function(response_text) {
-                    // Should get the same integrity metadata.
-                    assert_equals(response_text, integrity_metadata,
-                                  'Service Worker should respond to fetch with the correct integrity');
-                })
-                .then(resolve())
-                .catch(reject());
-          });
+          return frame.contentWindow.fetch(scope, {'integrity': integrity_metadata});
         })
-      .then(function() {
+      .then(response => {
+          return response.text();
+        })
+      .then(response_text => {
+          assert_equals(response_text, integrity_metadata, 'integrity');
           frame.remove();
           return service_worker_unregister_and_done(t, scope);
-      })
+        })
       .catch(unreached_rejection(t));
   }, 'Service Worker responds to fetch event with the correct integrity_metadata');
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting-expected.txt
deleted file mode 100644
index fd7a2e2..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting-expected.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = error2
-PASS Aborting a WritableStream before it starts should cause the writer's unsettled ready promise to reject 
-PASS Aborting a WritableStream should cause the writer's fulfilled ready promise to reset to a rejected one 
-PASS abort() on a released writer rejects 
-PASS Aborting a WritableStream immediately prevents future writes 
-PASS Aborting a WritableStream prevents further writes after any that are in progress 
-PASS Fulfillment value of ws.abort() call must be undefined even if the underlying sink returns a non-undefined value 
-PASS WritableStream if sink's abort throws, the promise returned by writer.abort() rejects 
-PASS WritableStream if sink's abort throws, the promise returned by ws.abort() rejects 
-PASS WritableStream if sink's abort throws, for an abort performed during a write, the promise returned by ws.abort() rejects 
-PASS Aborting a WritableStream passes through the given reason 
-PASS Aborting a WritableStream puts it in an errored state, with a TypeError as the stored error 
-PASS Aborting a WritableStream causes any outstanding write() promises to be rejected with a TypeError 
-PASS Closing but then immediately aborting a WritableStream causes the stream to error 
-PASS Closing a WritableStream and aborting it while it closes causes the stream to ignore the abort attempt 
-PASS Aborting a WritableStream after it is closed is a no-op 
-PASS WritableStream should NOT call underlying sink's close if no abort is supplied (historical) 
-PASS returning a thenable from abort() should work 
-PASS .closed should not resolve before fulfilled write() 
-FAIL .closed should not resolve before rejected write(); write() error should not overwrite abort() error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writes should be satisfied in order when aborting 
-FAIL writes should be satisfied in order after rejected write when aborting promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL close() should reject with TypeError when abort() is first error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS underlying abort() should not be called until underlying write() completes 
-PASS underlying abort() should not be called if underlying close() has started 
-PASS if underlying close() has started and then rejects, the abort() and close() promises should reject with the underlying close rejection reason 
-PASS an abort() that happens during a write() should trigger the underlying abort() even with a close() queued 
-PASS if a writer is created for a stream with a pending abort, its ready should be rejected with a TypeError 
-PASS writer close() promise should resolve before abort() promise 
-PASS writer.ready should reject on controller error without waiting for underlying write 
-FAIL writer.abort() while there is an in-flight write, and then finish the write with rejection promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL writer.abort(), controller.error() while there is an in-flight write, and then finish the write assert_throws: writePromise3 must reject with an error indicating abort function "function () { throw e }" threw object "error2: error2" ("error2") expected object "TypeError" ("TypeError")
-FAIL writer.abort(), controller.error() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL controller.error(), writer.abort() while there is an in-flight write, and then finish the write assert_array_equals: writePromise and writer.closed must not be fulfilled/rejected yet even after writer.abort() lengths differ, expected 0 got 1
-FAIL controller.error(), writer.abort() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-PASS releaseLock() while aborting should reject the original closed promise 
-FAIL releaseLock() during delayed async abort() should reject the writer.closed promise assert_equals: closed promise should not have changed expected object "[object Promise]" but got object "[object Promise]"
-PASS sink abort() should not be called until sink start() is done 
-FAIL if start attempts to error the controller after abort() has been called, then it should lose promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL stream abort() promise should still resolve if sink start() rejects promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writer abort() during sink start() should replace the writer.ready promise synchronously 
-FAIL promises returned from other writer methods should be rejected when writer abort() happens during sink start() assert_array_equals: promises should resolve in the standard order property 1, expected "write1" but got "close"
-FAIL abort() should succeed despite rejection from write promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL abort() should be rejected with the rejection returned from close() assert_throws: abort() should reject with error2 function "function () { throw e }" threw object "error1: error1" ("error1") expected object "error2: error2" ("error2")
-FAIL a rejecting sink.write() should not prevent sink.abort() from being called promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when start errors after stream abort(), underlying sink abort() should be called anyway promise_test: Unhandled rejection with value: object "error1: error1"
-PASS when calling abort() twice on the same stream, the second call should reject 
-PASS sink abort() should not be called if stream was erroring due to controller.error() before abort() was called 
-PASS sink abort() should not be called if stream was erroring due to bad strategy before abort() was called 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.dedicatedworker-expected.txt
deleted file mode 100644
index fd7a2e2..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.dedicatedworker-expected.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = error2
-PASS Aborting a WritableStream before it starts should cause the writer's unsettled ready promise to reject 
-PASS Aborting a WritableStream should cause the writer's fulfilled ready promise to reset to a rejected one 
-PASS abort() on a released writer rejects 
-PASS Aborting a WritableStream immediately prevents future writes 
-PASS Aborting a WritableStream prevents further writes after any that are in progress 
-PASS Fulfillment value of ws.abort() call must be undefined even if the underlying sink returns a non-undefined value 
-PASS WritableStream if sink's abort throws, the promise returned by writer.abort() rejects 
-PASS WritableStream if sink's abort throws, the promise returned by ws.abort() rejects 
-PASS WritableStream if sink's abort throws, for an abort performed during a write, the promise returned by ws.abort() rejects 
-PASS Aborting a WritableStream passes through the given reason 
-PASS Aborting a WritableStream puts it in an errored state, with a TypeError as the stored error 
-PASS Aborting a WritableStream causes any outstanding write() promises to be rejected with a TypeError 
-PASS Closing but then immediately aborting a WritableStream causes the stream to error 
-PASS Closing a WritableStream and aborting it while it closes causes the stream to ignore the abort attempt 
-PASS Aborting a WritableStream after it is closed is a no-op 
-PASS WritableStream should NOT call underlying sink's close if no abort is supplied (historical) 
-PASS returning a thenable from abort() should work 
-PASS .closed should not resolve before fulfilled write() 
-FAIL .closed should not resolve before rejected write(); write() error should not overwrite abort() error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writes should be satisfied in order when aborting 
-FAIL writes should be satisfied in order after rejected write when aborting promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL close() should reject with TypeError when abort() is first error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS underlying abort() should not be called until underlying write() completes 
-PASS underlying abort() should not be called if underlying close() has started 
-PASS if underlying close() has started and then rejects, the abort() and close() promises should reject with the underlying close rejection reason 
-PASS an abort() that happens during a write() should trigger the underlying abort() even with a close() queued 
-PASS if a writer is created for a stream with a pending abort, its ready should be rejected with a TypeError 
-PASS writer close() promise should resolve before abort() promise 
-PASS writer.ready should reject on controller error without waiting for underlying write 
-FAIL writer.abort() while there is an in-flight write, and then finish the write with rejection promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL writer.abort(), controller.error() while there is an in-flight write, and then finish the write assert_throws: writePromise3 must reject with an error indicating abort function "function () { throw e }" threw object "error2: error2" ("error2") expected object "TypeError" ("TypeError")
-FAIL writer.abort(), controller.error() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL controller.error(), writer.abort() while there is an in-flight write, and then finish the write assert_array_equals: writePromise and writer.closed must not be fulfilled/rejected yet even after writer.abort() lengths differ, expected 0 got 1
-FAIL controller.error(), writer.abort() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-PASS releaseLock() while aborting should reject the original closed promise 
-FAIL releaseLock() during delayed async abort() should reject the writer.closed promise assert_equals: closed promise should not have changed expected object "[object Promise]" but got object "[object Promise]"
-PASS sink abort() should not be called until sink start() is done 
-FAIL if start attempts to error the controller after abort() has been called, then it should lose promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL stream abort() promise should still resolve if sink start() rejects promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writer abort() during sink start() should replace the writer.ready promise synchronously 
-FAIL promises returned from other writer methods should be rejected when writer abort() happens during sink start() assert_array_equals: promises should resolve in the standard order property 1, expected "write1" but got "close"
-FAIL abort() should succeed despite rejection from write promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL abort() should be rejected with the rejection returned from close() assert_throws: abort() should reject with error2 function "function () { throw e }" threw object "error1: error1" ("error1") expected object "error2: error2" ("error2")
-FAIL a rejecting sink.write() should not prevent sink.abort() from being called promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when start errors after stream abort(), underlying sink abort() should be called anyway promise_test: Unhandled rejection with value: object "error1: error1"
-PASS when calling abort() twice on the same stream, the second call should reject 
-PASS sink abort() should not be called if stream was erroring due to controller.error() before abort() was called 
-PASS sink abort() should not be called if stream was erroring due to bad strategy before abort() was called 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.https-expected.txt
deleted file mode 100644
index 4367f58c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.serviceworker.https-expected.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = error2
-PASS Service worker test setup 
-PASS Aborting a WritableStream before it starts should cause the writer's unsettled ready promise to reject 
-PASS Aborting a WritableStream should cause the writer's fulfilled ready promise to reset to a rejected one 
-PASS abort() on a released writer rejects 
-PASS Aborting a WritableStream immediately prevents future writes 
-PASS Aborting a WritableStream prevents further writes after any that are in progress 
-PASS Fulfillment value of ws.abort() call must be undefined even if the underlying sink returns a non-undefined value 
-PASS WritableStream if sink's abort throws, the promise returned by writer.abort() rejects 
-PASS WritableStream if sink's abort throws, the promise returned by ws.abort() rejects 
-PASS WritableStream if sink's abort throws, for an abort performed during a write, the promise returned by ws.abort() rejects 
-PASS Aborting a WritableStream passes through the given reason 
-PASS Aborting a WritableStream puts it in an errored state, with a TypeError as the stored error 
-PASS Aborting a WritableStream causes any outstanding write() promises to be rejected with a TypeError 
-PASS Closing but then immediately aborting a WritableStream causes the stream to error 
-PASS Closing a WritableStream and aborting it while it closes causes the stream to ignore the abort attempt 
-PASS Aborting a WritableStream after it is closed is a no-op 
-PASS WritableStream should NOT call underlying sink's close if no abort is supplied (historical) 
-PASS returning a thenable from abort() should work 
-PASS .closed should not resolve before fulfilled write() 
-FAIL .closed should not resolve before rejected write(); write() error should not overwrite abort() error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writes should be satisfied in order when aborting 
-FAIL writes should be satisfied in order after rejected write when aborting promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL close() should reject with TypeError when abort() is first error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS underlying abort() should not be called until underlying write() completes 
-PASS underlying abort() should not be called if underlying close() has started 
-PASS if underlying close() has started and then rejects, the abort() and close() promises should reject with the underlying close rejection reason 
-PASS an abort() that happens during a write() should trigger the underlying abort() even with a close() queued 
-PASS if a writer is created for a stream with a pending abort, its ready should be rejected with a TypeError 
-PASS writer close() promise should resolve before abort() promise 
-PASS writer.ready should reject on controller error without waiting for underlying write 
-FAIL writer.abort() while there is an in-flight write, and then finish the write with rejection promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL writer.abort(), controller.error() while there is an in-flight write, and then finish the write assert_throws: writePromise3 must reject with an error indicating abort function "function () { throw e }" threw object "error2: error2" ("error2") expected object "TypeError" ("TypeError")
-FAIL writer.abort(), controller.error() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL controller.error(), writer.abort() while there is an in-flight write, and then finish the write assert_array_equals: writePromise and writer.closed must not be fulfilled/rejected yet even after writer.abort() lengths differ, expected 0 got 1
-FAIL controller.error(), writer.abort() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-PASS releaseLock() while aborting should reject the original closed promise 
-FAIL releaseLock() during delayed async abort() should reject the writer.closed promise assert_equals: closed promise should not have changed expected object "[object Promise]" but got object "[object Promise]"
-PASS sink abort() should not be called until sink start() is done 
-FAIL if start attempts to error the controller after abort() has been called, then it should lose promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL stream abort() promise should still resolve if sink start() rejects promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writer abort() during sink start() should replace the writer.ready promise synchronously 
-FAIL promises returned from other writer methods should be rejected when writer abort() happens during sink start() assert_array_equals: promises should resolve in the standard order property 1, expected "write1" but got "close"
-FAIL abort() should succeed despite rejection from write promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL abort() should be rejected with the rejection returned from close() assert_throws: abort() should reject with error2 function "function () { throw e }" threw object "error1: error1" ("error1") expected object "error2: error2" ("error2")
-FAIL a rejecting sink.write() should not prevent sink.abort() from being called promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when start errors after stream abort(), underlying sink abort() should be called anyway promise_test: Unhandled rejection with value: object "error1: error1"
-PASS when calling abort() twice on the same stream, the second call should reject 
-PASS sink abort() should not be called if stream was erroring due to controller.error() before abort() was called 
-PASS sink abort() should not be called if stream was erroring due to bad strategy before abort() was called 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.sharedworker-expected.txt
deleted file mode 100644
index fd7a2e2..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/aborting.sharedworker-expected.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = error2
-PASS Aborting a WritableStream before it starts should cause the writer's unsettled ready promise to reject 
-PASS Aborting a WritableStream should cause the writer's fulfilled ready promise to reset to a rejected one 
-PASS abort() on a released writer rejects 
-PASS Aborting a WritableStream immediately prevents future writes 
-PASS Aborting a WritableStream prevents further writes after any that are in progress 
-PASS Fulfillment value of ws.abort() call must be undefined even if the underlying sink returns a non-undefined value 
-PASS WritableStream if sink's abort throws, the promise returned by writer.abort() rejects 
-PASS WritableStream if sink's abort throws, the promise returned by ws.abort() rejects 
-PASS WritableStream if sink's abort throws, for an abort performed during a write, the promise returned by ws.abort() rejects 
-PASS Aborting a WritableStream passes through the given reason 
-PASS Aborting a WritableStream puts it in an errored state, with a TypeError as the stored error 
-PASS Aborting a WritableStream causes any outstanding write() promises to be rejected with a TypeError 
-PASS Closing but then immediately aborting a WritableStream causes the stream to error 
-PASS Closing a WritableStream and aborting it while it closes causes the stream to ignore the abort attempt 
-PASS Aborting a WritableStream after it is closed is a no-op 
-PASS WritableStream should NOT call underlying sink's close if no abort is supplied (historical) 
-PASS returning a thenable from abort() should work 
-PASS .closed should not resolve before fulfilled write() 
-FAIL .closed should not resolve before rejected write(); write() error should not overwrite abort() error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writes should be satisfied in order when aborting 
-FAIL writes should be satisfied in order after rejected write when aborting promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL close() should reject with TypeError when abort() is first error promise_test: Unhandled rejection with value: object "error1: error1"
-PASS underlying abort() should not be called until underlying write() completes 
-PASS underlying abort() should not be called if underlying close() has started 
-PASS if underlying close() has started and then rejects, the abort() and close() promises should reject with the underlying close rejection reason 
-PASS an abort() that happens during a write() should trigger the underlying abort() even with a close() queued 
-PASS if a writer is created for a stream with a pending abort, its ready should be rejected with a TypeError 
-PASS writer close() promise should resolve before abort() promise 
-PASS writer.ready should reject on controller error without waiting for underlying write 
-FAIL writer.abort() while there is an in-flight write, and then finish the write with rejection promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL writer.abort(), controller.error() while there is an in-flight write, and then finish the write assert_throws: writePromise3 must reject with an error indicating abort function "function () { throw e }" threw object "error2: error2" ("error2") expected object "TypeError" ("TypeError")
-FAIL writer.abort(), controller.error() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-FAIL controller.error(), writer.abort() while there is an in-flight write, and then finish the write assert_array_equals: writePromise and writer.closed must not be fulfilled/rejected yet even after writer.abort() lengths differ, expected 0 got 1
-FAIL controller.error(), writer.abort() while there is an in-flight close, and then finish the close promise_test: Unhandled rejection with value: object "error2: error2"
-PASS releaseLock() while aborting should reject the original closed promise 
-FAIL releaseLock() during delayed async abort() should reject the writer.closed promise assert_equals: closed promise should not have changed expected object "[object Promise]" but got object "[object Promise]"
-PASS sink abort() should not be called until sink start() is done 
-FAIL if start attempts to error the controller after abort() has been called, then it should lose promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL stream abort() promise should still resolve if sink start() rejects promise_test: Unhandled rejection with value: object "error1: error1"
-PASS writer abort() during sink start() should replace the writer.ready promise synchronously 
-FAIL promises returned from other writer methods should be rejected when writer abort() happens during sink start() assert_array_equals: promises should resolve in the standard order property 1, expected "write1" but got "close"
-FAIL abort() should succeed despite rejection from write promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL abort() should be rejected with the rejection returned from close() assert_throws: abort() should reject with error2 function "function () { throw e }" threw object "error1: error1" ("error1") expected object "error2: error2" ("error2")
-FAIL a rejecting sink.write() should not prevent sink.abort() from being called promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when start errors after stream abort(), underlying sink abort() should be called anyway promise_test: Unhandled rejection with value: object "error1: error1"
-PASS when calling abort() twice on the same stream, the second call should reject 
-PASS sink abort() should not be called if stream was erroring due to controller.error() before abort() was called 
-PASS sink abort() should not be called if stream was erroring due to bad strategy before abort() was called 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close-expected.txt
deleted file mode 100644
index 400571f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-This is a testharness.js-based test.
-PASS fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined value 
-FAIL when sink calls error asynchronously while sink close is in-flight, the stream should not become errored promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when sink calls error synchronously while closing, the stream should not become errored promise_test: Unhandled rejection with value: object "Error: error me"
-PASS when the sink throws during close, and the close is requested while a write is still in-flight, the stream should become errored during the close 
-PASS releaseLock on a stream with a pending write in which the stream has been errored 
-PASS releaseLock on a stream with a pending close in which controller.error() was called 
-PASS when close is called on a WritableStream in writable state, ready should return a fulfilled promise 
-PASS when close is called on a WritableStream in waiting state, ready promise should be fulfilled 
-PASS when close is called on a WritableStream in waiting state, ready should be fulfilled immediately even if close takes a long time 
-PASS returning a thenable from close() should work 
-PASS releaseLock() should not change the result of sync close() 
-PASS releaseLock() should not change the result of async close() 
-PASS close() should set state to CLOSED even if writer has detached 
-PASS the promise returned by async abort during close should resolve 
-PASS promises must fulfill/reject in the expected order on closure 
-FAIL promises must fulfill/reject in the expected order on aborted closure assert_array_equals: promises must fulfill/reject in the expected order property 1, expected "abortPromise" but got "closed"
-FAIL promises must fulfill/reject in the expected order on aborted and errored closure assert_throws: writer.closed must reject with a TypeError indicating the stream was aborted function "function () { throw e }" threw object "error1: error1" ("error1") expected object "TypeError" ("TypeError")
-FAIL close() should not reject until no sink methods are in flight assert_false: expected false got true
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.dedicatedworker-expected.txt
deleted file mode 100644
index 400571f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.dedicatedworker-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-This is a testharness.js-based test.
-PASS fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined value 
-FAIL when sink calls error asynchronously while sink close is in-flight, the stream should not become errored promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when sink calls error synchronously while closing, the stream should not become errored promise_test: Unhandled rejection with value: object "Error: error me"
-PASS when the sink throws during close, and the close is requested while a write is still in-flight, the stream should become errored during the close 
-PASS releaseLock on a stream with a pending write in which the stream has been errored 
-PASS releaseLock on a stream with a pending close in which controller.error() was called 
-PASS when close is called on a WritableStream in writable state, ready should return a fulfilled promise 
-PASS when close is called on a WritableStream in waiting state, ready promise should be fulfilled 
-PASS when close is called on a WritableStream in waiting state, ready should be fulfilled immediately even if close takes a long time 
-PASS returning a thenable from close() should work 
-PASS releaseLock() should not change the result of sync close() 
-PASS releaseLock() should not change the result of async close() 
-PASS close() should set state to CLOSED even if writer has detached 
-PASS the promise returned by async abort during close should resolve 
-PASS promises must fulfill/reject in the expected order on closure 
-FAIL promises must fulfill/reject in the expected order on aborted closure assert_array_equals: promises must fulfill/reject in the expected order property 1, expected "abortPromise" but got "closed"
-FAIL promises must fulfill/reject in the expected order on aborted and errored closure assert_throws: writer.closed must reject with a TypeError indicating the stream was aborted function "function () { throw e }" threw object "error1: error1" ("error1") expected object "TypeError" ("TypeError")
-FAIL close() should not reject until no sink methods are in flight assert_false: expected false got true
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.https-expected.txt
deleted file mode 100644
index f99ba6e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.serviceworker.https-expected.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-This is a testharness.js-based test.
-PASS Service worker test setup 
-PASS fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined value 
-FAIL when sink calls error asynchronously while sink close is in-flight, the stream should not become errored promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when sink calls error synchronously while closing, the stream should not become errored promise_test: Unhandled rejection with value: object "Error: error me"
-PASS when the sink throws during close, and the close is requested while a write is still in-flight, the stream should become errored during the close 
-PASS releaseLock on a stream with a pending write in which the stream has been errored 
-PASS releaseLock on a stream with a pending close in which controller.error() was called 
-PASS when close is called on a WritableStream in writable state, ready should return a fulfilled promise 
-PASS when close is called on a WritableStream in waiting state, ready promise should be fulfilled 
-PASS when close is called on a WritableStream in waiting state, ready should be fulfilled immediately even if close takes a long time 
-PASS returning a thenable from close() should work 
-PASS releaseLock() should not change the result of sync close() 
-PASS releaseLock() should not change the result of async close() 
-PASS close() should set state to CLOSED even if writer has detached 
-PASS the promise returned by async abort during close should resolve 
-PASS promises must fulfill/reject in the expected order on closure 
-FAIL promises must fulfill/reject in the expected order on aborted closure assert_array_equals: promises must fulfill/reject in the expected order property 1, expected "abortPromise" but got "closed"
-FAIL promises must fulfill/reject in the expected order on aborted and errored closure assert_throws: writer.closed must reject with a TypeError indicating the stream was aborted function "function () { throw e }" threw object "error1: error1" ("error1") expected object "TypeError" ("TypeError")
-FAIL close() should not reject until no sink methods are in flight assert_false: expected false got true
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.sharedworker-expected.txt
deleted file mode 100644
index 400571f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/close.sharedworker-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-This is a testharness.js-based test.
-PASS fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined value 
-FAIL when sink calls error asynchronously while sink close is in-flight, the stream should not become errored promise_test: Unhandled rejection with value: object "error1: error1"
-FAIL when sink calls error synchronously while closing, the stream should not become errored promise_test: Unhandled rejection with value: object "Error: error me"
-PASS when the sink throws during close, and the close is requested while a write is still in-flight, the stream should become errored during the close 
-PASS releaseLock on a stream with a pending write in which the stream has been errored 
-PASS releaseLock on a stream with a pending close in which controller.error() was called 
-PASS when close is called on a WritableStream in writable state, ready should return a fulfilled promise 
-PASS when close is called on a WritableStream in waiting state, ready promise should be fulfilled 
-PASS when close is called on a WritableStream in waiting state, ready should be fulfilled immediately even if close takes a long time 
-PASS returning a thenable from close() should work 
-PASS releaseLock() should not change the result of sync close() 
-PASS releaseLock() should not change the result of async close() 
-PASS close() should set state to CLOSED even if writer has detached 
-PASS the promise returned by async abort during close should resolve 
-PASS promises must fulfill/reject in the expected order on closure 
-FAIL promises must fulfill/reject in the expected order on aborted closure assert_array_equals: promises must fulfill/reject in the expected order property 1, expected "abortPromise" but got "closed"
-FAIL promises must fulfill/reject in the expected order on aborted and errored closure assert_throws: writer.closed must reject with a TypeError indicating the stream was aborted function "function () { throw e }" threw object "error1: error1" ("error1") expected object "TypeError" ("TypeError")
-FAIL close() should not reject until no sink methods are in flight assert_false: expected false got true
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor-expected.txt
deleted file mode 100644
index 1998efd..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a testharness.js-based test.
-PASS controller argument should be passed to start method 
-PASS controller argument should be passed to write method 
-FAIL controller argument should not be passed to close method assert_array_equals: no arguments should be passed to close lengths differ, expected 0 got 1
-PASS highWaterMark should be reflected to desiredSize 
-PASS WritableStream should be writable and ready should fulfill immediately if the strategy does not apply backpressure 
-PASS WritableStream should be constructible with no arguments 
-PASS WritableStream instances should have standard methods and properties 
-PASS private constructors should not be exported 
-PASS WritableStreamDefaultController constructor should throw unless passed a WritableStream 
-PASS WritableStreamDefaultController constructor should throw when passed an initialised WritableStream 
-PASS WritableStreamDefaultWriter should throw unless passed a WritableStream 
-PASS WritableStreamDefaultWriter constructor should throw when stream argument is locked 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.dedicatedworker-expected.txt
deleted file mode 100644
index 1998efd..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.dedicatedworker-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a testharness.js-based test.
-PASS controller argument should be passed to start method 
-PASS controller argument should be passed to write method 
-FAIL controller argument should not be passed to close method assert_array_equals: no arguments should be passed to close lengths differ, expected 0 got 1
-PASS highWaterMark should be reflected to desiredSize 
-PASS WritableStream should be writable and ready should fulfill immediately if the strategy does not apply backpressure 
-PASS WritableStream should be constructible with no arguments 
-PASS WritableStream instances should have standard methods and properties 
-PASS private constructors should not be exported 
-PASS WritableStreamDefaultController constructor should throw unless passed a WritableStream 
-PASS WritableStreamDefaultController constructor should throw when passed an initialised WritableStream 
-PASS WritableStreamDefaultWriter should throw unless passed a WritableStream 
-PASS WritableStreamDefaultWriter constructor should throw when stream argument is locked 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.https-expected.txt
deleted file mode 100644
index d064d68..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.serviceworker.https-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-This is a testharness.js-based test.
-PASS Service worker test setup 
-PASS controller argument should be passed to start method 
-PASS controller argument should be passed to write method 
-FAIL controller argument should not be passed to close method assert_array_equals: no arguments should be passed to close lengths differ, expected 0 got 1
-PASS highWaterMark should be reflected to desiredSize 
-PASS WritableStream should be writable and ready should fulfill immediately if the strategy does not apply backpressure 
-PASS WritableStream should be constructible with no arguments 
-PASS WritableStream instances should have standard methods and properties 
-PASS private constructors should not be exported 
-PASS WritableStreamDefaultController constructor should throw unless passed a WritableStream 
-PASS WritableStreamDefaultController constructor should throw when passed an initialised WritableStream 
-PASS WritableStreamDefaultWriter should throw unless passed a WritableStream 
-PASS WritableStreamDefaultWriter constructor should throw when stream argument is locked 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.sharedworker-expected.txt
deleted file mode 100644
index 1998efd..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/constructor.sharedworker-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a testharness.js-based test.
-PASS controller argument should be passed to start method 
-PASS controller argument should be passed to write method 
-FAIL controller argument should not be passed to close method assert_array_equals: no arguments should be passed to close lengths differ, expected 0 got 1
-PASS highWaterMark should be reflected to desiredSize 
-PASS WritableStream should be writable and ready should fulfill immediately if the strategy does not apply backpressure 
-PASS WritableStream should be constructible with no arguments 
-PASS WritableStream instances should have standard methods and properties 
-PASS private constructors should not be exported 
-PASS WritableStreamDefaultController constructor should throw unless passed a WritableStream 
-PASS WritableStreamDefaultController constructor should throw when passed an initialised WritableStream 
-PASS WritableStreamDefaultWriter should throw unless passed a WritableStream 
-PASS WritableStreamDefaultWriter constructor should throw when stream argument is locked 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error-expected.txt
deleted file mode 100644
index e3bb1267..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS controller.error() should error the stream 
-PASS controller.error() on erroring stream should not throw 
-FAIL surplus calls to controller.error() should be a no-op Cannot error a errored writable stream
-FAIL controller.error() on errored stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a errored writable stream"
-FAIL controller.error() on closed stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a closed writable stream"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.dedicatedworker-expected.txt
deleted file mode 100644
index e3bb1267..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.dedicatedworker-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS controller.error() should error the stream 
-PASS controller.error() on erroring stream should not throw 
-FAIL surplus calls to controller.error() should be a no-op Cannot error a errored writable stream
-FAIL controller.error() on errored stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a errored writable stream"
-FAIL controller.error() on closed stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a closed writable stream"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.serviceworker.https-expected.txt
deleted file mode 100644
index 57815f8..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.serviceworker.https-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = error1
-PASS Service worker test setup 
-PASS controller.error() should error the stream 
-PASS controller.error() on erroring stream should not throw 
-FAIL surplus calls to controller.error() should be a no-op Cannot error a errored writable stream
-FAIL controller.error() on errored stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a errored writable stream"
-FAIL controller.error() on closed stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a closed writable stream"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.sharedworker-expected.txt
deleted file mode 100644
index e3bb1267..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/error.sharedworker-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS controller.error() should error the stream 
-PASS controller.error() on erroring stream should not throw 
-FAIL surplus calls to controller.error() should be a no-op Cannot error a errored writable stream
-FAIL controller.error() on errored stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a errored writable stream"
-FAIL controller.error() on closed stream should not throw promise_test: Unhandled rejection with value: object "TypeError: Cannot error a closed writable stream"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties-expected.txt
deleted file mode 100644
index 6fe9cca..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties-expected.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-This is a testharness.js-based test.
-PASS WritableStreamDefaultController should not be exported on the global object 
-PASS WritableStreamDefaultWriter should not be exported on the global object 
-PASS WritableStream.prototype.constructor should have standard properties 
-PASS WritableStream.prototype.constructor should be a constructor 
-PASS WritableStream.prototype.locked should have standard properties 
-PASS WritableStream.prototype.locked should be a getter 
-PASS WritableStream.prototype.abort should have standard properties 
-PASS WritableStream.prototype.abort should be a method 
-PASS WritableStream.prototype.getWriter should have standard properties 
-PASS WritableStream.prototype.getWriter should be a method 
-PASS WritableStream.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultController.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultController.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultController.prototype.error should have standard properties 
-PASS WritableStreamDefaultController.prototype.error should be a method 
-PASS WritableStreamDefaultController.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultWriter.prototype.closed should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.closed should be a getter 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should be a getter 
-PASS WritableStreamDefaultWriter.prototype.ready should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.ready should be a getter 
-PASS WritableStreamDefaultWriter.prototype.abort should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.abort should be a method 
-PASS WritableStreamDefaultWriter.prototype.close should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.close should be a method 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should be a method 
-PASS WritableStreamDefaultWriter.prototype.write should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.write should be a method 
-PASS WritableStreamDefaultWriter.prototype should have exactly the expected properties 
-PASS sink method start should be called with the right number of arguments 
-PASS sink method start should be called even when it's located on the prototype chain 
-PASS sink method write should be called with the right number of arguments 
-PASS sink method write should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method write 
-FAIL sink method close should be called with the right number of arguments assert_equals: close should be called with 0 arguments expected 0 but got 1
-PASS sink method close should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method close 
-PASS sink method abort should be called with the right number of arguments 
-PASS sink method abort should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method abort 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.dedicatedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.dedicatedworker-expected.txt
deleted file mode 100644
index 6fe9cca..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.dedicatedworker-expected.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-This is a testharness.js-based test.
-PASS WritableStreamDefaultController should not be exported on the global object 
-PASS WritableStreamDefaultWriter should not be exported on the global object 
-PASS WritableStream.prototype.constructor should have standard properties 
-PASS WritableStream.prototype.constructor should be a constructor 
-PASS WritableStream.prototype.locked should have standard properties 
-PASS WritableStream.prototype.locked should be a getter 
-PASS WritableStream.prototype.abort should have standard properties 
-PASS WritableStream.prototype.abort should be a method 
-PASS WritableStream.prototype.getWriter should have standard properties 
-PASS WritableStream.prototype.getWriter should be a method 
-PASS WritableStream.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultController.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultController.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultController.prototype.error should have standard properties 
-PASS WritableStreamDefaultController.prototype.error should be a method 
-PASS WritableStreamDefaultController.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultWriter.prototype.closed should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.closed should be a getter 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should be a getter 
-PASS WritableStreamDefaultWriter.prototype.ready should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.ready should be a getter 
-PASS WritableStreamDefaultWriter.prototype.abort should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.abort should be a method 
-PASS WritableStreamDefaultWriter.prototype.close should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.close should be a method 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should be a method 
-PASS WritableStreamDefaultWriter.prototype.write should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.write should be a method 
-PASS WritableStreamDefaultWriter.prototype should have exactly the expected properties 
-PASS sink method start should be called with the right number of arguments 
-PASS sink method start should be called even when it's located on the prototype chain 
-PASS sink method write should be called with the right number of arguments 
-PASS sink method write should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method write 
-FAIL sink method close should be called with the right number of arguments assert_equals: close should be called with 0 arguments expected 0 but got 1
-PASS sink method close should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method close 
-PASS sink method abort should be called with the right number of arguments 
-PASS sink method abort should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method abort 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.serviceworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.serviceworker.https-expected.txt
deleted file mode 100644
index ad8c37c802..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.serviceworker.https-expected.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-This is a testharness.js-based test.
-PASS Service worker test setup 
-PASS WritableStreamDefaultController should not be exported on the global object 
-PASS WritableStreamDefaultWriter should not be exported on the global object 
-PASS WritableStream.prototype.constructor should have standard properties 
-PASS WritableStream.prototype.constructor should be a constructor 
-PASS WritableStream.prototype.locked should have standard properties 
-PASS WritableStream.prototype.locked should be a getter 
-PASS WritableStream.prototype.abort should have standard properties 
-PASS WritableStream.prototype.abort should be a method 
-PASS WritableStream.prototype.getWriter should have standard properties 
-PASS WritableStream.prototype.getWriter should be a method 
-PASS WritableStream.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultController.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultController.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultController.prototype.error should have standard properties 
-PASS WritableStreamDefaultController.prototype.error should be a method 
-PASS WritableStreamDefaultController.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultWriter.prototype.closed should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.closed should be a getter 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should be a getter 
-PASS WritableStreamDefaultWriter.prototype.ready should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.ready should be a getter 
-PASS WritableStreamDefaultWriter.prototype.abort should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.abort should be a method 
-PASS WritableStreamDefaultWriter.prototype.close should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.close should be a method 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should be a method 
-PASS WritableStreamDefaultWriter.prototype.write should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.write should be a method 
-PASS WritableStreamDefaultWriter.prototype should have exactly the expected properties 
-PASS sink method start should be called with the right number of arguments 
-PASS sink method start should be called even when it's located on the prototype chain 
-PASS sink method write should be called with the right number of arguments 
-PASS sink method write should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method write 
-FAIL sink method close should be called with the right number of arguments assert_equals: close should be called with 0 arguments expected 0 but got 1
-PASS sink method close should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method close 
-PASS sink method abort should be called with the right number of arguments 
-PASS sink method abort should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method abort 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.sharedworker-expected.txt
deleted file mode 100644
index 6fe9cca..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/streams/writable-streams/properties.sharedworker-expected.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-This is a testharness.js-based test.
-PASS WritableStreamDefaultController should not be exported on the global object 
-PASS WritableStreamDefaultWriter should not be exported on the global object 
-PASS WritableStream.prototype.constructor should have standard properties 
-PASS WritableStream.prototype.constructor should be a constructor 
-PASS WritableStream.prototype.locked should have standard properties 
-PASS WritableStream.prototype.locked should be a getter 
-PASS WritableStream.prototype.abort should have standard properties 
-PASS WritableStream.prototype.abort should be a method 
-PASS WritableStream.prototype.getWriter should have standard properties 
-PASS WritableStream.prototype.getWriter should be a method 
-PASS WritableStream.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultController.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultController.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultController.prototype.error should have standard properties 
-PASS WritableStreamDefaultController.prototype.error should be a method 
-PASS WritableStreamDefaultController.prototype should have exactly the expected properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.constructor should be a constructor 
-PASS WritableStreamDefaultWriter.prototype.closed should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.closed should be a getter 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.desiredSize should be a getter 
-PASS WritableStreamDefaultWriter.prototype.ready should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.ready should be a getter 
-PASS WritableStreamDefaultWriter.prototype.abort should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.abort should be a method 
-PASS WritableStreamDefaultWriter.prototype.close should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.close should be a method 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.releaseLock should be a method 
-PASS WritableStreamDefaultWriter.prototype.write should have standard properties 
-PASS WritableStreamDefaultWriter.prototype.write should be a method 
-PASS WritableStreamDefaultWriter.prototype should have exactly the expected properties 
-PASS sink method start should be called with the right number of arguments 
-PASS sink method start should be called even when it's located on the prototype chain 
-PASS sink method write should be called with the right number of arguments 
-PASS sink method write should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method write 
-FAIL sink method close should be called with the right number of arguments assert_equals: close should be called with 0 arguments expected 0 but got 1
-PASS sink method close should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method close 
-PASS sink method abort should be called with the right number of arguments 
-PASS sink method abort should be called even when it's located on the prototype chain 
-PASS unexpected properties should not be accessed when calling sink method abort 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic-expected.html b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic-expected.html
new file mode 100644
index 0000000..6f12503
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic-expected.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<style>
+#target {
+  text-decoration: underline;
+  text-underline-position: under;
+}
+</style>
+<p id=target>This text should have under-positioned underline.</p>
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic.html b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic.html
new file mode 100644
index 0000000..246db46
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<style>
+#target {
+  text-decoration: underline;
+}
+</style>
+<p id=target>This text should have under-positioned underline.</p>
+<script>
+if (window.testRunner)
+  testRunner.waitUntilDone();
+window.onload = function () {
+  document.body.offsetTop; /* force layout */
+  /* Theoretically setting style can reproduce the issue, but neither setting
+     immediately nor requestAnimationFrame() work, so use setTimeout(). */
+  setTimeout(function () {
+    target.style.textUnderlinePosition = 'under';
+    if (window.testRunner)
+      testRunner.notifyDone();
+  }, 10);
+};
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell-collapsed-border.html
index fbe7a8cc..64900e5 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell-collapsed-border.html
@@ -5,6 +5,7 @@
 <link rel="prev" href="backgr_border-table-column.html" title="Background with Borders: Background on 'table-column'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {border: 5px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell.html
index 0ee2e37..63d6419 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-cell.html
@@ -5,6 +5,7 @@
 <link rel="prev" href="backgr_border-table-column.html" title="Background with Borders: Background on 'table-column'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {border: 5px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-collapsed-border.html
index c97ed35..52cc1b5 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-collapsed-border.html
@@ -5,6 +5,7 @@
 <link rel="prev" href="backgr_layers-opacity.html" title="Background with Borders: Background on 'table-cell'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(resources/edge.gif) top left no-repeat; border: 5px dotted;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-collapsed-border.html
index 64d24b9..1e66a2ae 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table-row.html" title="Background with Borders: Background on 'table-row'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table  {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group-collapsed-border.html
index c475b0f5..0c236e95 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table-row-group.html" title="Background with Borders: Background on 'table-row-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table       {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group.html
index 197218f99..008221f 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column-group.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table-row-group.html" title="Background with Borders: Background on 'table-row-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table       {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column.html
index 6f5456d..65756145 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-column.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table-row.html" title="Background with Borders: Background on 'table-row'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table  {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html
index 2ea144c0..942e083 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks-collapsed-border.html
@@ -5,6 +5,7 @@
 <link rel="prev" href="layers-opacity.html" title="Background with Borders: Background on 'table-cell'">
 <link rel="contents" href="./" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(edge.gif) top left no-repeat; border: 5px dotted;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html
index 5f9b360..595c55d 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-quirks.html
@@ -5,6 +5,7 @@
 <link rel="prev" href="layers-opacity.html" title="Background with Borders: Background on 'table-cell'">
 <link rel="contents" href="./" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(edge.gif) top left no-repeat; border: 5px dotted;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-collapsed-border.html
index a6c39978..c307b316 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table-column-group.html" title="Background with Borders: Background on 'table-column-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table     {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group-collapsed-border.html
index 5ec3c8b..5a59da7 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table.html" title="Background with Borders: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group.html
index f779070d..adf875d1 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row-group.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table.html" title="Background with Borders: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row.html
index c75e9c6..c37a0f9d 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table-row.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_border-table-column-group.html" title="Background with Borders: Background on 'table-column-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table     {                                                        border: 3px dotted}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table.html b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table.html
index e2610baf..8d0bc94 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_border-table.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_border-table.html
@@ -5,6 +5,7 @@
 <link rel="prev" href="backgr_layers-opacity.html" title="Background with Borders: Background on 'table-cell'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(resources/edge.gif) top left no-repeat; border: 5px dotted;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_image-crash.html b/third_party/WebKit/LayoutTests/fast/table/backgr_image-crash.html
index 3ac79a57..b346905 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_image-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_image-crash.html
@@ -3,6 +3,7 @@
 <table id="table">
   <colgroup style="background: url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)">
 </table>
+<script src="resources/wait-for-onload.js"></script>
 <script>
   if (window.testRunner)
     testRunner.dumpAsText();
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide-collapsed-border.html
index 45f7acb4..e59c17f6 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_layers-show.html" title="Background Layers: empty-cell: show">
 <link rel="contents" href="./backgr_indxe.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
   table        {background: blue; empty-cells: hide}
   tbody, thead {background: url(resources/edge.gif) right top  no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide.html b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide.html
index 26392dcd..8ab8df7 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-hide.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_layers-show.html" title="Background Layers: empty-cell: show">
 <link rel="contents" href="./backgr_indxe.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
   table        {background: blue; empty-cells: hide}
   tbody, thead {background: url(resources/edge.gif) right top  no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show-collapsed-border.html
index 388a598..f70e857 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-cell.html" title="Background Position: Background on 'table-cell'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
   table        {background: blue; empty-cells: show}
   tbody, thead {background: url(../images/edge.gif) right top  no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show.html b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show.html
index 2d1abd88..db9a015 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_layers-show.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-cell.html" title="Background Position: Background on 'table-cell'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
   table        {background: blue; empty-cells: show}
   tbody, thead {background: url(../images/edge.gif) right top  no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell-collapsed-border.html
index f08cd8a..a68c6a8 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-column.html" title="Background Position: Background on 'table-column'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .e {background: black url(resources/edge.gif) top left no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell.html
index 17c9292..6321524 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-cell.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-column.html" title="Background Position: Background on 'table-column'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .e {background: black url(resources/edge.gif) top left no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-collapsed-border.html
index 0b0f9273..1620090 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-cell.html" title="Background Position: Background on 'table-cell'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(resources/edge.gif) top right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-collapsed-border.html
index 3d79787..8cd8870 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-row.html" title="Background Position: Background on 'table-row'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .col-1 {background: black url(resources/edge.gif) bottom right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group-collapsed-border.html
index 453e34b1..ec4d490d 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-row-group.html" title="Background Position: Background on 'table-row-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .colgroup-A {background: black url(resources/edge.gif) bottom right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group.html
index f4b614fd1..4a52735 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column-group.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-row-group.html" title="Background Position: Background on 'table-row-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .colgroup-A {background: black url(resources/edge.gif) bottom right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column.html
index ca61357..ee474f7 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-column.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-row.html" title="Background Position: Background on 'table-row'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .col-1 {background: black url(resources/edge.gif) bottom right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-collapsed-border.html
index a4a3dea..251c89ac 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-column-group.html" title="Background Position: Background on 'table-column-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .th-row-1 {background: black url(resources/edge.gif) bottom right no-repeat;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group-collapsed-border.html
index 08c0b318..218c71c0 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table.html" title="Background Position: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   thead {background: black url(resources/edge.gif) top    right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group.html
index 990b15e9..0ffcd4d 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row-group.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table.html" title="Background Position: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   thead {background: black url(resources/edge.gif) top    right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row.html
index 62d9cc6..3b2625f 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table-row.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-column-group.html" title="Background Position: Background on 'table-column-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   .th-row-1 {background: black url(resources/edge.gif) bottom right no-repeat;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table.html b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table.html
index 7156564..c20dfbfb 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_position-table.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_position-table.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_position-table-cell.html" title="Background Position: Background on 'table-cell'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(resources/edge.gif) top right no-repeat}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell-collapsed-border.html
index 71151bf4..478dde7 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="next" href="backgr_position-table.html" title="Background Position: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   td,th {background: black url(resources/rainbowv.gif) top right}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell.html
index 6740910..d712ee9 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-cell.html
@@ -6,6 +6,7 @@
 <link rel="next" href="backgr_position-table.html" title="Background Position: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   td,th {background: black url(resources/rainbowv.gif) top right}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-collapsed-border.html
index b743e50..5103e1a0 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-collapsed-border.html
@@ -5,6 +5,7 @@
 <link rel="next" href="backgr_simple-table-row-group.html" title="Background Area: Background on 'table-row-group'">
 <link rel="prev contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(resources/rainbowh.gif) top right}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-collapsed-border.html
index d9fd912..4585c55 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table-row.html" title="Background Area: Background on 'table-row'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   col {background: black url(resources/rainbowv.gif) top right}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group-collapsed-border.html
index 5ac4187..cb5700f5 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table-row-group.html" title="Background Area: Background on 'table-row-group'">
 <link rel="contents" href="./backgr_index,.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   colgroup {background: black url(resources/rainbowv.gif) top left}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group.html
index 73634d9..646d956 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column-group.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table-row-group.html" title="Background Area: Background on 'table-row-group'">
 <link rel="contents" href="./backgr_index,.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   colgroup {background: black url(resources/rainbowv.gif) top left}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column.html
index d1979d3..7ced06d 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-column.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table-row.html" title="Background Area: Background on 'table-row'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   col {background: black url(resources/rainbowv.gif) top right}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-collapsed-border.html
index 2d90cf8..c5fe415 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table-column-group.html" title="Background Area: Background on 'table-column-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   tr {background: black url(resources/rainbowh.gif) bottom left;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group-collapsed-border.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group-collapsed-border.html
index 873e4a1..2ff4ee9 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group-collapsed-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group-collapsed-border.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table.html" title="Background Area: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   tbody {background: black url(resources/rainbowh.gif) bottom left}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group.html
index 6f9fd4c..88e901a 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row-group.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table.html" title="Background Area: Background on 'table'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   tbody {background: black url(resources/rainbowh.gif) bottom left}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row.html
index 4750803..571b5030 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table-row.html
@@ -6,6 +6,7 @@
 <link rel="prev" href="backgr_simple-table-column-group.html" title="Background Area: Background on 'table-column-group'">
 <link rel="contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   tr {background: black url(resources/rainbowh.gif) bottom left;}
diff --git a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table.html b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table.html
index 0ecfbfe..0bf8609 100644
--- a/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table.html
+++ b/third_party/WebKit/LayoutTests/fast/table/backgr_simple-table.html
@@ -5,6 +5,7 @@
 <link rel="next" href="backgr_simple-table-row-group.html" title="Background Area: Background on 'table-row-group'">
 <link rel="prev contents" href="./backgr_index.html" title="Table of Contents">
 <link rel="stylesheet" type="text/css" href="resources/common.css">
+<script src="resources/wait-for-onload.js"></script>
 <style type="text/css">
 
   table {background: black url(resources/rainbowh.gif) top right}
diff --git a/third_party/WebKit/LayoutTests/fast/table/resources/wait-for-onload.js b/third_party/WebKit/LayoutTests/fast/table/resources/wait-for-onload.js
new file mode 100644
index 0000000..4afdabc1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/resources/wait-for-onload.js
@@ -0,0 +1,15 @@
+if (window.testRunner) {
+  // This is a workaroud for an issue that the test runner sends notifyDone
+  // before resources specified in CSS url finish loading. Currently all
+  // such resources are specified in inline CSSs so we can rely on the
+  // Document load event (Note that we cannot rely on that with linked
+  // CSSs).
+  testRunner.waitUntilDone();
+  window.addEventListener('load', () => {
+    // Force layout.
+    document.body.offsetTop;
+
+    testRunner.notifyDone();
+  });
+}
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/resources/thorough-util.js b/third_party/WebKit/LayoutTests/http/tests/fetch/resources/thorough-util.js
index 6fb0899..053c7c2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/resources/thorough-util.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/resources/thorough-util.js
@@ -166,7 +166,7 @@
   checkJsonpHeader.bind(this, 'X-ServiceWorker-Test', 'test');
 var hasCustomHeader2 = function(url, data) {
   checkJsonpHeader('X-ServiceWorker-s', 'test1', url, data);
-  checkJsonpHeader('X-ServiceWorker-Test', 'test2,test3', url, data);
+  checkJsonpHeader('X-ServiceWorker-Test', 'test2, test3', url, data);
   checkJsonpHeader('X-ServiceWorker-ua', 'test4', url, data);
   checkJsonpHeader('X-ServiceWorker-U', 'test5', url, data);
   checkJsonpHeader('X-ServiceWorker-V', 'test6', url, data);
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/headers.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/headers.js
index 7c36bb3..babfaf7c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/headers.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/headers.js
@@ -136,7 +136,7 @@
     headers.append('X-FETCH-TEST-2', 'response test field - append');
     assert_equals(size(headers), 5, 'headers size should increase by 1.');
     assert_equals(headers.get('X-FETCH-Test'),
-                  'response test field - updated,response test field - append',
+                  'response test field - updated, response test field - append',
                   'the value of the first header added should be returned.');
     allValues = headers.getAll('X-FETch-TEST');
     assert_equals(allValues.length, 2);
@@ -156,7 +156,7 @@
     headers = new Headers([['a', 'b'], ['c', 'd'], ['c', 'e']]);
     assert_equals(size(headers), 2, 'headers size should match');
     assert_equals(headers.get('a'), 'b');
-    assert_equals(headers.get('c'), 'd,e');
+    assert_equals(headers.get('c'), 'd, e');
     assert_equals(headers.getAll('c')[0], 'd');
     assert_equals(headers.getAll('c')[1], 'e');
 
@@ -164,7 +164,7 @@
     var headers2 = new Headers(headers);
     assert_equals(size(headers2), 2, 'headers size should match');
     assert_equals(headers2.get('a'), 'b');
-    assert_equals(headers2.get('c'), 'd,e');
+    assert_equals(headers2.get('c'), 'd, e');
     assert_equals(headers2.getAll('c')[0], 'd');
     assert_equals(headers2.getAll('c')[1], 'e');
     headers.set('a', 'x');
@@ -175,14 +175,14 @@
     headers3.append('test', 'a');
     headers3.append('test', '');
     headers3.append('test', 'b');
-    assert_equals(headers3.get('test'), 'a,,b');
+    assert_equals(headers3.get('test'), 'a, , b');
     headers3.set('test', '');
     assert_equals(headers3.get('test'), '');
 
     var headers4 = new Headers();
     headers4.append('foo', '');
     headers4.append('foo', 'a');
-    assert_equals(headers4.get('foo'), ',a');
+    assert_equals(headers4.get('foo'), ', a');
     // new Headers with Dictionary
     headers = new Headers({'a': 'b', 'c': 'd'});
     assert_equals(size(headers), 2, 'headers size should match');
@@ -269,7 +269,7 @@
     assert_array_equals(keys, ['a', 'b', 'c'],
                         'The pairs to iterate over should be the return ' +
                         'value of an algorithm that implicitly makes a copy.');
-    assert_array_equals(values, ['1,2,3', '2', '3'],
+    assert_array_equals(values, ['1, 2, 3', '2', '3'],
                         "The values should be combined and separated by ','.");
 }, 'Iteration mutation');
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https-expected.txt b/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https-expected.txt
deleted file mode 100644
index abdd077..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = 5 duplicate test names: "Piping from an errored readable stream to an errored writable stream", "Piping from an errored readable stream to an errored writable stream; preventAbort = true", "Piping from an errored readable stream to a closed writable stream", "Piping from a closed readable stream to an errored writable stream", "Piping from a closed readable stream to a closed writable stream"
-PASS Piping from an errored readable stream to an errored writable stream 
-PASS Piping from an errored readable stream to an errored writable stream; preventAbort = true 
-PASS Piping from an errored readable stream to a closed writable stream 
-PASS Piping from a closed readable stream to an errored writable stream 
-PASS Piping from a closed readable stream to a closed writable stream 
-PASS Untitled 
-PASS Piping from an errored readable stream to an errored writable stream 
-PASS Piping from an errored readable stream to an errored writable stream; preventAbort = true 
-PASS Piping from an errored readable stream to a closed writable stream 
-PASS Piping from a closed readable stream to an errored writable stream 
-PASS Piping from a closed readable stream to a closed writable stream 
-PASS Piping from an errored readable stream to an errored writable stream 
-PASS Piping from an errored readable stream to an errored writable stream; preventAbort = true 
-PASS Piping from an errored readable stream to a closed writable stream 
-PASS Piping from a closed readable stream to an errored writable stream 
-PASS Piping from a closed readable stream to a closed writable stream 
-PASS Piping from an errored readable stream to an errored writable stream 
-PASS Piping from an errored readable stream to an errored writable stream; preventAbort = true 
-PASS Piping from an errored readable stream to a closed writable stream 
-PASS Piping from a closed readable stream to an errored writable stream 
-PASS Piping from a closed readable stream to a closed writable stream 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https.html b/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https.html
deleted file mode 100644
index c7951db8..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.https.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/serviceworker/resources/test-helpers.js"></script>
-<script src="../resources/test-initializer.js"></script>
-<script src="../resources/test-utils.js"></script>
-<script src="../resources/recording-streams.js"></script>
-
-<script src="multiple-propagation.js"></script>
-<script>
-'use strict';
-worker_test('multiple-propagation.js');
-</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.js b/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.js
deleted file mode 100644
index 2c7fd141..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/streams/piping/multiple-propagation.js
+++ /dev/null
@@ -1,139 +0,0 @@
-'use strict';
-
-if (self.importScripts) {
-  self.importScripts('/resources/testharness.js');
-  self.importScripts('../resources/test-utils.js');
-  self.importScripts('../resources/recording-streams.js');
-}
-
-const error1 = new Error('error1!');
-error1.name = 'error1';
-
-const error2 = new Error('error2!');
-error2.name = 'error2';
-
-promise_test(t => {
-  const rs = recordingReadableStream({
-    start(c) {
-      c.error(error1);
-    }
-  });
-  const ws = recordingWritableStream({
-    start(c) {
-      c.error(error2);
-    }
-  });
-
-  // Trying to abort a stream that was errored will give that error back
-  return promise_rejects(t, error2, rs.pipeTo(ws), 'pipeTo must reject with the writable stream\'s error').then(() => {
-    assert_array_equals(rs.events, []);
-    assert_array_equals(ws.events, []);
-
-    return Promise.all([
-      promise_rejects(t, error1, rs.getReader().closed, 'the readable stream must be errored with error1'),
-      promise_rejects(t, error2, ws.getWriter().closed, 'the writable stream must be errored with error2')
-    ]);
-  });
-
-}, 'Piping from an errored readable stream to an errored writable stream');
-
-promise_test(t => {
-  const rs = recordingReadableStream({
-    start(c) {
-      c.error(error1);
-    }
-  });
-  const ws = recordingWritableStream({
-    start(c) {
-      c.error(error2);
-    }
-  });
-
-  return promise_rejects(t, error1, rs.pipeTo(ws, { preventAbort: true }),
-    'pipeTo must reject with the readable stream\'s error')
-  .then(() => {
-    assert_array_equals(rs.events, []);
-    assert_array_equals(ws.events, []);
-
-    return Promise.all([
-      promise_rejects(t, error1, rs.getReader().closed, 'the readable stream must be errored with error1'),
-      promise_rejects(t, error2, ws.getWriter().closed, 'the writable stream must be errored with error2')
-    ]);
-  });
-
-}, 'Piping from an errored readable stream to an errored writable stream; preventAbort = true');
-
-// TODO(ricea): Revert to the upstream version of this test once https://github.com/whatwg/streams/pull/634 is
-// resolved and WritableStream.js has been updated to match.
-promise_test(t => {
-  const rs = recordingReadableStream({
-    start(c) {
-      c.error(error1);
-    }
-  });
-  const ws = recordingWritableStream();
-  const writer = ws.getWriter();
-  const closePromise = writer.close();
-  writer.releaseLock();
-
-  return promise_rejects(t, error1, rs.pipeTo(ws), 'pipeTo must reject with the readable stream\'s error').then(() => {
-    assert_array_equals(rs.events, []);
-    assert_array_equals(ws.events, ['abort', error1], 'ws.events should contain abort for the time being');
-
-    return Promise.all([
-      promise_rejects(t, error1, rs.getReader().closed, 'the readable stream must be errored with error1'),
-      promise_rejects(t, new TypeError(), ws.getWriter().closed, 'the writable stream should be errored for the time being'),
-      promise_rejects(t, new TypeError(), closePromise, 'close() should reject for the time being')
-    ]);
-  });
-
-}, 'Piping from an errored readable stream to a closed writable stream');
-
-promise_test(t => {
-  const rs = recordingReadableStream({
-    start(c) {
-      c.close();
-    }
-  });
-  const ws = recordingWritableStream({
-    start(c) {
-      c.error(error1);
-    }
-  });
-
-  return promise_rejects(t, error1, rs.pipeTo(ws), 'pipeTo must reject with the writable stream\'s error').then(() => {
-    assert_array_equals(rs.events, []);
-    assert_array_equals(ws.events, []);
-
-    return Promise.all([
-      rs.getReader().closed,
-      promise_rejects(t, error1, ws.getWriter().closed, 'the writable stream must be errored with error1')
-    ]);
-  });
-
-}, 'Piping from a closed readable stream to an errored writable stream');
-
-promise_test(() => {
-  const rs = recordingReadableStream({
-    start(c) {
-      c.close();
-    }
-  });
-  const ws = recordingWritableStream();
-  const writer = ws.getWriter();
-  writer.close();
-  writer.releaseLock();
-
-  return rs.pipeTo(ws).then(() => {
-    assert_array_equals(rs.events, []);
-    assert_array_equals(ws.events, ['close']);
-
-    return Promise.all([
-      rs.getReader().closed,
-      ws.getWriter().closed
-    ]);
-  });
-
-}, 'Piping from a closed readable stream to a closed writable stream');
-
-done();
diff --git a/third_party/WebKit/LayoutTests/transforms/combine-transforms-properties-motion-path.html b/third_party/WebKit/LayoutTests/transforms/combine-transforms-properties-motion-path.html
index 2b1615b..9b007b6 100644
--- a/third_party/WebKit/LayoutTests/transforms/combine-transforms-properties-motion-path.html
+++ b/third_party/WebKit/LayoutTests/transforms/combine-transforms-properties-motion-path.html
@@ -14,7 +14,7 @@
     translate: 200px 10px;
     rotate: 90deg;
     scale: 1 2;
-    motion: path("m 0 0 v -20 h 20") 0rad 100%;
+    offset: path("m 0 0 v -20 h 20") 100% 0rad;
 }
 #expected {
     background-color: green;
diff --git a/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js b/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js
index 112a780..f20c71a 100644
--- a/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js
+++ b/third_party/WebKit/LayoutTests/usb/resources/webusb-test.js
@@ -136,13 +136,13 @@
           }
           switch (endpoint.type) {
           case "bulk":
-            endpointInfo.type = mojo.device.UsbEndpointType.BULK;
+            endpointInfo.type = mojo.device.UsbTransferType.BULK;
             break;
           case "interrupt":
-            endpointInfo.type = mojo.device.UsbEndpointType.INTERRUPT;
+            endpointInfo.type = mojo.device.UsbTransferType.INTERRUPT;
             break;
           case "isochronous":
-            endpointInfo.type = mojo.device.UsbEndpointType.ISOCHRONOUS;
+            endpointInfo.type = mojo.device.UsbTransferType.ISOCHRONOUS;
             break;
           }
           alternateInfo.endpoints.push(endpointInfo);
diff --git a/third_party/WebKit/LayoutTests/virtual/mojo-loading/fast/table/README.txt b/third_party/WebKit/LayoutTests/virtual/mojo-loading/fast/table/README.txt
new file mode 100644
index 0000000..9444a6b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/mojo-loading/fast/table/README.txt
@@ -0,0 +1,4 @@
+This directory is for testing loading with mojo.
+
+This directory was added because fast/table tests once relied on a unspecified
+timing and were broken with mojo-loading.
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index b607b33..3813f6b 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -14,6 +14,37 @@
     getter y
     getter z
     method constructor
+interface AccessibleNode
+    attribute @@toStringTag
+    getter autocomplete
+    getter checked
+    getter current
+    getter invalid
+    getter keyShortcuts
+    getter label
+    getter live
+    getter orientation
+    getter placeholder
+    getter relevant
+    getter role
+    getter roleDescription
+    getter sort
+    getter valueText
+    method constructor
+    setter autocomplete
+    setter checked
+    setter current
+    setter invalid
+    setter keyShortcuts
+    setter label
+    setter live
+    setter orientation
+    setter placeholder
+    setter relevant
+    setter role
+    setter roleDescription
+    setter sort
+    setter valueText
 interface AmbientLightSensor : Sensor
     attribute @@toStringTag
     getter illuminance
@@ -1682,6 +1713,7 @@
 interface Element : Node
     attribute @@toStringTag
     attribute @@unscopables
+    getter accessibleNode
     getter assignedSlot
     getter attributes
     getter childElementCount
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt
index 5512948f..70a32387 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt
@@ -192,7 +192,6 @@
 minWidth
 minZoom
 mixBlendMode
-motion
 objectFit
 objectPosition
 offset
diff --git a/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
index c8f4570..a9d3112 100644
--- a/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/css-properties-as-js-properties-expected.txt
@@ -198,7 +198,6 @@
 minWidth
 minZoom
 mixBlendMode
-motion
 objectFit
 objectPosition
 offset
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index 9f75dde..bb77da6 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -25,6 +25,7 @@
     property PROCESSING_INSTRUCTION_NODE
     property TEXT_NODE
     property accessKey
+    property accessibleNode
     property addEventListener
     property after
     property animate
@@ -1125,6 +1126,7 @@
     property PROCESSING_INSTRUCTION_NODE
     property TEXT_NODE
     property accessKey
+    property accessibleNode
     property addEventListener
     property after
     property animate
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index dc45ff62d..32079e5 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -14,6 +14,37 @@
     getter y
     getter z
     method constructor
+interface AccessibleNode
+    attribute @@toStringTag
+    getter autocomplete
+    getter checked
+    getter current
+    getter invalid
+    getter keyShortcuts
+    getter label
+    getter live
+    getter orientation
+    getter placeholder
+    getter relevant
+    getter role
+    getter roleDescription
+    getter sort
+    getter valueText
+    method constructor
+    setter autocomplete
+    setter checked
+    setter current
+    setter invalid
+    setter keyShortcuts
+    setter label
+    setter live
+    setter orientation
+    setter placeholder
+    setter relevant
+    setter role
+    setter roleDescription
+    setter sort
+    setter valueText
 interface AmbientLightSensor : Sensor
     attribute @@toStringTag
     getter illuminance
@@ -1682,6 +1713,7 @@
 interface Element : Node
     attribute @@toStringTag
     attribute @@unscopables
+    getter accessibleNode
     getter assignedSlot
     getter attributes
     getter childElementCount
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h
index 2390472594..81c2f92 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.h
@@ -72,10 +72,6 @@
   void SuppressStreaming();
   bool StreamingSuppressed() const { return streaming_suppressed_; }
 
-  v8::ScriptCompiler::CompileOptions GetCompileOptions() const {
-    return compile_options_;
-  }
-
   // Called by PendingScript when data arrives from the network.
   void NotifyAppendData(ScriptResource*);
   void NotifyFinished(Resource*);
@@ -84,10 +80,6 @@
   // has processed it.
   void StreamingCompleteOnBackgroundThread();
 
-  v8::ScriptCompiler::StreamedSource::Encoding GetEncoding() const {
-    return encoding_;
-  }
-
   const String& ScriptURLString() const { return script_url_string_; }
   unsigned long ScriptResourceIdentifier() const {
     return script_resource_identifier_;
@@ -97,8 +89,6 @@
     small_script_threshold_ = threshold;
   }
 
-  static size_t SmallScriptThreshold() { return small_script_threshold_; }
-
  private:
   // Scripts whose first data chunk is smaller than this constant won't be
   // streamed. Non-const for testing.
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index f96ccc36..85f50b95 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1350,6 +1350,7 @@
     "loader/TextResourceDecoderBuilderTest.cpp",
     "loader/ThreadableLoaderTest.cpp",
     "loader/modulescript/ModuleScriptLoaderTest.cpp",
+    "loader/modulescript/ModuleTreeLinkerTest.cpp",
     "loader/resource/CSSStyleSheetResourceTest.cpp",
     "loader/resource/FontResourceTest.cpp",
     "loader/resource/ImageResourceTest.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index a3217e9b..5c3cfba 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1264,7 +1264,6 @@
       api_class: "CSSPropertyAPIMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertQuirkyLength",
-      initial: "InitialMargin",
       interpolable: true,
     },
     {
@@ -1272,7 +1271,6 @@
       api_class: "CSSPropertyAPIMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertQuirkyLength",
-      initial: "InitialMargin",
       interpolable: true,
     },
     {
@@ -1280,7 +1278,6 @@
       api_class: "CSSPropertyAPIMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertQuirkyLength",
-      initial: "InitialMargin",
       interpolable: true,
     },
     {
@@ -1288,7 +1285,6 @@
       api_class: "CSSPropertyAPIMargin",
       api_methods: ["parseSingleValue"],
       converter: "ConvertQuirkyLength",
-      initial: "InitialMargin",
       interpolable: true,
     },
     {
@@ -2818,10 +2814,6 @@
       longhands: "marker-start;marker-mid;marker-end",
     },
     {
-      name: "motion",
-      longhands: "offset-path;offset-distance;offset-rotation",
-    },
-    {
       name: "offset",
       longhands: "offset-path;offset-distance;offset-rotation",
     },
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index 83acd1a5..c8b49c4d 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -3412,10 +3412,6 @@
     case CSSPropertyBackgroundRepeatY:
       return nullptr;
 
-    case CSSPropertyMotion:
-      return ValuesForShorthandProperty(motionShorthand(), style, layout_object,
-                                        styled_node, allow_visited_style);
-
     case CSSPropertyOffset:
       return ValuesForShorthandProperty(offsetShorthand(), style, layout_object,
                                         styled_node, allow_visited_style);
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
index 3918ae8..44d2b01 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -335,7 +335,6 @@
     case CSSPropertyGridArea:
     case CSSPropertyGridGap:
     case CSSPropertyListStyle:
-    case CSSPropertyMotion:
     case CSSPropertyOffset:
     case CSSPropertyTextDecoration:
     case CSSPropertyWebkitMarginCollapse:
@@ -475,8 +474,6 @@
       return FontVariantValue();
     case CSSPropertyMargin:
       return Get4Values(marginShorthand());
-    case CSSPropertyMotion:
-      return GetShorthandValue(motionShorthand());
     case CSSPropertyOffset:
       return GetShorthandValue(offsetShorthand());
     case CSSPropertyWebkitMarginCollapse:
diff --git a/third_party/WebKit/Source/core/css/mediaControls.css b/third_party/WebKit/Source/core/css/mediaControls.css
index dd4a094..152f634 100644
--- a/third_party/WebKit/Source/core/css/mediaControls.css
+++ b/third_party/WebKit/Source/core/css/mediaControls.css
@@ -153,12 +153,11 @@
     direction: ltr;
     display: flex;
     flex-direction: column;
-    font-family: Segoe, "Helvetica Neue", Roboto, Arial, Helvetica, sans-serif;
     justify-content: flex-end;
     align-items: center;
-    font-size: 28px;
+    font-size: 16px;
     background-color: black;
-    transition: opacity .2s cubic-bezier (0.4, 0.0, 0.2, 1);
+    transition: opacity .2s ease-in-out;
 }
 
 video::-internal-media-remoting-background-image {
@@ -183,11 +182,11 @@
     margin: 0px;
     border-width: 0px;
     background-color: transparent;
-    height: 36px;
-    width: 44px;
+    height: 18px;
+    width: 22px;
     padding: 0px;
-    left: calc(50% - 22px);
-    top: calc(50% - 60px);
+    left: calc(50% - 11px);
+    top: calc(50% - 40px);
 }
 
 video::-internal-media-remoting-cast-text-message {
@@ -195,14 +194,13 @@
     position: absolute;
     top: calc(50% - 10px);
     border: none;
-    color: #FFFFFF;
-    opacity: 54%
+    color: rgba(255,255,255,.54);
     width: 100%;
     text-wrap: none;
     text-align: center;
     background-color: transparent;
-    font-size: 13pt;
-    font-face: Roboto-Regular, Sans-serif, Segoe, Serif, Helvetica;
+    font-size: 81.25%;
+    font-family: Roboto-Regular, Sans-serif, Segoe, Serif, Helvetica;
     padding: 0px;
     margin: 0px;
 }
@@ -210,20 +208,28 @@
 video::-internal-media-remoting-disable-button {
     display: flex;
     position: absolute;
-    top: calc(50% + 55pt);
-    left: calc(50% - 102px);
-    height: 28pt;
-    border: 2pt solid rgba(255,255,255,.54);
+    top: calc(50% + 60px);
+    left: calc(50% - 74px);
+    height: 28px;
+    border: 1pt solid rgba(255,255,255,.54);
     border-radius: 2pt;
     background-color: transparent;
-    color: #FFFFFF;
+    color: rgba(255,255,255,.54);
     margin: 0px;
-    padding: 8pt 16pt 0pt 16pt;
+    padding: 5.5px 16px 0px 16px;
     text-wrap: none;
-    font-size: 13pt;
-    font-face: Roboto-Medium, Sans-serif, Segoe, Serif, Helvetica;
-    opacity: 54%
-    transition: border .5s ease-out;
+    font-size: 75%;
+    font-weight: 500;
+    font-family: Roboto-Medium, Sans-serif, Segoe, Serif, Helvetica;
+    box-sizing: border-box;
+    transition: border,color .5s ease-out;
+    z-index: 1;  /* Set this z-index to make the hover effect work. */
+}
+
+video::-internal-media-remoting-disable-button:hover {
+    border: 1pt solid rgba(255,255,255,.70);
+    color: rgba(255,255,255,.70);
+    cursor: pointer;
 }
 
 video::-internal-media-controls-overlay-cast-button {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index eaab6a2..7abefdc 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -1951,9 +1951,7 @@
       return ConsumePathOrNone(range_);
     case CSSPropertyOffsetPath:
       return ConsumeOffsetPath(
-          range_, context_,
-          current_shorthand == CSSPropertyMotion ||
-              unresolved_property == CSSPropertyAliasMotionPath);
+          range_, context_, unresolved_property == CSSPropertyAliasMotionPath);
     case CSSPropertyOffsetDistance:
       return ConsumeLengthOrPercent(range_, context_->Mode(), kValueRangeAll);
     case CSSPropertyOffsetRotate:
@@ -3478,8 +3476,6 @@
       return Consume4Values(marginShorthand(), important);
     case CSSPropertyPadding:
       return Consume4Values(paddingShorthand(), important);
-    case CSSPropertyMotion:
-      return ConsumeShorthandGreedily(motionShorthand(), important);
     case CSSPropertyOffset:
       return ConsumeOffsetShorthand(important);
     case CSSPropertyWebkitTextEmphasis:
diff --git a/third_party/WebKit/Source/core/dom/BUILD.gn b/third_party/WebKit/Source/core/dom/BUILD.gn
index 01139383..80821d3 100644
--- a/third_party/WebKit/Source/core/dom/BUILD.gn
+++ b/third_party/WebKit/Source/core/dom/BUILD.gn
@@ -194,6 +194,8 @@
     "MessagePort.h",
     "Modulator.cpp",
     "Modulator.h",
+    "ModulatorImpl.cpp",
+    "ModulatorImpl.h",
     "ModuleMap.cpp",
     "ModuleMap.h",
     "ModuleScript.cpp",
diff --git a/third_party/WebKit/Source/core/dom/Modulator.cpp b/third_party/WebKit/Source/core/dom/Modulator.cpp
index c48775ff..56abb82 100644
--- a/third_party/WebKit/Source/core/dom/Modulator.cpp
+++ b/third_party/WebKit/Source/core/dom/Modulator.cpp
@@ -6,6 +6,10 @@
 
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8PerContextData.h"
+#include "core/dom/Document.h"
+#include "core/dom/ModulatorImpl.h"
+#include "core/frame/LocalFrame.h"
 
 namespace blink {
 
@@ -16,10 +20,20 @@
 Modulator* Modulator::From(ScriptState* script_state) {
   if (!script_state)
     return nullptr;
+
   V8PerContextData* per_context_data = script_state->PerContextData();
   if (!per_context_data)
     return nullptr;
-  return static_cast<Modulator*>(per_context_data->GetData(kPerContextDataKey));
+
+  Modulator* modulator =
+      static_cast<Modulator*>(per_context_data->GetData(kPerContextDataKey));
+  if (!modulator) {
+    if (Document* document = ToDocument(ExecutionContext::From(script_state))) {
+      modulator = ModulatorImpl::Create(script_state, *document);
+      Modulator::SetModulator(script_state, modulator);
+    }
+  }
+  return modulator;
 }
 
 Modulator::~Modulator() {}
diff --git a/third_party/WebKit/Source/core/dom/Modulator.h b/third_party/WebKit/Source/core/dom/Modulator.h
index e3a00c5..4c63e3c3 100644
--- a/third_party/WebKit/Source/core/dom/Modulator.h
+++ b/third_party/WebKit/Source/core/dom/Modulator.h
@@ -89,6 +89,7 @@
 
   // Synchronously retrieves a single module script from existing module map
   // entry.
+  // Note: returns nullptr if the module map entry is still "fetching".
   virtual ModuleScript* GetFetchedModuleScript(const KURL&) = 0;
 
   // https://html.spec.whatwg.org/#resolve-a-module-specifier
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp
new file mode 100644
index 0000000..dbf2f24
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp
@@ -0,0 +1,151 @@
+// 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/dom/ModulatorImpl.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/ExecutionContext.h"
+#include "core/dom/ModuleMap.h"
+#include "core/dom/ModuleScript.h"
+#include "core/dom/ScriptModuleResolverImpl.h"
+#include "core/dom/TaskRunnerHelper.h"
+#include "core/frame/LocalFrame.h"
+#include "core/loader/modulescript/ModuleScriptFetchRequest.h"
+#include "core/loader/modulescript/ModuleScriptLoaderRegistry.h"
+#include "platform/loader/fetch/ResourceFetcher.h"
+
+namespace blink {
+
+ModulatorImpl* ModulatorImpl::Create(RefPtr<ScriptState> script_state,
+                                     Document& document) {
+  return new ModulatorImpl(
+      std::move(script_state),
+      TaskRunnerHelper::Get(TaskType::kNetworking, &document),
+      document.Fetcher());
+}
+
+ModulatorImpl::ModulatorImpl(RefPtr<ScriptState> script_state,
+                             RefPtr<WebTaskRunner> task_runner,
+                             ResourceFetcher* fetcher)
+    : script_state_(std::move(script_state)),
+      task_runner_(std::move(task_runner)),
+      fetcher_(fetcher),
+      map_(this, ModuleMap::Create(this)),
+      loader_registry_(ModuleScriptLoaderRegistry::Create()),
+      script_module_resolver_(ScriptModuleResolverImpl::Create(this)) {
+  DCHECK(script_state_);
+  DCHECK(task_runner_);
+  DCHECK(fetcher_);
+}
+
+ModulatorImpl::~ModulatorImpl() {}
+
+ReferrerPolicy ModulatorImpl::GetReferrerPolicy() {
+  return GetExecutionContext()->GetReferrerPolicy();
+}
+
+SecurityOrigin* ModulatorImpl::GetSecurityOrigin() {
+  return GetExecutionContext()->GetSecurityOrigin();
+}
+
+void ModulatorImpl::FetchTree(const ModuleScriptFetchRequest& request,
+                              ModuleTreeClient* client) {
+  // Step 1. Perform the internal module script graph fetching procedure given
+  // url, settings object, destination, cryptographic nonce, parser state,
+  // credentials mode, settings object, a new empty list, "client", and with the
+  // top-level module fetch flag set. If the caller of this algorithm specified
+  // custom perform the fetch steps, pass those along as well.
+
+  // Note: "Fetch a module script graph" algorithm doesn't have "referrer" as
+  // its argument.
+  DCHECK(request.GetReferrer().IsNull());
+
+  AncestorList empty_ancestor_list;
+  FetchTreeInternal(request, empty_ancestor_list,
+                    ModuleGraphLevel::kTopLevelModuleFetch, client);
+
+  // Step 2. When the internal module script graph fetching procedure
+  // asynchronously completes with result, asynchronously complete this
+  // algorithm with result.
+  // Note: We delegate to ModuleTreeLinker to notify ModuleTreeClient.
+}
+
+void ModulatorImpl::FetchTreeInternal(const ModuleScriptFetchRequest& request,
+                                      const AncestorList& ancestor_list,
+                                      ModuleGraphLevel level,
+                                      ModuleTreeClient* client) {
+  NOTIMPLEMENTED();
+}
+
+void ModulatorImpl::FetchSingle(const ModuleScriptFetchRequest& request,
+                                ModuleGraphLevel level,
+                                SingleModuleClient* client) {
+  map_->FetchSingleModuleScript(request, level, client);
+}
+
+void ModulatorImpl::FetchNewSingleModule(
+    const ModuleScriptFetchRequest& request,
+    ModuleGraphLevel level,
+    ModuleScriptLoaderClient* client) {
+  loader_registry_->Fetch(request, level, this, fetcher_.Get(), client);
+}
+
+ModuleScript* ModulatorImpl::GetFetchedModuleScript(const KURL& url) {
+  return map_->GetFetchedModuleScript(url);
+}
+
+ScriptModule ModulatorImpl::CompileModule(
+    const String& provided_source,
+    const String& url_str,
+    AccessControlStatus access_control_status) {
+  // Implements Steps 3-6 of
+  // https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-module-script
+
+  // Step 3. Let realm be the provided environment settings object's Realm.
+  // Note: Realm is v8::Context.
+
+  // Step 4. If scripting is disabled for the given environment settings
+  // object's responsible browsing context, then let script source be the empty
+  // string. Otherwise, let script source be the provided script source.
+  String script_source;
+  if (GetExecutionContext()->CanExecuteScripts(kAboutToExecuteScript))
+    script_source = provided_source;
+
+  // Step 5. Let result be ParseModule(script source, realm, script).
+  // Step 6. If result is a List of errors, report the exception given by the
+  // first element of result for script, return null, and abort these steps.
+  // Note: reporting is routed via V8Initializer::messageHandlerInMainThread.
+  ScriptState::Scope scope(script_state_.Get());
+  return ScriptModule::Compile(script_state_->GetIsolate(), script_source,
+                               url_str, access_control_status);
+}
+
+ScriptValue ModulatorImpl::InstantiateModule(ScriptModule script_module) {
+  ScriptState::Scope scope(script_state_.Get());
+  return script_module.Instantiate(script_state_.Get());
+}
+
+Vector<String> ModulatorImpl::ModuleRequestsFromScriptModule(
+    ScriptModule script_module) {
+  ScriptState::Scope scope(script_state_.Get());
+  return script_module.ModuleRequests(script_state_.Get());
+}
+
+inline ExecutionContext* ModulatorImpl::GetExecutionContext() const {
+  return ExecutionContext::From(script_state_.Get());
+}
+
+DEFINE_TRACE(ModulatorImpl) {
+  Modulator::Trace(visitor);
+  visitor->Trace(fetcher_);
+  visitor->Trace(map_);
+  visitor->Trace(loader_registry_);
+  visitor->Trace(script_module_resolver_);
+}
+
+DEFINE_TRACE_WRAPPERS(ModulatorImpl) {
+  visitor->TraceWrappers(map_);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.h b/third_party/WebKit/Source/core/dom/ModulatorImpl.h
new file mode 100644
index 0000000..711d4d7d
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.h
@@ -0,0 +1,79 @@
+// 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 ModulatorImpl_h
+#define ModulatorImpl_h
+
+#include "bindings/core/v8/ScriptModule.h"
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "bindings/core/v8/TraceWrapperMember.h"
+#include "bindings/core/v8/V8PerIsolateData.h"
+#include "core/dom/Modulator.h"
+#include "platform/heap/Handle.h"
+
+namespace blink {
+
+class Document;
+class ExecutionContext;
+class ModuleMap;
+class ModuleScriptLoaderRegistry;
+class ResourceFetcher;
+class ScriptState;
+class WebTaskRunner;
+
+// ModulatorImpl is the implementation of Modulator interface, which represents
+// "environment settings object" concept for module scripts.
+// ModulatorImpl serves as the backplane for tieing all ES6 module algorithm
+// components together.
+class ModulatorImpl final : public Modulator {
+ public:
+  static ModulatorImpl* Create(RefPtr<ScriptState>, Document&);
+
+  virtual ~ModulatorImpl();
+  DECLARE_TRACE();
+  DECLARE_VIRTUAL_TRACE_WRAPPERS();
+
+ private:
+  // Implements Modulator
+
+  ScriptModuleResolver* GetScriptModuleResolver() override {
+    return script_module_resolver_.Get();
+  }
+  WebTaskRunner* TaskRunner() override { return task_runner_.Get(); }
+  ReferrerPolicy GetReferrerPolicy() override;
+  SecurityOrigin* GetSecurityOrigin() override;
+
+  void FetchTree(const ModuleScriptFetchRequest&, ModuleTreeClient*) override;
+  void FetchTreeInternal(const ModuleScriptFetchRequest&,
+                         const AncestorList&,
+                         ModuleGraphLevel,
+                         ModuleTreeClient*) override;
+  void FetchSingle(const ModuleScriptFetchRequest&,
+                   ModuleGraphLevel,
+                   SingleModuleClient*) override;
+  ModuleScript* GetFetchedModuleScript(const KURL&) override;
+  void FetchNewSingleModule(const ModuleScriptFetchRequest&,
+                            ModuleGraphLevel,
+                            ModuleScriptLoaderClient*) override;
+  ScriptModule CompileModule(const String& script,
+                             const String& url_str,
+                             AccessControlStatus) override;
+  ScriptValue InstantiateModule(ScriptModule) override;
+  Vector<String> ModuleRequestsFromScriptModule(ScriptModule) override;
+
+  ModulatorImpl(RefPtr<ScriptState>, RefPtr<WebTaskRunner>, ResourceFetcher*);
+
+  ExecutionContext* GetExecutionContext() const;
+
+  RefPtr<ScriptState> script_state_;
+  RefPtr<WebTaskRunner> task_runner_;
+  Member<ResourceFetcher> fetcher_;
+  TraceWrapperMember<ModuleMap> map_;
+  Member<ModuleScriptLoaderRegistry> loader_registry_;
+  Member<ScriptModuleResolver> script_module_resolver_;
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.cpp b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
index f175cd9..9e2845e1 100644
--- a/third_party/WebKit/Source/core/dom/ModuleScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
@@ -4,18 +4,36 @@
 
 #include "core/dom/ModuleScript.h"
 
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/ScriptValue.h"
+#include "v8/include/v8.h"
+
 namespace blink {
 
-void ModuleScript::SetInstantiationError(v8::Isolate* isolate,
-                                         v8::Local<v8::Value> error) {
+void ModuleScript::SetInstantiationErrorAndClearRecord(ScriptValue error) {
+  // Implements Step 7.1 of:
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+
+  // "set script's instantiation state to "errored", ..."
   DCHECK_EQ(instantiation_state_, ModuleInstantiationState::kUninstantiated);
   instantiation_state_ = ModuleInstantiationState::kErrored;
 
+  // "its instantiation error to instantiationStatus.[[Value]], and ..."
   DCHECK(!error.IsEmpty());
-  instantiation_error_.Set(isolate, error);
+  {
+    ScriptState::Scope scope(error.GetScriptState());
+    instantiation_error_.Set(error.GetIsolate(), error.V8Value());
+  }
+
+  // "its module record to null."
+  record_ = ScriptModule();
 }
 
 void ModuleScript::SetInstantiationSuccess() {
+  // Implements Step 7.2 of:
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+
+  // "set script's instantiation state to "instantiated"."
   DCHECK_EQ(instantiation_state_, ModuleInstantiationState::kUninstantiated);
   instantiation_state_ = ModuleInstantiationState::kInstantiated;
 }
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.h b/third_party/WebKit/Source/core/dom/ModuleScript.h
index 17cec9d..f334179 100644
--- a/third_party/WebKit/Source/core/dom/ModuleScript.h
+++ b/third_party/WebKit/Source/core/dom/ModuleScript.h
@@ -43,15 +43,18 @@
   ~ModuleScript() override = default;
 
   ScriptModule& Record() { return record_; }
-  void ClearRecord() { record_ = ScriptModule(); }
   const KURL& BaseURL() const { return base_url_; }
 
   ModuleInstantiationState InstantiationState() const {
     return instantiation_state_;
   }
 
+  // Implements Step 7.1 of:
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+  void SetInstantiationErrorAndClearRecord(ScriptValue error);
+  // Implements Step 7.2 of:
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
   void SetInstantiationSuccess();
-  void SetInstantiationError(v8::Isolate*, v8::Local<v8::Value> error);
 
   ParserDisposition ParserState() const { return parser_state_; }
   WebURLRequest::FetchCredentialsMode CredentialsMode() const {
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn
index 12efe0b37..15bdd615 100644
--- a/third_party/WebKit/Source/core/editing/BUILD.gn
+++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -32,6 +32,8 @@
     "EditorKeyBindings.cpp",
     "EphemeralRange.cpp",
     "EphemeralRange.h",
+    "FindInPageCoordinates.cpp",
+    "FindInPageCoordinates.h",
     "FrameCaret.cpp",
     "FrameCaret.h",
     "FrameSelection.cpp",
diff --git a/third_party/WebKit/Source/web/FindInPageCoordinates.cpp b/third_party/WebKit/Source/core/editing/FindInPageCoordinates.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/FindInPageCoordinates.cpp
rename to third_party/WebKit/Source/core/editing/FindInPageCoordinates.cpp
index e84c7c7..f09f593b 100644
--- a/third_party/WebKit/Source/web/FindInPageCoordinates.cpp
+++ b/third_party/WebKit/Source/core/editing/FindInPageCoordinates.cpp
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "web/FindInPageCoordinates.h"
+#include "core/editing/FindInPageCoordinates.h"
 
 #include "core/dom/Node.h"
 #include "core/dom/Range.h"
diff --git a/third_party/WebKit/Source/web/FindInPageCoordinates.h b/third_party/WebKit/Source/core/editing/FindInPageCoordinates.h
similarity index 91%
rename from third_party/WebKit/Source/web/FindInPageCoordinates.h
rename to third_party/WebKit/Source/core/editing/FindInPageCoordinates.h
index 5aa8fff..bf1c37a8 100644
--- a/third_party/WebKit/Source/web/FindInPageCoordinates.h
+++ b/third_party/WebKit/Source/core/editing/FindInPageCoordinates.h
@@ -31,8 +31,8 @@
 #ifndef FindInPageCoordinates_h
 #define FindInPageCoordinates_h
 
+#include "core/CoreExport.h"
 #include "platform/geometry/FloatRect.h"
-#include "web/WebExport.h"
 
 namespace blink {
 class Range;
@@ -54,9 +54,9 @@
 // of their container.  The provided methods support scroll:overflow and are
 // CSS position and transform-friendly.
 
-WEB_EXPORT FloatRect FindInPageRectFromAbsoluteRect(const FloatRect&,
-                                                    const LayoutObject*);
-WEB_EXPORT FloatRect FindInPageRectFromRange(Range*);
+CORE_EXPORT FloatRect FindInPageRectFromAbsoluteRect(const FloatRect&,
+                                                     const LayoutObject*);
+CORE_EXPORT FloatRect FindInPageRectFromRange(Range*);
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index c754219..44d4438 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -127,8 +127,6 @@
     case CSSPropertyAliasMotionPath:
       return replacedWillBeRemoved("motion-path", "offset-path", M58,
                                    "6390764217040896");
-    case CSSPropertyMotion:
-      return replacedWillBeRemoved("motion", "offset", M58, "6390764217040896");
     case CSSPropertyOffsetRotation:
       return replacedWillBeRemoved("offset-rotation", "offset-rotate", M58,
                                    "6390764217040896");
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index 74e0cefd..070d70a 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -896,9 +896,24 @@
     return;
   }
 
+  CanvasColorParams canvas_color_params;
+  if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() &&
+      RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) {
+    ImageDataColorSettings color_settings;
+    data->getColorSettings(color_settings);
+    CanvasColorSpace canvas_color_space =
+        ImageData::GetCanvasColorSpace(color_settings.colorSpace());
+    CanvasPixelFormat canvas_pixel_format = kRGBA8CanvasPixelFormat;
+    if (ImageData::GetImageDataStorageFormat(color_settings.storageFormat()) !=
+        kUint8ClampedArrayStorageFormat) {
+      canvas_pixel_format = kF16CanvasPixelFormat;
+    }
+    canvas_color_params =
+        CanvasColorParams(canvas_color_space, canvas_pixel_format);
+  }
   std::unique_ptr<ImageBuffer> buffer =
       ImageBuffer::Create(parsed_options.crop_rect.Size(), kNonOpaque,
-                          kDoNotInitializeImagePixels, data->GetSkColorSpace());
+                          kDoNotInitializeImagePixels, canvas_color_params);
   if (!buffer)
     return;
 
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp
index 8a46a3b..5a68e69 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -887,8 +887,7 @@
       return 458;
     case CSSPropertyAliasMotionRotation:
       return 459;
-    case CSSPropertyMotion:
-      return 460;
+    // CSSPropertyMotion was 460.
     case CSSPropertyX:
       return 461;
     case CSSPropertyY:
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index 32b5099..ca26c8a 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -896,10 +896,9 @@
   virtual std::unique_ptr<ImageBufferSurface> CreateSurface(
       const IntSize& size,
       OpacityMode opacity_mode,
-      sk_sp<SkColorSpace> color_space,
-      SkColorType color_type) {
+      const CanvasColorParams& color_params) {
     return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, opacity_mode, kInitializeImagePixels, color_space, color_type));
+        size, opacity_mode, kInitializeImagePixels, color_params));
   }
 
   virtual ~UnacceleratedSurfaceFactory() {}
@@ -908,7 +907,10 @@
 }  // namespace
 
 bool HTMLCanvasElement::ShouldUseDisplayList() {
-  if (context_->ColorSpace() != kLegacyCanvasColorSpace)
+  // Rasterization of web contents will blend in the output space. Only embed
+  // the canvas as a display list if it intended to do output space blending as
+  // well.
+  if (!context_->color_params().UsesOutputSpaceBlending())
     return false;
 
   if (RuntimeEnabledFeatures::forceDisplayList2dCanvasEnabled())
@@ -927,8 +929,7 @@
   // then make a non-accelerated ImageBuffer. This means copying the internal
   // Image will require a pixel readback, but that is unavoidable in this case.
   auto surface = WTF::WrapUnique(new AcceleratedImageBufferSurface(
-      size(), opacity_mode, context_->SkSurfaceColorSpace(),
-      context_->ColorType()));
+      size(), opacity_mode, context_->color_params()));
   if (surface->IsValid())
     return std::move(surface);
   return nullptr;
@@ -958,8 +959,7 @@
   std::unique_ptr<ImageBufferSurface> surface =
       WTF::WrapUnique(new Canvas2DImageBufferSurface(
           std::move(context_provider), size(), *msaa_sample_count, opacity_mode,
-          Canvas2DLayerBridge::kEnableAcceleration, context_->GfxColorSpace(),
-          context_->SkSurfacesUseColorSpace(), context_->ColorType()));
+          Canvas2DLayerBridge::kEnableAcceleration, context_->color_params()));
   if (!surface->IsValid()) {
     CanvasMetrics::CountCanvasContextUsage(
         CanvasMetrics::kGPUAccelerated2DCanvasImageBufferCreationFailed);
@@ -977,7 +977,7 @@
   if (ShouldUseDisplayList()) {
     auto surface = WTF::WrapUnique(new RecordingImageBufferSurface(
         size(), WTF::WrapUnique(new UnacceleratedSurfaceFactory), opacity_mode,
-        context_->SkSurfaceColorSpace(), context_->ColorType()));
+        context_->color_params()));
     if (surface->IsValid()) {
       CanvasMetrics::CountCanvasContextUsage(
           CanvasMetrics::kDisplayList2DCanvasImageBufferCreated);
@@ -989,8 +989,7 @@
 
   auto surface_factory = WTF::MakeUnique<UnacceleratedSurfaceFactory>();
   auto surface = surface_factory->CreateSurface(size(), opacity_mode,
-                                                context_->SkSurfaceColorSpace(),
-                                                context_->ColorType());
+                                                context_->color_params());
   if (surface->IsValid()) {
     CanvasMetrics::CountCanvasContextUsage(
         CanvasMetrics::kUnaccelerated2DCanvasImageBufferCreated);
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
index 23590934..bb9f51c 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp
@@ -67,7 +67,7 @@
   // linearPixelMath rather than the requested one.
   creation_attributes_.setColorSpace(ColorSpaceAsString());
   creation_attributes_.setPixelFormat(PixelFormatAsString());
-  creation_attributes_.setLinearPixelMath(LinearPixelMath());
+  creation_attributes_.setLinearPixelMath(color_params_.LinearPixelMath());
 }
 
 WTF::String CanvasRenderingContext::ColorSpaceAsString() const {
@@ -100,37 +100,13 @@
   return "";
 }
 
-gfx::ColorSpace CanvasRenderingContext::GfxColorSpace() const {
-  return color_params_.GetGfxColorSpace();
-}
-
-sk_sp<SkColorSpace> CanvasRenderingContext::SkSurfaceColorSpace() const {
-  return color_params_.GetSkColorSpaceForSkSurfaces();
-}
-
-bool CanvasRenderingContext::SkSurfacesUseColorSpace() const {
-  return color_params_.GetSkColorSpaceForSkSurfaces();
-}
-
-bool CanvasRenderingContext::LinearPixelMath() const {
-  return color_params_.LinearPixelMath();
-}
-
 ColorBehavior CanvasRenderingContext::ColorBehaviorForMediaDrawnToCanvas()
     const {
   if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled())
-    return ColorBehavior::TransformTo(GfxColorSpace());
+    return ColorBehavior::TransformTo(color_params_.GetGfxColorSpace());
   return ColorBehavior::TransformToGlobalTarget();
 }
 
-CanvasColorSpace CanvasRenderingContext::ColorSpace() const {
-  return color_params_.color_space();
-}
-
-SkColorType CanvasRenderingContext::ColorType() const {
-  return color_params_.GetSkColorType();
-}
-
 void CanvasRenderingContext::Dispose() {
   if (finalize_frame_scheduled_) {
     Platform::Current()->CurrentThread()->RemoveTaskObserver(this);
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
index 0a6a2369..84040416 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h
@@ -89,21 +89,11 @@
 
   HTMLCanvasElement* canvas() const { return canvas_; }
 
-  CanvasColorSpace ColorSpace() const;
   WTF::String ColorSpaceAsString() const;
-  CanvasPixelFormat PixelFormat() const;
   WTF::String PixelFormatAsString() const;
-  bool LinearPixelMath() const;
 
-  // The color space in which the the content should be interpreted by the
-  // compositor. This is always defined.
-  gfx::ColorSpace GfxColorSpace() const;
-  // The color space that should be used for SkSurface creation. This may
-  // be nullptr.
-  sk_sp<SkColorSpace> SkSurfaceColorSpace() const;
-  SkColorType ColorType() const;
+  const CanvasColorParams& color_params() const { return color_params_; }
   ColorBehavior ColorBehaviorForMediaDrawnToCanvas() const;
-  bool SkSurfacesUseColorSpace() const;
 
   virtual PassRefPtr<Image> GetImage(AccelerationHint,
                                      SnapshotReason) const = 0;
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp
index be63dba..1add0ab 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -651,8 +651,7 @@
   }
 
   mouse_event_manager_->SetClickCount(mouse_event.click_count);
-  mouse_event_manager_->SetClickElement(
-      EventHandlingUtil::ParentElementIfNeeded(mev.InnerNode()));
+  mouse_event_manager_->SetClickElement(mev.InnerElement());
 
   if (!mouse_event.FromTouch())
     frame_->Selection().SetCaretBlinkingSuspended(true);
@@ -957,8 +956,7 @@
   HitTestRequest request(hit_type);
   MouseEventWithHitTestResults mev =
       EventHandlingUtil::PerformMouseEventHitTest(frame_, request, mouse_event);
-  Element* mouse_release_target =
-      EventHandlingUtil::ParentElementIfNeeded(mev.InnerNode());
+  Element* mouse_release_target = mev.InnerElement();
   LocalFrame* subframe =
       capturing_mouse_events_node_.Get()
           ? SubframeForTargetNode(capturing_mouse_events_node_.Get())
diff --git a/third_party/WebKit/Source/core/input/EventHandlingUtil.cpp b/third_party/WebKit/Source/core/input/EventHandlingUtil.cpp
index 0872c3a..8ce9d0ca 100644
--- a/third_party/WebKit/Source/core/input/EventHandlingUtil.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandlingUtil.cpp
@@ -92,14 +92,6 @@
   return nullptr;
 }
 
-Element* ParentElementIfNeeded(Node* node) {
-  if (!node)
-    return nullptr;
-  if (node->IsElementNode())
-    return ToElement(node);
-  return FlatTreeTraversal::ParentElement(*node);
-}
-
 ContainerNode* ParentForClickEvent(const Node& node) {
   // IE doesn't dispatch click events for mousedown/mouseup events across form
   // controls.
diff --git a/third_party/WebKit/Source/core/input/EventHandlingUtil.h b/third_party/WebKit/Source/core/input/EventHandlingUtil.h
index edef3b9..fb9ed3da 100644
--- a/third_party/WebKit/Source/core/input/EventHandlingUtil.h
+++ b/third_party/WebKit/Source/core/input/EventHandlingUtil.h
@@ -31,7 +31,6 @@
 PaintLayer* LayerForNode(Node*);
 ScrollableArea* AssociatedScrollableArea(const PaintLayer*);
 
-Element* ParentElementIfNeeded(Node*);
 ContainerNode* ParentForClickEvent(const Node&);
 
 LayoutPoint ContentPointFromRootFrame(LocalFrame*,
diff --git a/third_party/WebKit/Source/core/input/GestureManager.cpp b/third_party/WebKit/Source/core/input/GestureManager.cpp
index a291e0e..ce5f660 100644
--- a/third_party/WebKit/Source/core/input/GestureManager.cpp
+++ b/third_party/WebKit/Source/core/input/GestureManager.cpp
@@ -188,8 +188,7 @@
   IntPoint tapped_position =
       FlooredIntPoint(gesture_event.PositionInRootFrame());
   Node* tapped_node = current_hit_test.InnerNode();
-  Element* tapped_element =
-      EventHandlingUtil::ParentElementIfNeeded(tapped_node);
+  Element* tapped_element = current_hit_test.InnerElement();
   UserGestureIndicator gesture_indicator(DocumentUserGestureToken::Create(
       tapped_node ? &tapped_node->GetDocument() : nullptr));
 
diff --git a/third_party/WebKit/Source/core/layout/HitTestResult.cpp b/third_party/WebKit/Source/core/layout/HitTestResult.cpp
index 3799c7b..3018bc3 100644
--- a/third_party/WebKit/Source/core/layout/HitTestResult.cpp
+++ b/third_party/WebKit/Source/core/layout/HitTestResult.cpp
@@ -508,13 +508,11 @@
 }
 
 Element* HitTestResult::InnerElement() const {
-  for (Node* node = inner_node_.Get(); node;
-       node = FlatTreeTraversal::Parent(*node)) {
-    if (node->IsElementNode())
-      return ToElement(node);
-  }
-
-  return nullptr;
+  if (!inner_node_)
+    return nullptr;
+  if (inner_node_->IsElementNode())
+    return ToElement(inner_node_);
+  return FlatTreeTraversal::ParentElement(*inner_node_);
 }
 
 Node* HitTestResult::InnerNodeOrImageMapImage() const {
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
index 4976df78..bee54c30 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
@@ -133,25 +133,25 @@
       ToLayoutText(GetLayoutObjectByElementId("text")->SlowFirstChild());
   DCHECK(layout_text->HasTextBoxes());
 
-  ASSERT_EQ(4UL, text_fragments.size());
+  // Line break points may vary by minor differences in fonts.
+  // The test is valid as long as we have 3 or more lines and their positions
+  // are correct.
+  EXPECT_GE(text_fragments.size(), 3UL);
 
   auto* text_fragment1 = text_fragments[0];
   // 40 = #left-float1' width 30 + #left-float2 10
   EXPECT_EQ(LayoutUnit(40), text_fragment1->LeftOffset());
-  EXPECT_EQ("The quick ", text_fragment1->Text());
   InlineTextBox* inline_text_box1 = layout_text->FirstTextBox();
   EXPECT_EQ(LayoutUnit(40), inline_text_box1->X());
 
   auto* text_fragment2 = text_fragments[1];
   // 40 = #left-float1' width 30
   EXPECT_EQ(LayoutUnit(30), text_fragment2->LeftOffset());
-  EXPECT_EQ("brown fox ", text_fragment2->Text());
   InlineTextBox* inline_text_box2 = inline_text_box1->NextTextBox();
   EXPECT_EQ(LayoutUnit(30), inline_text_box2->X());
 
   auto* text_fragment3 = text_fragments[2];
   EXPECT_EQ(LayoutUnit(), text_fragment3->LeftOffset());
-  EXPECT_EQ("jumps over the lazy ", text_fragment3->Text());
   InlineTextBox* inline_text_box3 = inline_text_box2->NextTextBox();
   EXPECT_EQ(LayoutUnit(), inline_text_box3->X());
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index a9d8dd6..96402b5 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -203,6 +203,11 @@
     LayoutObject* next_sibling = layout_box_->NextSibling();
     if (next_sibling) {
       if (next_sibling->IsInline()) {
+        // As long as we traverse LayoutObject tree, this should not happen.
+        // See ShouldHandleByInlineContext() for more context.
+        // Also this leads to incorrect layout because we create two
+        // NGLayoutInputNode for one LayoutBlockFlow.
+        NOTREACHED();
         next_sibling_ = new NGInlineNode(
             next_sibling, ToLayoutBlockFlow(layout_box_->Parent()));
       } else {
@@ -217,11 +222,32 @@
   return layout_box_;
 }
 
+static bool ShouldHandleByInlineContext(LayoutObject* child) {
+  DCHECK(child);
+  // The spec isn't clear about whether floats/OOF should be in inline
+  // formatting context or in block formatting context.
+  // Prefer inline formatting context because 1) floats/OOF at the beginning
+  // and in the middle of inline should be handled in the same code, and 2)
+  // it matches to the LayoutObject tree.
+  for (; child; child = child->NextSibling()) {
+    if (child->IsInline())
+      return true;
+    if (child->IsFloating() || child->IsOutOfFlowPositioned())
+      continue;
+    return false;
+  }
+  // All children are either float or OOF.
+  // TODO(kojii): Should this be handled in block context or inline context?
+  // If we handle in inline, we can remove all code for floats/OOF from block
+  // layout, but it may change semantics and causes incorrectness?
+  return false;
+}
+
 NGLayoutInputNode* NGBlockNode::FirstChild() {
   if (!first_child_) {
     LayoutObject* child = layout_box_->SlowFirstChild();
     if (child) {
-      if (child->IsInline()) {
+      if (ShouldHandleByInlineContext(child)) {
         first_child_ = new NGInlineNode(child, ToLayoutBlockFlow(layout_box_));
       } else {
         first_child_ = new NGBlockNode(child);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node_test.cc
index 7c70718..d3becbc 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node_test.cc
@@ -18,6 +18,152 @@
   ~NGBlockNodeForTest() { RuntimeEnabledFeatures::setLayoutNGEnabled(false); };
 };
 
+TEST_F(NGBlockNodeForTest, ChildInlineAndBlock) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <div id=container>Hello!<div></div></div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsBlock());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_TRUE(child2 && child2->IsBlock());
+  NGLayoutInputNode* child3 = child2->NextSibling();
+  EXPECT_EQ(child3, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildBlockAndInline) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <div id=container><div></div>Hello!</div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsBlock());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_TRUE(child2 && child2->IsBlock());
+  NGLayoutInputNode* child3 = child2->NextSibling();
+  EXPECT_EQ(child3, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildFloatBeforeBlock) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      float { float: left; }
+    </style>
+    <div id=container><float></float><div></div></div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsBlock());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_TRUE(child2 && child2->IsBlock());
+  NGLayoutInputNode* child3 = child2->NextSibling();
+  EXPECT_EQ(child3, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildFloatBeforeInline) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      float { float: left; }
+    </style>
+    <div id=container><float></float>Hello!</div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsInline());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_EQ(child2, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildFloatAfterInline) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      float { float: left; }
+    </style>
+    <div id=container>Hello<float></float></div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsInline());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_EQ(child2, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildFloatOnly) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      float { float: left; }
+    </style>
+    <div id=container><float></float></div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsBlock());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_EQ(child2, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildFloatWithSpaces) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      float { float: left; }
+    </style>
+    <div id=container>
+      <float></float>
+    </div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsBlock());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_EQ(child2, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildOofBeforeInline) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      oof { position: absolute; }
+    </style>
+    <div id=container><oof></oof>Hello!</div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsInline());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_EQ(child2, nullptr);
+}
+
+TEST_F(NGBlockNodeForTest, ChildOofAfterInline) {
+  SetBodyInnerHTML(R"HTML(
+    <!DOCTYPE html>
+    <style>
+      oof { position: absolute; }
+    </style>
+    <div id=container>Hello!<oof></oof></div>
+  )HTML");
+  NGBlockNode* container =
+      new NGBlockNode(GetLayoutObjectByElementId("container"));
+  NGLayoutInputNode* child1 = container->FirstChild();
+  EXPECT_TRUE(child1 && child1->IsInline());
+  NGLayoutInputNode* child2 = child1->NextSibling();
+  EXPECT_EQ(child2, nullptr);
+}
+
 TEST_F(NGBlockNodeForTest, MinAndMaxContent) {
   SetBodyInnerHTML(R"HTML(
     <div id="box" >
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
index c26d53819..4156e04 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
@@ -418,6 +418,58 @@
   }
 }
 
+void SVGResources::ClearReferencesTo(LayoutSVGResourceContainer* resource) {
+  DCHECK(resource);
+  if (linked_resource_ == resource) {
+    DCHECK(!clipper_filter_masker_data_);
+    DCHECK(!marker_data_);
+    DCHECK(!fill_stroke_data_);
+    linked_resource_ = nullptr;
+    return;
+  }
+
+  switch (resource->ResourceType()) {
+    case kMaskerResourceType:
+      DCHECK(clipper_filter_masker_data_);
+      DCHECK_EQ(clipper_filter_masker_data_->masker, resource);
+      clipper_filter_masker_data_->masker = nullptr;
+      break;
+    case kMarkerResourceType:
+      DCHECK(marker_data_);
+      DCHECK(resource == MarkerStart() || resource == MarkerMid() ||
+             resource == MarkerEnd());
+      if (marker_data_->marker_start == resource)
+        marker_data_->marker_start = nullptr;
+      if (marker_data_->marker_mid == resource)
+        marker_data_->marker_mid = nullptr;
+      if (marker_data_->marker_end == resource)
+        marker_data_->marker_end = nullptr;
+      break;
+    case kPatternResourceType:
+    case kLinearGradientResourceType:
+    case kRadialGradientResourceType:
+      DCHECK(fill_stroke_data_);
+      DCHECK(resource == Fill() || resource == Stroke());
+      if (fill_stroke_data_->fill == resource)
+        fill_stroke_data_->fill = nullptr;
+      if (fill_stroke_data_->stroke == resource)
+        fill_stroke_data_->stroke = nullptr;
+      break;
+    case kFilterResourceType:
+      DCHECK(clipper_filter_masker_data_);
+      DCHECK_EQ(clipper_filter_masker_data_->filter, resource);
+      clipper_filter_masker_data_->filter = nullptr;
+      break;
+    case kClipperResourceType:
+      DCHECK(clipper_filter_masker_data_);
+      DCHECK_EQ(clipper_filter_masker_data_->clipper, resource);
+      clipper_filter_masker_data_->clipper = nullptr;
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
 void SVGResources::BuildSetOfResources(
     HashSet<LayoutSVGResourceContainer*>& set) {
   if (!HasResourceData())
@@ -469,12 +521,6 @@
   clipper_filter_masker_data_->clipper = clipper;
 }
 
-void SVGResources::ResetClipper() {
-  DCHECK(clipper_filter_masker_data_);
-  DCHECK(clipper_filter_masker_data_->clipper);
-  clipper_filter_masker_data_->clipper = nullptr;
-}
-
 void SVGResources::SetFilter(LayoutSVGResourceFilter* filter) {
   if (!filter)
     return;
@@ -487,12 +533,6 @@
   clipper_filter_masker_data_->filter = filter;
 }
 
-void SVGResources::ResetFilter() {
-  DCHECK(clipper_filter_masker_data_);
-  DCHECK(clipper_filter_masker_data_->filter);
-  clipper_filter_masker_data_->filter = nullptr;
-}
-
 void SVGResources::SetMarkerStart(LayoutSVGResourceMarker* marker_start) {
   if (!marker_start)
     return;
@@ -505,12 +545,6 @@
   marker_data_->marker_start = marker_start;
 }
 
-void SVGResources::ResetMarkerStart() {
-  DCHECK(marker_data_);
-  DCHECK(marker_data_->marker_start);
-  marker_data_->marker_start = nullptr;
-}
-
 void SVGResources::SetMarkerMid(LayoutSVGResourceMarker* marker_mid) {
   if (!marker_mid)
     return;
@@ -523,12 +557,6 @@
   marker_data_->marker_mid = marker_mid;
 }
 
-void SVGResources::ResetMarkerMid() {
-  DCHECK(marker_data_);
-  DCHECK(marker_data_->marker_mid);
-  marker_data_->marker_mid = nullptr;
-}
-
 void SVGResources::SetMarkerEnd(LayoutSVGResourceMarker* marker_end) {
   if (!marker_end)
     return;
@@ -541,12 +569,6 @@
   marker_data_->marker_end = marker_end;
 }
 
-void SVGResources::ResetMarkerEnd() {
-  DCHECK(marker_data_);
-  DCHECK(marker_data_->marker_end);
-  marker_data_->marker_end = nullptr;
-}
-
 void SVGResources::SetMasker(LayoutSVGResourceMasker* masker) {
   if (!masker)
     return;
@@ -559,12 +581,6 @@
   clipper_filter_masker_data_->masker = masker;
 }
 
-void SVGResources::ResetMasker() {
-  DCHECK(clipper_filter_masker_data_);
-  DCHECK(clipper_filter_masker_data_->masker);
-  clipper_filter_masker_data_->masker = nullptr;
-}
-
 void SVGResources::SetFill(LayoutSVGResourcePaintServer* fill) {
   if (!fill)
     return;
@@ -575,12 +591,6 @@
   fill_stroke_data_->fill = fill;
 }
 
-void SVGResources::ResetFill() {
-  DCHECK(fill_stroke_data_);
-  DCHECK(fill_stroke_data_->fill);
-  fill_stroke_data_->fill = nullptr;
-}
-
 void SVGResources::SetStroke(LayoutSVGResourcePaintServer* stroke) {
   if (!stroke)
     return;
@@ -591,12 +601,6 @@
   fill_stroke_data_->stroke = stroke;
 }
 
-void SVGResources::ResetStroke() {
-  DCHECK(fill_stroke_data_);
-  DCHECK(fill_stroke_data_->stroke);
-  fill_stroke_data_->stroke = nullptr;
-}
-
 void SVGResources::SetLinkedResource(
     LayoutSVGResourceContainer* linked_resource) {
   if (!linked_resource)
@@ -605,11 +609,6 @@
   linked_resource_ = linked_resource;
 }
 
-void SVGResources::ResetLinkedResource() {
-  DCHECK(linked_resource_);
-  linked_resource_ = nullptr;
-}
-
 #ifndef NDEBUG
 void SVGResources::Dump(const LayoutObject* object) {
   DCHECK(object);
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResources.h b/third_party/WebKit/Source/core/layout/svg/SVGResources.h
index 41af41f5..276203ba 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResources.h
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResources.h
@@ -99,27 +99,15 @@
       LayoutObject*,
       bool mark_for_invalidation = true) const;
   void ResourceDestroyed(LayoutSVGResourceContainer*);
+  void ClearReferencesTo(LayoutSVGResourceContainer*);
 
 #ifndef NDEBUG
   void Dump(const LayoutObject*);
 #endif
 
  private:
-  friend class SVGResourcesCycleSolver;
-
   bool HasResourceData() const;
 
-  // Only used by SVGResourcesCache cycle detection logic
-  void ResetClipper();
-  void ResetFilter();
-  void ResetMarkerStart();
-  void ResetMarkerMid();
-  void ResetMarkerEnd();
-  void ResetMasker();
-  void ResetFill();
-  void ResetStroke();
-  void ResetLinkedResource();
-
   void SetClipper(LayoutSVGResourceClipper*);
   void SetFilter(LayoutSVGResourceFilter*);
   void SetMarkerStart(LayoutSVGResourceMarker*);
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp
index bda16fa1..94986229 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.cpp
@@ -19,14 +19,7 @@
 
 #include "core/layout/svg/SVGResourcesCycleSolver.h"
 
-// Set to a value > 0, to debug the resource cache.
-#define DEBUG_CYCLE_DETECTION 0
-
-#include "core/layout/svg/LayoutSVGResourceClipper.h"
-#include "core/layout/svg/LayoutSVGResourceFilter.h"
-#include "core/layout/svg/LayoutSVGResourceMarker.h"
-#include "core/layout/svg/LayoutSVGResourceMasker.h"
-#include "core/layout/svg/LayoutSVGResourcePaintServer.h"
+#include "core/layout/svg/LayoutSVGResourceContainer.h"
 #include "core/layout/svg/SVGResources.h"
 #include "core/layout/svg/SVGResourcesCache.h"
 
@@ -108,58 +101,10 @@
   for (auto* local_resource : local_resources) {
     if (active_resources_.Contains(local_resource) ||
         ResourceContainsCycles(local_resource))
-      BreakCycle(local_resource);
+      resources_->ClearReferencesTo(local_resource);
   }
 
   active_resources_.Clear();
 }
 
-void SVGResourcesCycleSolver::BreakCycle(
-    LayoutSVGResourceContainer* resource_leading_to_cycle) {
-  DCHECK(resource_leading_to_cycle);
-  if (resource_leading_to_cycle == resources_->LinkedResource()) {
-    resources_->ResetLinkedResource();
-    return;
-  }
-
-  switch (resource_leading_to_cycle->ResourceType()) {
-    case kMaskerResourceType:
-      DCHECK_EQ(resource_leading_to_cycle, resources_->Masker());
-      resources_->ResetMasker();
-      break;
-    case kMarkerResourceType:
-      DCHECK(resource_leading_to_cycle == resources_->MarkerStart() ||
-             resource_leading_to_cycle == resources_->MarkerMid() ||
-             resource_leading_to_cycle == resources_->MarkerEnd());
-      if (resources_->MarkerStart() == resource_leading_to_cycle)
-        resources_->ResetMarkerStart();
-      if (resources_->MarkerMid() == resource_leading_to_cycle)
-        resources_->ResetMarkerMid();
-      if (resources_->MarkerEnd() == resource_leading_to_cycle)
-        resources_->ResetMarkerEnd();
-      break;
-    case kPatternResourceType:
-    case kLinearGradientResourceType:
-    case kRadialGradientResourceType:
-      DCHECK(resource_leading_to_cycle == resources_->Fill() ||
-             resource_leading_to_cycle == resources_->Stroke());
-      if (resources_->Fill() == resource_leading_to_cycle)
-        resources_->ResetFill();
-      if (resources_->Stroke() == resource_leading_to_cycle)
-        resources_->ResetStroke();
-      break;
-    case kFilterResourceType:
-      DCHECK_EQ(resource_leading_to_cycle, resources_->Filter());
-      resources_->ResetFilter();
-      break;
-    case kClipperResourceType:
-      DCHECK_EQ(resource_leading_to_cycle, resources_->Clipper());
-      resources_->ResetClipper();
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.h b/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.h
index 8ce080e..ca02bbe 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.h
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResourcesCycleSolver.h
@@ -44,7 +44,6 @@
 
  private:
   bool ResourceContainsCycles(LayoutSVGResourceContainer*);
-  void BreakCycle(LayoutSVGResourceContainer*);
 
   LayoutObject* layout_object_;
   SVGResources* resources_;
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn
index 393c8b9..c5ec0ea2 100644
--- a/third_party/WebKit/Source/core/loader/BUILD.gn
+++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -79,6 +79,10 @@
     "modulescript/ModuleScriptLoaderClient.h",
     "modulescript/ModuleScriptLoaderRegistry.cpp",
     "modulescript/ModuleScriptLoaderRegistry.h",
+    "modulescript/ModuleTreeLinker.cpp",
+    "modulescript/ModuleTreeLinker.h",
+    "modulescript/ModuleTreeLinkerRegistry.cpp",
+    "modulescript/ModuleTreeLinkerRegistry.h",
     "private/CrossOriginPreflightResultCache.cpp",
     "private/CrossOriginPreflightResultCache.h",
     "private/FrameClientHintsPreferencesContext.cpp",
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
new file mode 100644
index 0000000..470f28b0
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
@@ -0,0 +1,460 @@
+// 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/loader/modulescript/ModuleTreeLinker.h"
+
+#include "bindings/core/v8/ScriptModule.h"
+#include "core/dom/AncestorList.h"
+#include "core/dom/ModuleScript.h"
+#include "core/loader/modulescript/ModuleScriptFetchRequest.h"
+#include "core/loader/modulescript/ModuleTreeLinkerRegistry.h"
+#include "platform/loader/fetch/ResourceLoadingLog.h"
+#include "platform/wtf/HashSet.h"
+
+namespace blink {
+
+ModuleTreeLinker* ModuleTreeLinker::Fetch(
+    const ModuleScriptFetchRequest& request,
+    const AncestorList& ancestor_list,
+    ModuleGraphLevel level,
+    Modulator* modulator,
+    ModuleTreeLinkerRegistry* registry,
+    ModuleTreeClient* client) {
+  AncestorList ancestor_list_with_url = ancestor_list;
+  ancestor_list_with_url.insert(request.Url());
+
+  ModuleTreeLinker* fetcher =
+      new ModuleTreeLinker(ancestor_list_with_url, modulator, registry, client);
+  fetcher->FetchSelf(request, level);
+  return fetcher;
+}
+
+ModuleTreeLinker::ModuleTreeLinker(const AncestorList& ancestor_list_with_url,
+                                   Modulator* modulator,
+                                   ModuleTreeLinkerRegistry* registry,
+                                   ModuleTreeClient* client)
+    : modulator_(modulator),
+      registry_(registry),
+      client_(client),
+      ancestor_list_with_url_(ancestor_list_with_url) {
+  CHECK(modulator);
+  CHECK(registry);
+  CHECK(client);
+}
+
+DEFINE_TRACE(ModuleTreeLinker) {
+  visitor->Trace(modulator_);
+  visitor->Trace(registry_);
+  visitor->Trace(client_);
+  visitor->Trace(module_script_);
+  visitor->Trace(descendants_module_script_);
+  visitor->Trace(dependency_clients_);
+  SingleModuleClient::Trace(visitor);
+}
+
+#if DCHECK_IS_ON()
+const char* ModuleTreeLinker::StateToString(ModuleTreeLinker::State state) {
+  switch (state) {
+    case State::kInitial:
+      return "Initial";
+    case State::kFetchingSelf:
+      return "FetchingSelf";
+    case State::kFetchingDependencies:
+      return "FetchingDependencies";
+    case State::kInstantiating:
+      return "Instantiating";
+    case State::kFinished:
+      return "Finished";
+  }
+  NOTREACHED();
+  return "";
+}
+#endif
+
+void ModuleTreeLinker::AdvanceState(State new_state) {
+#if DCHECK_IS_ON()
+  RESOURCE_LOADING_DVLOG(1)
+      << "ModuleTreeLinker[" << this << "]::advanceState("
+      << StateToString(state_) << " -> " << StateToString(new_state) << ")";
+#endif
+
+  switch (state_) {
+    case State::kInitial:
+      CHECK_EQ(num_incomplete_descendants_, 0u);
+      CHECK_EQ(new_state, State::kFetchingSelf);
+      break;
+    case State::kFetchingSelf:
+      CHECK_EQ(num_incomplete_descendants_, 0u);
+      CHECK(new_state == State::kFetchingDependencies ||
+            (!descendants_module_script_ && new_state == State::kFinished));
+      break;
+    case State::kFetchingDependencies:
+      CHECK_EQ(new_state, State::kInstantiating);
+      DCHECK(!num_incomplete_descendants_ || !descendants_module_script_)
+          << num_incomplete_descendants_
+          << " outstanding descendant loads found, but the descendant module "
+             "script load procedure unexpectedly finished with "
+          << (!!descendants_module_script_ ? "success." : "failure.");
+      break;
+    case State::kInstantiating:
+      CHECK(num_incomplete_descendants_ == 0u || !descendants_module_script_);
+      CHECK_EQ(new_state, State::kFinished);
+      break;
+    case State::kFinished:
+      NOTREACHED();
+      break;
+  }
+
+  state_ = new_state;
+
+  if (state_ == State::kFinished) {
+    registry_->ReleaseFinishedFetcher(this);
+
+    // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+    // Step 8. Asynchronously complete this algorithm with descendants result.
+    client_->NotifyModuleTreeLoadFinished(descendants_module_script_);
+  }
+}
+
+void ModuleTreeLinker::FetchSelf(const ModuleScriptFetchRequest& request,
+                                 ModuleGraphLevel level) {
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+
+  // Step 1. Fetch a single module script given url, fetch client settings
+  // object, destination, cryptographic nonce, parser state, credentials mode,
+  // module map settings object, referrer, and the top-level module fetch flag.
+  // If the caller of this algorithm specified custom perform the fetch steps,
+  // pass those along while fetching a single module script.
+  AdvanceState(State::kFetchingSelf);
+  modulator_->FetchSingle(request, level, this);
+
+  // Step 2. Return from this algorithm, and run the following steps when
+  // fetching a single module script asynchronously completes with result.
+  // Note: Modulator::fetchSingle asynchronously notifies result to
+  // ModuleTreeLinker::notifyModuleLoadFinished().
+}
+
+void ModuleTreeLinker::NotifyModuleLoadFinished(ModuleScript* module_script) {
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+
+  // Step 3. "If result is null, ..."
+  if (!module_script) {
+    // "asynchronously complete this algorithm with null and abort these steps."
+    // Note: The return variable for "internal module script graph fetching
+    // procedure" is descendants_module_script_ per Step 8.
+    DCHECK(!descendants_module_script_);
+    AdvanceState(State::kFinished);
+    return;
+  }
+
+  // Step 4. Otherwise, result is a module script. Fetch the descendants of
+  // result given destination and an ancestor list obtained by appending url to
+  // ancestor list. Wait for fetching the descendants of a module script to
+  // asynchronously complete with descendants result before proceeding to the
+  // next step.
+  module_script_ = module_script;
+
+  FetchDescendants();
+
+  // Note: Step 5- continues in instantiate() method, after
+  // "fetch the descendants of a module script" procedure completes.
+}
+
+class ModuleTreeLinker::DependencyModuleClient
+    : public GarbageCollectedFinalized<
+          ModuleTreeLinker::DependencyModuleClient>,
+      public ModuleTreeClient {
+  USING_GARBAGE_COLLECTED_MIXIN(ModuleTreeLinker::DependencyModuleClient);
+
+ public:
+  static DependencyModuleClient* Create(ModuleTreeLinker* module_tree_linker) {
+    return new DependencyModuleClient(module_tree_linker);
+  }
+  virtual ~DependencyModuleClient() = default;
+
+  DEFINE_INLINE_TRACE() {
+    visitor->Trace(module_tree_linker_);
+    ModuleTreeClient::Trace(visitor);
+  }
+
+ private:
+  DependencyModuleClient(ModuleTreeLinker* module_tree_linker)
+      : module_tree_linker_(module_tree_linker) {
+    CHECK(module_tree_linker);
+  }
+
+  // Implements ModuleTreeClient
+  void NotifyModuleTreeLoadFinished(ModuleScript*) override;
+
+  Member<ModuleTreeLinker> module_tree_linker_;
+};
+
+void ModuleTreeLinker::FetchDescendants() {
+  CHECK(module_script_);
+  AdvanceState(State::kFetchingDependencies);
+
+  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-the-descendants-of-a-module-script
+
+  // Step 1. Let record be module script's module record.
+  ScriptModule record = module_script_->Record();
+
+  // Step 2. If record.[[RequestedModules]] is empty, asynchronously complete
+  // this algorithm with module script.
+  Vector<String> module_requests =
+      modulator_->ModuleRequestsFromScriptModule(record);
+
+  // Step 3. Let urls be a new empty list.
+  HashSet<KURL> urls;
+
+  // Step 4. For each string requested of record.[[RequestedModules]],
+  for (const auto& module_request : module_requests) {
+    // Step 4.1. Let url be the result of resolving a module specifier given
+    // module script and requested.
+    KURL url = Modulator::ResolveModuleSpecifier(module_request,
+                                                 module_script_->BaseURL());
+
+    // Step 4.2. If the result is error: ...
+    if (url.IsNull()) {
+      // Let error be a new TypeError exception.
+      // Report the exception error for module script.
+      // TODO(kouhei): Implement the exception.
+
+      // Abort this algorithm, and asynchronously complete it with null.
+      // Note: The return variable for "internal module script graph fetching
+      // procedure" is descendants_module_script_ per Step 8.
+      DCHECK(!descendants_module_script_);
+      // Note: while we complete "fetch the descendants of a module script"
+      //       algorithm here, we still need to continue to the rest of the
+      //       steps in "internal module script graph fetching procedure"
+      Instantiate();
+      return;
+    }
+
+    // Step 4.3. Otherwise, if ancestor list does not contain url, append url to
+    // urls.
+
+    // Modulator::resolveModuleSpecifier() impl must return either a valid url
+    // or null.
+    CHECK(url.IsValid());
+    if (!ancestor_list_with_url_.Contains(url))
+      urls.insert(url);
+  }
+
+  // Step 5. For each url in urls, perform the internal module script graph
+  // fetching procedure given url, module script's credentials mode, module
+  // script's cryptographic nonce, module script's parser state, destination,
+  // module script's settings object, module script's settings object, ancestor
+  // list, module script's base URL, and with the top-level module fetch flag
+  // unset. If the caller of this algorithm specified custom perform the fetch
+  // steps, pass those along while performing the internal module script graph
+  // fetching procedure.
+  // TODO(kouhei): handle "destination".
+  CHECK_EQ(num_incomplete_descendants_, 0u);
+  if (urls.IsEmpty()) {
+    // Continue to instantiate() to process "internal module script graph
+    // fetching procedure" Step 5-.
+    descendants_module_script_ = module_script_;
+    Instantiate();
+    return;
+  }
+  num_incomplete_descendants_ = urls.size();
+  for (const KURL& url : urls) {
+    DependencyModuleClient* dependency_client =
+        DependencyModuleClient::Create(this);
+    dependency_clients_.insert(dependency_client);
+
+    ModuleScriptFetchRequest request(url, module_script_->Nonce(),
+                                     module_script_->ParserState(),
+                                     module_script_->CredentialsMode(),
+                                     module_script_->BaseURL().GetString());
+    modulator_->FetchTreeInternal(request, ancestor_list_with_url_,
+                                  ModuleGraphLevel::kDependentModuleFetch,
+                                  dependency_client);
+  }
+
+  // Asynchronously continue processing after notifyOneDescendantFinished() is
+  // called m_numIncompleteDescendants times.
+  CHECK_GT(num_incomplete_descendants_, 0u);
+}
+
+void ModuleTreeLinker::DependencyModuleClient::NotifyModuleTreeLoadFinished(
+    ModuleScript* module_script) {
+  DescendantLoad was_success =
+      !!module_script ? DescendantLoad::kSuccess : DescendantLoad::kFailed;
+  module_tree_linker_->NotifyOneDescendantFinished(was_success);
+}
+
+void ModuleTreeLinker::NotifyOneDescendantFinished(DescendantLoad was_success) {
+  CHECK(!descendants_module_script_);
+
+  if (state_ == State::kFinished) {
+    // We may reach here if one of the descendant failed to load, and the other
+    // descendants fetches were in flight.
+    return;
+  }
+  CHECK_EQ(state_, State::kFetchingDependencies);
+
+  CHECK_GT(num_incomplete_descendants_, 0u);
+  --num_incomplete_descendants_;
+
+  // TODO(kouhei): Potential room for optimization. Cancel inflight descendants
+  // fetch if a descendant load failed.
+
+  CHECK(module_script_);
+  RESOURCE_LOADING_DVLOG(1)
+      << "ModuleTreeLinker[" << this << "]::NotifyOneDescendantFinished with "
+      << (was_success == DescendantLoad::kSuccess ? "success. " : "failure. ")
+      << num_incomplete_descendants_ << " remaining descendants.";
+
+  // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-the-descendants-of-a-module-script
+  // Step 5. "... If any of them asynchronously complete with null, then
+  // asynchronously complete this algorithm with null"
+  if (was_success == DescendantLoad::kFailed) {
+    DCHECK(!descendants_module_script_);
+    // Note: while we complete "fetch the descendants of a module script"
+    //       algorithm here, we still need to continue to the rest of the steps
+    //       in "internal module script graph fetching procedure"
+    Instantiate();
+    return;
+  }
+
+  // Step 5. "Wait for all of the internal module script graph fetching
+  // procedure invocations to asynchronously complete..."
+  if (!num_incomplete_descendants_) {
+    descendants_module_script_ = module_script_;
+    Instantiate();
+    return;
+  }
+}
+
+void ModuleTreeLinker::Instantiate() {
+  CHECK(module_script_);
+  AdvanceState(State::kInstantiating);
+
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+
+  // Step 5. Let record be result's module record.
+  ScriptModule record = module_script_->Record();
+
+  // Step 6. Let instantiationStatus be record.ModuleDeclarationInstantiation().
+  // Note: The |error| variable corresponds to spec variable
+  // "instantiationStatus". If |error| is empty, it indicates successful
+  // completion.
+  ScriptValue error = modulator_->InstantiateModule(record);
+
+  // Step 7. For each module script script in result's uninstantiated inclusive
+  // descendant module scripts, perform the following steps:
+  HeapHashSet<Member<ModuleScript>> uninstantiated_set =
+      UninstantiatedInclusiveDescendants();
+  for (const auto& descendant : uninstantiated_set) {
+    if (!error.IsEmpty()) {
+      // Step 7.1. If instantiationStatus is an abrupt completion, then set
+      // script's instantiation state to "errored", its instantiation error to
+      // instantiationStatus.[[Value]], and its module record to null.
+      descendant->SetInstantiationErrorAndClearRecord(error);
+    } else {
+      // Step 7.2. Otherwise, set script's instantiation state to
+      // "instantiated".
+      descendant->SetInstantiationSuccess();
+    }
+  }
+
+  // Step 8. Asynchronously complete this algorithm with descendants result.
+  AdvanceState(State::kFinished);
+}
+
+HeapHashSet<Member<ModuleScript>>
+ModuleTreeLinker::UninstantiatedInclusiveDescendants() {
+  // https://html.spec.whatwg.org/multipage/webappapis.html#uninstantiated-inclusive-descendant-module-scripts
+  // Step 1. Let moduleMap be script's settings object's module map.
+  // Note: Modulator is our "settings object".
+  // Note: We won't reference the ModuleMap directly here to aid testing.
+
+  // Step 2. Let stack be the stack « script ».
+  // TODO(kouhei): Make stack a HeapLinkedHashSet for O(1) lookups.
+  HeapDeque<Member<ModuleScript>> stack;
+  stack.push_front(module_script_);
+
+  // Step 3. Let inclusive descendants be an empty set.
+  // Note: We use unordered set here as the order is not observable from web
+  // platform.
+  // This is allowed per spec: https://infra.spec.whatwg.org/#sets
+  HeapHashSet<Member<ModuleScript>> inclusive_descendants;
+
+  // Step 4. While stack is not empty:
+  while (!stack.IsEmpty()) {
+    // Step 4.1. Let current the result of popping from stack.
+    ModuleScript* current = stack.TakeFirst();
+
+    // Step 4.2. Assert: current is a module script (i.e., it is not "fetching"
+    // or null).
+    DCHECK(current);
+
+    // Step 4.3. If inclusive descendants and stack both do not contain current,
+    // then:
+    if (inclusive_descendants.Contains(current))
+      continue;
+    if (std::find(stack.begin(), stack.end(), current) != stack.end())
+      continue;
+
+    // Step 4.3.1. Append current to inclusive descendants.
+    inclusive_descendants.insert(current);
+
+    // TODO(kouhei): This implementation is a direct transliteration of the
+    // spec. Omit intermediate vectors at the least.
+
+    // Step 4.3.2. Let child specifiers be the value of current's module
+    // record's [[RequestedModules]] internal slot.
+    Vector<String> child_specifiers =
+        modulator_->ModuleRequestsFromScriptModule(current->Record());
+    // Step 4.3.3. Let child URLs be the list obtained by calling resolve a
+    // module specifier once for each item of child specifiers, given current
+    // and that item. Omit any failures.
+    Vector<KURL> child_urls;
+    for (const auto& child_specifier : child_specifiers) {
+      KURL child_url = modulator_->ResolveModuleSpecifier(child_specifier,
+                                                          current->BaseURL());
+      if (child_url.IsValid())
+        child_urls.push_back(child_url);
+    }
+    // Step 4.3.4. Let child modules be the list obtained by getting each value
+    // in moduleMap whose key is given by an item of child URLs.
+    HeapVector<Member<ModuleScript>> child_modules;
+    for (const auto& child_url : child_urls) {
+      ModuleScript* module_script =
+          modulator_->GetFetchedModuleScript(child_url);
+
+      child_modules.push_back(module_script);
+    }
+    // Step 4.3.5. For each s of child modules:
+    for (const auto& s : child_modules) {
+      // Step 4.3.5.2. If s is null, continue.
+      // Note: We do null check first, as Blink HashSet can't contain nullptr.
+      // Step 4.3.5.3. Assert: s is a module script (i.e., it is not "fetching",
+      // since by this point all child modules must have been fetched). Note:
+      // GetFetchedModuleScript returns nullptr if "fetching"
+      if (!s)
+        continue;
+
+      // Step 4.3.5.1. If inclusive descendants already contains s, continue.
+      if (inclusive_descendants.Contains(s))
+        continue;
+
+      // Step 4.3.5.4. Push s onto satck.
+      stack.push_front(s);
+    }
+  }
+
+  // Step 5. Return a set containing all items of inclusive descendants whose
+  // instantiation state is "uninstantiated".
+  HeapHashSet<Member<ModuleScript>> uninstantiated_set;
+  for (const auto& script : inclusive_descendants) {
+    if (script->InstantiationState() ==
+        ModuleInstantiationState::kUninstantiated)
+      uninstantiated_set.insert(script);
+  }
+  return uninstantiated_set;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.h b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.h
new file mode 100644
index 0000000..6fdd1a1
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.h
@@ -0,0 +1,94 @@
+// 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 ModuleTreeLinker_h
+#define ModuleTreeLinker_h
+
+#include "core/CoreExport.h"
+#include "core/dom/AncestorList.h"
+#include "core/dom/Modulator.h"
+
+namespace blink {
+
+class ModuleScriptFetchRequest;
+enum class ModuleGraphLevel;
+class ModuleTreeLinkerRegistry;
+
+// A ModuleTreeLinker is responsible for running and keeping intermediate states
+// for "internal module script graph fetching procedure" for a module graph tree
+// node.
+// https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+class CORE_EXPORT ModuleTreeLinker final
+    : public GarbageCollectedFinalized<ModuleTreeLinker>,
+      public SingleModuleClient {
+  USING_GARBAGE_COLLECTED_MIXIN(ModuleTreeLinker);
+
+ public:
+  static ModuleTreeLinker* Fetch(const ModuleScriptFetchRequest&,
+                                 const AncestorList&,
+                                 ModuleGraphLevel,
+                                 Modulator*,
+                                 ModuleTreeLinkerRegistry*,
+                                 ModuleTreeClient*);
+  virtual ~ModuleTreeLinker() = default;
+  DECLARE_TRACE();
+
+  bool IsFetching() const {
+    return State::kFetchingSelf <= state_ && state_ < State::kFinished;
+  }
+  bool HasFinished() const { return state_ == State::kFinished; }
+
+ private:
+  ModuleTreeLinker(const AncestorList& ancestor_list_with_url,
+                   Modulator*,
+                   ModuleTreeLinkerRegistry*,
+                   ModuleTreeClient*);
+
+  enum class State {
+    kInitial,
+    // Running fetch of the module script corresponding to the target node.
+    kFetchingSelf,
+    // Running fetch of descendants of the target node.
+    kFetchingDependencies,
+    // Instantiating m_moduleScript and the node descendants.
+    kInstantiating,
+    kFinished,
+  };
+#if DCHECK_IS_ON()
+  static const char* StateToString(State);
+#endif
+  void AdvanceState(State);
+
+  void FetchSelf(const ModuleScriptFetchRequest&, ModuleGraphLevel);
+  // Implements SingleModuleClient
+  void NotifyModuleLoadFinished(ModuleScript*) override;
+
+  void FetchDescendants();
+  enum class DescendantLoad { kFailed, kSuccess };
+  void NotifyOneDescendantFinished(DescendantLoad was_success);
+
+  void Instantiate();
+  HeapHashSet<Member<ModuleScript>> UninstantiatedInclusiveDescendants();
+
+  class DependencyModuleClient;
+  friend class DependencyModuleClient;
+
+  Member<Modulator> modulator_;
+  Member<ModuleTreeLinkerRegistry> registry_;
+  Member<ModuleTreeClient> client_;
+  HashSet<KURL> ancestor_list_with_url_;
+  State state_ = State::kInitial;
+  // Correspond to _result_ in
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+  Member<ModuleScript> module_script_;
+  // Correspond to _descendants result_ in
+  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
+  Member<ModuleScript> descendants_module_script_;
+  size_t num_incomplete_descendants_ = 0;
+  HeapHashSet<Member<DependencyModuleClient>> dependency_clients_;
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp
new file mode 100644
index 0000000..7c9c6669b
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/loader/modulescript/ModuleTreeLinkerRegistry.h"
+
+#include "core/loader/modulescript/ModuleTreeLinker.h"
+#include "platform/weborigin/KURL.h"
+#include "platform/weborigin/KURLHash.h"
+
+namespace blink {
+
+DEFINE_TRACE(ModuleTreeLinkerRegistry) {
+  visitor->Trace(active_tree_linkers_);
+}
+
+ModuleTreeLinker* ModuleTreeLinkerRegistry::Fetch(
+    const ModuleScriptFetchRequest& request,
+    const AncestorList& ancestor_list,
+    ModuleGraphLevel level,
+    Modulator* modulator,
+    ModuleTreeClient* client) {
+  ModuleTreeLinker* fetcher = ModuleTreeLinker::Fetch(
+      request, ancestor_list, level, modulator, this, client);
+  DCHECK(fetcher->IsFetching());
+  active_tree_linkers_.insert(fetcher);
+  return fetcher;
+}
+
+void ModuleTreeLinkerRegistry::ReleaseFinishedFetcher(
+    ModuleTreeLinker* fetcher) {
+  DCHECK(fetcher->HasFinished());
+
+  auto it = active_tree_linkers_.Find(fetcher);
+  DCHECK_NE(it, active_tree_linkers_.end());
+  active_tree_linkers_.erase(it);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h
new file mode 100644
index 0000000..a038896
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ModuleTreeLinkerRegistry_h
+#define ModuleTreeLinkerRegistry_h
+
+#include "core/CoreExport.h"
+#include "core/dom/AncestorList.h"
+#include "platform/heap/Handle.h"
+
+namespace blink {
+
+class Modulator;
+class ModuleScriptFetchRequest;
+class ModuleTreeClient;
+class ModuleTreeLinker;
+enum class ModuleGraphLevel;
+
+// ModuleTreeLinkerRegistry keeps active ModuleTreeLinkers alive.
+class CORE_EXPORT ModuleTreeLinkerRegistry
+    : public GarbageCollected<ModuleTreeLinkerRegistry> {
+ public:
+  static ModuleTreeLinkerRegistry* Create() {
+    return new ModuleTreeLinkerRegistry;
+  }
+  DECLARE_TRACE();
+
+  ModuleTreeLinker* Fetch(const ModuleScriptFetchRequest&,
+                          const AncestorList&,
+                          ModuleGraphLevel,
+                          Modulator*,
+                          ModuleTreeClient*);
+
+ private:
+  ModuleTreeLinkerRegistry() = default;
+
+  friend class ModuleTreeLinker;
+  void ReleaseFinishedFetcher(ModuleTreeLinker*);
+
+  HeapHashSet<Member<ModuleTreeLinker>> active_tree_linkers_;
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
new file mode 100644
index 0000000..ef8355dc
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
@@ -0,0 +1,451 @@
+// 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/loader/modulescript/ModuleTreeLinker.h"
+
+#include "bindings/core/v8/ScriptModule.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8BindingForTesting.h"
+#include "bindings/core/v8/V8ThrowException.h"
+#include "core/dom/Modulator.h"
+#include "core/dom/ModuleScript.h"
+#include "core/loader/modulescript/ModuleScriptFetchRequest.h"
+#include "core/loader/modulescript/ModuleTreeLinkerRegistry.h"
+#include "core/testing/DummyModulator.h"
+#include "core/testing/DummyPageHolder.h"
+#include "platform/heap/Handle.h"
+#include "platform/weborigin/KURL.h"
+#include "platform/wtf/text/StringBuilder.h"
+#include "public/platform/Platform.h"
+#include "public/platform/scheduler/renderer/renderer_scheduler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+namespace {
+
+class TestModuleTreeClient final
+    : public GarbageCollectedFinalized<TestModuleTreeClient>,
+      public ModuleTreeClient {
+  USING_GARBAGE_COLLECTED_MIXIN(TestModuleTreeClient);
+
+ public:
+  TestModuleTreeClient() = default;
+
+  DEFINE_INLINE_TRACE() { visitor->Trace(module_script_); }
+
+  void NotifyModuleTreeLoadFinished(ModuleScript* module_script) override {
+    was_notify_finished_ = true;
+    module_script_ = module_script;
+  }
+
+  bool WasNotifyFinished() const { return was_notify_finished_; }
+  ModuleScript* GetModuleScript() { return module_script_; }
+
+ private:
+  bool was_notify_finished_ = false;
+  Member<ModuleScript> module_script_;
+};
+
+class ModuleTreeLinkerTestModulator final : public DummyModulator {
+ public:
+  ModuleTreeLinkerTestModulator(RefPtr<ScriptState> script_state)
+      : script_state_(std::move(script_state)) {}
+  ~ModuleTreeLinkerTestModulator() override {}
+
+  DECLARE_TRACE();
+
+  enum class ResolveResult { kFailure, kSuccess };
+
+  // Resolve last |Modulator::FetchSingle()| call.
+  ModuleScript* ResolveSingleModuleScriptFetch(
+      const KURL& url,
+      const Vector<String>& dependency_module_requests) {
+    ScriptState::Scope scope(script_state_.Get());
+
+    StringBuilder source_text;
+    for (const auto& request : dependency_module_requests) {
+      source_text.Append("import '");
+      source_text.Append(request);
+      source_text.Append("';\n");
+    }
+    source_text.Append("export default 'grapes';");
+
+    ScriptModule script_module = ScriptModule::Compile(
+        script_state_->GetIsolate(), source_text.ToString(), url.GetString(),
+        kSharableCrossOrigin);
+    ModuleScript* module_script =
+        ModuleScript::Create(this, script_module, url, "", kParserInserted,
+                             WebURLRequest::kFetchCredentialsModeOmit);
+    auto result_request = dependency_module_requests_map_.insert(
+        script_module, dependency_module_requests);
+    EXPECT_TRUE(result_request.is_new_entry);
+    auto result_map = module_map_.insert(url, module_script);
+    EXPECT_TRUE(result_map.is_new_entry);
+
+    EXPECT_EQ(url, pending_request_url_);
+    EXPECT_TRUE(pending_client_);
+    pending_client_->NotifyModuleLoadFinished(module_script);
+    pending_client_.Clear();
+
+    return module_script;
+  }
+
+  // Get AncestorList specified in |Modulator::FetchTreeInternal()| call for
+  // request matching |url|.
+  AncestorList GetAncestorListForTreeFetch(const KURL& url) const {
+    const auto& it = pending_tree_ancestor_list_.Find(url);
+    if (it == pending_tree_ancestor_list_.end())
+      return AncestorList();
+    return it->value;
+  }
+
+  // Resolve |Modulator::FetchTreeInternal()| for given url.
+  void ResolveDependentTreeFetch(const KURL& url, ResolveResult result) {
+    const auto& it = pending_tree_client_map_.Find(url);
+    EXPECT_NE(pending_tree_client_map_.end(), it);
+    auto pending_client = it->value;
+    EXPECT_TRUE(pending_client);
+    pending_tree_client_map_.erase(it);
+
+    if (result == ResolveResult::kFailure) {
+      pending_client->NotifyModuleTreeLoadFinished(nullptr);
+      return;
+    }
+    EXPECT_EQ(ResolveResult::kSuccess, result);
+
+    ScriptState::Scope scope(script_state_.Get());
+
+    ScriptModule script_module = ScriptModule::Compile(
+        script_state_->GetIsolate(), "export default 'pineapples';",
+        url.GetString(), kSharableCrossOrigin);
+    ModuleScript* module_script =
+        ModuleScript::Create(this, script_module, url, "", kParserInserted,
+                             WebURLRequest::kFetchCredentialsModeOmit);
+    auto result_map = module_map_.insert(url, module_script);
+    EXPECT_TRUE(result_map.is_new_entry);
+
+    pending_client->NotifyModuleTreeLoadFinished(module_script);
+  }
+
+  void SetInstantiateShouldFail(bool b) { instantiate_should_fail_ = b; }
+
+ private:
+  // Implements Modulator:
+
+  void FetchSingle(const ModuleScriptFetchRequest& request,
+                   ModuleGraphLevel,
+                   SingleModuleClient* client) override {
+    pending_request_url_ = request.Url();
+    EXPECT_FALSE(pending_client_);
+    pending_client_ = client;
+  }
+
+  void FetchTreeInternal(const ModuleScriptFetchRequest& request,
+                         const AncestorList& list,
+                         ModuleGraphLevel level,
+                         ModuleTreeClient* client) override {
+    const auto& url = request.Url();
+
+    auto ancestor_result = pending_tree_ancestor_list_.insert(url, list);
+    EXPECT_TRUE(ancestor_result.is_new_entry);
+
+    EXPECT_EQ(ModuleGraphLevel::kDependentModuleFetch, level);
+
+    auto result_map = pending_tree_client_map_.insert(url, client);
+    EXPECT_TRUE(result_map.is_new_entry);
+  }
+
+  ModuleScript* GetFetchedModuleScript(const KURL& url) override {
+    const auto& it = module_map_.Find(url);
+    if (it == module_map_.end())
+      return nullptr;
+
+    return it->value;
+  }
+
+  ScriptValue InstantiateModule(ScriptModule) override {
+    if (instantiate_should_fail_) {
+      ScriptState::Scope scope(script_state_.Get());
+      v8::Local<v8::Value> error = V8ThrowException::CreateError(
+          script_state_->GetIsolate(), "Instantiation failure.");
+      return ScriptValue(script_state_.Get(), error);
+    }
+    return ScriptValue();
+  }
+
+  Vector<String> ModuleRequestsFromScriptModule(
+      ScriptModule script_module) override {
+    const auto& it = dependency_module_requests_map_.Find(script_module);
+    if (it == dependency_module_requests_map_.end())
+      return Vector<String>();
+
+    return it->value;
+  }
+
+  RefPtr<ScriptState> script_state_;
+  KURL pending_request_url_;
+  Member<SingleModuleClient> pending_client_;
+  HashMap<ScriptModule, Vector<String>> dependency_module_requests_map_;
+  HeapHashMap<KURL, Member<ModuleScript>> module_map_;
+  HeapHashMap<KURL, Member<ModuleTreeClient>> pending_tree_client_map_;
+  HashMap<KURL, AncestorList> pending_tree_ancestor_list_;
+  bool instantiate_should_fail_ = false;
+};
+
+DEFINE_TRACE(ModuleTreeLinkerTestModulator) {
+  visitor->Trace(pending_client_);
+  visitor->Trace(module_map_);
+  visitor->Trace(pending_tree_client_map_);
+  DummyModulator::Trace(visitor);
+}
+
+}  // namespace
+
+class ModuleTreeLinkerTest : public ::testing::Test {
+  DISALLOW_COPY_AND_ASSIGN(ModuleTreeLinkerTest);
+
+ public:
+  ModuleTreeLinkerTest() = default;
+  void SetUp() override;
+
+  ModuleTreeLinkerTestModulator* GetModulator() { return modulator_.Get(); }
+
+ protected:
+  std::unique_ptr<DummyPageHolder> dummy_page_holder_;
+  Persistent<ModuleTreeLinkerTestModulator> modulator_;
+};
+
+void ModuleTreeLinkerTest::SetUp() {
+  dummy_page_holder_ = DummyPageHolder::Create(IntSize(500, 500));
+  RefPtr<ScriptState> script_state =
+      ToScriptStateForMainWorld(&dummy_page_holder_->GetFrame());
+  modulator_ = new ModuleTreeLinkerTestModulator(script_state);
+}
+
+TEST_F(ModuleTreeLinkerTest, fetchTreeNoDeps) {
+  ModuleTreeLinkerRegistry* registry = ModuleTreeLinkerRegistry::Create();
+
+  KURL url(kParsedURLString, "http://example.com/root.js");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleTreeClient* client = new TestModuleTreeClient;
+  registry->Fetch(module_request, AncestorList(),
+                  ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
+                  client);
+
+  EXPECT_FALSE(client->WasNotifyFinished())
+      << "ModuleTreeLinker should always finish asynchronously.";
+  EXPECT_FALSE(client->GetModuleScript());
+
+  GetModulator()->ResolveSingleModuleScriptFetch(url, {});
+  EXPECT_TRUE(client->WasNotifyFinished());
+  ASSERT_TRUE(client->GetModuleScript());
+  EXPECT_EQ(client->GetModuleScript()->InstantiationState(),
+            ModuleInstantiationState::kInstantiated);
+}
+
+TEST_F(ModuleTreeLinkerTest, fetchTreeInstantiationFailure) {
+  GetModulator()->SetInstantiateShouldFail(true);
+
+  ModuleTreeLinkerRegistry* registry = ModuleTreeLinkerRegistry::Create();
+
+  KURL url(kParsedURLString, "http://example.com/root.js");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleTreeClient* client = new TestModuleTreeClient;
+  registry->Fetch(module_request, AncestorList(),
+                  ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
+                  client);
+
+  EXPECT_FALSE(client->WasNotifyFinished())
+      << "ModuleTreeLinker should always finish asynchronously.";
+  EXPECT_FALSE(client->GetModuleScript());
+
+  GetModulator()->ResolveSingleModuleScriptFetch(url, {});
+  EXPECT_TRUE(client->WasNotifyFinished());
+  ASSERT_TRUE(client->GetModuleScript());
+  EXPECT_EQ(client->GetModuleScript()->InstantiationState(),
+            ModuleInstantiationState::kErrored);
+}
+
+TEST_F(ModuleTreeLinkerTest, fetchTreeWithSingleDependency) {
+  ModuleTreeLinkerRegistry* registry = ModuleTreeLinkerRegistry::Create();
+
+  KURL url(kParsedURLString, "http://example.com/root.js");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleTreeClient* client = new TestModuleTreeClient;
+  registry->Fetch(module_request, AncestorList(),
+                  ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
+                  client);
+
+  EXPECT_FALSE(client->WasNotifyFinished())
+      << "ModuleTreeLinker should always finish asynchronously.";
+  EXPECT_FALSE(client->GetModuleScript());
+
+  GetModulator()->ResolveSingleModuleScriptFetch(url, {"./dep1.js"});
+  EXPECT_FALSE(client->WasNotifyFinished());
+
+  KURL url_dep1(kParsedURLString, "http://example.com/dep1.js");
+  auto ancestor_list = GetModulator()->GetAncestorListForTreeFetch(url_dep1);
+  EXPECT_EQ(1u, ancestor_list.size());
+  EXPECT_TRUE(ancestor_list.Contains(
+      KURL(kParsedURLString, "http://example.com/root.js")));
+
+  GetModulator()->ResolveDependentTreeFetch(
+      url_dep1, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+  EXPECT_TRUE(client->WasNotifyFinished());
+
+  ASSERT_TRUE(client->GetModuleScript());
+  EXPECT_EQ(client->GetModuleScript()->InstantiationState(),
+            ModuleInstantiationState::kInstantiated);
+}
+
+TEST_F(ModuleTreeLinkerTest, fetchTreeWith3Deps) {
+  ModuleTreeLinkerRegistry* registry = ModuleTreeLinkerRegistry::Create();
+
+  KURL url(kParsedURLString, "http://example.com/root.js");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleTreeClient* client = new TestModuleTreeClient;
+  registry->Fetch(module_request, AncestorList(),
+                  ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
+                  client);
+
+  EXPECT_FALSE(client->WasNotifyFinished())
+      << "ModuleTreeLinker should always finish asynchronously.";
+  EXPECT_FALSE(client->GetModuleScript());
+
+  GetModulator()->ResolveSingleModuleScriptFetch(
+      url, {"./dep1.js", "./dep2.js", "./dep3.js"});
+  EXPECT_FALSE(client->WasNotifyFinished());
+
+  Vector<KURL> url_deps;
+  for (int i = 1; i <= 3; ++i) {
+    StringBuilder url_dep_str;
+    url_dep_str.Append("http://example.com/dep");
+    url_dep_str.AppendNumber(i);
+    url_dep_str.Append(".js");
+
+    KURL url_dep(kParsedURLString, url_dep_str.ToString());
+    url_deps.push_back(url_dep);
+  }
+
+  for (const auto& url_dep : url_deps) {
+    SCOPED_TRACE(url_dep.GetString());
+    auto ancestor_list = GetModulator()->GetAncestorListForTreeFetch(url_dep);
+    EXPECT_EQ(1u, ancestor_list.size());
+    EXPECT_TRUE(ancestor_list.Contains(
+        KURL(kParsedURLString, "http://example.com/root.js")));
+  }
+
+  for (const auto& url_dep : url_deps) {
+    EXPECT_FALSE(client->WasNotifyFinished());
+    GetModulator()->ResolveDependentTreeFetch(
+        url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+  }
+
+  EXPECT_TRUE(client->WasNotifyFinished());
+  ASSERT_TRUE(client->GetModuleScript());
+  EXPECT_EQ(client->GetModuleScript()->InstantiationState(),
+            ModuleInstantiationState::kInstantiated);
+}
+
+TEST_F(ModuleTreeLinkerTest, fetchTreeWith3Deps1Fail) {
+  ModuleTreeLinkerRegistry* registry = ModuleTreeLinkerRegistry::Create();
+
+  KURL url(kParsedURLString, "http://example.com/root.js");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleTreeClient* client = new TestModuleTreeClient;
+  registry->Fetch(module_request, AncestorList(),
+                  ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
+                  client);
+
+  EXPECT_FALSE(client->WasNotifyFinished())
+      << "ModuleTreeLinker should always finish asynchronously.";
+  EXPECT_FALSE(client->GetModuleScript());
+
+  GetModulator()->ResolveSingleModuleScriptFetch(
+      url, {"./dep1.js", "./dep2.js", "./dep3.js"});
+  EXPECT_FALSE(client->WasNotifyFinished());
+
+  Vector<KURL> url_deps;
+  for (int i = 1; i <= 3; ++i) {
+    StringBuilder url_dep_str;
+    url_dep_str.Append("http://example.com/dep");
+    url_dep_str.AppendNumber(i);
+    url_dep_str.Append(".js");
+
+    KURL url_dep(kParsedURLString, url_dep_str.ToString());
+    url_deps.push_back(url_dep);
+  }
+
+  for (const auto& url_dep : url_deps) {
+    SCOPED_TRACE(url_dep.GetString());
+    auto ancestor_list = GetModulator()->GetAncestorListForTreeFetch(url_dep);
+    EXPECT_EQ(1u, ancestor_list.size());
+    EXPECT_TRUE(ancestor_list.Contains(
+        KURL(kParsedURLString, "http://example.com/root.js")));
+  }
+
+  auto url_dep = url_deps.back();
+  url_deps.pop_back();
+  GetModulator()->ResolveDependentTreeFetch(
+      url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+  EXPECT_FALSE(client->WasNotifyFinished());
+  url_dep = url_deps.back();
+  url_deps.pop_back();
+  GetModulator()->ResolveDependentTreeFetch(
+      url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kFailure);
+
+  EXPECT_TRUE(client->WasNotifyFinished());
+  EXPECT_FALSE(client->GetModuleScript());
+
+  // Check below doesn't crash.
+  url_dep = url_deps.back();
+  url_deps.pop_back();
+  GetModulator()->ResolveDependentTreeFetch(
+      url_dep, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+  EXPECT_TRUE(url_deps.IsEmpty());
+}
+
+TEST_F(ModuleTreeLinkerTest, fetchDependencyTree) {
+  ModuleTreeLinkerRegistry* registry = ModuleTreeLinkerRegistry::Create();
+
+  KURL url(kParsedURLString, "http://example.com/depth1.js");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleTreeClient* client = new TestModuleTreeClient;
+  registry->Fetch(
+      module_request,
+      AncestorList{KURL(kParsedURLString, "http://example.com/root.js")},
+      ModuleGraphLevel::kDependentModuleFetch, GetModulator(), client);
+
+  EXPECT_FALSE(client->WasNotifyFinished())
+      << "ModuleTreeLinker should always finish asynchronously.";
+  EXPECT_FALSE(client->GetModuleScript());
+
+  GetModulator()->ResolveSingleModuleScriptFetch(url, {"./depth2.js"});
+
+  KURL url_dep2(kParsedURLString, "http://example.com/depth2.js");
+  auto ancestor_list = GetModulator()->GetAncestorListForTreeFetch(url_dep2);
+  EXPECT_EQ(2u, ancestor_list.size());
+  EXPECT_TRUE(ancestor_list.Contains(
+      KURL(kParsedURLString, "http://example.com/root.js")));
+  EXPECT_TRUE(ancestor_list.Contains(
+      KURL(kParsedURLString, "http://example.com/depth1.js")));
+
+  GetModulator()->ResolveDependentTreeFetch(
+      url_dep2, ModuleTreeLinkerTestModulator::ResolveResult::kSuccess);
+
+  EXPECT_TRUE(client->WasNotifyFinished());
+  ASSERT_TRUE(client->GetModuleScript());
+  EXPECT_EQ(client->GetModuleScript()->InstantiationState(),
+            ModuleInstantiationState::kInstantiated);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/page/EventWithHitTestResults.h b/third_party/WebKit/Source/core/page/EventWithHitTestResults.h
index 0b1c2f44..c967ea65 100644
--- a/third_party/WebKit/Source/core/page/EventWithHitTestResults.h
+++ b/third_party/WebKit/Source/core/page/EventWithHitTestResults.h
@@ -47,6 +47,7 @@
     return hit_test_result_.IsOverFrameViewBase();
   }
   Node* InnerNode() const { return hit_test_result_.InnerNode(); }
+  Element* InnerElement() const { return hit_test_result_.InnerElement(); }
   const String& CanvasRegionId() const {
     return hit_test_result_.CanvasRegionId();
   }
diff --git a/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp b/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp
index fdb7993..f0fae6b 100644
--- a/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/HTMLCanvasPainterTest.cpp
@@ -59,7 +59,7 @@
     return AdoptRef(new Canvas2DLayerBridge(
         WTF::WrapUnique(new FakeWebGraphicsContext3DProvider(&gl_)), size, 0,
         kNonOpaque, Canvas2DLayerBridge::kForceAccelerationForTesting,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType));
+        CanvasColorParams()));
   }
 
  private:
diff --git a/third_party/WebKit/Source/core/streams/WritableStream.js b/third_party/WebKit/Source/core/streams/WritableStream.js
index 4a4429c..f12192b 100644
--- a/third_party/WebKit/Source/core/streams/WritableStream.js
+++ b/third_party/WebKit/Source/core/streams/WritableStream.js
@@ -41,14 +41,16 @@
   const _strategySize = v8.createPrivateSymbol('[[strategySize]]');
   const _underlyingSink = v8.createPrivateSymbol('[[underlyingSink]]');
 
-  // Numeric encodings of states
+  // Numeric encodings of stream states. Stored in the _stateAndFlags slot.
   const WRITABLE = 0;
   const CLOSED = 1;
-  const ERRORED = 2;
+  const ERRORING = 2;
+  const ERRORED = 3;
 
-  // Mask to extract or assign states to _stateAndFlags
+  // Mask to extract or assign states to _stateAndFlags.
   const STATE_MASK = 0xF;
 
+  // Also stored in _stateAndFlags.
   const BACKPRESSURE_FLAG = 0x10;
 
   // Javascript functions. It is important to use these copies, as the ones on
@@ -105,8 +107,8 @@
 
   const stateNames = {[CLOSED]: 'closed', [ERRORED]: 'errored'};
   function createCannotActionOnStateStreamError(action, state) {
-    TEMP_ASSERT(stateNames[state] !== undefined,
-                `name for state ${state} exists in stateNames`);
+    // assert(stateNames[state] !== undefined,
+    //        `name for state ${state} exists in stateNames`);
     return new TypeError(
         templateErrorCannotActionOnStateStream(action, stateNames[state]));
   }
@@ -115,27 +117,6 @@
     queue.forEach(promise => v8.rejectPromise(promise, e));
   }
 
-  // https://tc39.github.io/ecma262/#sec-ispropertykey
-  // TODO(ricea): Remove this when the asserts using it are removed.
-  function IsPropertyKey(argument) {
-    return typeof argument === 'string' || typeof argument === 'symbol';
-  }
-
-  // TODO(ricea): Remove all asserts once the implementation has stabilised.
-  function TEMP_ASSERT(predicate, message) {
-    if (predicate) {
-      return;
-    }
-    v8.log(`Assertion failed: ${message}\n`);
-    v8.logStackTrace();
-    class WritableStreamInternalError extends Error {
-      constructor(message) {
-        super(message);
-      }
-    }
-    throw new WritableStreamInternalError(message);
-  }
-
   class WritableStream {
     constructor(underlyingSink = {}, { size, highWaterMark = 1 } = {}) {
       this[_stateAndFlags] = WRITABLE;
@@ -193,8 +174,8 @@
   }
 
   function IsWritableStreamLocked(stream) {
-    TEMP_ASSERT(IsWritableStream(stream),
-                '! IsWritableStream(stream) is true.');
+    // assert(IsWritableStream(stream),
+    //        '! IsWritableStream(stream) is true.');
     return stream[_writer] !== undefined;
   }
 
@@ -206,136 +187,184 @@
     if (state === ERRORED) {
       return Promise_reject(stream[_storedError]);
     }
-    TEMP_ASSERT(state === WRITABLE,
-               'state is "writable".');
     const error = new TypeError(errStreamAborting);
     if (stream[_pendingAbortRequest] !== undefined) {
       return Promise_reject(error);
     }
 
-    const controller = stream[_writableStreamController];
-    TEMP_ASSERT(controller !== undefined,
-                'controller is not undefined');
-    if (!WritableStreamHasOperationMarkedInFlight(stream) &&
-        controller[_started]) {
-      WritableStreamFinishAbort(stream);
-      return WritableStreamDefaultControllerAbortSteps(controller, reason);
+    // assert(state === WRITABLE || state === ERRORING,
+    //        '_state_ is `"writable"` or `"erroring"`');
+
+    const wasAlreadyErroring = state === ERRORING;
+    if (wasAlreadyErroring) {
+      reason = undefined;
     }
-    const writer = stream[_writer];
-    if (writer !== undefined) {
-      WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error);
-    }
+
     const promise = v8.createPromise();
-    stream[_pendingAbortRequest] = {promise, reason};
+    stream[_pendingAbortRequest] = {promise, reason, wasAlreadyErroring};
+
+    if (!wasAlreadyErroring) {
+      WritableStreamStartErroring(stream, error);
+    }
     return promise;
   }
 
-  function WritableStreamError(stream, error) {
-    stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORED;
-    stream[_storedError] = error;
-    WritableStreamDefaultControllerErrorSteps(stream[_writableStreamController]);
-    if (stream[_pendingAbortRequest] === undefined) {
-      const writer = stream[_writer];
-      if (writer !== undefined) {
-        WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error);
-      }
-    }
-    if (!WritableStreamHasOperationMarkedInFlight(stream)) {
-      WritableStreamRejectPromisesInReactionToError(stream);
-    }
-  }
-
-  function WritableStreamFinishAbort(stream) {
-    const error = new TypeError(errStreamAborted);
-    WritableStreamError(stream, error);
-  }
-
   // Writable Stream Abstract Operations Used by Controllers
 
   function WritableStreamAddWriteRequest(stream) {
-    TEMP_ASSERT(IsWritableStreamLocked(stream),
-                '! IsWritableStreamLocked(writer) is true.');
-    TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
-                'stream.[[state]] is "writable".');
+    // assert(IsWritableStreamLocked(stream),
+    //        '! IsWritableStreamLocked(writer) is true.');
+    // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
+    //        'stream.[[state]] is "writable".');
     const promise = v8.createPromise();
     stream[_writeRequests].push(promise);
     return promise;
   }
 
-  function WritableStreamFinishInFlightWrite(stream) {
-    TEMP_ASSERT(stream[_inFlightWriteRequest] !== undefined,
-                '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
-    v8.resolvePromise(stream[_inFlightWriteRequest], undefined);
-    stream[_inFlightWriteRequest] = undefined;
+  function WritableStreamDealWithRejection(stream, error) {
     const state = stream[_stateAndFlags] & STATE_MASK;
-    if (state === ERRORED) {
-      WritableStreamFinishInFlightWriteInErroredState(stream);
+    if (state === WRITABLE) {
+      WritableStreamStartErroring(stream, error);
       return;
     }
-    TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
-    WritableStreamHandleAbortRequestIfPending(stream);
+
+    // assert(state === ERRORING, '_state_ is `"erroring"`');
+    WritableStreamFinishErroring(stream);
   }
 
-  function WritableStreamFinishInFlightWriteInErroredState(stream) {
-    WritableStreamRejectAbortRequestIfPending(stream);
-    WritableStreamRejectPromisesInReactionToError(stream);
+  function WritableStreamStartErroring(stream, reason) {
+    // assert(stream[_storedError] === undefined,
+    //        '_stream_.[[storedError]] is *undefined*');
+    // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
+    //        '_stream_.[[state]] is `"writable"`');
+
+    const controller = stream[_writableStreamController];
+    // assert(controller !== undefined, '_controller_ is not *undefined*');
+
+    stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORING;
+    stream[_storedError] = reason;
+
+    const writer = stream[_writer];
+    if (writer !== undefined) {
+      WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
+    }
+
+    if (!WritableStreamHasOperationMarkedInFlight(stream) &&
+        controller[_started]) {
+      WritableStreamFinishErroring(stream);
+    }
+  }
+
+  function WritableStreamFinishErroring(stream) {
+    // assert((stream[_stateAndFlags] & STATE_MASK) === ERRORING,
+    //        '_stream_.[[state]] is `"erroring"`');
+    // assert(!WritableStreamHasOperationMarkedInFlight(stream),
+    //        '! WritableStreamHasOperationMarkedInFlight(_stream_) is *false*');
+
+    stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORED;
+
+    WritableStreamDefaultControllerErrorSteps(
+        stream[_writableStreamController]);
+
+    const storedError = stream[_storedError];
+    rejectPromises(stream[_writeRequests], storedError);
+    stream[_writeRequests] = new binding.SimpleQueue();
+
+    if (stream[_pendingAbortRequest] === undefined) {
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+      return;
+    }
+
+    const abortRequest = stream[_pendingAbortRequest];
+    stream[_pendingAbortRequest] = undefined;
+
+    if (abortRequest.wasAlreadyErroring === true) {
+      v8.rejectPromise(abortRequest.promise, storedError);
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+      return;
+    }
+
+    const promise = WritableStreamDefaultControllerAbortSteps(
+        stream[_writableStreamController], abortRequest.reason);
+
+    thenPromise(
+        promise,
+        () => {
+          v8.resolvePromise(abortRequest.promise, undefined);
+          WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+        },
+        reason => {
+          v8.rejectPromise(abortRequest.promise, reason);
+          WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+        });
+  }
+
+  function WritableStreamFinishInFlightWrite(stream) {
+    // assert(stream[_inFlightWriteRequest] !== undefined,
+    //        '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
+    v8.resolvePromise(stream[_inFlightWriteRequest], undefined);
+    stream[_inFlightWriteRequest] = undefined;
   }
 
   function WritableStreamFinishInFlightWriteWithError(stream, error) {
-    TEMP_ASSERT(stream[_inFlightWriteRequest] !== undefined,
-                '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
+    // assert(stream[_inFlightWriteRequest] !== undefined,
+    //        '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
     v8.rejectPromise(stream[_inFlightWriteRequest], error);
     stream[_inFlightWriteRequest] = undefined;
-    const state = stream[_stateAndFlags] & STATE_MASK;
-    if (state === ERRORED) {
-      WritableStreamFinishInFlightWriteInErroredState(stream);
-      return;
-    }
-    TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
-    WritableStreamError(stream, error);
-    WritableStreamRejectAbortRequestIfPending(stream);
+
+    let state = stream[_stateAndFlags] & STATE_MASK;
+    // assert(state === WRITABLE || state === ERRORING,
+    //        '_stream_.[[state]] is `"writable"` or `"erroring"`');
+
+    WritableStreamDealWithRejection(stream, error);
   }
 
   function WritableStreamFinishInFlightClose(stream) {
-    TEMP_ASSERT(stream[_inFlightCloseRequest] !== undefined,
-                '_stream_.[[inFlightCloseRequest]] is not *undefined*.');
+    // assert(stream[_inFlightCloseRequest] !== undefined,
+    //        '_stream_.[[inFlightCloseRequest]] is not *undefined*.');
     v8.resolvePromise(stream[_inFlightCloseRequest], undefined);
     stream[_inFlightCloseRequest] = undefined;
+
     const state = stream[_stateAndFlags] & STATE_MASK;
-    if (state === ERRORED) {
-      WritableStreamFinishInFlightCloseInErroredState(stream);
-      return;
+    // assert(state === WRITABLE || state === ERRORING,
+    //        '_stream_.[[state]] is `"writable"` or `"erroring"`');
+
+    if (state === ERRORING) {
+      stream[_storedError] = undefined;
+      if (stream[_pendingAbortRequest] !== undefined) {
+        v8.resolvePromise(stream[_pendingAbortRequest].promise, undefined);
+        stream[_pendingAbortRequest] = undefined;
+      }
     }
-    TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
+
     stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | CLOSED;
     const writer = stream[_writer];
     if (writer !== undefined) {
       v8.resolvePromise(writer[_closedPromise], undefined);
     }
-    if (stream[_pendingAbortRequest] !== undefined) {
-      v8.resolvePromise(stream[_pendingAbortRequest].promise, undefined);
-      stream[_pendingAbortRequest] = undefined;
-    }
-  }
 
-  function WritableStreamFinishInFlightCloseInErroredState(stream) {
-    WritableStreamRejectAbortRequestIfPending(stream);
-    WritableStreamRejectClosedPromiseInReactionToError(stream);
+    // assert(stream[_pendingAbortRequest] === undefined,
+    //        '_stream_.[[pendingAbortRequest]] is *undefined*');
+    // assert(stream[_storedError] === undefined,
+    //        '_stream_.[[storedError]] is *undefined*');
   }
 
   function WritableStreamFinishInFlightCloseWithError(stream, error) {
-    TEMP_ASSERT(stream[_inFlightCloseRequest] !== undefined,
-                '_stream_.[[inFlightCloseRequest]] is not *undefined*.');
+    // assert(stream[_inFlightCloseRequest] !== undefined,
+    //        '_stream_.[[inFlightCloseRequest]] is not *undefined*.');
     v8.rejectPromise(stream[_inFlightCloseRequest], error);
     stream[_inFlightCloseRequest] = undefined;
+
     const state = stream[_stateAndFlags] & STATE_MASK;
-    if (state === ERRORED) {
-      WritableStreamFinishInFlightCloseInErroredState(stream);
-      return;
+    // assert(state === WRITABLE || state === ERRORING,
+    //        '_stream_.[[state]] is `"writable"` or `"erroring"`');
+
+    if (stream[_pendingAbortRequest] !== undefined) {
+      v8.rejectPromise(stream[_pendingAbortRequest].promise, error);
+      stream[_pendingAbortRequest] = undefined;
     }
-    TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
-    WritableStreamError(stream, error);
-    WritableStreamRejectAbortRequestIfPending(stream);
+
+    WritableStreamDealWithRejection(stream, error);
   }
 
   function WritableStreamCloseQueuedOrInFlight(stream) {
@@ -343,45 +372,40 @@
         stream[_inFlightCloseRequest] !== undefined;
   }
 
-  function WritableStreamHandleAbortRequestIfPending(stream) {
-    if (stream[_pendingAbortRequest] === undefined) {
-      return;
-    }
-    WritableStreamFinishAbort(stream);
-    const abortRequest = stream[_pendingAbortRequest];
-    stream[_pendingAbortRequest] = undefined;
-    const promise =
-        WritableStreamDefaultControllerAbortSteps(stream[_writableStreamController],
-                                                  abortRequest.reason);
-    thenPromise(promise,
-                result => v8.resolvePromise(abortRequest.promise, result),
-                reason => v8.rejectPromise(abortRequest.promise, reason));
-  }
-
   function WritableStreamHasOperationMarkedInFlight(stream) {
     return stream[_inFlightWriteRequest] !== undefined ||
         stream[_inFlightCloseRequest] !== undefined;
   }
 
   function WritableStreamMarkCloseRequestInFlight(stream) {
-    TEMP_ASSERT(stream[_inFlightCloseRequest] === undefined,
-                '_stream_.[[inFlightCloseRequest]] is *undefined*.');
-    TEMP_ASSERT(stream[_closeRequest] !== undefined,
-                '_stream_.[[closeRequest]] is not *undefined*.');
+    // assert(stream[_inFlightCloseRequest] === undefined,
+    //        '_stream_.[[inFlightCloseRequest]] is *undefined*.');
+    // assert(stream[_closeRequest] !== undefined,
+    //        '_stream_.[[closeRequest]] is not *undefined*.');
     stream[_inFlightCloseRequest] = stream[_closeRequest];
     stream[_closeRequest] = undefined;
   }
 
   function WritableStreamMarkFirstWriteRequestInFlight(stream) {
-    TEMP_ASSERT(stream[_inFlightWriteRequest] === undefined,
-                '_stream_.[[inFlightWriteRequest]] is *undefined*.');
-    TEMP_ASSERT(stream[_writeRequests].length !== 0,
-                '_stream_.[[writeRequests]] is not empty.');
+    // assert(stream[_inFlightWriteRequest] === undefined,
+    //        '_stream_.[[inFlightWriteRequest]] is *undefined*.');
+    // assert(stream[_writeRequests].length !== 0,
+    //        '_stream_.[[writeRequests]] is not empty.');
     const writeRequest = stream[_writeRequests].shift();
     stream[_inFlightWriteRequest] = writeRequest;
   }
 
-  function WritableStreamRejectClosedPromiseInReactionToError(stream) {
+  function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
+    // assert((stream[_stateAndFlags] & STATE_MASK) === ERRORED,
+    //        '_stream_.[[state]] is `"errored"`');
+
+    if (stream[_closeRequest] !== undefined) {
+      // assert(stream[_inFlightCloseRequest] === undefined,
+      //        '_stream_.[[inFlightCloseRequest]] is *undefined*');
+      v8.rejectPromise(stream[_closeRequest], stream[_storedError]);
+      stream[_closeRequest] = undefined;
+    }
+
     const writer = stream[_writer];
     if (writer !== undefined) {
       v8.rejectPromise(writer[_closedPromise], stream[_storedError]);
@@ -389,41 +413,18 @@
     }
   }
 
-  function WritableStreamRejectAbortRequestIfPending(stream) {
-    if (stream[_pendingAbortRequest] !== undefined) {
-      v8.rejectPromise(stream[_pendingAbortRequest].promise,
-                       stream[_storedError]);
-      stream[_pendingAbortRequest] = undefined;
-    }
-  }
-
-  function WritableStreamRejectPromisesInReactionToError(stream) {
-    const storedError = stream[_storedError];
-    rejectPromises(stream[_writeRequests], storedError);
-    stream[_writeRequests] = new binding.SimpleQueue();
-
-    if (stream[_closeRequest] !== undefined) {
-      TEMP_ASSERT(stream[_inFlightCloseRequest] === undefined,
-                  '_stream_.[[inFlightCloseRequest]] is *undefined*.');
-      v8.rejectPromise(stream[_closeRequest], storedError);
-      stream[_closeRequest] = undefined;
-    }
-
-    WritableStreamRejectClosedPromiseInReactionToError(stream);
-  }
-
   function WritableStreamUpdateBackpressure(stream, backpressure) {
-    TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
-                'stream.[[state]] is "writable".');
-    TEMP_ASSERT(!WritableStreamCloseQueuedOrInFlight(stream),
-                'WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
+    // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
+    //        'stream.[[state]] is "writable".');
+    // assert(!WritableStreamCloseQueuedOrInFlight(stream),
+    //        'WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
     const writer = stream[_writer];
     if (writer !== undefined &&
         backpressure !== Boolean(stream[_stateAndFlags] & BACKPRESSURE_FLAG)) {
       if (backpressure) {
         writer[_readyPromise] = v8.createPromise();
       } else {
-        TEMP_ASSERT(!backpressure, '_backpressure_ is *false*.');
+        // assert(!backpressure, '_backpressure_ is *false*.');
         v8.resolvePromise(writer[_readyPromise], undefined);
       }
     }
@@ -437,21 +438,21 @@
   // Functions to expose internals for ReadableStream.pipeTo. These are not
   // part of the standard.
   function isWritableStreamErrored(stream) {
-    TEMP_ASSERT(
-        IsWritableStream(stream), '! IsWritableStream(stream) is true.');
+    // assert(
+    //     IsWritableStream(stream), '! IsWritableStream(stream) is true.');
     return (stream[_stateAndFlags] & STATE_MASK) === ERRORED;
   }
 
   function isWritableStreamClosingOrClosed(stream) {
-    TEMP_ASSERT(
-        IsWritableStream(stream), '! IsWritableStream(stream) is true.');
+    // assert(
+    //     IsWritableStream(stream), '! IsWritableStream(stream) is true.');
     return WritableStreamCloseQueuedOrInFlight(stream) ||
         (stream[_stateAndFlags] & STATE_MASK) === CLOSED;
   }
 
   function getWritableStreamStoredError(stream) {
-    TEMP_ASSERT(
-        IsWritableStream(stream), '! IsWritableStream(stream) is true.');
+    // assert(
+    //     IsWritableStream(stream), '! IsWritableStream(stream) is true.');
     return stream[_storedError];
   }
 
@@ -466,28 +467,44 @@
       this[_ownerWritableStream] = stream;
       stream[_writer] = this;
       const state = stream[_stateAndFlags] & STATE_MASK;
-      if (state === WRITABLE) {
-        if (stream[_pendingAbortRequest] !== undefined) {
-          const error = new TypeError(errStreamAborting);
-          this[_readyPromise] = Promise_reject(error);
-          v8.markPromiseAsHandled(this[_readyPromise]);
-        } else if (!WritableStreamCloseQueuedOrInFlight(stream) &&
-            stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
-          this[_readyPromise] = v8.createPromise();
-        } else {
-          this[_readyPromise] = Promise_resolve(undefined);
+      switch (state) {
+        case WRITABLE:
+        {
+          if (!WritableStreamCloseQueuedOrInFlight(stream) &&
+              stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
+            this[_readyPromise] = v8.createPromise();
+          } else {
+            this[_readyPromise] = Promise_resolve(undefined);
+          }
+          this[_closedPromise] = v8.createPromise();
+          break;
         }
-        this[_closedPromise] = v8.createPromise();
-      } else if (state === CLOSED) {
-        this[_readyPromise] = Promise_resolve(undefined);
-        this[_closedPromise] = Promise_resolve(undefined);
-      } else {
-        TEMP_ASSERT(state === ERRORED, '_state_ is `"errored"`.');
-        const storedError = stream[_storedError];
-        this[_readyPromise] = Promise_reject(storedError);
-        v8.markPromiseAsHandled(this[_readyPromise]);
-        this[_closedPromise] = Promise_reject(storedError);
-        v8.markPromiseAsHandled(this[_closedPromise]);
+
+        case ERRORING:
+        {
+          this[_readyPromise] = Promise_reject(stream[_storedError]);
+          v8.markPromiseAsHandled(this[_readyPromise]);
+          this[_closedPromise] = v8.createPromise();
+          break;
+        }
+
+        case CLOSED:
+        {
+          this[_readyPromise] = Promise_resolve(undefined);
+          this[_closedPromise] = Promise_resolve(undefined);
+          break;
+        }
+
+        default:
+        {
+          // assert(state === ERRORED, '_state_ is `"errored"`.');
+          const storedError = stream[_storedError];
+          this[_readyPromise] = Promise_reject(storedError);
+          v8.markPromiseAsHandled(this[_readyPromise]);
+          this[_closedPromise] = Promise_reject(storedError);
+          v8.markPromiseAsHandled(this[_closedPromise]);
+          break;
+        }
       }
     }
 
@@ -547,8 +564,8 @@
       if (stream === undefined) {
         return;
       }
-      TEMP_ASSERT(stream[_writer] !== undefined,
-                  'stream.[[writer]] is not undefined.');
+      // assert(stream[_writer] !== undefined,
+      //        'stream.[[writer]] is not undefined.');
       WritableStreamDefaultWriterRelease(this);
     }
 
@@ -571,28 +588,29 @@
 
   function WritableStreamDefaultWriterAbort(writer, reason) {
     const stream = writer[_ownerWritableStream];
-    TEMP_ASSERT(stream !== undefined,
-                'stream is not undefined.');
+    // assert(stream !== undefined,
+    //        'stream is not undefined.');
     return WritableStreamAbort(stream, reason);
   }
 
   function WritableStreamDefaultWriterClose(writer) {
     const stream = writer[_ownerWritableStream];
-    TEMP_ASSERT(stream !== undefined, 'stream is not undefined.');
+    // assert(stream !== undefined, 'stream is not undefined.');
     const state = stream[_stateAndFlags] & STATE_MASK;
     if (state === CLOSED || state === ERRORED) {
       return Promise_reject(
           createCannotActionOnStateStreamError('close', state));
     }
-    if (stream[_pendingAbortRequest] !== undefined) {
-      return Promise_reject(new TypeError(errStreamAborting));
-    }
-    TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
-    TEMP_ASSERT(!WritableStreamCloseQueuedOrInFlight(stream),
-                '! WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
+
+    // assert(state === WRITABLE || state === ERRORING,
+    //        '_state_ is `"writable"` or `"erroring"`.');
+    // assert(!WritableStreamCloseQueuedOrInFlight(stream),
+    //        '! WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
     const promise = v8.createPromise();
     stream[_closeRequest] = promise;
-    if (stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
+
+    if ((stream[_stateAndFlags] & BACKPRESSURE_FLAG) &&
+        state === WRITABLE) {
       v8.resolvePromise(writer[_readyPromise], undefined);
     }
     WritableStreamDefaultControllerClose(stream[_writableStreamController]);
@@ -601,7 +619,7 @@
 
   function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
     const stream = writer[_ownerWritableStream];
-    TEMP_ASSERT(stream !== undefined, 'stream is not undefined.');
+    // assert(stream !== undefined, 'stream is not undefined.');
     const state = stream[_stateAndFlags] & STATE_MASK;
     if (WritableStreamCloseQueuedOrInFlight(stream) || state === CLOSED) {
       return Promise_resolve(undefined);
@@ -609,12 +627,26 @@
     if (state === ERRORED) {
       return Promise_reject(stream[_storedError]);
     }
-    TEMP_ASSERT(state === WRITABLE, 'state is "writable".');
+
+    // assert(state === WRITABLE || state === ERRORING,
+    //        '_state_ is `"writable"` or `"erroring"`.');
+
     return WritableStreamDefaultWriterClose(writer);
   }
 
-  function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer,
-                                                                 error) {
+  function WritableStreamDefaultWriterEnsureClosedPromiseRejected(
+      writer, error) {
+    if (v8.promiseState(writer[_closedPromise]) === v8.kPROMISE_PENDING) {
+      v8.rejectPromise(writer[_closedPromise], error);
+    } else {
+      writer[_closedPromise] = Promise_reject(error);
+    }
+    v8.markPromiseAsHandled(writer[_closedPromise]);
+  }
+
+
+  function WritableStreamDefaultWriterEnsureReadyPromiseRejected(
+      writer, error) {
     if (v8.promiseState(writer[_readyPromise]) === v8.kPROMISE_PENDING) {
       v8.rejectPromise(writer[_readyPromise], error);
     } else {
@@ -626,7 +658,7 @@
   function WritableStreamDefaultWriterGetDesiredSize(writer) {
     const stream = writer[_ownerWritableStream];
     const state = stream[_stateAndFlags] & STATE_MASK;
-    if (state === ERRORED || stream[_pendingAbortRequest] !== undefined) {
+    if (state === ERRORED || state === ERRORING) {
       return null;
     }
     if (state === CLOSED) {
@@ -638,28 +670,22 @@
 
   function WritableStreamDefaultWriterRelease(writer) {
     const stream = writer[_ownerWritableStream];
-    TEMP_ASSERT(stream !== undefined,
-                'stream is not undefined.');
-    TEMP_ASSERT(stream[_writer] === writer,
-                'stream.[[writer]] is writer.');
+    // assert(stream !== undefined,
+    //        'stream is not undefined.');
+    // assert(stream[_writer] === writer,
+    //        'stream.[[writer]] is writer.');
     const releasedError = new TypeError(errReleasedWriterClosedPromise);
-    const state = stream[_stateAndFlags] & STATE_MASK;
-    WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer,
-                                                          releasedError);
-    if (state === WRITABLE ||
-        WritableStreamHasOperationMarkedInFlight(stream)) {
-      v8.rejectPromise(writer[_closedPromise], releasedError);
-    } else {
-      writer[_closedPromise] = Promise_reject(releasedError);
-    }
-    v8.markPromiseAsHandled(writer[_closedPromise]);
+    WritableStreamDefaultWriterEnsureReadyPromiseRejected(
+        writer, releasedError);
+    WritableStreamDefaultWriterEnsureClosedPromiseRejected(
+        writer, releasedError);
     stream[_writer] = undefined;
     writer[_ownerWritableStream] = undefined;
   }
 
   function WritableStreamDefaultWriterWrite(writer, chunk) {
     const stream = writer[_ownerWritableStream];
-    TEMP_ASSERT(stream !== undefined, 'stream is not undefined.');
+    // assert(stream !== undefined, 'stream is not undefined.');
     const controller = stream[_writableStreamController];
     const chunkSize =
         WritableStreamDefaultControllerGetChunkSize(controller, chunk);
@@ -678,9 +704,10 @@
       return Promise_reject(
           createCannotActionOnStateStreamError('write to', CLOSED));
     }
-    if (stream[_pendingAbortRequest] !== undefined) {
-      return Promise_reject(new TypeError(errStreamAborting));
+    if (state === ERRORING) {
+      return Promise_reject(stream[_storedError]);
     }
+    // assert(state === WRITABLE, '_state_ is `"writable"`');
     const promise = WritableStreamAddWriteRequest(stream);
     WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
     return promise;
@@ -689,16 +716,16 @@
   // Functions to expose internals for ReadableStream.pipeTo. These do not
   // appear in the standard.
   function getWritableStreamDefaultWriterClosedPromise(writer) {
-    TEMP_ASSERT(
-        IsWritableStreamDefaultWriter(writer),
-        'writer is a WritableStreamDefaultWriter.');
+    // assert(
+    //     IsWritableStreamDefaultWriter(writer),
+    //     'writer is a WritableStreamDefaultWriter.');
     return writer[_closedPromise];
   }
 
   function getWritableStreamDefaultWriterReadyPromise(writer) {
-    TEMP_ASSERT(
-        IsWritableStreamDefaultWriter(writer),
-        'writer is a WritableStreamDefaultWriter.');
+    // assert(
+    //     IsWritableStreamDefaultWriter(writer),
+    //     'writer is a WritableStreamDefaultWriter.');
     return writer[_readyPromise];
   }
 
@@ -730,9 +757,10 @@
       if (!IsWritableStreamDefaultController(this)) {
         throw new TypeError(streamErrors.illegalInvocation);
       }
-      const state = this[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
-      if (state === CLOSED || state === ERRORED) {
-        throw createCannotActionOnStateStreamError('error', state);
+      const state =
+          this[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
+      if (state !== WRITABLE) {
+        return;
       }
       WritableStreamDefaultControllerError(this, e);
     }
@@ -744,9 +772,7 @@
   // or impossible, so use static dispatch for now. This will have to be fixed
   // when adding a byte controller.
   function WritableStreamDefaultControllerAbortSteps(controller, reason) {
-    const sinkAbortPromise =
-        PromiseInvokeOrNoop(controller[_underlyingSink], 'abort', [reason]);
-    return thenPromise(sinkAbortPromise, () => undefined);
+    return PromiseInvokeOrNoop(controller[_underlyingSink], 'abort', [reason]);
   }
 
   function WritableStreamDefaultControllerErrorSteps(controller) {
@@ -761,21 +787,18 @@
     thenPromise(
         startPromise,
         () => {
+          const state = stream[_stateAndFlags] & STATE_MASK;
+          // assert(state === WRITABLE || state === ERRORING,
+          //        '_stream_.[[state]] is `"writable"` or `"erroring"`');
           controller[_started] = true;
-          if ((stream[_stateAndFlags] & STATE_MASK) === ERRORED) {
-            WritableStreamRejectAbortRequestIfPending(stream);
-          } else {
-            WritableStreamHandleAbortRequestIfPending(stream);
-          }
           WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
         },
         r => {
-          TEMP_ASSERT(
-              (stream[_stateAndFlags] & STATE_MASK) === WRITABLE ||
-                  (stream[_stateAndFlags] & STATE_MASK) === ERRORED,
-              '_stream_.[[state]] is `"writable"` or `"errored"`.');
-          WritableStreamDefaultControllerErrorIfNeeded(controller, r);
-          WritableStreamRejectAbortRequestIfPending(stream);
+          const state = stream[_stateAndFlags] & STATE_MASK;
+          // assert(state === WRITABLE || state === ERRORING,
+          //        '_stream_.[[state]] is `"writable"` or `"erroring"`');
+          controller[_started] = true;
+          WritableStreamDealWithRejection(stream, r);
         });
   }
 
@@ -818,7 +841,8 @@
       return;
     }
     const stream = controller[_controlledWritableStream];
-    if (!WritableStreamCloseQueuedOrInFlight(stream)) {
+    if (!WritableStreamCloseQueuedOrInFlight(stream) &&
+        (stream[_stateAndFlags] & STATE_MASK) === WRITABLE) {
       const backpressure =
           WritableStreamDefaultControllerGetBackpressure(controller);
       WritableStreamUpdateBackpressure(stream, backpressure);
@@ -828,16 +852,20 @@
 
   function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
     const stream = controller[_controlledWritableStream];
-    const state = stream[_stateAndFlags] & STATE_MASK;
-    if (state === CLOSED || state === ERRORED) {
-      return;
-    }
     if (!controller[_started]) {
       return;
     }
     if (stream[_inFlightWriteRequest] !== undefined) {
       return;
     }
+    const state = stream[_stateAndFlags] & STATE_MASK;
+    if (state === CLOSED || state === ERRORED) {
+      return;
+    }
+    if (state === ERRORING) {
+      WritableStreamFinishErroring(stream);
+      return;
+    }
     if (controller[_queue].length === 0) {
       return;
     }
@@ -851,7 +879,8 @@
   }
 
   function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
-    const state = controller[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
+    const state =
+        controller[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
     if (state === WRITABLE) {
       WritableStreamDefaultControllerError(controller, error);
     }
@@ -861,10 +890,10 @@
     const stream = controller[_controlledWritableStream];
     WritableStreamMarkCloseRequestInFlight(stream);
     DequeueValue(controller);
-    TEMP_ASSERT(controller[_queue].length === 0,
-                'controller.[[queue]] is empty.');
-    const sinkClosePromise = PromiseInvokeOrNoop(controller[_underlyingSink],
-                                                 'close', [controller]);
+    // assert(controller[_queue].length === 0,
+    //        'controller.[[queue]] is empty.');
+    const sinkClosePromise = PromiseInvokeOrNoop(
+        controller[_underlyingSink], 'close', []);
     thenPromise(
         sinkClosePromise,
         () => WritableStreamFinishInFlightClose(stream),
@@ -882,12 +911,11 @@
         () => {
           WritableStreamFinishInFlightWrite(stream);
           const state = stream[_stateAndFlags] & STATE_MASK;
-          if (state === ERRORED) {
-            return;
-          }
-          TEMP_ASSERT(state === WRITABLE, '_state_ is `"writable"`.');
+          // assert(state === WRITABLE || state === ERRORING,
+          //        '_state_ is `"writable"` or `"erroring"`');
           DequeueValue(controller);
-          if (!WritableStreamCloseQueuedOrInFlight(stream)) {
+          if (!WritableStreamCloseQueuedOrInFlight(stream) &&
+              state === WRITABLE) {
             const backpressure =
                 WritableStreamDefaultControllerGetBackpressure(controller);
             WritableStreamUpdateBackpressure(stream, backpressure);
@@ -895,13 +923,7 @@
           WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
         },
         reason => {
-          const wasErrored = (stream[_stateAndFlags] & STATE_MASK) === ERRORED;
           WritableStreamFinishInFlightWriteWithError(stream, reason);
-          TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === ERRORED,
-                      '_stream_.[[state]] is `"errored"`.');
-          if (!wasErrored) {
-            ResetQueue(controller);
-          }
         });
   }
 
@@ -913,22 +935,22 @@
 
   function WritableStreamDefaultControllerError(controller, error) {
     const stream = controller[_controlledWritableStream];
-    TEMP_ASSERT((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
-                '_stream_.[[state]] is `"writable"`.');
-    WritableStreamError(stream, error);
+    // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
+    //        '_stream_.[[state]] is `"writable"`.');
+    WritableStreamStartErroring(stream, error);
   }
 
   // Queue-with-Sizes Operations
   //
   // TODO(ricea): Share these operations with ReadableStream.js.
   function DequeueValue(container) {
-    TEMP_ASSERT(
-        hasOwnProperty(container, _queue) &&
-            hasOwnProperty(container, _queueTotalSize),
-        'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
-            'slots.');
-    TEMP_ASSERT(container[_queue].length !== 0,
-                '_container_.[[queue]] is not empty.');
+    // assert(
+    //     hasOwnProperty(container, _queue) &&
+    //         hasOwnProperty(container, _queueTotalSize),
+    //     'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
+    //         'slots.');
+    // assert(container[_queue].length !== 0,
+    //        '_container_.[[queue]] is not empty.');
     const pair = container[_queue].shift();
     container[_queueTotalSize] -= pair.size;
     if (container[_queueTotalSize] < 0) {
@@ -938,11 +960,11 @@
   }
 
   function EnqueueValueWithSize(container, value, size) {
-    TEMP_ASSERT(
-        hasOwnProperty(container, _queue) &&
-            hasOwnProperty(container, _queueTotalSize),
-        'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
-            'slots.');
+    // assert(
+    //     hasOwnProperty(container, _queue) &&
+    //         hasOwnProperty(container, _queueTotalSize),
+    //     'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
+    //         'slots.');
     size = Number(size);
     if (!IsFiniteNonNegativeNumber(size)) {
       throw new RangeError(streamErrors.invalidSize);
@@ -953,23 +975,23 @@
   }
 
   function PeekQueueValue(container) {
-    TEMP_ASSERT(
-        hasOwnProperty(container, _queue) &&
-            hasOwnProperty(container, _queueTotalSize),
-        'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
-            'slots.');
-    TEMP_ASSERT(container[_queue].length !== 0,
-                '_container_.[[queue]] is not empty.');
+    // assert(
+    //     hasOwnProperty(container, _queue) &&
+    //         hasOwnProperty(container, _queueTotalSize),
+    //     'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
+    //         'slots.');
+    // assert(container[_queue].length !== 0,
+    //        '_container_.[[queue]] is not empty.');
     const pair = container[_queue].peek();
     return pair.value;
   }
 
   function ResetQueue(container) {
-    TEMP_ASSERT(
-        hasOwnProperty(container, _queue) &&
-            hasOwnProperty(container, _queueTotalSize),
-        'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
-            'slots.');
+    // assert(
+    //     hasOwnProperty(container, _queue) &&
+    //         hasOwnProperty(container, _queueTotalSize),
+    //     'Assert: _container_ has [[queue]] and [[queueTotalSize]] internal ' +
+    //         'slots.');
     container[_queue] = new binding.SimpleQueue();
     container[_queueTotalSize] = 0;
   }
@@ -982,8 +1004,8 @@
   //
   // TODO(ricea): Consolidate with ReadableStream implementation.
   function InvokeOrNoop(O, P, args) {
-    TEMP_ASSERT(IsPropertyKey(P),
-                'P is a valid property key.');
+    // assert(IsPropertyKey(P),
+    //        'P is a valid property key.');
     if (args === undefined) {
       args = [];
     }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 2a287ca..96c46e9 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1089,6 +1089,8 @@
                         ->VisitedLinkTextEmphasisColor() ||
                 rare_inherited_data_->text_emphasis_fill !=
                     other.rare_inherited_data_->text_emphasis_fill ||
+                rare_inherited_data_->text_underline_position_ !=
+                    other.rare_inherited_data_->text_underline_position_ ||
                 rare_inherited_data_->text_decoration_skip_ !=
                     other.rare_inherited_data_->text_decoration_skip_ ||
                 rare_inherited_data_->applied_text_decorations !=
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 3f8e4e3..1c86397 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -1091,23 +1091,26 @@
   }
 
   // Margin properties.
-  static Length InitialMargin() { return Length(kFixed); }
 
   // margin-top
+  static Length InitialMarginTop() { return Length(kFixed); }
   const Length& MarginTop() const { return surround_->margin_.Top(); }
   void SetMarginTop(const Length& v) { SET_VAR(surround_, margin_.top_, v); }
 
   // margin-bottom
+  static Length InitialMarginBottom() { return Length(kFixed); }
   const Length& MarginBottom() const { return surround_->margin_.Bottom(); }
   void SetMarginBottom(const Length& v) {
     SET_VAR(surround_, margin_.bottom_, v);
   }
 
   // margin-left
+  static Length InitialMarginLeft() { return Length(kFixed); }
   const Length& MarginLeft() const { return surround_->margin_.Left(); }
   void SetMarginLeft(const Length& v) { SET_VAR(surround_, margin_.left_, v); }
 
   // margin-right
+  static Length InitialMarginRight() { return Length(kFixed); }
   const Length& MarginRight() const { return surround_->margin_.Right(); }
   void SetMarginRight(const Length& v) {
     SET_VAR(surround_, margin_.right_, v);
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
index deb6671..594c44d4 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -987,7 +987,7 @@
   settings.setAlpha(CreationAttributes().alpha());
   settings.setColorSpace(ColorSpaceAsString());
   settings.setPixelFormat(PixelFormatAsString());
-  settings.setLinearPixelMath(LinearPixelMath());
+  settings.setLinearPixelMath(color_params().LinearPixelMath());
 }
 
 void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) {
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index 0df9635..1105d69 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -252,9 +252,9 @@
     std::unique_ptr<FakeWebGraphicsContext3DProvider> provider,
     const IntSize& size,
     Canvas2DLayerBridge::AccelerationMode acceleration_mode) {
-  return AdoptRef(new Canvas2DLayerBridge(
-      std::move(provider), size, 0, kNonOpaque, acceleration_mode,
-      gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType));
+  return AdoptRef(new Canvas2DLayerBridge(std::move(provider), size, 0,
+                                          kNonOpaque, acceleration_mode,
+                                          CanvasColorParams()));
 }
 
 //============================================================================
@@ -355,12 +355,11 @@
   std::unique_ptr<ImageBufferSurface> CreateSurface(
       const IntSize& size,
       OpacityMode mode,
-      sk_sp<SkColorSpace> color_space,
-      SkColorType color_type) override {
+      const CanvasColorParams& color_params) override {
     EXPECT_EQ(kExpectFallback, expectation_);
     did_fallback_ = true;
     return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, mode, kInitializeImagePixels, color_space, color_type));
+        size, mode, kInitializeImagePixels, color_params));
   }
 
   ~MockSurfaceFactory() override {
@@ -558,7 +557,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited());
@@ -570,7 +569,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setGlobalAlpha(0.5f);  // To prevent overdraw optimization
@@ -589,7 +588,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setGlobalAlpha(0.5f);  // To prevent overdraw optimization
@@ -608,7 +607,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   NonThrowableExceptionState exception_state;
@@ -643,7 +642,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   NonThrowableExceptionState exception_state;
@@ -680,7 +679,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -705,7 +704,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -729,7 +728,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -752,7 +751,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -769,7 +768,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->beginPath();
@@ -793,7 +792,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setShadowColor(String("red"));
@@ -813,7 +812,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->setShadowColor(String("red"));
@@ -829,7 +828,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->fillRect(0, 0, 1, 1);  // To have a non-empty dirty rect
@@ -849,7 +848,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->fillRect(0, 0, 1, 1);  // To have a non-empty dirty rect
@@ -873,7 +872,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectFallback),
-          kOpaque, nullptr));
+          kOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->fillText("Text", 0, 5);
@@ -886,7 +885,7 @@
       WTF::WrapUnique(new RecordingImageBufferSurface(
           IntSize(10, 10),
           MockSurfaceFactory::Create(MockSurfaceFactory::kExpectNoFallback),
-          kNonOpaque, nullptr));
+          kNonOpaque));
   CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface));
 
   Context2d()->fillText("Text", 0, 5);
diff --git a/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp b/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp
index 4ef2381c..42111cf 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchHeaderList.cpp
@@ -99,8 +99,7 @@
       resultBuilder.Append(header->second);
       found = true;
     } else {
-      // TODO(rakuco): This must be ", " instead. crbug.com/700434.
-      resultBuilder.Append(',');
+      resultBuilder.Append(", ");
       resultBuilder.Append(header->second);
     }
   }
diff --git a/third_party/WebKit/Source/modules/fetch/FetchHeaderListTest.cpp b/third_party/WebKit/Source/modules/fetch/FetchHeaderListTest.cpp
index 70de823..e8bfdf78 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchHeaderListTest.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchHeaderListTest.cpp
@@ -87,7 +87,7 @@
   EXPECT_TRUE(headerList->Get("X-Foo", combinedValue));
   EXPECT_EQ("bar", combinedValue);
   EXPECT_TRUE(headerList->Get("content-TYPE", combinedValue));
-  EXPECT_EQ("text/plain,application/xml,foo", combinedValue);
+  EXPECT_EQ("text/plain, application/xml, foo", combinedValue);
 }
 
 // This is going to be removed: see crbug.com/645492.
@@ -146,7 +146,7 @@
   headerList->Append("X-Foo", "bar");
   const std::pair<String, String> expectedHeaders[] = {
       std::make_pair("accept", "XYZ"),
-      std::make_pair("content-type", "multipart/form-data,application/xml"),
+      std::make_pair("content-type", "multipart/form-data, application/xml"),
       std::make_pair("x-foo", "bar")};
   const Vector<FetchHeaderList::Header> sortedAndCombined =
       headerList->SortAndCombine();
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index bfbd9ea..8216a1f 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -1132,11 +1132,11 @@
   } else {
     NOTREACHED();
   }
-  return DrawingBuffer::Create(std::move(context_provider), this,
-                               ClampedCanvasSize(), premultiplied_alpha,
-                               want_alpha_channel, want_depth_buffer,
-                               want_stencil_buffer, want_antialiasing, preserve,
-                               web_gl_version, chromium_image_usage);
+  return DrawingBuffer::Create(
+      std::move(context_provider), this, ClampedCanvasSize(),
+      premultiplied_alpha, want_alpha_channel, want_depth_buffer,
+      want_stencil_buffer, want_antialiasing, preserve, web_gl_version,
+      chromium_image_usage, color_params());
 }
 
 void WebGLRenderingContextBase::InitializeNewContext() {
diff --git a/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp b/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
index 16babb2..81f7a50d 100644
--- a/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USBEndpoint.cpp
@@ -9,7 +9,7 @@
 #include "device/usb/public/interfaces/device.mojom-blink.h"
 #include "modules/webusb/USBAlternateInterface.h"
 
-using device::mojom::blink::UsbEndpointType;
+using device::mojom::blink::UsbTransferType;
 using device::mojom::blink::UsbTransferDirection;
 
 namespace blink {
@@ -28,13 +28,13 @@
   }
 }
 
-String ConvertTypeToEnum(const UsbEndpointType& type) {
+String ConvertTypeToEnum(const UsbTransferType& type) {
   switch (type) {
-    case UsbEndpointType::BULK:
+    case UsbTransferType::BULK:
       return "bulk";
-    case UsbEndpointType::INTERRUPT:
+    case UsbTransferType::INTERRUPT:
       return "interrupt";
-    case UsbEndpointType::ISOCHRONOUS:
+    case UsbTransferType::ISOCHRONOUS:
       return "isochronous";
     default:
       ASSERT_NOT_REACHED();
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 18cde98..ce58ba9b 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -68,7 +68,7 @@
     {
       name: "AccessibilityObjectModel",
       settable_from_internals: true,
-      status: "experimental",
+      status: "test",
     },
     {
       name: "AudioOutputDevices",
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h
index 942c9d4..270e51e 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DImageBufferSurface.h
@@ -47,24 +47,15 @@
       int msaa_sample_count,
       OpacityMode opacity_mode,
       Canvas2DLayerBridge::AccelerationMode acceleration_mode,
-      const gfx::ColorSpace& color_space,
-      bool sk_surfaces_use_color_space,
-      SkColorType color_type)
-      : ImageBufferSurface(size,
-                           opacity_mode,
-                           sk_surfaces_use_color_space
-                               ? color_space.ToSkColorSpace()
-                               : nullptr,
-                           color_type),
+      const CanvasColorParams& color_params)
+      : ImageBufferSurface(size, opacity_mode, color_params),
         layer_bridge_(
             AdoptRef(new Canvas2DLayerBridge(std::move(context_provider),
                                              size,
                                              msaa_sample_count,
                                              opacity_mode,
                                              acceleration_mode,
-                                             color_space,
-                                             sk_surfaces_use_color_space,
-                                             color_type))) {
+                                             color_params))) {
     Init();
   }
 
@@ -72,8 +63,7 @@
                              const IntSize& size)
       : ImageBufferSurface(size,
                            bridge->GetOpacityMode(),
-                           bridge->SkSurfaceColorSpace(),
-                           bridge->ColorType()),
+                           bridge->color_params()),
         layer_bridge_(std::move(bridge)) {
     Init();
   }
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index d29e539..eaf8e1bd 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -87,16 +87,16 @@
                                         const IntSize& size,
                                         int msaa_sample_count,
                                         OpacityMode opacity_mode,
-                                        sk_sp<SkColorSpace> color_space,
-                                        SkColorType color_type,
+                                        const CanvasColorParams& color_params,
                                         bool* surface_is_accelerated) {
   if (gr)
     gr->resetContext();
 
   SkAlphaType alpha_type =
       (kOpaque == opacity_mode) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
-  SkImageInfo info = SkImageInfo::Make(size.Width(), size.Height(), color_type,
-                                       alpha_type, color_space);
+  SkImageInfo info = SkImageInfo::Make(
+      size.Width(), size.Height(), color_params.GetSkColorType(), alpha_type,
+      color_params.GetSkColorSpaceForSkSurfaces());
   SkSurfaceProps disable_lcd_props(0, kUnknown_SkPixelGeometry);
   sk_sp<SkSurface> surface;
 
@@ -129,9 +129,7 @@
     int msaa_sample_count,
     OpacityMode opacity_mode,
     AccelerationMode acceleration_mode,
-    const gfx::ColorSpace& color_space,
-    bool sk_surfaces_use_color_space,
-    SkColorType color_type)
+    const CanvasColorParams& color_params)
     : context_provider_(std::move(context_provider)),
       logger_(WTF::WrapUnique(new Logger)),
       weak_ptr_factory_(this),
@@ -149,12 +147,10 @@
       acceleration_mode_(acceleration_mode),
       opacity_mode_(opacity_mode),
       size_(size),
-      color_space_(color_space),
-      sk_surfaces_use_color_space_(sk_surfaces_use_color_space),
-      color_type_(color_type) {
+      color_params_(color_params) {
   DCHECK(context_provider_);
   DCHECK(!context_provider_->IsSoftwareRendering());
-  DCHECK(color_space_.IsValid());
+  DCHECK(color_params_.GetGfxColorSpace().IsValid());
   // Used by browser tests to detect the use of a Canvas2DLayerBridge.
   TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation",
                        TRACE_EVENT_SCOPE_GLOBAL);
@@ -286,8 +282,9 @@
       cc::TextureMailbox(mailbox, sync_token, texture_target, gfx::Size(size_),
                          is_overlay_candidate, secure_output_only);
   if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) {
-    out_mailbox->set_color_space(color_space_);
-    image_info->gpu_memory_buffer_->SetColorSpaceForScanout(color_space_);
+    gfx::ColorSpace color_space = color_params_.GetGfxColorSpace();
+    out_mailbox->set_color_space(color_space);
+    image_info->gpu_memory_buffer_->SetColorSpaceForScanout(color_space);
   }
 
   gl->BindTexture(GC3D_TEXTURE_RECTANGLE_ARB, 0);
@@ -534,12 +531,6 @@
   logger_->DidStartHibernating();
 }
 
-sk_sp<SkColorSpace> Canvas2DLayerBridge::SkSurfaceColorSpace() const {
-  if (sk_surfaces_use_color_space_)
-    return color_space_.ToSkColorSpace();
-  return nullptr;
-}
-
 void Canvas2DLayerBridge::ReportSurfaceCreationFailure() {
   if (!surface_creation_failed_at_least_once_) {
     // Only count the failure once per instance so that the histogram may
@@ -570,7 +561,7 @@
   bool surface_is_accelerated;
   surface_ = CreateSkSurface(
       want_acceleration ? context_provider_->GetGrContext() : nullptr, size_,
-      msaa_sample_count_, opacity_mode_, SkSurfaceColorSpace(), color_type_,
+      msaa_sample_count_, opacity_mode_, color_params_,
       &surface_is_accelerated);
   surface_paint_canvas_ =
       WTF::WrapUnique(new SkiaPaintCanvas(surface_->getCanvas()));
@@ -794,9 +785,9 @@
     SkCanvas* canvas = GetOrCreateSurface()->getCanvas();
     std::unique_ptr<SkCanvas> color_transform_canvas;
     if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled() &&
-        !sk_surfaces_use_color_space_) {
-      color_transform_canvas =
-          SkCreateColorSpaceXformCanvas(canvas, color_space_.ToSkColorSpace());
+        color_params_.UsesOutputSpaceBlending()) {
+      color_transform_canvas = SkCreateColorSpaceXformCanvas(
+          canvas, color_params_.GetSkColorSpace());
       canvas = color_transform_canvas.get();
     }
 
@@ -883,9 +874,9 @@
   if (shared_gl && shared_gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
     GrContext* gr_ctx = context_provider_->GetGrContext();
     bool surface_is_accelerated;
-    sk_sp<SkSurface> surface(CreateSkSurface(
-        gr_ctx, size_, msaa_sample_count_, opacity_mode_, SkSurfaceColorSpace(),
-        color_type_, &surface_is_accelerated));
+    sk_sp<SkSurface> surface(CreateSkSurface(gr_ctx, size_, msaa_sample_count_,
+                                             opacity_mode_, color_params_,
+                                             &surface_is_accelerated));
     if (!surface_)
       ReportSurfaceCreationFailure();
 
@@ -952,7 +943,7 @@
   if (!PrepareMailboxFromImage(std::move(image), out_mailbox))
     return false;
   out_mailbox->set_nearest_neighbor(GetGLFilter() == GL_NEAREST);
-  out_mailbox->set_color_space(color_space_);
+  out_mailbox->set_color_space(color_params_.GetGfxColorSpace());
 
   auto func =
       WTF::Bind(&Canvas2DLayerBridge::MailboxReleased,
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
index 9417d67..eec71a5 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
@@ -93,9 +93,7 @@
                       int msaa_sample_count,
                       OpacityMode,
                       AccelerationMode,
-                      const gfx::ColorSpace&,
-                      bool sk_surfaces_use_color_space,
-                      SkColorType);
+                      const CanvasColorParams&);
 
   ~Canvas2DLayerBridge() override;
 
@@ -141,8 +139,7 @@
   void BeginDestruction();
   void Hibernate();
   bool IsHibernating() const { return hibernation_image_.get(); }
-  sk_sp<SkColorSpace> SkSurfaceColorSpace() const;
-  SkColorType ColorType() const { return color_type_; }
+  const CanvasColorParams& color_params() const { return color_params_; }
 
   bool HasRecordedDrawCommands() { return have_recorded_draw_commands_; }
 
@@ -286,11 +283,7 @@
   AccelerationMode acceleration_mode_;
   OpacityMode opacity_mode_;
   const IntSize size_;
-  // The color space that the compositor is to use. This will always be
-  // defined.
-  gfx::ColorSpace color_space_;
-  bool sk_surfaces_use_color_space_ = false;
-  SkColorType color_type_;
+  CanvasColorParams color_params_;
   int recording_pixel_count_;
 
 #if USE_IOSURFACE_FOR_2D_CANVAS
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
index c54f8d7..17ba8fe6 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -124,9 +124,9 @@
       std::unique_ptr<FakeWebGraphicsContext3DProvider> provider,
       const IntSize& size,
       Canvas2DLayerBridge::AccelerationMode acceleration_mode) {
-    RefPtr<Canvas2DLayerBridge> bridge = AdoptRef(new Canvas2DLayerBridge(
-        std::move(provider), size, 0, kNonOpaque, acceleration_mode,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType));
+    RefPtr<Canvas2DLayerBridge> bridge = AdoptRef(
+        new Canvas2DLayerBridge(std::move(provider), size, 0, kNonOpaque,
+                                acceleration_mode, CanvasColorParams()));
     bridge->DontUseIdleSchedulingForTesting();
     return bridge.Release();
   }
@@ -139,8 +139,7 @@
 
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
         std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
-        Canvas2DLayerBridge::kDisableAcceleration,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+        Canvas2DLayerBridge::kDisableAcceleration, CanvasColorParams())));
 
     const GrGLTextureInfo* texture_info =
         skia::GrBackendObjectToGrGLTextureInfo(
@@ -160,8 +159,7 @@
     gl.setIsContextLost(true);
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
         std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
-        Canvas2DLayerBridge::kEnableAcceleration, gfx::ColorSpace::CreateSRGB(),
-        false, kN32_SkColorType)));
+        Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams())));
     EXPECT_TRUE(bridge->CheckSurfaceValid());
     EXPECT_FALSE(bridge->IsAccelerated());
   }
@@ -174,8 +172,7 @@
           WTF::WrapUnique(new FakeWebGraphicsContext3DProvider(&gl));
       Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
           std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
-          Canvas2DLayerBridge::kEnableAcceleration,
-          gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+          Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams())));
       EXPECT_TRUE(bridge->CheckSurfaceValid());
       EXPECT_TRUE(bridge->IsAccelerated());
       sk_sp<SkImage> snapshot = bridge->NewImageSnapshot(
@@ -192,8 +189,7 @@
       GrContext* gr = context_provider->GetGrContext();
       Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
           std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
-          Canvas2DLayerBridge::kEnableAcceleration,
-          gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+          Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams())));
       EXPECT_TRUE(bridge->CheckSurfaceValid());
       EXPECT_TRUE(bridge->IsAccelerated());  // We don't yet know that
                                              // allocation will fail.
@@ -215,7 +211,7 @@
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
         std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
         Canvas2DLayerBridge::kForceAccelerationForTesting,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+        CanvasColorParams())));
     EXPECT_TRUE(bridge->CheckSurfaceValid());
     PaintFlags flags;
     uint32_t gen_id = bridge->GetOrCreateSurface()->generationID();
@@ -241,7 +237,7 @@
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
         std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
         Canvas2DLayerBridge::kForceAccelerationForTesting,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+        CanvasColorParams())));
 
     EXPECT_TRUE(bridge->IsAccelerated());
 
@@ -262,7 +258,7 @@
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
         std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
         Canvas2DLayerBridge::kForceAccelerationForTesting,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+        CanvasColorParams())));
 
     bridge->GetOrCreateSurface();
     EXPECT_TRUE(bridge->CheckSurfaceValid());
@@ -293,7 +289,7 @@
       Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
           std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
           Canvas2DLayerBridge::kForceAccelerationForTesting,
-          gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+          CanvasColorParams())));
 
       cc::TextureMailbox texture_mailbox;
       std::unique_ptr<cc::SingleReleaseCallback> release_callback;
@@ -317,7 +313,7 @@
         Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
             std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
             Canvas2DLayerBridge::kForceAccelerationForTesting,
-            gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+            CanvasColorParams())));
         bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback);
         // |bridge| goes out of scope and would normally be destroyed, but
         // object is kept alive by self references.
@@ -339,8 +335,7 @@
           WTF::WrapUnique(new FakeWebGraphicsContext3DProvider(&gl));
       Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
           std::move(context_provider), IntSize(300, 300), 0, kNonOpaque,
-          Canvas2DLayerBridge::kEnableAcceleration,
-          gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+          Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams())));
       PaintFlags flags;
       bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
       sk_sp<SkImage> image = bridge->NewImageSnapshot(kPreferAcceleration,
@@ -355,8 +350,7 @@
           WTF::WrapUnique(new FakeWebGraphicsContext3DProvider(&gl));
       Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
           std::move(context_provider), IntSize(300, 300), 0, kNonOpaque,
-          Canvas2DLayerBridge::kEnableAcceleration,
-          gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+          Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams())));
       PaintFlags flags;
       bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
       sk_sp<SkImage> image = bridge->NewImageSnapshot(kPreferNoAcceleration,
@@ -1320,7 +1314,7 @@
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
         std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
         Canvas2DLayerBridge::kForceAccelerationForTesting,
-        gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+        CanvasColorParams())));
     bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback);
   }
 
@@ -1344,8 +1338,7 @@
   EXPECT_CALL(gl, Flush()).Times(0);
   Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
       std::move(context_provider), IntSize(300, 150), 0, kNonOpaque,
-      Canvas2DLayerBridge::kForceAccelerationForTesting,
-      gfx::ColorSpace::CreateSRGB(), false, kN32_SkColorType)));
+      Canvas2DLayerBridge::kForceAccelerationForTesting, CanvasColorParams())));
   EXPECT_FALSE(bridge->HasRecordedDrawCommands());
   ::testing::Mock::VerifyAndClearExpectations(&gl);
 
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
index ea864676..80edcb1 100644
--- a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.cpp
@@ -8,10 +8,16 @@
 
 namespace blink {
 
+CanvasColorParams::CanvasColorParams() = default;
+
 CanvasColorParams::CanvasColorParams(CanvasColorSpace color_space,
                                      CanvasPixelFormat pixel_format)
     : color_space_(color_space), pixel_format_(pixel_format) {}
 
+bool CanvasColorParams::UsesOutputSpaceBlending() const {
+  return color_space_ == kLegacyCanvasColorSpace;
+}
+
 sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpaceForSkSurfaces() const {
   if (color_space_ == kLegacyCanvasColorSpace)
     return nullptr;
@@ -24,6 +30,10 @@
   return kN32_SkColorType;
 }
 
+uint8_t CanvasColorParams::BytesPerPixel() const {
+  return SkColorTypeBytesPerPixel(GetSkColorType());
+}
+
 gfx::ColorSpace CanvasColorParams::GetGfxColorSpace() const {
   switch (color_space_) {
     case kLegacyCanvasColorSpace:
@@ -42,6 +52,10 @@
   return gfx::ColorSpace();
 }
 
+sk_sp<SkColorSpace> CanvasColorParams::GetSkColorSpace() const {
+  return GetGfxColorSpace().ToSkColorSpace();
+}
+
 bool CanvasColorParams::LinearPixelMath() const {
   return pixel_format_ == kF16CanvasPixelFormat;
 }
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h
index daf034a..32d2c1b 100644
--- a/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h
+++ b/third_party/WebKit/Source/platform/graphics/CanvasColorParams.h
@@ -31,22 +31,33 @@
 
 class PLATFORM_EXPORT CanvasColorParams {
  public:
+  // The default constructor will create an output-blended 8-bit surface.
+  CanvasColorParams();
   CanvasColorParams(CanvasColorSpace, CanvasPixelFormat);
   CanvasColorSpace color_space() const { return color_space_; }
   CanvasPixelFormat pixel_format() const { return pixel_format_; }
 
+  // Returns true if the canvas uses blends output color space values (that is,
+  // not linear space colors).
+  bool UsesOutputSpaceBlending() const;
+
   // The SkColorSpace to use in the SkImageInfo for allocated SkSurfaces. This
   // is nullptr in legacy rendering mode.
   sk_sp<SkColorSpace> GetSkColorSpaceForSkSurfaces() const;
 
   // The pixel format to use for allocating SkSurfaces.
   SkColorType GetSkColorType() const;
+  uint8_t BytesPerPixel() const;
 
-  // The color space to use for compositing.
+  // The color space to use for compositing. This will always return a valid
+  // gfx or skia color space.
   gfx::ColorSpace GetGfxColorSpace() const;
+  sk_sp<SkColorSpace> GetSkColorSpace() const;
 
   // This matches CanvasRenderingContext::LinearPixelMath, and is true only when
   // the pixel format is half-float linear.
+  // TODO(ccameron): This is not the same as !UsesOutputSpaceBlending, but
+  // perhaps should be.
   bool LinearPixelMath() const;
 
  private:
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index ee46ab4..bb1a4cc 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -80,16 +80,10 @@
     const IntSize& size,
     OpacityMode opacity_mode,
     ImageInitializationMode initialization_mode,
-    sk_sp<SkColorSpace> color_space) {
-  SkColorType color_type = kN32_SkColorType;
-  if (color_space && SkColorSpace::Equals(color_space.get(),
-                                          SkColorSpace::MakeSRGBLinear().get()))
-    color_type = kRGBA_F16_SkColorType;
-
+    const CanvasColorParams& color_params) {
   std::unique_ptr<ImageBufferSurface> surface(
       WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-          size, opacity_mode, initialization_mode, std::move(color_space),
-          color_type)));
+          size, opacity_mode, initialization_mode, color_params)));
 
   if (!surface->IsValid())
     return nullptr;
@@ -354,9 +348,7 @@
 bool ImageBuffer::GetImageData(Multiply multiplied,
                                const IntRect& rect,
                                WTF::ArrayBufferContents& contents) const {
-  uint8_t bytes_per_pixel = 4;
-  if (surface_->ColorSpace())
-    bytes_per_pixel = SkColorTypeBytesPerPixel(surface_->ColorType());
+  uint8_t bytes_per_pixel = surface_->color_params().BytesPerPixel();
   CheckedNumeric<int> data_size = bytes_per_pixel;
   data_size *= rect.Width();
   data_size *= rect.Height();
@@ -399,7 +391,8 @@
                                   WTF::ArrayBufferContents::kNotShared);
 
   // Skia does not support unpremultiplied read with an F16 to 8888 conversion
-  bool use_f16_workaround = surface_->ColorType() == kRGBA_F16_SkColorType;
+  bool use_f16_workaround =
+      surface_->color_params().GetSkColorType() == kRGBA_F16_SkColorType;
 
   SkAlphaType alpha_type = (multiplied == kPremultiplied || use_f16_workaround)
                                ? kPremul_SkAlphaType
@@ -411,10 +404,8 @@
 
   // Only use sRGB when the surface has a color space.  Converting untagged
   // pixels to a particular color space is not well-defined in Skia.
-  sk_sp<SkColorSpace> color_space = nullptr;
-  if (surface_->ColorSpace()) {
-    color_space = SkColorSpace::MakeSRGB();
-  }
+  sk_sp<SkColorSpace> color_space =
+      surface_->color_params().GetSkColorSpaceForSkSurfaces();
 
   SkImageInfo info = SkImageInfo::Make(rect.Width(), rect.Height(), color_type,
                                        alpha_type, std::move(color_space));
@@ -455,9 +446,7 @@
                                const IntPoint& dest_point) {
   if (!IsSurfaceValid())
     return;
-  uint8_t bytes_per_pixel = 4;
-  if (surface_->ColorSpace())
-    bytes_per_pixel = SkColorTypeBytesPerPixel(surface_->ColorType());
+  uint8_t bytes_per_pixel = surface_->color_params().BytesPerPixel();
 
   DCHECK_GT(source_rect.Width(), 0);
   DCHECK_GT(source_rect.Height(), 0);
@@ -494,10 +483,11 @@
   }
 
   SkImageInfo info;
-  if (surface_->ColorSpace()) {
-    info = SkImageInfo::Make(source_rect.Width(), source_rect.Height(),
-                             surface_->ColorType(), alpha_type,
-                             surface_->ColorSpace());
+  if (surface_->color_params().GetSkColorSpaceForSkSurfaces()) {
+    info = SkImageInfo::Make(
+        source_rect.Width(), source_rect.Height(),
+        surface_->color_params().GetSkColorType(), alpha_type,
+        surface_->color_params().GetSkColorSpaceForSkSurfaces());
   } else {
     info = SkImageInfo::Make(source_rect.Width(), source_rect.Height(),
                              kRGBA_8888_SkColorType, alpha_type,
@@ -511,7 +501,7 @@
     // If image buffer is accelerated, we should keep track of GPU memory usage.
     int gpu_buffer_count = 2;
     CheckedNumeric<intptr_t> checked_gpu_usage =
-        SkColorTypeBytesPerPixel(surface_->ColorType()) * gpu_buffer_count;
+        surface_->color_params().BytesPerPixel() * gpu_buffer_count;
     checked_gpu_usage *= this->size().Width();
     checked_gpu_usage *= this->size().Height();
     intptr_t gpu_memory_usage =
@@ -543,11 +533,9 @@
   virtual std::unique_ptr<ImageBufferSurface> CreateSurface(
       const IntSize& size,
       OpacityMode opacity_mode,
-      sk_sp<SkColorSpace> color_space,
-      SkColorType color_type) {
+      const CanvasColorParams& color_params) {
     return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, opacity_mode, kInitializeImagePixels, std::move(color_space),
-        color_type));
+        size, opacity_mode, kInitializeImagePixels, color_params));
   }
 
   virtual ~UnacceleratedSurfaceFactory() {}
@@ -565,8 +553,7 @@
   std::unique_ptr<ImageBufferSurface> surface =
       WTF::WrapUnique(new RecordingImageBufferSurface(
           surface_->size(), std::move(surface_factory),
-          surface_->GetOpacityMode(), surface_->ColorSpace(),
-          surface_->ColorType()));
+          surface_->GetOpacityMode(), surface_->color_params()));
   SetSurface(std::move(surface));
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
index 0d18f76..cbf3e35 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
@@ -78,7 +78,7 @@
       const IntSize&,
       OpacityMode = kNonOpaque,
       ImageInitializationMode = kInitializeImagePixels,
-      sk_sp<SkColorSpace> = nullptr);
+      const CanvasColorParams& = CanvasColorParams());
   static std::unique_ptr<ImageBuffer> Create(
       std::unique_ptr<ImageBufferSurface>);
 
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
index 9139f79..10858cc 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
@@ -41,12 +41,8 @@
 
 ImageBufferSurface::ImageBufferSurface(const IntSize& size,
                                        OpacityMode opacity_mode,
-                                       sk_sp<SkColorSpace> color_space,
-                                       SkColorType color_type)
-    : opacity_mode_(opacity_mode),
-      size_(size),
-      color_space_(color_space),
-      color_type_(color_type) {
+                                       const CanvasColorParams& color_params)
+    : opacity_mode_(opacity_mode), size_(size), color_params_(color_params) {
   SetIsHidden(false);
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
index 9ac1b57..bc4af9dd 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
@@ -33,6 +33,7 @@
 
 #include "platform/PlatformExport.h"
 #include "platform/geometry/IntSize.h"
+#include "platform/graphics/CanvasColorParams.h"
 #include "platform/graphics/GraphicsTypes.h"
 #include "platform/graphics/paint/PaintCanvas.h"
 #include "platform/graphics/paint/PaintFlags.h"
@@ -43,7 +44,6 @@
 #include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 
-class SkColorSpace;
 class SkImage;
 struct SkImageInfo;
 
@@ -104,22 +104,17 @@
 
   OpacityMode GetOpacityMode() const { return opacity_mode_; }
   const IntSize& size() const { return size_; }
-  const sk_sp<SkColorSpace> ColorSpace() const { return color_space_; }
-  SkColorType ColorType() const { return color_type_; }
+  const CanvasColorParams& color_params() const { return color_params_; }
   void NotifyIsValidChanged(bool is_valid) const;
 
  protected:
-  ImageBufferSurface(const IntSize&,
-                     OpacityMode,
-                     sk_sp<SkColorSpace>,
-                     SkColorType);
+  ImageBufferSurface(const IntSize&, OpacityMode, const CanvasColorParams&);
   void Clear();
 
  private:
   OpacityMode opacity_mode_;
   IntSize size_;
-  sk_sp<SkColorSpace> color_space_;
-  SkColorType color_type_;
+  CanvasColorParams color_params_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
index 1973c948..4b0bb49 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
@@ -21,12 +21,8 @@
     std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory>
         fallback_factory,
     OpacityMode opacity_mode,
-    sk_sp<SkColorSpace> color_space,
-    SkColorType color_type)
-    : ImageBufferSurface(size,
-                         opacity_mode,
-                         std::move(color_space),
-                         color_type),
+    const CanvasColorParams& color_params)
+    : ImageBufferSurface(size, opacity_mode, color_params),
       image_buffer_(0),
       current_frame_pixel_count_(0),
       previous_frame_pixel_count_(0),
@@ -97,8 +93,8 @@
                                kFallbackReasonCount));
   canvas_fallback_histogram.Count(reason);
 
-  fallback_surface_ = fallback_factory_->CreateSurface(
-      size(), GetOpacityMode(), ColorSpace(), ColorType());
+  fallback_surface_ = fallback_factory_->CreateSurface(size(), GetOpacityMode(),
+                                                       color_params());
   fallback_surface_->SetImageBuffer(image_buffer_);
 
   if (previous_frame_) {
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h
index a3cf0efb..a0b8f493 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.h
@@ -23,10 +23,8 @@
   WTF_MAKE_NONCOPYABLE(RecordingImageBufferFallbackSurfaceFactory);
 
  public:
-  virtual std::unique_ptr<ImageBufferSurface> CreateSurface(const IntSize&,
-                                                            OpacityMode,
-                                                            sk_sp<SkColorSpace>,
-                                                            SkColorType) = 0;
+  virtual std::unique_ptr<ImageBufferSurface>
+  CreateSurface(const IntSize&, OpacityMode, const CanvasColorParams&) = 0;
   virtual ~RecordingImageBufferFallbackSurfaceFactory() {}
 
  protected:
@@ -47,8 +45,7 @@
       std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory>
           fallback_factory = nullptr,
       OpacityMode = kNonOpaque,
-      sk_sp<SkColorSpace> = nullptr,
-      SkColorType = kN32_SkColorType);
+      const CanvasColorParams& = CanvasColorParams());
   ~RecordingImageBufferSurface() override;
 
   // Implementation of ImageBufferSurface interfaces
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
index 8430490..b37d903 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -32,12 +32,10 @@
   virtual std::unique_ptr<ImageBufferSurface> CreateSurface(
       const IntSize& size,
       OpacityMode opacity_mode,
-      sk_sp<SkColorSpace> color_space,
-      SkColorType color_type) {
+      const CanvasColorParams& color_params) {
     create_surface_count_++;
     return WTF::WrapUnique(new UnacceleratedImageBufferSurface(
-        size, opacity_mode, kInitializeImagePixels, std::move(color_space),
-        color_type));
+        size, opacity_mode, kInitializeImagePixels, color_params));
   }
 
   virtual ~MockSurfaceFactory() {}
@@ -56,7 +54,7 @@
     surface_factory_ = surface_factory.get();
     std::unique_ptr<RecordingImageBufferSurface> test_surface =
         WTF::WrapUnique(new RecordingImageBufferSurface(
-            IntSize(10, 10), std::move(surface_factory), kNonOpaque, nullptr));
+            IntSize(10, 10), std::move(surface_factory), kNonOpaque));
     test_surface_ = test_surface.get();
     // We create an ImageBuffer in order for the testSurface to be
     // properly initialized with a GraphicsContext
diff --git a/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
index b047754..ce38fa85 100644
--- a/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.cpp
@@ -40,13 +40,13 @@
     const IntSize& size,
     OpacityMode opacity_mode,
     ImageInitializationMode initialization_mode,
-    sk_sp<SkColorSpace> color_space,
-    SkColorType color_type)
-    : ImageBufferSurface(size, opacity_mode, color_space, color_type) {
+    const CanvasColorParams& color_params)
+    : ImageBufferSurface(size, opacity_mode, color_params) {
   SkAlphaType alpha_type =
       (kOpaque == opacity_mode) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
-  SkImageInfo info = SkImageInfo::Make(size.Width(), size.Height(), color_type,
-                                       alpha_type, color_space);
+  SkImageInfo info = SkImageInfo::Make(
+      size.Width(), size.Height(), color_params.GetSkColorType(), alpha_type,
+      color_params.GetSkColorSpaceForSkSurfaces());
   SkSurfaceProps disable_lcd_props(0, kUnknown_SkPixelGeometry);
   surface_ = SkSurface::MakeRaster(
       info, kOpaque == opacity_mode ? 0 : &disable_lcd_props);
diff --git a/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h
index 31c143f9..2a6cf946 100644
--- a/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h
+++ b/third_party/WebKit/Source/platform/graphics/UnacceleratedImageBufferSurface.h
@@ -47,8 +47,8 @@
       const IntSize&,
       OpacityMode = kNonOpaque,
       ImageInitializationMode = kInitializeImagePixels,
-      sk_sp<SkColorSpace> = nullptr,
-      SkColorType = kN32_SkColorType);
+      const CanvasColorParams& = CanvasColorParams(kLegacyCanvasColorSpace,
+                                                   kRGBA8CanvasPixelFormat));
   ~UnacceleratedImageBufferSurface() override;
 
   PaintCanvas* Canvas() override;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
index e15d266..fd5a436f 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.cpp
@@ -42,9 +42,8 @@
 AcceleratedImageBufferSurface::AcceleratedImageBufferSurface(
     const IntSize& size,
     OpacityMode opacity_mode,
-    sk_sp<SkColorSpace> color_space,
-    SkColorType color_type)
-    : ImageBufferSurface(size, opacity_mode, color_space, color_type) {
+    const CanvasColorParams& color_params)
+    : ImageBufferSurface(size, opacity_mode, color_params) {
   if (!SharedGpuContext::IsValid())
     return;
   GrContext* gr_context = SharedGpuContext::Gr();
@@ -53,8 +52,9 @@
 
   SkAlphaType alpha_type =
       (kOpaque == opacity_mode) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
-  SkImageInfo info = SkImageInfo::Make(size.Width(), size.Height(), color_type,
-                                       alpha_type, color_space);
+  SkImageInfo info = SkImageInfo::Make(
+      size.Width(), size.Height(), color_params.GetSkColorType(), alpha_type,
+      color_params.GetSkColorSpaceForSkSurfaces());
   SkSurfaceProps disable_lcd_props(0, kUnknown_SkPixelGeometry);
   surface_ = SkSurface::MakeRenderTarget(
       gr_context, SkBudgeted::kYes, info, 0 /* sampleCount */,
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h
index 2fe2f6f..91ee454 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h
@@ -48,8 +48,7 @@
  public:
   AcceleratedImageBufferSurface(const IntSize&,
                                 OpacityMode = kNonOpaque,
-                                sk_sp<SkColorSpace> = nullptr,
-                                SkColorType = kN32_SkColorType);
+                                const CanvasColorParams& = CanvasColorParams());
   ~AcceleratedImageBufferSurface() override {}
 
   PaintCanvas* Canvas() override { return canvas_.get(); }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index 7a26d0f..e4d34d37 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -77,7 +77,8 @@
     bool want_antialiasing,
     PreserveDrawingBuffer preserve,
     WebGLVersion web_gl_version,
-    ChromiumImageUsage chromium_image_usage) {
+    ChromiumImageUsage chromium_image_usage,
+    const CanvasColorParams& color_params) {
   DCHECK(context_provider);
 
   if (g_should_fail_drawing_buffer_creation_for_testing) {
@@ -119,7 +120,7 @@
       std::move(context_provider), std::move(extensions_util), client,
       discard_framebuffer_supported, want_alpha_channel, premultiplied_alpha,
       preserve, web_gl_version, want_depth_buffer, want_stencil_buffer,
-      chromium_image_usage));
+      chromium_image_usage, color_params));
   if (!drawing_buffer->Initialize(size, multisample_supported)) {
     drawing_buffer->BeginDestruction();
     return PassRefPtr<DrawingBuffer>();
@@ -142,7 +143,8 @@
     WebGLVersion web_gl_version,
     bool want_depth,
     bool want_stencil,
-    ChromiumImageUsage chromium_image_usage)
+    ChromiumImageUsage chromium_image_usage,
+    const CanvasColorParams& color_params)
     : client_(client),
       preserve_drawing_buffer_(preserve),
       web_gl_version_(web_gl_version),
@@ -156,7 +158,7 @@
       software_rendering_(this->ContextProvider()->IsSoftwareRendering()),
       want_depth_(want_depth),
       want_stencil_(want_stencil),
-      color_space_(gfx::ColorSpace::CreateSRGB()),
+      color_space_(color_params.GetGfxColorSpace()),
       chromium_image_usage_(chromium_image_usage) {
   // Used by browser tests to detect the use of a DrawingBuffer.
   TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
index 16e778c..938c0c3 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -66,6 +66,7 @@
 }
 
 namespace blink {
+class CanvasColorParams;
 class Extensions3DUtil;
 class StaticBitmapImage;
 class WebExternalTextureLayer;
@@ -121,7 +122,8 @@
       bool want_antialiasing,
       PreserveDrawingBuffer,
       WebGLVersion,
-      ChromiumImageUsage);
+      ChromiumImageUsage,
+      const CanvasColorParams&);
   static void ForceNextDrawingBufferCreationToFail();
 
   ~DrawingBuffer() override;
@@ -241,7 +243,8 @@
                 WebGLVersion,
                 bool wants_depth,
                 bool wants_stencil,
-                ChromiumImageUsage);
+                ChromiumImageUsage,
+                const CanvasColorParams&);
 
   bool Initialize(const IntSize&, bool use_multisampling);
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
index d05d2335..6cd8201 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -37,6 +37,7 @@
 #include "gpu/command_buffer/client/gles2_interface_stub.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/common/sync_token.h"
+#include "platform/graphics/CanvasColorParams.h"
 #include "platform/graphics/ImageBuffer.h"
 #include "platform/graphics/UnacceleratedImageBufferSurface.h"
 #include "platform/graphics/gpu/DrawingBufferTestHelpers.h"
@@ -653,7 +654,7 @@
         std::move(provider), nullptr, IntSize(10, 10), premultiplied_alpha,
         want_alpha_channel, want_depth_buffer, want_stencil_buffer,
         want_antialiasing, preserve, DrawingBuffer::kWebGL1,
-        DrawingBuffer::kAllowChromiumImage);
+        DrawingBuffer::kAllowChromiumImage, CanvasColorParams());
 
     // When we request a depth or a stencil buffer, we will get both.
     EXPECT_EQ(cases[i].request_depth || cases[i].request_stencil,
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h
index 7cc062f..35c078cc 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h
@@ -4,6 +4,7 @@
 
 #include "gpu/command_buffer/common/capabilities.h"
 #include "platform/RuntimeEnabledFeatures.h"
+#include "platform/graphics/CanvasColorParams.h"
 #include "platform/graphics/gpu/DrawingBuffer.h"
 #include "platform/graphics/gpu/Extensions3DUtil.h"
 #include "public/platform/WebGraphicsContext3DProvider.h"
@@ -61,7 +62,8 @@
             kWebGL1,
             false /* wantDepth */,
             false /* wantStencil */,
-            DrawingBuffer::kAllowChromiumImage /* ChromiumImageUsage */),
+            DrawingBuffer::kAllowChromiumImage /* ChromiumImageUsage */,
+            CanvasColorParams()),
         live_(0) {}
 
   ~DrawingBufferForTests() override {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
index c67d741..60db8457 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
@@ -328,7 +328,7 @@
                                          const AtomicString& value) {
   HTTPHeaderMap::AddResult result = http_header_fields_.Add(name, value);
   if (!result.is_new_entry)
-    result.stored_value->value = result.stored_value->value + ',' + value;
+    result.stored_value->value = result.stored_value->value + ", " + value;
 }
 
 void ResourceRequest::AddHTTPHeaderFields(const HTTPHeaderMap& header_fields) {
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index 22fd373b..a709fe17 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -73,8 +73,6 @@
     "ExternalDateTimeChooser.h",
     "ExternalPopupMenu.cpp",
     "ExternalPopupMenu.h",
-    "FindInPageCoordinates.cpp",
-    "FindInPageCoordinates.h",
     "FullscreenController.cpp",
     "FullscreenController.h",
     "IndexedDBClientImpl.cpp",
diff --git a/third_party/WebKit/Source/web/TextFinder.cpp b/third_party/WebKit/Source/web/TextFinder.cpp
index bf22601..905d4bd 100644
--- a/third_party/WebKit/Source/web/TextFinder.cpp
+++ b/third_party/WebKit/Source/web/TextFinder.cpp
@@ -34,6 +34,7 @@
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/dom/shadow/ShadowRoot.h"
 #include "core/editing/Editor.h"
+#include "core/editing/FindInPageCoordinates.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/iterators/SearchBuffer.h"
 #include "core/editing/markers/DocumentMarker.h"
@@ -52,7 +53,6 @@
 #include "public/web/WebFindOptions.h"
 #include "public/web/WebFrameClient.h"
 #include "public/web/WebViewClient.h"
-#include "web/FindInPageCoordinates.h"
 #include "web/WebLocalFrameImpl.h"
 #include "web/WebViewImpl.h"
 
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index d8e9cc2..0c15266 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -111,6 +111,7 @@
 #include "core/dom/shadow/ShadowRoot.h"
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/Editor.h"
+#include "core/editing/FindInPageCoordinates.h"
 #include "core/editing/FrameSelection.h"
 #include "core/editing/InputMethodController.h"
 #include "core/editing/PlainTextRange.h"
@@ -219,7 +220,6 @@
 #include "public/web/WebTreeScopeType.h"
 #include "skia/ext/platform_canvas.h"
 #include "web/CompositionUnderlineVectorBuilder.h"
-#include "web/FindInPageCoordinates.h"
 #include "web/RemoteFrameOwner.h"
 #include "web/SharedWorkerRepositoryClientImpl.h"
 #include "web/SuspendableScriptExecutor.h"
diff --git a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
index 12360428..3c3cf1a 100644
--- a/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
+++ b/third_party/WebKit/Source/web/tests/TextFinderTest.cpp
@@ -9,6 +9,7 @@
 #include "core/dom/NodeList.h"
 #include "core/dom/Range.h"
 #include "core/dom/shadow/ShadowRoot.h"
+#include "core/editing/FindInPageCoordinates.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/VisualViewport.h"
 #include "core/html/HTMLElement.h"
@@ -19,7 +20,6 @@
 #include "public/platform/Platform.h"
 #include "public/web/WebDocument.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "web/FindInPageCoordinates.h"
 #include "web/WebLocalFrameImpl.h"
 #include "web/tests/FrameTestHelpers.h"
 
diff --git a/third_party/WebKit/public/default_100_percent/blink/mediaremoting_cast.png b/third_party/WebKit/public/default_100_percent/blink/mediaremoting_cast.png
index 6188c7af..583f1a8 100644
--- a/third_party/WebKit/public/default_100_percent/blink/mediaremoting_cast.png
+++ b/third_party/WebKit/public/default_100_percent/blink/mediaremoting_cast.png
Binary files differ
diff --git a/third_party/WebKit/public/default_200_percent/blink/mediaremoting_cast.png b/third_party/WebKit/public/default_200_percent/blink/mediaremoting_cast.png
index 377c4e4..b2c5864 100644
--- a/third_party/WebKit/public/default_200_percent/blink/mediaremoting_cast.png
+++ b/third_party/WebKit/public/default_200_percent/blink/mediaremoting_cast.png
Binary files differ
diff --git a/third_party/WebKit/public/platform/WebPrivatePtr.h b/third_party/WebKit/public/platform/WebPrivatePtr.h
index 6de994e..1349d00 100644
--- a/third_party/WebKit/public/platform/WebPrivatePtr.h
+++ b/third_party/WebKit/public/platform/WebPrivatePtr.h
@@ -305,12 +305,12 @@
   T* Get() const { return Storage().Get(); }
 
   T& operator*() const {
-    ASSERT(storage_);
+    DCHECK(storage_);
     return *Get();
   }
 
   T* operator->() const {
-    ASSERT(storage_);
+    DCHECK(storage_);
     return Get();
   }
 #endif
diff --git a/third_party/WebKit/public/web/WebTextDirection.h b/third_party/WebKit/public/web/WebTextDirection.h
index 39686c8..c3718ec 100644
--- a/third_party/WebKit/public/web/WebTextDirection.h
+++ b/third_party/WebKit/public/web/WebTextDirection.h
@@ -53,7 +53,7 @@
     case TextDirection::kRtl:
       return kWebTextDirectionRightToLeft;
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return kWebTextDirectionDefault;
 }
 #endif
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index 4e3fd2d2..aae74a7 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -172,10 +172,10 @@
     "structures": [15920],
   },
   "components/resources/components_resources.grd": {
-    "includes": [15930],
+    "includes": [16030],
   },
   "components/resources/components_scaled_resources.grd": {
-    "structures": [16050],
+    "structures": [16150],
   },
   # END components/ section.
 
diff --git a/tools/licenses.py b/tools/licenses.py
index 97600d4..8d0310aa 100755
--- a/tools/licenses.py
+++ b/tools/licenses.py
@@ -19,6 +19,7 @@
 import cgi
 import os
 import shutil
+import re
 import subprocess
 import sys
 import tempfile
@@ -480,6 +481,22 @@
     return os.path.join(_REPOSITORY_ROOT, 'buildtools', subdir, exe)
 
 
+def GetThirdPartyDepsFromGNDepsOutput(gn_deps):
+    """Returns third_party/foo directories given the output of "gn desc deps".
+
+    Note that it always returns the direct sub-directory of third_party
+    where README.chromium and LICENSE files are, so that it can be passed to
+    ParseDir(). e.g.:
+        .../third_party/cld_3/src/src/BUILD.gn -> .../third_party/cld_3
+    """
+    third_party_deps = set()
+    for build_dep in gn_deps.split():
+        m = re.search(r'^(.+/third_party/[^/]+)/(.+/)?BUILD\.gn$', build_dep)
+        if m:
+            third_party_deps.add(m.group(1))
+    return third_party_deps
+
+
 def FindThirdPartyDeps(gn_out_dir, gn_target):
     if not gn_out_dir:
         raise RuntimeError("--gn-out-dir is required if --gn-target is used.")
@@ -500,12 +517,7 @@
         if tmp_dir and os.path.exists(tmp_dir):
             shutil.rmtree(tmp_dir)
 
-    third_party_deps = set()
-    for build_dep in gn_deps.split():
-        if ("third_party" in build_dep and
-                os.path.basename(build_dep) == "BUILD.gn"):
-            third_party_deps.add(os.path.dirname(build_dep))
-    return third_party_deps
+    return GetThirdPartyDepsFromGNDepsOutput(gn_deps)
 
 
 def ScanThirdPartyDirs(root=None):
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 97b63fd..d89cbc6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -20550,6 +20550,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Favicons.DownloadAttempts" units="attempts">
+  <owner>fhorschig@chromium.org</owner>
+  <summary>
+    Records the number of icons requested until the best-fitting candidate was
+    found or there were no candidates left to check. More than 15 attempts are
+    unlikely and will be stored in overflow bucket 16. Less than 1 attempt means
+    an error happened; these cases are in bucket 0.
+  </summary>
+</histogram>
+
 <histogram name="Favicons.LargeIconService.DownloadedSize" units="pixels">
   <owner>jkrcal@chromium.org</owner>
   <summary>
@@ -28435,6 +28445,14 @@
   <summary>Pixel format used in HTML5 video. Emitted on video load.</summary>
 </histogram>
 
+<histogram base="true" name="Media.VideoHeight.Initial" units="pixels">
+  <owner>media-dev@chromium.org</owner>
+  <summary>
+    The height of the first video frame in an HTML5 video. Reported when the
+    first video frame is available.
+  </summary>
+</histogram>
+
 <histogram name="Media.VideoPersistence.AttemptResult"
     enum="VideoPersistenceAttemptResult">
   <owner>mlamouri@chromium.org</owner>
@@ -120618,6 +120636,13 @@
   <affected-histogram name="Extensions.ExternalExtensionEvent"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="FaviconIconType" separator=".">
+  <suffix name="Favicons" label="Metrics for regular favicons."/>
+  <suffix name="LargeIcons" label="Metrics for large non-touch icons."/>
+  <suffix name="TouchIcons" label="Metrics for large touch icons."/>
+  <affected-histogram name="Favicons.DownloadAttempts"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="FieldPredictionSubmissionEvents" separator=".">
   <suffix name="NoSubmission" label="No observed submission."/>
   <suffix name="BasedOnAutocomplete"
@@ -121657,6 +121682,14 @@
   <affected-histogram name="Media.VideoCaptureManager"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="MediaVideoCategories" separator=".">
+  <suffix name="All" label="All media with a video track."/>
+  <suffix name="EME" label="EME media with a video track."/>
+  <suffix name="MSE" label="MSE media with a video track."/>
+  <suffix name="SRC" label="SRC media with a video track."/>
+  <affected-histogram name="Media.VideoHeight.Initial"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="MediaWatchTimeCategories" separator=".">
   <suffix name="Audio.All"
       label="Watch time for all media with only an audio track."/>
diff --git a/tools/tests/OWNERS b/tools/tests/OWNERS
new file mode 100644
index 0000000..68295e64
--- /dev/null
+++ b/tools/tests/OWNERS
@@ -0,0 +1 @@
+per-file licenses_test.py=file://tools/copyright_scanner/OWNERS
diff --git a/tools/tests/licenses_test.py b/tools/tests/licenses_test.py
new file mode 100755
index 0000000..3a25f88
--- /dev/null
+++ b/tools/tests/licenses_test.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# Copyright (c) 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.
+
+"""Unit tests for //tools/licenses.py.
+"""
+
+import os
+import sys
+import unittest
+
+REPOSITORY_ROOT = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '..', '..'))
+sys.path.append(os.path.join(REPOSITORY_ROOT, 'tools'))
+
+import licenses
+
+
+class LicensesTest(unittest.TestCase):
+
+    def test_get_third_party_deps_from_gn_deps_output(self):
+        third_party_deps = licenses.GetThirdPartyDepsFromGNDepsOutput(
+            '/home/example/src/net/BUILD.gn\n'
+            '/home/example/src/third_party/zlib/BUILD.gn\n'
+            '/home/example/src/third_party/cld_3/src/src/BUILD.gn\n')
+
+        # '/home/example/src/net' is not in the output because it's not a
+        # third_party dependency.
+        #
+        # It must return the direct sub-directory of "third_party". So it should
+        # return '/home/example/src/third_party/cld_3', not
+        # '/home/example/src/third_party/cld_3/src/src'.
+        assert third_party_deps == set([
+            '/home/example/src/third_party/zlib',
+            '/home/example/src/third_party/cld_3',
+        ])
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/ui/gfx/generic_shared_memory_id.cc b/ui/gfx/generic_shared_memory_id.cc
index 33a5ef0..e9ed1c9 100644
--- a/ui/gfx/generic_shared_memory_id.cc
+++ b/ui/gfx/generic_shared_memory_id.cc
@@ -9,7 +9,8 @@
 
 namespace gfx {
 
-base::trace_event::MemoryAllocatorDumpGuid GetGenericSharedMemoryGUIDForTracing(
+base::trace_event::MemoryAllocatorDumpGuid
+GetGenericSharedGpuMemoryGUIDForTracing(
     uint64_t tracing_process_id,
     GenericSharedMemoryId generic_shared_memory_id) {
   return base::trace_event::MemoryAllocatorDumpGuid(
diff --git a/ui/gfx/generic_shared_memory_id.h b/ui/gfx/generic_shared_memory_id.h
index b18c869e..c9675af 100644
--- a/ui/gfx/generic_shared_memory_id.h
+++ b/ui/gfx/generic_shared_memory_id.h
@@ -41,7 +41,7 @@
 // Generates GUID which can be used to trace shared memory using its
 // GenericSharedMemoryId.
 GFX_EXPORT base::trace_event::MemoryAllocatorDumpGuid
-GetGenericSharedMemoryGUIDForTracing(
+GetGenericSharedGpuMemoryGUIDForTracing(
     uint64_t tracing_process_id,
     GenericSharedMemoryId generic_shared_memory_id);
 
diff --git a/ui/gfx/gpu_memory_buffer.cc b/ui/gfx/gpu_memory_buffer.cc
index 3b85d06..185d461 100644
--- a/ui/gfx/gpu_memory_buffer.cc
+++ b/ui/gfx/gpu_memory_buffer.cc
@@ -4,6 +4,8 @@
 
 #include "ui/gfx/gpu_memory_buffer.h"
 
+#include "ui/gfx/generic_shared_memory_id.h"
+
 namespace gfx {
 
 GpuMemoryBufferHandle::GpuMemoryBufferHandle()
@@ -49,4 +51,10 @@
   return gfx::GpuMemoryBufferHandle();
 }
 
+base::trace_event::MemoryAllocatorDumpGuid GpuMemoryBuffer::GetGUIDForTracing(
+    uint64_t tracing_process_id) const {
+  return gfx::GetGenericSharedGpuMemoryGUIDForTracing(tracing_process_id,
+                                                      GetId());
+}
+
 }  // namespace gfx
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h
index df0112d..6d23c84 100644
--- a/ui/gfx/gpu_memory_buffer.h
+++ b/ui/gfx/gpu_memory_buffer.h
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 #include "base/memory/shared_memory.h"
+#include "base/trace_event/memory_allocator_dump_guid.h"
 #include "build/build_config.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/generic_shared_memory_id.h"
@@ -97,6 +98,10 @@
 
   // Type-checking downcast routine.
   virtual ClientBuffer AsClientBuffer() = 0;
+
+  // Returns the GUID for tracing.
+  virtual base::trace_event::MemoryAllocatorDumpGuid GetGUIDForTracing(
+      uint64_t tracing_process_id) const;
 };
 
 // Returns an instance of |handle| which can be sent over IPC. This duplicates
diff --git a/ui/gfx/gpu_memory_buffer_tracing.cc b/ui/gfx/gpu_memory_buffer_tracing.cc
index 86642b60..5f58707 100644
--- a/ui/gfx/gpu_memory_buffer_tracing.cc
+++ b/ui/gfx/gpu_memory_buffer_tracing.cc
@@ -4,16 +4,18 @@
 
 #include "ui/gfx/gpu_memory_buffer_tracing.h"
 
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
+
 namespace gfx {
 
-base::trace_event::MemoryAllocatorDumpGuid GetGpuMemoryBufferGUIDForTracing(
+base::trace_event::MemoryAllocatorDumpGuid GetSharedMemoryGUIDForTracing(
     uint64_t tracing_process_id,
     GpuMemoryBufferId buffer_id) {
-  // TODO(ericrk): Currently this function just wraps
-  // GetGenericSharedMemoryGUIDForTracing, we may want to special case this if
-  // the GPU memory buffer is not backed by shared memory.
-  return gfx::GetGenericSharedMemoryGUIDForTracing(tracing_process_id,
-                                                   buffer_id);
+  // TODO(hajimehoshi): This should be unified to shared memory GUIDs in
+  // base/memory/shared_memory_tracker.cc
+  return base::trace_event::MemoryAllocatorDumpGuid(base::StringPrintf(
+      "shared_memory_gpu/%" PRIx64 "/%d", tracing_process_id, buffer_id.id));
 }
 
 }  // namespace gfx
diff --git a/ui/gfx/gpu_memory_buffer_tracing.h b/ui/gfx/gpu_memory_buffer_tracing.h
index 5ea918c..0b66a91a 100644
--- a/ui/gfx/gpu_memory_buffer_tracing.h
+++ b/ui/gfx/gpu_memory_buffer_tracing.h
@@ -9,7 +9,7 @@
 namespace gfx {
 
 base::trace_event::MemoryAllocatorDumpGuid GFX_EXPORT
-GetGpuMemoryBufferGUIDForTracing(uint64_t tracing_process_id,
-                                 GpuMemoryBufferId buffer_id);
+GetSharedMemoryGUIDForTracing(uint64_t tracing_process_id,
+                              GpuMemoryBufferId buffer_id);
 
 }  // namespace gfx
diff --git a/ui/gl/gl_image_io_surface.mm b/ui/gl/gl_image_io_surface.mm
index 7bcb9626..8e20830 100644
--- a/ui/gl/gl_image_io_surface.mm
+++ b/ui/gl/gl_image_io_surface.mm
@@ -375,8 +375,8 @@
         base::trace_event::MemoryDumpManager::kInvalidTracingProcessId;
   }
 
-  auto guid =
-      GetGenericSharedMemoryGUIDForTracing(process_tracing_id, io_surface_id_);
+  auto guid = GetGenericSharedGpuMemoryGUIDForTracing(process_tracing_id,
+                                                      io_surface_id_);
   pmd->CreateSharedGlobalAllocatorDump(guid);
   pmd->AddOwnershipEdge(dump->guid(), guid);
 }
diff --git a/ui/gl/gl_image_shared_memory.cc b/ui/gl/gl_image_shared_memory.cc
index 83c8e5e..03f5aa87 100644
--- a/ui/gl/gl_image_shared_memory.cc
+++ b/ui/gl/gl_image_shared_memory.cc
@@ -13,6 +13,7 @@
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/gpu_memory_buffer_tracing.h"
 
 namespace gl {
 
@@ -87,8 +88,8 @@
                   base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                   static_cast<uint64_t>(size_in_bytes));
 
-  auto guid = GetGenericSharedMemoryGUIDForTracing(process_tracing_id,
-                                                   shared_memory_id_);
+  auto guid =
+      gfx::GetSharedMemoryGUIDForTracing(process_tracing_id, shared_memory_id_);
   pmd->CreateSharedGlobalAllocatorDump(guid);
   pmd->AddOwnershipEdge(dump->guid(), guid);
 }
diff --git a/ui/gl/yuv_to_rgb_converter.cc b/ui/gl/yuv_to_rgb_converter.cc
index 1cb715d..daef399 100644
--- a/ui/gl/yuv_to_rgb_converter.cc
+++ b/ui/gl/yuv_to_rgb_converter.cc
@@ -129,6 +129,7 @@
   glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture1_binding);
 
   // Allocate the rgb texture.
+  glActiveTexture(old_active_texture);
   glBindTexture(target, rgb_texture);
   glTexImage2D(target, 0, GL_RGB, size.width(), size.height(),
                0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc
index 2551fab8..bd731b7 100644
--- a/ui/message_center/views/message_list_view.cc
+++ b/ui/message_center/views/message_list_view.cc
@@ -312,7 +312,8 @@
   }
 
   if (!clearing_all_views_.empty()) {
-    AnimateClearingOneNotification();
+    if (!clear_all_started_)
+      AnimateClearingOneNotification();
     return;
   }