diff --git a/DEPS b/DEPS
index bee087b..2df13d7 100644
--- a/DEPS
+++ b/DEPS
@@ -43,7 +43,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'ce76b7cd4c1f35fc6d4473a38f27c78e4481aa1d',
+  'v8_revision': '20b025f9ca68e822ebcddb515f9300a5b8d995e7',
   # 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.
@@ -87,7 +87,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': 'eff184407eb183c8f6ec65d74abc4356d466f448',
+  'nacl_revision': 'c64289d884a477876419421b1a789e9fab58b940',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling dEQP
   # and whatever else without interference from each other.
@@ -215,7 +215,7 @@
    Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '067ab64dbee579393c17e5b80dfd3beffa3f39bf', # commit position 11616
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '4df8757c5f51f8f35d1728dac8bba3edd4a612e5', # commit position 11618
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
@@ -275,7 +275,7 @@
 
   'src/third_party/catapult':
     Var('chromium_git') + '/external/github.com/catapult-project/catapult.git' + '@' +
-    'e26797f24e90bac9118d1b18195804000da67b51',
+    'cd823453c2e0bdb3e1c15e58ef17365eb54d83da',
 
   'src/third_party/openh264/src':
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'b37cda248234162033e3e11b0335f3131cdfe488',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index e6805756..81b3710 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -1602,6 +1602,7 @@
                  r"^chrome/docs",
                  r"^components/dom_distiller/core/css/distilledpage_ios.css",
                  r"^components/flags_ui/resources/apple_flags.css",
+                 r"^components/neterror/resources/neterror.css",
                  r"^native_client_sdk"))
   file_filter = lambda f: input_api.FilterSourceFile(
       f, white_list=file_inclusion_pattern, black_list=black_list)
diff --git a/android_webview/native/state_serializer.cc b/android_webview/native/state_serializer.cc
index 65eceb3..398b17e 100644
--- a/android_webview/native/state_serializer.cc
+++ b/android_webview/native/state_serializer.cc
@@ -31,10 +31,7 @@
 
 namespace {
 
-// Sanity check value that we are restoring from a valid pickle.
-// This can potentially used as an actual serialization version number in the
-// future if we ever decide to support restoring from older versions.
-const uint32_t AW_STATE_VERSION = 20151204;
+const uint32_t AW_STATE_VERSION = internal::AW_STATE_VERSION_DATA_URL;
 
 }  // namespace
 
@@ -65,7 +62,10 @@
       return false;
   }
 
-  // Please update AW_STATE_VERSION if serialization format is changed.
+  // Please update AW_STATE_VERSION and IsSupportedVersion() if serialization
+  // format is changed.
+  // Make sure the serialization format is updated in a backwards compatible
+  // way.
 
   return true;
 }
@@ -75,7 +75,8 @@
   DCHECK(iterator);
   DCHECK(web_contents);
 
-  if (!internal::RestoreHeaderFromPickle(iterator))
+  uint32_t state_version = internal::RestoreHeaderFromPickle(iterator);
+  if (!state_version)
     return false;
 
   int entry_count = -1;
@@ -98,7 +99,8 @@
   entries.reserve(entry_count);
   for (int i = 0; i < entry_count; ++i) {
     entries.push_back(content::NavigationEntry::Create());
-    if (!internal::RestoreNavigationEntryFromPickle(iterator, entries[i].get()))
+    if (!internal::RestoreNavigationEntryFromPickle(state_version, iterator,
+                                                    entries[i].get()))
       return false;
 
     entries[i]->SetPageID(i);
@@ -136,22 +138,39 @@
 namespace internal {
 
 bool WriteHeaderToPickle(base::Pickle* pickle) {
-  return pickle->WriteUInt32(AW_STATE_VERSION);
+  return WriteHeaderToPickle(AW_STATE_VERSION, pickle);
 }
 
-bool RestoreHeaderFromPickle(base::PickleIterator* iterator) {
+bool WriteHeaderToPickle(uint32_t state_version, base::Pickle* pickle) {
+  return pickle->WriteUInt32(state_version);
+}
+
+uint32_t RestoreHeaderFromPickle(base::PickleIterator* iterator) {
   uint32_t state_version = -1;
   if (!iterator->ReadUInt32(&state_version))
-    return false;
+    return 0;
 
-  if (AW_STATE_VERSION != state_version)
-    return false;
+  if (IsSupportedVersion(state_version)) {
+    return state_version;
+  }
 
-  return true;
+  return 0;
+}
+
+bool IsSupportedVersion(uint32_t state_version) {
+  return state_version == internal::AW_STATE_VERSION_INITIAL ||
+         state_version == internal::AW_STATE_VERSION_DATA_URL;
 }
 
 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry,
                                   base::Pickle* pickle) {
+  return WriteNavigationEntryToPickle(AW_STATE_VERSION, entry, pickle);
+}
+
+bool WriteNavigationEntryToPickle(uint32_t state_version,
+                                  const content::NavigationEntry& entry,
+                                  base::Pickle* pickle) {
+  DCHECK(IsSupportedVersion(state_version));
   if (!pickle->WriteString(entry.GetURL().spec()))
     return false;
 
@@ -179,7 +198,7 @@
   if (!pickle->WriteString(entry.GetBaseURLForDataURL().spec()))
     return false;
 
-  {
+  if (state_version >= internal::AW_STATE_VERSION_DATA_URL) {
     const char* data = nullptr;
     size_t size = 0;
     scoped_refptr<const base::RefCountedString> s = entry.GetDataURLAsString();
@@ -202,13 +221,23 @@
   if (!pickle->WriteInt(entry.GetHttpStatusCode()))
     return false;
 
-  // Please update AW_STATE_VERSION if serialization format is changed.
+  // Please update AW_STATE_VERSION and IsSupportedVersion() if serialization
+  // format is changed.
+  // Make sure the serialization format is updated in a backwards compatible
+  // way.
 
   return true;
 }
 
 bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator,
                                       content::NavigationEntry* entry) {
+  return RestoreNavigationEntryFromPickle(AW_STATE_VERSION, iterator, entry);
+}
+
+bool RestoreNavigationEntryFromPickle(uint32_t state_version,
+                                      base::PickleIterator* iterator,
+                                      content::NavigationEntry* entry) {
+  DCHECK(IsSupportedVersion(state_version));
   {
     string url;
     if (!iterator->ReadString(&url))
@@ -274,7 +303,7 @@
     entry->SetBaseURLForDataURL(GURL(base_url_for_data_url));
   }
 
-  {
+  if (state_version >= internal::AW_STATE_VERSION_DATA_URL) {
     const char* data;
     int size;
     if (!iterator->ReadData(&data, &size))
diff --git a/android_webview/native/state_serializer.h b/android_webview/native/state_serializer.h
index b220ccf..644d5cca 100644
--- a/android_webview/native/state_serializer.h
+++ b/android_webview/native/state_serializer.h
@@ -5,6 +5,8 @@
 #ifndef ANDROID_WEBVIEW_NATIVE_STATE_SERIALIZER_H_
 #define ANDROID_WEBVIEW_NATIVE_STATE_SERIALIZER_H_
 
+#include <cstdint>
+
 #include "base/compiler_specific.h"
 
 namespace base {
@@ -37,16 +39,30 @@
 
 namespace internal {
 
-// Functions below are individual helper functiosn called by functions above.
+const uint32_t AW_STATE_VERSION_INITIAL = 20130814;
+const uint32_t AW_STATE_VERSION_DATA_URL = 20151204;
+
+// Functions below are individual helper functions called by functions above.
 // They are broken up for unit testing, and should not be called out side of
 // tests.
 bool WriteHeaderToPickle(base::Pickle* pickle) WARN_UNUSED_RESULT;
-bool RestoreHeaderFromPickle(base::PickleIterator* iterator) WARN_UNUSED_RESULT;
+bool WriteHeaderToPickle(uint32_t state_version,
+                         base::Pickle* pickle) WARN_UNUSED_RESULT;
+uint32_t RestoreHeaderFromPickle(base::PickleIterator* iterator)
+    WARN_UNUSED_RESULT;
+bool IsSupportedVersion(uint32_t state_version) WARN_UNUSED_RESULT;
 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry,
                                   base::Pickle* pickle) WARN_UNUSED_RESULT;
-bool RestoreNavigationEntryFromPickle(
-    base::PickleIterator* iterator,
-    content::NavigationEntry* entry) WARN_UNUSED_RESULT;
+bool WriteNavigationEntryToPickle(uint32_t state_version,
+                                  const content::NavigationEntry& entry,
+                                  base::Pickle* pickle) WARN_UNUSED_RESULT;
+bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator,
+                                      content::NavigationEntry* entry)
+    WARN_UNUSED_RESULT;
+bool RestoreNavigationEntryFromPickle(uint32_t state_version,
+                                      base::PickleIterator* iterator,
+                                      content::NavigationEntry* entry)
+    WARN_UNUSED_RESULT;
 
 }  // namespace interanl
 
diff --git a/android_webview/native/state_serializer_unittest.cc b/android_webview/native/state_serializer_unittest.cc
index a9671c6..9415367d 100644
--- a/android_webview/native/state_serializer_unittest.cc
+++ b/android_webview/native/state_serializer_unittest.cc
@@ -21,23 +21,9 @@
 
 namespace android_webview {
 
-TEST(AndroidWebViewStateSerializerTest, TestHeaderSerialization) {
-  base::Pickle pickle;
-  bool result = internal::WriteHeaderToPickle(&pickle);
-  EXPECT_TRUE(result);
+namespace {
 
-  base::PickleIterator iterator(pickle);
-  result = internal::RestoreHeaderFromPickle(&iterator);
-  EXPECT_TRUE(result);
-}
-
-TEST(AndroidWebViewStateSerializerTest, TestNavigationEntrySerialization) {
-  // This is required for NavigationEntry::Create.
-  content::ContentClient content_client;
-  content::SetContentClient(&content_client);
-  content::ContentBrowserClient browser_client;
-  content::SetBrowserClientForTesting(&browser_client);
-
+scoped_ptr<content::NavigationEntry> CreateNavigationEntry() {
   scoped_ptr<content::NavigationEntry> entry(
       content::NavigationEntry::Create());
 
@@ -73,6 +59,51 @@
   entry->SetIsOverridingUserAgent(is_overriding_user_agent);
   entry->SetTimestamp(timestamp);
   entry->SetHttpStatusCode(http_status_code);
+  return entry;
+}
+
+}  // namespace
+
+TEST(AndroidWebViewStateSerializerTest, TestHeaderSerialization) {
+  base::Pickle pickle;
+  bool result = internal::WriteHeaderToPickle(&pickle);
+  EXPECT_TRUE(result);
+
+  base::PickleIterator iterator(pickle);
+  uint32_t version = internal::RestoreHeaderFromPickle(&iterator);
+  EXPECT_GT(version, 0U);
+}
+
+TEST(AndroidWebViewStateSerializerTest, TestLegacyVersionHeaderSerialization) {
+  base::Pickle pickle;
+  bool result = internal::WriteHeaderToPickle(
+      internal::AW_STATE_VERSION_INITIAL, &pickle);
+  EXPECT_TRUE(result);
+
+  base::PickleIterator iterator(pickle);
+  uint32_t version = internal::RestoreHeaderFromPickle(&iterator);
+  EXPECT_EQ(version, internal::AW_STATE_VERSION_INITIAL);
+}
+
+TEST(AndroidWebViewStateSerializerTest,
+     TestUnsupportedVersionHeaderSerialization) {
+  base::Pickle pickle;
+  bool result = internal::WriteHeaderToPickle(20000101, &pickle);
+  EXPECT_TRUE(result);
+
+  base::PickleIterator iterator(pickle);
+  uint32_t version = internal::RestoreHeaderFromPickle(&iterator);
+  EXPECT_EQ(version, 0U);
+}
+
+TEST(AndroidWebViewStateSerializerTest, TestNavigationEntrySerialization) {
+  // This is required for NavigationEntry::Create.
+  content::ContentClient content_client;
+  content::SetContentClient(&content_client);
+  content::ContentBrowserClient browser_client;
+  content::SetBrowserClientForTesting(&browser_client);
+
+  scoped_ptr<content::NavigationEntry> entry(CreateNavigationEntry());
 
   base::Pickle pickle;
   bool result = internal::WriteNavigationEntryToPickle(*entry, &pickle);
@@ -83,19 +114,59 @@
   result = internal::RestoreNavigationEntryFromPickle(&iterator, copy.get());
   EXPECT_TRUE(result);
 
-  EXPECT_EQ(url, copy->GetURL());
-  EXPECT_EQ(virtual_url, copy->GetVirtualURL());
-  EXPECT_EQ(referrer.url, copy->GetReferrer().url);
-  EXPECT_EQ(referrer.policy, copy->GetReferrer().policy);
-  EXPECT_EQ(title, copy->GetTitle());
-  EXPECT_EQ(page_state, copy->GetPageState());
-  EXPECT_EQ(has_post_data, copy->GetHasPostData());
-  EXPECT_EQ(original_request_url, copy->GetOriginalRequestURL());
-  EXPECT_EQ(base_url_for_data_url, copy->GetBaseURLForDataURL());
-  EXPECT_EQ(data_url_as_string, copy->GetDataURLAsString()->data());
-  EXPECT_EQ(is_overriding_user_agent, copy->GetIsOverridingUserAgent());
-  EXPECT_EQ(timestamp, copy->GetTimestamp());
-  EXPECT_EQ(http_status_code, copy->GetHttpStatusCode());
+  EXPECT_EQ(entry->GetURL(), copy->GetURL());
+  EXPECT_EQ(entry->GetVirtualURL(), copy->GetVirtualURL());
+  EXPECT_EQ(entry->GetReferrer().url, copy->GetReferrer().url);
+  EXPECT_EQ(entry->GetReferrer().policy, copy->GetReferrer().policy);
+  EXPECT_EQ(entry->GetTitle(), copy->GetTitle());
+  EXPECT_EQ(entry->GetPageState(), copy->GetPageState());
+  EXPECT_EQ(entry->GetHasPostData(), copy->GetHasPostData());
+  EXPECT_EQ(entry->GetOriginalRequestURL(), copy->GetOriginalRequestURL());
+  EXPECT_EQ(entry->GetBaseURLForDataURL(), copy->GetBaseURLForDataURL());
+  EXPECT_EQ(entry->GetDataURLAsString()->data(),
+            copy->GetDataURLAsString()->data());
+  EXPECT_EQ(entry->GetIsOverridingUserAgent(),
+            copy->GetIsOverridingUserAgent());
+  EXPECT_EQ(entry->GetTimestamp(), copy->GetTimestamp());
+  EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode());
+}
+
+TEST(AndroidWebViewStateSerializerTest,
+     TestLegacyNavigationEntrySerialization) {
+  // This is required for NavigationEntry::Create.
+  content::ContentClient content_client;
+  content::SetContentClient(&content_client);
+  content::ContentBrowserClient browser_client;
+  content::SetBrowserClientForTesting(&browser_client);
+
+  scoped_ptr<content::NavigationEntry> entry(CreateNavigationEntry());
+
+  base::Pickle pickle;
+  bool result = internal::WriteNavigationEntryToPickle(
+      internal::AW_STATE_VERSION_INITIAL, *entry, &pickle);
+  EXPECT_TRUE(result);
+
+  scoped_ptr<content::NavigationEntry> copy(content::NavigationEntry::Create());
+  base::PickleIterator iterator(pickle);
+  result = internal::RestoreNavigationEntryFromPickle(
+      internal::AW_STATE_VERSION_INITIAL, &iterator, copy.get());
+  EXPECT_TRUE(result);
+
+  EXPECT_EQ(entry->GetURL(), copy->GetURL());
+  EXPECT_EQ(entry->GetVirtualURL(), copy->GetVirtualURL());
+  EXPECT_EQ(entry->GetReferrer().url, copy->GetReferrer().url);
+  EXPECT_EQ(entry->GetReferrer().policy, copy->GetReferrer().policy);
+  EXPECT_EQ(entry->GetTitle(), copy->GetTitle());
+  EXPECT_EQ(entry->GetPageState(), copy->GetPageState());
+  EXPECT_EQ(entry->GetHasPostData(), copy->GetHasPostData());
+  EXPECT_EQ(entry->GetOriginalRequestURL(), copy->GetOriginalRequestURL());
+  EXPECT_EQ(entry->GetBaseURLForDataURL(), copy->GetBaseURLForDataURL());
+  // DataURL not supported by 20130814 format
+  EXPECT_FALSE(copy->GetDataURLAsString());
+  EXPECT_EQ(entry->GetIsOverridingUserAgent(),
+            copy->GetIsOverridingUserAgent());
+  EXPECT_EQ(entry->GetTimestamp(), copy->GetTimestamp());
+  EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode());
 }
 
 TEST(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) {
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc
index f2bc5ed..285e95a 100644
--- a/base/time/time_mac.cc
+++ b/base/time/time_mac.cc
@@ -167,19 +167,23 @@
 
 // static
 Time Time::FromExploded(bool is_local, const Exploded& exploded) {
-  CFGregorianDate date;
-  date.second = exploded.second +
-      exploded.millisecond / static_cast<double>(kMillisecondsPerSecond);
-  date.minute = exploded.minute;
-  date.hour = exploded.hour;
-  date.day = exploded.day_of_month;
-  date.month = exploded.month;
-  date.year = exploded.year;
-
   base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
-      is_local ? CFTimeZoneCopySystem() : NULL);
-  CFAbsoluteTime seconds = CFGregorianDateGetAbsoluteTime(date, time_zone) +
-      kCFAbsoluteTimeIntervalSince1970;
+      is_local
+          ? CFTimeZoneCopySystem()
+          : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
+  base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
+      kCFAllocatorDefault, kCFGregorianCalendar));
+  CFCalendarSetTimeZone(gregorian, time_zone);
+  CFAbsoluteTime absolute_time;
+  // 'S' is not defined in componentDesc in Apple documentation, but can be
+  // found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
+  CFCalendarComposeAbsoluteTime(
+      gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month,
+      exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
+      exploded.millisecond);
+  // Milliseconds from |exploded| is added back to |absolute_time| here
+  // because CFCalendar parameters are integer values.
+  CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970;
   return Time(static_cast<int64_t>(seconds * kMicrosecondsPerSecond) +
               kWindowsEpochDeltaMicroseconds);
 }
@@ -195,19 +199,25 @@
                            kCFAbsoluteTimeIntervalSince1970;
 
   base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
-      is_local ? CFTimeZoneCopySystem() : NULL);
-  CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(seconds, time_zone);
-  // 1 = Monday, ..., 7 = Sunday.
-  int cf_day_of_week = CFAbsoluteTimeGetDayOfWeek(seconds, time_zone);
-
-  exploded->year = date.year;
-  exploded->month = date.month;
-  exploded->day_of_week = cf_day_of_week % 7;
-  exploded->day_of_month = date.day;
-  exploded->hour = date.hour;
-  exploded->minute = date.minute;
+      is_local
+          ? CFTimeZoneCopySystem()
+          : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
+  base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
+      kCFAllocatorDefault, kCFGregorianCalendar));
+  CFCalendarSetTimeZone(gregorian, time_zone);
+  int second, day_of_week;
+  // 'E' sets the day of week, but is not defined in componentDesc in Apple
+  // documentation. It can be found in open source code here:
+  // http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
+  CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE",
+                                  &exploded->year, &exploded->month,
+                                  &exploded->day_of_month, &exploded->hour,
+                                  &exploded->minute, &second, &day_of_week);
   // Make sure seconds are rounded down towards -infinity.
-  exploded->second = floor(date.second);
+  exploded->second = floor(second);
+  // |Exploded|'s convention for day of week is 0 = Sunday, i.e. different
+  // from CF's 1 = Sunday.
+  exploded->day_of_week = (day_of_week - 1) % 7;
   // Calculate milliseconds ourselves, since we rounded the |seconds|, making
   // sure to round towards -infinity.
   exploded->millisecond =
diff --git a/build/all.gyp b/build/all.gyp
index c62c52d..1984049 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -611,6 +611,7 @@
             '../gpu/gpu.gyp:gl_tests',
             '../gpu/gpu.gyp:angle_unittests',
             '../gpu/gpu.gyp:gpu_unittests',
+	    '../gpu/gpu.gyp:command_buffer_gles2_tests',
             '../third_party/catapult/telemetry/telemetry.gyp:*',
           ],
           'conditions': [
@@ -648,6 +649,7 @@
             '../gpu/gpu.gyp:gl_tests',
             '../gpu/gpu.gyp:angle_unittests',
             '../gpu/gpu.gyp:gpu_unittests',
+	    '../gpu/gpu.gyp:command_buffer_gles2_tests',
             '../third_party/catapult/telemetry/telemetry.gyp:*',
           ],
           'conditions': [
@@ -844,6 +846,7 @@
             '../content/content_shell_and_tests.gyp:content_gl_tests_apk',
             '../content/content_shell_and_tests.gyp:content_unittests_apk',
             '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest_apk',
+            '../gpu/gpu.gyp:command_buffer_gles2_tests_apk',
             '../gpu/gpu.gyp:gl_tests_apk',
             '../gpu/gpu.gyp:gpu_unittests_apk',
             '../ipc/ipc.gyp:ipc_tests_apk',
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index de8cbbad..8effb92 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -210,6 +210,7 @@
             '../content/content_shell_and_tests.gyp:content_unittests_apk',
             '../content/content_shell_and_tests.gyp:video_decode_accelerator_unittest_apk',
             '../device/device_tests.gyp:device_unittests_apk',
+            '../gpu/gpu.gyp:command_buffer_gles2_tests_apk',
             '../gpu/gpu.gyp:gl_tests_apk',
             '../gpu/gpu.gyp:gpu_perftests_apk',
             '../gpu/gpu.gyp:gpu_unittests_apk',
diff --git a/chrome/VERSION b/chrome/VERSION
index 08bff69..d12d335 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=50
 MINOR=0
-BUILD=2651
+BUILD=2652
 PATCH=0
diff --git a/chrome/android/java/res/layout/fre_choose_account.xml b/chrome/android/java/res/layout/fre_choose_account.xml
index de5e94e..b6bccdda 100644
--- a/chrome/android/java/res/layout/fre_choose_account.xml
+++ b/chrome/android/java/res/layout/fre_choose_account.xml
@@ -6,6 +6,7 @@
 -->
 <org.chromium.chrome.browser.firstrun.AccountFirstRunView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:id="@+id/fre_account_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
@@ -13,7 +14,7 @@
     <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginBottom="57dp"
+        android:layout_marginBottom="76dp"
         android:fillViewport="true"
         android:scrollbarStyle="outsideOverlay" >
 
@@ -59,6 +60,7 @@
                     android:paddingStart="24dp" >
 
                     <Spinner
+                        style="@style/Widget.AppCompat.Spinner.Underlined"
                         android:id="@+id/google_accounts_spinner"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
@@ -66,63 +68,86 @@
                         android:padding="0dp"
                         android:textColor="@color/fre_text_color" />
 
-                    <TextView
-                        android:id="@+id/description"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:gravity="center"
-                        android:lineSpacingMultiplier="1.4"
-                        android:text="@string/fre_account_choice_description"
-                        android:textColor="@color/fre_light_text_color"
-                        android:textSize="@dimen/fre_normal_text_size" />
+
+                    <FrameLayout
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content">
+                        
+                        <org.chromium.ui.widget.TextViewWithClickableSpans
+                            android:id="@+id/description"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:gravity="center_horizontal"
+                            android:lineSpacingMultiplier="1.4"
+                            android:text="@string/fre_account_choice_description"
+                            android:textColor="@color/fre_light_text_color"
+                            android:textSize="@dimen/fre_normal_text_size"
+                            android:visibility="visible"/>
+                            
+                        <!-- We use an invisible TextView overlapping with the visible one to keep
+                        the layout constant between text changes. This TextView will have its
+                        contents programmatically set to the longest string the above TextView can
+                        contain. -->
+                        
+                        <org.chromium.ui.widget.TextViewWithClickableSpans
+                            android:id="@+id/longest_description"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:gravity="center"
+                            android:lineSpacingMultiplier="1.4"
+                            android:textColor="@color/fre_light_text_color"
+                            android:textSize="@dimen/fre_normal_text_size"
+                            android:visibility="invisible"/>
+
+                    </FrameLayout>
+
                 </LinearLayout>
             </LinearLayout>
         </LinearLayout>
     </ScrollView>
 
-    <View android:id="@+id/button_bar_separator" 
-        style="@style/ButtonBarTopDivider"
-        android:layout_gravity="bottom"
-        android:layout_marginBottom="56dp" />
-
     <LinearLayout
         android:id="@+id/button_bar"
         android:layout_width="match_parent"
-        android:layout_height="56dp"
+        android:layout_height="76dp"
         android:layout_gravity="bottom"
-        android:orientation="horizontal" >
+        android:orientation="horizontal" 
+        android:padding="@dimen/fre_button_padding" >
 
         <!--suppress ButtonStyle -->
         <Button
             android:id="@+id/negative_button"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:background="?attr/listChoiceBackgroundIndicator"
-            android:gravity="start|center_vertical"
-            android:textDirection="locale"
-            android:paddingStart="@dimen/fre_button_padding"
-            android:paddingEnd="@dimen/fre_button_padding"
+            style="@style/ButtonCompatBorderless"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:text="@string/fre_skip_text"
             android:textAllCaps="true"
             android:textColor="@color/light_normal_color"
-            android:textSize="@dimen/fre_button_text_size" />
+            android:textSize="15sp" />
+
+        <View
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible"/>
 
         <!--suppress ButtonStyle -->
-        <Button
+        <org.chromium.ui.widget.ButtonCompat
             android:id="@+id/positive_button"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:background="?attr/listChoiceBackgroundIndicator"
-            android:gravity="end|center_vertical"
-            android:textDirection="locale"
-            android:paddingStart="@dimen/fre_button_padding"
-            android:paddingEnd="@dimen/fre_button_padding"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:text="@string/choose_account_sign_in"
             android:textAllCaps="true"
-            android:textColor="@color/light_active_color"
-            android:textSize="@dimen/fre_button_text_size" />
+            android:textColor="@android:color/white"
+            android:textSize="15sp"
+            chrome:buttonColor="@color/light_active_color" />
+
+        <View
+            android:id="@+id/positive_button_end_padding"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="gone"/>
     </LinearLayout>
 
 </org.chromium.chrome.browser.firstrun.AccountFirstRunView>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 3dede14..895151e 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -163,7 +163,7 @@
     <dimen name="badge_border_size">1.3dp</dimen>
 
     <!-- First Run Experience and Welcome Page dimensions -->
-    <dimen name="fre_button_padding">16dp</dimen>
+    <dimen name="fre_button_padding">12dp</dimen>
     <dimen name="fre_margin">24dp</dimen>
     <dimen name="fre_title_text_size">24sp</dimen>
     <dimen name="fre_button_text_size">14sp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSigninActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSigninActivity.java
index f75af4d..c359b91e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSigninActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSigninActivity.java
@@ -131,6 +131,11 @@
     }
 
     @Override
+    public void onAccountSelectionCancelled() {
+        finish();
+    };
+
+    @Override
     public ProfileDataCache getProfileDataCache() {
         if (mProfileDataCache == null) {
             mProfileDataCache = new ProfileDataCache(this, Profile.getLastUsedProfile());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
index 034fd89..8e57330 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
@@ -85,13 +85,13 @@
         if (titles.length == 1) {
             mSnackbarManager.showSnackbar(Snackbar.make(titles[0], this, Snackbar.TYPE_ACTION)
                     .setTemplateText(mContext.getString(R.string.undo_bar_delete_message))
-                    .setAction(mContext.getString(R.string.undo_bar_button_text), null));
+                    .setAction(mContext.getString(R.string.undo), null));
         } else {
             mSnackbarManager.showSnackbar(
                     Snackbar.make(String.format(Locale.getDefault(), "%d", titles.length), this,
                             Snackbar.TYPE_ACTION)
                     .setTemplateText(mContext.getString(R.string.undo_bar_multiple_delete_message))
-                    .setAction(mContext.getString(R.string.undo_bar_button_text), null));
+                    .setAction(mContext.getString(R.string.undo), null));
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java
index db5f742..be16f4c3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java
@@ -38,11 +38,6 @@
 
         mView.setListener(new AccountFirstRunView.Listener() {
             @Override
-            public void onAccountSelectionConfirmed(String accountName) {
-                mView.switchToSignedMode();
-            }
-
-            @Override
             public void onAccountSelectionCanceled() {
                 getPageDelegate().refuseSignIn();
                 advanceToNextPage();
@@ -54,14 +49,17 @@
             }
 
             @Override
-            public void onSigningInCompleted(String accountName) {
+            public void onAccountSelected(String accountName) {
                 getPageDelegate().acceptSignIn(accountName);
+            }
+
+            @Override
+            public void onDoneClicked() {
                 advanceToNextPage();
             }
 
             @Override
-            public void onSettingsButtonClicked(String accountName) {
-                getPageDelegate().acceptSignIn(accountName);
+            public void onSettingsClicked() {
                 getPageDelegate().askToOpenSyncSettings();
                 advanceToNextPage();
             }
@@ -72,6 +70,7 @@
                 // The user would have to go through the FRE again.
                 getPageDelegate().abortFirstRunExperience();
             }
+
         });
 
         mView.init(getPageDelegate().getProfileDataCache());
@@ -88,7 +87,6 @@
     @Override
     public void onStart() {
         super.onStart();
-        mView.setButtonsEnabled(true);
         mView.setProfileDataCache(getPageDelegate().getProfileDataCache());
         getPageDelegate().onSigninDialogShown();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java
index 002cd2e..856c7d2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunView.java
@@ -6,11 +6,13 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
-import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.text.TextPaint;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
 import android.util.AttributeSet;
-import android.view.Gravity;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
@@ -27,7 +29,8 @@
 import org.chromium.chrome.browser.profiles.ProfileDownloader;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.sync.signin.AccountManagerHelper;
-import org.chromium.ui.widget.ButtonCompat;
+import org.chromium.ui.text.SpanApplier;
+import org.chromium.ui.text.SpanApplier.SpanInfo;
 
 import java.util.List;
 
@@ -45,12 +48,6 @@
      */
     public interface Listener {
         /**
-         * The user selected an account.
-         * @param accountName The name of the account
-         */
-        public void onAccountSelectionConfirmed(String accountName);
-
-        /**
          * The user canceled account selection.
          */
         public void onAccountSelectionCanceled();
@@ -61,16 +58,24 @@
         public void onNewAccount();
 
         /**
-         * The user has been signed in and pressed 'Done' button.
+         * The user selected an account.
+         * This call will be followed by either {@link #onSettingsClicked} or
+         * {@link #onDoneClicked}.
          * @param accountName The name of the account
          */
-        public void onSigningInCompleted(String accountName);
+        public void onAccountSelected(String accountName);
 
         /**
-         * The user has signed in and pressed 'Settings' button.
-         * @param accountName The name of the account
+         * The user has completed the dialog flow.
+         * This will only be called after {@link #onAccountSelected} and should exit the View.
          */
-        public void onSettingsButtonClicked(String accountName);
+        public void onDoneClicked();
+
+        /**
+         * The user has selected to view sync settings.
+         * This will only be called after {@link #onAccountSelected} and should exit the View.
+         */
+        public void onSettingsClicked();
 
         /**
          * Failed to set the forced account because it wasn't found.
@@ -102,20 +107,27 @@
         }
     }
 
+    private static final String TAG = "AccountFirstRunView";
+
     private static final int EXPERIMENT_TITLE_VARIANT_MASK = 1;
     private static final int EXPERIMENT_SUMMARY_VARIANT_MASK = 2;
     private static final int EXPERIMENT_LAYOUT_VARIANT_MASK = 4;
     private static final int EXPERIMENT_MAX_VALUE = 7;
 
+    private static final String SETTINGS_LINK_OPEN = "<LINK1>";
+    private static final String SETTINGS_LINK_CLOSE = "</LINK1>";
+
     private AccountManagerHelper mAccountManagerHelper;
     private List<String> mAccountNames;
     private ArrayAdapter<CharSequence> mArrayAdapter;
     private ImageCarousel mImageCarousel;
     private Button mPositiveButton;
     private Button mNegativeButton;
+    private TextView mTitle;
     private TextView mDescriptionText;
     private Listener mListener;
     private Spinner mSpinner;
+    private Drawable mSpinnerBackground;
     private String mForcedAccountName;
     private String mAccountName;
     private String mAddAnotherAccount;
@@ -123,11 +135,14 @@
     private boolean mSignedIn;
     private boolean mPositionSetProgrammatically;
     private int mDescriptionTextId;
+    private int mCancelButtonTextId;
     private boolean mIsChildAccount;
     private boolean mHorizontalModeEnabled = true;
+    private boolean mShowSettingsSpan = true;
 
     public AccountFirstRunView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mAccountManagerHelper = AccountManagerHelper.get(getContext().getApplicationContext());
     }
 
     /**
@@ -157,30 +172,32 @@
 
         mPositiveButton = (Button) findViewById(R.id.positive_button);
         mNegativeButton = (Button) findViewById(R.id.negative_button);
-        mNegativeButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                setButtonsEnabled(false);
-                mListener.onAccountSelectionCanceled();
-            }
-        });
 
         // A workaround for Android support library ignoring padding set in XML. b/20307607
         int padding = getResources().getDimensionPixelSize(R.dimen.fre_button_padding);
         ApiCompatibilityUtils.setPaddingRelative(mPositiveButton, padding, 0, padding, 0);
         ApiCompatibilityUtils.setPaddingRelative(mNegativeButton, padding, 0, padding, 0);
 
+        mTitle = (TextView) findViewById(R.id.title);
         mDescriptionText = (TextView) findViewById(R.id.description);
+        // For the spans to be clickable.
+        mDescriptionText.setMovementMethod(LinkMovementMethod.getInstance());
         mDescriptionTextId = R.string.fre_account_choice_description;
 
+        // TODO(peconn): Ensure this is changed to R.string.cancel when used in Settings > Sign In.
+        mCancelButtonTextId = R.string.fre_skip_text;
+
+        // Set the invisible TextView to contain the longest text the visible TextView can hold.
+        // It assumes that the signed in description for child accounts is the longest text.
+        ((TextView) findViewById(R.id.longest_description)).setText(getSignedInDescription(true));
+
         mAddAnotherAccount = getResources().getString(R.string.fre_add_account);
 
         mSpinner = (Spinner) findViewById(R.id.google_accounts_spinner);
+        mSpinnerBackground = mSpinner.getBackground();
         mArrayAdapter = new ArrayAdapter<CharSequence>(
                 getContext().getApplicationContext(), R.layout.fre_spinner_text);
 
-        updateAccounts();
-
         mArrayAdapter.setDropDownViewResource(R.layout.fre_spinner_dropdown);
         mSpinner.setAdapter(mArrayAdapter);
         mSpinner.setOnItemSelectedListener(new SpinnerOnItemSelectedListener());
@@ -201,6 +218,8 @@
                 return super.performAccessibilityAction(host, action, args);
             }
         });
+
+        showSignInPage();
     }
 
     @Override
@@ -213,7 +232,12 @@
     public void onWindowVisibilityChanged(int visibility) {
         super.onWindowVisibilityChanged(visibility);
         if (visibility == View.VISIBLE) {
-            updateAccounts();
+            if (updateAccounts()) {
+                // A new account has been added and the visibility has returned to us.
+                // The updateAccounts function will have selected the new account.
+                // Shortcut to confirm sign in page.
+                showConfirmSignInPage();
+            }
         }
     }
 
@@ -244,33 +268,20 @@
     /**
      * Changes the visuals slightly for when this view appears in the recent tabs page instead of
      * in first run. For example, the title text is changed as well as the button style.
+     * This is currently used in the Recent Tabs Promo and the Enhanced Bookmark page.
      */
-    public void configureForRecentTabsPage() {
+    public void configureForRecentTabsOrBookmarksPage() {
         mHorizontalModeEnabled = false;
+        mShowSettingsSpan = false;
 
         setBackgroundResource(R.color.ntp_bg);
-        TextView title = (TextView) findViewById(R.id.title);
-        title.setText(R.string.sign_in_to_chrome);
+        mTitle.setText(R.string.sign_in_to_chrome);
 
-        // Remove the border above the button, swap in a new button with a blue material background,
-        // and center the button.
-        View buttonBarSeparator = findViewById(R.id.button_bar_separator);
-        buttonBarSeparator.setVisibility(View.GONE);
+        mCancelButtonTextId = R.string.cancel;
+        setUpCancelButton();
 
-        LinearLayout buttonContainer = (LinearLayout) findViewById(R.id.button_bar);
-        buttonContainer.setGravity(Gravity.CENTER_HORIZONTAL);
-        setPadding(0, 0, 0, getResources().getDimensionPixelOffset(
-                R.dimen.sign_in_promo_padding_bottom));
-
-        ButtonCompat positiveButton = new ButtonCompat(getContext(),
-                ApiCompatibilityUtils.getColor(getResources(), R.color.light_active_color));
-        positiveButton.setTextColor(Color.WHITE);
-        positiveButton.setLayoutParams(new LinearLayout.LayoutParams(
-                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
-
-        buttonContainer.removeView(mPositiveButton);
-        buttonContainer.addView(positiveButton);
-        mPositiveButton = positiveButton;
+        setPadding(0, 0, 0,
+                getResources().getDimensionPixelOffset(R.dimen.sign_in_promo_padding_bottom));
     }
 
     /**
@@ -281,9 +292,8 @@
         int experimentGroup = SigninManager.getAndroidSigninPromoExperimentGroup();
         assert experimentGroup >= 0 && experimentGroup <= EXPERIMENT_MAX_VALUE;
 
-        TextView title = (TextView) findViewById(R.id.title);
         if ((experimentGroup & EXPERIMENT_TITLE_VARIANT_MASK) != 0) {
-            title.setText(R.string.make_chrome_yours);
+            mTitle.setText(R.string.make_chrome_yours);
         }
 
         mDescriptionTextId = (experimentGroup & EXPERIMENT_SUMMARY_VARIANT_MASK) != 0
@@ -322,36 +332,21 @@
     }
 
     /**
-     * Tell the view whether or not the user can cancel account selection. In
-     * wizards, it makes sense to allow the user to skip account selection.
-     * However, in other settings-type contexts it does not make sense to allow
-     * this.
-     *
-     * @param canCancel Whether or not account selection can be canceled.
-     */
-    public void setCanCancel(boolean canCancel) {
-        mNegativeButton.setVisibility(canCancel ? View.VISIBLE : View.GONE);
-        mPositiveButton.setGravity(
-                canCancel ? Gravity.END | Gravity.CENTER_VERTICAL : Gravity.CENTER);
-    }
-
-    /**
      * Refresh the list of available system account.
+     * @return Whether any new accounts were added (the first newly added account will now be
+     *         selected).
      */
-    private void updateAccounts() {
-        if (mSignedIn) return;
-        setButtonsEnabled(true);
-
-        mAccountManagerHelper = AccountManagerHelper.get(getContext().getApplicationContext());
+    private boolean updateAccounts() {
+        if (mSignedIn) return false;
 
         List<String> oldAccountNames = mAccountNames;
         mAccountNames = mAccountManagerHelper.getGoogleAccountNames();
         int accountToSelect = 0;
-        if (mForcedAccountName != null) {
+        if (isInForcedAccountMode()) {
             accountToSelect = mAccountNames.indexOf(mForcedAccountName);
             if (accountToSelect < 0) {
                 mListener.onFailedToSetForcedAccount(mForcedAccountName);
-                return;
+                return false;
             }
         } else {
             accountToSelect = getIndexOfNewElement(
@@ -363,24 +358,14 @@
             mSpinner.setVisibility(View.VISIBLE);
             mArrayAdapter.addAll(mAccountNames);
             mArrayAdapter.add(mAddAnotherAccount);
-            mPositiveButton.setText(R.string.choose_account_sign_in);
-            mPositiveButton.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    mListener.onAccountSelectionConfirmed(mAccountName);
-                }
-            });
+
+            setUpSignInButton(true);
             mDescriptionText.setText(mDescriptionTextId);
+
         } else {
             mSpinner.setVisibility(View.GONE);
             mArrayAdapter.add(mAddAnotherAccount);
-            mPositiveButton.setText(R.string.fre_no_accounts);
-            mPositiveButton.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    mListener.onNewAccount();
-                }
-            });
+            setUpSignInButton(false);
             mDescriptionText.setText(R.string.fre_no_account_choice_description);
         }
 
@@ -390,6 +375,10 @@
         mSpinner.setSelection(accountToSelect);
         mAccountName = mArrayAdapter.getItem(accountToSelect).toString();
         mImageCarousel.scrollTo(accountToSelect, false, false);
+
+        return oldAccountNames != null
+                && !(oldAccountNames.size() == mAccountNames.size()
+                    && oldAccountNames.containsAll(mAccountNames));
     }
 
     /**
@@ -444,45 +433,146 @@
         if (!mSignedIn) return;
 
         String name = null;
-        if (mIsChildAccount) name = mProfileData.getGivenName(mAccountName);
-        if (name == null) name = mProfileData.getFullName(mAccountName);
+        if (mProfileData != null) {
+            if (mIsChildAccount) name = mProfileData.getGivenName(mAccountName);
+            if (name == null) name = mProfileData.getFullName(mAccountName);
+        }
         if (name == null) name = mAccountName;
         String text = String.format(getResources().getString(R.string.fre_hi_name), name);
-        ((TextView) findViewById(R.id.title)).setText(text);
+        mTitle.setText(text);
     }
 
     /**
      * Updates the view to show that sign in has completed.
      */
     public void switchToSignedMode() {
+        showConfirmSignInPage();
+    }
+
+    private void showSignInPage() {
+        mSignedIn = false;
+        mTitle.setText(R.string.sign_in_to_chrome);
+
+        mSpinner.setEnabled(true);
+        mSpinner.setBackground(mSpinnerBackground);
+        mImageCarousel.setVisibility(VISIBLE);
+
+        setUpCancelButton();
+        updateAccounts();
+
+        mImageCarousel.setSignedInMode(false);
+    }
+
+    private void showConfirmSignInPage() {
         mSignedIn = true;
         updateProfileName();
 
         mSpinner.setEnabled(false);
         mSpinner.setBackground(null);
-        mPositiveButton.setText(getResources().getText(R.string.fre_done));
-        mPositiveButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mListener.onSigningInCompleted(mAccountName);
-            }
-        });
-        mNegativeButton.setText(getResources().getText(R.string.fre_settings));
+        setUpConfirmButton();
+        setUpUndoButton();
+
+        if (mShowSettingsSpan) {
+            ClickableSpan settingsSpan = new ClickableSpan() {
+                @Override
+                public void onClick(View widget) {
+                    mListener.onAccountSelected(mAccountName);
+                    mListener.onSettingsClicked();
+                }
+
+                @Override
+                public void updateDrawState(TextPaint textPaint) {
+                    textPaint.setColor(textPaint.linkColor);
+                    textPaint.setUnderlineText(false);
+                }
+            };
+            mDescriptionText.setText(SpanApplier.applySpans(getSignedInDescription(mIsChildAccount),
+                    new SpanInfo(SETTINGS_LINK_OPEN, SETTINGS_LINK_CLOSE, settingsSpan)));
+        } else {
+            // If we aren't showing the span, get rid of the LINK1 annotations.
+            mDescriptionText.setText(getSignedInDescription(mIsChildAccount)
+                                             .replace(SETTINGS_LINK_OPEN, "")
+                                             .replace(SETTINGS_LINK_CLOSE, ""));
+        }
+
+        mImageCarousel.setVisibility(VISIBLE);
+        mImageCarousel.setSignedInMode(true);
+    }
+
+    private void setUpCancelButton() {
+        setNegativeButtonVisible(true);
+
+        mNegativeButton.setText(getResources().getText(mCancelButtonTextId));
         mNegativeButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                mListener.onSettingsButtonClicked(mAccountName);
+                setButtonsEnabled(false);
+                mListener.onAccountSelectionCanceled();
             }
         });
-        setButtonsEnabled(true);
-        String text = getResources().getString(R.string.fre_signed_in_description);
-        if (mIsChildAccount) {
-            text += "\n" + getResources().getString(
-                    R.string.fre_signed_in_description_uca_addendum);
+    }
+
+    private void setUpSignInButton(boolean hasAccounts) {
+        if (hasAccounts) {
+            mPositiveButton.setText(R.string.choose_account_sign_in);
+            mPositiveButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    showConfirmSignInPage();
+                }
+            });
+        } else {
+            mPositiveButton.setText(R.string.fre_no_accounts);
+            mPositiveButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mListener.onNewAccount();
+                }
+            });
         }
-        mDescriptionText.setText(text);
-        mImageCarousel.setVisibility(VISIBLE);
-        mImageCarousel.setSignedInMode();
+    }
+
+    private void setUpUndoButton() {
+        setNegativeButtonVisible(!isInForcedAccountMode());
+        if (isInForcedAccountMode()) return;
+
+        mNegativeButton.setText(getResources().getText(R.string.undo));
+        mNegativeButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showSignInPage();
+            }
+        });
+    }
+
+    private void setUpConfirmButton() {
+        mPositiveButton.setText(getResources().getText(R.string.fre_accept));
+        mPositiveButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mListener.onAccountSelected(mAccountName);
+                mListener.onDoneClicked();
+            }
+        });
+    }
+
+    private void setNegativeButtonVisible(boolean enabled) {
+        if (enabled) {
+            mNegativeButton.setVisibility(View.VISIBLE);
+            findViewById(R.id.positive_button_end_padding).setVisibility(View.GONE);
+        } else {
+            mNegativeButton.setVisibility(View.GONE);
+            findViewById(R.id.positive_button_end_padding).setVisibility(View.INVISIBLE);
+        }
+    }
+
+    private String getSignedInDescription(boolean childAccount) {
+        if (childAccount) {
+            return getResources().getString(R.string.fre_signed_in_description) + '\n'
+                    + getResources().getString(R.string.fre_signed_in_description_uca_addendum);
+        } else {
+            return getResources().getString(R.string.fre_signed_in_description);
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ImageCarousel.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ImageCarousel.java
index df5a61f..499bac2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ImageCarousel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ImageCarousel.java
@@ -151,6 +151,7 @@
     private float mPosition = 0f;
 
     private ImageCarouselPositionChangeListener mListener;
+    private ImageView mCheckmark;
     private int mLastPosition = 0;
     private boolean mNeedsPositionUpdates = true;
 
@@ -221,24 +222,33 @@
     }
 
     /**
-     * Sets the ImageCarousel to signed in mode that disables scrolling, animates away the
-     * background images, and displays a checkmark next to the account image that was chosen.
+     * Sets whether the ImageCarousel is in signed in mode. This mode disables scrolling, animates
+     * away the background images, and displays a checkmark next to the chosen account image.
+     * @param isSignedIn Whether the ImageCarousel should in signed in mode or not.
      */
-    public void setSignedInMode() {
-        mScrollingDisabled = true;
-        mAccountSelected = true;
+    public void setSignedInMode(boolean isSignedIn) {
+        if (isSignedIn == mAccountSelected) return;
+
+        mScrollingDisabled = isSignedIn;
+        mAccountSelected = isSignedIn;
         setPosition(getCenterPosition());
 
-        ImageView checkmark = new ImageView(getContext());
-        checkmark.setImageResource(R.drawable.verify_checkmark);
-        setLayoutParamsForCheckmark(checkmark);
-        addView(checkmark);
+        if (mCheckmark == null) {
+            mCheckmark = new ImageView(getContext());
+            mCheckmark.setImageResource(R.drawable.verify_checkmark);
+            setLayoutParamsForCheckmark(mCheckmark);
+            addView(mCheckmark);
+        }
 
         if (mFadeInOutAnimator != null) mFadeInOutAnimator.cancel();
         AnimatorSet animatorSet = new AnimatorSet();
-        animatorSet.playTogether(
-                ObjectAnimator.ofFloat(this, BACKGROUND_IMAGE_ALPHA, 0),
-                ObjectAnimator.ofFloat(checkmark, View.ALPHA, 0.0f, 1.0f));
+        if (isSignedIn) {
+            animatorSet.playTogether(ObjectAnimator.ofFloat(this, BACKGROUND_IMAGE_ALPHA, 0),
+                    ObjectAnimator.ofFloat(mCheckmark, View.ALPHA, 0.0f, 1.0f));
+        } else {
+            animatorSet.playTogether(ObjectAnimator.ofFloat(this, BACKGROUND_IMAGE_ALPHA, 1),
+                    ObjectAnimator.ofFloat(mCheckmark, View.ALPHA, 1.0f, 0.0f));
+        }
         mFadeInOutAnimator = animatorSet;
         mFadeInOutAnimator.setDuration(ACCOUNT_SIGNED_IN_ANIMATION_DURATION_MS);
         mFadeInOutAnimator.start();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java
index 21b87a8..25b590b8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java
@@ -142,7 +142,7 @@
             Bitmap bitmap) {
         bitmap = getCroppedBitmap(bitmap);
         mCacheEntries.put(accountId, new CacheEntry(bitmap, fullName, givenName));
-        if (mObserver != null) mObserver.onProfileDownloaded(accountId, givenName, fullName,
+        if (mObserver != null) mObserver.onProfileDownloaded(accountId, fullName, givenName,
                 bitmap);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index c88469a..813a0dce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -616,7 +616,7 @@
         Context context = mNewTabPageView.getContext();
         Snackbar snackbar = Snackbar.make(context.getString(R.string.most_visited_item_removed),
                 mMostVisitedItemRemovedController, Snackbar.TYPE_ACTION)
-                .setAction(context.getString(R.string.undo_bar_button_text), url);
+                .setAction(context.getString(R.string.undo), url);
         mTab.getSnackbarManager().showSnackbar(snackbar);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
index c598cfa..54bff39 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
@@ -5,7 +5,9 @@
 package org.chromium.chrome.browser.ntp;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.graphics.Bitmap;
+import android.preference.PreferenceManager;
 
 import org.chromium.base.ObserverList;
 import org.chromium.base.ThreadUtils;
@@ -52,6 +54,8 @@
     }
 
     private static final int RECENTLY_CLOSED_MAX_TAB_COUNT = 5;
+    private static final String PREF_SIGNIN_PROMO_DECLINED =
+            "recent_tabs_signin_promo_declined";
 
     private final Profile mProfile;
     private final Tab mTab;
@@ -386,10 +390,25 @@
             return false;
         }
 
+        if (PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
+                PREF_SIGNIN_PROMO_DECLINED, false)) {
+            return false;
+        }
+
         return !AndroidSyncSettings.isSyncEnabled(mContext) || mForeignSessions.isEmpty();
     }
 
     /**
+     * Save that user tapped "No" button on the signin promo.
+     */
+    public void setSigninPromoDeclined() {
+        SharedPreferences.Editor sharedPreferencesEditor =
+                PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+        sharedPreferencesEditor.putBoolean(PREF_SIGNIN_PROMO_DECLINED, true);
+        sharedPreferencesEditor.apply();
+    }
+
+    /**
      * Collapse the sync promo.
      *
      * @param isCollapsed Whether the sync promo is collapsed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPromoView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPromoView.java
index 3ef19806..f84cdee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPromoView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPromoView.java
@@ -93,6 +93,11 @@
          * Called when user attempts to create a new account.
          */
         void onNewAccount();
+
+        /**
+         * Called when a user cancels the account sign in process.
+         */
+        void onAccountSelectionCancelled();
     }
 
     private static final int PROMO_TYPE_SIGN_IN = 0;
@@ -249,18 +254,14 @@
         signInPromoView.init(mModel.getProfileDataCache());
         signInPromoView.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
         ((FrameLayout.LayoutParams) signInPromoView.getLayoutParams()).gravity = Gravity.CENTER;
-        signInPromoView.configureForRecentTabsPage();
-        signInPromoView.setCanCancel(false);
+        signInPromoView.configureForRecentTabsOrBookmarksPage();
         signInPromoView.setListener(new AccountFirstRunView.Listener() {
-            @Override
-            public void onAccountSelectionConfirmed(String accountName) {
-                if (mUserActionListener != null) mUserActionListener.onAccountSelectionConfirmed();
-                SigninManager.get(mActivity).signIn(accountName, mActivity, null);
-            }
+            private String mAccountName;
 
             @Override
             public void onAccountSelectionCanceled() {
-                assert false : "Button should be hidden";
+                assert mUserActionListener != null;
+                mUserActionListener.onAccountSelectionCancelled();
             }
 
             @Override
@@ -271,12 +272,18 @@
             }
 
             @Override
-            public void onSigningInCompleted(String accountName) {
-                assert false : "Button should be hidden";
+            public void onAccountSelected(String accountName) {
+                mAccountName = accountName;
             }
 
             @Override
-            public void onSettingsButtonClicked(String accountName) {
+            public void onDoneClicked() {
+                if (mUserActionListener != null) mUserActionListener.onAccountSelectionConfirmed();
+                SigninManager.get(mActivity).signIn(mAccountName, mActivity, null);
+            }
+
+            @Override
+            public void onSettingsClicked() {
                 assert false : "Button should be hidden";
             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java
index 2b70b635..6afa1e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java
@@ -603,6 +603,11 @@
                             public void onNewAccount() {
                                 RecordUserAction.record("Signin_AddAccountToDevice");
                             }
+                            @Override
+                            public void onAccountSelectionCancelled() {
+                                mRecentTabsManager.setSigninPromoDeclined();
+                                notifyDataSetChanged();
+                            }
                         });
             }
             if (!mRecentTabsManager.isSignedIn()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoScreen.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoScreen.java
index 96ac59b..b72e672 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoScreen.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoScreen.java
@@ -35,6 +35,7 @@
         extends AlwaysDismissedDialog implements AccountFirstRunView.Listener {
     private AccountFirstRunView mAccountFirstRunView;
     private ProfileDataCache mProfileDataCache;
+    private String mAccountName;
 
     /**
      * Launches the signin promo if it needs to be displayed.
@@ -98,26 +99,6 @@
         mProfileDataCache.destroy();
         mProfileDataCache = null;
     }
-
-    @Override
-    public void onAccountSelectionConfirmed(String accountName) {
-        Activity activity = getOwnerActivity();
-        RecordUserAction.record("Signin_Signin_FromSigninPromo");
-        SigninManager.get(activity).signIn(accountName, activity, new SignInCallback() {
-            @Override
-            public void onSignInComplete() {
-                mAccountFirstRunView.switchToSignedMode();
-                SigninPromoUma.recordAction(SigninPromoUma.SIGNIN_PROMO_ACCEPTED);
-            }
-
-            @Override
-            public void onSignInAborted() {
-                SigninPromoUma.recordAction(SigninPromoUma.SIGNIN_PROMO_DECLINED);
-                dismiss();
-            }
-        });
-    }
-
     @Override
     public void onAccountSelectionCanceled() {
         SigninPromoUma.recordAction(SigninPromoUma.SIGNIN_PROMO_DECLINED);
@@ -130,17 +111,36 @@
     }
 
     @Override
-    public void onSigningInCompleted(String accountName) {
-        dismiss();
+    public void onAccountSelected(String accountName) {
+        mAccountName = accountName;
     }
 
     @Override
-    public void onSettingsButtonClicked(String accountName) {
+    public void onDoneClicked() {
+        Activity activity = getOwnerActivity();
+        RecordUserAction.record("Signin_Signin_FromSigninPromo");
+        SigninManager.get(activity).signIn(mAccountName, activity, new SignInCallback() {
+            @Override
+            public void onSignInComplete() {
+                SigninManager.get(getOwnerActivity()).logInSignedInUser();
+                SigninPromoUma.recordAction(SigninPromoUma.SIGNIN_PROMO_ACCEPTED);
+            }
+
+            @Override
+            public void onSignInAborted() {
+                SigninPromoUma.recordAction(SigninPromoUma.SIGNIN_PROMO_DECLINED);
+                dismiss();
+            }
+        });
+    }
+
+    @Override
+    public void onSettingsClicked() {
         if (ProfileSyncService.get() != null) {
             Intent intent = PreferencesLauncher.createIntentForSettingsPage(getContext(),
                     SyncCustomizationFragment.class.getName());
             Bundle args = new Bundle();
-            args.putString(SyncCustomizationFragment.ARGUMENT_ACCOUNT, accountName);
+            args.putString(SyncCustomizationFragment.ARGUMENT_ACCOUNT, mAccountName);
             intent.putExtra(Preferences.EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
             getContext().startActivity(intent);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java
index d77aaef..fe35884d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java
@@ -129,7 +129,7 @@
                 TAB_CLOSE_UNDO_TOAST_COUNT);
         mSnackbarManager.showSnackbar(Snackbar.make(content, this, Snackbar.TYPE_ACTION)
                 .setTemplateText(mContext.getString(R.string.undo_bar_close_message))
-                .setAction(mContext.getString(R.string.undo_bar_button_text), tabId));
+                .setAction(mContext.getString(R.string.undo), tabId));
     }
 
     /**
@@ -144,7 +144,7 @@
         String content = String.format(Locale.getDefault(), "%d", closedTabIds.size());
         mSnackbarManager.showSnackbar(Snackbar.make(content, this, Snackbar.TYPE_ACTION)
                 .setTemplateText(mContext.getString(R.string.undo_bar_close_all_message))
-                .setAction(mContext.getString(R.string.undo_bar_button_text), closedTabIds));
+                .setAction(mContext.getString(R.string.undo), closedTabIds));
 
     }
 
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 9b71ce5..dbae249 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -170,6 +170,9 @@
       <message name="IDS_NEXT" desc="Generic label for a button to advance to the next item. [CHAR-LIMIT=20]">
         Next
       </message>
+      <message name="IDS_UNDO" desc="Generic label for a button to undo the previous action.">
+        Undo
+      </message>
 
       <!-- Main Preferences -->
       <message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
@@ -1586,7 +1589,10 @@
         Set up Chrome
       </message>
       <message name="IDS_FRE_ACCOUNT_CHOICE_DESCRIPTION" desc="Text for account chooser page">
-        Select an account to get your bookmarks, history, passwords, and other settings on all your devices.
+        Sign in to get your bookmarks, history, passwords, and other settings on all your devices.
+      </message>
+      <message name="IDS_FRE_ACCEPT" desc="Text for button to accept being signed in">
+        OK, got it
       </message>
       <message name="IDS_FRE_SKIP_TEXT" desc="Text for second page skip button">
         No thanks
@@ -1619,7 +1625,7 @@
         Hi, <ph name="FULL_NAME">%1$s<ex>John Smith</ex></ph>
       </message>
       <message name="IDS_FRE_SIGNED_IN_DESCRIPTION" desc="Explanation of what gets synced after the user signed in">
-        Your bookmarks, history, passwords, and other settings will be synced to your Google Account.
+        Your bookmarks, history, passwords, and other settings will be synced to your Google Account so you can use them on all your devices. You can choose what to sync in <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Settings<ph name="END_LINK1">&lt;/LINK1&gt;</ph>.
       </message>
       <message name="IDS_FRE_SIGNED_IN_DESCRIPTION_UCA_ADDENDUM" desc="Additional explanation for child accounts that synced settings are managed by parents.">
         Your parents help manage these settings.
@@ -2262,9 +2268,6 @@
       <message name="IDS_UNDO_BAR_MULTIPLE_DELETE_MESSAGE" desc="Message shown when you can undo several bookmark delete actions.">
         <ph name="NUMBER_OF_BOOKMARKS">%1$s<ex>3</ex></ph> bookmarks deleted
       </message>
-      <message name="IDS_UNDO_BAR_BUTTON_TEXT" desc="Button text to undo closing a tab.">
-        Undo
-      </message>
 
       <!-- MultiWindow -->
       <message name="IDS_UNSUPPORTED_NUMBER_OF_WINDOWS" desc="Popup message for when the user has tried to start too many concurrent versions of Chrome.">
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 69aacd6..cf1dd246 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -247,7 +247,6 @@
         <structure type="chrome_scaled_image" name="IDR_ENABLE_DEBUGGING_FAILURE" file="cros/enable_debugging_failure.png" />
         <structure type="chrome_scaled_image" name="IDR_ENABLE_DEBUGGING_SUCCESS" file="cros/enable_debugging_success.png" />
       </if>
-      <structure type="chrome_scaled_image" name="IDR_ERROR_NETWORK_GENERIC" file="common/error_network_generic.png" />
       <structure type="chrome_scaled_image" name="IDR_ERROR_NETWORK_OFFLINE" file="common/error_network_offline.png" />
       <if expr="enable_extensions">
         <structure type="chrome_scaled_image" name="IDR_EXTENSIONS_FAVICON" file="common/favicon_extensions.png" />
@@ -500,7 +499,6 @@
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP" file="common/omnibox_popup_border_and_shadow_top.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP_LEFT" file="common/omnibox_popup_border_and_shadow_top_left.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW_TOP_RIGHT" file="common/omnibox_popup_border_and_shadow_top_right.png" />
-      <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SEARCH_BUTTON_LOUPE" file="common/omnibox_search_button_loupe.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SEARCH_SELECTED" file="common/omnibox_search_selected.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM" file="common/omnibox_selected_keyword_bubble_bottom.png" />
       <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SELECTED_KEYWORD_BUBBLE_BOTTOM_LEFT" file="common/omnibox_selected_keyword_bubble_bottom_left.png" />
diff --git a/chrome/browser/android/profiles/profile_downloader_android.cc b/chrome/browser/android/profiles/profile_downloader_android.cc
index 635689d7..eba72f1 100644
--- a/chrome/browser/android/profiles/profile_downloader_android.cc
+++ b/chrome/browser/android/profiles/profile_downloader_android.cc
@@ -193,6 +193,15 @@
   AccountTrackerService* account_tracker_service =
       AccountTrackerServiceFactory::GetForProfile(profile);
 
+  AccountInfo account_info =
+      account_tracker_service->FindAccountInfoByEmail(email);
+
+  if (account_info.account_id.empty()) {
+      LOG(ERROR) << "Attempted to get AccountInfo for account not in the "
+          << "AccountTrackerService";
+      return;
+  }
+
   AccountInfoRetriever* retriever = new AccountInfoRetriever(
       profile,
       account_tracker_service->FindAccountInfoByEmail(email).account_id, email,
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc
index 5c8b4af..533ccee 100644
--- a/chrome/browser/chrome_browser_field_trials.cc
+++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -29,15 +29,15 @@
 // create an appropriate allocator for such if so.
 void InstantiatePersistentHistograms() {
   if (base::FeatureList::IsEnabled(base::kPersistentHistogramsFeature)) {
-    const std::string allocator_name("BrowserMetrics");
+    const char kAllocatorName[] = "BrowserMetrics";
     // Create persistent/shared memory and allow histograms to be stored in it.
     // TODO(bcwhite): Update this with correct allocator and memory size.
     base::SetPersistentHistogramMemoryAllocator(
-        new base::LocalPersistentMemoryAllocator(1 << 20,     // 1 MiB
-                                                 0x4D5B9953,  // SHA1(B..M..A..)
-                                                 allocator_name));
+        new base::LocalPersistentMemoryAllocator(2 << 20,     // 2 MiB
+                                                 0x935DDD43,  // SHA1(B...M...)
+                                                 kAllocatorName));
     base::GetPersistentHistogramMemoryAllocator()->CreateTrackingHistograms(
-        allocator_name);
+        kAllocatorName);
   }
 }
 
diff --git a/chrome/browser/resources/chromeos/neterror.css b/chrome/browser/resources/chromeos/neterror.css
index 234c7cc..1b72f5d 100644
--- a/chrome/browser/resources/chromeos/neterror.css
+++ b/chrome/browser/resources/chromeos/neterror.css
@@ -40,14 +40,14 @@
    * renderer process, so embed the resource manually.
    */
   content: -webkit-image-set(
-      url(../../../renderer/resources/default_100_percent/common/error_network_generic.png) 1x,
-      url(../../../renderer/resources/default_200_percent/common/error_network_generic.png) 2x);
+      url(../../../../components/resources/default_100_percent/neterror/error_network_generic.png) 1x,
+      url(../../../../components/resources/default_200_percent/neterror/error_network_generic.png) 2x);
 }
 
 .icon-offline {
   content: -webkit-image-set(
-      url(../../../renderer/resources/default_100_percent/offline/100-error-offline.png) 1x,
-      url(../../../renderer/resources/default_200_percent/offline/200-error-offline.png) 2x);
+      url(../../../../components/neterror/resources/default_100_percent/offline/100-error-offline.png) 1x,
+      url(../../../../components/neterror/resources/default_200_percent/offline/200-error-offline.png) 2x);
 }
 
 #help-box-outer {
diff --git a/chrome/browser/resources/md_history/history.js b/chrome/browser/resources/md_history/history.js
index 50bf72dc..dc695a2 100644
--- a/chrome/browser/resources/md_history/history.js
+++ b/chrome/browser/resources/md_history/history.js
@@ -76,6 +76,8 @@
  */
 function historyResult(info, results) {
   $('history-list').addNewResults(results);
+  if (info.finished)
+    $('history-list').disableResultLoading();
 }
 
 /**
diff --git a/chrome/browser/resources/md_history/history_list.js b/chrome/browser/resources/md_history/history_list.js
index 421e713..9375739 100644
--- a/chrome/browser/resources/md_history/history_list.js
+++ b/chrome/browser/resources/md_history/history_list.js
@@ -27,6 +27,11 @@
     menuIdentifier: {
       type: Number,
       value: 0
+    },
+
+    resultLoadingDisabled_: {
+      type: Boolean,
+      value: false
     }
   },
 
@@ -69,6 +74,13 @@
   },
 
   /**
+   * Disables history result loading when there are no more history results.
+   */
+  disableResultLoading: function() {
+    this.resultLoadingDisabled_ = true;
+  },
+
+  /**
    * Adds the newly updated history results into historyData. Adds new fields
    * for each result.
    * @param {!Array<!HistoryEntry>} historyResults The new history results.
@@ -212,6 +224,9 @@
     // Close overflow menu on scroll.
     this.closeMenu();
 
+    if (this.resultLoadingDisabled_)
+      return;
+
     // Requests the next list of results when the scrollbar is near the bottom
     // of the window.
     var scrollOffset = 10;
diff --git a/chrome/browser/resources_util_unittest.cc b/chrome/browser/resources_util_unittest.cc
index 123b5790..c086aec 100644
--- a/chrome/browser/resources_util_unittest.cc
+++ b/chrome/browser/resources_util_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "grit/components_scaled_resources.h"
 #include "grit/theme_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/resources/grit/ui_resources.h"
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 64299a9..b417e35e 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -263,6 +263,7 @@
         '../components/components.gyp:translate_content_renderer',
         '../components/components.gyp:visitedlink_renderer',
         '../components/components.gyp:web_cache_renderer',
+        '../components/components_resources.gyp:components_resources',
         '../content/app/resources/content_resources.gyp:content_resources',
         '../content/app/strings/content_strings.gyp:content_strings',
         '../content/content.gyp:content_renderer',
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index e1143ac6..e821ee12 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -48,6 +48,7 @@
     "//components/password_manager/content/renderer",
     "//components/plugins/renderer",
     "//components/printing/renderer",
+    "//components/resources:components_resources",
     "//components/startup_metric_utils/common",
     "//components/translate/content/renderer",
     "//components/translate/core/common",
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index 6d32ec07..937c4d3 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -226,7 +226,6 @@
   source_map->RegisterSource("chromeWebViewInternal",
                              IDR_CHROME_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("chromeWebView", IDR_CHROME_WEB_VIEW_JS);
-  source_map->RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS);
 }
 
 void ChromeExtensionsDispatcherDelegate::RequireAdditionalModules(
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index c813b33..ca58825 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -16,7 +16,6 @@
 #include "build/build_config.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/render_messages.h"
-#include "chrome/grit/renderer_resources.h"
 #include "components/error_page/common/error_page_params.h"
 #include "components/error_page/common/localized_error.h"
 #include "components/error_page/common/net_error_info.h"
@@ -28,6 +27,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/resource_fetcher.h"
+#include "grit/components_resources.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
diff --git a/chrome/renderer/resources/extensions/inject_app_titlebar.js b/chrome/renderer/resources/extensions/inject_app_titlebar.js
deleted file mode 100644
index 9f2ba37..0000000
--- a/chrome/renderer/resources/extensions/inject_app_titlebar.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 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.
-
-exports.didCreateDocumentElement = function() {
-  var root = document.documentElement.createShadowRoot();
-  root.appendChild(document.createElement('style')).innerText =
-      // TODO(jeremya): switch this to use automatic inlining once grit
-      // supports inlining into JS. See http://crbug.com/146319.
-      "x-titlebar { height: 24px; width: 100%; " +
-        "position: fixed; left: 0; top: 0; }\n" +
-      "div { margin-top: 24px; position: absolute; top: 0px; width: 100%; " +
-        "-webkit-widget-region: region(control rectangle); }\n" +
-      ":-webkit-full-screen * { display: none; }\n" +
-      ":-webkit-full-screen-document * { display: none; }\n" +
-      "div:-webkit-full-screen, div:-webkit-full-screen-document { " +
-        "margin-top: 0; }\n" +
-      "button { -webkit-widget-region: region(control rectangle); }\n" +
-      "button.close { border: 0; background-color: transparent; " +
-      "width: 16px; height: 16px; " +
-      "position: absolute; right: 4px; top: 4px; }\n" +
-      "button.close { background-image: url(data:image/png;base64," +
-      "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA9ElEQVQ4T7VTQQ6CMBCk0H" +
-      "AyIfAQbiZ+QHyDL/QLxqvx4MWDB+MvFAWMAuKsacmmSjkQSDbQ2Z3Z3WkQzsBHDOQ7owgs" +
-      "MdUacTGmi3BeIFYcNycgciGlfFRVtcd3qoojz/PmdV0XOD8RGy1iCoQgT5G8IyREjni7IC" +
-      "cg58ilwA7A8i4BwgMUxkKIV9M0PggTAoFlJpnwLhO5iEuFapq2s20CyoWIGbpeaRICyrI8" +
-      "89FtAtqwGxdQ65yYsV8NcwVN5obR/uTJW4mQsfp2fgToGjPqbBjWeoJVfNRsbSskSO7+7B" +
-      "sAiznZdgu6Qe97lH+htysv+AA10msRAt5JYQAAAABJRU5ErkJggg==); }\n" +
-      "button.close:hover { background-image: url(data:image/png;base64," +
-      "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABTElEQVQ4T2NkoBAwUqifAc" +
-      "WA////KwANFAPiV4yMjA+QDcclBzcApCA6Otpz2bJluQkJCf3z58/fDTMEnxyyAWZADQuA" +
-      "tj4B4ncpKSnbZs+efQjkCqjBmUDmMyD+ADSwD6j2FEgOxQWJiYmuCxYscIYawpWamnr89+" +
-      "/fHECxbKjmB2VlZbs6OzsvwFyHEQZATXZz5syxAGr4BMR8QCwJDYvn1dXVO1taWi4ihw9G" +
-      "LID8m5aWZgt0viXUEBaQAUDNh9E1o3gBFuIgA6Be8QKK3QXiLyA5oNMvIDsdph7DC9AASw" +
-      "cquI9sAJDNk5GRcX769OlHsXoBKapAoQ2KiQcgPwMDkbGrq8sGyP8DChNQwM6aNeswRiAC" +
-      "DYBF4yOgwnuwAAM5NTMz03rGjBnWsIAFql2ANxqB/l2B7F/kgCUYjUBbyEvKsFAllaY4Nw" +
-      "IAmJDPEd+LFvYAAAAASUVORK5CYII=); }\n" +
-      "button.close:active { background-image: url(data:image/png;base64," +
-      "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAZ0lEQVQ4T2NkoBAwUqifge" +
-      "oG2AFd1AfERUB8CM11WOXQXXAGSROyITDNMGkTGAPdAHSFIENAAOQqGEBxHbYwQDcE2ScY" +
-      "XsMViNgMwRYuOGOBIgMo8gLFgUi1aCQ7IZGcNaieF0h2AQCMABwRdsuhtQAAAABJRU5Erk" +
-      "Jggg==); }\n"
-  var titlebar = root.appendChild(document.createElement('x-titlebar'));
-  var closeButton = titlebar.appendChild(document.createElement('button'));
-  closeButton.className = 'close'
-  closeButton.addEventListener('click', function() { window.close(); });
-  var container = root.appendChild(document.createElement('div'));
-  container.appendChild(document.createElement('content'));
-}
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index 731eead..732d4c6 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -19,7 +19,6 @@
       </if>
       <include name="IDR_BLOCKED_PLUGIN_HTML" file="plugins/blocked_plugin.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_DISABLED_PLUGIN_HTML" file="plugins/disabled_plugin.html" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_NET_ERROR_HTML" file="neterror.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_PLUGIN_POSTER_HTML" file="plugins/plugin_poster.html" flattenhtml="true" type="BINDATA" />
 
       <!-- Searchbox API -->
@@ -87,9 +86,6 @@
         <include name="IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS" file="extensions\tts_engine_custom_bindings.js" type="BINDATA" />
         <include name="IDR_WEBRTC_DESKTOP_CAPTURE_PRIVATE_CUSTOM_BINDINGS_JS" file="extensions\webrtc_desktop_capture_private_custom_bindings.js" type="BINDATA" />
         <include name="IDR_WEBSTORE_CUSTOM_BINDINGS_JS" file="extensions\webstore_custom_bindings.js" type="BINDATA" />
-
-        <!-- Platform app support. -->
-        <include name="IDR_INJECT_APP_TITLEBAR_JS" file="extensions\inject_app_titlebar.js" type="BINDATA" />
       </if>
     </includes>
   </release>
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index c178b5f7..998e476 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-7921.0.0
\ No newline at end of file
+7925.0.0
\ No newline at end of file
diff --git a/components/neterror/OWNERS b/components/neterror/OWNERS
new file mode 100644
index 0000000..0c27a2f
--- /dev/null
+++ b/components/neterror/OWNERS
@@ -0,0 +1,3 @@
+jar@chromium.org
+mmenke@chromium.org
+ttuttle@chromium.org
diff --git a/chrome/renderer/resources/default_100_percent/offline/100-disabled.png b/components/neterror/resources/default_100_percent/offline/100-disabled.png
similarity index 100%
rename from chrome/renderer/resources/default_100_percent/offline/100-disabled.png
rename to components/neterror/resources/default_100_percent/offline/100-disabled.png
Binary files differ
diff --git a/chrome/renderer/resources/default_100_percent/offline/100-error-offline.png b/components/neterror/resources/default_100_percent/offline/100-error-offline.png
similarity index 100%
rename from chrome/renderer/resources/default_100_percent/offline/100-error-offline.png
rename to components/neterror/resources/default_100_percent/offline/100-error-offline.png
Binary files differ
diff --git a/chrome/renderer/resources/default_100_percent/offline/100-offline-sprite.png b/components/neterror/resources/default_100_percent/offline/100-offline-sprite.png
similarity index 100%
rename from chrome/renderer/resources/default_100_percent/offline/100-offline-sprite.png
rename to components/neterror/resources/default_100_percent/offline/100-offline-sprite.png
Binary files differ
diff --git a/chrome/renderer/resources/default_200_percent/offline/200-disabled.png b/components/neterror/resources/default_200_percent/offline/200-disabled.png
similarity index 100%
rename from chrome/renderer/resources/default_200_percent/offline/200-disabled.png
rename to components/neterror/resources/default_200_percent/offline/200-disabled.png
Binary files differ
diff --git a/chrome/renderer/resources/default_200_percent/offline/200-error-offline.png b/components/neterror/resources/default_200_percent/offline/200-error-offline.png
similarity index 100%
rename from chrome/renderer/resources/default_200_percent/offline/200-error-offline.png
rename to components/neterror/resources/default_200_percent/offline/200-error-offline.png
Binary files differ
diff --git a/chrome/renderer/resources/default_200_percent/offline/200-offline-sprite.png b/components/neterror/resources/default_200_percent/offline/200-offline-sprite.png
similarity index 100%
rename from chrome/renderer/resources/default_200_percent/offline/200-offline-sprite.png
rename to components/neterror/resources/default_200_percent/offline/200-offline-sprite.png
Binary files differ
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css
new file mode 100644
index 0000000..b9ba88b
--- /dev/null
+++ b/components/neterror/resources/neterror.css
@@ -0,0 +1,472 @@
+/* Copyright 2013 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. */
+
+/* Don't use the main frame div when the error is in a subframe. */
+html[subframe] #main-frame-error {
+  display: none;
+}
+
+/* Don't use the subframe error div when the error is in a main frame. */
+html:not([subframe]) #sub-frame-error {
+  display: none;
+}
+
+#diagnose-button {
+  -webkit-margin-start: 0;
+  float: none;
+  margin-bottom: 10px;
+  margin-top: 20px;
+}
+
+h1 {
+  margin-top: 0;
+  word-wrap: break-word;
+}
+
+h1 span {
+  font-weight: 500;
+}
+
+h2 {
+  color: #666;
+  font-size: 1.2em;
+  font-weight: normal;
+  margin: 10px 0;
+}
+
+a {
+  color: rgb(17, 85, 204);
+  text-decoration: none;
+}
+
+.icon {
+  -webkit-user-select: none;
+  display: inline-block;
+}
+
+.icon-generic {
+  /**
+   * Can't access chrome://theme/IDR_ERROR_NETWORK_GENERIC from an untrusted
+   * renderer process, so embed the resource manually.
+   */
+  content: -webkit-image-set(
+      url(../../resources/default_100_percent/neterror/error_network_generic.png) 1x,
+      url(../../resources/default_200_percent/neterror/error_network_generic.png) 2x);
+}
+
+.icon-offline {
+  content: -webkit-image-set(
+      url(default_100_percent/offline/100-error-offline.png) 1x,
+      url(default_200_percent/offline/200-error-offline.png) 2x);
+  position: relative;
+}
+
+.icon-disabled {
+  content: -webkit-image-set(
+      url(default_100_percent/offline/100-disabled.png) 1x,
+      url(default_200_percent/offline/200-disabled.png) 2x);
+  width: 112px;
+}
+
+.error-code {
+  display: block;
+  font-size: .8em;
+}
+
+#content-top {
+  margin: 20px;
+}
+
+#help-box-inner {
+  background-color: #f9f9f9;
+  border-top: 1px solid #EEE;
+  color: #444;
+  padding: 20px;
+  text-align: start;
+}
+
+.hidden {
+  display: none;
+}
+
+#suggestion {
+  margin-top: 15px;
+}
+
+#short-suggestion {
+  margin-top: 5px;
+}
+
+#sub-frame-error-details {
+<if expr="is_ios">
+  font-size: 8pt;
+</if>
+  color: #8F8F8F;
+<if expr="not is_android and not is_ios">
+  /* Not done on mobile for performance reasons. */
+  text-shadow: 0 1px 0 rgba(255,255,255,0.3);
+</if>
+}
+
+[jscontent=failedUrl] {
+  overflow-wrap: break-word;
+}
+
+#search-container {
+  /* Prevents a space between controls. */
+  display: flex;
+  margin-top: 20px;
+}
+
+#search-box {
+  border: 1px solid #cdcdcd;
+  flex-grow: 1;
+  font-size: 1em;
+  height: 26px;
+  margin-right: 0;
+  padding: 1px 9px;
+}
+
+#search-box:focus {
+  border: 1px solid rgb(93, 154, 255);
+  outline: none;
+}
+
+#search-button {
+  border: none;
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+  box-shadow: none;
+  display: flex;
+  height: 30px;
+  margin: 0;
+  padding: 0;
+  width: 60px;
+}
+
+#search-image {
+  content:
+      -webkit-image-set(
+          url(../../resources/default_100_percent/omnibox/omnibox_search_button_loupe.png) 1x,
+          url(../../resources/default_200_percent/omnibox/omnibox_search_button_loupe.png) 2x);
+  margin: auto;
+}
+
+.secondary-button {
+  -webkit-margin-end: 16px;
+  background: #d9d9d9;
+  color: #696969;
+}
+
+.snackbar {
+  background: #323232;
+  border-radius: 2px;
+  bottom: 24px;
+  box-sizing: border-box;
+  color: #fff;
+  font-size: .87em;
+  left: 24px;
+  max-width: 568px;
+  min-width: 288px;
+  opacity: 0;
+  padding: 16px 24px 12px;
+  position: fixed;
+  transform: translateY(90px);
+  will-change: opacity, transform;
+  z-index: 999;
+}
+
+.snackbar-show {
+  -webkit-animation:
+    show-snackbar .25s cubic-bezier(0.0, 0.0, 0.2, 1) forwards,
+    hide-snackbar .25s cubic-bezier(0.4, 0.0, 1, 1) forwards 5s;
+}
+
+@-webkit-keyframes show-snackbar {
+  100% {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+@-webkit-keyframes hide-snackbar {
+  0% {
+    opacity: 1;
+    transform: translateY(0);
+  }
+  100% {
+    opacity: 0;
+    transform: translateY(90px);
+  }
+}
+
+.suggestions {
+  margin-top: 18px;
+}
+
+.suggestion-header {
+  font-weight: bold;
+  margin-bottom: 4px;
+}
+
+.suggestion-body {
+  color: #777;
+}
+
+/* Increase line height at higher resolutions. */
+@media (min-width: 641px) and (min-height: 641px) {
+  #help-box-inner {
+    line-height: 18px;
+  }
+}
+
+/* Decrease padding at low sizes. */
+@media (max-width: 640px), (max-height: 640px) {
+  h1 {
+    margin: 0 0 15px;
+  }
+  #content-top {
+    margin: 15px;
+  }
+  #help-box-inner {
+    padding: 20px;
+  }
+  .suggestions {
+    margin-top: 10px;
+  }
+  .suggestion-header {
+    margin-bottom: 0;
+  }
+}
+
+/* Don't allow overflow when in a subframe. */
+html[subframe] body {
+  overflow: hidden;
+}
+
+#sub-frame-error {
+  -webkit-align-items: center;
+  background-color: #DDD;
+  display: -webkit-flex;
+  -webkit-flex-flow: column;
+  height: 100%;
+  -webkit-justify-content: center;
+  left: 0;
+  position: absolute;
+  top: 0;
+  transition: background-color .2s ease-in-out;
+  width: 100%;
+}
+
+#sub-frame-error:hover {
+  background-color: #EEE;
+}
+
+#sub-frame-error .icon-generic {
+  margin: 0 0 16px;
+}
+
+#sub-frame-error-details {
+  margin: 0 10px;
+  text-align: center;
+  visibility: hidden;
+}
+
+/* Show details only when hovering. */
+#sub-frame-error:hover #sub-frame-error-details {
+  visibility: visible;
+}
+
+/* If the iframe is too small, always hide the error code. */
+/* TODO(mmenke): See if overflow: no-display works better, once supported. */
+@media (max-width: 200px), (max-height: 95px) {
+  #sub-frame-error-details {
+    display: none;
+  }
+}
+
+/* Adjust icon for small embedded frames in apps. */
+@media (max-height: 100px) {
+  #sub-frame-error .icon-generic {
+    height: auto;
+    margin: 0;
+    padding-top: 0;
+    width: 25px;
+  }
+}
+
+/* details-button is special; it's a <button> element that looks like a link. */
+#details-button {
+  box-shadow: none;
+  min-width: 0;
+}
+
+/* Styles for platform dependent separation of controls and details button. */
+.suggested-left > #control-buttons,
+.suggested-left #stale-load-button,
+.suggested-right > #details-button {
+  float: left;
+}
+
+.suggested-right > #control-buttons,
+.suggested-right #stale-load-button,
+.suggested-left > #details-button {
+  float: right;
+}
+
+.suggested-left .secondary-button {
+  -webkit-margin-end: 0px;
+  -webkit-margin-start: 16px;
+}
+
+#details-button.singular {
+  float: none;
+}
+
+#buttons::after {
+  clear: both;
+  content: '';
+  display: block;
+  width: 100%;
+}
+
+/* Offline page */
+.offline {
+  transition: -webkit-filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1),
+              background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
+  will-change: -webkit-filter, background-color;
+}
+
+.offline.inverted {
+  -webkit-filter: invert(100%);
+  background-color: #000;
+}
+
+.offline .interstitial-wrapper {
+  color: #2b2b2b;
+  font-size: 1em;
+  line-height: 1.55;
+  margin: 0 auto;
+  max-width: 600px;
+  padding-top: 100px;
+  width: 100%;
+}
+
+.offline .runner-container {
+  height: 150px;
+  max-width: 600px;
+  overflow: hidden;
+  position: absolute;
+  top: 35px;
+  width: 44px;
+}
+
+.offline .runner-canvas {
+  height: 150px;
+  max-width: 600px;
+  opacity: 1;
+  overflow: hidden;
+  position: absolute;
+  top: 0;
+  z-index: 2;
+}
+
+.offline .controller {
+  background: rgba(247,247,247, .1);
+  height: 100vh;
+  left: 0;
+  position: absolute;
+  top: 0;
+  width: 100vw;
+  z-index: 1;
+}
+
+#offline-resources {
+  display: none;
+}
+
+@media (max-width: 420px) {
+  .suggested-left > #control-buttons,
+  .suggested-right > #control-buttons {
+    float: none;
+  }
+
+  .snackbar {
+    left: 0;
+    bottom: 0;
+    width: 100%;
+    border-radius: 0;
+  }
+}
+
+@media (max-height: 350px) {
+  h1 {
+    margin: 0 0 15px;
+  }
+
+  .icon-offline {
+    margin: 0 0 10px;
+  }
+
+  .interstitial-wrapper {
+    margin-top: 5%;
+  }
+
+  .nav-wrapper {
+    margin-top: 30px;
+  }
+}
+
+@media (min-width: 600px) and (max-width: 736px) and (orientation: landscape) {
+  .offline .interstitial-wrapper {
+    margin-left: 0;
+    margin-right: 0;
+  }
+}
+
+@media (min-width: 420px) and (max-width: 736px) and
+       (min-height: 240px) and (max-height: 420px) and
+       (orientation:landscape) {
+  .interstitial-wrapper {
+    margin-bottom: 100px;
+  }
+}
+
+@media (min-height: 240px) and (orientation: landscape) {
+  .offline .interstitial-wrapper {
+    margin-bottom: 90px;
+  }
+
+  .icon-offline {
+    margin-bottom: 20px;
+  }
+}
+
+@media (max-height: 320px) and (orientation: landscape) {
+  .icon-offline {
+    margin-bottom: 0;
+  }
+
+  .offline .runner-container {
+    top: 10px;
+  }
+}
+
+@media (max-width: 240px) {
+  button {
+    padding-left: 12px;
+    padding-right: 12px;
+  }
+
+  .interstitial-wrapper {
+    overflow: inherit;
+    padding: 0 8px;
+  }
+}
+
+@media (max-width: 120px) {
+  button {
+    width: auto;
+  }
+}
diff --git a/chrome/renderer/resources/neterror.html b/components/neterror/resources/neterror.html
similarity index 94%
rename from chrome/renderer/resources/neterror.html
rename to components/neterror/resources/neterror.html
index f8f53ea..5615447 100644
--- a/chrome/renderer/resources/neterror.html
+++ b/components/neterror/resources/neterror.html
@@ -5,9 +5,9 @@
   <meta name="viewport" content="width=device-width, initial-scale=1.0,
                                  maximum-scale=1.0, user-scalable=no">
   <title i18n-content="title"></title>
-  <link rel="stylesheet" href="../../../components/security_interstitials/core/browser/resources/interstitial_v2.css">
+  <link rel="stylesheet" href="../../security_interstitials/core/browser/resources/interstitial_v2.css">
   <link rel="stylesheet" href="neterror.css">
-  <script src="../../../components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js"></script>
+  <script src="../../security_interstitials/core/browser/resources/interstitial_v2_mobile.js"></script>
   <script src="neterror.js"></script>
   <script src="offline.js"></script>
 </head>
diff --git a/chrome/renderer/resources/neterror.js b/components/neterror/resources/neterror.js
similarity index 100%
rename from chrome/renderer/resources/neterror.js
rename to components/neterror/resources/neterror.js
diff --git a/chrome/renderer/resources/offline.js b/components/neterror/resources/offline.js
similarity index 100%
rename from chrome/renderer/resources/offline.js
rename to components/neterror/resources/offline.js
diff --git a/chrome/renderer/resources/sounds/button-press.mp3 b/components/neterror/resources/sounds/button-press.mp3
similarity index 100%
rename from chrome/renderer/resources/sounds/button-press.mp3
rename to components/neterror/resources/sounds/button-press.mp3
Binary files differ
diff --git a/chrome/renderer/resources/sounds/hit.mp3 b/components/neterror/resources/sounds/hit.mp3
similarity index 100%
rename from chrome/renderer/resources/sounds/hit.mp3
rename to components/neterror/resources/sounds/hit.mp3
Binary files differ
diff --git a/chrome/renderer/resources/sounds/score-reached.mp3 b/components/neterror/resources/sounds/score-reached.mp3
similarity index 100%
rename from chrome/renderer/resources/sounds/score-reached.mp3
rename to components/neterror/resources/sounds/score-reached.mp3
Binary files differ
diff --git a/components/resources/OWNERS b/components/resources/OWNERS
index a247c17..83609568 100644
--- a/components/resources/OWNERS
+++ b/components/resources/OWNERS
@@ -18,6 +18,8 @@
 per-file gcm_driver_resources.grdp=jianli@chromium.org
 per-file gcm_driver_resources.grdp=peter@chromium.org
 per-file gcm_driver_resources.grdp=zea@chromium.org
+per-file neterror*=mmenke@chromium.org
+per-file neterror*=ttuttle@chromium.org
 per-file proximity_auth*=isherman@chromium.org
 per-file proximity_auth*=tengs@chromium.org
 per-file version_ui*=bauerb@chromium.org
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd
index 466ae2e..3793a19 100644
--- a/components/resources/components_resources.grd
+++ b/components/resources/components_resources.grd
@@ -15,6 +15,7 @@
       <part file="flags_ui_resources.grdp" />
       <part file="gcm_driver_resources.grdp" />
       <part file="net_log_resources.grdp" />
+      <part file="neterror_resources.grdp" />
       <part file="printing_resources.grdp" />
       <part file="proximity_auth_resources.grdp" />
       <part file="security_interstitials_resources.grdp" />
diff --git a/components/resources/components_scaled_resources.grd b/components/resources/components_scaled_resources.grd
index 82fc3fd..5be1c8c 100644
--- a/components/resources/components_scaled_resources.grd
+++ b/components/resources/components_scaled_resources.grd
@@ -17,6 +17,7 @@
       <part file="autofill_scaled_resources.grdp" />
       <part file="crash_scaled_resources.grdp" />
       <part file="flags_ui_scaled_resources.grdp" />
+      <part file="neterror_scaled_resources.grdp" />
       <part file="omnibox_scaled_resources.grdp" />
       <part file="version_ui_scaled_resources.grdp" />
 
diff --git a/chrome/app/theme/default_100_percent/common/error_network_generic.png b/components/resources/default_100_percent/neterror/error_network_generic.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/error_network_generic.png
rename to components/resources/default_100_percent/neterror/error_network_generic.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/omnibox_search_button_loupe.png b/components/resources/default_100_percent/omnibox/omnibox_search_button_loupe.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/omnibox_search_button_loupe.png
rename to components/resources/default_100_percent/omnibox/omnibox_search_button_loupe.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/error_network_generic.png b/components/resources/default_200_percent/neterror/error_network_generic.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/common/error_network_generic.png
rename to components/resources/default_200_percent/neterror/error_network_generic.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_search_button_loupe.png b/components/resources/default_200_percent/omnibox/omnibox_search_button_loupe.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/common/omnibox_search_button_loupe.png
rename to components/resources/default_200_percent/omnibox/omnibox_search_button_loupe.png
Binary files differ
diff --git a/components/resources/neterror_resources.grdp b/components/resources/neterror_resources.grdp
new file mode 100644
index 0000000..298f85ac
--- /dev/null
+++ b/components/resources/neterror_resources.grdp
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <include name="IDR_NET_ERROR_HTML" file="../neterror/resources/neterror.html" flattenhtml="true" type="BINDATA" />
+</grit-part>
diff --git a/components/resources/neterror_scaled_resources.grdp b/components/resources/neterror_scaled_resources.grdp
new file mode 100644
index 0000000..1e2cad3
--- /dev/null
+++ b/components/resources/neterror_scaled_resources.grdp
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <structure type="chrome_scaled_image" name="IDR_ERROR_NETWORK_GENERIC" file="neterror/error_network_generic.png" />
+</grit-part>
diff --git a/components/resources/omnibox_scaled_resources.grdp b/components/resources/omnibox_scaled_resources.grdp
index b8890f8d..46a18f3 100644
--- a/components/resources/omnibox_scaled_resources.grdp
+++ b/components/resources/omnibox_scaled_resources.grdp
@@ -3,6 +3,7 @@
   <structure type="chrome_scaled_image" name="IDR_OMNIBOX_CALCULATOR" file="omnibox/omnibox_calculator.png" />
   <structure type="chrome_scaled_image" name="IDR_OMNIBOX_EXTENSION_APP" file="omnibox/omnibox_extension_app.png" />
   <structure type="chrome_scaled_image" name="IDR_OMNIBOX_HTTPS_POLICY_WARNING" file="omnibox/controlled_setting_mandatory.png" />
+  <structure type="chrome_scaled_image" name="IDR_OMNIBOX_SEARCH_BUTTON_LOUPE" file="omnibox/omnibox_search_button_loupe.png" />
   <if expr="is_ios">
     <structure type="chrome_scaled_image" name="IDR_LOCATION_BAR_HTTP" file="omnibox/ios/location_bar_http.png" />
     <structure type="chrome_scaled_image" name="IDR_OMNIBOX_HISTORY" file="omnibox/ios/omnibox_history.png" />
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index f7ff1907..bb2a918 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/containers/hash_tables.h"
 #include "base/debug/alias.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/shared_memory.h"
@@ -26,6 +27,7 @@
 #include "content/common/resource_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/resource_response.h"
 #include "net/base/io_buffer.h"
 #include "net/base/load_flags.h"
@@ -45,6 +47,14 @@
 // The interval for calls to ReportUploadProgress.
 static int kUploadProgressIntervalMsec = 10;
 
+// Used when kOptimizeIPCForSmallResource is enabled.
+// Small resource typically issues two Read call: one for the content itself
+// and another for getting zero response to detect EOF.
+// Inline these two into the IPC message to avoid allocating an expensive
+// SharedMemory for small resources.
+const int kNumLeadingChunk = 2;
+const int kInlinedLeadingChunkSize = 2048;
+
 void GetNumericArg(const std::string& name, int* result) {
   const std::string& value =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
@@ -65,6 +75,111 @@
 
 }  // namespace
 
+// Used when kOptimizeIPCForSmallResource is enabled.
+// The instance hooks the buffer allocation of AsyncResourceHandler, and
+// determine if we should use SharedMemory or should inline the data into
+// the IPC message.
+class AsyncResourceHandler::InliningHelper {
+ public:
+
+  InliningHelper() {}
+  ~InliningHelper() {}
+
+  void OnResponseReceived(const ResourceResponse& response) {
+    InliningStatus status = IsInliningApplicable(response);
+    UMA_HISTOGRAM_ENUMERATION(
+        "Net.ResourceLoader.InliningStatus",
+        static_cast<int>(status),
+        static_cast<int>(InliningStatus::INLINING_STATUS_COUNT));
+    inlining_applicable_ = status == InliningStatus::APPLICABLE;
+  }
+
+  // Returns true if InliningHelper allocates the buffer for inlining.
+  bool PrepareInlineBufferIfApplicable(scoped_refptr<net::IOBuffer>* buf,
+                                      int* buf_size) {
+    ++num_allocation_;
+
+    // If the server sends the resource in multiple small chunks,
+    // |num_allocation_| may exceed |kNumLeadingChunk|. Disable inlining and
+    // fall back to the regular resource loading path in that case.
+    if (!inlining_applicable_ ||
+        num_allocation_ > kNumLeadingChunk ||
+        !base::FeatureList::IsEnabled(features::kOptimizeIPCForSmallResource)) {
+      return false;
+    }
+
+    leading_chunk_buffer_ = new net::IOBuffer(kInlinedLeadingChunkSize);
+    *buf = leading_chunk_buffer_;
+    *buf_size = kInlinedLeadingChunkSize;
+    return true;
+  }
+
+  // Returns true if the received data is sent to the consumer.
+  bool SendInlinedDataIfApplicable(int bytes_read,
+                                   int encoded_data_length,
+                                   IPC::Sender* sender,
+                                   int request_id) {
+    DCHECK(sender);
+    if (!leading_chunk_buffer_)
+      return false;
+
+    std::vector<char> data(
+        leading_chunk_buffer_->data(),
+        leading_chunk_buffer_->data() + bytes_read);
+    leading_chunk_buffer_ = nullptr;
+
+    sender->Send(new ResourceMsg_InlinedDataChunkReceived(
+        request_id, data, encoded_data_length));
+    return true;
+  }
+
+  void RecordHistogram(int64_t elapsed_time) {
+    if (inlining_applicable_) {
+      UMA_HISTOGRAM_CUSTOM_COUNTS(
+          "Net.ResourceLoader.ResponseStartToEnd.InliningApplicable",
+          elapsed_time, 1, 100000, 100);
+    }
+  }
+
+ private:
+  enum class InliningStatus : int {
+    APPLICABLE = 0,
+    EARLY_ALLOCATION = 1,
+    UNKNOWN_CONTENT_LENGTH = 2,
+    LARGE_CONTENT = 3,
+    HAS_TRANSFER_ENCODING = 4,
+    HAS_CONTENT_ENCODING = 5,
+    INLINING_STATUS_COUNT,
+  };
+
+  InliningStatus IsInliningApplicable(const ResourceResponse& response) {
+    // Disable if the leading chunk is already arrived.
+    if (num_allocation_)
+      return InliningStatus::EARLY_ALLOCATION;
+
+    // Disable if the content is known to be large.
+    if (response.head.content_length > kInlinedLeadingChunkSize)
+      return InliningStatus::LARGE_CONTENT;
+
+    // Disable if the length of the content is unknown.
+    if (response.head.content_length < 0)
+      return InliningStatus::UNKNOWN_CONTENT_LENGTH;
+
+    if (response.head.headers) {
+      if (response.head.headers->HasHeader("Transfer-Encoding"))
+        return InliningStatus::HAS_TRANSFER_ENCODING;
+      if (response.head.headers->HasHeader("Content-Encoding"))
+        return InliningStatus::HAS_CONTENT_ENCODING;
+    }
+
+    return InliningStatus::APPLICABLE;
+  }
+
+  int num_allocation_ = 0;
+  bool inlining_applicable_ = false;
+  scoped_refptr<net::IOBuffer> leading_chunk_buffer_;
+};
+
 class DependentIOBuffer : public net::WrappedIOBuffer {
  public:
   DependentIOBuffer(ResourceBuffer* backing, char* memory)
@@ -87,7 +202,8 @@
       did_defer_(false),
       has_checked_for_sufficient_resources_(false),
       sent_received_response_msg_(false),
-      sent_first_data_msg_(false),
+      sent_data_buffer_msg_(false),
+      inlining_helper_(new InliningHelper),
       last_upload_position_(0),
       waiting_for_upload_progress_ack_(false),
       reported_transfer_size_(0) {
@@ -266,6 +382,7 @@
                                                                 copy));
   }
 
+  inlining_helper_->OnResponseReceived(*response);
   return true;
 }
 
@@ -294,6 +411,11 @@
   if (!CheckForSufficientResource())
     return false;
 
+  // Return early if InliningHelper allocates the buffer, so that we should
+  // inline the data into the IPC message without allocating SharedMemory.
+  if (inlining_helper_->PrepareInlineBufferIfApplicable(buf, buf_size))
+    return true;
+
   if (!EnsureResourceBufferIsInitialized())
     return false;
 
@@ -317,9 +439,16 @@
   if (!filter)
     return false;
 
+  int encoded_data_length = CalculateEncodedDataLengthToReport();
+
+  // Return early if InliningHelper handled the received data.
+  if (inlining_helper_->SendInlinedDataIfApplicable(
+          bytes_read, encoded_data_length, filter, GetRequestID()))
+    return true;
+
   buffer_->ShrinkLastAllocation(bytes_read);
 
-  if (!sent_first_data_msg_) {
+  if (!sent_data_buffer_msg_) {
     base::SharedMemoryHandle handle;
     int size;
     if (!buffer_->ShareToProcess(filter->PeerHandle(), &handle, &size))
@@ -329,11 +458,10 @@
     CHECK_LE(size, kBufferSize);
     filter->Send(new ResourceMsg_SetDataBuffer(
         GetRequestID(), handle, size, filter->peer_pid()));
-    sent_first_data_msg_ = true;
+    sent_data_buffer_msg_ = true;
   }
 
   int data_offset = buffer_->GetLastAllocationOffset();
-  int encoded_data_length = CalculateEncodedDataLengthToReport();
 
   // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
   CHECK_LE(data_offset, kBufferSize);
@@ -415,7 +543,8 @@
   info->filter()->Send(
       new ResourceMsg_RequestComplete(GetRequestID(), request_complete_data));
 
-  RecordHistogram();
+  if (status.is_success())
+    RecordHistogram();
 }
 
 bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
@@ -483,6 +612,8 @@
         "Net.ResourceLoader.ResponseStartToEnd.Over_512kB",
         elapsed_time, 1, 100000, 100);
   }
+
+  inlining_helper_->RecordHistogram(elapsed_time);
 }
 
 }  // namespace content
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h
index f46fef96..5097413 100644
--- a/content/browser/loader/async_resource_handler.h
+++ b/content/browser/loader/async_resource_handler.h
@@ -14,6 +14,7 @@
 #include "base/timer/timer.h"
 #include "content/browser/loader/resource_handler.h"
 #include "content/browser/loader/resource_message_delegate.h"
+#include "net/base/io_buffer.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -55,6 +56,8 @@
   void OnDataDownloaded(int bytes_downloaded) override;
 
  private:
+  class InliningHelper;
+
   // IPC message handlers:
   void OnFollowRedirect(int request_id);
   void OnDataReceivedACK(int request_id);
@@ -82,8 +85,9 @@
 
   bool has_checked_for_sufficient_resources_;
   bool sent_received_response_msg_;
-  bool sent_first_data_msg_;
+  bool sent_data_buffer_msg_;
 
+  scoped_ptr<InliningHelper> inlining_helper_;
   base::TimeTicks response_started_ticks_;
 
   uint64_t last_upload_position_;
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 9341fcf..79a8f80 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
@@ -41,6 +42,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/child_process_host.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/process_type.h"
 #include "content/public/common/resource_response.h"
 #include "content/public/test/test_browser_context.h"
@@ -126,6 +128,7 @@
     case ResourceMsg_ReceivedRedirect::ID:
     case ResourceMsg_SetDataBuffer::ID:
     case ResourceMsg_DataReceived::ID:
+    case ResourceMsg_InlinedDataChunkReceived::ID:
     case ResourceMsg_DataDownloaded::ID:
     case ResourceMsg_RequestComplete::ID: {
       bool result = base::PickleIterator(msg).ReadInt(&request_id);
@@ -828,7 +831,12 @@
   net::UploadProgress upload_progress;
 };
 
-class ResourceDispatcherHostTest : public testing::Test,
+enum class TestConfig {
+  kDefault,
+  kOptimizeIPCForSmallResourceEnabled,
+};
+
+class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
                                    public IPC::Sender {
  public:
   typedef ResourceDispatcherHostImpl::LoadInfo LoadInfo;
@@ -899,6 +907,22 @@
         browser_context_->GetResourceContext(),
         web_contents_->GetRenderProcessHost()->GetID());
     child_ids_.insert(web_contents_->GetRenderProcessHost()->GetID());
+
+    base::FeatureList::ClearInstanceForTesting();
+    switch (GetParam()) {
+      case TestConfig::kDefault:
+        base::FeatureList::InitializeInstance();
+        break;
+      case TestConfig::kOptimizeIPCForSmallResourceEnabled: {
+        scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+        feature_list->InitializeFromCommandLine(
+            features::kOptimizeIPCForSmallResource.name, std::string());
+        base::FeatureList::SetInstance(std::move(feature_list));
+        ASSERT_TRUE(base::FeatureList::IsEnabled(
+            features::kOptimizeIPCForSmallResource));
+        break;
+      }
+    }
   }
 
   void TearDown() override {
@@ -1193,6 +1217,22 @@
   ASSERT_EQ(expected_error_code, error_code);
 }
 
+testing::AssertionResult ExtractInlinedChunkData(
+    const IPC::Message& message,
+    std::string* leading_chunk_data) {
+  base::PickleIterator iter(message);
+  int request_id;
+  if (!IPC::ReadParam(&message, &iter, &request_id))
+    return testing::AssertionFailure() << "Could not read request_id";
+
+  std::vector<char> data;
+  if (!IPC::ReadParam(&message, &iter, &data))
+    return testing::AssertionFailure() << "Could not read data";
+  leading_chunk_data->assign(data.begin(), data.end());
+
+  return testing::AssertionSuccess();
+}
+
 testing::AssertionResult ExtractDataOffsetAndLength(const IPC::Message& message,
                                                     int* data_offset,
                                                     int* data_length) {
@@ -1207,10 +1247,39 @@
   return testing::AssertionSuccess();
 }
 
+void CheckSuccessfulRequestWithErrorCodeForInlinedCase(
+    const std::vector<IPC::Message>& messages,
+    const std::string& reference_data,
+    int expected_error) {
+  // A successful request on the inlined case will have received 3 messages:
+  //     ReceivedResponse         (indicates headers received)
+  //     InlinedDataChunkReceived (contains the content)
+  //     RequestComplete          (request is done)
+
+  ASSERT_EQ(3U, messages.size());
+
+  // The first messages should be received response
+  ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type());
+  ASSERT_EQ(ResourceMsg_InlinedDataChunkReceived::ID, messages[1].type());
+
+  std::string leading_chunk_data;
+  ASSERT_TRUE(ExtractInlinedChunkData(messages[1], &leading_chunk_data));
+  ASSERT_EQ(reference_data, leading_chunk_data);
+  CheckRequestCompleteErrorCode(messages[2], expected_error);
+}
+
 void CheckSuccessfulRequestWithErrorCode(
     const std::vector<IPC::Message>& messages,
     const std::string& reference_data,
     int expected_error) {
+  ASSERT_LT(2U, messages.size());
+  if (base::FeatureList::IsEnabled(features::kOptimizeIPCForSmallResource) &&
+      messages[1].type() == ResourceMsg_InlinedDataChunkReceived::ID) {
+    CheckSuccessfulRequestWithErrorCodeForInlinedCase(
+        messages, reference_data, expected_error);
+    return;
+  }
+
   // A successful request will have received 4 messages:
   //     ReceivedResponse    (indicates headers received)
   //     SetDataBuffer       (contains shared memory handle)
@@ -1286,7 +1355,7 @@
 }
 
 // Tests whether many messages get dispatched properly.
-TEST_F(ResourceDispatcherHostTest, TestMany) {
+TEST_P(ResourceDispatcherHostTest, TestMany) {
   MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
   MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
   MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
@@ -1319,7 +1388,7 @@
 
 // Tests whether messages get canceled properly. We issue four requests,
 // cancel two of them, and make sure that each sent the proper notifications.
-TEST_F(ResourceDispatcherHostTest, Cancel) {
+TEST_P(ResourceDispatcherHostTest, Cancel) {
   MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
   MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
   MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
@@ -1374,7 +1443,7 @@
 
 // Shows that detachable requests will timeout if the request takes too long to
 // complete.
-TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
+TEST_P(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
   MakeTestRequestWithResourceType(filter_.get(), 0, 1,
                                   net::URLRequestTestJob::test_url_2(),
                                   RESOURCE_TYPE_PREFETCH);  // detachable type
@@ -1416,7 +1485,7 @@
 
 // If the filter has disappeared then detachable resources should continue to
 // load.
-TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
+TEST_P(ResourceDispatcherHostTest, DeletedFilterDetached) {
   // test_url_1's data is available synchronously, so use 2 and 3.
   ResourceHostMsg_Request request_prefetch = CreateResourceRequest(
       "GET", RESOURCE_TYPE_PREFETCH, net::URLRequestTestJob::test_url_2());
@@ -1468,7 +1537,7 @@
 
 // If the filter has disappeared (original process dies) then detachable
 // resources should continue to load, even when redirected.
-TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
+TEST_P(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
   ResourceHostMsg_Request request = CreateResourceRequest(
       "GET", RESOURCE_TYPE_PREFETCH,
       net::URLRequestTestJob::test_url_redirect_to_url_2());
@@ -1515,7 +1584,7 @@
   EXPECT_EQ(0, network_delegate()->error_count());
 }
 
-TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
+TEST_P(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
   bool was_deleted = false;
 
   // Arrange to have requests deferred before starting.
@@ -1539,7 +1608,7 @@
   EXPECT_TRUE(was_deleted);
 }
 
-TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
+TEST_P(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
   bool was_deleted = false;
 
   // Arrange to have requests deferred before starting.
@@ -1581,7 +1650,7 @@
 
 // Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
 // URLRequest will not be started.
-TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
+TEST_P(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
   TestResourceDispatcherHostDelegate delegate;
   delegate.set_flags(CANCEL_BEFORE_START);
   host_.SetDelegate(&delegate);
@@ -1603,7 +1672,7 @@
   EXPECT_EQ(0, job_factory_->url_request_jobs_created_count());
 }
 
-TEST_F(ResourceDispatcherHostTest, PausedStartError) {
+TEST_P(ResourceDispatcherHostTest, PausedStartError) {
   // Arrange to have requests deferred before processing response headers.
   TestResourceDispatcherHostDelegate delegate;
   delegate.set_flags(DEFER_PROCESSING_RESPONSE);
@@ -1621,7 +1690,7 @@
 }
 
 // Test the WillStartUsingNetwork throttle.
-TEST_F(ResourceDispatcherHostTest, ThrottleNetworkStart) {
+TEST_P(ResourceDispatcherHostTest, ThrottleNetworkStart) {
   // Arrange to have requests deferred before processing response headers.
   TestResourceDispatcherHostDelegate delegate;
   delegate.set_flags(DEFER_NETWORK_START);
@@ -1647,7 +1716,7 @@
   EXPECT_EQ(0, host_.pending_requests());
 }
 
-TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
+TEST_P(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
   // Arrange to have requests deferred before starting.
   TestResourceDispatcherHostDelegate delegate;
   delegate.set_flags(DEFER_STARTING_REQUEST);
@@ -1685,7 +1754,7 @@
 
 
 // Tests that the delegate can cancel a request and provide a error code.
-TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
+TEST_P(ResourceDispatcherHostTest, CancelInDelegate) {
   TestResourceDispatcherHostDelegate delegate;
   delegate.set_flags(CANCEL_BEFORE_START);
   delegate.set_error_code_for_cancellation(net::ERR_ACCESS_DENIED);
@@ -1709,7 +1778,7 @@
 }
 
 // Tests CancelRequestsForProcess
-TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
+TEST_P(ResourceDispatcherHostTest, TestProcessCancel) {
   scoped_refptr<TestFilter> test_filter = new TestFilter(
       browser_context_->GetResourceContext());
   child_ids_.insert(test_filter->child_id());
@@ -1786,7 +1855,7 @@
 
 // Tests whether the correct requests get canceled when a RenderViewHost is
 // deleted.
-TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
   // Requests all hang once started.  This prevents requests from being
   // destroyed due to completion.
   job_factory_->SetHangAfterStartJobGeneration(true);
@@ -1836,7 +1905,7 @@
   EXPECT_EQ(0U, msgs.size());
 }
 
-TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
+TEST_P(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
   MakeTestRequestWithResourceType(filter_.get(), 0, 1,
                                   net::URLRequestTestJob::test_url_4(),
                                   RESOURCE_TYPE_PREFETCH);  // detachable type
@@ -1882,7 +1951,7 @@
 }
 
 // Tests blocking and resuming requests.
-TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
+TEST_P(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
   host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 11));
   host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 12));
   host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 13));
@@ -1950,7 +2019,7 @@
 }
 
 // Tests blocking and canceling requests.
-TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
+TEST_P(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
   host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 11));
 
   MakeTestRequestWithRenderFrame(0, 10, 1, net::URLRequestTestJob::test_url_1(),
@@ -1991,7 +2060,7 @@
 }
 
 // Tests that blocked requests are canceled if their associated process dies.
-TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
+TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
   // This second filter is used to emulate a second process.
   scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
 
@@ -2038,7 +2107,7 @@
 // away.  Note that we rely on Purify for finding the leaks if any.
 // If this test turns the Purify bot red, check the ResourceDispatcherHost
 // destructor to make sure the blocked requests are deleted.
-TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
+TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
   // This second filter is used to emulate a second process.
   scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
 
@@ -2080,7 +2149,7 @@
 }
 
 // Test the private helper method "CalculateApproximateMemoryCost()".
-TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
+TEST_P(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
   net::URLRequestContext context;
   scoped_ptr<net::URLRequest> req(context.CreateRequest(
       GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL));
@@ -2111,7 +2180,7 @@
 
 // Test that too much memory for outstanding requests for a particular
 // render_process_host_id causes requests to fail.
-TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
+TEST_P(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
   // Expected cost of each request as measured by
   // ResourceDispatcherHost::CalculateApproximateMemoryCost().
   int kMemoryCostOfTest2Req =
@@ -2188,7 +2257,7 @@
 // Test that when too many requests are outstanding for a particular
 // render_process_host_id, any subsequent request from it fails. Also verify
 // that the global limit is honored.
-TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
+TEST_P(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
   // Tighten the bound on the ResourceDispatcherHost, to speed things up.
   const size_t kMaxRequestsPerProcess = 2;
   host_.set_max_num_in_flight_requests_per_process(kMaxRequestsPerProcess);
@@ -2251,7 +2320,7 @@
 }
 
 // Tests that we sniff the mime type for a simple request.
-TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
+TEST_P(ResourceDispatcherHostTest, MimeSniffed) {
   std::string raw_headers("HTTP/1.1 200 OK\n\n");
   std::string response_data("<html><title>Test One</title></html>");
   SetResponse(raw_headers, response_data);
@@ -2273,7 +2342,7 @@
 }
 
 // Tests that we don't sniff the mime type when the server provides one.
-TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
+TEST_P(ResourceDispatcherHostTest, MimeNotSniffed) {
   std::string raw_headers("HTTP/1.1 200 OK\n"
                           "Content-type: image/jpeg\n\n");
   std::string response_data("<html><title>Test One</title></html>");
@@ -2296,7 +2365,7 @@
 }
 
 // Tests that we don't sniff the mime type when there is no message body.
-TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
+TEST_P(ResourceDispatcherHostTest, MimeNotSniffed2) {
   SetResponse("HTTP/1.1 304 Not Modified\n\n");
 
   HandleScheme("http");
@@ -2315,7 +2384,7 @@
   ASSERT_EQ("", response_head.mime_type);
 }
 
-TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
+TEST_P(ResourceDispatcherHostTest, MimeSniff204) {
   SetResponse("HTTP/1.1 204 No Content\n\n");
 
   HandleScheme("http");
@@ -2334,7 +2403,7 @@
   ASSERT_EQ("text/plain", response_head.mime_type);
 }
 
-TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
+TEST_P(ResourceDispatcherHostTest, MimeSniffEmpty) {
   SetResponse("HTTP/1.1 200 OK\n\n");
 
   HandleScheme("http");
@@ -2354,7 +2423,7 @@
 }
 
 // Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
-TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
+TEST_P(ResourceDispatcherHostTest, ForbiddenDownload) {
   std::string raw_headers("HTTP/1.1 403 Forbidden\n"
                           "Content-disposition: attachment; filename=blah\n"
                           "Content-type: application/octet-stream\n\n");
@@ -2388,7 +2457,7 @@
 // Test for http://crbug.com/76202 .  We don't want to destroy a
 // download request prematurely when processing a cancellation from
 // the renderer.
-TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
+TEST_P(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
   EXPECT_EQ(0, host_.pending_requests());
 
   int render_view_id = 0;
@@ -2428,7 +2497,7 @@
   while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
 }
 
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
   EXPECT_EQ(0, host_.pending_requests());
 
   int render_view_id = 0;
@@ -2469,7 +2538,7 @@
   EXPECT_EQ(0, host_.pending_requests());
 }
 
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
   EXPECT_EQ(0, host_.pending_requests());
 
   int render_view_id = 0;
@@ -2498,7 +2567,7 @@
 
 // Test the cancelling of requests that are being transferred to a new renderer
 // due to a redirection.
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
   EXPECT_EQ(0, host_.pending_requests());
 
   int request_id = 1;
@@ -2537,7 +2606,7 @@
 
 // Test transferred navigations with text/html, which doesn't trigger any
 // content sniffing.
-TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
   if (IsBrowserSideNavigationEnabled()) {
     SUCCEED() << "Test is not applicable with browser side navigation enabled";
     return;
@@ -2611,7 +2680,7 @@
 
 // Test transferring two navigations with text/html, to ensure the resource
 // accounting works.
-TEST_F(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
+TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
   if (IsBrowserSideNavigationEnabled()) {
     SUCCEED() << "Test is not applicable with browser side navigation enabled";
     return;
@@ -2698,7 +2767,7 @@
 // Test transferred navigations with text/plain, which causes
 // MimeTypeResourceHandler to buffer the response to sniff the content before
 // the transfer occurs.
-TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
   if (IsBrowserSideNavigationEnabled()) {
     SUCCEED() << "Test is not applicable with browser side navigation enabled";
     return;
@@ -2772,7 +2841,7 @@
   CheckSuccessfulRequest(msgs[1], kResponseBody);
 }
 
-TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
   if (IsBrowserSideNavigationEnabled()) {
     SUCCEED() << "Test is not applicable with browser side navigation enabled";
     return;
@@ -2862,7 +2931,7 @@
   CheckSuccessfulRequest(msgs[1], kResponseBody);
 }
 
-TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
   if (IsBrowserSideNavigationEnabled()) {
     SUCCEED() << "Test is not applicable with browser side navigation enabled";
     return;
@@ -2956,7 +3025,7 @@
   CheckSuccessfulRequest(msgs[1], kResponseBody);
 }
 
-TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
+TEST_P(ResourceDispatcherHostTest, UnknownURLScheme) {
   EXPECT_EQ(0, host_.pending_requests());
 
   HandleScheme("http");
@@ -2980,7 +3049,7 @@
   CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_UNKNOWN_URL_SCHEME);
 }
 
-TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
+TEST_P(ResourceDispatcherHostTest, DataReceivedACKs) {
   EXPECT_EQ(0, host_.pending_requests());
 
   SendDataReceivedACKs(true);
@@ -3005,7 +3074,7 @@
 
 // Request a very large detachable resource and cancel part way. Some of the
 // data should have been sent to the renderer, but not all.
-TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
+TEST_P(ResourceDispatcherHostTest, DataSentBeforeDetach) {
   EXPECT_EQ(0, host_.pending_requests());
 
   int render_view_id = 0;
@@ -3061,7 +3130,7 @@
       net::ERR_ABORTED);
 }
 
-TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
+TEST_P(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
   EXPECT_EQ(0, host_.pending_requests());
 
   HandleScheme("big-job");
@@ -3110,7 +3179,7 @@
 
 // Flakyness of this test might indicate memory corruption issues with
 // for example the ResourceBuffer of AsyncResourceHandler.
-TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
+TEST_P(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
   EXPECT_EQ(0, host_.pending_requests());
 
   HandleScheme("big-job");
@@ -3163,7 +3232,7 @@
 }
 
 // Tests the dispatcher host's temporary file management.
-TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
+TEST_P(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
   const int kRequestID = 1;
 
   // Create a temporary file.
@@ -3210,7 +3279,7 @@
 
 // Tests that temporary files held on behalf of child processes are released
 // when the child process dies.
-TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
+TEST_P(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
   const int kRequestID = 1;
 
   // Create a temporary file.
@@ -3241,7 +3310,7 @@
   EXPECT_FALSE(base::PathExists(file_path));
 }
 
-TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
+TEST_P(ResourceDispatcherHostTest, DownloadToFile) {
   // Make a request which downloads to file.
   ResourceHostMsg_Request request = CreateResourceRequest(
       "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
@@ -3315,14 +3384,14 @@
 }
 
 // Tests GetLoadInfoForAllRoutes when there are no pending requests.
-TEST_F(ResourceDispatcherHostTest, LoadInfoNoRequests) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoNoRequests) {
   scoped_ptr<LoadInfoMap> load_info_map = RunLoadInfoTest(nullptr, 0);
   EXPECT_EQ(0u, load_info_map->size());
 }
 
 // Tests GetLoadInfoForAllRoutes when there are 3 requests from the same
 // RenderView.  The second one is farthest along.
-TEST_F(ResourceDispatcherHostTest, LoadInfo) {
+TEST_P(ResourceDispatcherHostTest, LoadInfo) {
   const GlobalRoutingID kId(filter_->child_id(), 0);
   LoadInfoTestRequestInfo request_info[] = {
       {kId.route_id,
@@ -3351,7 +3420,7 @@
 
 // Tests GetLoadInfoForAllRoutes when there are 2 requests with the same
 // priority.  The first one (Which will have the lowest ID) should be returned.
-TEST_F(ResourceDispatcherHostTest, LoadInfoSamePriority) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoSamePriority) {
   const GlobalRoutingID kId(filter_->child_id(), 0);
   LoadInfoTestRequestInfo request_info[] = {
       {kId.route_id,
@@ -3374,7 +3443,7 @@
 }
 
 // Tests GetLoadInfoForAllRoutes when a request is uploading a body.
-TEST_F(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
   const GlobalRoutingID kId(filter_->child_id(), 0);
   LoadInfoTestRequestInfo request_info[] = {
       {kId.route_id,
@@ -3412,7 +3481,7 @@
 // Tests GetLoadInfoForAllRoutes when there are 4 requests from 2 different
 // RenderViews.  Also tests the case where the first / last requests are the
 // most interesting ones.
-TEST_F(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
   const GlobalRoutingID kId1(filter_->child_id(), 0);
   const GlobalRoutingID kId2(filter_->child_id(), 1);
   LoadInfoTestRequestInfo request_info[] = {
@@ -3454,7 +3523,7 @@
 
 // Confirm that resource response started notifications are correctly
 // transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferResponseStarted) {
+TEST_P(ResourceDispatcherHostTest, TransferResponseStarted) {
   int initial_count = web_contents_observer_->resource_response_start_count();
 
   MakeWebContentsAssociatedTestRequest(1, net::URLRequestTestJob::test_url_1());
@@ -3466,7 +3535,7 @@
 
 // Confirm that request redirected notifications are correctly
 // transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferRequestRedirected) {
+TEST_P(ResourceDispatcherHostTest, TransferRequestRedirected) {
   int initial_count = web_contents_observer_->resource_request_redirect_count();
 
   MakeWebContentsAssociatedTestRequest(
@@ -3478,7 +3547,7 @@
 }
 
 // Confirm that DidChangePriority messages are respected.
-TEST_F(ResourceDispatcherHostTest, DidChangePriority) {
+TEST_P(ResourceDispatcherHostTest, DidChangePriority) {
   // ResourceScheduler only throttles http and https requests.
   HandleScheme("http");
 
@@ -3515,7 +3584,7 @@
 
 // Confirm that resource response started notifications for downloads are not
 // transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferResponseStartedDownload) {
+TEST_P(ResourceDispatcherHostTest, TransferResponseStartedDownload) {
   int initial_count(web_contents_observer_->resource_response_start_count());
 
   MakeWebContentsAssociatedDownloadRequest(
@@ -3527,7 +3596,7 @@
 
 // Confirm that request redirected notifications for downloads are not
 // transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
+TEST_P(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
   int initial_count(web_contents_observer_->resource_request_redirect_count());
 
   MakeWebContentsAssociatedDownloadRequest(
@@ -3601,4 +3670,10 @@
   return nullptr;
 }
 
+INSTANTIATE_TEST_CASE_P(
+    ResourceDispatcherHostTests,
+    ResourceDispatcherHostTest,
+    testing::Values(TestConfig::kDefault,
+                    TestConfig::kOptimizeIPCForSmallResourceEnabled));
+
 }  // namespace content
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index bf48eb7..6d94b930 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -13,6 +13,7 @@
 #include "base/debug/alias.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/debug/stack_trace.h"
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/memory/shared_memory.h"
 #include "base/message_loop/message_loop.h"
@@ -33,6 +34,7 @@
 #include "content/public/child/fixed_received_data.h"
 #include "content/public/child/request_peer.h"
 #include "content/public/child/resource_dispatcher_delegate.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/resource_response.h"
 #include "content/public/common/resource_type.h"
 #include "net/base/net_errors.h"
@@ -245,6 +247,36 @@
   }
 }
 
+void ResourceDispatcher::OnReceivedInlinedDataChunk(
+    int request_id,
+    const std::vector<char>& data,
+    int encoded_data_length) {
+  TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedInlinedDataChunk");
+  DCHECK(!data.empty());
+  DCHECK(base::FeatureList::IsEnabled(features::kOptimizeIPCForSmallResource));
+
+  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
+  if (!request_info || data.empty())
+    return;
+
+  // Check whether this response data is compliant with our cross-site
+  // document blocking policy. We only do this for the first chunk of data.
+  if (request_info->site_isolation_metadata.get()) {
+    SiteIsolationStatsGatherer::OnReceivedFirstChunk(
+        request_info->site_isolation_metadata, data.data(), data.size());
+    request_info->site_isolation_metadata.reset();
+  }
+
+  // ThreadedDataProvider should not be attached at this point since |buffer|
+  // is not yet set up here.
+  DCHECK(!request_info->buffer.get());
+  CHECK(!request_info->threaded_data_provider);
+
+  scoped_ptr<RequestPeer::ReceivedData> received_data(
+      new content::FixedReceivedData(data, encoded_data_length));
+  request_info->peer->OnReceivedData(std::move(received_data));
+}
+
 void ResourceDispatcher::OnReceivedData(int request_id,
                                         int data_offset,
                                         int data_length,
@@ -572,6 +604,8 @@
     IPC_MESSAGE_HANDLER(ResourceMsg_SetDataBuffer, OnSetDataBuffer)
     IPC_MESSAGE_HANDLER(ResourceMsg_DataReceivedDebug, OnReceivedDataDebug)
     IPC_MESSAGE_HANDLER(ResourceMsg_DataReceivedDebug2, OnReceivedDataDebug2)
+    IPC_MESSAGE_HANDLER(ResourceMsg_InlinedDataChunkReceived,
+                        OnReceivedInlinedDataChunk)
     IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData)
     IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData)
     IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete)
@@ -753,6 +787,7 @@
     case ResourceMsg_SetDataBuffer::ID:
     case ResourceMsg_DataReceivedDebug::ID:
     case ResourceMsg_DataReceivedDebug2::ID:
+    case ResourceMsg_InlinedDataChunkReceived::ID:
     case ResourceMsg_DataReceived::ID:
     case ResourceMsg_DataDownloaded::ID:
     case ResourceMsg_RequestComplete::ID:
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h
index a2aada8..0c33d65 100644
--- a/content/child/resource_dispatcher.h
+++ b/content/child/resource_dispatcher.h
@@ -206,6 +206,9 @@
                             int data_offset,
                             int data_length,
                             int encoded_data_length);
+  void OnReceivedInlinedDataChunk(int request_id,
+                                  const std::vector<char>& data,
+                                  int encoded_data_length);
   void OnReceivedData(int request_id,
                       int data_offset,
                       int data_length,
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index f300673..20b0475 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -376,6 +376,14 @@
                      int /* data_length */,
                      int /* encoded_data_length */)
 
+// Sent when a chunk of data from a resource request is ready, and the resource
+// is expected to be small enough to fit in the inlined buffer.
+// The data is sent as a part of IPC message.
+IPC_MESSAGE_CONTROL3(ResourceMsg_InlinedDataChunkReceived,
+                     int /* request_id */,
+                     std::vector<char> /* data */,
+                     int /* encoded_data_length */)
+
 // Sent when some data from a resource request is ready.  The data offset and
 // length specify a byte range into the shared memory buffer provided by the
 // SetDataBuffer message.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 9022adb8..9a396b5 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -23,6 +23,12 @@
 const base::Feature kExperimentalFramework{"ExperimentalFramework",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
+// An experiment to optimize resource loading IPC for small resources.
+// http://crbug.com/580928
+const base::Feature kOptimizeIPCForSmallResource{
+    "OptimizeForSmallResource",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Scrolls to compensate for layout movements (bit.ly/scroll-anchoring).
 const base::Feature kScrollAnchoring{"ScrollAnchoring",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 509ffb7..ace7c61 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -19,6 +19,7 @@
 CONTENT_EXPORT extern const base::Feature kBrotliEncoding;
 CONTENT_EXPORT extern const base::Feature kDownloadResumption;
 CONTENT_EXPORT extern const base::Feature kExperimentalFramework;
+CONTENT_EXPORT extern const base::Feature kOptimizeIPCForSmallResource;
 CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
 CONTENT_EXPORT extern const base::Feature kTokenBinding;
 CONTENT_EXPORT extern const base::Feature kUpdateRendererPriorityOnStartup;
diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc
index d7def0f..3e9f45f 100644
--- a/extensions/browser/api/app_window/app_window_api.cc
+++ b/extensions/browser/api/app_window/app_window_api.cc
@@ -75,8 +75,6 @@
 }  // namespace app_window_constants
 
 const char kNoneFrameOption[] = "none";
-  // TODO(benwells): Remove HTML titlebar injection.
-const char kHtmlFrameOption[] = "experimental-html";
 
 namespace {
 
@@ -124,8 +122,7 @@
 
 }  // namespace
 
-AppWindowCreateFunction::AppWindowCreateFunction()
-    : inject_html_titlebar_(false) {}
+AppWindowCreateFunction::AppWindowCreateFunction() {}
 
 bool AppWindowCreateFunction::RunAsync() {
   // Don't create app window if the system is shutting down.
@@ -198,8 +195,6 @@
           result->Set("frameId", new base::FundamentalValue(frame_id));
           existing_window->GetSerializedState(result);
           result->SetBoolean("existingWindow", true);
-          // TODO(benwells): Remove HTML titlebar injection.
-          result->SetBoolean("injectTitlebar", false);
           SetResult(result);
           SendResponse(true);
           return true;
@@ -360,8 +355,6 @@
 
   base::DictionaryValue* result = new base::DictionaryValue;
   result->Set("frameId", new base::FundamentalValue(frame_id));
-  result->Set("injectTitlebar",
-      new base::FundamentalValue(inject_html_titlebar_));
   result->Set("id", new base::StringValue(app_window->window_key()));
   app_window->GetSerializedState(result);
   SetResult(result);
@@ -503,15 +496,6 @@
 
 AppWindow::Frame AppWindowCreateFunction::GetFrameFromString(
     const std::string& frame_string) {
-  if (frame_string == kHtmlFrameOption &&
-      (extension()->permissions_data()->HasAPIPermission(
-           APIPermission::kExperimental) ||
-       base::CommandLine::ForCurrentProcess()->HasSwitch(
-           switches::kEnableExperimentalExtensionApis))) {
-     inject_html_titlebar_ = true;
-     return AppWindow::FRAME_NONE;
-  }
-
   if (frame_string == kNoneFrameOption)
     return AppWindow::FRAME_NONE;
 
diff --git a/extensions/browser/api/app_window/app_window_api.h b/extensions/browser/api/app_window/app_window_api.h
index f70aecb3..f10ec98 100644
--- a/extensions/browser/api/app_window/app_window_api.h
+++ b/extensions/browser/api/app_window/app_window_api.h
@@ -36,8 +36,6 @@
       const extensions::api::app_window::CreateWindowOptions& options,
       AppWindow::CreateParams* create_params);
   void UpdateFrameOptionsForChannel(AppWindow::CreateParams* create_params);
-
-  bool inject_html_titlebar_;
 };
 
 }  // namespace extensions
diff --git a/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc b/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
index 015eca3..08957fe3 100644
--- a/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
+++ b/extensions/browser/api/display_source/wifi_display/wifi_display_session_service_impl.cc
@@ -62,7 +62,7 @@
   DCHECK(client_);
   // We support only one Wi-Fi Display session at a time.
   if (delegate_->connection()) {
-    client_->OnError(ERROR_TYPE_EXCEEDED_SESSION_LIMIT_ERROR,
+    client_->OnError(ERROR_TYPE_SESSION_LIMIT_ERROR,
                      kErrorCannotHaveMultipleSessions);
     return;
   }
@@ -72,8 +72,7 @@
       sinks.begin(), sinks.end(),
       [sink_id](DisplaySourceSinkInfoPtr ptr) { return ptr->id == sink_id; });
   if (found == sinks.end() || (*found)->state != SINK_STATE_DISCONNECTED) {
-    client_->OnError(ERROR_TYPE_ESTABLISH_CONNECTION_ERROR,
-                     kErrorSinkNotAvailable);
+    client_->OnError(ERROR_TYPE_CONNECTION_ERROR, kErrorSinkNotAvailable);
     return;
   }
   AuthenticationInfo auth_info;
@@ -182,7 +181,7 @@
   if (sink_id != sink_id_)
     return;
   DCHECK(client_);
-  client_->OnError(ERROR_TYPE_ESTABLISH_CONNECTION_ERROR, message);
+  client_->OnError(ERROR_TYPE_CONNECTION_ERROR, message);
 }
 
 void WiFiDisplaySessionServiceImpl::OnDisconnectFailed(
diff --git a/extensions/common/api/display_source.idl b/extensions/common/api/display_source.idl
index 83cfa0de..00434a6 100644
--- a/extensions/common/api/display_source.idl
+++ b/extensions/common/api/display_source.idl
@@ -6,31 +6,22 @@
 // session using WebMediaStreamTrack as sources.
 namespace displaySource {
   enum ErrorType {
-    // Cannot create media pipeline from the given media stream which could be
-    // appropriate for a Display session (e.g., necessary codecs are missing
-    // on the platform).
-    create_media_pipeline_error,
-
     // A new Display session cannot be started before the existing one is
     // terminated.
-    exceeded_session_limit_error,
+    session_limit_error,
 
-    // Could not establish connection to the sink.
-    establish_connection_error,
+    // The connection with sink cannot be established or has dropped
+    // unexpectedly.
+    connection_error,
 
     // The capabilities of this Display Source and the connected  
     // sink do not fit (e.g. the sink cannot play the media content of
     // the formats given by the source).
     capabilities_negotiation_error,
 
-    // There was an error while packetizing and sending the media content.
-    media_send_error,
-
-    // The TCP connection with sink has dropped unexpectedly.
-    connection_error,
-
-    // An unexpected message has arrived from the sink.
-    unexpected_message_error,
+    // There was an error in media pipeline: while encoding, packetizing or
+    // sending the media content.
+    media_pipeline_error,
 
     // The sink became unresponsive.
     timeout_error,
diff --git a/extensions/common/mojo/wifi_display_session_service.mojom b/extensions/common/mojo/wifi_display_session_service.mojom
index 637a1f0..025ed7f 100644
--- a/extensions/common/mojo/wifi_display_session_service.mojom
+++ b/extensions/common/mojo/wifi_display_session_service.mojom
@@ -10,6 +10,8 @@
   SetClient(WiFiDisplaySessionServiceClient client);
 
   // Requires connection to a sink using the given authentication information.
+  // Note: 'auth_method' values must correspond to 'enum AuthenticationMethod'
+  // from display_source.idl
   Connect(int32 sink_id, int32 auth_method, string auth_data);
 
   // Drops the established connection to the connected sink.
@@ -27,6 +29,8 @@
   OnTerminated();
 
   // Notification of an error occurred during the session.
+  // Note: 'type' values must correspond to 'enum ErrorType'
+  // from display_source.idl
   OnError(int32 type, string description);
 
   // Invoked to transmit a controlling message from
diff --git a/extensions/renderer/app_window_custom_bindings.cc b/extensions/renderer/app_window_custom_bindings.cc
index b61c384..04e45a1 100644
--- a/extensions/renderer/app_window_custom_bindings.cc
+++ b/extensions/renderer/app_window_custom_bindings.cc
@@ -4,19 +4,14 @@
 
 #include "extensions/renderer/app_window_custom_bindings.h"
 
-#include <string>
-
 #include "base/command_line.h"
-#include "base/macros.h"
 #include "content/public/child/v8_value_converter.h"
 #include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/switches.h"
 #include "extensions/renderer/script_context.h"
-#include "extensions/renderer/script_context_set.h"
 #include "grit/extensions_renderer_resources.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
@@ -25,39 +20,8 @@
 
 namespace extensions {
 
-class DidCreateDocumentElementObserver : public content::RenderFrameObserver {
- public:
-  DidCreateDocumentElementObserver(content::RenderFrame* frame,
-                                   const ScriptContextSet* script_context_set)
-      : content::RenderFrameObserver(frame),
-        script_context_set_(script_context_set) {
-    DCHECK(script_context_set_);
-  }
-
-  void DidCreateDocumentElement() override {
-    blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
-    // Don't attempt to inject the titlebar into iframes.
-    if (web_frame->parent())
-      return;
-    ScriptContext* script_context = script_context_set_->GetByV8Context(
-        web_frame->mainWorldScriptContext());
-    if (!script_context)
-      return;
-    script_context->module_system()->CallModuleMethod(
-        "injectAppTitlebar", "didCreateDocumentElement");
-  }
-
- private:
-  const ScriptContextSet* script_context_set_;
-
-  DISALLOW_COPY_AND_ASSIGN(DidCreateDocumentElementObserver);
-};
-
-AppWindowCustomBindings::AppWindowCustomBindings(
-    const ScriptContextSet* script_context_set,
-    ScriptContext* context)
-    : ObjectBackedNativeHandler(context),
-      script_context_set_(script_context_set) {
+AppWindowCustomBindings::AppWindowCustomBindings(ScriptContext* context)
+    : ObjectBackedNativeHandler(context) {
   RouteFunction("GetFrame", base::Bind(&AppWindowCustomBindings::GetFrame,
                                        base::Unretained(this)));
 
@@ -70,19 +34,14 @@
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   // TODO(jeremya): convert this to IDL nocompile to get validation, and turn
   // these argument checks into CHECK().
-  if (args.Length() != 2)
+  if (args.Length() != 1)
     return;
 
   if (!args[0]->IsInt32())
     return;
 
-  if (!args[1]->IsBoolean())
-    return;
-
   int frame_id = args[0]->Int32Value();
 
-  bool inject_titlebar = args[1]->BooleanValue();
-
   if (frame_id == MSG_ROUTING_NONE)
     return;
 
@@ -99,9 +58,6 @@
   if (!context_render_frame)
     return;
 
-  if (inject_titlebar)
-    new DidCreateDocumentElementObserver(app_frame, script_context_set_);
-
   blink::WebFrame* opener = context_render_frame->GetWebFrame();
   blink::WebLocalFrame* app_web_frame = app_frame->GetWebFrame();
   app_web_frame->setOpener(opener);
diff --git a/extensions/renderer/app_window_custom_bindings.h b/extensions/renderer/app_window_custom_bindings.h
index 26e02c72..3fbab04 100644
--- a/extensions/renderer/app_window_custom_bindings.h
+++ b/extensions/renderer/app_window_custom_bindings.h
@@ -14,8 +14,7 @@
 // Implements custom bindings for the app.window API.
 class AppWindowCustomBindings : public ObjectBackedNativeHandler {
  public:
-  AppWindowCustomBindings(const ScriptContextSet* script_context_set,
-                          ScriptContext* context);
+  AppWindowCustomBindings(ScriptContext* context);
 
  private:
   void GetFrame(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -25,9 +24,6 @@
   void GetWindowControlsHtmlTemplate(
       const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  // ScriptContextSet handle. Not owned.
-  const ScriptContextSet* script_context_set_;
-
   DISALLOW_COPY_AND_ASSIGN(AppWindowCustomBindings);
 };
 
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index a8a2b3e..2c6ad7d1 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -807,13 +807,9 @@
       scoped_ptr<NativeHandler>(new FileSystemNatives(context)));
 
   // Custom bindings.
-  // |dispatcher| is null in unit tests.
-  const ScriptContextSet* script_context_set = dispatcher ?
-      &dispatcher->script_context_set() : nullptr;
   module_system->RegisterNativeHandler(
       "app_window_natives",
-      scoped_ptr<NativeHandler>(new AppWindowCustomBindings(
-          script_context_set, context)));
+      scoped_ptr<NativeHandler>(new AppWindowCustomBindings(context)));
   module_system->RegisterNativeHandler(
       "blob_natives",
       scoped_ptr<NativeHandler>(new BlobNativeHandler(context)));
diff --git a/extensions/renderer/resources/app_window_custom_bindings.js b/extensions/renderer/resources/app_window_custom_bindings.js
index 63f1eae..3800beac 100644
--- a/extensions/renderer/resources/app_window_custom_bindings.js
+++ b/extensions/renderer/resources/app_window_custom_bindings.js
@@ -118,10 +118,8 @@
     var view = null;
 
     // When window creation fails, |windowParams| will be undefined.
-    if (windowParams && windowParams.frameId) {
-      view = appWindowNatives.GetFrame(
-          windowParams.frameId, windowParams.injectTitlebar);
-    }
+    if (windowParams && windowParams.frameId)
+      view = appWindowNatives.GetFrame(windowParams.frameId);
 
     if (!view) {
       // No route to created window. If given a callback, trigger it with an
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 63447f1..b602ed42 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -60,6 +60,8 @@
     "gles2_conform_support/egl/egl.cc",
     "gles2_conform_support/egl/surface.cc",
     "gles2_conform_support/egl/surface.h",
+    "gles2_conform_support/egl/test_support.cc",
+    "gles2_conform_support/egl/test_support.h",
   ]
 
   deps = [
@@ -81,6 +83,43 @@
   }
 }
 
+# GYP version: //gpu/gpu.gyp:command_buffer_gles2_tests
+test("command_buffer_gles2_tests") {
+  sources = [
+    "command_buffer/tests/command_buffer_gles2_tests_main.cc",
+    "command_buffer/tests/egl_test.cc",
+  ]
+
+  deps = [
+    ":command_buffer_gles2",
+    "//base",
+    "//base/test:test_support",
+    "//base/third_party/dynamic_annotations",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+
+  defines = [
+    "COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY",
+    "EGLAPIENTRY=",
+  ]
+  if (current_os == "win") {
+    defines += [ "EGLAPI=__declspec(dllimport)" ]
+  } else {
+    defines += [ "EGLAPI=" ]
+  }
+
+  libs = []
+
+  if (is_android) {
+    libs += [ "android" ]
+    deps += [ "//ui/android:ui_java" ]
+  }
+  if (!is_component_build) {
+    configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+  }
+}
+
 source_set("test_support") {
   testonly = true
   sources = [
diff --git a/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc b/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc
new file mode 100644
index 0000000..f945390
--- /dev/null
+++ b/gpu/command_buffer/tests/command_buffer_gles2_tests_main.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 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 "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+// This file implements the main entry point for tests for command_buffer_gles2,
+// the mode of command buffer where the code is compiled as a standalone dynamic
+// library and exposed through EGL API.
+namespace {
+
+int RunHelper(base::TestSuite* testSuite) {
+#if defined(USE_OZONE)
+  base::MessageLoopForUI main_loop;
+#else
+  base::MessageLoopForIO message_loop;
+#endif
+  return testSuite->Run();
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+// NOTE: we initialize globals through TestSuite constructor or through JNI
+// library registration process on Android.
+
+// However, when the system is compiled with component build,
+// command_buffer_gles2 library and this test runner share the globals, such
+// as AtExitManager and JVM references.  When command_buffer_gles2 is run with
+// the test runner, the globals may be populated.  Any other app linking to
+// command_buffer_gles2 of course can not provide the globals.
+
+// When the system is compiled without component build, command_buffer_gles2
+// gets its own globals, while the test runner gets its own. The runner
+// initialize different global variables than the ones command_buffer_gles2
+// library uses. For example, there should be a global AtExitManager for the
+// test runner, and there should be a global AtExitManager that the library
+// uses. Similarly, if the test runner would use JNI, it should have global
+// reference to the JNI environent. If the command_buffer_gles2 library would
+// use JNI, it should have its own global reference to the JNI that always
+// remains null. The reference of the library should always stay null, since
+// JNI is not part of command_buffer_gles2 exported API (EGL API), and thus
+// there is no way for the client of the library to populate the JNI
+// pointer. The client may not even be a Java app.
+
+// We signify that the globals have been initialized when running
+// the component build.
+#if defined(COMPONENT_BUILD)
+  g_command_buffer_gles_has_atexit_manager = true;
+#endif
+
+  base::TestSuite test_suite(argc, argv);
+#if defined(OS_MACOSX)
+  base::mac::ScopedNSAutoreleasePool pool;
+#endif
+  testing::InitGoogleMock(&argc, argv);
+  return base::LaunchUnitTestsSerially(
+      argc, argv, base::Bind(&RunHelper, base::Unretained(&test_suite)));
+}
diff --git a/gpu/command_buffer/tests/egl_test.cc b/gpu/command_buffer/tests/egl_test.cc
new file mode 100644
index 0000000..bf7e30e5
--- /dev/null
+++ b/gpu/command_buffer/tests/egl_test.cc
@@ -0,0 +1,36 @@
+// Copyright 2015 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 "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include <EGL/egl.h>
+
+// This file tests EGL basic interface for command_buffer_gles2, the mode of
+// command buffer where the code is compiled as a standalone dynamic library and
+// exposed through EGL API.
+namespace gpu {
+
+using testing::Test;
+
+TEST_F(Test, BasicEGLInitialization) {
+  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  ASSERT_NE(display, EGL_NO_DISPLAY);
+
+  // Test for no crash even though passing nullptrs for major, minor.
+  EGLBoolean success = eglInitialize(display, nullptr, nullptr);
+  ASSERT_TRUE(success);
+
+  EGLint major = 0;
+  EGLint minor = 0;
+  success = eglInitialize(display, &major, &minor);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(major, 1);
+  ASSERT_EQ(minor, 4);
+
+  success = eglTerminate(display);
+  ASSERT_TRUE(success);
+}
+
+}  // namespace gpu
diff --git a/gpu/command_buffer_gles2_tests_apk.isolate b/gpu/command_buffer_gles2_tests_apk.isolate
new file mode 100644
index 0000000..aeae953
--- /dev/null
+++ b/gpu/command_buffer_gles2_tests_apk.isolate
@@ -0,0 +1,18 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'includes': [
+    '../build/android/android.isolate',
+  ],
+  'variables': {
+    'command': [
+      '<(PRODUCT_DIR)/bin/run_command_buffer_gles2_tests',
+      '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
+    ],
+    'files': [
+      '<(PRODUCT_DIR)/bin/run_command_buffer_gles2_tests',
+      '<(PRODUCT_DIR)/command_buffer_gles2_tests_apk/',
+    ]
+  },
+}
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc
index 9df0095..bf63108 100644
--- a/gpu/gles2_conform_support/egl/display.cc
+++ b/gpu/gles2_conform_support/egl/display.cc
@@ -23,6 +23,7 @@
 #include "gpu/command_buffer/service/valuebuffer_manager.h"
 #include "gpu/gles2_conform_support/egl/config.h"
 #include "gpu/gles2_conform_support/egl/surface.h"
+#include "gpu/gles2_conform_support/egl/test_support.h"
 
 namespace {
 const int32_t kCommandBufferSize = 1024 * 1024;
@@ -40,6 +41,11 @@
 base::AtExitManager* g_exit_manager;
 void RefAtExitManager() {
   base::AutoLock lock(g_exit_manager_lock.Get());
+#if defined(COMPONENT_BUILD)
+  if (g_command_buffer_gles_has_atexit_manager) {
+    return;
+  }
+#endif
   if (g_exit_manager_use_count == 0) {
     g_exit_manager = new base::AtExitManager;
   }
@@ -47,6 +53,11 @@
 }
 void ReleaseAtExitManager() {
   base::AutoLock lock(g_exit_manager_lock.Get());
+#if defined(COMPONENT_BUILD)
+  if (g_command_buffer_gles_has_atexit_manager) {
+    return;
+  }
+#endif
   --g_exit_manager_use_count;
   if (g_exit_manager_use_count == 0) {
     delete g_exit_manager;
diff --git a/gpu/gles2_conform_support/egl/egl.cc b/gpu/gles2_conform_support/egl/egl.cc
index a61bf53..5a81954b 100644
--- a/gpu/gles2_conform_support/egl/egl.cc
+++ b/gpu/gles2_conform_support/egl/egl.cc
@@ -143,9 +143,10 @@
 
     gfx::GLSurface::InitializeOneOff();
   }
-
-  *major = 1;
-  *minor = 4;
+  if (major)
+    *major = 1;
+  if (minor)
+    *minor = 4;
   return EglSuccess(EGL_TRUE);
 }
 
diff --git a/gpu/gles2_conform_support/egl/test_support.cc b/gpu/gles2_conform_support/egl/test_support.cc
new file mode 100644
index 0000000..938abcfd4
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/test_support.cc
@@ -0,0 +1,9 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test_support.h"
+
+#if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+bool g_command_buffer_gles_has_atexit_manager;
+#endif
diff --git a/gpu/gles2_conform_support/egl/test_support.h b/gpu/gles2_conform_support/egl/test_support.h
new file mode 100644
index 0000000..b1a70885
--- /dev/null
+++ b/gpu/gles2_conform_support/egl/test_support.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_GLES2_CONFORM_SUPPORT_EGL_TEST_SUPPORT_H_
+#define GPU_GLES2_CONFORM_SUPPORT_EGL_TEST_SUPPORT_H_
+
+#if defined(COMPONENT_BUILD) && defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
+// A variable used for communicating whether the app has initialized the global
+// variables.
+// On component build, the dynamic library and the Chromium test
+// runner executable refer to the same global variables. Any non-Chromium client
+// of the dynamic library will not initialize the globabl variables.
+// On non-component (static) build, the library and the runner have distinct
+// global variables.
+EGLAPI extern EGLAPIENTRY bool g_command_buffer_gles_has_atexit_manager;
+#endif
+
+#endif
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 25487b09..2b529e1 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -437,23 +437,63 @@
         'gles2_conform_support/egl/egl.cc',
         'gles2_conform_support/egl/surface.cc',
         'gles2_conform_support/egl/surface.h',
+        'gles2_conform_support/egl/test_support.cc',
+        'gles2_conform_support/egl/test_support.h',
+      ],
+	  'defines': [
+        'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
+        'EGLAPIENTRY=',
+	  ],
+      'conditions': [
+        ['OS=="win"', {
+          'defines': [
+            'EGLAPI=__declspec(dllexport)',
+          ],
+        }, { # OS!="win"
+		  'defines': [
+            'EGLAPI=__attribute__((visibility(\"default\")))'
+          ],
+        }],
+      ],
+    },
+    {
+      # GN version: //gpu:command_buffer_gles2_tests
+      'target_name': 'command_buffer_gles2_tests',
+      'type': '<(gtest_target_type)',
+      'dependencies': [
+        '../base/base.gyp:base',
+        '../base/base.gyp:test_support_base',
+        '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../testing/gmock.gyp:gmock',
+        '../testing/gtest.gyp:gtest',
+        'command_buffer_gles2',
+      ],
+      'sources': [
+        # Note: sources list duplicated in GN build.
+        'command_buffer/tests/command_buffer_gles2_tests_main.cc',
+        'command_buffer/tests/egl_test.cc',
+      ],
+	  'defines': [
+         'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
+         'EGLAPIENTRY=',
       ],
       'conditions': [
         ['OS=="win"', {
           'defines': [
-            'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
-            'EGLAPIENTRY=',
-            'EGLAPI=__declspec(dllexport)',
+            'EGLAPI=__declspec(dllimport)',
           ],
         }, { # OS!="win"
-          'defines': [
-            'COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY',
-            'EGLAPIENTRY=',
-            'EGLAPI=__attribute__((visibility(\"default\")))'
+		  'defines': [
+            'EGLAPI=',
           ],
-        }, ],
+		}],
+        ['OS == "android"', {
+          'dependencies': [
+            '../testing/android/native_test.gyp:native_test_native_code',
+          ],
+        }],
       ],
-    }
+    },
   ],
   'conditions': [
     ['component=="static_library"', {
@@ -753,6 +793,19 @@
           },
           'includes': [ '../build/apk_test.gypi' ],
         },
+        {
+          'target_name': 'command_buffer_gles2_tests_apk',
+          'type': 'none',
+          'dependencies': [
+            'command_buffer_gles2_tests',
+          ],
+          'variables': {
+            'test_suite_name': 'command_buffer_gles2_tests',
+          },
+          'includes': [
+            '../build/apk_test.gypi',
+          ],
+        },
       ],
     }],
     ['OS == "win" or (OS == "linux" and use_x11==1) or OS == "mac"', {
@@ -880,6 +933,19 @@
       {
         'targets': [
           {
+            'target_name': 'command_buffer_gles2_tests_apk_run',
+            'type': 'none',
+            'dependencies': [
+              'command_buffer_gles2_tests_apk',
+            ],
+            'includes': [
+              '../build/isolate.gypi',
+            ],
+            'sources': [
+              'command_buffer_gles2_apk.isolate',
+            ],
+          },
+          {
             'target_name': 'gl_tests_apk_run',
             'type': 'none',
             'dependencies': [
diff --git a/ios/chrome/BUILD.gn b/ios/chrome/BUILD.gn
index 59a9731..f59a480 100644
--- a/ios/chrome/BUILD.gn
+++ b/ios/chrome/BUILD.gn
@@ -23,6 +23,8 @@
     "browser/net/image_fetcher_unittest.mm",
     "browser/net/metrics_network_client_unittest.mm",
     "browser/net/retryable_url_fetcher_unittest.mm",
+    "browser/reading_list/reading_list_entry_unittest.cc",
+    "browser/reading_list/reading_list_model_unittest.cc",
     "browser/signin/chrome_identity_service_observer_bridge_unittest.mm",
     "browser/signin/gaia_auth_fetcher_ios_unittest.mm",
     "browser/snapshots/lru_cache_unittest.mm",
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index 648375c..8469be43 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -292,6 +292,15 @@
     "prefs/pref_observer_bridge.h",
     "prefs/pref_observer_bridge.mm",
     "procedural_block_types.h",
+    "reading_list/reading_list_entry.cc",
+    "reading_list/reading_list_entry.h",
+    "reading_list/reading_list_model.cc",
+    "reading_list/reading_list_model.h",
+    "reading_list/reading_list_model_factory.cc",
+    "reading_list/reading_list_model_factory.h",
+    "reading_list/reading_list_model_memory.cc",
+    "reading_list/reading_list_model_memory.h",
+    "reading_list/reading_list_model_observer.h",
     "search/search_util.cc",
     "search/search_util.h",
     "search_engines/search_engines_util.cc",
diff --git a/ios/chrome/browser/reading_list/OWNERS b/ios/chrome/browser/reading_list/OWNERS
new file mode 100644
index 0000000..bf1620f
--- /dev/null
+++ b/ios/chrome/browser/reading_list/OWNERS
@@ -0,0 +1 @@
+noyau@chromium.org
diff --git a/ios/chrome/browser/reading_list/reading_list_entry.cc b/ios/chrome/browser/reading_list/reading_list_entry.cc
new file mode 100644
index 0000000..15c0dea
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_entry.cc
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/reading_list/reading_list_entry.h"
+
+ReadingListEntry::ReadingListEntry(const GURL& url, const std::string& title)
+    : url_(url), title_(title) {
+  DCHECK(!url.is_empty());
+  DCHECK(url.is_valid());
+}
+ReadingListEntry::ReadingListEntry(const ReadingListEntry& entry)
+    : url_(entry.url()), title_(entry.title()) {}
+ReadingListEntry::~ReadingListEntry() {}
+
+const GURL& ReadingListEntry::url() const {
+  return url_;
+}
+
+const std::string ReadingListEntry::title() const {
+  return title_;
+}
+
+ReadingListEntry& ReadingListEntry::operator=(const ReadingListEntry& other) {
+  url_ = other.url_;
+  title_ = other.title_;
+  return *this;
+}
+
+bool ReadingListEntry::operator==(const ReadingListEntry& other) const {
+  return url_ == other.url_;
+}
diff --git a/ios/chrome/browser/reading_list/reading_list_entry.h b/ios/chrome/browser/reading_list/reading_list_entry.h
new file mode 100644
index 0000000..f7287b71
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_entry.h
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_ENTRY_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_ENTRY_H_
+
+#include <string>
+
+#include "url/gurl.h"
+
+// An entry in the reading list. The URL is a unique identifier for an entry, as
+// such it should not be empty and is the only thing considered when comparing
+// entries.
+class ReadingListEntry {
+ public:
+  ReadingListEntry(const GURL& url, const std::string& title);
+  ReadingListEntry(const ReadingListEntry& entry);
+  ~ReadingListEntry();
+
+  const GURL& url() const;
+  const std::string title() const;
+
+  ReadingListEntry& operator=(const ReadingListEntry& other);
+  bool operator==(const ReadingListEntry& other) const;
+
+ private:
+  GURL url_;
+  std::string title_;
+};
+
+#endif  // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_ENTRY_H_
diff --git a/ios/chrome/browser/reading_list/reading_list_entry_unittest.cc b/ios/chrome/browser/reading_list/reading_list_entry_unittest.cc
new file mode 100644
index 0000000..1bb920b9
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_entry_unittest.cc
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/reading_list/reading_list_entry.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(ReadingListEntry, CompareIgnoreTitle) {
+  const ReadingListEntry e1(GURL("http://example.com"), "bar");
+  const ReadingListEntry e2(GURL("http://example.com"), "foo");
+
+  EXPECT_EQ(e1, e2);
+}
+
+TEST(ReadingListEntry, CompareFailureIgnoreTitle) {
+  const ReadingListEntry e1(GURL("http://example.com"), "bar");
+  const ReadingListEntry e2(GURL("http://example.org"), "bar");
+
+  EXPECT_FALSE(e1 == e2);
+}
+
+TEST(ReadingListEntry, CopyAreEquals) {
+  const ReadingListEntry e1(GURL("http://example.com"), "bar");
+  const ReadingListEntry e2(e1);
+
+  EXPECT_EQ(e1, e2);
+  EXPECT_EQ(e1.title(), e2.title());
+}
diff --git a/ios/chrome/browser/reading_list/reading_list_model.cc b/ios/chrome/browser/reading_list/reading_list_model.cc
new file mode 100644
index 0000000..bdc26516
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model.cc
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/reading_list/reading_list_model.h"
+
+ReadingListModel::ReadingListModel() {}
+ReadingListModel::~ReadingListModel() {}
+
+// Observer methods.
+void ReadingListModel::AddObserver(ReadingListModelObserver* observer) {
+  DCHECK(observer);
+  observers_.AddObserver(observer);
+  if (loaded()) {
+    observer->ReadingListModelLoaded(this);
+  }
+}
+
+void ReadingListModel::RemoveObserver(ReadingListModelObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
diff --git a/ios/chrome/browser/reading_list/reading_list_model.h b/ios/chrome/browser/reading_list/reading_list_model.h
new file mode 100644
index 0000000..196476e
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model.h
@@ -0,0 +1,76 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/observer_list.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_observer.h"
+
+class GURL;
+class ReadingListEntry;
+class ReadingListModel;
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// The reading list model contains two list of entries: one of unread urls, the
+// other of read ones. This object should only be accessed from one thread
+// (Usually the main thread). The observers callbacks are also sent on the main
+// thread.
+class ReadingListModel {
+ public:
+  // Returns true if the model finished loading. Until this returns true the
+  // reading list is not ready for use.
+  virtual bool loaded() const = 0;
+
+  // Returns the size of read and unread entries.
+  virtual size_t unread_size() const = 0;
+  virtual size_t read_size() const = 0;
+
+  // Returns true if there are entries in the model that were not seen by the
+  // user yet. Reset to true when new unread entries are added. Reset to false
+  // when ResetUnseenEntries is called.
+  virtual bool HasUnseenEntries() const = 0;
+  virtual void ResetUnseenEntries() = 0;
+
+  // Returns a specific entry.
+  virtual const ReadingListEntry& GetUnreadEntryAtIndex(size_t index) const = 0;
+  virtual const ReadingListEntry& GetReadEntryAtIndex(size_t index) const = 0;
+
+  // Adds |url| at the top of the unread entries, and removes entries with the
+  // same |url| from everywhere else if they exist. The addition may be
+  // asynchronous, and the data will be available only once the observers are
+  // notified.
+  virtual const ReadingListEntry& AddEntry(const GURL& url,
+                                           const std::string& title) = 0;
+
+  // Removes an entry. The removal may be asynchronous, and not happen
+  // immediately.
+  virtual void RemoveEntryByUrl(const GURL& url) = 0;
+
+  // If the |url| is in the reading list and unread, mark it read. If it is in
+  // the reading list and read, move it to the top of unread if it is not here
+  // already. This may trigger deletion of old read entries.
+  virtual void MarkReadByURL(const GURL& url) = 0;
+
+  // Observer registration methods.
+  void AddObserver(ReadingListModelObserver* observer);
+  void RemoveObserver(ReadingListModelObserver* observer);
+
+ protected:
+  ReadingListModel();
+  virtual ~ReadingListModel();
+  // The observers.
+  base::ObserverList<ReadingListModelObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ReadingListModel);
+};
+
+#endif  // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_H_
diff --git a/ios/chrome/browser/reading_list/reading_list_model_factory.cc b/ios/chrome/browser/reading_list/reading_list_model_factory.cc
new file mode 100644
index 0000000..dcf6c2bc
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_factory.cc
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
+
+#include <utility>
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/ios/browser_state_dependency_manager.h"
+#include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_memory.h"
+
+// static
+ReadingListModel* ReadingListModelFactory::GetForBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  return static_cast<ReadingListModelMemory*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, true));
+}
+
+// static
+ReadingListModel* ReadingListModelFactory::GetForBrowserStateIfExists(
+    ios::ChromeBrowserState* browser_state) {
+  return static_cast<ReadingListModelMemory*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, false));
+}
+
+// static
+ReadingListModelFactory* ReadingListModelFactory::GetInstance() {
+  return base::Singleton<ReadingListModelFactory>::get();
+}
+
+ReadingListModelFactory::ReadingListModelFactory()
+    : BrowserStateKeyedServiceFactory(
+          "ReadingListModel",
+          BrowserStateDependencyManager::GetInstance()) {}
+
+ReadingListModelFactory::~ReadingListModelFactory() {}
+
+scoped_ptr<KeyedService> ReadingListModelFactory::BuildServiceInstanceFor(
+    web::BrowserState* context) const {
+  scoped_ptr<ReadingListModelMemory> reading_list_model(
+      new ReadingListModelMemory());
+  return std::move(reading_list_model);
+}
+
+web::BrowserState* ReadingListModelFactory::GetBrowserStateToUse(
+    web::BrowserState* context) const {
+  return GetBrowserStateRedirectedInIncognito(context);
+}
diff --git a/ios/chrome/browser/reading_list/reading_list_model_factory.h b/ios/chrome/browser/reading_list/reading_list_model_factory.h
new file mode 100644
index 0000000..96a6638
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_factory.h
@@ -0,0 +1,46 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_FACTORY_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_FACTORY_H_
+
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}  // namespace base
+
+class ReadingListModel;
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// Singleton that owns the ReadingListModel and associates it with
+// ios::ChromeBrowserState.
+class ReadingListModelFactory : public BrowserStateKeyedServiceFactory {
+ public:
+  static ReadingListModel* GetForBrowserState(
+      ios::ChromeBrowserState* browser_state);
+  static ReadingListModel* GetForBrowserStateIfExists(
+      ios::ChromeBrowserState* browser_state);
+  static ReadingListModelFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<ReadingListModelFactory>;
+
+  ReadingListModelFactory();
+  ~ReadingListModelFactory() override;
+
+  // BrowserStateKeyedServiceFactory implementation.
+  scoped_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+  web::BrowserState* GetBrowserStateToUse(
+      web::BrowserState* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(ReadingListModelFactory);
+};
+
+#endif  // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_FACTORY_H_
diff --git a/ios/chrome/browser/reading_list/reading_list_model_memory.cc b/ios/chrome/browser/reading_list/reading_list_model_memory.cc
new file mode 100644
index 0000000..40f9224
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_memory.cc
@@ -0,0 +1,117 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/reading_list/reading_list_model_memory.h"
+
+#include "url/gurl.h"
+
+ReadingListModelMemory::ReadingListModelMemory()
+    : hasUnseen_(false), loaded_(true) {}
+ReadingListModelMemory::~ReadingListModelMemory() {}
+
+void ReadingListModelMemory::Shutdown() {
+  FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                    ReadingListModelBeingDeleted(this));
+  loaded_ = false;
+}
+
+bool ReadingListModelMemory::loaded() const {
+  return loaded_;
+}
+
+size_t ReadingListModelMemory::unread_size() const {
+  DCHECK(loaded());
+  return unread_.size();
+}
+
+size_t ReadingListModelMemory::read_size() const {
+  DCHECK(loaded());
+  return read_.size();
+}
+
+bool ReadingListModelMemory::HasUnseenEntries() const {
+  DCHECK(loaded());
+  return unread_size() && hasUnseen_;
+}
+
+void ReadingListModelMemory::ResetUnseenEntries() {
+  DCHECK(loaded());
+  hasUnseen_ = false;
+}
+
+// Returns a specific entry.
+const ReadingListEntry& ReadingListModelMemory::GetUnreadEntryAtIndex(
+    size_t index) const {
+  DCHECK(loaded());
+  return unread_[index];
+}
+const ReadingListEntry& ReadingListModelMemory::GetReadEntryAtIndex(
+    size_t index) const {
+  DCHECK(loaded());
+  return read_[index];
+}
+
+void ReadingListModelMemory::RemoveEntryByUrl(const GURL& url) {
+  DCHECK(loaded());
+  const ReadingListEntry entry(url, std::string());
+
+  auto result = std::find(unread_.begin(), unread_.end(), entry);
+  if (result != unread_.end()) {
+    FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                      ReadingListWillRemoveUnreadEntry(
+                          this, std::distance(unread_.begin(), result)));
+    unread_.erase(result);
+    FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                      ReadingListDidApplyChanges(this));
+    return;
+  }
+
+  result = std::find(read_.begin(), read_.end(), entry);
+  if (result != read_.end()) {
+    FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                      ReadingListWillRemoveReadEntry(
+                          this, std::distance(read_.begin(), result)));
+    read_.erase(result);
+    FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                      ReadingListDidApplyChanges(this));
+    return;
+  }
+}
+
+const ReadingListEntry& ReadingListModelMemory::AddEntry(
+    const GURL& url,
+    const std::string& title) {
+  DCHECK(loaded());
+  RemoveEntryByUrl(url);
+  const ReadingListEntry entry(url, title);
+  FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                    ReadingListWillAddUnreadEntry(this, entry));
+  unread_.insert(unread_.begin(), entry);
+  FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                    ReadingListDidApplyChanges(this));
+
+  hasUnseen_ = true;
+  return *unread_.begin();
+}
+
+void ReadingListModelMemory::MarkReadByURL(const GURL& url) {
+  DCHECK(loaded());
+  const ReadingListEntry entry(url, std::string());
+
+  auto result = std::find(unread_.begin(), unread_.end(), entry);
+  if (result == unread_.end()) {
+    return;
+  }
+  FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                    ReadingListWillRemoveUnreadEntry(
+                        this, std::distance(unread_.begin(), result)));
+  FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                    ReadingListWillAddReadEntry(this, entry));
+
+  read_.insert(read_.begin(), *result);
+  unread_.erase(result);
+
+  FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
+                    ReadingListDidApplyChanges(this));
+}
diff --git a/ios/chrome/browser/reading_list/reading_list_model_memory.h b/ios/chrome/browser/reading_list/reading_list_model_memory.h
new file mode 100644
index 0000000..1dda495
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_memory.h
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_MEMORY_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_MEMORY_H_
+
+#include "components/keyed_service/core/keyed_service.h"
+#include "ios/chrome/browser/reading_list/reading_list_entry.h"
+#include "ios/chrome/browser/reading_list/reading_list_model.h"
+
+// Concrete implementation of a reading list model using in memory lists.
+class ReadingListModelMemory : public ReadingListModel, public KeyedService {
+ public:
+  ReadingListModelMemory();
+  ~ReadingListModelMemory() override;
+  void Shutdown() override;
+
+  bool loaded() const override;
+  size_t unread_size() const override;
+  size_t read_size() const override;
+
+  bool HasUnseenEntries() const override;
+  void ResetUnseenEntries() override;
+
+  // Returns a specific entry.
+  const ReadingListEntry& GetUnreadEntryAtIndex(size_t index) const override;
+  const ReadingListEntry& GetReadEntryAtIndex(size_t index) const override;
+
+  void RemoveEntryByUrl(const GURL& url) override;
+
+  const ReadingListEntry& AddEntry(const GURL& url,
+                                   const std::string& title) override;
+
+  void MarkReadByURL(const GURL& url) override;
+
+ private:
+  std::vector<ReadingListEntry> unread_;
+  std::vector<ReadingListEntry> read_;
+  bool hasUnseen_;
+  bool loaded_;
+};
+
+#endif  // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_MEMORY_H_
diff --git a/ios/chrome/browser/reading_list/reading_list_model_observer.h b/ios/chrome/browser/reading_list/reading_list_model_observer.h
new file mode 100644
index 0000000..4881d3932
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_observer.h
@@ -0,0 +1,55 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_OBSERVER_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_OBSERVER_H_
+
+#import <set>
+#import <vector>
+
+class ReadingListModel;
+class ReadingListEntry;
+
+// Observer for the Reading List model. In the observer methods care should be
+// taken to not modify the model.
+class ReadingListModelObserver {
+ public:
+  // Invoked when the model has finished loading. Until this method is called it
+  // is unsafe to use the model.
+  virtual void ReadingListModelLoaded(const ReadingListModel* model) = 0;
+
+  // Invoked from the destructor of the model. The model is no longer valid
+  // after this call.
+  virtual void ReadingListModelBeingDeleted(const ReadingListModel* model) {}
+
+  // Invoked when elements are about to be removed from the read or unread list.
+  virtual void ReadingListWillRemoveUnreadEntry(const ReadingListModel* model,
+                                                size_t index) {}
+  virtual void ReadingListWillRemoveReadEntry(const ReadingListModel* model,
+                                              size_t index) {}
+
+  // Invoked when elements are added to the read or the unread list. The new
+  // entries are always added at the beginning. these methods may be called
+  // multiple time (to process changes coming from a synchronization for
+  // example) and they will be executed in call order, the last call will end up
+  // in first position.
+  virtual void ReadingListWillAddUnreadEntry(const ReadingListModel* model,
+                                             const ReadingListEntry& entry) {}
+
+  virtual void ReadingListWillAddReadEntry(const ReadingListModel* model,
+                                           const ReadingListEntry& entry) {}
+
+  // Called after all th"e changes signaled by calls to the "Will" methods are
+  // done. All the "Will" methods are called as necessary, then the changes
+  // are applied and then this method is called.
+  virtual void ReadingListDidApplyChanges(ReadingListModel* model) {}
+
+ protected:
+  ReadingListModelObserver() {}
+  virtual ~ReadingListModelObserver() {}
+
+  DISALLOW_COPY_AND_ASSIGN(ReadingListModelObserver);
+};
+
+#endif  // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_OBSERVER_H_
diff --git a/ios/chrome/browser/reading_list/reading_list_model_unittest.cc b/ios/chrome/browser/reading_list/reading_list_model_unittest.cc
new file mode 100644
index 0000000..a863707
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_unittest.cc
@@ -0,0 +1,123 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/reading_list/reading_list_model_memory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class ReadingListModelTest : public ReadingListModelObserver,
+                             public testing::Test {
+ public:
+  ReadingListModelTest() : model_(new ReadingListModelMemory()) {
+    ClearCounts();
+    model_->AddObserver(this);
+  }
+  ~ReadingListModelTest() override {}
+
+  void ClearCounts() {
+    observer_loaded_ = observer_deleted_ = observer_remove_unread_ =
+        observer_remove_read_ = observer_add_unread_ = observer_add_read_ =
+            observer_did_apply_ = 0;
+  }
+
+  void AssertObserverCount(int observer_loaded,
+                           int observer_deleted,
+                           int observer_remove_unread,
+                           int observer_remove_read,
+                           int observer_add_unread,
+                           int observer_add_read,
+                           int observer_did_apply) {
+    ASSERT_EQ(observer_loaded, observer_loaded_);
+    ASSERT_EQ(observer_deleted, observer_deleted_);
+    ASSERT_EQ(observer_remove_unread, observer_remove_unread_);
+    ASSERT_EQ(observer_remove_read, observer_remove_read_);
+    ASSERT_EQ(observer_add_unread, observer_add_unread_);
+    ASSERT_EQ(observer_add_read, observer_add_read_);
+    ASSERT_EQ(observer_did_apply, observer_did_apply_);
+  }
+
+  // ReadingListModelObserver
+  void ReadingListModelLoaded(const ReadingListModel* model) override {
+    observer_loaded_ += 1;
+  }
+  void ReadingListModelBeingDeleted(const ReadingListModel* model) override {
+    observer_deleted_ += 1;
+  }
+  void ReadingListWillRemoveUnreadEntry(const ReadingListModel* model,
+                                        size_t index) override {
+    observer_remove_unread_ += 1;
+  }
+  void ReadingListWillRemoveReadEntry(const ReadingListModel* model,
+                                      size_t index) override {
+    observer_remove_read_ += 1;
+  }
+  void ReadingListWillAddUnreadEntry(const ReadingListModel* model,
+                                     const ReadingListEntry& entry) override {
+    observer_add_unread_ += 1;
+  }
+  void ReadingListWillAddReadEntry(const ReadingListModel* model,
+                                   const ReadingListEntry& entry) override {
+    observer_add_read_ += 1;
+  }
+  void ReadingListDidApplyChanges(ReadingListModel* model) override {
+    observer_did_apply_ += 1;
+  }
+
+ protected:
+  int observer_loaded_;
+  int observer_deleted_;
+  int observer_remove_unread_;
+  int observer_remove_read_;
+  int observer_add_unread_;
+  int observer_add_read_;
+  int observer_did_apply_;
+
+  scoped_ptr<ReadingListModelMemory> model_;
+};
+
+TEST_F(ReadingListModelTest, EmptyLoaded) {
+  EXPECT_TRUE(model_->loaded());
+  AssertObserverCount(1, 0, 0, 0, 0, 0, 0);
+  EXPECT_EQ(0ul, model_->unread_size());
+  EXPECT_EQ(0ul, model_->read_size());
+  model_->Shutdown();
+  EXPECT_FALSE(model_->loaded());
+  AssertObserverCount(1, 1, 0, 0, 0, 0, 0);
+}
+
+TEST_F(ReadingListModelTest, AddEntry) {
+  ClearCounts();
+  const ReadingListEntry entry =
+      model_->AddEntry(GURL("http://example.com"), "sample");
+  EXPECT_EQ(GURL("http://example.com"), entry.url());
+  EXPECT_EQ("sample", entry.title());
+
+  AssertObserverCount(0, 0, 0, 0, 1, 0, 1);
+  EXPECT_EQ(1ul, model_->unread_size());
+  EXPECT_EQ(0ul, model_->read_size());
+  EXPECT_TRUE(model_->HasUnseenEntries());
+
+  const ReadingListEntry other_entry = model_->GetUnreadEntryAtIndex(0);
+  EXPECT_EQ(GURL("http://example.com"), other_entry.url());
+  EXPECT_EQ("sample", other_entry.title());
+}
+
+TEST_F(ReadingListModelTest, ReadEntry) {
+  const ReadingListEntry entry =
+      model_->AddEntry(GURL("http://example.com"), "sample");
+
+  ClearCounts();
+  model_->MarkReadByURL(GURL("http://example.com"));
+  AssertObserverCount(0, 0, 1, 0, 0, 1, 1);
+  EXPECT_EQ(0ul, model_->unread_size());
+  EXPECT_EQ(1ul, model_->read_size());
+  EXPECT_FALSE(model_->HasUnseenEntries());
+
+  const ReadingListEntry other_entry = model_->GetReadEntryAtIndex(0);
+  EXPECT_EQ(GURL("http://example.com"), other_entry.url());
+  EXPECT_EQ("sample", other_entry.title());
+}
+
+}  // namespace
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index a1ac53d..50af6e1 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -447,6 +447,15 @@
         'browser/prefs/pref_observer_bridge.h',
         'browser/prefs/pref_observer_bridge.mm',
         'browser/procedural_block_types.h',
+        'browser/reading_list/reading_list_entry.cc',
+        'browser/reading_list/reading_list_entry.h',
+        'browser/reading_list/reading_list_model.cc',
+        'browser/reading_list/reading_list_model.h',
+        'browser/reading_list/reading_list_model_factory.cc',
+        'browser/reading_list/reading_list_model_factory.h',
+        'browser/reading_list/reading_list_model_memory.cc',
+        'browser/reading_list/reading_list_model_memory.h',
+        'browser/reading_list/reading_list_model_observer.h',
         'browser/search/search_util.cc',
         'browser/search/search_util.h',
         'browser/search_engines/search_engines_util.cc',
diff --git a/ios/chrome/ios_chrome_tests.gyp b/ios/chrome/ios_chrome_tests.gyp
index 70012fe..d72f00e 100644
--- a/ios/chrome/ios_chrome_tests.gyp
+++ b/ios/chrome/ios_chrome_tests.gyp
@@ -55,6 +55,8 @@
         'browser/net/image_fetcher_unittest.mm',
         'browser/net/metrics_network_client_unittest.mm',
         'browser/net/retryable_url_fetcher_unittest.mm',
+        'browser/reading_list/reading_list_entry_unittest.cc',
+        'browser/reading_list/reading_list_model_unittest.cc',
         'browser/signin/chrome_identity_service_observer_bridge_unittest.mm',
         'browser/signin/gaia_auth_fetcher_ios_unittest.mm',
         'browser/snapshots/lru_cache_unittest.mm',
diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc
index 62854b9..5f4507ad 100644
--- a/media/audio/mac/audio_low_latency_input_mac.cc
+++ b/media/audio/mac/audio_low_latency_input_mac.cc
@@ -30,6 +30,12 @@
 // if input callbacks have started, and false otherwise.
 const int kInputCallbackStartTimeoutInSeconds = 5;
 
+// Returns true if the format flags in |format_flags| has the "non-interleaved"
+// flag (kAudioFormatFlagIsNonInterleaved) cleared (set to 0).
+static bool FormatIsInterleaved(UInt32 format_flags) {
+  return !(format_flags & kAudioFormatFlagIsNonInterleaved);
+}
+
 static std::ostream& operator<<(std::ostream& os,
                                 const AudioStreamBasicDescription& format) {
   // The 32-bit integer format.mFormatID is actually a non-terminated 4 byte
@@ -46,10 +52,26 @@
      << "bytes per frame   : " << format.mBytesPerFrame << std::endl
      << "channels per frame: " << format.mChannelsPerFrame << std::endl
      << "bits per channel  : " << format.mBitsPerChannel << std::endl
-     << "reserved          : " << format.mReserved;
+     << "reserved          : " << format.mReserved << std::endl
+     << "interleaved       : "
+     << (FormatIsInterleaved(format.mFormatFlags) ? "yes" : "no");
   return os;
 }
 
+static OSStatus GetInputDeviceStreamFormat(
+    AudioUnit audio_unit,
+    AudioStreamBasicDescription* format) {
+  DCHECK(audio_unit);
+  UInt32 property_size = sizeof(*format);
+  // Get the audio stream data format on the input scope of the input element
+  // since it is connected to the current input device.
+  OSStatus result =
+      AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat,
+                           kAudioUnitScope_Input, 1, format, &property_size);
+  DVLOG(1) << "Input device stream format: " << *format;
+  return result;
+}
+
 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit"
 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html
 // for more details and background regarding this implementation.
@@ -70,7 +92,8 @@
             kNumberOfBlocksBufferInFifo),
       input_callback_is_active_(false),
       start_was_deferred_(false),
-      buffer_size_was_changed_(false) {
+      buffer_size_was_changed_(false),
+      audio_unit_render_has_worked_(false) {
   DCHECK(manager_);
 
   // Set up the desired (output) format specified by the client.
@@ -78,6 +101,7 @@
   format_.mFormatID = kAudioFormatLinearPCM;
   format_.mFormatFlags = kLinearPCMFormatFlagIsPacked |
                          kLinearPCMFormatFlagIsSignedInteger;
+  DCHECK(FormatIsInterleaved(format_.mFormatFlags));
   format_.mBitsPerChannel = input_params.bits_per_sample();
   format_.mChannelsPerFrame = input_params.channels();
   format_.mFramesPerPacket = 1;  // uncompressed audio
@@ -91,10 +115,6 @@
   DVLOG(1) << "buffer size : " << number_of_frames_;
   DVLOG(1) << "channels : " << input_params.channels();
   DVLOG(1) << "desired output format: " << format_;
-  // Ensure that the output format is interleaved.
-  const bool interleaved =
-      !(format_.mFormatFlags & kAudioFormatFlagIsNonInterleaved);
-  DCHECK(interleaved);
 
   // Derive size (in bytes) of the buffers that we will render to.
   UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame;
@@ -248,11 +268,7 @@
   // in the AUHAL, only *simple* conversions, e.g., 32-bit float to 16-bit
   // signed integer format.
   AudioStreamBasicDescription input_device_format = {0};
-  UInt32 property_size = sizeof(input_device_format);
-  result = AudioUnitGetProperty(audio_unit_, kAudioUnitProperty_StreamFormat,
-                                kAudioUnitScope_Input, 1, &input_device_format,
-                                &property_size);
-  DVLOG(1) << "Input device format: " << input_device_format;
+  GetInputDeviceStreamFormat(audio_unit_, &input_device_format);
   if (input_device_format.mSampleRate != format_.mSampleRate) {
     LOG(ERROR)
         << "Input device's sample rate does not match the client's sample rate";
@@ -285,7 +301,7 @@
   // perfect match. Any such mismatch will be compensated for in
   // OnDataIsAvailable().
   UInt32 buffer_frame_size = 0;
-  property_size = sizeof(buffer_frame_size);
+  UInt32 property_size = sizeof(buffer_frame_size);
   result = AudioUnitGetProperty(
       audio_unit_, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
       0, &buffer_frame_size, &property_size);
@@ -354,6 +370,7 @@
 
   sink_ = callback;
   last_success_time_ = base::TimeTicks::Now();
+  audio_unit_render_has_worked_ = false;
   StartAgc();
   OSStatus result = AudioOutputUnitStart(audio_unit_);
   if (result == noErr) {
@@ -605,7 +622,9 @@
   // See crbug/428706 for details.
   UInt32 new_size = number_of_frames * format_.mBytesPerFrame;
   AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers;
+  bool new_buffer_size_detected = false;
   if (new_size != audio_buffer->mDataByteSize) {
+    new_buffer_size_detected = true;
     DVLOG(1) << "New size of number_of_frames detected: " << number_of_frames;
     io_buffer_frame_size_ = static_cast<size_t>(number_of_frames);
     if (new_size > audio_buffer->mDataByteSize) {
@@ -628,6 +647,9 @@
   // renders into.
   OSStatus result = AudioUnitRender(audio_unit_, flags, time_stamp, bus_number,
                                     number_of_frames, &audio_buffer_list_);
+  if (result == noErr) {
+    audio_unit_render_has_worked_ = true;
+  }
   if (result) {
     UMA_HISTOGRAM_SPARSE_SLOWLY("Media.AudioInputCbErrorMac", result);
     OSSTATUS_LOG(ERROR, result) << "AudioUnitRender() failed ";
@@ -654,6 +676,15 @@
         LOG(ERROR) << "Too long sequence of " << err << " errors!";
         HandleError(result);
       }
+
+      // Add some extra UMA stat to track down if we see this particular error
+      // in combination with a previous change of buffer size "on the fly".
+      if (result == kAudioUnitErr_CannotDoInCurrentContext) {
+        UMA_HISTOGRAM_BOOLEAN("Media.Audio.RenderFailsWhenBufferSizeChangesMac",
+                              new_buffer_size_detected);
+        UMA_HISTOGRAM_BOOLEAN("Media.Audio.AudioUnitRenderHasWorkedMac",
+                              audio_unit_render_has_worked_);
+      }
     } else {
       // We have also seen kAudioUnitErr_NoConnection in some cases. Bailing
       // out for this error for now.
@@ -919,16 +950,16 @@
   // (by the client) number of audio frames per I/O buffer connected to the
   // selected input device. Ideally, this size will be the same as the native
   // I/O buffer size given by |io_buffer_frame_size_|.
-  UMA_HISTOGRAM_COUNTS("Media.Audio.RequestedInputBufferFrameSizeMac",
-                       number_of_frames_);
+  UMA_HISTOGRAM_SPARSE_SLOWLY("Media.Audio.RequestedInputBufferFrameSizeMac",
+                              number_of_frames_);
   DVLOG(1) << "number_of_frames_: " << number_of_frames_;
   // This value indicates the number of frames in the IO buffers connected to
   // the selected input device. It has been set by the audio manger in Open()
   // and can be the same as |number_of_frames_|, which is the desired buffer
   // size. These two values might differ if other streams are using the same
   // device and any of these streams have asked for a smaller buffer size.
-  UMA_HISTOGRAM_COUNTS("Media.Audio.ActualInputBufferFrameSizeMac",
-                       io_buffer_frame_size_);
+  UMA_HISTOGRAM_SPARSE_SLOWLY("Media.Audio.ActualInputBufferFrameSizeMac",
+                              io_buffer_frame_size_);
   DVLOG(1) << "io_buffer_frame_size_: " << io_buffer_frame_size_;
   // TODO(henrika): this value will currently always report true. It should be
   // fixed when we understand the problem better.
diff --git a/media/audio/mac/audio_low_latency_input_mac.h b/media/audio/mac/audio_low_latency_input_mac.h
index 7067985..6d2d8f5 100644
--- a/media/audio/mac/audio_low_latency_input_mac.h
+++ b/media/audio/mac/audio_low_latency_input_mac.h
@@ -215,6 +215,9 @@
   // called.
   bool buffer_size_was_changed_;
 
+  // Set to true once when AudioUnitRender() succeeds for the first time.
+  bool audio_unit_render_has_worked_;
+
   DISALLOW_COPY_AND_ASSIGN(AUAudioInputStream);
 };
 
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index 2b6ef438..97b48356 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -447,7 +447,9 @@
     return;
   }
 #if defined(OS_WIN)
-  if (base::win::GetVersion() == base::win::VERSION_WIN10) {
+  base::win::Version version = base::win::GetVersion();
+  VLOG(1) << "Windows version: " << (int)version;
+  if (version >= base::win::VERSION_WIN10) {
     VLOG(1) << "Skipped on Win10: http://crbug.com/570604.";
     return;
   }
diff --git a/mojo/edk/system/channel_win.cc b/mojo/edk/system/channel_win.cc
index 77a19a68..3678835 100644
--- a/mojo/edk/system/channel_win.cc
+++ b/mojo/edk/system/channel_win.cc
@@ -4,6 +4,7 @@
 
 #include "mojo/edk/system/channel.h"
 
+#include <stdint.h>
 #include <windows.h>
 
 #include <algorithm>
@@ -77,6 +78,8 @@
         self_(this),
         handle_(std::move(handle)),
         io_task_runner_(io_task_runner) {
+    sentinel_ = ~reinterpret_cast<uintptr_t>(this);
+    CHECK(handle_.is_valid());
     memset(&read_context_, 0, sizeof(read_context_));
     read_context_.handler = this;
 
@@ -134,7 +137,13 @@
 
  private:
   // May run on any thread.
-  ~ChannelWin() override {}
+  ~ChannelWin() override {
+    // This is intentionally not 0. If another object is constructed on top of
+    // this memory, it is likely to initialise values to 0. Using a non-zero
+    // value lets us detect the difference between just destroying, and
+    // re-allocating the memory.
+    sentinel_ = UINTPTR_MAX;
+  }
 
   void StartOnIOThread() {
     base::MessageLoop::current()->AddDestructionObserver(this);
@@ -158,6 +167,9 @@
   void ShutDownOnIOThread() {
     base::MessageLoop::current()->RemoveDestructionObserver(this);
 
+    // BUG(crbug.com/583525): This function is expected to be called once, and
+    // |handle_| should be valid at this point.
+    CHECK(handle_.is_valid());
     CancelIo(handle_.get().handle);
     handle_.reset();
 
@@ -167,6 +179,7 @@
 
   // base::MessageLoop::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
+    CheckValid();
     DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
     if (self_)
       ShutDownOnIOThread();
@@ -176,6 +189,7 @@
   void OnIOCompleted(base::MessageLoopForIO::IOContext* context,
                      DWORD bytes_transfered,
                      DWORD error) override {
+    CheckValid();
     if (error != ERROR_SUCCESS) {
       OnError();
     } else if (context == &read_context_) {
@@ -270,6 +284,10 @@
     return WriteNoLock(outgoing_messages_.front());
   }
 
+  void CheckValid() const {
+    CHECK_EQ(reinterpret_cast<uintptr_t>(this), ~sentinel_);
+  }
+
   // Keeps the Channel alive at least until explicit shutdown on the IO thread.
   scoped_refptr<Channel> self_;
 
@@ -287,6 +305,12 @@
   bool reject_writes_ = false;
   std::deque<MessageView> outgoing_messages_;
 
+  // A value that is unlikely to be valid if this object is destroyed and the
+  // memory overwritten by something else. When this is valid, its value will be
+  // ~|this|.
+  // TODO(amistry): Remove before M50 branch point.
+  uintptr_t sentinel_;
+
   DISALLOW_COPY_AND_ASSIGN(ChannelWin);
 };
 
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn
index 1adf800..c0154a72 100644
--- a/mojo/shell/BUILD.gn
+++ b/mojo/shell/BUILD.gn
@@ -121,8 +121,8 @@
 mojom("test_bindings") {
   sources = [
     "application_manager_apptests.mojom",
-    "application_package_apptest.mojom",
     "capability_filter_unittest.mojom",
+    "package_test.mojom",
     "test.mojom",
   ]
 }
@@ -133,7 +133,7 @@
 
   sources = [
     "application_manager_apptest.cc",
-    "application_package_apptest.cc",
+    "package_apptest.cc",
   ]
 
   deps = [
@@ -151,12 +151,43 @@
   data_deps = [
     ":application_manager_apptest_driver",
     ":application_manager_apptest_target",
+    ":package_test_package",
   ]
 }
 
 mojo_application_manifest("apptests_manifest") {
   application_name = "mojo_shell_apptests"
   source = "application_manager_apptest_manifest.json"
+}
+
+mojo_application_manifest("package_test_a_manifest") {
+  application_name = "package_test_a"
+  source = "package_test_app_a_manifest.json"
+}
+
+mojo_application_manifest("package_test_b_manifest") {
+  application_name = "package_test_b"
+  source = "package_test_app_b_manifest.json"
+}
+
+mojo_native_application("package_test_package") {
+  testonly = true
+  sources = [
+    "package_test_package.cc",
+  ]
+  deps = [
+    ":package_test_package_manifest",
+    ":test_bindings",
+    "//base",
+    "//mojo/common:common_base",
+    "//mojo/shell/public/cpp:sources",
+    "//mojo/shell/public/interfaces",
+  ]
+}
+
+mojo_application_manifest("package_test_package_manifest") {
+  application_name = "package_test_package"
+  source = "package_test_package_manifest.json"
   deps = [
     ":package_test_a_manifest",
     ":package_test_b_manifest",
@@ -167,16 +198,6 @@
   ]
 }
 
-mojo_application_manifest("package_test_a_manifest") {
-  application_name = "package_test_a"
-  source = "application_package_apptest_app_a_manifest.json"
-}
-
-mojo_application_manifest("package_test_b_manifest") {
-  application_name = "package_test_b"
-  source = "application_package_apptest_app_b_manifest.json"
-}
-
 executable("application_manager_apptest_driver") {
   testonly = true
 
diff --git a/mojo/shell/application_package_apptest.cc b/mojo/shell/application_package_apptest.cc
deleted file mode 100644
index 333ab70..0000000
--- a/mojo/shell/application_package_apptest.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/threading/simple_thread.h"
-#include "mojo/public/cpp/bindings/weak_binding_set.h"
-#include "mojo/shell/application_package_apptest.mojom.h"
-#include "mojo/shell/public/cpp/application_runner.h"
-#include "mojo/shell/public/cpp/application_test_base.h"
-#include "mojo/shell/public/cpp/interface_factory.h"
-#include "mojo/shell/public/interfaces/content_handler.mojom.h"
-
-// Tests that multiple applications can be packaged in a single Mojo application
-// implementing ContentHandler; that these applications can be specified by
-// the package's manifest and are thus registered with the PackageManager.
-
-namespace mojo {
-namespace shell {
-namespace {
-
-using GetNameCallback =
-    test::mojom::ApplicationPackageApptestService::GetNameCallback;
-
-class ProvidedApplicationDelegate
-    : public ShellClient,
-      public InterfaceFactory<test::mojom::ApplicationPackageApptestService>,
-      public test::mojom::ApplicationPackageApptestService,
-      public base::SimpleThread {
- public:
-  ProvidedApplicationDelegate(const std::string& name,
-                              InterfaceRequest<mojom::ShellClient> request,
-                              const Callback<void()>& destruct_callback)
-      : base::SimpleThread(name),
-        name_(name),
-        request_(std::move(request)),
-        destruct_callback_(destruct_callback) {
-    Start();
-  }
-  ~ProvidedApplicationDelegate() override {
-    Join();
-    destruct_callback_.Run();
-  }
-
- private:
-  // mojo::ShellClient:
-  void Initialize(Shell* shell, const std::string& url, uint32_t id) override {}
-  bool AcceptConnection(Connection* connection) override {
-    connection->AddInterface<test::mojom::ApplicationPackageApptestService>(
-        this);
-    return true;
-  }
-
-  // InterfaceFactory<test::mojom::ApplicationPackageApptestService>:
-  void Create(
-      Connection* connection,
-      InterfaceRequest<test::mojom::ApplicationPackageApptestService> request)
-          override {
-    bindings_.AddBinding(this, std::move(request));
-  }
-
-  // test::mojom::ApplicationPackageApptestService:
-  void GetName(const GetNameCallback& callback) override {
-    callback.Run(name_);
-  }
-
-  // base::SimpleThread:
-  void Run() override {
-    ApplicationRunner(this).Run(request_.PassMessagePipe().release().value(),
-                                false);
-    delete this;
-  }
-
-  const std::string name_;
-  InterfaceRequest<mojom::ShellClient> request_;
-  const Callback<void()> destruct_callback_;
-  WeakBindingSet<test::mojom::ApplicationPackageApptestService> bindings_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProvidedApplicationDelegate);
-};
-
-class ApplicationPackageApptestDelegate
-    : public ShellClient,
-      public InterfaceFactory<mojom::ContentHandler>,
-      public InterfaceFactory<test::mojom::ApplicationPackageApptestService>,
-      public mojom::ContentHandler,
-      public test::mojom::ApplicationPackageApptestService {
- public:
-  ApplicationPackageApptestDelegate() {}
-  ~ApplicationPackageApptestDelegate() override {}
-
- private:
-  // mojo::ShellClient:
-  void Initialize(Shell* shell, const std::string& url, uint32_t id) override {}
-  bool AcceptConnection(Connection* connection) override {
-    connection->AddInterface<ContentHandler>(this);
-    connection->AddInterface<test::mojom::ApplicationPackageApptestService>(
-        this);
-    return true;
-  }
-
-  // InterfaceFactory<mojom::ContentHandler>:
-  void Create(Connection* connection,
-              InterfaceRequest<mojom::ContentHandler> request) override {
-    content_handler_bindings_.AddBinding(this, std::move(request));
-  }
-
-  // InterfaceFactory<test::mojom::ApplicationPackageApptestService>:
-  void Create(Connection* connection,
-              InterfaceRequest<test::mojom::ApplicationPackageApptestService>
-                  request) override {
-    bindings_.AddBinding(this, std::move(request));
-  }
-
-  // mojom::ContentHandler:
-  void StartApplication(InterfaceRequest<mojom::ShellClient> request,
-                        URLResponsePtr response,
-                        const Callback<void()>& destruct_callback) override {
-    const std::string url = response->url;
-    if (url == "mojo://package_test_a/") {
-      new ProvidedApplicationDelegate("A", std::move(request),
-                                      destruct_callback);
-    } else if (url == "mojo://package_test_b/") {
-      new ProvidedApplicationDelegate("B", std::move(request),
-                                      destruct_callback);
-    }
-  }
-
-  // test::mojom::ApplicationPackageApptestService:
-  void GetName(const GetNameCallback& callback) override {
-    callback.Run("ROOT");
-  }
-
-  std::vector<scoped_ptr<ShellClient>> delegates_;
-  WeakBindingSet<mojom::ContentHandler> content_handler_bindings_;
-  WeakBindingSet<test::mojom::ApplicationPackageApptestService> bindings_;
-
-  DISALLOW_COPY_AND_ASSIGN(ApplicationPackageApptestDelegate);
-};
-
-void ReceiveName(std::string* out_name,
-                 base::RunLoop* loop,
-                 const String& name) {
-  *out_name = name;
-  loop->Quit();
-}
-
-}  // namespace
-
-class ApplicationPackageApptest : public mojo::test::ApplicationTestBase {
- public:
-  ApplicationPackageApptest() : delegate_(nullptr) {}
-  ~ApplicationPackageApptest() override {}
-
- private:
-  // test::ApplicationTestBase:
-  ShellClient* GetShellClient() override {
-    delegate_ = new ApplicationPackageApptestDelegate;
-    return delegate_;
-  }
-
-  ApplicationPackageApptestDelegate* delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(ApplicationPackageApptest);
-};
-
-TEST_F(ApplicationPackageApptest, Basic) {
-  {
-    // We need to do this to force the shell to read the test app's manifest and
-    // register aliases.
-    test::mojom::ApplicationPackageApptestServicePtr root_service;
-    shell()->ConnectToInterface("mojo:mojo_shell_apptests", &root_service);
-    base::RunLoop run_loop;
-    std::string root_name;
-    root_service->GetName(base::Bind(&ReceiveName, &root_name, &run_loop));
-    run_loop.Run();
-  }
-
-  {
-    // Now subsequent connects to applications provided by the root app will be
-    // resolved correctly.
-    test::mojom::ApplicationPackageApptestServicePtr service_a;
-    shell()->ConnectToInterface("mojo:package_test_a", &service_a);
-    base::RunLoop run_loop;
-    std::string a_name;
-    service_a->GetName(base::Bind(&ReceiveName, &a_name, &run_loop));
-    run_loop.Run();
-    EXPECT_EQ("A", a_name);
-  }
-
-  {
-    test::mojom::ApplicationPackageApptestServicePtr service_b;
-    shell()->ConnectToInterface("mojo:package_test_b", &service_b);
-    base::RunLoop run_loop;
-    std::string b_name;
-    service_b->GetName(base::Bind(&ReceiveName, &b_name, &run_loop));
-    run_loop.Run();
-    EXPECT_EQ("B", b_name);
-  }
-}
-
-}  // namespace shell
-}  // namespace mojo
diff --git a/mojo/shell/package_apptest.cc b/mojo/shell/package_apptest.cc
new file mode 100644
index 0000000..5e2db9b
--- /dev/null
+++ b/mojo/shell/package_apptest.cc
@@ -0,0 +1,84 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "mojo/shell/package_test.mojom.h"
+#include "mojo/shell/public/cpp/application_test_base.h"
+#include "mojo/shell/public/interfaces/application_manager.mojom.h"
+
+// Tests that multiple applications can be packaged in a single Mojo application
+// implementing ContentHandler; that these applications can be specified by
+// the package's manifest and are thus registered with the PackageManager.
+
+namespace mojo {
+namespace shell {
+namespace {
+void ReceiveName(std::string* out_name,
+                 base::RunLoop* loop,
+                 const String& name) {
+  *out_name = name;
+  loop->Quit();
+}
+}  // namespace
+
+using PackageApptest = mojo::test::ApplicationTestBase;
+
+TEST_F(PackageApptest, Basic) {
+  std::set<uint32_t> ids;
+  {
+    // We need to do this to force the shell to read the test app's manifest and
+    // register aliases.
+    test::mojom::PackageTestServicePtr root_service;
+    scoped_ptr<Connection> connection =
+        shell()->Connect("mojo:package_test_package");
+    connection->GetInterface(&root_service);
+    base::RunLoop run_loop;
+    std::string root_name;
+    root_service->GetName(base::Bind(&ReceiveName, &root_name, &run_loop));
+    run_loop.Run();
+    uint32_t id = mojom::Shell::kInvalidApplicationID;
+    EXPECT_TRUE(connection->GetRemoteApplicationID(&id));
+    ids.insert(id);
+  }
+
+  {
+    // Now subsequent connects to applications provided by the root app will be
+    // resolved correctly.
+    test::mojom::PackageTestServicePtr service_a;
+    scoped_ptr<Connection> connection = shell()->Connect("mojo:package_test_a");
+    connection->GetInterface(&service_a);
+    base::RunLoop run_loop;
+    std::string a_name;
+    service_a->GetName(base::Bind(&ReceiveName, &a_name, &run_loop));
+    run_loop.Run();
+    EXPECT_EQ("A", a_name);
+    uint32_t id = mojom::Shell::kInvalidApplicationID;
+    EXPECT_TRUE(connection->GetRemoteApplicationID(&id));
+    ids.insert(id);
+  }
+
+  {
+    test::mojom::PackageTestServicePtr service_b;
+    scoped_ptr<Connection> connection = shell()->Connect("mojo:package_test_b");
+    connection->GetInterface(&service_b);
+    base::RunLoop run_loop;
+    std::string b_name;
+    service_b->GetName(base::Bind(&ReceiveName, &b_name, &run_loop));
+    run_loop.Run();
+    EXPECT_EQ("B", b_name);
+    uint32_t id = mojom::Shell::kInvalidApplicationID;
+    EXPECT_TRUE(connection->GetRemoteApplicationID(&id));
+    ids.insert(id);
+  }
+}
+
+}  // namespace shell
+}  // namespace mojo
diff --git a/mojo/shell/application_package_apptest.mojom b/mojo/shell/package_test.mojom
similarity index 83%
rename from mojo/shell/application_package_apptest.mojom
rename to mojo/shell/package_test.mojom
index 88cbeead..1bcebcb29 100644
--- a/mojo/shell/application_package_apptest.mojom
+++ b/mojo/shell/package_test.mojom
@@ -4,6 +4,6 @@
 
 module mojo.shell.test.mojom;
 
-interface ApplicationPackageApptestService {
+interface PackageTestService {
   GetName() => (string name);
 };
diff --git a/mojo/shell/application_package_apptest_app_a_manifest.json b/mojo/shell/package_test_app_a_manifest.json
similarity index 100%
rename from mojo/shell/application_package_apptest_app_a_manifest.json
rename to mojo/shell/package_test_app_a_manifest.json
diff --git a/mojo/shell/application_package_apptest_app_b_manifest.json b/mojo/shell/package_test_app_b_manifest.json
similarity index 100%
rename from mojo/shell/application_package_apptest_app_b_manifest.json
rename to mojo/shell/package_test_app_b_manifest.json
diff --git a/mojo/shell/package_test_package.cc b/mojo/shell/package_test_package.cc
new file mode 100644
index 0000000..2c932689
--- /dev/null
+++ b/mojo/shell/package_test_package.cc
@@ -0,0 +1,173 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/threading/simple_thread.h"
+#include "mojo/public/c/system/main.h"
+#include "mojo/public/cpp/bindings/weak_binding_set.h"
+#include "mojo/shell/package_test.mojom.h"
+#include "mojo/shell/public/cpp/application_runner.h"
+#include "mojo/shell/public/cpp/interface_factory.h"
+#include "mojo/shell/public/cpp/shell.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/interfaces/content_handler.mojom.h"
+
+// Tests that multiple applications can be packaged in a single Mojo application
+// implementing ContentHandler; that these applications can be specified by
+// the package's manifest and are thus registered with the PackageManager.
+
+namespace mojo {
+namespace shell {
+
+using GetNameCallback = test::mojom::PackageTestService::GetNameCallback;
+
+class ProvidedShellClient
+    : public ShellClient,
+      public InterfaceFactory<test::mojom::PackageTestService>,
+      public test::mojom::PackageTestService,
+      public base::SimpleThread {
+ public:
+  ProvidedShellClient(const std::string& name,
+                      mojom::ShellClientRequest request,
+                      const Callback<void()>& destruct_callback)
+      : base::SimpleThread(name),
+        name_(name),
+        request_(std::move(request)),
+        destruct_callback_(destruct_callback),
+        shell_(nullptr) {
+    Start();
+  }
+  ~ProvidedShellClient() override {
+    Join();
+    destruct_callback_.Run();
+  }
+
+ private:
+  // mojo::ShellClient:
+  void Initialize(Shell* shell, const std::string& url, uint32_t id) override {
+    shell_ = shell;
+    bindings_.set_connection_error_handler(
+        base::Bind(&ProvidedShellClient::OnConnectionError,
+                   base::Unretained(this)));
+  }
+  bool AcceptConnection(Connection* connection) override {
+    connection->AddInterface<test::mojom::PackageTestService>(
+        this);
+    return true;
+  }
+
+  // InterfaceFactory<test::mojom::PackageTestService>:
+  void Create(Connection* connection,
+              test::mojom::PackageTestServiceRequest request) override {
+    bindings_.AddBinding(this, std::move(request));
+  }
+
+  // test::mojom::PackageTestService:
+  void GetName(const GetNameCallback& callback) override {
+    callback.Run(name_);
+  }
+
+  // base::SimpleThread:
+  void Run() override {
+    ApplicationRunner(this).Run(request_.PassMessagePipe().release().value(),
+                                false);
+    delete this;
+  }
+
+  void OnConnectionError() {
+    if (bindings_.empty())
+      shell_->Quit();
+  }
+
+  const std::string name_;
+  mojom::ShellClientRequest request_;
+  const Callback<void()> destruct_callback_;
+  Shell* shell_;
+  WeakBindingSet<test::mojom::PackageTestService> bindings_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProvidedShellClient);
+};
+
+class PackageTestShellClient
+    : public ShellClient,
+      public InterfaceFactory<mojom::ContentHandler>,
+      public InterfaceFactory<test::mojom::PackageTestService>,
+      public mojom::ContentHandler,
+      public test::mojom::PackageTestService {
+ public:
+  PackageTestShellClient() : shell_(nullptr) {}
+  ~PackageTestShellClient() override {}
+
+ private:
+  // mojo::ShellClient:
+  void Initialize(Shell* shell, const std::string& url, uint32_t id) override {
+    shell_ = shell;
+    bindings_.set_connection_error_handler(
+        base::Bind(&PackageTestShellClient::OnConnectionError,
+                   base::Unretained(this)));
+  }
+  bool AcceptConnection(Connection* connection) override {
+    connection->AddInterface<ContentHandler>(this);
+    connection->AddInterface<test::mojom::PackageTestService>(
+        this);
+    return true;
+  }
+
+  // InterfaceFactory<mojom::ContentHandler>:
+  void Create(Connection* connection,
+              mojom::ContentHandlerRequest request) override {
+    content_handler_bindings_.AddBinding(this, std::move(request));
+  }
+
+  // InterfaceFactory<test::mojom::PackageTestService>:
+  void Create(Connection* connection,
+              test::mojom::PackageTestServiceRequest request) override {
+    bindings_.AddBinding(this, std::move(request));
+  }
+
+  // mojom::ContentHandler:
+  void StartApplication(mojom::ShellClientRequest request,
+                        URLResponsePtr response,
+                        const Callback<void()>& destruct_callback) override {
+    const std::string url = response->url;
+    if (url == "mojo://package_test_a/")
+      new ProvidedShellClient("A", std::move(request), destruct_callback);
+    else if (url == "mojo://package_test_b/")
+      new ProvidedShellClient("B", std::move(request), destruct_callback);
+  }
+
+  // test::mojom::PackageTestService:
+  void GetName(const GetNameCallback& callback) override {
+    callback.Run("ROOT");
+  }
+
+  void OnConnectionError() {
+    if (bindings_.empty())
+      shell_->Quit();
+  }
+
+  Shell* shell_;
+  std::vector<scoped_ptr<ShellClient>> delegates_;
+  WeakBindingSet<mojom::ContentHandler> content_handler_bindings_;
+  WeakBindingSet<test::mojom::PackageTestService> bindings_;
+
+  DISALLOW_COPY_AND_ASSIGN(PackageTestShellClient);
+};
+
+}  // namespace shell
+}  // namespace mojo
+
+
+MojoResult MojoMain(MojoHandle shell_handle) {
+  MojoResult rv = mojo::ApplicationRunner(
+      new mojo::shell::PackageTestShellClient).Run(shell_handle);
+  return rv;
+}
diff --git a/mojo/shell/package_test_package_manifest.json b/mojo/shell/package_test_package_manifest.json
new file mode 100644
index 0000000..d4825b26
--- /dev/null
+++ b/mojo/shell/package_test_package_manifest.json
@@ -0,0 +1,5 @@
+{
+  "url": "mojo://package_test_package/",
+  "name": "Package Test Package",
+  "capabilities": { }
+}
diff --git a/mojo/shell/public/cpp/lib/application_runner.cc b/mojo/shell/public/cpp/lib/application_runner.cc
index c4aba6d..de4bfe96 100644
--- a/mojo/shell/public/cpp/lib/application_runner.cc
+++ b/mojo/shell/public/cpp/lib/application_runner.cc
@@ -72,7 +72,12 @@
 }
 
 MojoResult ApplicationRunner::Run(MojoHandle shell_client_request_handle) {
-  return Run(shell_client_request_handle, true);
+  bool init_base = true;
+  if (base::CommandLine::InitializedForCurrentProcess()) {
+    init_base =
+        !base::CommandLine::ForCurrentProcess()->HasSwitch("single-process");
+  }
+  return Run(shell_client_request_handle, init_base);
 }
 
 }  // namespace mojo
diff --git a/remoting/host/basic_desktop_environment.cc b/remoting/host/basic_desktop_environment.cc
index b65018e8..cdaadf0 100644
--- a/remoting/host/basic_desktop_environment.cc
+++ b/remoting/host/basic_desktop_environment.cc
@@ -10,7 +10,9 @@
 #include "build/build_config.h"
 #include "remoting/host/audio_capturer.h"
 #include "remoting/host/client_session_control.h"
+#include "remoting/host/desktop_capturer_proxy.h"
 #include "remoting/host/input_injector.h"
+#include "remoting/host/mouse_cursor_monitor_proxy.h"
 #include "remoting/host/screen_controls.h"
 #include "remoting/host/security_key/gnubby_auth_handler.h"
 #include "remoting/protocol/capability_names.h"
@@ -52,12 +54,16 @@
 
 scoped_ptr<webrtc::MouseCursorMonitor>
 BasicDesktopEnvironment::CreateMouseCursorMonitor() {
+  scoped_ptr<webrtc::MouseCursorMonitor> cursor_monitor;
+
 #if defined(OS_CHROMEOS)
-  return make_scoped_ptr(new MouseCursorMonitorAura());
+  cursor_monitor.reset(new MouseCursorMonitorAura());
 #else
-  return make_scoped_ptr(webrtc::MouseCursorMonitor::CreateForScreen(
+  cursor_monitor.reset(webrtc::MouseCursorMonitor::CreateForScreen(
       *desktop_capture_options_, webrtc::kFullDesktopScreenId));
 #endif
+  return make_scoped_ptr(new MouseCursorMonitorProxy(
+      video_capture_task_runner_, std::move(cursor_monitor)));
 }
 
 std::string BasicDesktopEnvironment::GetCapabilities() const {
@@ -79,27 +85,30 @@
 BasicDesktopEnvironment::CreateVideoCapturer() {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
+  scoped_ptr<webrtc::DesktopCapturer> capturer;
+
 #if defined(OS_CHROMEOS)
-  return scoped_ptr<webrtc::DesktopCapturer>(new AuraDesktopCapturer());
+  capturer.reset(new AuraDesktopCapturer());
 #else  // !defined(OS_CHROMEOS)
-  // The basic desktop environment does not use X DAMAGE, since it is
-  // broken on many systems - see http://crbug.com/73423.
-  return make_scoped_ptr(
-      webrtc::ScreenCapturer::Create(*desktop_capture_options_));
+  capturer.reset(webrtc::ScreenCapturer::Create(*desktop_capture_options_));
 #endif  // !defined(OS_CHROMEOS)
+
+  return make_scoped_ptr(new DesktopCapturerProxy(video_capture_task_runner_,
+                                                  std::move(capturer)));
 }
 
 BasicDesktopEnvironment::BasicDesktopEnvironment(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     bool supports_touch_events)
     : caller_task_runner_(caller_task_runner),
+      video_capture_task_runner_(video_capture_task_runner),
       input_task_runner_(input_task_runner),
       ui_task_runner_(ui_task_runner),
-      desktop_capture_options_(
-          new webrtc::DesktopCaptureOptions(
-              webrtc::DesktopCaptureOptions::CreateDefault())),
+      desktop_capture_options_(new webrtc::DesktopCaptureOptions(
+          webrtc::DesktopCaptureOptions::CreateDefault())),
       supports_touch_events_(supports_touch_events) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 #if defined(USE_X11)
@@ -109,16 +118,16 @@
 
 BasicDesktopEnvironmentFactory::BasicDesktopEnvironmentFactory(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : caller_task_runner_(caller_task_runner),
+      video_capture_task_runner_(video_capture_task_runner),
       input_task_runner_(input_task_runner),
       ui_task_runner_(ui_task_runner),
-      supports_touch_events_(false) {
-}
+      supports_touch_events_(false) {}
 
-BasicDesktopEnvironmentFactory::~BasicDesktopEnvironmentFactory() {
-}
+BasicDesktopEnvironmentFactory::~BasicDesktopEnvironmentFactory() {}
 
 bool BasicDesktopEnvironmentFactory::SupportsAudioCapture() const {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
diff --git a/remoting/host/basic_desktop_environment.h b/remoting/host/basic_desktop_environment.h
index c99c831..8530061 100644
--- a/remoting/host/basic_desktop_environment.h
+++ b/remoting/host/basic_desktop_environment.h
@@ -45,6 +45,7 @@
 
   BasicDesktopEnvironment(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       bool supports_touch_events);
@@ -53,6 +54,11 @@
     return caller_task_runner_;
   }
 
+  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner()
+      const {
+    return video_capture_task_runner_;
+  }
+
   scoped_refptr<base::SingleThreadTaskRunner> input_task_runner() const {
     return input_task_runner_;
   }
@@ -70,6 +76,9 @@
   // called.
   scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
 
+  // Used to run video capturer.
+  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner_;
+
   // Used to run input-related tasks.
   scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
 
@@ -94,6 +103,7 @@
  public:
   BasicDesktopEnvironmentFactory(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~BasicDesktopEnvironmentFactory() override;
@@ -110,6 +120,11 @@
     return caller_task_runner_;
   }
 
+  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner()
+      const {
+    return video_capture_task_runner_;
+  }
+
   scoped_refptr<base::SingleThreadTaskRunner> input_task_runner() const {
     return input_task_runner_;
   }
@@ -125,6 +140,9 @@
   // be called.
   scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
 
+  // Used to run video capture tasks.
+  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner_;
+
   // Used to run input-related tasks.
   scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
 
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc
index 885f2e9..81ccacfb 100644
--- a/remoting/host/chromoting_host.cc
+++ b/remoting/host/chromoting_host.cc
@@ -68,26 +68,16 @@
     scoped_ptr<protocol::SessionManager> session_manager,
     scoped_refptr<protocol::TransportContext> transport_context,
     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+    scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner)
     : desktop_environment_factory_(desktop_environment_factory),
       session_manager_(std::move(session_manager)),
       transport_context_(transport_context),
       audio_task_runner_(audio_task_runner),
-      input_task_runner_(input_task_runner),
-      video_capture_task_runner_(video_capture_task_runner),
       video_encode_task_runner_(video_encode_task_runner),
-      network_task_runner_(network_task_runner),
-      ui_task_runner_(ui_task_runner),
       started_(false),
       login_backoff_(&kDefaultBackoffPolicy),
       enable_curtaining_(false),
       weak_factory_(this) {
-  DCHECK(network_task_runner_->BelongsToCurrentThread());
-
   jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
 }
 
@@ -142,7 +132,7 @@
 }
 
 void ChromotingHost::SetEnableCurtaining(bool enable) {
-  DCHECK(network_task_runner_->BelongsToCurrentThread());
+  DCHECK(CalledOnValidThread());
 
   if (enable_curtaining_ == enable)
     return;
@@ -285,11 +275,10 @@
   }
 
   // Create a ClientSession object.
-  ClientSession* client = new ClientSession(
-      this, audio_task_runner_, input_task_runner_, video_capture_task_runner_,
-      video_encode_task_runner_, network_task_runner_, ui_task_runner_,
-      std::move(connection), desktop_environment_factory_,
-      max_session_duration_, pairing_registry_, extensions_.get());
+  ClientSession* client =
+      new ClientSession(this, audio_task_runner_, std::move(connection),
+                        desktop_environment_factory_, max_session_duration_,
+                        pairing_registry_, extensions_.get());
 
   clients_.push_back(client);
 }
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h
index 3b1a1fa..78ae1e4 100644
--- a/remoting/host/chromoting_host.h
+++ b/remoting/host/chromoting_host.h
@@ -72,11 +72,7 @@
       scoped_ptr<protocol::SessionManager> session_manager,
       scoped_refptr<protocol::TransportContext> transport_context,
       scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
+      scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner);
   ~ChromotingHost() override;
 
   // Asynchronously starts the host.
@@ -160,11 +156,7 @@
   scoped_ptr<protocol::SessionManager> session_manager_;
   scoped_refptr<protocol::TransportContext> transport_context_;
   scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 
   // Must be used on the network thread only.
   base::ObserverList<HostStatusObserver> status_observers_;
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc
index f033eee..1b94ed5 100644
--- a/remoting/host/chromoting_host_unittest.cc
+++ b/remoting/host/chromoting_host_unittest.cc
@@ -67,11 +67,7 @@
         desktop_environment_factory_.get(), make_scoped_ptr(session_manager_),
         protocol::TransportContext::ForTests(protocol::TransportRole::SERVER),
         task_runner_,    // Audio
-        task_runner_,    // Input
-        task_runner_,    // Video capture
-        task_runner_,    // Video encode
-        task_runner_,    // Network
-        task_runner_));  // UI
+        task_runner_));  // Video encode
     host_->AddStatusObserver(&host_status_observer_);
 
     xmpp_login_ = "host@domain";
@@ -129,13 +125,7 @@
         (connection_index == 0) ? owned_connection1_ : owned_connection2_);
     protocol::ConnectionToClient* connection_ptr = connection.get();
     scoped_ptr<ClientSession> client(new ClientSession(
-        host_.get(),
-        task_runner_,  // Audio
-        task_runner_,  // Input
-        task_runner_,  // Video capture
-        task_runner_,  // Video encode
-        task_runner_,  // Network
-        task_runner_,  // UI
+        host_.get(), task_runner_ /* audio_task_runner */,
         std::move(connection), desktop_environment_factory_.get(),
         base::TimeDelta(), nullptr, std::vector<HostExtension*>()));
     ClientSession* client_ptr = client.get();
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index e51db407..8aa6997ac 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -18,11 +18,9 @@
 #include "remoting/codec/audio_encoder_verbatim.h"
 #include "remoting/host/audio_capturer.h"
 #include "remoting/host/audio_pump.h"
-#include "remoting/host/desktop_capturer_proxy.h"
 #include "remoting/host/desktop_environment.h"
 #include "remoting/host/host_extension_session.h"
 #include "remoting/host/input_injector.h"
-#include "remoting/host/mouse_cursor_monitor_proxy.h"
 #include "remoting/host/mouse_shape_pump.h"
 #include "remoting/host/screen_controls.h"
 #include "remoting/host/screen_resolution.h"
@@ -65,11 +63,6 @@
 ClientSession::ClientSession(
     EventHandler* event_handler,
     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     scoped_ptr<protocol::ConnectionToClient> connection,
     DesktopEnvironmentFactory* desktop_environment_factory,
     const base::TimeDelta& max_duration,
@@ -87,11 +80,6 @@
       client_clipboard_factory_(clipboard_echo_filter_.client_filter()),
       max_duration_(max_duration),
       audio_task_runner_(audio_task_runner),
-      input_task_runner_(input_task_runner),
-      video_capture_task_runner_(video_capture_task_runner),
-      video_encode_task_runner_(video_encode_task_runner),
-      network_task_runner_(network_task_runner),
-      ui_task_runner_(ui_task_runner),
       pairing_registry_(pairing_registry),
       is_authenticated_(false),
       pause_video_(false),
@@ -455,21 +443,13 @@
     return;
 
   // Create MouseShapePump to send mouse cursor shape.
-  // TODO(sergeyu): Move MouseCursorMonitorProxy creation to DesktopEnvironment.
-  // When using IpcDesktopCapturer the capture thread is not useful.
   mouse_shape_pump_.reset(
-      new MouseShapePump(make_scoped_ptr(new MouseCursorMonitorProxy(
-                             video_capture_task_runner_,
-                             desktop_environment_->CreateMouseCursorMonitor())),
+      new MouseShapePump(desktop_environment_->CreateMouseCursorMonitor(),
                          connection_->client_stub()));
 
   // Create a VideoStream to pump frames from the capturer to the client.
-  // TODO(sergeyu): Move DesktopCapturerProxy creation to DesktopEnvironment.
-  // When using IpcDesktopCapturer the capture thread is not useful.
-  scoped_ptr<webrtc::DesktopCapturer> capturer_proxy(new DesktopCapturerProxy(
-      video_capture_task_runner_, std::move(video_capturer)));
+  video_stream_ = connection_->StartVideoStream(std::move(video_capturer));
 
-  video_stream_ = connection_->StartVideoStream(std::move(capturer_proxy));
   video_stream_->SetSizeCallback(
       base::Bind(&ClientSession::OnScreenSizeChanged, base::Unretained(this)));
 
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h
index 750a8af7..03965919 100644
--- a/remoting/host/client_session.h
+++ b/remoting/host/client_session.h
@@ -86,19 +86,13 @@
 
   // |event_handler| and |desktop_environment_factory| must outlive |this|.
   // All |HostExtension|s in |extensions| must outlive |this|.
-  ClientSession(
-      EventHandler* event_handler,
-      scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      scoped_ptr<protocol::ConnectionToClient> connection,
-      DesktopEnvironmentFactory* desktop_environment_factory,
-      const base::TimeDelta& max_duration,
-      scoped_refptr<protocol::PairingRegistry> pairing_registry,
-      const std::vector<HostExtension*>& extensions);
+  ClientSession(EventHandler* event_handler,
+                scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
+                scoped_ptr<protocol::ConnectionToClient> connection,
+                DesktopEnvironmentFactory* desktop_environment_factory,
+                const base::TimeDelta& max_duration,
+                scoped_refptr<protocol::PairingRegistry> pairing_registry,
+                const std::vector<HostExtension*>& extensions);
   ~ClientSession() override;
 
   // Returns the set of capabilities negotiated between client and host.
@@ -203,11 +197,6 @@
   base::OneShotTimer max_duration_timer_;
 
   scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 
   // Objects responsible for sending video, audio and mouse shape.
   // |video_stream_| and |mouse_shape_pump_| may be nullptr if the video
diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc
index dade4725..3e7eacb 100644
--- a/remoting/host/client_session_unittest.cc
+++ b/remoting/host/client_session_unittest.cc
@@ -188,11 +188,6 @@
   client_session_.reset(new ClientSession(
       &session_event_handler_,
       task_runner_,  // Audio thread.
-      task_runner_,  // Input thread.
-      task_runner_,  // Capture thread.
-      task_runner_,  // Encode thread.
-      task_runner_,  // Network thread.
-      task_runner_,  // UI thread.
       std::move(connection), desktop_environment_factory_.get(),
       base::TimeDelta(), nullptr, extensions_));
 }
diff --git a/remoting/host/desktop_process.cc b/remoting/host/desktop_process.cc
index 749fd65..b0afa8e 100644
--- a/remoting/host/desktop_process.cc
+++ b/remoting/host/desktop_process.cc
@@ -121,16 +121,10 @@
       AutoThread::CreateWithType(
           "I/O thread", caller_task_runner_, base::MessageLoop::TYPE_IO);
 
-  // Launch the video capture thread.
-  scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner =
-      AutoThread::Create("Video capture thread", caller_task_runner_);
-
   // Create a desktop agent.
-  desktop_agent_ = new DesktopSessionAgent(audio_task_runner,
-                                           caller_task_runner_,
-                                           input_task_runner_,
-                                           io_task_runner,
-                                           video_capture_task_runner);
+  desktop_agent_ =
+      new DesktopSessionAgent(audio_task_runner, caller_task_runner_,
+                              input_task_runner_, io_task_runner);
 
   // Start the agent and create an IPC channel to talk to it.
   IPC::PlatformFileForTransit desktop_pipe;
diff --git a/remoting/host/desktop_process_main.cc b/remoting/host/desktop_process_main.cc
index 95242c9..794128c 100644
--- a/remoting/host/desktop_process_main.cc
+++ b/remoting/host/desktop_process_main.cc
@@ -40,6 +40,10 @@
       new AutoThreadTaskRunner(message_loop.task_runner(),
                                run_loop.QuitClosure());
 
+  // Launch the video capture thread.
+  scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner =
+      AutoThread::Create("Video capture thread", ui_task_runner);
+
   // Launch the input thread.
   scoped_refptr<AutoThreadTaskRunner> input_task_runner =
       AutoThread::CreateWithType(
@@ -52,17 +56,13 @@
   // Create a platform-dependent environment factory.
   scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory;
 #if defined(OS_WIN)
-  desktop_environment_factory.reset(
-      new SessionDesktopEnvironmentFactory(
-          ui_task_runner,
-          input_task_runner,
-          ui_task_runner,
-          base::Bind(&DesktopProcess::InjectSas,
-                     desktop_process.AsWeakPtr())));
+  desktop_environment_factory.reset(new SessionDesktopEnvironmentFactory(
+      ui_task_runner, video_capture_task_runner, input_task_runner,
+      ui_task_runner,
+      base::Bind(&DesktopProcess::InjectSas, desktop_process.AsWeakPtr())));
 #else  // !defined(OS_WIN)
   desktop_environment_factory.reset(new Me2MeDesktopEnvironmentFactory(
-      ui_task_runner,
-      input_task_runner,
+      ui_task_runner, video_capture_task_runner, input_task_runner,
       ui_task_runner));
 #endif  // !defined(OS_WIN)
 
diff --git a/remoting/host/desktop_process_unittest.cc b/remoting/host/desktop_process_unittest.cc
index 55aac14..97d0249 100644
--- a/remoting/host/desktop_process_unittest.cc
+++ b/remoting/host/desktop_process_unittest.cc
@@ -25,6 +25,7 @@
 #include "remoting/base/auto_thread_task_runner.h"
 #include "remoting/host/chromoting_messages.h"
 #include "remoting/host/desktop_process.h"
+#include "remoting/host/fake_mouse_cursor_monitor.h"
 #include "remoting/host/host_exit_codes.h"
 #include "remoting/host/host_mock_objects.h"
 #include "remoting/host/screen_resolution.h"
@@ -123,6 +124,10 @@
   // DesktopEnvironment::CreateVideoCapturer().
   webrtc::DesktopCapturer* CreateVideoCapturer();
 
+  // Creates a fake webrtc::MouseCursorMonitor, to mock
+  // DesktopEnvironment::CreateMouseCursorMonitor().
+  webrtc::MouseCursorMonitor* CreateMouseCursorMonitor();
+
   // Disconnects the daemon-to-desktop channel causing the desktop process to
   // exit.
   void DisconnectChannels();
@@ -207,6 +212,9 @@
   EXPECT_CALL(*desktop_environment, CreateVideoCapturerPtr())
       .Times(AtMost(1))
       .WillOnce(Invoke(this, &DesktopProcessTest::CreateVideoCapturer));
+  EXPECT_CALL(*desktop_environment, CreateMouseCursorMonitorPtr())
+      .Times(AtMost(1))
+      .WillOnce(Invoke(this, &DesktopProcessTest::CreateMouseCursorMonitor));
   EXPECT_CALL(*desktop_environment, GetCapabilities())
       .Times(AtMost(1));
   EXPECT_CALL(*desktop_environment, SetCapabilities(_))
@@ -227,6 +235,10 @@
   return new protocol::FakeDesktopCapturer();
 }
 
+webrtc::MouseCursorMonitor* DesktopProcessTest::CreateMouseCursorMonitor() {
+  return new FakeMouseCursorMonitor();
+}
+
 void DesktopProcessTest::DisconnectChannels() {
   daemon_channel_.reset();
   network_channel_.reset();
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index d8ac3e7..ed594d4 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -158,13 +158,11 @@
     scoped_refptr<AutoThreadTaskRunner> audio_capture_task_runner,
     scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
     scoped_refptr<AutoThreadTaskRunner> input_task_runner,
-    scoped_refptr<AutoThreadTaskRunner> io_task_runner,
-    scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner)
+    scoped_refptr<AutoThreadTaskRunner> io_task_runner)
     : audio_capture_task_runner_(audio_capture_task_runner),
       caller_task_runner_(caller_task_runner),
       input_task_runner_(input_task_runner),
       io_task_runner_(io_task_runner),
-      video_capture_task_runner_(video_capture_task_runner),
       weak_factory_(this) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 }
@@ -315,14 +313,16 @@
 
   // Start the video capturer and mouse cursor monitor.
   video_capturer_ = desktop_environment_->CreateVideoCapturer();
+  video_capturer_->Start(this);
+  video_capturer_->SetSharedMemoryFactory(
+      rtc_make_scoped_ptr(new SharedMemoryFactoryImpl(
+          base::Bind(&DesktopSessionAgent::SendToNetwork, this))));
   mouse_cursor_monitor_ = desktop_environment_->CreateMouseCursorMonitor();
-  video_capture_task_runner_->PostTask(
-      FROM_HERE, base::Bind(
-          &DesktopSessionAgent::StartVideoCapturerAndMouseMonitor, this));
+  mouse_cursor_monitor_->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY);
 }
 
 void DesktopSessionAgent::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
-  DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   last_frame_.reset(frame);
 
@@ -345,7 +345,7 @@
 }
 
 void DesktopSessionAgent::OnMouseCursor(webrtc::MouseCursor* cursor) {
-  DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   scoped_ptr<webrtc::MouseCursor> owned_cursor(cursor);
 
@@ -440,19 +440,14 @@
         FROM_HERE, base::Bind(&DesktopSessionAgent::StopAudioCapturer, this));
 
     // Stop the video capturer.
-    video_capture_task_runner_->PostTask(
-        FROM_HERE, base::Bind(
-            &DesktopSessionAgent::StopVideoCapturerAndMouseMonitor, this));
+    video_capturer_.reset();
+    last_frame_.reset();
+    mouse_cursor_monitor_.reset();
   }
 }
 
 void DesktopSessionAgent::OnCaptureFrame() {
-  if (!video_capture_task_runner_->BelongsToCurrentThread()) {
-    video_capture_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&DesktopSessionAgent::OnCaptureFrame, this));
-    return;
-  }
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   mouse_cursor_monitor_->Capture();
 
@@ -583,27 +578,4 @@
   audio_capturer_.reset();
 }
 
-void DesktopSessionAgent::StartVideoCapturerAndMouseMonitor() {
-  DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
-
-  if (video_capturer_) {
-    video_capturer_->Start(this);
-    video_capturer_->SetSharedMemoryFactory(
-        rtc_make_scoped_ptr(new SharedMemoryFactoryImpl(
-            base::Bind(&DesktopSessionAgent::SendToNetwork, this))));
-  }
-
-  if (mouse_cursor_monitor_) {
-    mouse_cursor_monitor_->Init(this, webrtc::MouseCursorMonitor::SHAPE_ONLY);
-  }
-}
-
-void DesktopSessionAgent::StopVideoCapturerAndMouseMonitor() {
-  DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
-
-  video_capturer_.reset();
-  last_frame_.reset();
-  mouse_cursor_monitor_.reset();
-}
-
 }  // namespace remoting
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h
index 8004bcd..358bfce 100644
--- a/remoting/host/desktop_session_agent.h
+++ b/remoting/host/desktop_session_agent.h
@@ -70,8 +70,7 @@
       scoped_refptr<AutoThreadTaskRunner> audio_capture_task_runner,
       scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
       scoped_refptr<AutoThreadTaskRunner> input_task_runner,
-      scoped_refptr<AutoThreadTaskRunner> io_task_runner,
-      scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner);
+      scoped_refptr<AutoThreadTaskRunner> io_task_runner);
 
   // IPC::Listener implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
@@ -142,14 +141,6 @@
   // Posted to |audio_capture_task_runner_| to stop the audio capturer.
   void StopAudioCapturer();
 
-  // Posted to |video_capture_task_runner_| to start the video capturer and the
-  // mouse cursor monitor.
-  void StartVideoCapturerAndMouseMonitor();
-
-  // Posted to |video_capture_task_runner_| to stop the video capturer and the
-  // mouse cursor monitor.
-  void StopVideoCapturerAndMouseMonitor();
-
  private:
   // Task runner dedicated to running methods of |audio_capturer_|.
   scoped_refptr<AutoThreadTaskRunner> audio_capture_task_runner_;
@@ -163,9 +154,6 @@
   // Task runner used by the IPC channel.
   scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
 
-  // Task runner dedicated to running methods of |video_capturer_|.
-  scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner_;
-
   // Captures audio output.
   scoped_ptr<AudioCapturer> audio_capturer_;
 
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc
index a7bfdba..4dbe639 100644
--- a/remoting/host/desktop_session_proxy.cc
+++ b/remoting/host/desktop_session_proxy.cc
@@ -90,7 +90,6 @@
     scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     base::WeakPtr<ClientSessionControl> client_session_control,
     base::WeakPtr<DesktopSessionConnector> desktop_session_connector,
     bool virtual_terminal,
@@ -98,7 +97,6 @@
     : audio_capture_task_runner_(audio_capture_task_runner),
       caller_task_runner_(caller_task_runner),
       io_task_runner_(io_task_runner),
-      video_capture_task_runner_(video_capture_task_runner),
       client_session_control_(client_session_control),
       desktop_session_connector_(desktop_session_connector),
       pending_capture_frame_requests_(0),
@@ -276,7 +274,7 @@
   // Generate fake responses to keep the video capturer in sync.
   while (pending_capture_frame_requests_) {
     --pending_capture_frame_requests_;
-    PostCaptureCompleted(nullptr);
+    video_capturer_->OnCaptureCompleted(nullptr);
   }
 }
 
@@ -288,30 +286,26 @@
 }
 
 void DesktopSessionProxy::CaptureFrame() {
-  if (!caller_task_runner_->BelongsToCurrentThread()) {
-    caller_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&DesktopSessionProxy::CaptureFrame, this));
-    return;
-  }
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   if (desktop_channel_) {
     ++pending_capture_frame_requests_;
     SendToDesktop(new ChromotingNetworkDesktopMsg_CaptureFrame());
   } else {
-    PostCaptureCompleted(nullptr);
+    video_capturer_->OnCaptureCompleted(nullptr);
   }
 }
 
 void DesktopSessionProxy::SetVideoCapturer(
     const base::WeakPtr<IpcVideoFrameCapturer> video_capturer) {
-  DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   video_capturer_ = video_capturer;
 }
 
 void DesktopSessionProxy::SetMouseCursorMonitor(
     const base::WeakPtr<IpcMouseCursorMonitor>& mouse_cursor_monitor) {
-  DCHECK(video_capture_task_runner_->BelongsToCurrentThread());
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
   mouse_cursor_monitor_ = mouse_cursor_monitor;
 }
@@ -507,13 +501,17 @@
   }
 
   --pending_capture_frame_requests_;
-  PostCaptureCompleted(std::move(frame));
+  video_capturer_->OnCaptureCompleted(std::move(frame));
 }
 
 void DesktopSessionProxy::OnMouseCursor(
     const webrtc::MouseCursor& mouse_cursor) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
-  PostMouseCursor(make_scoped_ptr(webrtc::MouseCursor::CopyOf(mouse_cursor)));
+
+  if (mouse_cursor_monitor_) {
+    mouse_cursor_monitor_->OnMouseCursor(
+        make_scoped_ptr(webrtc::MouseCursor::CopyOf(mouse_cursor)));
+  }
 }
 
 void DesktopSessionProxy::OnInjectClipboardEvent(
@@ -531,26 +529,6 @@
   }
 }
 
-void DesktopSessionProxy::PostCaptureCompleted(
-    scoped_ptr<webrtc::DesktopFrame> frame) {
-  DCHECK(caller_task_runner_->BelongsToCurrentThread());
-
-  video_capture_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&IpcVideoFrameCapturer::OnCaptureCompleted, video_capturer_,
-                 base::Passed(&frame)));
-}
-
-void DesktopSessionProxy::PostMouseCursor(
-    scoped_ptr<webrtc::MouseCursor> mouse_cursor) {
-  DCHECK(caller_task_runner_->BelongsToCurrentThread());
-
-  video_capture_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&IpcMouseCursorMonitor::OnMouseCursor, mouse_cursor_monitor_,
-                 base::Passed(&mouse_cursor)));
-}
-
 void DesktopSessionProxy::SendToDesktop(IPC::Message* message) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h
index 52fa521..f54713f 100644
--- a/remoting/host/desktop_session_proxy.h
+++ b/remoting/host/desktop_session_proxy.h
@@ -76,7 +76,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       base::WeakPtr<ClientSessionControl> client_session_control,
       base::WeakPtr<DesktopSessionConnector> desktop_session_connector,
       bool virtual_terminal,
@@ -169,14 +168,6 @@
   // Handles InjectClipboardEvent request from the desktop integration process.
   void OnInjectClipboardEvent(const std::string& serialized_event);
 
-  // Posts OnCaptureCompleted() to |video_capturer_| on the video thread,
-  // passing |frame|.
-  void PostCaptureCompleted(scoped_ptr<webrtc::DesktopFrame> frame);
-
-  // Posts OnMouseCursor() to |mouse_cursor_monitor_| on the video thread,
-  // passing |mouse_cursor|.
-  void PostMouseCursor(scoped_ptr<webrtc::MouseCursor> mouse_cursor);
-
   // Sends a message to the desktop session agent. The message is silently
   // deleted if the channel is broken.
   void SendToDesktop(IPC::Message* message);
@@ -186,11 +177,9 @@
   //   - public methods of this class (with some exceptions) are called on
   //     |caller_task_runner_|.
   //   - background I/O is served on |io_task_runner_|.
-  //   - |video_capturer_| is called back on |video_capture_task_runner_|.
   scoped_refptr<base::SingleThreadTaskRunner> audio_capture_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner_;
 
   // Points to the audio capturer receiving captured audio packets.
   base::WeakPtr<IpcAudioCapturer> audio_capturer_;
diff --git a/remoting/host/ipc_desktop_environment.cc b/remoting/host/ipc_desktop_environment.cc
index 129a584..25dd9dc 100644
--- a/remoting/host/ipc_desktop_environment.cc
+++ b/remoting/host/ipc_desktop_environment.cc
@@ -28,7 +28,6 @@
 IpcDesktopEnvironment::IpcDesktopEnvironment(
     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     base::WeakPtr<ClientSessionControl> client_session_control,
     base::WeakPtr<DesktopSessionConnector> desktop_session_connector,
@@ -36,18 +35,13 @@
     bool supports_touch_events) {
   DCHECK(caller_task_runner->BelongsToCurrentThread());
 
-  desktop_session_proxy_ = new DesktopSessionProxy(audio_task_runner,
-                                                   caller_task_runner,
-                                                   io_task_runner,
-                                                   capture_task_runner,
-                                                   client_session_control,
-                                                   desktop_session_connector,
-                                                   virtual_terminal,
-                                                   supports_touch_events);
+  desktop_session_proxy_ = new DesktopSessionProxy(
+      audio_task_runner, caller_task_runner, io_task_runner,
+      client_session_control, desktop_session_connector, virtual_terminal,
+      supports_touch_events);
 }
 
-IpcDesktopEnvironment::~IpcDesktopEnvironment() {
-}
+IpcDesktopEnvironment::~IpcDesktopEnvironment() {}
 
 scoped_ptr<AudioCapturer> IpcDesktopEnvironment::CreateAudioCapturer() {
   return desktop_session_proxy_->CreateAudioCapturer();
@@ -87,36 +81,24 @@
 IpcDesktopEnvironmentFactory::IpcDesktopEnvironmentFactory(
     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     IPC::Sender* daemon_channel)
     : audio_task_runner_(audio_task_runner),
       caller_task_runner_(caller_task_runner),
-      capture_task_runner_(capture_task_runner),
       io_task_runner_(io_task_runner),
-      curtain_enabled_(false),
       daemon_channel_(daemon_channel),
-      next_id_(0),
-      connector_factory_(this),
-      supports_touch_events_(false) {
-}
+      connector_factory_(this) {}
 
-IpcDesktopEnvironmentFactory::~IpcDesktopEnvironmentFactory() {
-}
+IpcDesktopEnvironmentFactory::~IpcDesktopEnvironmentFactory() {}
 
 scoped_ptr<DesktopEnvironment> IpcDesktopEnvironmentFactory::Create(
     base::WeakPtr<ClientSessionControl> client_session_control) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  return make_scoped_ptr(
-      new IpcDesktopEnvironment(audio_task_runner_,
-                                caller_task_runner_,
-                                capture_task_runner_,
-                                io_task_runner_,
-                                client_session_control,
-                                connector_factory_.GetWeakPtr(),
-                                curtain_enabled_,
-                                supports_touch_events_));
+  return make_scoped_ptr(new IpcDesktopEnvironment(
+      audio_task_runner_, caller_task_runner_, io_task_runner_,
+      client_session_control, connector_factory_.GetWeakPtr(), curtain_enabled_,
+      supports_touch_events_));
 }
 
 void IpcDesktopEnvironmentFactory::SetEnableCurtaining(bool enable) {
diff --git a/remoting/host/ipc_desktop_environment.h b/remoting/host/ipc_desktop_environment.h
index c874337e..6d8cb7a 100644
--- a/remoting/host/ipc_desktop_environment.h
+++ b/remoting/host/ipc_desktop_environment.h
@@ -41,7 +41,6 @@
   IpcDesktopEnvironment(
       scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       base::WeakPtr<ClientSessionControl> client_session_control,
       base::WeakPtr<DesktopSessionConnector> desktop_session_connector,
@@ -77,7 +76,6 @@
   IpcDesktopEnvironmentFactory(
       scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       IPC::Sender* daemon_channel);
   ~IpcDesktopEnvironmentFactory() override;
@@ -114,14 +112,11 @@
   // be called.
   scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
 
-  // Used to run the video capturer.
-  scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
-
   // Task runner used for running background I/O.
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
 
   // True if curtain mode is enabled.
-  bool curtain_enabled_;
+  bool curtain_enabled_ = false;
 
   // IPC channel connected to the daemon process.
   IPC::Sender* daemon_channel_;
@@ -133,15 +128,15 @@
   // Next desktop session ID. IDs are allocated sequentially starting from 0.
   // This gives us more than 67 years of unique IDs assuming a new ID is
   // allocated every second.
-  int next_id_;
+  int next_id_ = 0;
+
+  // Defines whether desktop environments created by this factory will support
+  // touch events by default.
+  bool supports_touch_events_ = false;
 
   // Factory for weak pointers to DesktopSessionConnector interface.
   base::WeakPtrFactory<DesktopSessionConnector> connector_factory_;
 
-  // If true then the newly Create()ed desktop environments support touch
-  // events.
-  bool supports_touch_events_;
-
   DISALLOW_COPY_AND_ASSIGN(IpcDesktopEnvironmentFactory);
 };
 
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc
index 1a32693..86b9c80 100644
--- a/remoting/host/ipc_desktop_environment_unittest.cc
+++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -294,11 +294,7 @@
 
   // Create a desktop environment instance.
   desktop_environment_factory_.reset(new IpcDesktopEnvironmentFactory(
-      task_runner_,
-      task_runner_,
-      task_runner_,
-      io_task_runner_,
-      &daemon_channel_));
+      task_runner_, task_runner_, io_task_runner_, &daemon_channel_));
   desktop_environment_ = desktop_environment_factory_->Create(
       client_session_control_factory_.GetWeakPtr());
 
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc
index 3fc19d0a..f3a32a2 100644
--- a/remoting/host/it2me/it2me_host.cc
+++ b/remoting/host/it2me/it2me_host.cc
@@ -77,8 +77,8 @@
 
   desktop_environment_factory_.reset(new It2MeDesktopEnvironmentFactory(
       host_context_->network_task_runner(),
-      host_context_->input_task_runner(),
-      host_context_->ui_task_runner()));
+      host_context_->video_capture_task_runner(),
+      host_context_->input_task_runner(), host_context_->ui_task_runner()));
 
   // Start monitoring configured policies.
   policy_watcher_->StartWatching(
@@ -255,13 +255,10 @@
   session_manager->set_protocol_config(std::move(protocol_config));
 
   // Create the host.
-  host_.reset(new ChromotingHost(
-      desktop_environment_factory_.get(), std::move(session_manager),
-      transport_context, host_context_->audio_task_runner(),
-      host_context_->input_task_runner(),
-      host_context_->video_capture_task_runner(),
-      host_context_->video_encode_task_runner(),
-      host_context_->network_task_runner(), host_context_->ui_task_runner()));
+  host_.reset(new ChromotingHost(desktop_environment_factory_.get(),
+                                 std::move(session_manager), transport_context,
+                                 host_context_->audio_task_runner(),
+                                 host_context_->video_encode_task_runner()));
   host_->AddStatusObserver(this);
   host_status_logger_.reset(
       new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::IT2ME,
diff --git a/remoting/host/it2me_desktop_environment.cc b/remoting/host/it2me_desktop_environment.cc
index 511f4cc..f2f7cf05 100644
--- a/remoting/host/it2me_desktop_environment.cc
+++ b/remoting/host/it2me_desktop_environment.cc
@@ -27,11 +27,13 @@
 
 It2MeDesktopEnvironment::It2MeDesktopEnvironment(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     base::WeakPtr<ClientSessionControl> client_session_control,
     bool supports_touch_events)
     : BasicDesktopEnvironment(caller_task_runner,
+                              video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
                               supports_touch_events) {
@@ -72,25 +74,23 @@
 
 It2MeDesktopEnvironmentFactory::It2MeDesktopEnvironmentFactory(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : BasicDesktopEnvironmentFactory(caller_task_runner,
+                                     video_capture_task_runner,
                                      input_task_runner,
-                                     ui_task_runner) {
-}
+                                     ui_task_runner) {}
 
-It2MeDesktopEnvironmentFactory::~It2MeDesktopEnvironmentFactory() {
-}
+It2MeDesktopEnvironmentFactory::~It2MeDesktopEnvironmentFactory() {}
 
 scoped_ptr<DesktopEnvironment> It2MeDesktopEnvironmentFactory::Create(
     base::WeakPtr<ClientSessionControl> client_session_control) {
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
-  return make_scoped_ptr(new It2MeDesktopEnvironment(caller_task_runner(),
-                                                     input_task_runner(),
-                                                     ui_task_runner(),
-                                                     client_session_control,
-                                                     supports_touch_events()));
+  return make_scoped_ptr(new It2MeDesktopEnvironment(
+      caller_task_runner(), video_capture_task_runner(), input_task_runner(),
+      ui_task_runner(), client_session_control, supports_touch_events()));
 }
 
 }  // namespace remoting
diff --git a/remoting/host/it2me_desktop_environment.h b/remoting/host/it2me_desktop_environment.h
index 218187b..54118ba 100644
--- a/remoting/host/it2me_desktop_environment.h
+++ b/remoting/host/it2me_desktop_environment.h
@@ -25,6 +25,7 @@
   friend class It2MeDesktopEnvironmentFactory;
   It2MeDesktopEnvironment(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       base::WeakPtr<ClientSessionControl> client_session_control,
@@ -48,6 +49,7 @@
  public:
   It2MeDesktopEnvironmentFactory(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~It2MeDesktopEnvironmentFactory() override;
diff --git a/remoting/host/me2me_desktop_environment.cc b/remoting/host/me2me_desktop_environment.cc
index 6e278b3..c3b2568 100644
--- a/remoting/host/me2me_desktop_environment.cc
+++ b/remoting/host/me2me_desktop_environment.cc
@@ -52,15 +52,20 @@
 
 Me2MeDesktopEnvironment::Me2MeDesktopEnvironment(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     bool supports_touch_events)
     : BasicDesktopEnvironment(caller_task_runner,
+                              video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
-                              supports_touch_events),
-      gnubby_auth_enabled_(false) {
+                              supports_touch_events) {
   DCHECK(caller_task_runner->BelongsToCurrentThread());
+
+  // X DAMAGE is not enabled by default, since it is broken on many systems -
+  // see http://crbug.com/73423. It's safe to enable it here because it works
+  // properly under Xvfb.
   desktop_capture_options()->set_use_update_notifications(true);
 }
 
@@ -132,13 +137,13 @@
 
 Me2MeDesktopEnvironmentFactory::Me2MeDesktopEnvironmentFactory(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : BasicDesktopEnvironmentFactory(caller_task_runner,
+                                     video_capture_task_runner,
                                      input_task_runner,
-                                     ui_task_runner),
-      curtain_enabled_(false) {
-}
+                                     ui_task_runner) {}
 
 Me2MeDesktopEnvironmentFactory::~Me2MeDesktopEnvironmentFactory() {
 }
@@ -148,10 +153,9 @@
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
   scoped_ptr<Me2MeDesktopEnvironment> desktop_environment(
-      new Me2MeDesktopEnvironment(caller_task_runner(),
-                                  input_task_runner(),
-                                  ui_task_runner(),
-                                  supports_touch_events()));
+      new Me2MeDesktopEnvironment(
+          caller_task_runner(), video_capture_task_runner(),
+          input_task_runner(), ui_task_runner(), supports_touch_events()));
   if (!desktop_environment->InitializeSecurity(client_session_control,
                                                curtain_enabled_)) {
     return nullptr;
diff --git a/remoting/host/me2me_desktop_environment.h b/remoting/host/me2me_desktop_environment.h
index 7faf9a5..6d9969f 100644
--- a/remoting/host/me2me_desktop_environment.h
+++ b/remoting/host/me2me_desktop_environment.h
@@ -30,6 +30,7 @@
   friend class Me2MeDesktopEnvironmentFactory;
   Me2MeDesktopEnvironment(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       bool supports_touch_events);
@@ -54,7 +55,7 @@
   scoped_ptr<LocalInputMonitor> local_input_monitor_;
 
   // True if gnubby auth is enabled.
-  bool gnubby_auth_enabled_;
+  bool gnubby_auth_enabled_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(Me2MeDesktopEnvironment);
 };
@@ -64,6 +65,7 @@
  public:
   Me2MeDesktopEnvironmentFactory(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~Me2MeDesktopEnvironmentFactory() override;
@@ -79,10 +81,10 @@
 
  private:
   // True if curtain mode is enabled.
-  bool curtain_enabled_;
+  bool curtain_enabled_ = false;
 
   // True if gnubby auth is enabled.
-  bool gnubby_auth_enabled_;
+  bool gnubby_auth_enabled_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(Me2MeDesktopEnvironmentFactory);
 };
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index b664dd2..a80ef55b 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -897,27 +897,19 @@
 #if defined(REMOTING_MULTI_PROCESS)
   IpcDesktopEnvironmentFactory* desktop_environment_factory =
       new IpcDesktopEnvironmentFactory(
-          context_->audio_task_runner(),
-          context_->network_task_runner(),
-          context_->video_capture_task_runner(),
-          context_->network_task_runner(),
-          daemon_channel_.get());
+          context_->audio_task_runner(), context_->network_task_runner(),
+          context_->network_task_runner(), daemon_channel_.get());
   desktop_session_connector_ = desktop_environment_factory;
 #else  // !defined(REMOTING_MULTI_PROCESS)
   BasicDesktopEnvironmentFactory* desktop_environment_factory;
   if (enable_window_capture_) {
-    desktop_environment_factory =
-      new SingleWindowDesktopEnvironmentFactory(
-          context_->network_task_runner(),
-          context_->input_task_runner(),
-          context_->ui_task_runner(),
-          window_id_);
+    desktop_environment_factory = new SingleWindowDesktopEnvironmentFactory(
+        context_->network_task_runner(), context_->video_capture_task_runner(),
+        context_->input_task_runner(), context_->ui_task_runner(), window_id_);
   } else {
-    desktop_environment_factory =
-      new Me2MeDesktopEnvironmentFactory(
-          context_->network_task_runner(),
-          context_->input_task_runner(),
-          context_->ui_task_runner());
+    desktop_environment_factory = new Me2MeDesktopEnvironmentFactory(
+        context_->network_task_runner(), context_->video_capture_task_runner(),
+        context_->input_task_runner(), context_->ui_task_runner());
   }
 #endif  // !defined(REMOTING_MULTI_PROCESS)
   desktop_environment_factory->set_supports_touch_events(
@@ -1543,12 +1535,10 @@
   }
   session_manager->set_protocol_config(std::move(protocol_config));
 
-  host_.reset(new ChromotingHost(
-      desktop_environment_factory_.get(), std::move(session_manager),
-      transport_context, context_->audio_task_runner(),
-      context_->input_task_runner(), context_->video_capture_task_runner(),
-      context_->video_encode_task_runner(), context_->network_task_runner(),
-      context_->ui_task_runner()));
+  host_.reset(new ChromotingHost(desktop_environment_factory_.get(),
+                                 std::move(session_manager), transport_context,
+                                 context_->audio_task_runner(),
+                                 context_->video_encode_task_runner()));
 
   if (frame_recorder_buffer_size_ > 0) {
     scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
diff --git a/remoting/host/single_window_desktop_environment.cc b/remoting/host/single_window_desktop_environment.cc
index d120932..0f2b1480 100644
--- a/remoting/host/single_window_desktop_environment.cc
+++ b/remoting/host/single_window_desktop_environment.cc
@@ -29,6 +29,7 @@
   friend class SingleWindowDesktopEnvironmentFactory;
   SingleWindowDesktopEnvironment(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       webrtc::WindowId window_id,
@@ -70,27 +71,29 @@
 
 SingleWindowDesktopEnvironment::SingleWindowDesktopEnvironment(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     webrtc::WindowId window_id,
     bool supports_touch_events)
     : BasicDesktopEnvironment(caller_task_runner,
+                              video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
                               supports_touch_events),
-      window_id_(window_id) {
-}
+      window_id_(window_id) {}
 
 SingleWindowDesktopEnvironmentFactory::SingleWindowDesktopEnvironmentFactory(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     webrtc::WindowId window_id)
     : BasicDesktopEnvironmentFactory(caller_task_runner,
+                                     video_capture_task_runner,
                                      input_task_runner,
                                      ui_task_runner),
-      window_id_(window_id) {
-}
+      window_id_(window_id) {}
 
 SingleWindowDesktopEnvironmentFactory::
     ~SingleWindowDesktopEnvironmentFactory() {
@@ -100,13 +103,9 @@
     base::WeakPtr<ClientSessionControl> client_session_control) {
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
-  scoped_ptr<SingleWindowDesktopEnvironment> desktop_environment(
-      new SingleWindowDesktopEnvironment(caller_task_runner(),
-                                         input_task_runner(),
-                                         ui_task_runner(),
-                                         window_id_,
-                                         supports_touch_events()));
-  return std::move(desktop_environment);
+  return make_scoped_ptr(new SingleWindowDesktopEnvironment(
+      caller_task_runner(), video_capture_task_runner(), input_task_runner(),
+      ui_task_runner(), window_id_, supports_touch_events()));
 }
 
 }  // namespace remoting
diff --git a/remoting/host/single_window_desktop_environment.h b/remoting/host/single_window_desktop_environment.h
index a446cc9..c4e84ea 100644
--- a/remoting/host/single_window_desktop_environment.h
+++ b/remoting/host/single_window_desktop_environment.h
@@ -18,6 +18,7 @@
  public:
   SingleWindowDesktopEnvironmentFactory(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       webrtc::WindowId window_id);
diff --git a/remoting/host/win/session_desktop_environment.cc b/remoting/host/win/session_desktop_environment.cc
index 045562f..9d9f8b2 100644
--- a/remoting/host/win/session_desktop_environment.cc
+++ b/remoting/host/win/session_desktop_environment.cc
@@ -29,40 +29,43 @@
 
 SessionDesktopEnvironment::SessionDesktopEnvironment(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     const base::Closure& inject_sas,
     bool supports_touch_events)
     : Me2MeDesktopEnvironment(caller_task_runner,
+                              video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
                               supports_touch_events),
-      inject_sas_(inject_sas) {
-}
+      inject_sas_(inject_sas) {}
 
 SessionDesktopEnvironmentFactory::SessionDesktopEnvironmentFactory(
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
     const base::Closure& inject_sas)
     : Me2MeDesktopEnvironmentFactory(caller_task_runner,
+                                     video_capture_task_runner,
                                      input_task_runner,
                                      ui_task_runner),
       inject_sas_(inject_sas) {
   DCHECK(caller_task_runner->BelongsToCurrentThread());
 }
 
-SessionDesktopEnvironmentFactory::~SessionDesktopEnvironmentFactory() {
-}
+SessionDesktopEnvironmentFactory::~SessionDesktopEnvironmentFactory() {}
 
 scoped_ptr<DesktopEnvironment> SessionDesktopEnvironmentFactory::Create(
     base::WeakPtr<ClientSessionControl> client_session_control) {
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
   scoped_ptr<SessionDesktopEnvironment> desktop_environment(
-      new SessionDesktopEnvironment(caller_task_runner(), input_task_runner(),
-                                    ui_task_runner(), inject_sas_,
-                                    supports_touch_events()));
+      new SessionDesktopEnvironment(caller_task_runner(),
+                                    video_capture_task_runner(),
+                                    input_task_runner(), ui_task_runner(),
+                                    inject_sas_, supports_touch_events()));
   if (!desktop_environment->InitializeSecurity(client_session_control,
                                                curtain_enabled())) {
     return nullptr;
diff --git a/remoting/host/win/session_desktop_environment.h b/remoting/host/win/session_desktop_environment.h
index cc4b187..96fd493 100644
--- a/remoting/host/win/session_desktop_environment.h
+++ b/remoting/host/win/session_desktop_environment.h
@@ -26,6 +26,7 @@
   friend class SessionDesktopEnvironmentFactory;
   SessionDesktopEnvironment(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       const base::Closure& inject_sas,
@@ -42,6 +43,7 @@
  public:
   SessionDesktopEnvironmentFactory(
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
       const base::Closure& inject_sas);
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc
index b936479b..fa1a325 100644
--- a/remoting/test/protocol_perftest.cc
+++ b/remoting/test/protocol_perftest.cc
@@ -331,9 +331,7 @@
     host_.reset(new ChromotingHost(
         &desktop_environment_factory_, std::move(session_manager),
         transport_context, host_thread_.task_runner(),
-        host_thread_.task_runner(), capture_thread_.task_runner(),
-        encode_thread_.task_runner(), host_thread_.task_runner(),
-        host_thread_.task_runner()));
+        encode_thread_.task_runner()));
 
     base::FilePath certs_dir(net::GetTestCertsDirectory());
 
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/css-supports-supports-variables.html b/third_party/WebKit/LayoutTests/fast/css/variables/css-supports-supports-variables.html
new file mode 100644
index 0000000..b0d2b37
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/variables/css-supports-supports-variables.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<style>
+#testElem {
+  --foo:pretty much anything;
+  --space: space at start;
+  --bar:including this(</style>
+<style>
+#testElem {
+  --far\ :this is OK too ();
+  --foo\ \ :and this \(;
+}
+</style>
+<style>
+#testElem {
+  --wow: wow!;
+}
+</style>
+<style>
+#testElem {
+  --yay: yay :-);
+}
+</style>
+<style>
+#testElem {
+  --n:
+</style>
+<style>
+#testElem {
+  --wrong: '
+</style>
+<div id='testElem'></div>
+<script>
+test(function() {
+  assert_true(CSS.supports('--foo', 'pretty much anything'));
+  assert_true(CSS.supports('--bar', 'including this('));
+  assert_true(CSS.supports('--far ', 'this is OK too ()'));
+  assert_true(CSS.supports('--foo   ', 'and this \\('));
+  assert_false(CSS.supports('--wow', 'wow!'));
+  assert_false(CSS.supports('--yay', 'yay :-)'));
+  assert_true(CSS.supports('--n', '\n'));
+  assert_false(CSS.supports('--wrong', "'\n"));
+  assert_true(CSS.supports('--space', ' space at start'));
+
+  assert_false(CSS.supports('--width', '100px) and (width: 100px'),
+    "it's tempting to implement this supports function in terms of the other one. Don't.");
+}, "Test that CSS.supports(prop, val) returns true for custom properties.");
+
+test(function() {
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--foo'), 'pretty much anything');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--bar'), 'including this(');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--far '), 'this is OK too ()');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--foo  '), 'and this \\(');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--wow'), '');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--yay'), '');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--n'), ' ');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--wrong'), '');
+  assert_equals(getComputedStyle(testElem).getPropertyValue('--space'), ' space at start');
+}, "Test that above CSS.supports values can be specified in style.");
+
+test(function() {
+  testElem.style.setProperty('--foo', 'pretty much anything');
+  testElem.style.setProperty('--bar', 'including this(');
+  testElem.style.setProperty('--far ', 'this is OK too ()');
+  testElem.style.setProperty('--foo  ', 'and this \\(');
+  testElem.style.setProperty('--wow', 'wow!');
+  testElem.style.setProperty('--yay', 'yay :-)');
+  testElem.style.setProperty('--n', '\n');
+  testElem.style.setProperty('--wrong', "'\n");
+  testElem.style.setProperty('--space', ' space at start');
+  assert_equals(testElem.style.getPropertyValue('--foo'), 'pretty much anything');
+  assert_equals(testElem.style.getPropertyValue('--bar'), 'including this(');
+  assert_equals(testElem.style.getPropertyValue('--far '), 'this is OK too ()');
+  assert_equals(testElem.style.getPropertyValue('--foo  '), 'and this \\(');
+  assert_equals(testElem.style.getPropertyValue('--wow'), '');
+  assert_equals(testElem.style.getPropertyValue('--yay'), '');
+  assert_equals(testElem.style.getPropertyValue('--n'), ' ');
+  assert_equals(testElem.style.getPropertyValue('--wrong'), '');
+  assert_equals(testElem.style.getPropertyValue('--space'), ' space at start');
+}, "Test that above CSS.supports values can be written into inline style via CSSOM API");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/content-reprojection-recalc-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/shadow/content-reprojection-recalc-expected.txt
new file mode 100644
index 0000000..f7e9dbb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/content-reprojection-recalc-expected.txt
@@ -0,0 +1,11 @@
+Redistribution into same position should not cause style recalc
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.internals is defined.
+PASS internals.updateStyleAndReturnAffectedElementCount() is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/content-reprojection-recalc.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/content-reprojection-recalc.html
new file mode 100644
index 0000000..a486de2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/content-reprojection-recalc.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script src="../../../resources/js-test.js"></script>
+<div id="host">
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+</div>
+<script>
+description("Redistribution into same position should not cause style recalc");
+
+shouldBeDefined("window.internals");
+
+var root = host.createShadowRoot();
+root.innerHTML = "<content></content>";
+
+host.offsetTop;
+
+host.appendChild(document.createElement("div"));
+
+shouldBe("internals.updateStyleAndReturnAffectedElementCount()", "1");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/v1-slots-api-dynamic.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/v1-slots-api-dynamic.html
new file mode 100644
index 0000000..5d51a08
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/v1-slots-api-dynamic.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<script src='../../../resources/testharness.js'></script>
+<script src='../../../resources/testharnessreport.js'></script>
+<script src='resources/shadow-dom.js'></script>
+<div id='d1'>
+  <template data-mode='open' data-expose-as='d1_shadow'>
+    <div id='d1-d1'>
+      <template data-mode='open' data-expose-as='d1_d1_shadow'>
+        <slot name='d1-d1-s1'></slot>
+      </template>
+      <slot name='d1-s1' slot='d1-d1-s1'></slot>
+    </div>
+  </template>
+  <div id='d2' slot='d1-s1'></div>
+</div>
+<script>
+'use strict';
+convertTemplatesToShadowRootsWithin(d1);
+removeWhiteSpaceOnlyTextNodes(d1);
+
+test(() => {
+  const d1_s1 = d1_shadow.querySelector('slot');
+  const d1_d1_s1 = d1_d1_shadow.querySelector('slot');
+
+  assert_array_equals(d1_s1.getAssignedNodes(), [d2]);
+  assert_array_equals(d1_s1.getAssignedNodes({'flatten': true}), [d2]);
+
+  assert_array_equals(d1_d1_s1.getAssignedNodes(), [d1_s1]);
+  assert_array_equals(d1_d1_s1.getAssignedNodes({'flatten': true}), [d2]);
+
+  const d3 = document.createElement('div');
+  d3.setAttribute('id', 'd3');
+  d3.setAttribute('slot', 'd1-s1');
+  d1.appendChild(d3);
+
+  assert_array_equals(d1_s1.getAssignedNodes(), [d2, d3]);
+  assert_array_equals(d1_s1.getAssignedNodes({'flatten': true}), [d2, d3]);
+
+  assert_array_equals(d1_d1_s1.getAssignedNodes(), [d1_s1]);
+  assert_array_equals(d1_d1_s1.getAssignedNodes({'flatten': true}), [d2, d3]);
+}, "Distribution should be re-calcualted when assigned nodes of a slot in the parent tree is changed");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight.js
index fea9e4d..c2b1389d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight.js
@@ -12,94 +12,110 @@
     var checkMethod = checkJsonpMethod.bind(this, method);
     TEST_TARGETS.push(
       // Tests for Access-Control-Allow-Headers header.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method + '&headers=CUSTOM',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=*',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=' + BASE_ORIGIN,
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=*&ACAHeaders=x-serviceworker-test',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=' + BASE_ORIGIN +
        '&ACAHeaders=x-serviceworker-test',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&ACAHeaders=x-serviceworker-test&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&ACAHeaders=x-serviceworker-test' +
+       '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
        [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=' + BASE_ORIGIN +
-       '&ACAHeaders=x-serviceworker-test&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+       '&ACAHeaders=x-serviceworker-test' +
+       '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
        [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
 
       // Test that Access-Control-Allow-Headers is checked in
       // CORS preflight fetch.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&ACAHeaders=x-serviceworker-test&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&ACAHeaders=x-serviceworker-test&PreflightTest=200',
        [fetchRejected]],
 
       // Test that CORS check is done in both preflight and main fetch.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAHeaders=x-serviceworker-test' +
+       '&PreflightTest=200',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&PACAOrigin=*&PACAHeaders=x-serviceworker-test' +
+       '&PreflightTest=200',
        [fetchRejected]],
 
       // Test that Access-Control-Expose-Headers of CORS preflight is ignored.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PACEHeaders=Content-Length, X-ServiceWorker-ServerHeader&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PACEHeaders=Content-Length, X-ServiceWorker-ServerHeader&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
 
       // Test that CORS preflight with Status 2XX succeeds.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=201',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PreflightTest=201',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
 
       // Test that CORS preflight with Status other than 2XX fails.
       // https://crbug.com/452394
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=301',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PreflightTest=301',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=401',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PreflightTest=401',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PreflightTest=500',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PreflightTest=500',
        [fetchRejected]],
 
       // Test CORS preflight with multiple request headers.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-servicEworker-u, x-servicEworker-ua, x-servicewOrker-test, x-sErviceworker-s, x-sErviceworker-v&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM2&ACAOrigin=*' +
+       '&PACAOrigin=*&PACAHeaders=x-servicEworker-u, x-servicEworker-ua, x-servicewOrker-test, x-sErviceworker-s, x-sErviceworker-v&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader2]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-servicewOrker-test&PreflightTest=200',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-servicewOrker-test&PreflightTest=200',
        [fetchRejected]],
 
       // Test request headers sent in CORS preflight requests.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-serviceworker-test&PACRMethod=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-serviceworker-test&PACRMethod=' + method +
        '&PACRHeaders=x-serviceworker-test&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
       // Test Access-Control-Request-Headers is sorted https://crbug.com/452391
 
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*&PACAHeaders=x-servicEworker-u, x-servicEworker-ua, x-servicewOrker-test, x-sErviceworker-s, x-sErviceworker-v&PACRMethod=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*' +
+       '&PACAHeaders=x-servicEworker-u, x-servicEworker-ua, x-servicewOrker-test, x-sErviceworker-s, x-sErviceworker-v&PACRMethod=' + method +
        '&PACRHeaders=x-serviceworker-s, x-serviceworker-test, x-serviceworker-u, x-serviceworker-ua, x-serviceworker-v&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader2]]);
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight2.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight2.js
index b09bd7f8..ec49232e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight2.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors-preflight2.js
@@ -18,149 +18,157 @@
       // https://fetch.spec.whatwg.org/#cors-preflight-fetch
       // Tests for Access-Control-Allow-Methods header.
       // Tests for Access-Control-Allow-Headers header.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method,
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method,
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method + '&ACAMethods=' + method,
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&ACAMethods=' + method,
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method + '&ACAOrigin=*',
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&ACAOrigin=*',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&ACAMethods=' + method,
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&headers=CUSTOM&ACAMethods=' + method,
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&headers=CUSTOM&ACAMethods=' + method +
        '&ACAHeaders=x-serviceworker-test',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&headers=CUSTOM&ACAMethods=' + method +
+       '&ACAHeaders=x-serviceworker-test' +
+       '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+       [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
+       [checkMethod, hasCustomHeader]],
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&ACAOrigin=*&headers=CUSTOM&ACAMethods=PUT, XXX',
+       [fetchRejected]],
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&ACAOrigin=*&headers=CUSTOM&ACAMethods=PUT, XXX' +
+       '&ACAHeaders=x-serviceworker-test',
+       [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
+       [checkMethod, hasCustomHeader]],
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
+       '&ACAOrigin=*&headers=CUSTOM&ACAMethods=PUT, XXX' +
        '&ACAHeaders=x-serviceworker-test&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
        [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&ACAOrigin=*&headers=CUSTOM&ACAMethods=PUT, XXX',
-       [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&ACAOrigin=*&headers=CUSTOM&ACAMethods=PUT, XXX&ACAHeaders=x-serviceworker-test',
-       [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
-       [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
-       '&ACAOrigin=*&headers=CUSTOM&ACAMethods=PUT, XXX&ACAHeaders=x-serviceworker-test&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
-       [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
-       [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN,
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN + '&ACAMethods=' + method,
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN + '&headers=CUSTOM&ACAMethods=' + method,
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN + '&headers=CUSTOM&ACAMethods=' + method +
        '&ACAHeaders=x-serviceworker-test',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN + '&headers=CUSTOM&ACAMethods=' + method +
-       '&ACAHeaders=x-serviceworker-test&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+       '&ACAHeaders=x-serviceworker-test' +
+       '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
        [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN + '&headers=CUSTOM&ACAMethods=PUT, XXX',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN +
        '&headers=CUSTOM&ACAMethods=PUT, XXX&ACAHeaders=x-serviceworker-test',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=' + BASE_ORIGIN +
-       '&headers=CUSTOM&ACAMethods=PUT, XXX&ACAHeaders=x-serviceworker-test&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+       '&headers=CUSTOM&ACAMethods=PUT, XXX&ACAHeaders=x-serviceworker-test' +
+       '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
        [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
 
       // Test that Access-Control-Allow-Methods is checked in
       // CORS preflight fetch.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method + '&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&ACAMethods=' + method + '&PreflightTest=200',
        [fetchRejected]],
 
       // Test that Access-Control-Allow-Headers is checked in
       // CORS preflight fetch.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
        '&PACAHeaders=x-serviceworker-test&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
        '&ACAHeaders=x-serviceworker-test&PreflightTest=200',
        [fetchRejected]],
 
       // Test that CORS check is done in both preflight and main fetch.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAMethods=' + method + '&PreflightTest=200',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&PACAOrigin=*&PACAMethods=' + method + '&PreflightTest=200',
        [fetchRejected]],
 
       // Test that Access-Control-Expose-Headers of CORS preflight is ignored.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
-       '&PACEHeaders=Content-Length, X-ServiceWorker-ServerHeader&PreflightTest=200',
+       '&PACEHeaders=Content-Length, X-ServiceWorker-ServerHeader' +
+       '&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod]],
 
       // Test that CORS preflight with Status 2XX succeeds.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method + '&PreflightTest=201',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod]],
 
       // Test that CORS preflight with Status other than 2XX fails.
       // https://crbug.com/452394
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method + '&PreflightTest=301',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method + '&PreflightTest=401',
        [fetchRejected]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method + '&PreflightTest=500',
        [fetchRejected]],
 
       // Test CORS preflight with multiple request headers.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
        '&PACAHeaders=x-servicEworker-u, x-servicEworker-ua, x-servicewOrker-test, x-sErviceworker-s, x-sErviceworker-v&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader2]],
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
        '&PACAHeaders=x-servicewOrker-test&PreflightTest=200',
        [fetchRejected]],
 
       // Test request headers sent in CORS preflight requests.
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
        '&PACAHeaders=x-serviceworker-test&PACRMethod=' + method +
        '&PACRHeaders=x-serviceworker-test&PreflightTest=200',
        [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
        [checkMethod, hasCustomHeader]],
       // Test Access-Control-Request-Headers is sorted https://crbug.com/452391
-      [OTHER_BASE_URL + 'mode=cors&method=' + method +
+      [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=' + method +
        '&headers=CUSTOM2&ACAOrigin=*&PACAOrigin=*&PACAMethods=' + method +
        '&PACAHeaders=x-servicEworker-u, x-servicEworker-ua, x-servicewOrker-test, x-sErviceworker-s, x-sErviceworker-v&PACRMethod=' + method +
        '&PACRHeaders=x-serviceworker-s, x-serviceworker-test, x-serviceworker-u, x-serviceworker-ua, x-serviceworker-v&PreflightTest=200',
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors.js
index 409cf6a..93b153c3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/cors.js
@@ -18,34 +18,40 @@
   // CORS check
   // https://fetch.spec.whatwg.org/#concept-cors-check
   // Tests for Access-Control-Allow-Origin header.
-  [OTHER_BASE_URL + 'mode=cors&method=GET',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET',
    [fetchRejected]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=*',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=' + BASE_ORIGIN,
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=' + BASE_ORIGIN,
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=' + BASE_ORIGIN +
-   ',http://www.example.com',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET&' +
+   'ACAOrigin=' + BASE_ORIGIN + ',http://www.example.com',
    [fetchRejected]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=http://www.example.com',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=http://www.example.com',
    [fetchRejected]],
 
   // CORS filtered response
   // https://fetch.spec.whatwg.org/#concept-filtered-response-cors
   // Tests for Access-Control-Expose-Headers header.
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=*&ACEHeaders=X-ServiceWorker-ServerHeader',
-   [fetchResolved, noContentLength, hasServerHeader, hasBody, typeCors],
-   [methodIsGET]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=' + BASE_ORIGIN +
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET&ACAOrigin=*' +
    '&ACEHeaders=X-ServiceWorker-ServerHeader',
    [fetchResolved, noContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsGET]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=*&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=' + BASE_ORIGIN +
+   '&ACEHeaders=X-ServiceWorker-ServerHeader',
+   [fetchResolved, noContentLength, hasServerHeader, hasBody, typeCors],
+   [methodIsGET]],
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=*&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsGET]],
-  [OTHER_BASE_URL + 'mode=cors&method=GET&ACAOrigin=' + BASE_ORIGIN +
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=' + BASE_ORIGIN +
    '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsGET]],
@@ -55,34 +61,40 @@
   // CORS check
   // https://fetch.spec.whatwg.org/#concept-cors-check
   // Tests for Access-Control-Allow-Origin header.
-  [OTHER_BASE_URL + 'mode=cors&method=POST',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST',
    [fetchRejected]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=*',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsPOST]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=' + BASE_ORIGIN,
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=' + BASE_ORIGIN,
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsPOST]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=' + BASE_ORIGIN +
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=' + BASE_ORIGIN +
    ',http://www.example.com',
    [fetchRejected]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=http://www.example.com',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=http://www.example.com',
    [fetchRejected]],
 
   // CORS filtered response
   // https://fetch.spec.whatwg.org/#concept-filtered-response-cors
   // Tests for Access-Control-Expose-Headers header.
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=*&ACEHeaders=X-ServiceWorker-ServerHeader',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=*&ACEHeaders=X-ServiceWorker-ServerHeader',
    [fetchResolved, noContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsPOST]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=' + BASE_ORIGIN +
-   '&ACEHeaders=X-ServiceWorker-ServerHeader',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=' + BASE_ORIGIN + '&ACEHeaders=X-ServiceWorker-ServerHeader',
    [fetchResolved, noContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsPOST]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=*&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=*&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsPOST]],
-  [OTHER_BASE_URL + 'mode=cors&method=POST&ACAOrigin=' + BASE_ORIGIN +
+  [OTHER_BASE_URL + 'mode=cors&credentials=same-origin&method=POST' +
+   '&ACAOrigin=' + BASE_ORIGIN +
    '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsPOST]],
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect-loop.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect-loop.js
index 31bdae0..6b413a62d2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect-loop.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect-loop.js
@@ -5,42 +5,44 @@
 
 var TEST_TARGETS = [
   // Redirect loop: same origin -> same origin
-  [REDIRECT_LOOP_URL + encodeURIComponent(BASE_URL) + '&Count=20&mode=cors',
+  [REDIRECT_LOOP_URL + encodeURIComponent(BASE_URL) + '&Count=20&mode=cors' +
+   '&credentials=same-origin',
    [fetchResolved, hasContentLength, hasBody, typeBasic],
    [methodIsGET, authCheck1]],
-  [REDIRECT_LOOP_URL + encodeURIComponent(BASE_URL) + '&Count=21&mode=cors',
+  [REDIRECT_LOOP_URL + encodeURIComponent(BASE_URL) + '&Count=21&mode=cors' +
+   '&credentials=same-origin',
    [fetchRejected]],
 
   // Redirect loop: same origin -> other origin
   [REDIRECT_LOOP_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&Count=20&mode=cors&method=GET',
+   '&Count=20&mode=cors&credentials=same-origin&method=GET',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   // FIXME: due to the current implementation of Chromium,
   // Count=21 is resolved, Count=22 is rejected.
   // https://crbug.com/353768
   [REDIRECT_LOOP_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&Count=22&mode=cors&method=GET',
+   '&Count=22&mode=cors&credentials=same-origin&method=GET',
    [fetchRejected]],
 
   // Redirect loop: other origin -> same origin
   [OTHER_REDIRECT_LOOP_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&Count=20&mode=cors&method=GET&ACAOrigin=*',
+   '&Count=20&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   [OTHER_REDIRECT_LOOP_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&Count=21&mode=cors&method=GET&ACAOrigin=*',
+   '&Count=21&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchRejected]],
 
   // Redirect loop: other origin -> other origin
   [OTHER_REDIRECT_LOOP_URL +
    encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&Count=20&mode=cors&method=GET&ACAOrigin=*',
+   '&Count=20&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   [OTHER_REDIRECT_LOOP_URL +
    encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&Count=21&mode=cors&method=GET&ACAOrigin=*',
+   '&Count=21&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchRejected]],
 ];
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect.js b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect.js
index f34a736a..7f33e95b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect.js
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/script-tests/thorough/redirect.js
@@ -59,76 +59,77 @@
 
   // Do not redirect for other status even if Location header exists.
   [REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=same-origin&method=POST&Status=201&NoRedirectTest=true',
+   '&mode=same-origin&credentials=same-origin&method=POST&Status=201&' +
+   'NoRedirectTest=true',
    [fetchResolved, hasBody, typeBasic],
    [checkJsonpNoRedirect]],
 
   [REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=same-origin&method=PUT',
+   '&mode=same-origin&credentials=same-origin&method=PUT',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeBasic],
    [methodIsPUT, authCheck1]],
 
   [REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=cors&method=GET&headers=CUSTOM',
+   '&mode=cors&credentials=same-origin&method=GET&headers=CUSTOM',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeBasic],
    [methodIsGET, hasCustomHeader, authCheck1]],
 
   // Redirect: same origin -> other origin
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=same-origin&method=GET',
+   '&mode=same-origin&credentials=same-origin&method=GET',
    [fetchRejected]],
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=same-origin&method=POST',
+   '&mode=same-origin&credentials=same-origin&method=POST',
    [fetchRejected]],
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=same-origin&method=PUT',
+   '&mode=same-origin&credentials=same-origin&method=PUT',
    [fetchRejected]],
 
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=cors&method=GET',
+   '&mode=cors&credentials=same-origin&method=GET',
    [fetchRejected]],
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=cors&method=PUT',
+   '&mode=cors&credentials=same-origin&method=PUT',
    [fetchRejected]],
 
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&mode=cors&method=GET',
+   '&mode=cors&credentials=same-origin&method=GET',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&mode=cors&method=PUT',
+   '&mode=cors&credentials=same-origin&method=PUT',
    [fetchRejected]],
   [REDIRECT_URL +
    encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*&ACAMethods=PUT') +
-   '&mode=cors&method=PUT',
+   '&mode=cors&credentials=same-origin&method=PUT',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsPUT, noCustomHeader, authCheckNone]],
 
   // Status code tests for mode="cors"
   // The 301 redirect response MAY change the request method from POST to GET.
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&mode=cors&method=POST&Status=301',
+   '&mode=cors&credentials=same-origin&method=POST&Status=301',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // The 302 redirect response MAY change the request method from POST to GET.
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&mode=cors&method=POST&Status=302',
+   '&mode=cors&credentials=same-origin&method=POST&Status=302',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // GET method must be used for 303 redirect.
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&mode=cors&method=POST&Status=303',
+   '&mode=cors&credentials=same-origin&method=POST&Status=303',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // The 307 redirect response MUST NOT change the method.
   [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-   '&mode=cors&method=POST&Status=307',
+   '&mode=cors&credentials=same-origin&method=POST&Status=307',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsPOST]],
   // The 308 redirect response MUST NOT change the method.
   // FIXME: disabled due to https://crbug.com/451938
   // [REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + '&ACAOrigin=*') +
-  //  '&mode=cors&method=POST&Status=308',
+  //  '&mode=cors&credentials=same-origin&method=POST&Status=308',
   //  [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
   //  [methodIsPOST]],
 
@@ -138,54 +139,54 @@
      OTHER_BASE_URL +
      '&ACAOrigin=' + BASE_ORIGIN +
      '&ACEHeaders=Content-Length, X-ServiceWorker-ServerHeader') +
-   '&mode=cors&method=GET',
+   '&mode=cors&credentials=same-origin&method=GET',
    [fetchResolved, hasContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
 
   // Redirect: other origin -> same origin
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=same-origin&method=GET',
+   '&mode=same-origin&credentials=same-origin&method=GET',
    [fetchRejected]],
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=same-origin&method=POST',
+   '&mode=same-origin&credentials=same-origin&method=POST',
    [fetchRejected]],
 
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=cors&method=GET',
+   '&mode=cors&credentials=same-origin&method=GET',
    [fetchRejected]],
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL) +
-   '&mode=cors&method=GET&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchRejected]],
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=GET&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
 
   // Status code tests for mode="cors"
   // The 301 redirect response MAY change the request method from POST to GET.
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=post&ACAOrigin=*&Status=301',
+   '&mode=cors&credentials=same-origin&method=post&ACAOrigin=*&Status=301',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // The 302 redirect response MAY change the request method from POST to GET.
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=post&ACAOrigin=*&Status=302',
+   '&mode=cors&credentials=same-origin&method=post&ACAOrigin=*&Status=302',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // GET method must be used for 303 redirect.
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=post&ACAOrigin=*&Status=303',
+   '&mode=cors&credentials=same-origin&method=post&ACAOrigin=*&Status=303',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // The 307 redirect response MUST NOT change the method.
   [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=post&ACAOrigin=*&Status=307',
+   '&mode=cors&credentials=same-origin&method=post&ACAOrigin=*&Status=307',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsPOST]],
   // The 308 redirect response MUST NOT change the method.
   // FIXME: disabled due to https://crbug.com/451938
   // [OTHER_REDIRECT_URL + encodeURIComponent(BASE_URL + 'ACAOrigin=*') +
-  //  '&mode=cors&method=post&ACAOrigin=*&Status=308',
+  //  '&mode=cors&credentials=same-origin&method=post&ACAOrigin=*&Status=308',
   //  [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
   //  [methodIsPOST]],
 
@@ -194,14 +195,14 @@
   // Custom method
   [OTHER_REDIRECT_URL +
    encodeURIComponent(BASE_URL + 'ACAOrigin=*&ACAMethods=PUT') +
-   '&mode=cors&method=PUT&ACAOrigin=*&ACAMethods=PUT',
+   '&mode=cors&credentials=same-origin&method=PUT&ACAOrigin=*&ACAMethods=PUT',
    [fetchRejected]],
   // Custom header
   [OTHER_REDIRECT_URL +
    encodeURIComponent(
        BASE_URL +
        'ACAOrigin=' + BASE_ORIGIN + '&ACAHeaders=x-serviceworker-test') +
-   '&mode=cors&method=GET&headers=CUSTOM&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&headers=CUSTOM&ACAOrigin=*',
    [fetchRejected]],
 
   // Redirect: other origin -> other origin
@@ -209,55 +210,57 @@
    '&mode=same-origin&method=GET',
    [fetchRejected]],
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=cors&method=GET',
+   '&mode=cors&credentials=same-origin&method=GET',
    [fetchRejected]],
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL) +
-   '&mode=cors&method=GET&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchRejected]],
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=GET&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   [OTHER_REDIRECT_URL +
    encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + '') +
-   '&mode=cors&method=GET&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=GET&ACAOrigin=' + BASE_ORIGIN + '',
+   '&mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=' + BASE_ORIGIN + '',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
   [OTHER_REDIRECT_URL +
    encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + '') +
-   '&mode=cors&method=GET&ACAOrigin=' + BASE_ORIGIN + '',
+   '&mode=cors&credentials=same-origin&method=GET' +
+   '&ACAOrigin=' + BASE_ORIGIN + '',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
 
   // Status code tests for mode="cors"
   // The 301 redirect response MAY change the request method from POST to GET.
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=POST&ACAOrigin=*&Status=301',
+   '&mode=cors&credentials=same-origin&method=POST&ACAOrigin=*&Status=301',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // The 302 redirect response MAY change the request method from POST to GET.
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=POST&ACAOrigin=*&Status=302',
+   '&mode=cors&credentials=same-origin&method=POST&ACAOrigin=*&Status=302',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // GET method must be used for 303 redirect.
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=POST&ACAOrigin=*&Status=303',
+   '&mode=cors&credentials=same-origin&method=POST&ACAOrigin=*&Status=303',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsGET]],
   // The 307 redirect response MUST NOT change the method.
   [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-   '&mode=cors&method=POST&ACAOrigin=*&Status=307',
+   '&mode=cors&credentials=same-origin&method=POST&ACAOrigin=*&Status=307',
    [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
    [methodIsPOST]],
   // The 308 redirect response MUST NOT change the method.
   // FIXME: disabled due to https://crbug.com/451938
   // [OTHER_REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*') +
-  //  '&mode=cors&method=POST&ACAOrigin=*&Status=308',
+  //  '&mode=cors&credentials=same-origin&method=POST&ACAOrigin=*&Status=308',
   //  [fetchResolved, noContentLength, noServerHeader, hasBody, typeCors],
   //  [methodIsPOST]],
 
@@ -265,7 +268,7 @@
   [OTHER_REDIRECT_URL +
    encodeURIComponent(OTHER_BASE_URL +
                       'ACAOrigin=*&ACEHeaders=X-ServiceWorker-ServerHeader') +
-   '&mode=cors&method=GET&ACAOrigin=*',
+   '&mode=cors&credentials=same-origin&method=GET&ACAOrigin=*',
    [fetchResolved, noContentLength, hasServerHeader, hasBody, typeCors],
    [methodIsGET, authCheckNone]],
 
@@ -274,14 +277,14 @@
   // Custom method
   [OTHER_REDIRECT_URL +
    encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*&ACAMethods=PUT') +
-   '&mode=cors&method=PUT&ACAOrigin=*&ACAMethods=PUT',
+   '&mode=cors&credentials=same-origin&method=PUT&ACAOrigin=*&ACAMethods=PUT',
    [fetchRejected]],
   // Custom header
   [OTHER_REDIRECT_URL +
    encodeURIComponent(
      OTHER_BASE_URL +
      'ACAOrigin=' + BASE_ORIGIN + '&ACAHeaders=x-serviceworker-test') +
-   '&mode=cors&method=GET&headers=CUSTOM' +
+   '&mode=cors&credentials=same-origin&method=GET&headers=CUSTOM' +
    '&ACAOrigin=' + BASE_ORIGIN + '&ACAHeaders=x-serviceworker-test',
    [fetchRejected]],
 ];
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/fetch-request-resources.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/fetch-request-resources.html
index 3ee299c..7b7947a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/fetch-request-resources.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/fetch-request-resources.html
@@ -12,7 +12,6 @@
                     expected_mode, expected_credentials) {
   var actual_url = url + (++url_count);
   expected_results[actual_url] = {
-      cross_origin: cross_origin,
       mode: expected_mode,
       credentials: expected_credentials,
       redirect: 'follow',
@@ -26,7 +25,6 @@
                      expected_mode, expected_credentials) {
   var actual_url = url + (++url_count);
   expected_results[actual_url] = {
-      cross_origin: cross_origin,
       mode: expected_mode,
       credentials: expected_credentials,
       redirect: 'follow',
@@ -40,7 +38,6 @@
                   expected_mode, expected_credentials) {
   var actual_url = url + (++url_count);
   expected_results[actual_url] = {
-      cross_origin: cross_origin,
       mode: expected_mode,
       credentials: expected_credentials,
       redirect: 'follow',
@@ -89,6 +86,33 @@
   return frame.contentWindow.load_css_image_set(actual_url, type);
 }
 
+function fetch_test(frame, url, mode, credentials,
+                    expected_mode, expected_credentials) {
+  var actual_url = url + (++url_count);
+  expected_results[actual_url] = {
+      mode: expected_mode,
+      credentials: expected_credentials,
+      redirect: 'follow',
+      message: 'fetch (url:' + actual_url + ' mode:' + mode + ' credentials:' +
+               credentials + ')'
+    };
+  return frame.contentWindow.fetch(
+      new Request(actual_url, {mode: mode, credentials: credentials}));
+}
+
+function audio_test(frame, url, cross_origin,
+                    expected_mode, expected_credentials) {
+  var actual_url = url + (++url_count);
+  expected_results[actual_url] = {
+      mode: expected_mode,
+      credentials: expected_credentials,
+      redirect: 'follow',
+      message: 'Audio load (url:' + actual_url + ' cross_origin:' +
+               cross_origin + ')'
+    };
+  return frame.contentWindow.load_audio(actual_url, cross_origin);
+}
+
 async_test(function(t) {
     var SCOPE = 'resources/fetch-request-resources-iframe.html';
     var SCRIPT = 'resources/fetch-request-resources-worker.js';
@@ -143,45 +167,69 @@
       .then(function() { return with_iframe(SCOPE); })
       .then(function(f) {
         frame = f;
-        image_test(f, LOCAL_URL, '', 'no-cors', 'same-origin');
+        image_test(f, LOCAL_URL, '', 'no-cors', 'include');
         image_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
         image_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
-        image_test(f, REMOTE_URL, '', 'no-cors', 'same-origin');
+        image_test(f, REMOTE_URL, '', 'no-cors', 'include');
         image_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
         image_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
 
-        script_test(f, LOCAL_URL, '', 'no-cors', 'same-origin');
+        script_test(f, LOCAL_URL, '', 'no-cors', 'include');
         script_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
         script_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
-        script_test(f, REMOTE_URL, '', 'no-cors', 'same-origin');
+        script_test(f, REMOTE_URL, '', 'no-cors', 'include');
         script_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
         script_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
 
-        css_test(f, LOCAL_URL, '', 'no-cors', 'same-origin');
+        css_test(f, LOCAL_URL, '', 'no-cors', 'include');
         css_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
         css_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
-        css_test(f, REMOTE_URL, '', 'no-cors', 'same-origin');
+        css_test(f, REMOTE_URL, '', 'no-cors', 'include');
         css_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
         css_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
 
         font_face_test(f, LOCAL_URL, 'cors', 'same-origin');
         font_face_test(f, REMOTE_URL, 'cors', 'same-origin');
 
-        css_image_test(f, LOCAL_URL, 'backgroundImage',
-                       'no-cors', 'same-origin');
-        css_image_test(f, REMOTE_URL, 'backgroundImage',
-                       'no-cors', 'same-origin');
+        css_image_test(f, LOCAL_URL, 'backgroundImage', 'no-cors', 'include');
+        css_image_test(f, REMOTE_URL, 'backgroundImage', 'no-cors', 'include');
         css_image_test(f, LOCAL_URL, 'shapeOutside', 'cors', 'same-origin');
         css_image_test(f, REMOTE_URL, 'shapeOutside', 'cors', 'same-origin');
 
         css_image_set_test(f, LOCAL_URL, 'backgroundImage',
-                           'no-cors', 'same-origin');
+                           'no-cors', 'include');
         css_image_set_test(f, REMOTE_URL, 'backgroundImage',
-                           'no-cors', 'same-origin');
+                           'no-cors', 'include');
         css_image_set_test(f, LOCAL_URL, 'shapeOutside', 'cors', 'same-origin');
         css_image_set_test(f, REMOTE_URL, 'shapeOutside',
                            'cors', 'same-origin');
 
+        fetch_test(f, LOCAL_URL, 'same-origin', 'omit', 'same-origin', 'omit');
+        fetch_test(f, LOCAL_URL, 'same-origin', 'same-origin',
+                   'same-origin', 'same-origin');
+        fetch_test(f, LOCAL_URL, 'same-origin', 'include',
+                   'same-origin', 'include');
+        fetch_test(f, LOCAL_URL, 'no-cors', 'omit', 'no-cors', 'omit');
+        fetch_test(f, LOCAL_URL, 'no-cors', 'same-origin',
+                   'no-cors', 'same-origin');
+        fetch_test(f, LOCAL_URL, 'no-cors', 'include', 'no-cors', 'include');
+        fetch_test(f, LOCAL_URL, 'cors', 'omit', 'cors', 'omit');
+        fetch_test(f, LOCAL_URL, 'cors', 'same-origin', 'cors', 'same-origin');
+        fetch_test(f, LOCAL_URL, 'cors', 'include', 'cors', 'include');
+        fetch_test(f, REMOTE_URL, 'no-cors', 'omit', 'no-cors', 'omit');
+        fetch_test(f, REMOTE_URL, 'no-cors', 'same-origin',
+                   'no-cors', 'same-origin');
+        fetch_test(f, REMOTE_URL, 'no-cors', 'include', 'no-cors', 'include');
+        fetch_test(f, REMOTE_URL, 'cors', 'omit', 'cors', 'omit');
+        fetch_test(f, REMOTE_URL, 'cors', 'same-origin', 'cors', 'same-origin');
+        fetch_test(f, REMOTE_URL, 'cors', 'include', 'cors', 'include');
+
+        audio_test(f, LOCAL_URL, '', 'no-cors', 'include');
+        audio_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
+        audio_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
+        audio_test(f, REMOTE_URL, '', 'no-cors', 'include');
+        audio_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
+        audio_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
       })
       .catch(unreached_rejection(t));
   }, 'Verify FetchEvent for resources.');
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-resources-iframe.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-resources-iframe.html
index 00c58386d..f13129c5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-resources-iframe.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-resources-iframe.html
@@ -48,5 +48,13 @@
   div.style[type] = '-webkit-image-set(url(' + url + ') 1x)';
 }
 
+function load_audio(url, cross_origin) {
+  var audio = document.createElement('audio');
+  if (cross_origin != '') {
+    audio.crossOrigin = cross_origin;
+  }
+  audio.src = url;
+  document.body.appendChild(audio);
+}
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-xhr-iframe.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-xhr-iframe.html
index c16cc5dc..b485ee2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-xhr-iframe.html
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/fetch-request-xhr-iframe.html
@@ -133,7 +133,7 @@
   return xhr_send(host_info['HTTP_ORIGIN'], 'GET', '', false)
     .then(function(response){
         assert_equals(response.mode, 'cors');
-        assert_equals(response.credentials, 'same-origin');
+        assert_equals(response.credentials, 'include');
         return xhr_send(host_info['HTTP_ORIGIN'], 'GET', '', true);
       })
     .then(function(response){
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
index 9a1e604..b3e921af 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -32,7 +32,7 @@
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8RecursionScope.h"
 #include "bindings/core/v8/V8ScriptRunner.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 #include "core/inspector/MainThreadDebugger.h"
 #include "public/platform/Platform.h"
 #include "wtf/LeakAnnotations.h"
@@ -114,7 +114,7 @@
         return;
     }
     if (deprecated)
-        UseCounter::countDeprecation(currentExecutionContext(isolate), blinkFeature);
+        Deprecation::countDeprecation(currentExecutionContext(isolate), blinkFeature);
     else
         UseCounter::count(currentExecutionContext(isolate), blinkFeature);
 }
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
index 5312a76..2987967d 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
@@ -94,6 +94,9 @@
     if cached_attribute_validation_method or keep_alive_for_gc:
         includes.add('bindings/core/v8/V8HiddenValue.h')
 
+    if 'RuntimeEnabled' in extended_attributes:
+        includes.add('platform/RuntimeEnabledFeatures.h')
+
     if 'OriginTrialEnabled' in extended_attributes:
         includes.add('core/inspector/ConsoleMessage.h')
         includes.add('core/origin_trials/OriginTrials.h')
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
index 6565fc7b..f003601 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -63,10 +63,7 @@
     'bindings/core/v8/ExceptionState.h',
     'bindings/core/v8/V8DOMConfiguration.h',
     'bindings/core/v8/V8ObjectConstructor.h',
-    'core/dom/ContextFeatures.h',
     'core/dom/Document.h',
-    'platform/RuntimeEnabledFeatures.h',
-    'platform/TraceEvent.h',
     'wtf/GetPtr.h',
     'wtf/RefPtr.h',
 ])
@@ -162,6 +159,9 @@
     cpp_class_name_or_partial = cpp_name_or_partial(interface)
     v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface)
 
+    if 'RuntimeEnabled' in extended_attributes:
+        includes.add('platform/RuntimeEnabledFeatures.h')
+
     if 'OriginTrialEnabled' in extended_attributes:
         includes.add('core/inspector/ConsoleMessage.h')
         includes.add('core/origin_trials/OriginTrials.h')
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_methods.py b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
index ea6486c..a3d4232 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_methods.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_methods.py
@@ -118,6 +118,9 @@
     if 'LenientThis' in extended_attributes:
         raise Exception('[LenientThis] is not supported for operations.')
 
+    if 'RuntimeEnabled' in extended_attributes:
+        includes.add('platform/RuntimeEnabledFeatures.h')
+
     if 'OriginTrialEnabled' in extended_attributes:
         includes.add('core/inspector/ConsoleMessage.h')
         includes.add('core/origin_trials/OriginTrials.h')
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
index 7ec15f2e..88580d90 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
@@ -223,7 +223,7 @@
     extended_attributes = member.extended_attributes
     if 'DeprecateAs' not in extended_attributes:
         return None
-    includes.add('core/frame/UseCounter.h')
+    includes.add('core/frame/Deprecation.h')
     return extended_attributes['DeprecateAs']
 
 
diff --git a/third_party/WebKit/Source/bindings/templates/attributes.cpp b/third_party/WebKit/Source/bindings/templates/attributes.cpp
index 2cce9c177..68b988c 100644
--- a/third_party/WebKit/Source/bindings/templates/attributes.cpp
+++ b/third_party/WebKit/Source/bindings/templates/attributes.cpp
@@ -171,7 +171,7 @@
 {%- endif %})
 {
     {% if attribute.deprecate_as %}
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
     {% endif %}
     {% if attribute.measure_as %}
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as('AttributeGetter')}});
@@ -203,7 +203,7 @@
 static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info)
 {
     {% if attribute.deprecate_as %}
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
     {% endif %}
     {% if attribute.measure_as %}
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as('ConstructorGetter')}});
@@ -362,7 +362,7 @@
     v8::Local<v8::Value> v8Value = info[0];
     {% endif %}
     {% if attribute.deprecate_as %}
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
     {% endif %}
     {% if attribute.measure_as %}
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as('AttributeSetter')}});
diff --git a/third_party/WebKit/Source/bindings/templates/constants.cpp b/third_party/WebKit/Source/bindings/templates/constants.cpp
index 2ed818f..a0020c6be 100644
--- a/third_party/WebKit/Source/bindings/templates/constants.cpp
+++ b/third_party/WebKit/Source/bindings/templates/constants.cpp
@@ -5,7 +5,7 @@
 static void {{constant.name}}ConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info)
 {
     {% if constant.deprecate_as %}
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{constant.deprecate_as}});
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{constant.deprecate_as}});
     {% endif %}
     {% if constant.measure_as %}
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{constant.measure_as('ConstantGetter')}});
diff --git a/third_party/WebKit/Source/bindings/templates/dictionary_v8.cpp b/third_party/WebKit/Source/bindings/templates/dictionary_v8.cpp
index 459bec61..3a0d8274 100644
--- a/third_party/WebKit/Source/bindings/templates/dictionary_v8.cpp
+++ b/third_party/WebKit/Source/bindings/templates/dictionary_v8.cpp
@@ -66,7 +66,7 @@
         {% endif %}
         } else {
             {% if member.deprecate_as %}
-            UseCounter::countDeprecationIfNotPrivateScript(isolate, currentExecutionContext(isolate), UseCounter::{{member.deprecate_as}});
+            Deprecation::countDeprecationIfNotPrivateScript(isolate, currentExecutionContext(isolate), UseCounter::{{member.deprecate_as}});
             {% endif %}
             {{v8_value_to_local_cpp_value(member) | indent(12)}}
             {% if member.is_interface_type %}
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp b/third_party/WebKit/Source/bindings/templates/methods.cpp
index 584d770..e59be03 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp
@@ -400,7 +400,7 @@
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{overloads.measure_all_as}});
     {% endif %}
     {% if overloads.deprecate_all_as %}
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{overloads.deprecate_all_as}});
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{overloads.deprecate_all_as}});
     {% endif %}
     {# First resolve by length #}
     {# 2. Initialize argcount to be min(maxarg, n). #}
@@ -419,7 +419,7 @@
             UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as('Method')}});
             {% endif %}
             {% if method.deprecate_as and not overloads.deprecate_all_as %}
-            UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
+            Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
             {% endif %}
             {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
             return;
@@ -504,7 +504,7 @@
     UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as('Method')}});
     {% endif %}
     {% if method.deprecate_as %}
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
     {% endif %}
     {% if method.is_origin_trial_enabled %}
     {{check_origin_trial(method) | indent}}
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
index ad1d619..7a5b3d6c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.cpp
@@ -11,10 +11,7 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8SharedArrayBuffer.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
index 8416289..395989c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.cpp
@@ -22,10 +22,7 @@
 #include "bindings/core/v8/V8Uint32Array.h"
 #include "bindings/core/v8/V8Uint8Array.h"
 #include "bindings/core/v8/V8Uint8ClampedArray.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
index 1fb4a91..4dad8a53 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.cpp
@@ -11,10 +11,7 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8SharedArrayBuffer.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
index 56afd4c..3655d18 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
@@ -10,11 +10,8 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "core/SVGNames.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/dom/custom/CustomElementProcessingStack.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
index 6f5cc7f4..99c61ae 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestDictionary.cpp
@@ -20,7 +20,7 @@
 #include "bindings/core/v8/V8TestInterfaceWillBeGarbageCollected.h"
 #include "bindings/core/v8/V8Uint8Array.h"
 #include "core/dom/FlexibleArrayBufferView.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 
 namespace blink {
 
@@ -95,7 +95,7 @@
         if (deprecatedCreateMemberValue.IsEmpty() || deprecatedCreateMemberValue->IsUndefined()) {
             // Do nothing.
         } else {
-            UseCounter::countDeprecationIfNotPrivateScript(isolate, currentExecutionContext(isolate), UseCounter::CreateMember);
+            Deprecation::countDeprecationIfNotPrivateScript(isolate, currentExecutionContext(isolate), UseCounter::CreateMember);
             bool deprecatedCreateMember = toBoolean(isolate, deprecatedCreateMemberValue, exceptionState);
             if (exceptionState.hadException())
                 return;
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp
index e491557..137b2451 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
index d0a12d0..de8714b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
@@ -11,10 +11,7 @@
 #include "bindings/core/v8/V8Document.h"
 #include "bindings/core/v8/V8Node.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
index 072d0f3b..9785e31 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
@@ -11,10 +11,7 @@
 #include "bindings/core/v8/V8Document.h"
 #include "bindings/core/v8/V8Node.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
index fbe76861..c6544bc9 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
@@ -11,10 +11,7 @@
 #include "bindings/core/v8/V8Document.h"
 #include "bindings/core/v8/V8Node.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index a210e1a..1c98240 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -27,7 +27,6 @@
 #include "bindings/tests/idls/core/TestImplements3Implementation.h"
 #include "bindings/tests/idls/core/TestPartialInterface.h"
 #include "bindings/tests/idls/core/TestPartialInterfaceImplementation.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/UseCounter.h"
@@ -35,7 +34,6 @@
 #include "core/origin_trials/OriginTrials.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/ScriptForbiddenScope.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
index dd15d9c6..7b7c596 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -14,12 +14,9 @@
 #include "bindings/core/v8/V8Iterator.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
index c3b889e6..28a2d8e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -14,10 +14,8 @@
 #include "bindings/core/v8/V8Iterator.h"
 #include "bindings/core/v8/V8Node.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
index 0c24619..745fc95 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
@@ -10,10 +10,7 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
index ecdf110..6b0df0c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -13,12 +13,9 @@
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestDictionary.h"
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/UseCounter.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
index d1d6260..9c8dec4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
@@ -11,11 +11,8 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
index 47b1d67..10ec66a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
index 2523108e..83353aa 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
@@ -10,11 +10,8 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceConstructor4.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
index 8117563..5173a81 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
index 83be05e..a303cea 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
@@ -12,13 +12,10 @@
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "core/animation/DocumentAnimation.h"
 #include "core/css/DocumentFontFaceSet.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/dom/DocumentFullscreen.h"
 #include "core/svg/SVGDocumentExtensions.h"
 #include "core/xml/DocumentXPathEvaluator.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
index ce34377..d9b66ba7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
@@ -9,10 +9,7 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
index 80a80b1..b3f2af97 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
@@ -10,11 +10,9 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceEventInit.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
index 603fc98..70a2cfce 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
index a2f23fe..7ff47a7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
@@ -13,11 +13,8 @@
 #include "bindings/core/v8/V8Iterator.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceGarbageCollected.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
index 865074dd..c1b2103 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
index 266618f..f91fa7e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
index 99538e4..a2335d7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
@@ -13,11 +13,8 @@
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
 #include "core/HTMLNames.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/dom/custom/CustomElementProcessingStack.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceWillBeGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceWillBeGarbageCollected.cpp
index ea891f6..2dd0572af 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceWillBeGarbageCollected.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceWillBeGarbageCollected.cpp
@@ -10,11 +10,8 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceWillBeGarbageCollected.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
index d1ab744e..92a966c6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
@@ -9,11 +9,8 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index 856f721..0d7656e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -53,13 +53,13 @@
 #include "bindings/core/v8/V8XPathNSResolver.h"
 #include "core/HTMLNames.h"
 #include "core/dom/ClassCollection.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/DOMArrayBuffer.h"
 #include "core/dom/Document.h"
 #include "core/dom/FlexibleArrayBufferView.h"
 #include "core/dom/MessagePort.h"
 #include "core/dom/TagCollection.h"
 #include "core/dom/custom/CustomElementProcessingStack.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/ImageBitmap.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/UseCounter.h"
@@ -72,7 +72,6 @@
 #include "core/origin_trials/OriginTrials.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/ScriptForbiddenScope.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
@@ -98,7 +97,7 @@
 
 static void DEPRECATED_CONSTANTConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info)
 {
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::Constant);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::Constant);
     v8SetReturnValueInt(info, 1);
 }
 
@@ -2381,7 +2380,7 @@
 
 static void testInterfaceEmptyConstructorAttributeAttributeSetterCallback(v8::Local<v8::Name>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info)
 {
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::deprecatedTestInterfaceEmptyConstructorAttribute);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::deprecatedTestInterfaceEmptyConstructorAttribute);
     TestObjectV8Internal::testInterfaceEmptyConstructorAttributeAttributeSetter(v8Value, info);
 }
 
@@ -2474,7 +2473,7 @@
 
 static void deprecatedLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::LongAttribute);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::LongAttribute);
     TestObjectV8Internal::deprecatedLongAttributeAttributeGetter(info);
 }
 
@@ -2492,7 +2491,7 @@
 static void deprecatedLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     v8::Local<v8::Value> v8Value = info[0];
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::LongAttribute);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::LongAttribute);
     TestObjectV8Internal::deprecatedLongAttributeAttributeSetter(v8Value, info);
 }
 
@@ -5221,7 +5220,7 @@
 
 static void testInterfaceEmptyConstructorAttributeConstructorGetterCallback(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info)
 {
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::deprecatedTestInterfaceEmptyConstructorAttribute);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::deprecatedTestInterfaceEmptyConstructorAttribute);
     v8ConstructorAttributeGetter(property, info);
 }
 
@@ -9668,7 +9667,7 @@
 
 static void deprecatedVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::voidMethod);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::voidMethod);
     TestObjectV8Internal::deprecatedVoidMethodMethod(info);
 }
 
@@ -10025,14 +10024,14 @@
     switch (std::min(1, info.Length())) {
     case 0:
         if (true) {
-            UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureA);
+            Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureA);
             DeprecateAsOverloadedMethod1Method(info);
             return;
         }
         break;
     case 1:
         if (true) {
-            UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureB);
+            Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureB);
             DeprecateAsOverloadedMethod2Method(info);
             return;
         }
@@ -10072,7 +10071,7 @@
 static void DeprecateAsSameValueOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "DeprecateAsSameValueOverloadedMethod", "TestObject", info.Holder(), info.GetIsolate());
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
     switch (std::min(1, info.Length())) {
     case 0:
         if (true) {
@@ -10225,7 +10224,7 @@
     case 0:
         if (true) {
             UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
-            UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureA);
+            Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureA);
             deprecateAsMeasureAsSameValueOverloadedMethod1Method(info);
             return;
         }
@@ -10233,7 +10232,7 @@
     case 1:
         if (true) {
             UseCounter::countIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
-            UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureB);
+            Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureB);
             deprecateAsMeasureAsSameValueOverloadedMethod2Method(info);
             return;
         }
@@ -10273,7 +10272,7 @@
 static void deprecateAsSameValueMeasureAsOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "deprecateAsSameValueMeasureAsOverloadedMethod", "TestObject", info.Holder(), info.GetIsolate());
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeature);
     switch (std::min(1, info.Length())) {
     case 0:
         if (true) {
@@ -10324,7 +10323,7 @@
 static void deprecateAsSameValueMeasureAsSameValueOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
     ExceptionState exceptionState(ExceptionState::ExecutionContext, "deprecateAsSameValueMeasureAsSameValueOverloadedMethod", "TestObject", info.Holder(), info.GetIsolate());
-    UseCounter::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureA);
+    Deprecation::countDeprecationIfNotPrivateScript(info.GetIsolate(), currentExecutionContext(info.GetIsolate()), UseCounter::TestFeatureA);
     switch (std::min(1, info.Length())) {
     case 0:
         if (true) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
index 78ca243d..ed732e562 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
@@ -12,14 +12,11 @@
 #include "bindings/core/v8/V8Node.h"
 #include "bindings/core/v8/V8NodeList.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/dom/NameNodeList.h"
 #include "core/dom/NodeList.h"
 #include "core/dom/StaticNodeList.h"
 #include "core/html/LabelsNodeList.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
index f08e79e..2d08668a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
@@ -9,10 +9,7 @@
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
index 0dea0892..77f97fa 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
@@ -13,11 +13,8 @@
 #include "bindings/core/v8/V8TestCallbackInterface.h"
 #include "bindings/core/v8/V8TestInterface.h"
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalDOMWindow.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
index 6fb4ec0..5a3427a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.cpp
@@ -11,10 +11,7 @@
 #include "bindings/core/v8/V8DOMConfiguration.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8SharedArrayBuffer.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
index ad3c2e84..8105f624 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
@@ -15,10 +15,8 @@
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
 #include "bindings/modules/v8/UnionTypesModules.h"
 #include "bindings/modules/v8/V8TestInterface5.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "platform/RuntimeEnabledFeatures.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
index 65e31cc..93b652e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
@@ -15,14 +15,12 @@
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterface.h"
 #include "bindings/tests/idls/modules/TestPartialInterfaceImplementation3.h"
-#include "core/dom/ContextFeatures.h"
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/origin_trials/OriginTrials.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/ScriptForbiddenScope.h"
-#include "platform/TraceEvent.h"
 #include "wtf/GetPtr.h"
 #include "wtf/RefPtr.h"
 
diff --git a/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.cpp.tmpl
index 03a6198f..bec4e08 100644
--- a/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.cpp.tmpl
@@ -34,4 +34,9 @@
 }
 {% endfor %}
 
+DEFINE_TRACE(InternalSettingsGenerated)
+{
+    visitor->trace(m_page);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl
index 9a02e16..b5fea91 100644
--- a/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/InternalSettingsGenerated.h.tmpl
@@ -25,10 +25,7 @@
     void set{{setting.name|upper_first}}({{setting.type|to_passing_type}} {{setting.name}});
     {% endfor %}
 
-    DEFINE_INLINE_VIRTUAL_TRACE()
-    {
-        visitor->trace(m_page);
-    }
+    DECLARE_VIRTUAL_TRACE();
 
 private:
     RawPtrWillBeMember<Page> m_page;
diff --git a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
index 2aba4cd..f0eb22e 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
+++ b/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp
@@ -34,7 +34,7 @@
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/Node.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 #include "core/html/HTMLStyleElement.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "core/svg/SVGStyleElement.h"
@@ -313,7 +313,7 @@
 
 unsigned CSSStyleSheet::insertRule(const String& rule, ExceptionState& exceptionState)
 {
-    UseCounter::countDeprecation(currentExecutionContext(V8PerIsolateData::mainThreadIsolate()), UseCounter::CSSStyleSheetInsertRuleOptionalArg);
+    Deprecation::countDeprecation(currentExecutionContext(V8PerIsolateData::mainThreadIsolate()), UseCounter::CSSStyleSheetInsertRuleOptionalArg);
     return insertRule(rule, 0, exceptionState);
 }
 
diff --git a/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp b/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp
index 8c70fee04..a94ee84 100644
--- a/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp
+++ b/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp
@@ -33,6 +33,7 @@
 #include "core/css/CSSPropertyMetadata.h"
 #include "core/css/StylePropertySet.h"
 #include "core/css/parser/CSSParser.h"
+#include "core/css/parser/CSSVariableParser.h"
 #include "wtf/text/StringBuilder.h"
 #include "wtf/text/WTFString.h"
 
@@ -41,8 +42,14 @@
 bool DOMWindowCSS::supports(const String& property, const String& value)
 {
     CSSPropertyID unresolvedProperty = unresolvedCSSPropertyID(property);
-    if (unresolvedProperty == CSSPropertyInvalid)
+    if (unresolvedProperty == CSSPropertyInvalid) {
+        if (RuntimeEnabledFeatures::cssVariablesEnabled() && CSSVariableParser::isValidVariableName(property)) {
+            RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create(HTMLStandardMode);
+            return CSSParser::parseValueForCustomProperty(dummyStyle.get(), "--valid", value, false, 0);
+        }
         return false;
+    }
+
     ASSERT(CSSPropertyMetadata::isEnabledProperty(unresolvedProperty));
 
     // This will return false when !important is present
diff --git a/third_party/WebKit/Source/core/css/SelectorChecker.cpp b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
index 2738219..b8aeae9 100644
--- a/third_party/WebKit/Source/core/css/SelectorChecker.cpp
+++ b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
@@ -346,7 +346,7 @@
     case CSSSelector::ShadowPseudo:
         {
             if (!m_isUARule && context.selector->pseudoType() == CSSSelector::PseudoShadow)
-                UseCounter::countDeprecation(context.element->document(), UseCounter::CSSSelectorPseudoShadow);
+                Deprecation::countDeprecation(context.element->document(), UseCounter::CSSSelectorPseudoShadow);
             // If we're in the same tree-scope as the scoping element, then following a shadow descendant combinator would escape that and thus the scope.
             if (context.scope && context.scope->shadowHost() && context.scope->shadowHost()->treeScope() == context.element->treeScope())
                 return SelectorFailsCompletely;
@@ -361,7 +361,7 @@
     case CSSSelector::ShadowDeep:
         {
             if (!m_isUARule)
-                UseCounter::countDeprecation(context.element->document(), UseCounter::CSSDeepCombinator);
+                Deprecation::countDeprecation(context.element->document(), UseCounter::CSSDeepCombinator);
             if (ShadowRoot* root = context.element->containingShadowRoot()) {
                 if (root->type() == ShadowRootType::UserAgent)
                     return SelectorFailsCompletely;
diff --git a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp
index 7e6f913..3a2a9e3 100644
--- a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp
+++ b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp
@@ -30,7 +30,7 @@
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/NodeTraversal.h"
 #include "core/dom/shadow/DistributedNodes.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 #include "core/html/HTMLContentElement.h"
 #include "core/html/HTMLShadowElement.h"
 #include "core/inspector/InspectorInstrumentation.h"
@@ -156,9 +156,9 @@
             shadowHost.willAddFirstAuthorShadowRoot();
         } else if (m_shadowRoots.head()->type() == ShadowRootType::UserAgent) {
             shadowHost.willAddFirstAuthorShadowRoot();
-            UseCounter::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultipleWithUserAgentShadowRoot);
+            Deprecation::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultipleWithUserAgentShadowRoot);
         } else {
-            UseCounter::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultiple);
+            Deprecation::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultiple);
         }
     } else if (type == ShadowRootType::Open || type == ShadowRootType::Closed) {
         shadowHost.willAddFirstAuthorShadowRoot();
diff --git a/third_party/WebKit/Source/core/dom/shadow/SlotAssignment.cpp b/third_party/WebKit/Source/core/dom/shadow/SlotAssignment.cpp
index 6ee8312c..16ad5ad 100644
--- a/third_party/WebKit/Source/core/dom/shadow/SlotAssignment.cpp
+++ b/third_party/WebKit/Source/core/dom/shadow/SlotAssignment.cpp
@@ -7,6 +7,7 @@
 #include "core/HTMLNames.h"
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/NodeTraversal.h"
+#include "core/dom/shadow/ElementShadow.h"
 #include "core/dom/shadow/InsertionPoint.h"
 #include "core/dom/shadow/ShadowRoot.h"
 #include "core/html/HTMLSlotElement.h"
@@ -86,6 +87,8 @@
         slot.appendDistributedNodesFrom(toHTMLSlotElement(hostChild));
     else
         slot.appendDistributedNode(hostChild);
+    if (slot.isChildOfV1ShadowHost())
+        slot.parentElementShadow()->setNeedsDistributionRecalc();
 }
 
 DEFINE_TRACE(SlotAssignment)
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index cd04d73..639f888 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -155,6 +155,23 @@
     EXPECT_EQ_SELECTED_TEXT("Baz");
 }
 
+TEST_F(FrameSelectionTest, ModifyExtendWithFlatTree)
+{
+    setBodyContent("<span id=host></span>one");
+    setShadowContent("two<content></content>", "host");
+    updateLayoutAndStyleForPainting();
+    RefPtrWillBeRawPtr<Element> host = document().getElementById("host");
+    Node* const two = FlatTreeTraversal::firstChild(*host);
+    // Select "two" for selection in DOM tree
+    // Select "twoone" for selection in Flat tree
+    selection().setSelection(VisibleSelectionInFlatTree(PositionInFlatTree(host.get(), 0), PositionInFlatTree(document().body(), 2)));
+    selection().modify(FrameSelection::AlterationExtend, DirectionForward, WordGranularity);
+    EXPECT_EQ(Position(two, 0), visibleSelectionInDOMTree().start());
+    EXPECT_EQ(Position(two, 3), visibleSelectionInDOMTree().end());
+    EXPECT_EQ(PositionInFlatTree(two, 0), visibleSelectionInFlatTree().start());
+    EXPECT_EQ(PositionInFlatTree(two, 3), visibleSelectionInFlatTree().end());
+}
+
 TEST_F(FrameSelectionTest, MoveRangeSelectionTest)
 {
     // "Foo Bar Baz,"
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
index 4660cdc1..ceb6aa9e 100644
--- a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
@@ -194,6 +194,7 @@
         m_selection.setBase(end);
         m_selection.setExtent(start);
     }
+    SelectionAdjuster::adjustSelectionInFlatTree(&m_selectionInFlatTree, m_selection);
 }
 
 VisiblePosition SelectionEditor::positionForPlatform(bool isGetStart) const
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.h b/third_party/WebKit/Source/core/editing/SelectionEditor.h
index 2a2dab49..bf3f70a 100644
--- a/third_party/WebKit/Source/core/editing/SelectionEditor.h
+++ b/third_party/WebKit/Source/core/editing/SelectionEditor.h
@@ -90,9 +90,6 @@
 
     LocalFrame* frame() const;
 
-    void adjustVisibleSelectionInFlatTree();
-    void adjustVisibleSelectionInDOMTree();
-
     TextDirection directionOfEnclosingBlock();
     TextDirection directionOfSelection();
 
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index 3720339..6ba2c19 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -209,7 +209,9 @@
         }
         // Apply any remaining styles to the inline elements.
         if (!m_style->isEmpty() || m_styledInlineElement || m_isInlineElementToRemoveFunction) {
-            applyRelativeFontStyleChange(m_style.get());
+            applyRelativeFontStyleChange(m_style.get(), editingState);
+            if (editingState->isAborted())
+                return;
             applyInlineStyle(m_style.get(), editingState);
             if (editingState->isAborted())
                 return;
@@ -275,7 +277,9 @@
                     block = newBlock;
             }
             if (block && block->isHTMLElement()) {
-                removeCSSStyle(style, toHTMLElement(block));
+                removeCSSStyle(style, toHTMLElement(block), editingState);
+                if (editingState->isAborted())
+                    return;
                 if (!m_removeOnly)
                     addBlockStyle(styleChange, toHTMLElement(block));
             }
@@ -304,7 +308,7 @@
     return style->mutableCopy();
 }
 
-void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style)
+void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style, EditingState* editingState)
 {
     static const float MinimumFontSize = 0.1f;
 
@@ -402,7 +406,9 @@
             // Last styled node was not parent node of this text node, but we wish to style this
             // text node. To make this possible, add a style span to surround this text node.
             RefPtrWillBeRawPtr<HTMLSpanElement> span = HTMLSpanElement::create(document());
-            surroundNodeRangeWithElement(node, node, span.get(), ASSERT_NO_EDITING_ABORT);
+            surroundNodeRangeWithElement(node, node, span.get(), editingState);
+            if (editingState->isAborted())
+                return;
             element = span.release();
         }  else {
             // Only handle HTML elements and text nodes.
@@ -429,8 +435,11 @@
         }
     }
 
-    for (const auto& unstyledSpan : unstyledSpans)
-        removeNodePreservingChildren(unstyledSpan.get());
+    for (const auto& unstyledSpan : unstyledSpans) {
+        removeNodePreservingChildren(unstyledSpan.get(), editingState);
+        if (editingState->isAborted())
+            return;
+    }
 }
 
 static ContainerNode* dummySpanAncestorForNode(const Node* node)
@@ -441,7 +450,7 @@
     return node ? node->parentNode() : 0;
 }
 
-void ApplyStyleCommand::cleanupUnstyledAppleStyleSpans(ContainerNode* dummySpanAncestor)
+void ApplyStyleCommand::cleanupUnstyledAppleStyleSpans(ContainerNode* dummySpanAncestor, EditingState* editingState)
 {
     if (!dummySpanAncestor)
         return;
@@ -453,8 +462,11 @@
     Node* next;
     for (Node* node = dummySpanAncestor->firstChild(); node; node = next) {
         next = node->nextSibling();
-        if (isSpanWithoutAttributesOrUnstyledStyleSpan(node))
-            removeNodePreservingChildren(node);
+        if (isSpanWithoutAttributesOrUnstyledStyleSpan(node)) {
+            removeNodePreservingChildren(node, editingState);
+            if (editingState->isAborted())
+                return;
+        }
     }
 }
 
@@ -509,7 +521,7 @@
     return unsplitAncestor;
 }
 
-void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, HTMLElement* unsplitAncestor)
+void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, HTMLElement* unsplitAncestor, EditingState* editingState)
 {
     Element* block = enclosingBlock(node);
     if (!block)
@@ -537,8 +549,11 @@
             inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal);
             inlineStyle->removeProperty(CSSPropertyDirection);
             setNodeAttribute(element, styleAttr, AtomicString(inlineStyle->asText()));
-            if (isSpanWithoutAttributesOrUnstyledStyleSpan(element))
-                removeNodePreservingChildren(element);
+            if (isSpanWithoutAttributesOrUnstyledStyleSpan(element)) {
+                removeNodePreservingChildren(element, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
         }
     }
 }
@@ -620,8 +635,12 @@
         // Leave alone an ancestor that provides the desired single level embedding, if there is one.
         HTMLElement* startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.anchorNode(), true, textDirection);
         HTMLElement* endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.anchorNode(), false, textDirection);
-        removeEmbeddingUpToEnclosingBlock(start.anchorNode(), startUnsplitAncestor);
-        removeEmbeddingUpToEnclosingBlock(end.anchorNode(), endUnsplitAncestor);
+        removeEmbeddingUpToEnclosingBlock(start.anchorNode(), startUnsplitAncestor, editingState);
+        if (editingState->isAborted())
+            return;
+        removeEmbeddingUpToEnclosingBlock(end.anchorNode(), endUnsplitAncestor, editingState);
+        if (editingState->isAborted())
+            return;
 
         // Avoid removing the dir attribute and the unicode-bidi and direction properties from the unsplit ancestors.
         Position embeddingRemoveStart = removeStart;
@@ -636,24 +655,36 @@
             styleWithoutEmbedding = style->copy();
             embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDirection();
 
-            if (comparePositions(embeddingRemoveStart, embeddingRemoveEnd) <= 0)
-                removeInlineStyle(embeddingStyle.get(), embeddingRemoveStart, embeddingRemoveEnd);
+            if (comparePositions(embeddingRemoveStart, embeddingRemoveEnd) <= 0) {
+                removeInlineStyle(embeddingStyle.get(), embeddingRemoveStart, embeddingRemoveEnd, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
         }
     }
 
-    removeInlineStyle(styleWithoutEmbedding ? styleWithoutEmbedding.get() : style, removeStart, end);
+    removeInlineStyle(styleWithoutEmbedding ? styleWithoutEmbedding.get() : style, removeStart, end, editingState);
+    if (editingState->isAborted())
+        return;
     start = startPosition();
     end = endPosition();
     if (start.isNull() || start.isOrphan() || end.isNull() || end.isOrphan())
         return;
 
-    if (splitStart && mergeStartWithPreviousIfIdentical(start, end)) {
-        start = startPosition();
-        end = endPosition();
+    if (splitStart) {
+        bool mergeResult = mergeStartWithPreviousIfIdentical(start, end, editingState);
+        if (editingState->isAborted())
+            return;
+        if (splitStart && mergeResult) {
+            start = startPosition();
+            end = endPosition();
+        }
     }
 
     if (splitEnd) {
-        mergeEndWithNextIfIdentical(start, end);
+        mergeEndWithNextIfIdentical(start, end, editingState);
+        if (editingState->isAborted())
+            return;
         start = startPosition();
         end = endPosition();
     }
@@ -691,9 +722,11 @@
         return;
 
     // Remove dummy style spans created by splitting text elements.
-    cleanupUnstyledAppleStyleSpans(startDummySpanAncestor.get());
+    cleanupUnstyledAppleStyleSpans(startDummySpanAncestor.get(), editingState);
+    if (editingState->isAborted())
+        return;
     if (endDummySpanAncestor != startDummySpanAncestor)
-        cleanupUnstyledAppleStyleSpans(endDummySpanAncestor.get());
+        cleanupUnstyledAppleStyleSpans(endDummySpanAncestor.get(), editingState);
 }
 
 void ApplyStyleCommand::fixRangeAndApplyInlineStyle(EditingStyle* style, const Position& start, const Position& end, EditingState* editingState)
@@ -846,7 +879,9 @@
     }
 
     for (auto& run : runs) {
-        removeConflictingInlineStyleFromRun(style, run.start, run.end, run.pastEndNode);
+        removeConflictingInlineStyleFromRun(style, run.start, run.end, run.pastEndNode, editingState);
+        if (editingState->isAborted())
+            return;
         if (run.startAndEndAreStillInDocument())
             run.positionForStyleComputation = positionToComputeInlineStyleChange(run.start, run.dummyElement);
     }
@@ -894,7 +929,7 @@
     return false;
 }
 
-void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, RefPtrWillBeMember<Node>& runStart, RefPtrWillBeMember<Node>& runEnd, PassRefPtrWillBeRawPtr<Node> pastEndNode)
+void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style, RefPtrWillBeMember<Node>& runStart, RefPtrWillBeMember<Node>& runEnd, PassRefPtrWillBeRawPtr<Node> pastEndNode, EditingState* editingState)
 {
     ASSERT(runStart && runEnd);
     RefPtrWillBeRawPtr<Node> next = runStart;
@@ -912,7 +947,9 @@
         RefPtrWillBeRawPtr<Node> previousSibling = element.previousSibling();
         RefPtrWillBeRawPtr<Node> nextSibling = element.nextSibling();
         RefPtrWillBeRawPtr<ContainerNode> parent = element.parentNode();
-        removeInlineStyleFromElement(style, &element, RemoveAlways);
+        removeInlineStyleFromElement(style, &element, editingState, RemoveAlways);
+        if (editingState->isAborted())
+            return;
         if (!element.inDocument()) {
             // FIXME: We might need to update the start and the end of current selection here but need a test.
             if (runStart == element)
@@ -923,7 +960,7 @@
     }
 }
 
-bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRefPtrWillBeRawPtr<HTMLElement> element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle)
+bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRefPtrWillBeRawPtr<HTMLElement> element, EditingState* editingState, InlineStyleRemovalMode mode, EditingStyle* extractedStyle)
 {
     ASSERT(element);
 
@@ -935,34 +972,38 @@
             return true;
         if (extractedStyle)
             extractedStyle->mergeInlineStyleOfElement(element.get(), EditingStyle::OverrideValues);
-        removeNodePreservingChildren(element);
+        removeNodePreservingChildren(element, editingState);
+        if (editingState->isAborted())
+            return false;
         return true;
     }
 
-    bool removed = false;
-    if (removeImplicitlyStyledElement(style, element.get(), mode, extractedStyle))
-        removed = true;
+    bool removed = removeImplicitlyStyledElement(style, element.get(), mode, extractedStyle, editingState);
+    if (editingState->isAborted())
+        return false;
 
     if (!element->inDocument())
         return removed;
 
     // If the node was converted to a span, the span may still contain relevant
     // styles which must be removed (e.g. <b style='font-weight: bold'>)
-    if (removeCSSStyle(style, element.get(), mode, extractedStyle))
+    if (removeCSSStyle(style, element.get(), editingState, mode, extractedStyle))
         removed = true;
+    if (editingState->isAborted())
+        return false;
 
     return removed;
 }
 
-void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement* elem)
+void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement* elem, EditingState* editingState)
 {
     if (hasNoAttributeOrOnlyStyleAttribute(elem, StyleAttributeShouldBeEmpty))
-        removeNodePreservingChildren(elem);
+        removeNodePreservingChildren(elem, editingState);
     else
         replaceElementWithSpanPreservingChildrenAndAttributes(elem);
 }
 
-bool ApplyStyleCommand::removeImplicitlyStyledElement(EditingStyle* style, HTMLElement* element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle)
+bool ApplyStyleCommand::removeImplicitlyStyledElement(EditingStyle* style, HTMLElement* element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle, EditingState* editingState)
 {
     ASSERT(style);
     if (mode == RemoveNone) {
@@ -972,7 +1013,9 @@
 
     ASSERT(mode == RemoveIfNeeded || mode == RemoveAlways);
     if (style->conflictsWithImplicitStyleOfElement(element, extractedStyle, mode == RemoveAlways ? EditingStyle::ExtractMatchingStyle : EditingStyle::DoNotExtractMatchingStyle)) {
-        replaceWithSpanOrRemoveIfWithoutAttributes(element);
+        replaceWithSpanOrRemoveIfWithoutAttributes(element, editingState);
+        if (editingState->isAborted())
+            return false;
         return true;
     }
 
@@ -985,13 +1028,16 @@
     for (const auto& attribute : attributes)
         removeElementAttribute(element, attribute);
 
-    if (isEmptyFontTag(element) || isSpanWithoutAttributesOrUnstyledStyleSpan(element))
-        removeNodePreservingChildren(element);
+    if (isEmptyFontTag(element) || isSpanWithoutAttributesOrUnstyledStyleSpan(element)) {
+        removeNodePreservingChildren(element, editingState);
+        if (editingState->isAborted())
+            return false;
+    }
 
     return true;
 }
 
-bool ApplyStyleCommand::removeCSSStyle(EditingStyle* style, HTMLElement* element, InlineStyleRemovalMode mode, EditingStyle* extractedStyle)
+bool ApplyStyleCommand::removeCSSStyle(EditingStyle* style, HTMLElement* element, EditingState* editingState, InlineStyleRemovalMode mode, EditingStyle* extractedStyle)
 {
     ASSERT(style);
     ASSERT(element);
@@ -1008,7 +1054,7 @@
         removeCSSProperty(element, property);
 
     if (isSpanWithoutAttributesOrUnstyledStyleSpan(element))
-        removeNodePreservingChildren(element);
+        removeNodePreservingChildren(element, editingState);
 
     return true;
 }
@@ -1033,7 +1079,7 @@
     return result;
 }
 
-void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* style)
+void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* style, EditingState* editingState)
 {
     ASSERT(node);
 
@@ -1061,10 +1107,10 @@
     // We can't wrap node with the styled element here because new styled element will never be removed if we did.
     // If we modified the child pointer in pushDownInlineStyleAroundNode to point to new style element
     // then we fall into an infinite loop where we keep removing and adding styled element wrapping node.
-    addInlineStyleIfNeeded(newInlineStyle.get(), node, node, DoNotAddStyledElement);
+    addInlineStyleIfNeeded(newInlineStyle.get(), node, node, editingState, DoNotAddStyledElement);
 }
 
-void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node* targetNode)
+void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node* targetNode, EditingState* editingState)
 {
     HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(style, targetNode);
     if (!highestAncestor)
@@ -1085,8 +1131,11 @@
         }
 
         RefPtrWillBeRawPtr<EditingStyle> styleToPushDown = EditingStyle::create();
-        if (current->isHTMLElement())
-            removeInlineStyleFromElement(style, toHTMLElement(current), RemoveIfNeeded, styleToPushDown.get());
+        if (current->isHTMLElement()) {
+            removeInlineStyleFromElement(style, toHTMLElement(current), editingState, RemoveIfNeeded, styleToPushDown.get());
+            if (editingState->isAborted())
+                return;
+        }
 
         // The inner loop will go through children on each level
         // FIXME: we should aggregate inline child elements together so that we don't wrap each child separately.
@@ -1108,8 +1157,11 @@
 
             // Apply style to all nodes containing targetNode and their siblings but NOT to targetNode
             // But if we've removed styledElement then go ahead and always apply the style.
-            if (child != targetNode || styledElement)
-                applyInlineStyleToPushDown(child, styleToPushDown.get());
+            if (child != targetNode || styledElement) {
+                applyInlineStyleToPushDown(child, styleToPushDown.get(), editingState);
+                if (editingState->isAborted())
+                    return;
+            }
 
             // We found the next node for the outer loop (contains targetNode)
             // When reached targetNode, stop the outer loop upon the completion of the current inner loop
@@ -1119,7 +1171,7 @@
     }
 }
 
-void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &start, const Position &end)
+void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &start, const Position &end, EditingState* editingState)
 {
     ASSERT(start.isNotNull());
     ASSERT(end.isNotNull());
@@ -1144,8 +1196,12 @@
     if (pushDownEndContainer && pushDownEndContainer->isTextNode() && !pushDownEnd.computeOffsetInContainerNode())
         pushDownEnd = previousVisuallyDistinctCandidate(pushDownEnd);
 
-    pushDownInlineStyleAroundNode(style, pushDownStart.anchorNode());
-    pushDownInlineStyleAroundNode(style, pushDownEnd.anchorNode());
+    pushDownInlineStyleAroundNode(style, pushDownStart.anchorNode(), editingState);
+    if (editingState->isAborted())
+        return;
+    pushDownInlineStyleAroundNode(style, pushDownEnd.anchorNode(), editingState);
+    if (editingState->isAborted())
+        return;
 
     // The s and e variables store the positions used to set the ending selection after style removal
     // takes place. This will help callers to recognize when either the start node or the end node
@@ -1180,7 +1236,9 @@
                 childNode = elem->firstChild();
             }
 
-            removeInlineStyleFromElement(style, elem.get(), RemoveIfNeeded, styleToPushDown.get());
+            removeInlineStyleFromElement(style, elem.get(), editingState, RemoveIfNeeded, styleToPushDown.get());
+            if (editingState->isAborted())
+                return;
             if (!elem->inDocument()) {
                 if (s.anchorNode() == elem) {
                     // Since elem must have been fully selected, and it is at the start
@@ -1198,8 +1256,11 @@
             }
 
             if (styleToPushDown) {
-                for (; childNode; childNode = childNode->nextSibling())
-                    applyInlineStyleToPushDown(childNode.get(), styleToPushDown.get());
+                for (; childNode; childNode = childNode->nextSibling()) {
+                    applyInlineStyleToPushDown(childNode.get(), styleToPushDown.get(), editingState);
+                    if (editingState->isAborted())
+                        return;
+                }
             }
         }
         if (node == end.anchorNode())
@@ -1301,7 +1362,7 @@
     return offsetInText > caretMinOffset(node) && offsetInText < caretMaxOffset(node);
 }
 
-bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end)
+bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end, EditingState* editingState)
 {
     Node* startNode = start.computeContainerNode();
     int startOffset = start.computeOffsetInContainerNode();
@@ -1327,7 +1388,9 @@
         Element* element = toElement(startNode);
         Node* startChild = element->firstChild();
         ASSERT(startChild);
-        mergeIdenticalElements(previousElement, element);
+        mergeIdenticalElements(previousElement, element, editingState);
+        if (editingState->isAborted())
+            return false;
 
         int startOffsetAdjustment = startChild->nodeIndex();
         int endOffsetAdjustment = startNode == end.anchorNode() ? startOffsetAdjustment : 0;
@@ -1339,7 +1402,7 @@
     return false;
 }
 
-bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const Position& end)
+bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const Position& end, EditingState* editingState)
 {
     Node* endNode = end.computeContainerNode();
 
@@ -1363,7 +1426,9 @@
         Element* element = toElement(endNode);
         Node* nextChild = nextElement->firstChild();
 
-        mergeIdenticalElements(element, nextElement);
+        mergeIdenticalElements(element, nextElement, editingState);
+        if (editingState->isAborted())
+            return false;
 
         bool shouldUpdateStart = start.computeContainerNode() == endNode;
         int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childNodes()->length();
@@ -1403,14 +1468,20 @@
     RefPtrWillBeRawPtr<Node> nextSibling = element->nextSibling();
     RefPtrWillBeRawPtr<Node> previousSibling = element->previousSibling();
     if (nextSibling && nextSibling->isElementNode() && nextSibling->hasEditableStyle()
-        && areIdenticalElements(*element, toElement(*nextSibling)))
-        mergeIdenticalElements(element.get(), toElement(nextSibling));
+        && areIdenticalElements(*element, toElement(*nextSibling))) {
+        mergeIdenticalElements(element.get(), toElement(nextSibling), editingState);
+        if (editingState->isAborted())
+            return;
+    }
 
     if (previousSibling && previousSibling->isElementNode() && previousSibling->hasEditableStyle()) {
         Node* mergedElement = previousSibling->nextSibling();
         if (mergedElement->isElementNode() && mergedElement->hasEditableStyle()
-            && areIdenticalElements(toElement(*previousSibling), toElement(*mergedElement)))
-            mergeIdenticalElements(toElement(previousSibling), toElement(mergedElement));
+            && areIdenticalElements(toElement(*previousSibling), toElement(*mergedElement))) {
+            mergeIdenticalElements(toElement(previousSibling), toElement(mergedElement), editingState);
+            if (editingState->isAborted())
+                return;
+        }
     }
 
     // FIXME: We should probably call updateStartEnd if the start or end was in the node
@@ -1436,7 +1507,7 @@
     setNodeAttribute(block, styleAttr, cssText.toAtomicString());
 }
 
-void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWillBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EAddStyledElement addStyledElement)
+void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWillBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EditingState* editingState, EAddStyledElement addStyledElement)
 {
     if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->inDocument())
         return;
@@ -1445,10 +1516,13 @@
     RefPtrWillBeMember<HTMLSpanElement> dummyElement = nullptr;
     StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dummyElement));
 
-    if (dummyElement)
-        removeNode(dummyElement);
+    if (dummyElement) {
+        removeNode(dummyElement, editingState);
+        if (editingState->isAborted())
+            return;
+    }
 
-    applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement, ASSERT_NO_EDITING_ABORT);
+    applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement, editingState);
 }
 
 Position ApplyStyleCommand::positionToComputeInlineStyleChange(PassRefPtrWillBeRawPtr<Node> startNode, RefPtrWillBeMember<HTMLSpanElement>& dummyElement)
@@ -1617,7 +1691,8 @@
             newEnd = Position(childText, childText->length() + end.offsetInContainerNode());
         String textToMove = nextText->data();
         insertTextIntoNode(childText, childText->length(), textToMove);
-        removeNode(next);
+        // Removing a Text node doesn't dispatch synchronous events.
+        removeNode(next, ASSERT_NO_EDITING_ABORT);
         // don't move child node pointer. it may want to merge with more text nodes.
     }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h
index 42452e74..782fa16 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h
@@ -79,26 +79,28 @@
     // style-removal helpers
     bool isStyledInlineElementToRemove(Element*) const;
     bool shouldApplyInlineStyleToRun(EditingStyle*, Node* runStart, Node* pastEndNode);
-    void removeConflictingInlineStyleFromRun(EditingStyle*, RefPtrWillBeMember<Node>& runStart, RefPtrWillBeMember<Node>& runEnd, PassRefPtrWillBeRawPtr<Node> pastEndNode);
-    bool removeInlineStyleFromElement(EditingStyle*, PassRefPtrWillBeRawPtr<HTMLElement>, InlineStyleRemovalMode = RemoveIfNeeded, EditingStyle* extractedStyle = nullptr);
-    inline bool shouldRemoveInlineStyleFromElement(EditingStyle* style, HTMLElement* element) {return removeInlineStyleFromElement(style, element, RemoveNone);}
-    void replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*);
-    bool removeImplicitlyStyledElement(EditingStyle*, HTMLElement*, InlineStyleRemovalMode, EditingStyle* extractedStyle);
-    bool removeCSSStyle(EditingStyle*, HTMLElement*, InlineStyleRemovalMode = RemoveIfNeeded, EditingStyle* extractedStyle = nullptr);
+    void removeConflictingInlineStyleFromRun(EditingStyle*, RefPtrWillBeMember<Node>& runStart, RefPtrWillBeMember<Node>& runEnd, PassRefPtrWillBeRawPtr<Node> pastEndNode, EditingState*);
+    bool removeInlineStyleFromElement(EditingStyle*, PassRefPtrWillBeRawPtr<HTMLElement>, EditingState*, InlineStyleRemovalMode = RemoveIfNeeded, EditingStyle* extractedStyle = nullptr);
+    inline bool shouldRemoveInlineStyleFromElement(EditingStyle* style, HTMLElement* element) { return removeInlineStyleFromElement(style, element, ASSERT_NO_EDITING_ABORT, RemoveNone); }
+    void replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*, EditingState*);
+    bool removeImplicitlyStyledElement(EditingStyle*, HTMLElement*, InlineStyleRemovalMode, EditingStyle* extractedStyle, EditingState*);
+    bool removeCSSStyle(EditingStyle*, HTMLElement*, EditingState*, InlineStyleRemovalMode = RemoveIfNeeded, EditingStyle* extractedStyle = nullptr);
     HTMLElement* highestAncestorWithConflictingInlineStyle(EditingStyle*, Node*);
-    void applyInlineStyleToPushDown(Node*, EditingStyle*);
-    void pushDownInlineStyleAroundNode(EditingStyle*, Node*);
-    void removeInlineStyle(EditingStyle* , const Position& start, const Position& end);
+    void applyInlineStyleToPushDown(Node*, EditingStyle*, EditingState*);
+    void pushDownInlineStyleAroundNode(EditingStyle*, Node*, EditingState*);
+    void removeInlineStyle(EditingStyle* , const Position& start, const Position& end, EditingState*);
     bool elementFullySelected(HTMLElement&, const Position& start, const Position& end) const;
 
     // style-application helpers
     void applyBlockStyle(EditingStyle*, EditingState*);
-    void applyRelativeFontStyleChange(EditingStyle*);
+    void applyRelativeFontStyleChange(EditingStyle*, EditingState*);
     void applyInlineStyle(EditingStyle*, EditingState*);
     void fixRangeAndApplyInlineStyle(EditingStyle*, const Position& start, const Position& end, EditingState*);
     void applyInlineStyleToNodeRange(EditingStyle*, PassRefPtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> pastEndNode, EditingState*);
     void addBlockStyle(const StyleChange&, HTMLElement*);
-    void addInlineStyleIfNeeded(EditingStyle*, PassRefPtrWillBeRawPtr<Node> start, PassRefPtrWillBeRawPtr<Node> end, EAddStyledElement = AddStyledElement);
+    // TODO(tkent): Remove the EAddStyledElement argument. It's always
+    // DoNotAddStyledElement.
+    void addInlineStyleIfNeeded(EditingStyle*, PassRefPtrWillBeRawPtr<Node> start, PassRefPtrWillBeRawPtr<Node> end, EditingState*, EAddStyledElement = AddStyledElement);
     Position positionToComputeInlineStyleChange(PassRefPtrWillBeRawPtr<Node>, RefPtrWillBeMember<HTMLSpanElement>& dummyElement);
     void applyInlineStyleChange(PassRefPtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> endNode, StyleChange&, EAddStyledElement, EditingState*);
     void splitTextAtStart(const Position& start, const Position& end);
@@ -107,16 +109,16 @@
     void splitTextElementAtEnd(const Position& start, const Position& end);
     bool shouldSplitTextElement(Element*, EditingStyle*);
     bool isValidCaretPositionInTextNode(const Position&);
-    bool mergeStartWithPreviousIfIdentical(const Position& start, const Position& end);
-    bool mergeEndWithNextIfIdentical(const Position& start, const Position& end);
-    void cleanupUnstyledAppleStyleSpans(ContainerNode* dummySpanAncestor);
+    bool mergeStartWithPreviousIfIdentical(const Position& start, const Position& end, EditingState*);
+    bool mergeEndWithNextIfIdentical(const Position& start, const Position& end, EditingState*);
+    void cleanupUnstyledAppleStyleSpans(ContainerNode* dummySpanAncestor, EditingState*);
 
     void surroundNodeRangeWithElement(PassRefPtrWillBeRawPtr<Node> start, PassRefPtrWillBeRawPtr<Node> end, PassRefPtrWillBeRawPtr<Element>, EditingState*);
     float computedFontSize(Node*);
     void joinChildTextNodes(ContainerNode*, const Position& start, const Position& end);
 
     HTMLElement* splitAncestorsWithUnicodeBidi(Node*, bool before, WritingDirection allowedDirection);
-    void removeEmbeddingUpToEnclosingBlock(Node*, HTMLElement* unsplitAncestor);
+    void removeEmbeddingUpToEnclosingBlock(Node*, HTMLElement* unsplitAncestor, EditingState*);
 
     void updateStartEnd(const Position& newStart, const Position& newEnd);
     Position startPosition();
diff --git a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
index cea7493..b7bc276 100644
--- a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
@@ -72,14 +72,17 @@
 {
 }
 
-void BreakBlockquoteCommand::doApply(EditingState*)
+void BreakBlockquoteCommand::doApply(EditingState* editingState)
 {
     if (endingSelection().isNone())
         return;
 
     // Delete the current selection.
-    if (endingSelection().isRange())
-        deleteSelection(ASSERT_NO_EDITING_ABORT, false, false);
+    if (endingSelection().isRange()) {
+        deleteSelection(editingState, false, false);
+        if (editingState->isAborted())
+            return;
+    }
 
     // This is a scenario that should never happen, but we want to
     // make sure we don't dereference a null pointer below.
@@ -191,11 +194,15 @@
                 setNodeAttribute(clonedChild, startAttr, AtomicString::number(toLayoutListItem(listChildNode->layoutObject())->value()));
         }
 
-        appendNode(clonedChild.get(), clonedAncestor.get());
+        appendNode(clonedChild.get(), clonedAncestor.get(), editingState);
+        if (editingState->isAborted())
+            return;
         clonedAncestor = clonedChild;
     }
 
-    moveRemainingSiblingsToNewParent(startNode, 0, clonedAncestor);
+    moveRemainingSiblingsToNewParent(startNode, 0, clonedAncestor, editingState);
+    if (editingState->isAborted())
+        return;
 
     if (!ancestors.isEmpty()) {
         // Split the tree up the ancestor chain until the topBlockquote
@@ -206,13 +213,19 @@
         RefPtrWillBeRawPtr<Element> clonedParent = nullptr;
         for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parentElement();
             ancestor && ancestor != topBlockquote;
-            ancestor = ancestor->parentElement(), clonedParent = clonedParent->parentElement())
-            moveRemainingSiblingsToNewParent(ancestor->nextSibling(), 0, clonedParent);
+            ancestor = ancestor->parentElement(), clonedParent = clonedParent->parentElement()) {
+            moveRemainingSiblingsToNewParent(ancestor->nextSibling(), 0, clonedParent, editingState);
+            if (editingState->isAborted())
+                return;
+        }
 
         // If the startNode's original parent is now empty, remove it
         Element* originalParent = ancestors.first().get();
-        if (!originalParent->hasChildren())
-            removeNode(originalParent);
+        if (!originalParent->hasChildren()) {
+            removeNode(originalParent, editingState);
+            if (editingState->isAborted())
+                return;
+        }
     }
 
     // Make sure the cloned block quote renders.
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 9968645..112f619 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -388,7 +388,7 @@
     applyCommandToComposite(AppendNodeCommand::create(parent, node));
 }
 
-void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> node, unsigned from, unsigned to)
+void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> node, unsigned from, unsigned to, EditingState* editingState)
 {
     WillBeHeapVector<RefPtrWillBeMember<Node>> children;
     Node* child = NodeTraversal::childAt(*node, from);
@@ -396,8 +396,11 @@
         children.append(child);
 
     size_t size = children.size();
-    for (size_t i = 0; i < size; ++i)
-        removeNode(children[i].release());
+    for (size_t i = 0; i < size; ++i) {
+        removeNode(children[i].release(), editingState);
+        if (editingState->isAborted())
+            return;
+    }
 }
 
 void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
@@ -414,15 +417,17 @@
     applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, shouldAssumeContentIsAlwaysEditable), editingState);
 }
 
-void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node> node, Node* excludeNode)
+void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, Node* excludeNode)
 {
     ASSERT(node.get() != excludeNode);
     RefPtrWillBeRawPtr<ContainerNode> parent = node->parentNode();
-    removeNode(node);
-    prune(parent.release(), excludeNode);
+    removeNode(node, editingState);
+    if (editingState->isAborted())
+        return;
+    prune(parent.release(), editingState, excludeNode);
 }
 
-void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent)
+void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent, EditingState* editingState)
 {
     NodeVector nodesToRemove;
     RefPtrWillBeRawPtr<Element> newParent = prpNewParent;
@@ -431,8 +436,12 @@
         nodesToRemove.append(node);
 
     for (unsigned i = 0; i < nodesToRemove.size(); i++) {
-        removeNode(nodesToRemove[i]);
-        appendNode(nodesToRemove[i], newParent);
+        removeNode(nodesToRemove[i], editingState);
+        if (editingState->isAborted())
+            return;
+        appendNode(nodesToRemove[i], newParent, editingState);
+        if (editingState->isAborted())
+            return;
     }
 }
 
@@ -459,10 +468,10 @@
     return command->spanElement();
 }
 
-void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, Node* excludeNode)
+void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, Node* excludeNode)
 {
     if (RefPtrWillBeRawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get(), excludeNode))
-        removeNode(highestNodeToRemove.release());
+        removeNode(highestNodeToRemove.release(), editingState);
 }
 
 void CompositeEditCommand::splitTextNode(PassRefPtrWillBeRawPtr<Text> node, unsigned offset)
@@ -475,16 +484,18 @@
     applyCommandToComposite(SplitElementCommand::create(element, atChild));
 }
 
-void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond)
+void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<Element> first = prpFirst;
     RefPtrWillBeRawPtr<Element> second = prpSecond;
     ASSERT(!first->isDescendantOf(second.get()) && second != first);
     if (first->nextSibling() != second) {
-        removeNode(second);
+        removeNode(second, editingState);
+        if (editingState->isAborted())
+            return;
         insertNodeAfter(second, first);
     }
-    applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second));
+    applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second), editingState);
 }
 
 void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtrWillBeRawPtr<Element> element)
@@ -776,7 +787,8 @@
 
     if (!box) {
         // whole text node is empty
-        removeNode(textNode);
+        // Removing a Text node won't dispatch synchronous events.
+        removeNode(textNode, ASSERT_NO_EDITING_ABORT);
         return;
     }
 
@@ -917,7 +929,8 @@
 
     // We are certain that the position is at a line break, but it may be a br or a preserved newline.
     if (isHTMLBRElement(*p.anchorNode())) {
-        removeNode(p.anchorNode());
+        // Removing a BR element won't dispatch synchronous events.
+        removeNode(p.anchorNode(), ASSERT_NO_EDITING_ABORT);
         return;
     }
 
@@ -1107,7 +1120,7 @@
 // Deleting a paragraph will leave a placeholder. Remove it (and prune
 // empty or unrendered parents).
 
-void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination)
+void CompositeEditCommand::cleanupAfterDeletion(EditingState* editingState, VisiblePosition destination)
 {
     VisiblePosition caretAfterDelete = endingSelection().visibleStart();
     Node* destinationNode = destination.deepEquivalent().anchorNode();
@@ -1122,7 +1135,7 @@
 
         // Normally deletion will leave a br as a placeholder.
         if (isHTMLBRElement(*node)) {
-            removeNodeAndPruneAncestors(node, destinationNode);
+            removeNodeAndPruneAncestors(node, editingState, destinationNode);
 
             // If the selection to move was empty and in an empty block that
             // doesn't require a placeholder to prop itself open (like a bordered
@@ -1132,16 +1145,16 @@
             // If caret position after deletion and destination position coincides,
             // node should not be removed.
             if (!rendersInDifferentPosition(position, destination.deepEquivalent())) {
-                prune(node, destinationNode);
+                prune(node, editingState, destinationNode);
                 return;
             }
-            removeNodeAndPruneAncestors(node, destinationNode);
+            removeNodeAndPruneAncestors(node, editingState, destinationNode);
         } else if (lineBreakExistsAtPosition(position)) {
             // There is a preserved '\n' at caretAfterDelete.
             // We can safely assume this is a text node.
             Text* textNode = toText(node);
             if (textNode->length() == 1)
-                removeNodeAndPruneAncestors(node, destinationNode);
+                removeNodeAndPruneAncestors(node, editingState, destinationNode);
             else
                 deleteTextFromNode(textNode, position.computeOffsetInContainerNode(), 1);
         }
@@ -1180,7 +1193,9 @@
     // It expands and removes the entire table/list, but will let content
     // before and after the table/list collapse onto one line.
 
-    cleanupAfterDeletion();
+    cleanupAfterDeletion(editingState);
+    if (editingState->isAborted())
+        return;
 
     // Add a br if pruning an empty block level element caused a collapse.  For example:
     // foo^
@@ -1269,7 +1284,9 @@
         return;
 
     ASSERT(destination.deepEquivalent().inDocument());
-    cleanupAfterDeletion(destination);
+    cleanupAfterDeletion(editingState, destination);
+    if (editingState->isAborted())
+        return;
     ASSERT(destination.deepEquivalent().inDocument());
 
     // Add a br if pruning an empty block level element caused a collapse. For example:
@@ -1326,7 +1343,7 @@
 }
 
 // FIXME: Send an appropriate shouldDeleteRange call.
-bool CompositeEditCommand::breakOutOfEmptyListItem()
+bool CompositeEditCommand::breakOutOfEmptyListItem(EditingState* editingState)
 {
     RefPtrWillBeRawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
     if (!emptyListItem)
@@ -1352,7 +1369,9 @@
                 // If listNode does NOT appear at the end, then we should consider it as a regular paragraph.
                 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should become <ul><li> <div><br></div> hello</li></ul> at the end
                 splitElement(toElement(blockEnclosingList), listNode);
-                removeNodePreservingChildren(listNode->parentNode());
+                removeNodePreservingChildren(listNode->parentNode(), editingState);
+                if (editingState->isAborted())
+                    return false;
                 newBlock = HTMLLIElement::create(document());
             }
             // If listNode does NOT appear at the end of the outer list item, then behave as if in a regular paragraph.
@@ -1373,13 +1392,19 @@
         // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
         // Because we have splitted the element, emptyListItem is the first element in the list node.
         // i.e. insert newBlock before ul or ol whose first element is emptyListItem
-        insertNodeBefore(newBlock, listNode);
-        removeNode(emptyListItem);
+        insertNodeBefore(newBlock, listNode, editingState);
+        if (editingState->isAborted())
+            return false;
+        removeNode(emptyListItem, editingState);
+        if (editingState->isAborted())
+            return false;
     } else {
         // When emptyListItem does not follow any list item or nested list, insert newBlock after the enclosing list node.
         // Remove the enclosing node if emptyListItem is the only child; otherwise just remove emptyListItem.
         insertNodeAfter(newBlock, listNode);
-        removeNode(isListItem(previousListNode.get()) || isHTMLListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get());
+        removeNode(isListItem(previousListNode.get()) || isHTMLListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get(), editingState);
+        if (editingState->isAborted())
+            return false;
     }
 
     appendBlockPlaceholder(newBlock);
@@ -1394,7 +1419,7 @@
 
 // If the caret is in an empty quoted paragraph, and either there is nothing before that
 // paragraph, or what is before is unquoted, and the user presses delete, unquote that paragraph.
-bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
+bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph(EditingState* editingState)
 {
     if (!endingSelection().isCaret())
         return false;
@@ -1415,12 +1440,17 @@
     RefPtrWillBeRawPtr<HTMLBRElement> br = HTMLBRElement::create(document());
     // We want to replace this quoted paragraph with an unquoted one, so insert a br
     // to hold the caret before the highest blockquote.
-    insertNodeBefore(br, highestBlockquote);
+    insertNodeBefore(br, highestBlockquote, editingState);
+    if (editingState->isAborted())
+        return false;
     VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get()));
     // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
     // a second one.
-    if (!isStartOfParagraph(atBR))
-        insertNodeBefore(HTMLBRElement::create(document()), br);
+    if (!isStartOfParagraph(atBR)) {
+        insertNodeBefore(HTMLBRElement::create(document()), br, editingState);
+        if (editingState->isAborted())
+            return false;
+    }
     setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
 
     // If this is an empty paragraph there must be a line break here.
@@ -1432,7 +1462,9 @@
     ASSERT(isHTMLBRElement(caretPos.anchorNode()) || (caretPos.anchorNode()->isTextNode() && caretPos.anchorNode()->layoutObject()->style()->preserveNewline()));
 
     if (isHTMLBRElement(*caretPos.anchorNode())) {
-        removeNodeAndPruneAncestors(caretPos.anchorNode());
+        removeNodeAndPruneAncestors(caretPos.anchorNode(), editingState);
+        if (editingState->isAborted())
+            return false;
     } else if (caretPos.anchorNode()->isTextNode()) {
         ASSERT(caretPos.computeOffsetInContainerNode() == 0);
         Text* textNode = toText(caretPos.anchorNode());
@@ -1440,7 +1472,9 @@
         // The preserved newline must be the first thing in the node, since otherwise the previous
         // paragraph would be quoted, and we verified that it wasn't above.
         deleteTextFromNode(textNode, 0, 1);
-        prune(parentNode);
+        prune(parentNode, editingState);
+        if (editingState->isAborted())
+            return false;
     }
 
     return true;
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
index 7bcefc8d..8c0270f 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
@@ -114,7 +114,7 @@
     void insertNodeBefore(PassRefPtrWillBeRawPtr<Node>, PassRefPtrWillBeRawPtr<Node> refChild, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
     void insertParagraphSeparator(bool useDefaultParagraphElement = false, bool pasteBlockqutoeIntoUnquotedArea = false);
     void insertTextIntoNode(PassRefPtrWillBeRawPtr<Text>, unsigned offset, const String& text);
-    void mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element>);
+    void mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element>, EditingState*);
     void rebalanceWhitespace();
     void rebalanceWhitespaceAt(const Position&);
     void rebalanceWhitespaceOnTextSubstring(PassRefPtrWillBeRawPtr<Text>, int startOffset, int endOffset);
@@ -124,14 +124,14 @@
     bool shouldRebalanceLeadingWhitespaceFor(const String&) const;
     void removeCSSProperty(PassRefPtrWillBeRawPtr<Element>, CSSPropertyID);
     void removeElementAttribute(PassRefPtrWillBeRawPtr<Element>, const QualifiedName& attribute);
-    void removeChildrenInRange(PassRefPtrWillBeRawPtr<Node>, unsigned from, unsigned to);
-    virtual void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
+    void removeChildrenInRange(PassRefPtrWillBeRawPtr<Node>, unsigned from, unsigned to, EditingState*);
+    virtual void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState*, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
     HTMLSpanElement* replaceElementWithSpanPreservingChildrenAndAttributes(PassRefPtrWillBeRawPtr<HTMLElement>);
-    void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
-    void removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node>, Node* excludeNode = nullptr);
-    void moveRemainingSiblingsToNewParent(Node*, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent);
+    void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node>, EditingState*, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
+    void removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node>, EditingState*, Node* excludeNode = nullptr);
+    void moveRemainingSiblingsToNewParent(Node*, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent, EditingState*);
     void updatePositionForNodeRemovalPreservingChildren(Position&, Node&);
-    void prune(PassRefPtrWillBeRawPtr<Node>, Node* excludeNode = nullptr);
+    void prune(PassRefPtrWillBeRawPtr<Node>, EditingState*, Node* excludeNode = nullptr);
     void replaceTextInNode(PassRefPtrWillBeRawPtr<Text>, unsigned offset, unsigned count, const String& replacementText);
     Position replaceSelectedTextInNode(const String&);
     void replaceTextInNodePreservingMarkers(PassRefPtrWillBeRawPtr<Text>, unsigned offset, unsigned count, const String& replacementText);
@@ -162,10 +162,10 @@
     void moveParagraphs(const VisiblePosition&, const VisiblePosition&, const VisiblePosition&, EditingState*, bool preserveSelection = false, bool preserveStyle = true, Node* constrainingAncestor = nullptr);
     void moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* blockElement, Node* outerNode, EditingState* = ASSERT_NO_EDITING_ABORT);
     void cloneParagraphUnderNewElement(const Position& start, const Position& end, Node* outerNode, Element* blockElement, EditingState*);
-    void cleanupAfterDeletion(VisiblePosition destination = VisiblePosition());
+    void cleanupAfterDeletion(EditingState*, VisiblePosition destination = VisiblePosition());
 
-    bool breakOutOfEmptyListItem();
-    bool breakOutOfEmptyMailBlockquotedParagraph();
+    bool breakOutOfEmptyListItem(EditingState*);
+    bool breakOutOfEmptyMailBlockquotedParagraph(EditingState*);
 
     Position positionAvoidingSpecialElementBoundary(const Position&, EditingState*);
 
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index cd8700f7..da914f13 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -300,7 +300,7 @@
         m_deleteIntoBlockquoteStyle = nullptr;
 }
 
-bool DeleteSelectionCommand::handleSpecialCaseBRDelete()
+bool DeleteSelectionCommand::handleSpecialCaseBRDelete(EditingState* editingState)
 {
     Node* nodeAfterUpstreamStart = m_upstreamStart.computeNodeAfterPosition();
     Node* nodeAfterDownstreamStart = m_downstreamStart.computeNodeAfterPosition();
@@ -315,7 +315,7 @@
     bool downstreamStartIsBR = isHTMLBRElement(*nodeAfterDownstreamStart);
     bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && nodeAfterDownstreamStart == nodeAfterUpstreamEnd;
     if (isBROnLineByItself) {
-        removeNode(nodeAfterDownstreamStart);
+        removeNode(nodeAfterDownstreamStart, editingState);
         return true;
     }
 
@@ -431,7 +431,7 @@
     CompositeEditCommand::deleteTextFromNode(node, offset, count);
 }
 
-void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss()
+void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(EditingState* editingState)
 {
     RefPtrWillBeRawPtr<Range> range = createRange(m_selectionToDelete.toNormalizedEphemeralRange());
     RefPtrWillBeRawPtr<Node> node = range->firstNode();
@@ -441,8 +441,12 @@
             nextNode = NodeTraversal::nextSkippingChildren(*node);
             RefPtrWillBeRawPtr<Element> rootEditableElement = node->rootEditableElement();
             if (rootEditableElement.get()) {
-                removeNode(node);
-                appendNode(node, rootEditableElement);
+                removeNode(node, editingState);
+                if (editingState->isAborted())
+                    return;
+                appendNode(node, rootEditableElement, editingState);
+                if (editingState->isAborted())
+                    return;
             }
         }
         node = nextNode;
@@ -458,7 +462,9 @@
     Node* startNode = m_upstreamStart.anchorNode();
     ASSERT(startNode);
 
-    makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss();
+    makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(editingState);
+    if (editingState->isAborted())
+        return;
 
     // Never remove the start block unless it's a table, in which case we won't merge content in.
     if (startNode->isSameNode(m_startBlock.get()) && !startOffset && canHaveChildrenForEditing(startNode) && !isHTMLTableElement(*startNode)) {
@@ -490,7 +496,9 @@
                 Text* text = toText(startNode);
                 deleteTextFromNode(text, startOffset, m_downstreamEnd.computeOffsetInContainerNode() - startOffset);
             } else {
-                removeChildrenInRange(startNode, startOffset, m_downstreamEnd.computeEditingOffset());
+                removeChildrenInRange(startNode, startOffset, m_downstreamEnd.computeEditingOffset(), editingState);
+                if (editingState->isAborted())
+                    return;
                 m_endingPosition = m_upstreamStart;
             }
         }
@@ -573,7 +581,9 @@
                         if (n)
                             offset = n->nodeIndex() + 1;
                     }
-                    removeChildrenInRange(m_downstreamEnd.anchorNode(), offset, m_downstreamEnd.computeEditingOffset());
+                    removeChildrenInRange(m_downstreamEnd.anchorNode(), offset, m_downstreamEnd.computeEditingOffset(), editingState);
+                    if (editingState->isAborted())
+                        return;
                     m_downstreamEnd = Position::editingPositionOf(m_downstreamEnd.anchorNode(), offset);
                 }
             }
@@ -601,12 +611,14 @@
 
 // If a selection starts in one block and ends in another, we have to merge to bring content before the
 // start together with content after the end.
-void DeleteSelectionCommand::mergeParagraphs()
+void DeleteSelectionCommand::mergeParagraphs(EditingState* editingState)
 {
     if (!m_mergeBlocksAfterDelete) {
         if (m_pruneStartBlockIfNecessary) {
             // We aren't going to merge into the start block, so remove it if it's empty.
-            prune(m_startBlock);
+            prune(m_startBlock, editingState);
+            if (editingState->isAborted())
+                return;
             // Removing the start block during a deletion is usually an indication that we need
             // a placeholder, but not in this case.
             m_needPlaceholder = false;
@@ -636,13 +648,15 @@
     // move, so just remove it.
     Element* endBlock = enclosingBlock(m_downstreamEnd.anchorNode());
     if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent().anchorNode()) || !startOfParagraphToMove.deepEquivalent().anchorNode()) {
-        removeNode(enclosingBlock(m_downstreamEnd.anchorNode()));
+        removeNode(enclosingBlock(m_downstreamEnd.anchorNode()), editingState);
         return;
     }
 
     // We need to merge into m_upstreamStart's block, but it's been emptied out and collapsed by deletion.
     if (!mergeDestination.deepEquivalent().anchorNode() || (!mergeDestination.deepEquivalent().anchorNode()->isDescendantOf(enclosingBlock(m_upstreamStart.computeContainerNode())) && (!mergeDestination.deepEquivalent().anchorNode()->hasChildren() || !m_upstreamStart.computeContainerNode()->hasChildren())) || (m_startsAtEmptyLine && mergeDestination.deepEquivalent() != startOfParagraphToMove.deepEquivalent())) {
-        insertNodeAt(HTMLBRElement::create(document()).get(), m_upstreamStart);
+        insertNodeAt(HTMLBRElement::create(document()).get(), m_upstreamStart, editingState);
+        if (editingState->isAborted())
+            return;
         mergeDestination = createVisiblePosition(m_upstreamStart);
     }
 
@@ -660,7 +674,9 @@
     if (listItemInFirstParagraph && listItemInSecondParagraph
         && listItemInFirstParagraph->parentElement() != listItemInSecondParagraph->parentElement()
         && canMergeLists(listItemInFirstParagraph->parentElement(), listItemInSecondParagraph->parentElement())) {
-        mergeIdenticalElements(listItemInFirstParagraph->parentElement(), listItemInSecondParagraph->parentElement());
+        mergeIdenticalElements(listItemInFirstParagraph->parentElement(), listItemInSecondParagraph->parentElement(), editingState);
+        if (editingState->isAborted())
+            return;
         m_endingPosition = mergeDestination.deepEquivalent();
         return;
     }
@@ -669,7 +685,9 @@
     // FIXME: Consider RTL.
     if (!m_startsAtEmptyLine && isStartOfParagraph(mergeDestination) && absoluteCaretBoundsOf(startOfParagraphToMove).x() > absoluteCaretBoundsOf(mergeDestination).x()) {
         if (isHTMLBRElement(*mostForwardCaretPosition(mergeDestination.deepEquivalent()).anchorNode())) {
-            removeNodeAndPruneAncestors(mostForwardCaretPosition(mergeDestination.deepEquivalent()).anchorNode());
+            removeNodeAndPruneAncestors(mostForwardCaretPosition(mergeDestination.deepEquivalent()).anchorNode(), editingState);
+            if (editingState->isAborted())
+                return;
             m_endingPosition = startOfParagraphToMove.deepEquivalent();
             return;
         }
@@ -687,13 +705,15 @@
     // removals that it does cause the insertion of *another* placeholder.
     bool needPlaceholder = m_needPlaceholder;
     bool paragraphToMergeIsEmpty = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMove.deepEquivalent();
-    moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination, ASSERT_NO_EDITING_ABORT, false, !paragraphToMergeIsEmpty);
+    moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination, editingState, false, !paragraphToMergeIsEmpty);
+    if (editingState->isAborted())
+        return;
     m_needPlaceholder = needPlaceholder;
     // The endingPosition was likely clobbered by the move, so recompute it (moveParagraph selects the moved paragraph).
     m_endingPosition = endingSelection().start();
 }
 
-void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows()
+void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows(EditingState* editingState)
 {
     if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_startTableRow) {
         Node* row = m_endTableRow->previousSibling();
@@ -703,7 +723,9 @@
                 // Use a raw removeNode, instead of DeleteSelectionCommand's,
                 // because that won't remove rows, it only empties them in
                 // preparation for this function.
-                CompositeEditCommand::removeNode(row);
+                CompositeEditCommand::removeNode(row, editingState);
+                if (editingState->isAborted())
+                    return;
             }
             row = previousRow.get();
         }
@@ -714,8 +736,11 @@
         Node* row = m_startTableRow->nextSibling();
         while (row && row != m_endTableRow) {
             RefPtrWillBeRawPtr<Node> nextRow = row->nextSibling();
-            if (isTableRowEmpty(row))
-                CompositeEditCommand::removeNode(row);
+            if (isTableRowEmpty(row)) {
+                CompositeEditCommand::removeNode(row, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
             row = nextRow.get();
         }
     }
@@ -729,7 +754,9 @@
                 // fully selected, even if it is empty. We'll need to start
                 // adjusting the selection endpoints during deletion to know
                 // whether or not m_endTableRow was fully selected here.
-                CompositeEditCommand::removeNode(m_endTableRow.get());
+                CompositeEditCommand::removeNode(m_endTableRow.get(), editingState);
+                if (editingState->isAborted())
+                    return;
             }
         }
     }
@@ -842,7 +869,10 @@
 
     // deleting just a BR is handled specially, at least because we do not
     // want to replace it with a placeholder BR!
-    if (handleSpecialCaseBRDelete()) {
+    bool brResult = handleSpecialCaseBRDelete(editingState);
+    if (editingState->isAborted())
+        return;
+    if (brResult) {
         calculateTypingStyleAfterDelete();
         setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSelection().isDirectional()));
         clearTransientState();
@@ -856,9 +886,13 @@
 
     fixupWhitespace();
 
-    mergeParagraphs();
+    mergeParagraphs(editingState);
+    if (editingState->isAborted())
+        return;
 
-    removePreviouslySelectedEmptyTableRows();
+    removePreviouslySelectedEmptyTableRows(editingState);
+    if (editingState->isAborted())
+        return;
 
     if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) {
         VisiblePosition visualEnding = createVisiblePosition(m_endingPosition);
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h
index 6e8ea714..af4e2c70b 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h
@@ -59,15 +59,15 @@
     void setStartingSelectionOnSmartDelete(const Position&, const Position&);
     void initializePositionData();
     void saveTypingStyleState();
-    bool handleSpecialCaseBRDelete();
+    bool handleSpecialCaseBRDelete(EditingState*);
     void handleGeneralDelete(EditingState*);
     void fixupWhitespace();
-    void mergeParagraphs();
-    void removePreviouslySelectedEmptyTableRows();
+    void mergeParagraphs(EditingState*);
+    void removePreviouslySelectedEmptyTableRows(EditingState*);
     void calculateTypingStyleAfterDelete();
     void clearTransientState();
-    void makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss();
-    void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable) override;
+    void makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(EditingState*);
+    void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState*, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable) override;
     void deleteTextFromNode(PassRefPtrWillBeRawPtr<Text>, unsigned, unsigned) override;
     void removeRedundantBlocks(EditingState*);
 
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
index 6101908..b4044294 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
@@ -66,7 +66,7 @@
 {
 }
 
-bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const Position& end)
+bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const Position& end, EditingState* editingState)
 {
     // If our selection is not inside a list, bail out.
     RefPtrWillBeRawPtr<Node> lastNodeInSelectedParagraph = start.anchorNode();
@@ -89,22 +89,34 @@
     // list element will change visibility of list item, e.g. :first-child
     // CSS selector.
     RefPtrWillBeRawPtr<HTMLElement> newList = toHTMLElement(document().createElement(listElement->tagQName(), false).get());
-    insertNodeBefore(newList, selectedListItem.get());
+    insertNodeBefore(newList, selectedListItem.get(), editingState);
+    if (editingState->isAborted())
+        return false;
 
     // We should clone all the children of the list item for indenting purposes. However, in case the current
     // selection does not encompass all its children, we need to explicitally handle the same. The original
     // list item too would require proper deletion in that case.
     if (end.anchorNode() == selectedListItem.get() || end.anchorNode()->isDescendantOf(selectedListItem->lastChild())) {
-        moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(end), newList.get(), selectedListItem.get());
+        moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(end), newList.get(), selectedListItem.get(), editingState);
     } else {
-        moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(positionAfterNode(selectedListItem->lastChild())), newList.get(), selectedListItem.get());
-        removeNode(selectedListItem.get());
+        moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(positionAfterNode(selectedListItem->lastChild())), newList.get(), selectedListItem.get(), editingState);
+        if (editingState->isAborted())
+            return false;
+        removeNode(selectedListItem.get(), editingState);
     }
+    if (editingState->isAborted())
+        return false;
 
-    if (canMergeLists(previousList.get(), newList.get()))
-        mergeIdenticalElements(previousList.get(), newList.get());
-    if (canMergeLists(newList.get(), nextList.get()))
-        mergeIdenticalElements(newList.get(), nextList.get());
+    if (canMergeLists(previousList.get(), newList.get())) {
+        mergeIdenticalElements(previousList.get(), newList.get(), editingState);
+        if (editingState->isAborted())
+            return false;
+    }
+    if (canMergeLists(newList.get(), nextList.get())) {
+        mergeIdenticalElements(newList.get(), nextList.get(), editingState);
+        if (editingState->isAborted())
+            return false;
+    }
 
     return true;
 }
@@ -143,7 +155,7 @@
     moveParagraphWithClones(startOfContents, endOfContents, targetBlockquote.get(), outerBlock.get(), editingState);
 }
 
-void IndentOutdentCommand::outdentParagraph()
+void IndentOutdentCommand::outdentParagraph(EditingState* editingState)
 {
     VisiblePosition visibleStartOfParagraph = startOfParagraph(endingSelection().visibleStart());
     VisiblePosition visibleEndOfParagraph = endOfParagraph(visibleStartOfParagraph);
@@ -154,11 +166,11 @@
 
     // Use InsertListCommand to remove the selection from the list
     if (isHTMLOListElement(*enclosingElement)) {
-        applyCommandToComposite(InsertListCommand::create(document(), InsertListCommand::OrderedList));
+        applyCommandToComposite(InsertListCommand::create(document(), InsertListCommand::OrderedList), editingState);
         return;
     }
     if (isHTMLUListElement(*enclosingElement)) {
-        applyCommandToComposite(InsertListCommand::create(document(), InsertListCommand::UnorderedList));
+        applyCommandToComposite(InsertListCommand::create(document(), InsertListCommand::UnorderedList), editingState);
         return;
     }
 
@@ -173,7 +185,9 @@
         && visibleEndOfParagraph.deepEquivalent() == endOfEnclosingBlock.deepEquivalent()) {
         // The blockquote doesn't contain anything outside the paragraph, so it can be totally removed.
         Node* splitPoint = enclosingElement->nextSibling();
-        removeNodePreservingChildren(enclosingElement);
+        removeNodePreservingChildren(enclosingElement, editingState);
+        if (editingState->isAborted())
+            return;
         // outdentRegion() assumes it is operating on the first paragraph of an enclosing blockquote, but if there are multiply nested blockquotes and we've
         // just removed one, then this assumption isn't true. By splitting the next containing blockquote after this node, we keep this assumption true
         if (splitPoint) {
@@ -188,11 +202,13 @@
         document().updateLayoutIgnorePendingStylesheets();
         visibleStartOfParagraph = createVisiblePosition(visibleStartOfParagraph.deepEquivalent());
         visibleEndOfParagraph = createVisiblePosition(visibleEndOfParagraph.deepEquivalent());
-        if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleStartOfParagraph))
-            insertNodeAt(HTMLBRElement::create(document()), visibleStartOfParagraph.deepEquivalent());
+        if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleStartOfParagraph)) {
+            insertNodeAt(HTMLBRElement::create(document()), visibleStartOfParagraph.deepEquivalent(), editingState);
+            if (editingState->isAborted())
+                return;
+        }
         if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfParagraph))
-            insertNodeAt(HTMLBRElement::create(document()), visibleEndOfParagraph.deepEquivalent());
-
+            insertNodeAt(HTMLBRElement::create(document()), visibleEndOfParagraph.deepEquivalent(), editingState);
         return;
     }
     RefPtrWillBeRawPtr<Node> splitBlockquoteNode = enclosingElement;
@@ -210,18 +226,20 @@
     if (startOfParagraphToMove.isNull() || endOfParagraphToMove.isNull())
         return;
     RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document());
-    insertNodeBefore(placeholder, splitBlockquoteNode);
-    moveParagraph(startOfParagraphToMove, endOfParagraphToMove, createVisiblePosition(positionBeforeNode(placeholder.get())), ASSERT_NO_EDITING_ABORT, true);
+    insertNodeBefore(placeholder, splitBlockquoteNode, editingState);
+    if (editingState->isAborted())
+        return;
+    moveParagraph(startOfParagraphToMove, endOfParagraphToMove, createVisiblePosition(positionBeforeNode(placeholder.get())), editingState, true);
 }
 
 // FIXME: We should merge this function with ApplyBlockElementCommand::formatSelection
-void IndentOutdentCommand::outdentRegion(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection)
+void IndentOutdentCommand::outdentRegion(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection, EditingState* editingState)
 {
     VisiblePosition endOfCurrentParagraph = endOfParagraph(startOfSelection);
     VisiblePosition endOfLastParagraph = endOfParagraph(endOfSelection);
 
     if (endOfCurrentParagraph.deepEquivalent() == endOfLastParagraph.deepEquivalent()) {
-        outdentParagraph();
+        outdentParagraph(editingState);
         return;
     }
 
@@ -235,7 +253,9 @@
         else
             setEndingSelection(endOfCurrentParagraph);
 
-        outdentParagraph();
+        outdentParagraph(editingState);
+        if (editingState->isAborted())
+            return;
 
         // outdentParagraph could move more than one paragraph if the paragraph
         // is in a list item. As a result, endAfterSelection and endOfNextParagraph
@@ -256,12 +276,15 @@
     if (m_typeOfAction == Indent)
         ApplyBlockElementCommand::formatSelection(startOfSelection, endOfSelection, editingState);
     else
-        outdentRegion(startOfSelection, endOfSelection);
+        outdentRegion(startOfSelection, endOfSelection, editingState);
 }
 
 void IndentOutdentCommand::formatRange(const Position& start, const Position& end, const Position&, RefPtrWillBeRawPtr<HTMLElement>& blockquoteForNextIndent, EditingState* editingState)
 {
-    if (tryIndentingAsListItem(start, end))
+    bool indentingAsListItemResult = tryIndentingAsListItem(start, end, editingState);
+    if (editingState->isAborted())
+        return;
+    if (indentingAsListItemResult)
         blockquoteForNextIndent = nullptr;
     else
         indentIntoBlockquote(start, end, blockquoteForNextIndent, editingState);
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h
index 227aa6cf..45fe406a 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h
@@ -46,9 +46,9 @@
 
     EditAction editingAction() const override { return m_typeOfAction == Indent ? EditActionIndent : EditActionOutdent; }
 
-    void outdentRegion(const VisiblePosition&, const VisiblePosition&);
-    void outdentParagraph();
-    bool tryIndentingAsListItem(const Position&, const Position&);
+    void outdentRegion(const VisiblePosition&, const VisiblePosition&, EditingState*);
+    void outdentParagraph(EditingState*);
+    bool tryIndentingAsListItem(const Position&, const Position&, EditingState*);
     void indentIntoBlockquote(const Position&, const Position&, RefPtrWillBeRawPtr<HTMLElement>&, EditingState*);
 
     void formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection, EditingState*) override;
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index bdfaddb..76c69cd 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -50,21 +50,30 @@
     return listChild;
 }
 
-HTMLUListElement* InsertListCommand::fixOrphanedListChild(Node* node)
+HTMLUListElement* InsertListCommand::fixOrphanedListChild(Node* node, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<HTMLUListElement> listElement = HTMLUListElement::create(document());
-    insertNodeBefore(listElement, node);
-    removeNode(node);
-    appendNode(node, listElement);
+    insertNodeBefore(listElement, node, editingState);
+    if (editingState->isAborted())
+        return nullptr;
+    removeNode(node, editingState);
+    if (editingState->isAborted())
+        return nullptr;
+    appendNode(node, listElement, editingState);
+    if (editingState->isAborted())
+        return nullptr;
     return listElement.get();
 }
 
-PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement> passedList)
+PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement> passedList, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<HTMLElement> list = passedList;
     Element* previousList = ElementTraversal::previousSibling(*list);
-    if (canMergeLists(previousList, list.get()))
-        mergeIdenticalElements(previousList, list);
+    if (canMergeLists(previousList, list.get())) {
+        mergeIdenticalElements(previousList, list, editingState);
+        if (editingState->isAborted())
+            return nullptr;
+    }
 
     if (!list)
         return nullptr;
@@ -75,7 +84,9 @@
 
     RefPtrWillBeRawPtr<HTMLElement> nextList = toHTMLElement(nextSibling);
     if (canMergeLists(list.get(), nextList.get())) {
-        mergeIdenticalElements(list, nextList);
+        mergeIdenticalElements(list, nextList, editingState);
+        if (editingState->isAborted())
+            return nullptr;
         return nextList.release();
     }
     return list.release();
@@ -237,8 +248,12 @@
             }
         }
         if (!listElement) {
-            listElement = fixOrphanedListChild(listChildNode);
-            listElement = mergeWithNeighboringLists(listElement);
+            listElement = fixOrphanedListChild(listChildNode, editingState);
+            if (editingState->isAborted())
+                return false;
+            listElement = mergeWithNeighboringLists(listElement, editingState);
+            if (editingState->isAborted())
+                return false;
         }
         ASSERT(listElement->hasEditableStyle());
         ASSERT(listElement->parentNode()->hasEditableStyle());
@@ -259,20 +274,29 @@
             bool rangeEndIsInList = visiblePositionAfterNode(*listElement).deepEquivalent() == createVisiblePosition(currentSelection.endPosition()).deepEquivalent();
 
             RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document(), listTag);
-            insertNodeBefore(newList, listElement);
+            insertNodeBefore(newList, listElement, editingState);
+            if (editingState->isAborted())
+                return false;
 
             Node* firstChildInList = enclosingListChild(createVisiblePosition(firstPositionInNode(listElement.get())).deepEquivalent().anchorNode(), listElement.get());
             Element* outerBlock = firstChildInList && isBlockFlowElement(*firstChildInList) ? toElement(firstChildInList) : listElement.get();
 
-            moveParagraphWithClones(createVisiblePosition(firstPositionInNode(listElement.get())), createVisiblePosition(lastPositionInNode(listElement.get())), newList.get(), outerBlock);
+            moveParagraphWithClones(createVisiblePosition(firstPositionInNode(listElement.get())), createVisiblePosition(lastPositionInNode(listElement.get())), newList.get(), outerBlock, editingState);
+            if (editingState->isAborted())
+                return false;
 
             // Manually remove listNode because moveParagraphWithClones sometimes leaves it behind in the document.
             // See the bug 33668 and editing/execCommand/insert-list-orphaned-item-with-nested-lists.html.
             // FIXME: This might be a bug in moveParagraphWithClones or deleteSelection.
-            if (listElement && listElement->inDocument())
-                removeNode(listElement);
+            if (listElement && listElement->inDocument()) {
+                removeNode(listElement, editingState);
+                if (editingState->isAborted())
+                    return false;
+            }
 
-            newList = mergeWithNeighboringLists(newList);
+            newList = mergeWithNeighboringLists(newList, editingState);
+            if (editingState->isAborted())
+                return false;
 
             // Restore the start and the end of current selection if they started inside listNode
             // because moveParagraphWithClones could have removed them.
@@ -401,7 +425,7 @@
             return;
 
         if (canMergeLists(previousList, nextList))
-            mergeIdenticalElements(previousList, nextList);
+            mergeIdenticalElements(previousList, nextList, editingState);
 
         return;
     }
@@ -448,7 +472,7 @@
     if (editingState->isAborted())
         return;
 
-    mergeWithNeighboringLists(listElement);
+    mergeWithNeighboringLists(listElement, editingState);
 }
 
 void InsertListCommand::moveParagraphOverPositionIntoEmptyListItem(const VisiblePosition& pos, PassRefPtrWillBeRawPtr<HTMLLIElement> listItemElement, EditingState* editingState)
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h
index c70b5c8..6981ad0 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h
@@ -52,9 +52,9 @@
     void doApply(EditingState*) override;
     EditAction editingAction() const override { return EditActionInsertList; }
 
-    HTMLUListElement* fixOrphanedListChild(Node*);
+    HTMLUListElement* fixOrphanedListChild(Node*, EditingState*);
     bool selectionHasListOfType(const VisibleSelection&, const HTMLQualifiedName&);
-    PassRefPtrWillBeRawPtr<HTMLElement> mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement>);
+    PassRefPtrWillBeRawPtr<HTMLElement> mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement>, EditingState*);
     bool doApplyForSingleParagraph(bool forceCreateList, const HTMLQualifiedName&, Range& currentSelection, EditingState*);
     void unlistifyParagraph(const VisiblePosition& originalStart, HTMLElement* listNode, Node* listChildNode);
     void listifyParagraph(const VisiblePosition& originalStart, const HTMLQualifiedName& listTag, EditingState*);
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index a2297835..36b5938 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -148,7 +148,7 @@
     return parent.release();
 }
 
-void InsertParagraphSeparatorCommand::doApply(EditingState*)
+void InsertParagraphSeparatorCommand::doApply(EditingState* editingState)
 {
     if (!endingSelection().isNonOrphanedCaretOrRange())
         return;
@@ -193,7 +193,7 @@
 
     //---------------------------------------------------------------------
     // Handle special case of typing return on an empty list item
-    if (breakOutOfEmptyListItem())
+    if (breakOutOfEmptyListItem(editingState) || editingState->isAborted())
         return;
 
     //---------------------------------------------------------------------
@@ -410,7 +410,9 @@
             }
         }
 
-        moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert);
+        moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert, editingState);
+        if (editingState->isAborted())
+            return;
     }
 
     // Handle whitespace that occurs after the split
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
index b46dac6..81fca40 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
@@ -120,7 +120,7 @@
     return true;
 }
 
-void InsertTextCommand::doApply(EditingState*)
+void InsertTextCommand::doApply(EditingState* editingState)
 {
     ASSERT(m_text.find('\n') == kNotFound);
 
@@ -133,7 +133,9 @@
         if (performTrivialReplace(m_text, m_selectInsertedText))
             return;
         bool endOfSelectionWasAtStartOfBlock = isStartOfBlock(endingSelection().visibleEnd());
-        deleteSelection(ASSERT_NO_EDITING_ABORT, false, true, false, false);
+        deleteSelection(editingState, false, true, false, false);
+        if (editingState->isAborted())
+            return;
         // deleteSelection eventually makes a new endingSelection out of a Position. If that Position doesn't have
         // a layoutObject (e.g. it is on a <frameset> in the DOM), the VisibleSelection cannot be canonicalized to
         // anything other than NoSelection. The rest of this function requires a real endingSelection, so bail out.
@@ -179,7 +181,9 @@
     if (!isVisuallyEquivalentCandidate(startPosition))
         startPosition = mostForwardCaretPosition(startPosition);
 
-    startPosition = positionAvoidingSpecialElementBoundary(startPosition, ASSERT_NO_EDITING_ABORT);
+    startPosition = positionAvoidingSpecialElementBoundary(startPosition, editingState);
+    if (editingState->isAborted())
+        return;
 
     Position endPosition;
 
diff --git a/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp
index c1d2518..4a3af35 100644
--- a/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp
@@ -36,7 +36,7 @@
     ASSERT(m_fragment);
 }
 
-void MoveSelectionCommand::doApply(EditingState*)
+void MoveSelectionCommand::doApply(EditingState* editingState)
 {
     ASSERT(endingSelection().isNonOrphanedRange());
 
@@ -55,7 +55,9 @@
             pos = Position(pos.computeContainerNode(), pos.offsetInContainerNode() + selectionStart.offsetInContainerNode());
     }
 
-    deleteSelection(ASSERT_NO_EDITING_ABORT, m_smartDelete);
+    deleteSelection(editingState, m_smartDelete);
+    if (editingState->isAborted())
+        return;
 
     // If the node for the destination has been removed as a result of the deletion,
     // set the destination to the ending point after the deletion.
@@ -64,7 +66,9 @@
     if (!pos.inDocument())
         pos = endingSelection().start();
 
-    cleanupAfterDeletion(createVisiblePosition(pos));
+    cleanupAfterDeletion(editingState, createVisiblePosition(pos));
+    if (editingState->isAborted())
+        return;
 
     setEndingSelection(VisibleSelection(pos, endingSelection().affinity(), endingSelection().isDirectional()));
     if (!pos.inDocument()) {
@@ -74,7 +78,7 @@
     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting;
     if (m_smartInsert)
         options |= ReplaceSelectionCommand::SmartReplace;
-    applyCommandToComposite(ReplaceSelectionCommand::create(document(), m_fragment, options));
+    applyCommandToComposite(ReplaceSelectionCommand::create(document(), m_fragment, options), editingState);
 }
 
 EditAction MoveSelectionCommand::editingAction() const
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index eb5383d70..2edc6e3 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -482,7 +482,7 @@
 
 // Style rules that match just inserted elements could change their appearance, like
 // a div inserted into a document with div { display:inline; }.
-void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes& insertedNodes)
+void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes& insertedNodes, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf();
     RefPtrWillBeRawPtr<Node> next = nullptr;
@@ -532,7 +532,9 @@
         if (!inlineStyle || newInlineStyle->isEmpty()) {
             if (isStyleSpanOrSpanWithOnlyStyleAttribute(element) || isEmptyFontTag(element, AllowNonEmptyStyleAttribute)) {
                 insertedNodes.willRemoveNodePreservingChildren(*element);
-                removeNodePreservingChildren(element);
+                removeNodePreservingChildren(element, editingState);
+                if (editingState->isAborted())
+                    return;
                 continue;
             }
             removeElementAttribute(element, styleAttr);
@@ -545,7 +547,9 @@
             && createVisiblePosition(firstPositionInNode(element->parentNode())).deepEquivalent() == createVisiblePosition(firstPositionInNode(element)).deepEquivalent()
             && createVisiblePosition(lastPositionInNode(element->parentNode())).deepEquivalent() == createVisiblePosition(lastPositionInNode(element)).deepEquivalent()) {
             insertedNodes.willRemoveNodePreservingChildren(*element);
-            removeNodePreservingChildren(element);
+            removeNodePreservingChildren(element, editingState);
+            if (editingState->isAborted())
+                return;
             continue;
         }
 
@@ -557,7 +561,9 @@
         if (isLegacyAppleHTMLSpanElement(element)) {
             if (!element->hasChildren()) {
                 insertedNodes.willRemoveNodePreservingChildren(*element);
-                removeNodePreservingChildren(element);
+                removeNodePreservingChildren(element, editingState);
+                if (editingState->isAborted())
+                    return;
                 continue;
             }
             // There are other styles that style rules can give to style spans,
@@ -633,7 +639,7 @@
     return elements.contains(name);
 }
 
-void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes& insertedNodes)
+void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes& insertedNodes, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf();
     RefPtrWillBeRawPtr<Node> next = nullptr;
@@ -649,18 +655,24 @@
 
         HTMLElement& element = toHTMLElement(*node);
         if (isProhibitedParagraphChild(element.localName())) {
-            if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWithTag(positionInParentBeforeNode(element), pTag)))
-                moveElementOutOfAncestor(&element, paragraphElement);
+            if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWithTag(positionInParentBeforeNode(element), pTag))) {
+                moveElementOutOfAncestor(&element, paragraphElement, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
         }
 
         if (isHTMLHeaderElement(&element)) {
-            if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeOfType(positionInParentBeforeNode(element), isHTMLHeaderElement)))
-                moveElementOutOfAncestor(&element, headerElement);
+            if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeOfType(positionInParentBeforeNode(element), isHTMLHeaderElement))) {
+                moveElementOutOfAncestor(&element, headerElement, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
         }
     }
 }
 
-void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element> prpElement, PassRefPtrWillBeRawPtr<Element> prpAncestor)
+void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element> prpElement, PassRefPtrWillBeRawPtr<Element> prpAncestor, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<Element> element = prpElement;
     RefPtrWillBeRawPtr<Element> ancestor = prpAncestor;
@@ -671,18 +683,26 @@
     VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOrAfterNode(element.get()));
     VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPositionInNode(ancestor.get()));
     if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEquivalent()) {
-        removeNode(element);
+        removeNode(element, editingState);
+        if (editingState->isAborted())
+            return;
         if (ancestor->nextSibling())
-            insertNodeBefore(element, ancestor->nextSibling());
+            insertNodeBefore(element, ancestor->nextSibling(), editingState);
         else
-            appendNode(element, ancestor->parentNode());
+            appendNode(element, ancestor->parentNode(), editingState);
+        if (editingState->isAborted())
+            return;
     } else {
         RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(), ancestor.get(), true);
-        removeNode(element);
-        insertNodeBefore(element, nodeToSplitTo);
+        removeNode(element, editingState);
+        if (editingState->isAborted())
+            return;
+        insertNodeBefore(element, nodeToSplitTo, editingState);
+        if (editingState->isAborted())
+            return;
     }
     if (!ancestor->hasChildren())
-        removeNode(ancestor.release());
+        removeNode(ancestor.release(), editingState);
 }
 
 static inline bool nodeHasVisibleLayoutText(Text& text)
@@ -699,7 +719,8 @@
         && !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted), selectTag)
         && !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted), scriptTag)) {
         insertedNodes.willRemoveNode(*lastLeafInserted);
-        removeNode(lastLeafInserted);
+        // Removing a Text node won't dispatch synchronous events.
+        removeNode(lastLeafInserted, ASSERT_NO_EDITING_ABORT);
     }
 
     // We don't have to make sure that firstNodeInserted isn't inside a select or script element, because
@@ -707,7 +728,8 @@
     Node* firstNodeInserted = insertedNodes.firstNodeInserted();
     if (firstNodeInserted && firstNodeInserted->isTextNode() && !nodeHasVisibleLayoutText(toText(*firstNodeInserted))) {
         insertedNodes.willRemoveNode(*firstNodeInserted);
-        removeNode(firstNodeInserted);
+        // Removing a Text node won't dispatch synchronous events.
+        removeNode(firstNodeInserted, ASSERT_NO_EDITING_ABORT);
     }
 }
 
@@ -777,7 +799,7 @@
 // We should remove the Apple-style-span class when we're done, see <rdar://problem/5685600>.
 // We should remove styles from spans that are overridden by all of their children, either here
 // or at copy time.
-void ReplaceSelectionCommand::handleStyleSpans(InsertedNodes& insertedNodes)
+void ReplaceSelectionCommand::handleStyleSpans(InsertedNodes& insertedNodes, EditingState* editingState)
 {
     HTMLSpanElement* wrappingStyleSpan = nullptr;
     // The style span that contains the source document's default style should be at
@@ -819,7 +841,7 @@
 
     if (style->isEmpty() || !wrappingStyleSpan->hasChildren()) {
         insertedNodes.willRemoveNodePreservingChildren(*wrappingStyleSpan);
-        removeNodePreservingChildren(wrappingStyleSpan);
+        removeNodePreservingChildren(wrappingStyleSpan, editingState);
     } else {
         setNodeAttribute(wrappingStyleSpan, styleAttr, AtomicString(style->style()->asText()));
     }
@@ -932,7 +954,10 @@
         return;
 
     ReplacementFragment fragment(&document(), m_documentFragment.get(), selection);
-    if (performTrivialReplace(fragment))
+    bool trivialReplaceResult = performTrivialReplace(fragment, editingState);
+    if (editingState->isAborted())
+        return;
+    if (trivialReplaceResult)
         return;
 
     // We can skip matching the style if the selection is plain text.
@@ -1015,7 +1040,9 @@
         ASSERT(isHTMLBRElement(br));
         // Insert content between the two blockquotes, but remove the br (since it was just a placeholder).
         insertionPos = positionInParentBeforeNode(*br);
-        removeNode(br);
+        removeNode(br, editingState);
+        if (editingState->isAborted())
+            return;
     }
 
     // Inserting content could cause whitespace to collapse, e.g. inserting <div>foo</div> into hello^ world.
@@ -1148,8 +1175,11 @@
 
     removeUnrenderedTextNodesAtEnds(insertedNodes);
 
-    if (!handledStyleSpans)
-        handleStyleSpans(insertedNodes);
+    if (!handledStyleSpans) {
+        handleStyleSpans(insertedNodes, editingState);
+        if (editingState->isAborted())
+            return;
+    }
 
     // Mutation events (bug 20161) may have already removed the inserted content
     if (!insertedNodes.firstNodeInserted() || !insertedNodes.firstNodeInserted()->inDocument())
@@ -1170,16 +1200,24 @@
     if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText)))) {
         RefPtrWillBeRawPtr<ContainerNode> parent = endBR->parentNode();
         insertedNodes.willRemoveNode(*endBR);
-        removeNode(endBR);
+        removeNode(endBR, editingState);
+        if (editingState->isAborted())
+            return;
         if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) {
             insertedNodes.willRemoveNode(*nodeToRemove);
-            removeNode(nodeToRemove);
+            removeNode(nodeToRemove, editingState);
+            if (editingState->isAborted())
+                return;
         }
     }
 
-    makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes);
+    makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes, editingState);
+    if (editingState->isAborted())
+        return;
 
-    removeRedundantStylesAndKeepStyleSpanInline(insertedNodes);
+    removeRedundantStylesAndKeepStyleSpanInline(insertedNodes, editingState);
+    if (editingState->isAborted())
+        return;
 
     if (m_sanitizeFragment)
         applyCommandToComposite(SimplifyMarkupCommand::create(document(), insertedNodes.firstNodeInserted(), insertedNodes.pastLastLeaf()));
@@ -1268,7 +1306,7 @@
     if (plainTextFragment)
         m_matchStyle = false;
 
-    completeHTMLReplacement(lastPositionToSelect);
+    completeHTMLReplacement(lastPositionToSelect, editingState);
 }
 
 bool ReplaceSelectionCommand::shouldRemoveEndBR(HTMLBRElement* endBR, const VisiblePosition& originalVisPosBeforeEndBR)
@@ -1362,7 +1400,7 @@
     }
 }
 
-void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositionToSelect)
+void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositionToSelect, EditingState* editingState)
 {
     Position start = positionAtStartOfInsertedContent().deepEquivalent();
     Position end = positionAtEndOfInsertedContent().deepEquivalent();
@@ -1381,7 +1419,9 @@
         if (lastPositionToSelect.isNotNull())
             end = lastPositionToSelect;
 
-        mergeTextNodesAroundPosition(start, end);
+        mergeTextNodesAroundPosition(start, end, editingState);
+        if (editingState->isAborted())
+            return;
     } else if (lastPositionToSelect.isNotNull()) {
         start = end = lastPositionToSelect;
     } else {
@@ -1397,7 +1437,7 @@
         setEndingSelection(VisibleSelection(end, SelDefaultAffinity, endingSelection().isDirectional()));
 }
 
-void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, Position& positionOnlyToBeUpdated)
+void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, Position& positionOnlyToBeUpdated, EditingState* editingState)
 {
     bool positionIsOffsetInAnchor = position.isOffsetInAnchor();
     bool positionOnlyToBeUpdatedIsOffsetInAnchor = positionOnlyToBeUpdated.isOffsetInAnchor();
@@ -1435,7 +1475,9 @@
             updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous);
         }
 
-        removeNode(previous);
+        removeNode(previous, editingState);
+        if (editingState->isAborted())
+            return;
     }
     if (text->nextSibling() && text->nextSibling()->isTextNode()) {
         RefPtrWillBeRawPtr<Text> next = toText(text->nextSibling());
@@ -1450,7 +1492,9 @@
         else
             updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next);
 
-        removeNode(next);
+        removeNode(next, editingState);
+        if (editingState->isAborted())
+            return;
     }
 }
 
@@ -1517,7 +1561,7 @@
 // directly into the text node that holds the selection.  This is much faster than the generalized code in
 // ReplaceSelectionCommand, and works around <https://bugs.webkit.org/show_bug.cgi?id=6148> since we don't
 // split text nodes.
-bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& fragment)
+bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& fragment, EditingState* editingState)
 {
     if (!fragment.firstChild() || fragment.firstChild() != fragment.lastChild() || !fragment.firstChild()->isTextNode())
         return false;
@@ -1540,8 +1584,11 @@
         return false;
 
     if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBRElement(*nodeAfterInsertionPos)
-        && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), createVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get()))))
-        removeNodeAndPruneAncestors(nodeAfterInsertionPos.get());
+        && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), createVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) {
+        removeNodeAndPruneAncestors(nodeAfterInsertionPos.get(), editingState);
+        if (editingState->isAborted())
+            return false;
+    }
 
     m_startOfInsertedRange = start;
     m_endOfInsertedRange = end;
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h
index 4a36cb3..6467dd6 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h
@@ -93,20 +93,20 @@
 
     void removeUnrenderedTextNodesAtEnds(InsertedNodes&);
 
-    void removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes&);
-    void makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes&);
-    void moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element> ancestor);
-    void handleStyleSpans(InsertedNodes&);
+    void removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes&, EditingState*);
+    void makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes&, EditingState*);
+    void moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element> ancestor, EditingState*);
+    void handleStyleSpans(InsertedNodes&, EditingState*);
 
     VisiblePosition positionAtStartOfInsertedContent() const;
     VisiblePosition positionAtEndOfInsertedContent() const;
 
     bool shouldPerformSmartReplace() const;
     void addSpacesForSmartReplace();
-    void completeHTMLReplacement(const Position& lastPositionToSelect);
-    void mergeTextNodesAroundPosition(Position&, Position& positionOnlyToBeUpdated);
+    void completeHTMLReplacement(const Position& lastPositionToSelect, EditingState*);
+    void mergeTextNodesAroundPosition(Position&, Position& positionOnlyToBeUpdated, EditingState*);
 
-    bool performTrivialReplace(const ReplacementFragment&);
+    bool performTrivialReplace(const ReplacementFragment&, EditingState*);
 
     Position m_startOfInsertedContent;
     Position m_endOfInsertedContent;
diff --git a/third_party/WebKit/Source/core/editing/commands/TextInsertionBaseCommand.h b/third_party/WebKit/Source/core/editing/commands/TextInsertionBaseCommand.h
index 990a89b..f0e6add3 100644
--- a/third_party/WebKit/Source/core/editing/commands/TextInsertionBaseCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/TextInsertionBaseCommand.h
@@ -49,20 +49,22 @@
 // LineOperation should define member function "opeartor (size_t lineOffset, size_t lineLength, bool isLastLine)".
 // lienLength doesn't include the newline character. So the value of lineLength could be 0.
 template <class LineOperation>
-void forEachLineInString(const String& string, const LineOperation& operation)
+void forEachLineInString(const String& string, const LineOperation& operation, EditingState* editingState)
 {
     unsigned offset = 0;
     size_t newline;
     while ((newline = string.find('\n', offset)) != kNotFound) {
-        operation(offset, newline - offset, false);
+        operation(offset, newline - offset, false, editingState);
+        if (editingState->isAborted())
+            return;
         offset = newline + 1;
     }
     if (!offset) {
-        operation(0, string.length(), true);
+        operation(0, string.length(), true, editingState);
     } else {
         unsigned length = string.length();
         if (length != offset)
-            operation(offset, length - offset, true);
+            operation(offset, length - offset, true, editingState);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index d2dcf2565..58d157d3 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -56,14 +56,20 @@
     , m_text(text)
     { }
 
-    void operator()(size_t lineOffset, size_t lineLength, bool isLastLine) const
+    void operator()(size_t lineOffset, size_t lineLength, bool isLastLine, EditingState* editingState) const
     {
         if (isLastLine) {
-            if (!lineOffset || lineLength > 0)
-                m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), m_selectInsertedText);
+            if (!lineOffset || lineLength > 0) {
+                m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), m_selectInsertedText, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
         } else {
-            if (lineLength > 0)
-                m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), false);
+            if (lineLength > 0) {
+                m_typingCommand->insertTextRunWithoutNewlines(m_text.substring(lineOffset, lineLength), false, editingState);
+                if (editingState->isAborted())
+                    return;
+            }
             m_typingCommand->insertParagraphSeparator();
         }
     }
@@ -190,7 +196,9 @@
         lastTypingCommand->setCompositionType(compositionType);
         lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
         lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
-        lastTypingCommand->insertText(newText, options & SelectInsertedText);
+        EditingState editingState;
+        lastTypingCommand->insertText(newText, options & SelectInsertedText, &editingState);
+        // Nothing to do even if the command was aborted.
         return;
     }
 
@@ -277,7 +285,7 @@
         insertParagraphSeparatorInQuotedContent();
         return;
     case InsertText:
-        insertText(m_textToInsert, m_selectInsertedText);
+        insertText(m_textToInsert, m_selectInsertedText, editingState);
         return;
     }
 
@@ -334,7 +342,7 @@
     frame->editor().appliedEditing(this);
 }
 
-void TypingCommand::insertText(const String &text, bool selectInsertedText)
+void TypingCommand::insertText(const String &text, bool selectInsertedText, EditingState* editingState)
 {
     // FIXME: Need to implement selectInsertedText for cases where more than one insert is involved.
     // This requires support from insertTextRunWithoutNewlines and insertParagraphSeparator for extending
@@ -342,16 +350,17 @@
     // select what's inserted, but there's no way to "extend selection" to include both an old selection
     // that ends just before where we want to insert text and the newly inserted text.
     TypingCommandLineOperation operation(this, selectInsertedText, text);
-    forEachLineInString(text, operation);
+    forEachLineInString(text, operation, editingState);
 }
 
-void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText)
+void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText, EditingState* editingState)
 {
     RefPtrWillBeRawPtr<InsertTextCommand> command = InsertTextCommand::create(document(), text, selectInsertedText,
         m_compositionType == TextCompositionNone ? InsertTextCommand::RebalanceLeadingAndTrailingWhitespaces : InsertTextCommand::RebalanceAllWhitespaces);
 
-    applyCommandToComposite(command, endingSelection());
-
+    applyCommandToComposite(command, endingSelection(), editingState);
+    if (editingState->isAborted())
+        return;
     typingAddedToOpenCommand(InsertText);
 }
 
@@ -386,7 +395,7 @@
     typingAddedToOpenCommand(InsertParagraphSeparatorInQuotedContent);
 }
 
-bool TypingCommand::makeEditableRootEmpty()
+bool TypingCommand::makeEditableRootEmpty(EditingState* editingState)
 {
     Element* root = endingSelection().rootEditableElement();
     if (!root || !root->hasChildren())
@@ -400,8 +409,11 @@
         }
     }
 
-    while (Node* child = root->firstChild())
-        removeNode(child);
+    while (Node* child = root->firstChild()) {
+        removeNode(child, editingState);
+        if (editingState->isAborted())
+            return false;
+    }
 
     addBlockPlaceholderIfNeeded(root);
     setEndingSelection(VisibleSelection(firstPositionInNode(root), TextAffinity::Downstream, endingSelection().isDirectional()));
@@ -428,7 +440,10 @@
     case CaretSelection: {
         // After breaking out of an empty mail blockquote, we still want continue with the deletion
         // so actual content will get deleted, and not just the quote style.
-        if (breakOutOfEmptyMailBlockquotedParagraph())
+        bool breakOutResult = breakOutOfEmptyMailBlockquotedParagraph(editingState);
+        if (editingState->isAborted())
+            return;
+        if (breakOutResult)
             typingAddedToOpenCommand(DeleteKey);
 
         m_smartDelete = false;
@@ -442,15 +457,20 @@
         VisiblePosition visibleStart(endingSelection().visibleStart());
         if (previousPositionOf(visibleStart, CannotCrossEditingBoundary).isNull()) {
             // When the caret is at the start of the editable area in an empty list item, break out of the list item.
-            if (breakOutOfEmptyListItem()) {
+            bool breakOutOfEmptyListItemResult = breakOutOfEmptyListItem(editingState);
+            if (editingState->isAborted())
+                return;
+            if (breakOutOfEmptyListItemResult) {
                 typingAddedToOpenCommand(DeleteKey);
                 return;
             }
             // When there are no visible positions in the editing root, delete its entire contents.
-            if (nextPositionOf(visibleStart, CannotCrossEditingBoundary).isNull() && makeEditableRootEmpty()) {
+            if (nextPositionOf(visibleStart, CannotCrossEditingBoundary).isNull() && makeEditableRootEmpty(editingState)) {
                 typingAddedToOpenCommand(DeleteKey);
                 return;
             }
+            if (editingState->isAborted())
+                return;
         }
 
         // If we have a caret selection at the beginning of a cell, we have nothing to do.
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
index d015e60..780905c 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
@@ -67,8 +67,8 @@
     static void insertParagraphSeparatorInQuotedContent(Document&);
     static void closeTyping(LocalFrame*);
 
-    void insertText(const String &text, bool selectInsertedText);
-    void insertTextRunWithoutNewlines(const String &text, bool selectInsertedText);
+    void insertText(const String &text, bool selectInsertedText, EditingState*);
+    void insertTextRunWithoutNewlines(const String &text, bool selectInsertedText, EditingState*);
     void insertLineBreak();
     void insertParagraphSeparatorInQuotedContent();
     void insertParagraphSeparator();
@@ -109,7 +109,7 @@
     void updatePreservesTypingStyle(ETypingCommand);
     void markMisspellingsAfterTyping(ETypingCommand);
     void typingAddedToOpenCommand(ETypingCommand);
-    bool makeEditableRootEmpty();
+    bool makeEditableRootEmpty(EditingState*);
 
     void updateCommandTypeOfOpenCommand(ETypingCommand typingCommand) { m_commandType = typingCommand; }
     ETypingCommand commandTypeOfOpenCommand() const { return m_commandType; }
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index b2fec3f..9e5e64b 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -4,11 +4,13 @@
 
 #include "core/frame/Deprecation.h"
 
+#include "core/dom/Document.h"
+#include "core/dom/ExecutionContext.h"
 #include "core/frame/FrameConsole.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
-#include "core/frame/UseCounter.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/workers/WorkerGlobalScope.h"
 
 namespace blink {
 
@@ -56,10 +58,298 @@
 {
     switch (unresolvedProperty) {
     case CSSPropertyWebkitBackgroundComposite:
-        return UseCounter::willBeRemoved("'-webkit-background-composite'", 51, "6607299456008192");
+        return willBeRemoved("'-webkit-background-composite'", 51, "6607299456008192");
     default:
         return emptyString();
     }
 }
 
+void Deprecation::countDeprecation(const LocalFrame* frame, UseCounter::Feature feature)
+{
+    if (!frame)
+        return;
+    FrameHost* host = frame->host();
+    if (!host)
+        return;
+
+    if (!host->useCounter().hasRecordedMeasurement(feature)) {
+        host->useCounter().recordMeasurement(feature);
+        ASSERT(!deprecationMessage(feature).isEmpty());
+        frame->console().addMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, deprecationMessage(feature)));
+    }
+}
+
+void Deprecation::countDeprecation(ExecutionContext* context, UseCounter::Feature feature)
+{
+    if (!context)
+        return;
+    if (context->isDocument()) {
+        Deprecation::countDeprecation(*toDocument(context), feature);
+        return;
+    }
+    if (context->isWorkerGlobalScope())
+        toWorkerGlobalScope(context)->countDeprecation(feature);
+}
+
+void Deprecation::countDeprecation(const Document& document, UseCounter::Feature feature)
+{
+    Deprecation::countDeprecation(document.frame(), feature);
+}
+
+void Deprecation::countDeprecationIfNotPrivateScript(v8::Isolate* isolate, ExecutionContext* context, UseCounter::Feature feature)
+{
+    if (DOMWrapperWorld::current(isolate).isPrivateScriptIsolatedWorld())
+        return;
+    Deprecation::countDeprecation(context, feature);
+}
+
+static const char* milestoneString(int milestone)
+{
+    switch (milestone) {
+    case 50:
+        return "M50, around April 2016";
+    case 51:
+        return "M51, around June 2016";
+    case 52:
+        return "M52, around August 2016";
+    case 53:
+        return "M53, around September 2016";
+    }
+
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+static String replacedBy(const char* feature, const char* replacement)
+{
+    return String::format("%s is deprecated. Please use %s instead.", feature, replacement);
+}
+
+String Deprecation::willBeRemoved(const char* feature, int milestone, const char* details)
+{
+    return String::format("%s is deprecated and will be removed in %s. See https://www.chromestatus.com/features/%s for more details.", feature, milestoneString(milestone), details);
+}
+
+static String replacedWillBeRemoved(const char* feature, const char* replacement, int milestone, const char* details)
+{
+    return String::format("%s is deprecated and will be removed in %s. Please use %s instead. See https://www.chromestatus.com/features/%s for more details.", feature, milestoneString(milestone), replacement, details);
+}
+
+String Deprecation::deprecationMessage(UseCounter::Feature feature)
+{
+    switch (feature) {
+    // Quota
+    case UseCounter::PrefixedStorageInfo:
+        return replacedBy("'window.webkitStorageInfo'", "'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage'");
+
+    // Keyboard Event (DOM Level 3)
+    case UseCounter::KeyboardEventKeyLocation:
+        return replacedWillBeRemoved("'KeyboardEvent.keyLocation'", "'KeyboardEvent.location'", 50, "4997403308457984");
+
+    case UseCounter::ConsoleMarkTimeline:
+        return replacedBy("'console.markTimeline'", "'console.timeStamp'");
+
+    case UseCounter::FileError:
+        return "FileError is deprecated. Please use the 'name' or 'message' attributes of DOMError rather than 'code'.";
+
+    case UseCounter::CSSStyleSheetInsertRuleOptionalArg:
+        return "Calling CSSStyleSheet.insertRule() with one argument is deprecated. Please pass the index argument as well: insertRule(x, 0).";
+
+    case UseCounter::PrefixedVideoSupportsFullscreen:
+        return replacedBy("'HTMLVideoElement.webkitSupportsFullscreen'", "'Document.fullscreenEnabled'");
+
+    case UseCounter::PrefixedVideoDisplayingFullscreen:
+        return replacedBy("'HTMLVideoElement.webkitDisplayingFullscreen'", "'Document.fullscreenElement'");
+
+    case UseCounter::PrefixedVideoEnterFullscreen:
+        return replacedBy("'HTMLVideoElement.webkitEnterFullscreen()'", "'Element.requestFullscreen()'");
+
+    case UseCounter::PrefixedVideoExitFullscreen:
+        return replacedBy("'HTMLVideoElement.webkitExitFullscreen()'", "'Document.exitFullscreen()'");
+
+    case UseCounter::PrefixedVideoEnterFullScreen:
+        return replacedBy("'HTMLVideoElement.webkitEnterFullScreen()'", "'Element.requestFullscreen()'");
+
+    case UseCounter::PrefixedVideoExitFullScreen:
+        return replacedBy("'HTMLVideoElement.webkitExitFullScreen()'", "'Document.exitFullscreen()'");
+
+    case UseCounter::PrefixedIndexedDB:
+        return replacedBy("'webkitIndexedDB'", "'indexedDB'");
+
+    case UseCounter::PrefixedIDBCursorConstructor:
+        return replacedBy("'webkitIDBCursor'", "'IDBCursor'");
+
+    case UseCounter::PrefixedIDBDatabaseConstructor:
+        return replacedBy("'webkitIDBDatabase'", "'IDBDatabase'");
+
+    case UseCounter::PrefixedIDBFactoryConstructor:
+        return replacedBy("'webkitIDBFactory'", "'IDBFactory'");
+
+    case UseCounter::PrefixedIDBIndexConstructor:
+        return replacedBy("'webkitIDBIndex'", "'IDBIndex'");
+
+    case UseCounter::PrefixedIDBKeyRangeConstructor:
+        return replacedBy("'webkitIDBKeyRange'", "'IDBKeyRange'");
+
+    case UseCounter::PrefixedIDBObjectStoreConstructor:
+        return replacedBy("'webkitIDBObjectStore'", "'IDBObjectStore'");
+
+    case UseCounter::PrefixedIDBRequestConstructor:
+        return replacedBy("'webkitIDBRequest'", "'IDBRequest'");
+
+    case UseCounter::PrefixedIDBTransactionConstructor:
+        return replacedBy("'webkitIDBTransaction'", "'IDBTransaction'");
+
+    case UseCounter::PrefixedRequestAnimationFrame:
+        return "'webkitRequestAnimationFrame' is vendor-specific. Please use the standard 'requestAnimationFrame' instead.";
+
+    case UseCounter::PrefixedCancelAnimationFrame:
+        return "'webkitCancelAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead.";
+
+    case UseCounter::PrefixedCancelRequestAnimationFrame:
+        return "'webkitCancelRequestAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead.";
+
+    case UseCounter::SyncXHRWithCredentials:
+        return "Setting 'XMLHttpRequest.withCredentials' for synchronous requests is deprecated.";
+
+    case UseCounter::PictureSourceSrc:
+        return "<source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead.";
+
+    case UseCounter::ConsoleTimeline:
+        return replacedBy("'console.timeline'", "'console.time'");
+
+    case UseCounter::ConsoleTimelineEnd:
+        return replacedBy("'console.timelineEnd'", "'console.timeEnd'");
+
+    case UseCounter::XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload:
+        return "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.";
+
+    case UseCounter::GetMatchedCSSRules:
+        return "'getMatchedCSSRules()' is deprecated. For more help, check https://code.google.com/p/chromium/issues/detail?id=437569#c2";
+
+    case UseCounter::PrefixedImageSmoothingEnabled:
+        return replacedBy("'CanvasRenderingContext2D.webkitImageSmoothingEnabled'", "'CanvasRenderingContext2D.imageSmoothingEnabled'");
+
+    case UseCounter::AudioListenerDopplerFactor:
+        return "dopplerFactor is deprecated and will be removed in M45 when all doppler effects are removed";
+
+    case UseCounter::AudioListenerSpeedOfSound:
+        return "speedOfSound is deprecated and will be removed in M45 when all doppler effects are removed";
+
+    case UseCounter::AudioListenerSetVelocity:
+        return "setVelocity() is deprecated and will be removed in M45 when all doppler effects are removed";
+
+    case UseCounter::PrefixedWindowURL:
+        return replacedBy("'webkitURL'", "'URL'");
+
+    case UseCounter::PrefixedAudioContext:
+        return replacedBy("'webkitAudioContext'", "'AudioContext'");
+
+    case UseCounter::PrefixedOfflineAudioContext:
+        return replacedBy("'webkitOfflineAudioContext'", "'OfflineAudioContext'");
+
+    case UseCounter::RangeExpand:
+        return replacedBy("'Range.expand()'", "'Selection.modify()'");
+
+    case UseCounter::PrefixedMediaAddKey:
+    case UseCounter::PrefixedMediaGenerateKeyRequest:
+    case UseCounter::PrefixedMediaCancelKeyRequest:
+        return "The prefixed Encrypted Media Extensions APIs are deprecated. Please use 'navigator.requestMediaKeySystemAccess()' instead.";
+
+    case UseCounter::CanPlayTypeKeySystem:
+        return replacedBy("canPlayType()'s 'keySystem' parameter", "'navigator.requestMediaKeySystemAccess()'");
+
+    // Powerful features on insecure origins (https://goo.gl/rStTGz)
+    case UseCounter::DeviceMotionInsecureOrigin:
+        return "The devicemotion event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
+
+    case UseCounter::DeviceOrientationInsecureOrigin:
+        return "The deviceorientation event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
+
+    case UseCounter::DeviceOrientationAbsoluteInsecureOrigin:
+        return "The deviceorientationabsolute event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
+
+    case UseCounter::GeolocationInsecureOrigin:
+        // TODO(jww): This message should be made less ambigous after WebView
+        // is fixed so geolocation can be removed there. After that, this
+        // should be updated to read similarly to GetUserMediaInsecureOrigin's
+        // message.
+        return "getCurrentPosition() and watchPosition() are deprecated on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
+
+    case UseCounter::GetUserMediaInsecureOrigin:
+        return "getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
+
+    case UseCounter::EncryptedMediaInsecureOrigin:
+        return "requestMediaKeySystemAccess() is deprecated on insecure origins in the specification. Support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
+
+    case UseCounter::ElementCreateShadowRootMultiple:
+        return "Calling Element.createShadowRoot() for an element which already hosts a shadow root is deprecated. See https://www.chromestatus.com/features/4668884095336448 for more details.";
+
+    case UseCounter::ElementCreateShadowRootMultipleWithUserAgentShadowRoot:
+        return "Calling Element.createShadowRoot() for an element which already hosts a user-agent shadow root is deprecated. See https://www.chromestatus.com/features/4668884095336448 for more details.";
+
+    case UseCounter::CSSDeepCombinator:
+        return "/deep/ combinator is deprecated. See https://www.chromestatus.com/features/6750456638341120 for more details.";
+
+    case UseCounter::CSSSelectorPseudoShadow:
+        return "::shadow pseudo-element is deprecated. See https://www.chromestatus.com/features/6750456638341120 for more details.";
+
+    case UseCounter::SVGSMILElementInDocument:
+    case UseCounter::SVGSMILAnimationInImageRegardlessOfCache:
+        return "SVG's SMIL animations (<animate>, <set>, etc.) are deprecated and will be removed. Please use CSS animations or Web animations instead.";
+
+    case UseCounter::PrefixedPerformanceClearResourceTimings:
+        return replacedBy("'Performance.webkitClearResourceTimings'", "'Performance.clearResourceTimings'");
+
+    case UseCounter::PrefixedPerformanceSetResourceTimingBufferSize:
+        return replacedBy("'Performance.webkitSetResourceTimingBufferSize'", "'Performance.setResourceTimingBufferSize'");
+
+    case UseCounter::PrefixedPerformanceResourceTimingBufferFull:
+        return replacedBy("'Performance.onwebkitresourcetimingbufferfull'", "'Performance.onresourcetimingbufferfull'");
+
+    case UseCounter::BluetoothDeviceInstanceId:
+        return replacedBy("'BluetoothDevice.instanceID'", "'BluetoothDevice.id'");
+
+    case UseCounter::BluetoothDeviceConnectGATT:
+        return replacedWillBeRemoved("'BluetoothDevice.connectGATT'", "'BluetoothDevice.gatt.connect'", 52, "5264933985976320");
+
+    case UseCounter::V8SVGElement_OffsetParent_AttributeGetter:
+        return willBeRemoved("'SVGElement.offsetParent'", 50, "5724912467574784");
+
+    case UseCounter::V8SVGElement_OffsetTop_AttributeGetter:
+        return willBeRemoved("'SVGElement.offsetTop'", 50, "5724912467574784");
+
+    case UseCounter::V8SVGElement_OffsetLeft_AttributeGetter:
+        return willBeRemoved("'SVGElement.offsetLeft'", 50, "5724912467574784");
+
+    case UseCounter::V8SVGElement_OffsetWidth_AttributeGetter:
+        return willBeRemoved("'SVGElement.offsetWidth'", 50, "5724912467574784");
+
+    case UseCounter::V8SVGElement_OffsetHeight_AttributeGetter:
+        return willBeRemoved("'SVGElement.offsetHeight'", 50, "5724912467574784");
+
+    case UseCounter::MediaStreamTrackGetSources:
+        return "MediaStreamTrack.getSources is deprecated. See https://www.chromestatus.com/feature/4765305641369600 for more details.";
+
+    case UseCounter::DocumentDefaultCharset:
+        return willBeRemoved("'Document.defaultCharset'", 50, "6217124578066432");
+
+    case UseCounter::V8TouchEvent_InitTouchEvent_Method:
+        return replacedWillBeRemoved("'TouchEvent.initTouchEvent'", "the TouchEvent constructor", 53, "5730982598541312");
+
+    case UseCounter::RTCPeerConnectionCreateAnswerLegacyNoFailureCallback:
+        return "RTCPeerConnection.CreateAnswer without a failure callback is deprecated. The failure callback will be a required parameter in M50. See https://www.chromestatus.com/feature/5663288008376320 for more details";
+
+    case UseCounter::RTCPeerConnectionCreateOfferLegacyNoFailureCallback:
+        return "RTCPeerConnection.CreateOffer without a failure callback is deprecated. The failure callback will be a required parameter in M50. See https://www.chromestatus.com/feature/5663288008376320 for more details";
+
+    case UseCounter::ObjectObserve:
+        return willBeRemoved("'Object.observe'", 50, "6147094632988672");
+
+    // Features that aren't deprecated don't have a deprecation message.
+    default:
+        return String();
+    }
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.h b/third_party/WebKit/Source/core/frame/Deprecation.h
index beb24bb..42193fc 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.h
+++ b/third_party/WebKit/Source/core/frame/Deprecation.h
@@ -6,6 +6,8 @@
 #define Deprecation_h
 
 #include "core/CSSPropertyNames.h"
+#include "core/CoreExport.h"
+#include "core/frame/UseCounter.h"
 #include "wtf/BitVector.h"
 #include "wtf/Noncopyable.h"
 
@@ -13,7 +15,7 @@
 
 class LocalFrame;
 
-class Deprecation {
+class CORE_EXPORT Deprecation {
     DISALLOW_NEW();
     WTF_MAKE_NONCOPYABLE(Deprecation);
 public:
@@ -23,6 +25,26 @@
     static void warnOnDeprecatedProperties(const LocalFrame*, CSSPropertyID unresolvedProperty);
     void clearSuppression();
 
+    // "countDeprecation" sets the bit for this feature to 1, and sends a deprecation
+    // warning to the console. Repeated calls are ignored.
+    //
+    // Be considerate to developers' consoles: features should only send
+    // deprecation warnings when we're actively interested in removing them from
+    // the platform.
+    //
+    // For shared workers and service workers, the ExecutionContext* overload
+    // doesn't count the usage but only sends a console warning.
+    static void countDeprecation(const LocalFrame*, UseCounter::Feature);
+    static void countDeprecation(ExecutionContext*, UseCounter::Feature);
+    static void countDeprecation(const Document&, UseCounter::Feature);
+    // Use countDeprecationIfNotPrivateScript() instead of countDeprecation()
+    // if you don't want to count metrics in private scripts. You should use
+    // countDeprecationIfNotPrivateScript() in a binding layer.
+    static void countDeprecationIfNotPrivateScript(v8::Isolate*, ExecutionContext*, UseCounter::Feature);
+    static String deprecationMessage(UseCounter::Feature);
+
+    static String willBeRemoved(const char* feature, int milestone, const char* details);
+
 protected:
     void suppress(CSSPropertyID unresolvedProperty);
     bool isSuppressed(CSSPropertyID unresolvedProperty);
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp
index 86e31a8..ff3df3e 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -29,6 +29,7 @@
 #include "core/css/StyleSheetContents.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/FrameConsole.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
@@ -646,7 +647,7 @@
     if (!host)
         return;
 
-    ASSERT(deprecationMessage(feature).isEmpty());
+    ASSERT(Deprecation::deprecationMessage(feature).isEmpty());
     host->useCounter().recordMeasurement(feature);
 }
 
@@ -699,45 +700,6 @@
     UseCounter::count(context, feature);
 }
 
-void UseCounter::countDeprecation(const LocalFrame* frame, Feature feature)
-{
-    if (!frame)
-        return;
-    FrameHost* host = frame->host();
-    if (!host)
-        return;
-
-    if (!host->useCounter().hasRecordedMeasurement(feature)) {
-        host->useCounter().recordMeasurement(feature);
-        ASSERT(!deprecationMessage(feature).isEmpty());
-        frame->console().addMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, deprecationMessage(feature)));
-    }
-}
-
-void UseCounter::countDeprecation(ExecutionContext* context, Feature feature)
-{
-    if (!context)
-        return;
-    if (context->isDocument()) {
-        UseCounter::countDeprecation(*toDocument(context), feature);
-        return;
-    }
-    if (context->isWorkerGlobalScope())
-        toWorkerGlobalScope(context)->countDeprecation(feature);
-}
-
-void UseCounter::countDeprecation(const Document& document, Feature feature)
-{
-    UseCounter::countDeprecation(document.frame(), feature);
-}
-
-void UseCounter::countDeprecationIfNotPrivateScript(v8::Isolate* isolate, ExecutionContext* context, Feature feature)
-{
-    if (DOMWrapperWorld::current(isolate).isPrivateScriptIsolatedWorld())
-        return;
-    UseCounter::countDeprecation(context, feature);
-}
-
 void UseCounter::countCrossOriginIframe(const Document& document, Feature feature)
 {
     Frame* frame = document.frame();
@@ -750,256 +712,6 @@
         count(frame, feature);
 }
 
-// TODO(nainar): Migrate all console message functions to Deprecation
-static const char* milestoneString(int milestone)
-{
-    switch (milestone) {
-    case 50:
-        return "M50, around April 2016";
-    case 51:
-        return "M51, around June 2016";
-    case 52:
-        return "M52, around August 2016";
-    case 53:
-        return "M53, around September 2016";
-    }
-
-    ASSERT_NOT_REACHED();
-    return nullptr;
-}
-
-static String replacedBy(const char* feature, const char* replacement)
-{
-    return String::format("%s is deprecated. Please use %s instead.", feature, replacement);
-}
-
-String UseCounter::willBeRemoved(const char* feature, int milestone, const char* details)
-{
-    return String::format("%s is deprecated and will be removed in %s. See https://www.chromestatus.com/features/%s for more details.", feature, milestoneString(milestone), details);
-}
-
-static String replacedWillBeRemoved(const char* feature, const char* replacement, int milestone, const char* details)
-{
-    return String::format("%s is deprecated and will be removed in %s. Please use %s instead. See https://www.chromestatus.com/features/%s for more details.", feature, milestoneString(milestone), replacement, details);
-}
-
-String UseCounter::deprecationMessage(Feature feature)
-{
-    switch (feature) {
-    // Quota
-    case PrefixedStorageInfo:
-        return replacedBy("'window.webkitStorageInfo'", "'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage'");
-
-    // Keyboard Event (DOM Level 3)
-    case KeyboardEventKeyLocation:
-        return replacedWillBeRemoved("'KeyboardEvent.keyLocation'", "'KeyboardEvent.location'", 50, "4997403308457984");
-
-    case ConsoleMarkTimeline:
-        return replacedBy("'console.markTimeline'", "'console.timeStamp'");
-
-    case FileError:
-        return "FileError is deprecated. Please use the 'name' or 'message' attributes of DOMError rather than 'code'.";
-
-    case CSSStyleSheetInsertRuleOptionalArg:
-        return "Calling CSSStyleSheet.insertRule() with one argument is deprecated. Please pass the index argument as well: insertRule(x, 0).";
-
-    case PrefixedVideoSupportsFullscreen:
-        return replacedBy("'HTMLVideoElement.webkitSupportsFullscreen'", "'Document.fullscreenEnabled'");
-
-    case PrefixedVideoDisplayingFullscreen:
-        return replacedBy("'HTMLVideoElement.webkitDisplayingFullscreen'", "'Document.fullscreenElement'");
-
-    case PrefixedVideoEnterFullscreen:
-        return replacedBy("'HTMLVideoElement.webkitEnterFullscreen()'", "'Element.requestFullscreen()'");
-
-    case PrefixedVideoExitFullscreen:
-        return replacedBy("'HTMLVideoElement.webkitExitFullscreen()'", "'Document.exitFullscreen()'");
-
-    case PrefixedVideoEnterFullScreen:
-        return replacedBy("'HTMLVideoElement.webkitEnterFullScreen()'", "'Element.requestFullscreen()'");
-
-    case PrefixedVideoExitFullScreen:
-        return replacedBy("'HTMLVideoElement.webkitExitFullScreen()'", "'Document.exitFullscreen()'");
-
-    case PrefixedIndexedDB:
-        return replacedBy("'webkitIndexedDB'", "'indexedDB'");
-
-    case PrefixedIDBCursorConstructor:
-        return replacedBy("'webkitIDBCursor'", "'IDBCursor'");
-
-    case PrefixedIDBDatabaseConstructor:
-        return replacedBy("'webkitIDBDatabase'", "'IDBDatabase'");
-
-    case PrefixedIDBFactoryConstructor:
-        return replacedBy("'webkitIDBFactory'", "'IDBFactory'");
-
-    case PrefixedIDBIndexConstructor:
-        return replacedBy("'webkitIDBIndex'", "'IDBIndex'");
-
-    case PrefixedIDBKeyRangeConstructor:
-        return replacedBy("'webkitIDBKeyRange'", "'IDBKeyRange'");
-
-    case PrefixedIDBObjectStoreConstructor:
-        return replacedBy("'webkitIDBObjectStore'", "'IDBObjectStore'");
-
-    case PrefixedIDBRequestConstructor:
-        return replacedBy("'webkitIDBRequest'", "'IDBRequest'");
-
-    case PrefixedIDBTransactionConstructor:
-        return replacedBy("'webkitIDBTransaction'", "'IDBTransaction'");
-
-    case PrefixedRequestAnimationFrame:
-        return "'webkitRequestAnimationFrame' is vendor-specific. Please use the standard 'requestAnimationFrame' instead.";
-
-    case PrefixedCancelAnimationFrame:
-        return "'webkitCancelAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead.";
-
-    case PrefixedCancelRequestAnimationFrame:
-        return "'webkitCancelRequestAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead.";
-
-    case SyncXHRWithCredentials:
-        return "Setting 'XMLHttpRequest.withCredentials' for synchronous requests is deprecated.";
-
-    case PictureSourceSrc:
-        return "<source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead.";
-
-    case ConsoleTimeline:
-        return replacedBy("'console.timeline'", "'console.time'");
-
-    case ConsoleTimelineEnd:
-        return replacedBy("'console.timelineEnd'", "'console.timeEnd'");
-
-    case XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload:
-        return "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.";
-
-    case GetMatchedCSSRules:
-        return "'getMatchedCSSRules()' is deprecated. For more help, check https://code.google.com/p/chromium/issues/detail?id=437569#c2";
-
-    case PrefixedImageSmoothingEnabled:
-        return replacedBy("'CanvasRenderingContext2D.webkitImageSmoothingEnabled'", "'CanvasRenderingContext2D.imageSmoothingEnabled'");
-
-    case AudioListenerDopplerFactor:
-        return "dopplerFactor is deprecated and will be removed in M45 when all doppler effects are removed";
-
-    case AudioListenerSpeedOfSound:
-        return "speedOfSound is deprecated and will be removed in M45 when all doppler effects are removed";
-
-    case AudioListenerSetVelocity:
-        return "setVelocity() is deprecated and will be removed in M45 when all doppler effects are removed";
-
-    case PrefixedWindowURL:
-        return replacedBy("'webkitURL'", "'URL'");
-
-    case PrefixedAudioContext:
-        return replacedBy("'webkitAudioContext'", "'AudioContext'");
-
-    case PrefixedOfflineAudioContext:
-        return replacedBy("'webkitOfflineAudioContext'", "'OfflineAudioContext'");
-
-    case RangeExpand:
-        return replacedBy("'Range.expand()'", "'Selection.modify()'");
-
-    case PrefixedMediaAddKey:
-    case PrefixedMediaGenerateKeyRequest:
-    case PrefixedMediaCancelKeyRequest:
-        return "The prefixed Encrypted Media Extensions APIs are deprecated. Please use 'navigator.requestMediaKeySystemAccess()' instead.";
-
-    case CanPlayTypeKeySystem:
-        return replacedBy("canPlayType()'s 'keySystem' parameter", "'navigator.requestMediaKeySystemAccess()'");
-
-    // Powerful features on insecure origins (https://goo.gl/rStTGz)
-    case DeviceMotionInsecureOrigin:
-        return "The devicemotion event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
-
-    case DeviceOrientationInsecureOrigin:
-        return "The deviceorientation event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
-
-    case DeviceOrientationAbsoluteInsecureOrigin:
-        return "The deviceorientationabsolute event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
-
-    case GeolocationInsecureOrigin:
-        // TODO(jww): This message should be made less ambigous after WebView
-        // is fixed so geolocation can be removed there. After that, this
-        // should be updated to read similarly to GetUserMediaInsecureOrigin's
-        // message.
-        return "getCurrentPosition() and watchPosition() are deprecated on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
-
-    case GetUserMediaInsecureOrigin:
-        return "getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
-
-    case EncryptedMediaInsecureOrigin:
-        return "requestMediaKeySystemAccess() is deprecated on insecure origins in the specification. Support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.";
-
-    case ElementCreateShadowRootMultiple:
-        return "Calling Element.createShadowRoot() for an element which already hosts a shadow root is deprecated. See https://www.chromestatus.com/features/4668884095336448 for more details.";
-
-    case ElementCreateShadowRootMultipleWithUserAgentShadowRoot:
-        return "Calling Element.createShadowRoot() for an element which already hosts a user-agent shadow root is deprecated. See https://www.chromestatus.com/features/4668884095336448 for more details.";
-
-    case CSSDeepCombinator:
-        return "/deep/ combinator is deprecated. See https://www.chromestatus.com/features/6750456638341120 for more details.";
-
-    case CSSSelectorPseudoShadow:
-        return "::shadow pseudo-element is deprecated. See https://www.chromestatus.com/features/6750456638341120 for more details.";
-
-    case SVGSMILElementInDocument:
-    case SVGSMILAnimationInImageRegardlessOfCache:
-        return "SVG's SMIL animations (<animate>, <set>, etc.) are deprecated and will be removed. Please use CSS animations or Web animations instead.";
-
-    case PrefixedPerformanceClearResourceTimings:
-        return replacedBy("'Performance.webkitClearResourceTimings'", "'Performance.clearResourceTimings'");
-
-    case PrefixedPerformanceSetResourceTimingBufferSize:
-        return replacedBy("'Performance.webkitSetResourceTimingBufferSize'", "'Performance.setResourceTimingBufferSize'");
-
-    case PrefixedPerformanceResourceTimingBufferFull:
-        return replacedBy("'Performance.onwebkitresourcetimingbufferfull'", "'Performance.onresourcetimingbufferfull'");
-
-    case BluetoothDeviceInstanceId:
-        return replacedBy("'BluetoothDevice.instanceID'", "'BluetoothDevice.id'");
-
-    case BluetoothDeviceConnectGATT:
-        return replacedWillBeRemoved("'BluetoothDevice.connectGATT'", "'BluetoothDevice.gatt.connect'", 52, "5264933985976320");
-
-    case V8SVGElement_OffsetParent_AttributeGetter:
-        return willBeRemoved("'SVGElement.offsetParent'", 50, "5724912467574784");
-
-    case V8SVGElement_OffsetTop_AttributeGetter:
-        return willBeRemoved("'SVGElement.offsetTop'", 50, "5724912467574784");
-
-    case V8SVGElement_OffsetLeft_AttributeGetter:
-        return willBeRemoved("'SVGElement.offsetLeft'", 50, "5724912467574784");
-
-    case V8SVGElement_OffsetWidth_AttributeGetter:
-        return willBeRemoved("'SVGElement.offsetWidth'", 50, "5724912467574784");
-
-    case V8SVGElement_OffsetHeight_AttributeGetter:
-        return willBeRemoved("'SVGElement.offsetHeight'", 50, "5724912467574784");
-
-    case MediaStreamTrackGetSources:
-        return "MediaStreamTrack.getSources is deprecated. See https://www.chromestatus.com/feature/4765305641369600 for more details.";
-
-    case DocumentDefaultCharset:
-        return willBeRemoved("'Document.defaultCharset'", 50, "6217124578066432");
-
-    case V8TouchEvent_InitTouchEvent_Method:
-        return replacedWillBeRemoved("'TouchEvent.initTouchEvent'", "the TouchEvent constructor", 53, "5730982598541312");
-
-    case RTCPeerConnectionCreateAnswerLegacyNoFailureCallback:
-        return "RTCPeerConnection.CreateAnswer without a failure callback is deprecated. The failure callback will be a required parameter in M50. See https://www.chromestatus.com/feature/5663288008376320 for more details";
-
-    case RTCPeerConnectionCreateOfferLegacyNoFailureCallback:
-        return "RTCPeerConnection.CreateOffer without a failure callback is deprecated. The failure callback will be a required parameter in M50. See https://www.chromestatus.com/feature/5663288008376320 for more details";
-
-    case ObjectObserve:
-        return willBeRemoved("'Object.observe'", 50, "6147094632988672");
-
-    // Features that aren't deprecated don't have a deprecation message.
-    default:
-        return String();
-    }
-}
-
 void UseCounter::count(CSSParserMode cssParserMode, CSSPropertyID feature)
 {
     ASSERT(feature >= firstCSSProperty);
@@ -1013,7 +725,7 @@
 
 void UseCounter::count(Feature feature)
 {
-    ASSERT(deprecationMessage(feature).isEmpty());
+    ASSERT(Deprecation::deprecationMessage(feature).isEmpty());
     recordMeasurement(feature);
 }
 
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index 77bdc764..853b7e95 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1104,31 +1104,10 @@
     void count(CSSParserMode, CSSPropertyID);
     void count(Feature);
 
-    // "countDeprecation" sets the bit for this feature to 1, and sends a deprecation
-    // warning to the console. Repeated calls are ignored.
-    //
-    // Be considerate to developers' consoles: features should only send
-    // deprecation warnings when we're actively interested in removing them from
-    // the platform.
-    //
-    // For shared workers and service workers, the ExecutionContext* overload
-    // doesn't count the usage but only sends a console warning.
-    static void countDeprecation(const LocalFrame*, Feature);
-    static void countDeprecation(ExecutionContext*, Feature);
-    static void countDeprecation(const Document&, Feature);
-    // Use countDeprecationIfNotPrivateScript() instead of countDeprecation()
-    // if you don't want to count metrics in private scripts. You should use
-    // countDeprecationIfNotPrivateScript() in a binding layer.
-    static void countDeprecationIfNotPrivateScript(v8::Isolate*, ExecutionContext*, Feature);
-    static String deprecationMessage(Feature);
-
     // Count only features if they're being used in an iframe which does not
     // have script access into the top level document.
     static void countCrossOriginIframe(const Document&, Feature);
 
-    // TODO (nainar): Migrate all console message functions to Deprecation
-    static String willBeRemoved(const char* feature, int milestone, const char* details);
-
     // Return whether the Feature was previously counted for this document.
     // NOTE: only for use in testing.
     static bool isCounted(Document&, Feature);
@@ -1144,6 +1123,11 @@
     static void muteForInspector();
     static void unmuteForInspector();
 
+    void recordMeasurement(Feature feature) { m_countBits.recordMeasurement(feature); }
+    void updateMeasurements();
+
+    bool hasRecordedMeasurement(Feature feature) const { return m_countBits.hasRecordedMeasurement(feature); }
+
     class CountBits {
         DISALLOW_NEW();
     public:
@@ -1179,11 +1163,6 @@
     friend class UseCounterTest;
     static int m_muteCount;
 
-    void recordMeasurement(Feature feature) { m_countBits.recordMeasurement(feature); }
-    void updateMeasurements();
-
-    bool hasRecordedMeasurement(Feature feature) const { return m_countBits.hasRecordedMeasurement(feature); }
-
     CountBits m_countBits;
     BitVector m_CSSFeatureBits;
 };
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index 40f436f5..407d7d15 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -52,6 +52,7 @@
 #include "core/imagebitmap/ImageBitmapOptions.h"
 #include "core/layout/LayoutHTMLCanvas.h"
 #include "core/paint/PaintLayer.h"
+#include "core/paint/PaintTiming.h"
 #include "platform/Histogram.h"
 #include "platform/MIMETypeRegistry.h"
 #include "platform/RuntimeEnabledFeatures.h"
@@ -451,6 +452,9 @@
         m_imageBuffer->setFilterQuality(filterQuality);
     }
 
+    if (hasImageBuffer() && !m_imageBufferIsClear)
+        PaintTiming::from(document()).markFirstContentfulPaint();
+
     if (!paintsIntoCanvasBuffer() && !document().printing())
         return;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index b547215..ae623aa 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -33,8 +33,8 @@
 #include "core/dom/NodeTraversal.h"
 #include "core/dom/shadow/ShadowRoot.h"
 #include "core/fetch/ImageResource.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/ImageBitmap.h"
-#include "core/frame/UseCounter.h"
 #include "core/html/HTMLAnchorElement.h"
 #include "core/html/HTMLCanvasElement.h"
 #include "core/html/HTMLFormElement.h"
@@ -331,7 +331,7 @@
 
         HTMLSourceElement* source = toHTMLSourceElement(child);
         if (!source->fastGetAttribute(srcAttr).isNull())
-            UseCounter::countDeprecation(document(), UseCounter::PictureSourceSrc);
+            Deprecation::countDeprecation(document(), UseCounter::PictureSourceSrc);
         String srcset = source->fastGetAttribute(srcsetAttr);
         if (srcset.isEmpty())
             continue;
diff --git a/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp b/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp
index e9d1fb2..2b36b211 100644
--- a/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/DateTimeEditElement.cpp
@@ -476,7 +476,7 @@
 
 void DateTimeEditElement::addField(PassRefPtrWillBeRawPtr<DateTimeFieldElement> field)
 {
-    if (m_fields.size() == m_fields.capacity())
+    if (m_fields.size() >= maximumNumberOfFields)
         return;
     m_fields.append(field.get());
     fieldsWrapperElement()->appendChild(field);
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
index f6afbf0d..dfb5ce59 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -181,27 +181,43 @@
             page->chromeClient().didObserveNonGetFetchFromScript();
     }
 
-    // If the fetch request will be handled by the ServiceWorker, the
-    // FetchRequestMode of the request must be FetchRequestModeCORS or
-    // FetchRequestModeCORSWithForcedPreflight. Otherwise the ServiceWorker can
-    // return a opaque response which is from the other origin site and the
-    // script in the page can read the content.
-    //
     // We assume that ServiceWorker is skipped for sync requests and unsupported
     // protocol requests by content/ code.
     if (m_async && !request.skipServiceWorker() && SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(request.url().protocol()) && document.fetcher()->isControlledByServiceWorker()) {
         ResourceRequest newRequest(request);
-        // FetchRequestMode should be set by the caller. But the expected value
-        // of FetchRequestMode is not speced yet except for XHR. So we set here.
-        // FIXME: When we support fetch API in document, this value should not
-        // be overridden here.
-        if (options.preflightPolicy == ForcePreflight)
-            newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
-        else
-            newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS);
-
-        m_fallbackRequestForServiceWorker = ResourceRequest(request);
-        m_fallbackRequestForServiceWorker.setSkipServiceWorker(true);
+        const WebURLRequest::RequestContext requestContext(request.requestContext());
+        if (requestContext != WebURLRequest::RequestContextFetch) {
+            // When the request context is not "fetch",
+            // |crossOriginRequestPolicy| represents the fetch request mode,
+            // and |credentialsRequested| represents the fetch credentials mode.
+            // So we set those flags here so that we can see the correct request
+            // mode and credentials mode in the service worker's fetch event
+            // handler.
+            switch (m_options.crossOriginRequestPolicy) {
+            case DenyCrossOriginRequests:
+                newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeSameOrigin);
+                break;
+            case UseAccessControl:
+                if (options.preflightPolicy == ForcePreflight)
+                    newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
+                else
+                    newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS);
+                break;
+            case AllowCrossOriginRequests:
+                // No-CORS requests are allowed only for those contexts.
+                RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(requestContext == WebURLRequest::RequestContextAudio || requestContext == WebURLRequest::RequestContextVideo || requestContext == WebURLRequest::RequestContextObject || requestContext == WebURLRequest::RequestContextFavicon || requestContext == WebURLRequest::RequestContextImage || requestContext == WebURLRequest::RequestContextScript);
+                newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeNoCORS);
+                break;
+            }
+            if (m_resourceLoaderOptions.allowCredentials == AllowStoredCredentials)
+                newRequest.setFetchCredentialsMode(WebURLRequest::FetchCredentialsModeInclude);
+            else
+                newRequest.setFetchCredentialsMode(WebURLRequest::FetchCredentialsModeSameOrigin);
+        }
+        if (newRequest.fetchRequestMode() == WebURLRequest::FetchRequestModeCORS || newRequest.fetchRequestMode() == WebURLRequest::FetchRequestModeCORSWithForcedPreflight) {
+            m_fallbackRequestForServiceWorker = ResourceRequest(request);
+            m_fallbackRequestForServiceWorker.setSkipServiceWorker(true);
+        }
 
         loadRequest(newRequest, m_resourceLoaderOptions);
         return;
@@ -593,10 +609,6 @@
     }
 
     if (response.wasFetchedViaServiceWorker()) {
-        // It's still possible to reach here with null m_fallbackRequestForServiceWorker
-        // if the request was for main resource loading (i.e. for SharedWorker), for which
-        // we create DocumentLoader before the controller ServiceWorker is set.
-        ASSERT(!m_fallbackRequestForServiceWorker.isNull() || m_requestContext == WebURLRequest::RequestContextSharedWorker);
         if (response.wasFallbackRequiredByServiceWorker()) {
             // At this point we must have m_fallbackRequestForServiceWorker.
             // (For SharedWorker the request won't be CORS or CORS-with-preflight,
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
index 7266759..f537aa7 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
@@ -318,7 +318,6 @@
         // Unlike raw <img>, we block mixed content inside of <picture> or <img srcset>.
         ResourceLoaderOptions resourceLoaderOptions = ResourceFetcher::defaultResourceOptions();
         ResourceRequest resourceRequest(url);
-        resourceRequest.setFetchCredentialsMode(WebURLRequest::FetchCredentialsModeSameOrigin);
         if (updateBehavior == UpdateForcedReload) {
             resourceRequest.setCachePolicy(ResourceRequestCachePolicy::ReloadBypassingCache);
             resourceRequest.setLoFiState(WebURLRequest::LoFiOff);
diff --git a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
index ecfbc70..2cbc1dc 100644
--- a/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
+++ b/third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp
@@ -32,7 +32,7 @@
 #include "core/events/Event.h"
 #include "core/events/EventListener.h"
 #include "core/events/EventSender.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 #include "core/svg/SVGDocumentExtensions.h"
 #include "core/svg/SVGSVGElement.h"
 #include "core/svg/SVGURIReference.h"
@@ -326,7 +326,7 @@
     if (!rootParent->inDocument())
         return InsertionDone;
 
-    UseCounter::countDeprecation(document(), UseCounter::SVGSMILElementInDocument);
+    Deprecation::countDeprecation(document(), UseCounter::SVGSMILElementInDocument);
 
     setAttributeName(constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr)));
     SVGSVGElement* owner = ownerSVGElement();
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
index 1059150..6e8d697 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -30,6 +30,7 @@
 #include "core/animation/AnimationTimeline.h"
 #include "core/dom/NodeTraversal.h"
 #include "core/dom/shadow/FlatTreeTraversal.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
@@ -417,7 +418,7 @@
 {
     if (SVGSVGElement* rootElement = svgRootElement(m_page.get())) {
         if (rootElement->timeContainer()->hasAnimations())
-            UseCounter::countDeprecation(document, UseCounter::SVGSMILAnimationInImageRegardlessOfCache);
+            Deprecation::countDeprecation(document, UseCounter::SVGSMILAnimationInImageRegardlessOfCache);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
index 7e662aba..3e3803e 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
@@ -32,6 +32,7 @@
 
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/SerializedScriptValue.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/workers/DedicatedWorkerThread.h"
 #include "core/workers/WorkerClients.h"
@@ -93,7 +94,7 @@
     {
         ASSERT(context->isDocument());
         if (m_isDeprecation)
-            UseCounter::countDeprecation(context, m_feature);
+            Deprecation::countDeprecation(context, m_feature);
         else
             UseCounter::count(context, m_feature);
     }
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index fc59a51b..df55400 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -46,12 +46,13 @@
 #include "core/fetch/MemoryCache.h"
 #include "core/frame/DOMTimer.h"
 #include "core/frame/DOMTimerCoordinator.h"
+#include "core/frame/Deprecation.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/inspector/ConsoleMessageStorage.h"
 #include "core/inspector/InspectorConsoleInstrumentation.h"
 #include "core/inspector/WorkerInspectorController.h"
 #include "core/loader/WorkerThreadableLoader.h"
-#include "core/frame/LocalDOMWindow.h"
 #include "core/workers/WorkerNavigator.h"
 #include "core/workers/WorkerClients.h"
 #include "core/workers/WorkerConsole.h"
@@ -354,9 +355,9 @@
     // per worker lifecycle.
     if (!m_deprecationWarningBits.hasRecordedMeasurement(feature)) {
         m_deprecationWarningBits.recordMeasurement(feature);
-        ASSERT(!UseCounter::deprecationMessage(feature).isEmpty());
+        ASSERT(!Deprecation::deprecationMessage(feature).isEmpty());
         ASSERT(executionContext());
-        executionContext()->addConsoleMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, UseCounter::deprecationMessage(feature)));
+        executionContext()->addConsoleMessage(ConsoleMessage::create(DeprecationMessageSource, WarningMessageLevel, Deprecation::deprecationMessage(feature)));
     }
 }
 
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index d52c89cb..7912da9 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -47,8 +47,8 @@
 #include "core/fileapi/File.h"
 #include "core/fileapi/FileReaderLoader.h"
 #include "core/fileapi/FileReaderLoaderClient.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/Settings.h"
-#include "core/frame/UseCounter.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/html/FormData.h"
 #include "core/html/HTMLDocument.h"
@@ -535,7 +535,7 @@
     // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessError exception here.
     // However for time being only print warning message to warn web developers.
     if (!m_async)
-        UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWithCredentials);
+        Deprecation::countDeprecation(executionContext(), UseCounter::SyncXHRWithCredentials);
 
     m_includeCredentials = value;
 }
@@ -608,7 +608,7 @@
         // Refer : https://xhr.spec.whatwg.org/#sync-warning
         // Use count for XHR synchronous requests on main thread only.
         if (!document()->processingBeforeUnload())
-            UseCounter::countDeprecation(executionContext(), UseCounter::XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload);
+            Deprecation::countDeprecation(executionContext(), UseCounter::XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload);
     }
 
     m_method = FetchUtils::normalizeMethod(method);
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
index abd7ee63..e4a79b63 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
@@ -5,9 +5,9 @@
 #include "modules/device_orientation/DeviceMotionController.h"
 
 #include "core/dom/Document.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/OriginsUsingFeatures.h"
 #include "core/frame/Settings.h"
-#include "core/frame/UseCounter.h"
 #include "modules/EventModules.h"
 #include "modules/device_orientation/DeviceMotionData.h"
 #include "modules/device_orientation/DeviceMotionDispatcher.h"
@@ -54,7 +54,7 @@
         if (document().isSecureContext(errorMessage)) {
             UseCounter::count(document().frame(), UseCounter::DeviceMotionSecureOrigin);
         } else {
-            UseCounter::countDeprecation(document().frame(), UseCounter::DeviceMotionInsecureOrigin);
+            Deprecation::countDeprecation(document().frame(), UseCounter::DeviceMotionInsecureOrigin);
             OriginsUsingFeatures::countAnyWorld(document(), OriginsUsingFeatures::Feature::DeviceMotionInsecureOrigin);
             if (document().frame()->settings()->strictPowerfulFeatureRestrictions())
                 return;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
index 9027b2f..cda7a481 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationAbsoluteController.cpp
@@ -47,7 +47,7 @@
         if (document().isSecureContext(errorMessage)) {
             UseCounter::count(document().frame(), UseCounter::DeviceOrientationAbsoluteSecureOrigin);
         } else {
-            UseCounter::countDeprecation(document().frame(), UseCounter::DeviceOrientationAbsoluteInsecureOrigin);
+            Deprecation::countDeprecation(document().frame(), UseCounter::DeviceOrientationAbsoluteInsecureOrigin);
             // TODO: add rappor logging of insecure origins as in DeviceOrientationController.
             if (document().frame()->settings()->strictPowerfulFeatureRestrictions())
                 return;
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
index 1b144e8..5a27c1f 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
@@ -5,9 +5,9 @@
 #include "modules/device_orientation/DeviceOrientationController.h"
 
 #include "core/dom/Document.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/OriginsUsingFeatures.h"
 #include "core/frame/Settings.h"
-#include "core/frame/UseCounter.h"
 #include "modules/EventModules.h"
 #include "modules/device_orientation/DeviceOrientationData.h"
 #include "modules/device_orientation/DeviceOrientationDispatcher.h"
@@ -61,7 +61,7 @@
         if (document().isSecureContext(errorMessage)) {
             UseCounter::count(document().frame(), UseCounter::DeviceOrientationSecureOrigin);
         } else {
-            UseCounter::countDeprecation(document().frame(), UseCounter::DeviceOrientationInsecureOrigin);
+            Deprecation::countDeprecation(document().frame(), UseCounter::DeviceOrientationInsecureOrigin);
             OriginsUsingFeatures::countAnyWorld(document(), OriginsUsingFeatures::Feature::DeviceOrientationInsecureOrigin);
             if (document().frame()->settings()->strictPowerfulFeatureRestrictions())
                 return;
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
index 82f0e18..a18e0255 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
@@ -9,8 +9,8 @@
 #include "core/dom/DOMException.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/OriginsUsingFeatures.h"
-#include "core/frame/UseCounter.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "modules/encryptedmedia/EncryptedMediaUtils.h"
 #include "modules/encryptedmedia/MediaKeySession.h"
@@ -235,7 +235,7 @@
     if (executionContext->isSecureContext(errorMessage)) {
         UseCounter::count(executionContext, UseCounter::EncryptedMediaSecureOrigin);
     } else {
-        UseCounter::countDeprecation(executionContext, UseCounter::EncryptedMediaInsecureOrigin);
+        Deprecation::countDeprecation(executionContext, UseCounter::EncryptedMediaInsecureOrigin);
         // TODO(ddorwin): Implement the following:
         // Reject promise with a new DOMException whose name is NotSupportedError.
     }
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
index 6d563050..6fe0bde 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -526,6 +526,8 @@
     ResourceRequest request(m_request->url());
     request.setRequestContext(m_request->context());
     request.setHTTPMethod(m_request->method());
+    request.setFetchRequestMode(m_request->mode());
+    request.setFetchCredentialsMode(m_request->credentials());
     const Vector<OwnPtr<FetchHeaderList::Header>>& list = m_request->headerList()->list();
     for (size_t i = 0; i < list.size(); ++i) {
         request.addHTTPHeaderField(AtomicString(list[i]->first), AtomicString(list[i]->second));
diff --git a/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp b/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
index 10cec9b..7b3f9e0 100644
--- a/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
+++ b/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
@@ -29,9 +29,9 @@
 
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/OriginsUsingFeatures.h"
 #include "core/frame/Settings.h"
-#include "core/frame/UseCounter.h"
 #include "core/html/HTMLFrameOwnerElement.h"
 #include "modules/geolocation/Coordinates.h"
 #include "modules/geolocation/GeolocationController.h"
@@ -159,7 +159,7 @@
         UseCounter::count(document, UseCounter::GeolocationSecureOrigin);
         UseCounter::countCrossOriginIframe(*document, UseCounter::GeolocationSecureOriginIframe);
     } else {
-        UseCounter::countDeprecation(document, UseCounter::GeolocationInsecureOrigin);
+        Deprecation::countDeprecation(document, UseCounter::GeolocationInsecureOrigin);
         UseCounter::countCrossOriginIframe(*document, UseCounter::GeolocationInsecureOriginIframe);
         OriginsUsingFeatures::countAnyWorld(*document, OriginsUsingFeatures::Feature::GeolocationInsecureOrigin);
     }
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
index 68bffa34..7a17bf6 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
@@ -30,7 +30,7 @@
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/events/Event.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 #include "modules/mediastream/MediaStream.h"
 #include "modules/mediastream/MediaStreamTrackSourcesCallback.h"
 #include "modules/mediastream/MediaStreamTrackSourcesRequestImpl.h"
@@ -145,7 +145,7 @@
         exceptionState.throwDOMException(NotSupportedError, "No sources controller available; is this a detached window?");
         return;
     }
-    UseCounter::countDeprecation(context, UseCounter::MediaStreamTrackGetSources);
+    Deprecation::countDeprecation(context, UseCounter::MediaStreamTrackGetSources);
     MediaStreamTrackSourcesRequest* request = MediaStreamTrackSourcesRequestImpl::create(*context, callback);
     userMedia->requestSources(request);
 }
diff --git a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
index 854a5bab..d97557f 100644
--- a/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/RTCPeerConnection.cpp
@@ -39,8 +39,8 @@
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/frame/Deprecation.h"
 #include "core/frame/LocalFrame.h"
-#include "core/frame/UseCounter.h"
 #include "core/html/VoidCallback.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
@@ -395,7 +395,7 @@
     if (errorCallback)
         UseCounter::count(context, UseCounter::RTCPeerConnectionCreateOfferLegacyFailureCallback);
     else
-        UseCounter::countDeprecation(context, UseCounter::RTCPeerConnectionCreateOfferLegacyNoFailureCallback);
+        Deprecation::countDeprecation(context, UseCounter::RTCPeerConnectionCreateOfferLegacyNoFailureCallback);
 
     if (throwExceptionIfSignalingStateClosed(m_signalingState, exceptionState))
         return;
@@ -437,7 +437,7 @@
     if (errorCallback)
         UseCounter::count(context, UseCounter::RTCPeerConnectionCreateAnswerLegacyFailureCallback);
     else
-        UseCounter::countDeprecation(context, UseCounter::RTCPeerConnectionCreateAnswerLegacyNoFailureCallback);
+        Deprecation::countDeprecation(context, UseCounter::RTCPeerConnectionCreateAnswerLegacyNoFailureCallback);
 
     if (mediaConstraints.isObject())
         UseCounter::count(context, UseCounter::RTCPeerConnectionCreateAnswerLegacyConstraints);
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
index 4312927..ca03444 100644
--- a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
@@ -37,7 +37,7 @@
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/SpaceSplitString.h"
-#include "core/frame/UseCounter.h"
+#include "core/frame/Deprecation.h"
 #include "modules/mediastream/MediaConstraintsImpl.h"
 #include "modules/mediastream/MediaStream.h"
 #include "modules/mediastream/MediaStreamConstraints.h"
@@ -132,7 +132,7 @@
 
     // While getUserMedia is blocked on insecure origins, we still want to
     // count attempts to use it.
-    UseCounter::countDeprecation(document->frame(), UseCounter::GetUserMediaInsecureOrigin);
+    Deprecation::countDeprecation(document->frame(), UseCounter::GetUserMediaInsecureOrigin);
     UseCounter::countCrossOriginIframe(*document, UseCounter::GetUserMediaInsecureOriginIframe);
     OriginsUsingFeatures::countAnyWorld(*document, OriginsUsingFeatures::Feature::GetUserMediaInsecureOrigin);
     return false;
diff --git a/third_party/WebKit/Source/platform/CrossThreadCopier.h b/third_party/WebKit/Source/platform/CrossThreadCopier.h
index 73f169c..fc5af66 100644
--- a/third_party/WebKit/Source/platform/CrossThreadCopier.h
+++ b/third_party/WebKit/Source/platform/CrossThreadCopier.h
@@ -44,194 +44,194 @@
 
 namespace blink {
 
-    class IntRect;
-    class IntSize;
-    class KURL;
-    class ResourceError;
-    class ResourceRequest;
-    class ResourceResponse;
-    struct CrossThreadResourceResponseData;
-    struct CrossThreadResourceRequestData;
+class IntRect;
+class IntSize;
+class KURL;
+class ResourceError;
+class ResourceRequest;
+class ResourceResponse;
+struct CrossThreadResourceResponseData;
+struct CrossThreadResourceRequestData;
 
-    template<typename T> struct CrossThreadCopierPassThrough {
-        STATIC_ONLY(CrossThreadCopierPassThrough);
-        typedef T Type;
-        static Type copy(const T& parameter)
-        {
-            return parameter;
-        }
-    };
-
-    template<bool isConvertibleToInteger, bool isThreadSafeRefCounted, bool isGarbageCollected, typename T> struct CrossThreadCopierBase;
-
-    // Integers get passed through without any changes.
-    template<typename T> struct CrossThreadCopierBase<true, false, false, T> : public CrossThreadCopierPassThrough<T> {
-        STATIC_ONLY(CrossThreadCopierBase);
-    };
-
-    // nullptr_t can be passed through without any changes.
-    template<> struct CrossThreadCopierBase<false, false, false, std::nullptr_t> : public CrossThreadCopierPassThrough<std::nullptr_t> {
-        STATIC_ONLY(CrossThreadCopierBase);
-    };
-
-    // To allow a type to be passed across threads using its copy constructor, add a forward declaration of the type and
-    // a CopyThreadCopierBase<false, false, TypeName> : public CrossThreadCopierPassThrough<TypeName> { }; to this file.
-    template<> struct CrossThreadCopierBase<false, false, false, IntRect> : public CrossThreadCopierPassThrough<IntRect> {
-        STATIC_ONLY(CrossThreadCopierBase);
-    };
-
-    template<> struct CrossThreadCopierBase<false, false, false, IntSize> : public CrossThreadCopierPassThrough<IntSize> {
-        STATIC_ONLY(CrossThreadCopierBase);
-    };
-
-    // Custom copy methods.
-    template<typename T> struct CrossThreadCopierBase<false, true, false, T> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef typename WTF::RemoveTemplate<T, RefPtr>::Type TypeWithoutRefPtr;
-        typedef typename WTF::RemoveTemplate<TypeWithoutRefPtr, PassRefPtr>::Type TypeWithoutPassRefPtr;
-        typedef typename std::remove_pointer<TypeWithoutPassRefPtr>::type RefCountedType;
-
-        // Verify that only one of the above did a change.
-        static_assert((std::is_same<RefPtr<RefCountedType>, T>::value
-                        || std::is_same<PassRefPtr<RefCountedType>, T>::value
-                        || std::is_same<RefCountedType*, T>::value),
-                        "only one type modification should be allowed");
-
-        typedef PassRefPtr<RefCountedType> Type;
-        static Type copy(const T& refPtr)
-        {
-            return refPtr;
-        }
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, false, PassOwnPtr<T>> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef PassOwnPtr<T> Type;
-        static Type copy(Type ownPtr)
-        {
-            return ownPtr;
-        }
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, false, WeakMember<T>*> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef WeakMember<T>* Type;
-        static Type copy(Type ptr)
-        {
-            return ptr;
-        }
-    };
-
-    template<> struct CrossThreadCopierBase<false, false, false, KURL> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef KURL Type;
-        PLATFORM_EXPORT static Type copy(const KURL&);
-    };
-
-    template<> struct CrossThreadCopierBase<false, false, false, String> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef String Type;
-        PLATFORM_EXPORT static Type copy(const String&);
-    };
-
-    template<> struct CrossThreadCopierBase<false, false, false, ResourceError> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef ResourceError Type;
-        PLATFORM_EXPORT static Type copy(const ResourceError&);
-    };
-
-    template<> struct CrossThreadCopierBase<false, false, false, ResourceRequest> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef PassOwnPtr<CrossThreadResourceRequestData> Type;
-        PLATFORM_EXPORT static Type copy(const ResourceRequest&);
-    };
-
-    template<> struct CrossThreadCopierBase<false, false, false, ResourceResponse> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef PassOwnPtr<CrossThreadResourceResponseData> Type;
-        PLATFORM_EXPORT static Type copy(const ResourceResponse&);
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, true, T> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef typename std::remove_pointer<T>::type TypeWithoutPointer;
-        typedef RawPtr<TypeWithoutPointer> Type;
-        static Type copy(const T& ptr)
-        {
-            return ptr;
-        }
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, true, RawPtr<T>> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef RawPtr<T> Type;
-        static Type copy(const Type& ptr)
-        {
-            return ptr;
-        }
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, true, Member<T>> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef RawPtr<T> Type;
-        static Type copy(const Member<T>& ptr)
-        {
-            return ptr;
-        }
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, true, WeakMember<T>> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef RawPtr<T> Type;
-        static Type copy(const WeakMember<T>& ptr)
-        {
-            return ptr;
-        }
-    };
-
-    template<typename T> struct CrossThreadCopier : public CrossThreadCopierBase<std::is_convertible<T, int>::value,
-        WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RefPtr>::Type, ThreadSafeRefCounted>::value
-            || WTF::IsSubclassOfTemplate<typename std::remove_pointer<T>::type, ThreadSafeRefCounted>::value
-            || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, PassRefPtr>::Type, ThreadSafeRefCounted>::value,
-        WTF::IsSubclassOfTemplate<typename std::remove_pointer<T>::type, GarbageCollected>::value
-            || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RawPtr>::Type, GarbageCollected>::value
-            || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, Member>::Type, GarbageCollected>::value
-            || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, WeakMember>::Type, GarbageCollected>::value,
-        T> {
-        STATIC_ONLY(CrossThreadCopier);
-    };
-
-    // |T| is |C*| or |const WeakPtr<C>&|.
-    template<typename T> struct AllowCrossThreadAccessWrapper {
-        STACK_ALLOCATED();
-    public:
-        explicit AllowCrossThreadAccessWrapper(T value) : m_value(value) { }
-        T value() const { return m_value; }
-    private:
-        // This raw pointer is safe since AllowCrossThreadAccessWrapper is
-        // always stack-allocated. Ideally this should be Member<T> if T is
-        // garbage-collected and T* otherwise, but we don't want to introduce
-        // another template magic just for distinguishing Member<T> from T*.
-        // From the perspective of GC, T* always works correctly.
-        GC_PLUGIN_IGNORE("")
-        T m_value;
-    };
-
-    template<typename T> struct CrossThreadCopierBase<false, false, false, AllowCrossThreadAccessWrapper<T>> {
-        STATIC_ONLY(CrossThreadCopierBase);
-        typedef T Type;
-        static Type copy(const AllowCrossThreadAccessWrapper<T>& wrapper) { return wrapper.value(); }
-    };
-
-    template<typename T> AllowCrossThreadAccessWrapper<T*> AllowCrossThreadAccess(T* value)
+template<typename T> struct CrossThreadCopierPassThrough {
+    STATIC_ONLY(CrossThreadCopierPassThrough);
+    typedef T Type;
+    static Type copy(const T& parameter)
     {
-        return AllowCrossThreadAccessWrapper<T*>(value);
+        return parameter;
     }
+};
 
-    template<typename T> AllowCrossThreadAccessWrapper<const WeakPtr<T>&> AllowCrossThreadAccess(const WeakPtr<T>& value)
+template<bool isConvertibleToInteger, bool isThreadSafeRefCounted, bool isGarbageCollected, typename T> struct CrossThreadCopierBase;
+
+// Integers get passed through without any changes.
+template<typename T> struct CrossThreadCopierBase<true, false, false, T> : public CrossThreadCopierPassThrough<T> {
+    STATIC_ONLY(CrossThreadCopierBase);
+};
+
+// nullptr_t can be passed through without any changes.
+template<> struct CrossThreadCopierBase<false, false, false, std::nullptr_t> : public CrossThreadCopierPassThrough<std::nullptr_t> {
+    STATIC_ONLY(CrossThreadCopierBase);
+};
+
+// To allow a type to be passed across threads using its copy constructor, add a forward declaration of the type and
+// a CopyThreadCopierBase<false, false, TypeName> : public CrossThreadCopierPassThrough<TypeName> { }; to this file.
+template<> struct CrossThreadCopierBase<false, false, false, IntRect> : public CrossThreadCopierPassThrough<IntRect> {
+    STATIC_ONLY(CrossThreadCopierBase);
+};
+
+template<> struct CrossThreadCopierBase<false, false, false, IntSize> : public CrossThreadCopierPassThrough<IntSize> {
+    STATIC_ONLY(CrossThreadCopierBase);
+};
+
+// Custom copy methods.
+template<typename T> struct CrossThreadCopierBase<false, true, false, T> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef typename WTF::RemoveTemplate<T, RefPtr>::Type TypeWithoutRefPtr;
+    typedef typename WTF::RemoveTemplate<TypeWithoutRefPtr, PassRefPtr>::Type TypeWithoutPassRefPtr;
+    typedef typename std::remove_pointer<TypeWithoutPassRefPtr>::type RefCountedType;
+
+    // Verify that only one of the above did a change.
+    static_assert((std::is_same<RefPtr<RefCountedType>, T>::value
+        || std::is_same<PassRefPtr<RefCountedType>, T>::value
+        || std::is_same<RefCountedType*, T>::value),
+        "only one type modification should be allowed");
+
+    typedef PassRefPtr<RefCountedType> Type;
+    static Type copy(const T& refPtr)
     {
-        return AllowCrossThreadAccessWrapper<const WeakPtr<T>&>(value);
+        return refPtr;
     }
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, false, PassOwnPtr<T>> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef PassOwnPtr<T> Type;
+    static Type copy(Type ownPtr)
+    {
+        return ownPtr;
+    }
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, false, WeakMember<T>*> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef WeakMember<T>* Type;
+    static Type copy(Type ptr)
+    {
+        return ptr;
+    }
+};
+
+template<> struct CrossThreadCopierBase<false, false, false, KURL> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef KURL Type;
+    PLATFORM_EXPORT static Type copy(const KURL&);
+};
+
+template<> struct CrossThreadCopierBase<false, false, false, String> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef String Type;
+    PLATFORM_EXPORT static Type copy(const String&);
+};
+
+template<> struct CrossThreadCopierBase<false, false, false, ResourceError> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef ResourceError Type;
+    PLATFORM_EXPORT static Type copy(const ResourceError&);
+};
+
+template<> struct CrossThreadCopierBase<false, false, false, ResourceRequest> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef PassOwnPtr<CrossThreadResourceRequestData> Type;
+    PLATFORM_EXPORT static Type copy(const ResourceRequest&);
+};
+
+template<> struct CrossThreadCopierBase<false, false, false, ResourceResponse> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef PassOwnPtr<CrossThreadResourceResponseData> Type;
+    PLATFORM_EXPORT static Type copy(const ResourceResponse&);
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, true, T> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef typename std::remove_pointer<T>::type TypeWithoutPointer;
+    typedef RawPtr<TypeWithoutPointer> Type;
+    static Type copy(const T& ptr)
+    {
+        return ptr;
+    }
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, true, RawPtr<T>> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef RawPtr<T> Type;
+    static Type copy(const Type& ptr)
+    {
+        return ptr;
+    }
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, true, Member<T>> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef RawPtr<T> Type;
+    static Type copy(const Member<T>& ptr)
+    {
+        return ptr;
+    }
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, true, WeakMember<T>> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef RawPtr<T> Type;
+    static Type copy(const WeakMember<T>& ptr)
+    {
+        return ptr;
+    }
+};
+
+template<typename T> struct CrossThreadCopier : public CrossThreadCopierBase<std::is_convertible<T, int>::value,
+    WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RefPtr>::Type, ThreadSafeRefCounted>::value
+    || WTF::IsSubclassOfTemplate<typename std::remove_pointer<T>::type, ThreadSafeRefCounted>::value
+    || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, PassRefPtr>::Type, ThreadSafeRefCounted>::value,
+    WTF::IsSubclassOfTemplate<typename std::remove_pointer<T>::type, GarbageCollected>::value
+    || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RawPtr>::Type, GarbageCollected>::value
+    || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, Member>::Type, GarbageCollected>::value
+    || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, WeakMember>::Type, GarbageCollected>::value,
+    T> {
+    STATIC_ONLY(CrossThreadCopier);
+};
+
+// |T| is |C*| or |const WeakPtr<C>&|.
+template<typename T> struct AllowCrossThreadAccessWrapper {
+    STACK_ALLOCATED();
+public:
+    explicit AllowCrossThreadAccessWrapper(T value) : m_value(value) { }
+    T value() const { return m_value; }
+private:
+    // This raw pointer is safe since AllowCrossThreadAccessWrapper is
+    // always stack-allocated. Ideally this should be Member<T> if T is
+    // garbage-collected and T* otherwise, but we don't want to introduce
+    // another template magic just for distinguishing Member<T> from T*.
+    // From the perspective of GC, T* always works correctly.
+    GC_PLUGIN_IGNORE("")
+    T m_value;
+};
+
+template<typename T> struct CrossThreadCopierBase<false, false, false, AllowCrossThreadAccessWrapper<T>> {
+    STATIC_ONLY(CrossThreadCopierBase);
+    typedef T Type;
+    static Type copy(const AllowCrossThreadAccessWrapper<T>& wrapper) { return wrapper.value(); }
+};
+
+template<typename T> AllowCrossThreadAccessWrapper<T*> AllowCrossThreadAccess(T* value)
+{
+    return AllowCrossThreadAccessWrapper<T*>(value);
+}
+
+template<typename T> AllowCrossThreadAccessWrapper<const WeakPtr<T>&> AllowCrossThreadAccess(const WeakPtr<T>& value)
+{
+    return AllowCrossThreadAccessWrapper<const WeakPtr<T>&>(value);
+}
 
 } // namespace blink
 
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi
index d080b17..8feb02bb 100644
--- a/third_party/WebKit/Source/platform/blink_platform.gypi
+++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -388,6 +388,8 @@
       'exported/WrappedResourceResponse.h',
       'exported/linux/WebFontInfo.cpp',
       'exported/linux/WebFontRenderStyle.cpp',
+      'fonts/AcceptLanguagesResolver.cpp',
+      'fonts/AcceptLanguagesResolver.h',
       'fonts/AlternateFontFamily.h',
       'fonts/Character.cpp',
       'fonts/Character.h',
@@ -1106,6 +1108,7 @@
       'animation/CompositorFloatAnimationCurveTest.cpp',
       'blob/BlobDataTest.cpp',
       'clipboard/ClipboardUtilitiesTest.cpp',
+      'fonts/AcceptLanguagesResolverTest.cpp',
       'fonts/CharacterTest.cpp',
       'fonts/FontCacheTest.cpp',
       'fonts/FontDescriptionTest.cpp',
diff --git a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp
new file mode 100644
index 0000000..dd675167
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.cpp
@@ -0,0 +1,78 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/fonts/AcceptLanguagesResolver.h"
+
+#include "platform/Language.h"
+#include "platform/text/LocaleToScriptMapping.h"
+#include <unicode/locid.h>
+
+namespace blink {
+
+UScriptCode AcceptLanguagesResolver::m_preferredHanScript = USCRIPT_COMMON;
+const char* AcceptLanguagesResolver::m_preferredHanSkFontMgrLocale = nullptr;
+
+// SkFontMgr requires script-based locale names, like "zh-Hant" and "zh-Hans",
+// instead of "zh-CN" and "zh-TW".
+static const char* toSkFontMgrLocaleForHan(UScriptCode script)
+{
+    switch (script) {
+    case USCRIPT_KATAKANA_OR_HIRAGANA:
+        return "ja-jp";
+    case USCRIPT_HANGUL:
+        return "ko-kr";
+    case USCRIPT_SIMPLIFIED_HAN:
+        return "zh-Hans";
+    case USCRIPT_TRADITIONAL_HAN:
+        return "zh-Hant";
+    default:
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
+}
+
+void AcceptLanguagesResolver::acceptLanguagesChanged(
+    const String& acceptLanguages)
+{
+    // Use the UI locale if it can disambiguate the Unified Han.
+    // Historically we use ICU on Windows. crbug.com/586520
+#if OS(WIN)
+    // Since Chrome synchronizes the ICU default locale with its UI locale,
+    // this ICU locale tells the current UI locale of Chrome.
+    m_preferredHanScript = scriptCodeForHanFromLocale(
+        icu::Locale::getDefault().getName(), '_');
+#else
+    m_preferredHanScript = scriptCodeForHanFromLocale(defaultLanguage());
+#endif
+    if (m_preferredHanScript != USCRIPT_COMMON) {
+        // We don't need additional locale if defaultLanguage() can disambiguate
+        // since it's always passed to matchFamilyStyleCharacter() separately.
+        m_preferredHanSkFontMgrLocale = nullptr;
+        return;
+    }
+
+    updateFromAcceptLanguages(acceptLanguages);
+}
+
+void AcceptLanguagesResolver::updateFromAcceptLanguages(
+    const String& acceptLanguages)
+{
+    // Use the first acceptLanguages that can disambiguate.
+    Vector<String> languages;
+    acceptLanguages.split(',', languages);
+    for (String token : languages) {
+        token = token.stripWhiteSpace();
+        m_preferredHanScript = scriptCodeForHanFromLocale(token);
+        if (m_preferredHanScript != USCRIPT_COMMON) {
+            m_preferredHanSkFontMgrLocale = toSkFontMgrLocaleForHan(
+                m_preferredHanScript);
+            return;
+        }
+    }
+
+    m_preferredHanScript = USCRIPT_COMMON;
+    m_preferredHanSkFontMgrLocale = nullptr;
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.h b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.h
new file mode 100644
index 0000000..c643d5e
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolver.h
@@ -0,0 +1,34 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef AcceptLanguagesResolver_h
+#define AcceptLanguagesResolver_h
+
+#include "platform/PlatformExport.h"
+#include "wtf/text/WTFString.h"
+
+#include <unicode/uscript.h>
+
+namespace blink {
+
+class PLATFORM_EXPORT AcceptLanguagesResolver {
+public:
+    static UScriptCode preferredHanScript() { return m_preferredHanScript; }
+    static const char* preferredHanSkFontMgrLocale()
+    {
+        return m_preferredHanSkFontMgrLocale;
+    }
+
+    static void acceptLanguagesChanged(const String&);
+
+    static void updateFromAcceptLanguages(const String&);
+
+private:
+    static UScriptCode m_preferredHanScript;
+    static const char* m_preferredHanSkFontMgrLocale;
+};
+
+} // namespace blink
+
+#endif // AcceptLanguagesResolver_h
diff --git a/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolverTest.cpp b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolverTest.cpp
new file mode 100644
index 0000000..94f636e
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/AcceptLanguagesResolverTest.cpp
@@ -0,0 +1,53 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/fonts/AcceptLanguagesResolver.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(AcceptLanguagesResolverTest, AcceptLanguagesChanged)
+{
+    struct {
+        const char* acceptLanguages;
+        UScriptCode script;
+        const char* locale;
+    } tests[] = {
+        // Non-Han script cases.
+        { "", USCRIPT_COMMON, nullptr },
+        { "en-US", USCRIPT_COMMON, nullptr },
+        { ",en-US", USCRIPT_COMMON, nullptr },
+
+        // Single value cases.
+        { "ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp" },
+        { "ko-KR", USCRIPT_HANGUL, "ko-kr" },
+        { "zh-CN", USCRIPT_SIMPLIFIED_HAN, "zh-Hans" },
+        { "zh-HK", USCRIPT_TRADITIONAL_HAN, "zh-Hant" },
+        { "zh-TW", USCRIPT_TRADITIONAL_HAN, "zh-Hant" },
+
+        // Unusual combinations.
+        { "en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp" },
+
+        // Han scripts not in the first item.
+        { "en-US,ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp" },
+        { "en-US,en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp" },
+
+        // Multiple Han scripts. The first one wins.
+        { "ja-JP,zh-CN", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp" },
+        { "zh-TW,ja-JP", USCRIPT_TRADITIONAL_HAN, "zh-Hant" },
+    };
+
+    for (auto& test : tests) {
+        AcceptLanguagesResolver::updateFromAcceptLanguages(test.acceptLanguages);
+
+        EXPECT_EQ(test.script, AcceptLanguagesResolver::preferredHanScript())
+            << test.acceptLanguages;
+        EXPECT_STREQ(test.locale,
+            AcceptLanguagesResolver::preferredHanSkFontMgrLocale())
+            << test.acceptLanguages;
+    }
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
index 649e475b..d2b7c7c 100644
--- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -33,6 +33,7 @@
 
 #include "platform/Histogram.h"
 #include "platform/RuntimeEnabledFeatures.h"
+#include "platform/fonts/AcceptLanguagesResolver.h"
 #include "platform/fonts/AlternateFontFamily.h"
 #include "platform/fonts/FontCacheClient.h"
 #include "platform/fonts/FontCacheKey.h"
@@ -161,6 +162,11 @@
     return verticalData;
 }
 
+void FontCache::acceptLanguagesChanged(const String& acceptLanguages)
+{
+    AcceptLanguagesResolver::acceptLanguagesChanged(acceptLanguages);
+}
+
 static FontDataCache* gFontDataCache = 0;
 
 PassRefPtr<SimpleFontData> FontCache::getFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName, ShouldRetain shouldRetain)
diff --git a/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp b/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
index 335b243f..4a552100 100644
--- a/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
+++ b/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
@@ -31,6 +31,7 @@
 #include "platform/fonts/FontCache.h"
 
 #include "platform/Language.h"
+#include "platform/fonts/AcceptLanguagesResolver.h"
 #include "platform/fonts/SimpleFontData.h"
 #include "platform/fonts/FontDescription.h"
 #include "platform/fonts/FontFaceCreationParams.h"
@@ -57,16 +58,13 @@
     }
 }
 
-void FontCache::acceptLanguagesChanged(const String&)
-{
-    // TODO(kojii): Take acceptLanguages into account for ambiguos scripts.
-}
-
 static AtomicString getFamilyNameForCharacter(UChar32 c, const FontDescription& fontDescription)
 {
     RefPtr<SkFontMgr> fm = adoptRef(SkFontMgr::RefDefault());
-    const char* bcp47Locales[2];
+    const char* bcp47Locales[3];
     int localeCount = 0;
+    if (const char* hanLocale = AcceptLanguagesResolver::preferredHanSkFontMgrLocale())
+        bcp47Locales[localeCount++] = hanLocale;
     CString defaultLocale = toSkFontMgrLocale(defaultLanguage());
     bcp47Locales[localeCount++] = defaultLocale.data();
     CString fontLocale;
diff --git a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
index fe9ae67f..70493006 100644
--- a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
+++ b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
@@ -32,8 +32,6 @@
 
 namespace blink {
 
-void FontCache::acceptLanguagesChanged(const String&) {}
-
 void FontCache::getFontForCharacter(UChar32 c, const char* preferredLocale, FontCache::PlatformFallbackFont* fallbackFont)
 {
     WebFallbackFont webFallbackFont;
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
index 159b06d1..629b7eb 100644
--- a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
+++ b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm
@@ -96,8 +96,6 @@
     return appKitFontWeight >= 7;
 }
 
-void FontCache::acceptLanguagesChanged(const String&) {}
-
 PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData* fontDataToSubstitute)
 {
     // FIXME: We should fix getFallbackFamily to take a UChar32
diff --git a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
index 9e2f761..3945eda 100644
--- a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
+++ b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
@@ -112,11 +112,6 @@
     m_fontManager = adoptPtr(fontManager);
 }
 
-void FontCache::acceptLanguagesChanged(const String&)
-{
-    // TODO(kojii): Take acceptLanguages into account for ambiguos scripts.
-}
-
 // Given the desired base font, this will create a SimpleFontData for a specific
 // font that can be used to render the given range of characters.
 PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(
diff --git a/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp b/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp
index 0ff4e29e..ed479845 100644
--- a/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp
+++ b/third_party/WebKit/Source/platform/fonts/win/FontFallbackWin.cpp
@@ -30,6 +30,7 @@
 
 #include "platform/fonts/win/FontFallbackWin.h"
 
+#include "platform/fonts/AcceptLanguagesResolver.h"
 #include "platform/fonts/FontCache.h"
 #include "SkFontMgr.h"
 #include "SkTypeface.h"
@@ -230,6 +231,19 @@
         scriptFontMap[USCRIPT_HAN] = localeFamily;
 }
 
+static UScriptCode scriptForHan(UScriptCode contentScript,
+    const AtomicString& contentLocale)
+{
+    UScriptCode script = scriptCodeForHanFromLocale(contentScript, contentLocale);
+    if (script != USCRIPT_COMMON)
+        return script;
+    script = AcceptLanguagesResolver::preferredHanScript();
+    if (script != USCRIPT_COMMON)
+        return script;
+    // Use UI locale. See initializeScriptFontMap().
+    return USCRIPT_HAN;
+}
+
 // There are a lot of characters in USCRIPT_COMMON that can be covered
 // by fonts for scripts closely related to them. See
 // http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Script=Common:]
@@ -408,13 +422,10 @@
     if (script == USCRIPT_COMMON)
         script = getScriptBasedOnUnicodeBlock(character);
 
-    // For unified-Han scripts, try the lang attribute.
-    if (script == USCRIPT_HAN) {
-        script = scriptCodeForHanFromLocale(contentScript, contentLocale);
-        // Use the UI locale if it is still ambiguous.
-        if (script == USCRIPT_COMMON)
-            script = USCRIPT_SIMPLIFIED_HAN;
-    }
+    // For unified-Han scripts, try the lang attribute, system, or
+    // accept-languages.
+    if (script == USCRIPT_HAN)
+        script = scriptForHan(contentScript, contentLocale);
 
     family = getFontFamilyForScript(script, generic, fontManager);
     // Another lame work-around to cover non-BMP characters.
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index 8a414e3e..7f7e19e 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -52,6 +52,9 @@
 
 namespace blink {
 
+HeapAllocHooks::AllocationHook* HeapAllocHooks::m_allocationHook = nullptr;
+HeapAllocHooks::FreeHook* HeapAllocHooks::m_freeHook = nullptr;
+
 class GCForbiddenScope final {
     DISALLOW_NEW();
 public:
diff --git a/third_party/WebKit/Source/platform/heap/Heap.h b/third_party/WebKit/Source/platform/heap/Heap.h
index 34f76741..ece92ca 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.h
+++ b/third_party/WebKit/Source/platform/heap/Heap.h
@@ -45,6 +45,45 @@
 
 namespace blink {
 
+class PLATFORM_EXPORT HeapAllocHooks {
+public:
+    // TODO(hajimehoshi): Pass a type name of the allocated object.
+    typedef void AllocationHook(Address, size_t);
+    typedef void FreeHook(Address);
+
+    static void setAllocationHook(AllocationHook* hook) { m_allocationHook = hook; }
+    static void setFreeHook(FreeHook* hook) { m_freeHook = hook; }
+
+    static void allocationHookIfEnabled(Address address, size_t size)
+    {
+        AllocationHook* allocationHook = m_allocationHook;
+        if (UNLIKELY(!!allocationHook))
+            allocationHook(address, size);
+    }
+
+    static void freeHookIfEnabled(Address address)
+    {
+        FreeHook* freeHook = m_freeHook;
+        if (UNLIKELY(!!freeHook))
+            freeHook(address);
+    }
+
+    static void reallocHookIfEnabled(Address oldAddress, Address newAddress, size_t size)
+    {
+        // Report a reallocation as a free followed by an allocation.
+        AllocationHook* allocationHook = m_allocationHook;
+        FreeHook* freeHook = m_freeHook;
+        if (UNLIKELY(allocationHook && freeHook)) {
+            freeHook(oldAddress);
+            allocationHook(newAddress, size);
+        }
+    }
+
+private:
+    static AllocationHook* m_allocationHook;
+    static FreeHook* m_freeHook;
+};
+
 class CrossThreadPersistentRegion;
 template<typename T> class Member;
 template<typename T> class WeakMember;
@@ -456,7 +495,9 @@
 Address Heap::allocate(size_t size, bool eagerlySweep)
 {
     ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
-    return Heap::allocateOnHeapIndex(state, size, eagerlySweep ? BlinkGC::EagerSweepHeapIndex : Heap::heapIndexForObjectSize(size), GCInfoTrait<T>::index());
+    Address address = Heap::allocateOnHeapIndex(state, size, eagerlySweep ? BlinkGC::EagerSweepHeapIndex : Heap::heapIndexForObjectSize(size), GCInfoTrait<T>::index());
+    HeapAllocHooks::allocationHookIfEnabled(address, size);
+    return address;
 }
 
 template<typename T>
@@ -489,6 +530,7 @@
     if (copySize > size)
         copySize = size;
     memcpy(address, previous, copySize);
+    HeapAllocHooks::reallocHookIfEnabled(static_cast<Address>(previous), address, size);
     return address;
 }
 
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.cpp b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
index e9dcbe1..5fb397c1 100644
--- a/third_party/WebKit/Source/platform/heap/HeapPage.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
@@ -98,6 +98,7 @@
 
 void HeapObjectHeader::finalize(Address object, size_t objectSize)
 {
+    HeapAllocHooks::freeHookIfEnabled(object);
     const GCInfo* gcInfo = Heap::gcInfo(gcInfoIndex());
     if (gcInfo->hasFinalizer())
         gcInfo->m_finalize(object);
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
index 24fa32ae5..3601422 100644
--- a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
@@ -429,10 +429,7 @@
     m_requestContext = WebURLRequest::RequestContextUnspecified;
     m_frameType = WebURLRequest::FrameTypeNone;
     m_fetchRequestMode = WebURLRequest::FetchRequestModeNoCORS;
-    // Contrary to the Fetch spec, we default to same-origin mode here, and deal
-    // with CORS modes in updateRequestForAccessControl if we're called in a
-    // context which requires it.
-    m_fetchCredentialsMode = WebURLRequest::FetchCredentialsModeSameOrigin;
+    m_fetchCredentialsMode = WebURLRequest::FetchCredentialsModeInclude;
     m_fetchRedirectMode = WebURLRequest::FetchRedirectModeFollow;
     m_referrerPolicy = ReferrerPolicyDefault;
     m_loFiState = WebURLRequest::LoFiUnspecified;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 5d4f1d8..93a1057 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -18738,6 +18738,18 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.AudioUnitRenderHasWorkedMac"
+    enum="BooleanEverWorked">
+  <owner>henrika@chromium.org</owner>
+  <summary>
+    Stored in combination with Media.Audio.RenderFailsWhenBufferSizeChangesMac.
+    It is set to true if calls to AudioUnitRender has ever worked, i.e., we did
+    not start to see kAudioUnitErr_CannotDoInCurrentContext error messages
+    directly from start but there has been at least on successful call to
+    AudioUnitRender.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.AutomaticGainControlMac" enum="BooleanEnabled">
   <owner>henrika@chromium.org</owner>
   <summary>
@@ -18837,6 +18849,17 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.RenderFailsWhenBufferSizeChangesMac"
+    enum="BooleanChanged">
+  <owner>henrika@chromium.org</owner>
+  <summary>
+    True if a call to AudioUnitRender failed with an error code of
+    kAudioUnitErr_CannotDoInCurrentContext (-10863) and the call was preceded
+    with a change in the native I/O buffer size. This value is logged while
+    input audio is active but it should be a very rare event.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.RequestedInputBufferFrameSizeMac">
   <owner>henrika@chromium.org</owner>
   <summary>
@@ -26930,6 +26953,15 @@
   </summary>
 </histogram>
 
+<histogram name="Net.ResourceLoader.InliningStatus"
+    enum="ResourceLoaderInliningStatus">
+  <owner>tzik@chromium.org</owner>
+  <summary>
+    Counts whether the chunk inlining is applicable or not to a resource
+    loading. Counts the reason if inapplicable.
+  </summary>
+</histogram>
+
 <histogram name="Net.ResourceLoader.ReadDeferral" units="ms">
   <owner>clamy@chromium.org</owner>
   <summary>
@@ -58638,6 +58670,11 @@
   <int value="1" label="Can check"/>
 </enum>
 
+<enum name="BooleanChanged" type="int">
+  <int value="0" label="Not changed"/>
+  <int value="1" label="Changed"/>
+</enum>
+
 <enum name="BooleanCloseTimeout" type="int">
   <int value="0" label="Closed normally"/>
   <int value="1" label="Timed out"/>
@@ -58738,6 +58775,11 @@
   <int value="1" label="Error"/>
 </enum>
 
+<enum name="BooleanEverWorked" type="int">
+  <int value="0" label="Has never worked"/>
+  <int value="1" label="Has worked at least once"/>
+</enum>
+
 <enum name="BooleanExpired" type="int">
   <int value="0" label="Unexpired"/>
   <int value="1" label="Expired"/>
@@ -77054,6 +77096,15 @@
   <int value="1" label="Has client"/>
 </enum>
 
+<enum name="ResourceLoaderInliningStatus" type="int">
+  <int value="0" label="Applicable"/>
+  <int value="1" label="EarlyAllocation"/>
+  <int value="2" label="UnknownContentLength"/>
+  <int value="3" label="LargeContent"/>
+  <int value="4" label="HasTransferEncoding"/>
+  <int value="5" label="HasContentEncoding"/>
+</enum>
+
 <enum name="ResourcePrefetchPredictorMainFrameRequestStats" type="int">
   <int value="0" label="MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS"/>
   <int value="1" label="MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS"/>
@@ -86880,6 +86931,8 @@
   <suffix name="LT_512kB"
       label="Sliced for resources smaller than 512kB and larger than 32kB."/>
   <suffix name="Over_512kB" label="Sliced for resources larger than 512kB."/>
+  <suffix name="InliningApplicable"
+      label="Resources that the chunk inlining is applicable."/>
   <affected-histogram name="Net.ResourceLoader.ResponseStartToEnd"/>
 </histogram_suffixes>
 
diff --git a/tools/perf/profile_creators/extension_profile_extender_unittest.py b/tools/perf/profile_creators/extension_profile_extender_unittest.py
index 08beec9..6049872 100644
--- a/tools/perf/profile_creators/extension_profile_extender_unittest.py
+++ b/tools/perf/profile_creators/extension_profile_extender_unittest.py
@@ -17,7 +17,8 @@
 
      Creates an extension profile and verifies that it has non-empty contents.
   """
-  @decorators.Enabled('mac')  # Extension generation only works on Mac for now.
+  # Should be enabled on mac, disabled because flaky: https://crbug.com/586362.
+  @decorators.Disabled('all')  # Extension generation only works on Mac for now.
   def testExtensionProfileCreation(self):
     tmp_dir = tempfile.mkdtemp()
     files_in_crx_dir = 0
diff --git a/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js b/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js
index 2bf0ca4..1aa179f8 100644
--- a/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js
@@ -111,6 +111,8 @@
       'click', this.processOKAction_.bind(this));
   dialogFooter.cancelButton.addEventListener(
       'click', this.onCancelBound_);
+  dialogFooter.newFolderButton.addEventListener(
+      'click', this.processNewFolderAction_.bind(this));
   dialogFooter.fileTypeSelector.addEventListener(
       'change', this.onFileTypeFilterChanged_.bind(this));
   dialogFooter.filenameInput.addEventListener(
@@ -122,6 +124,10 @@
   dialogFooter.initFileTypeFilter(
       this.fileTypes_, launchParam.includeAllFiles);
   this.onFileTypeFilterChanged_();
+
+  this.newFolderCommand_ = document.getElementById('new-folder');
+  this.newFolderCommand_.addEventListener(
+      'disabledChange', this.updateNewFolderButton_.bind(this));
 }
 
 /**
@@ -246,6 +252,23 @@
 };
 
 /**
+ * Creates a new folder using new-folder command.
+ * @private
+ */
+DialogActionController.prototype.processNewFolderAction_ = function() {
+  this.newFolderCommand_.canExecuteChange(this.dialogFooter_.newFolderButton);
+  this.newFolderCommand_.execute(this.dialogFooter_.newFolderButton);
+};
+
+/**
+ * Handles disabledChange event to update the new-folder button's avaliability.
+ * @private
+ */
+DialogActionController.prototype.updateNewFolderButton_ = function() {
+  this.dialogFooter_.newFolderButton.disabled = this.newFolderCommand_.disabled;
+};
+
+/**
  * Tries to close this modal dialog with some files selected.
  * Performs preprocessing if needed (e.g. for Drive).
  * @param {Object} selection Contains urls, filterIndex and multiple fields.
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 0440716..d241144 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -275,20 +275,39 @@
 };
 
 /**
- * If entry is fake or root entry, we don't show menu item for it.
+ * Returns true if the given entry is the root entry of the volume.
+ * @param {VolumeManagerWrapper} volumeManager
+ * @param {(!Entry|!FakeEntry)} entry Entry or a fake entry.
+ * @return {boolean} True if the entry is a root entry.
+ */
+CommandUtil.isRootEntry = function(volumeManager, entry) {
+  if (!volumeManager || !entry)
+    return false;
+
+  var volumeInfo = volumeManager.getVolumeInfo(entry);
+  return !!volumeInfo && volumeInfo.displayRoot === entry;
+};
+
+/**
+ * If entry is fake/invalid/root, we don't show menu item for it.
  * @param {VolumeManagerWrapper} volumeManager
  * @param {(!Entry|!FakeEntry)} entry Entry or a fake entry.
  * @return {boolean} True if we should show menu item for the entry.
  */
 CommandUtil.shouldShowMenuItemForEntry = function(volumeManager, entry) {
-  if (!volumeManager || util.isFakeEntry(entry))
+  // If the entry is fake entry, hide context menu entries.
+  if (util.isFakeEntry(entry))
     return false;
 
-  var volumeInfo = volumeManager.getVolumeInfo(entry);
-  if (!volumeInfo)
+  // If the entry is not a valid entry, hide context menu entries.
+  if (!volumeManager || !volumeManager.getVolumeInfo(entry))
     return false;
 
-  return volumeInfo.displayRoot !== entry;
+  // If the entry is root entry of its volume, hide context menu entries.
+  if (CommandUtil.isRootEntry(volumeManager, entry))
+    return false;
+
+  return true;
 };
 
 /**
@@ -600,8 +619,7 @@
     if (event.target instanceof DirectoryItem ||
         event.target instanceof DirectoryTree) {
       var entry = CommandUtil.getCommandEntry(event.target);
-      if (!entry || !CommandUtil.shouldShowMenuItemForEntry(
-          fileManager.volumeManager, entry)) {
+      if (!entry || util.isFakeEntry(entry)) {
         event.canExecute = false;
         event.command.setHidden(true);
         return;
@@ -609,7 +627,8 @@
 
       var locationInfo = fileManager.volumeManager.getLocationInfo(entry);
       event.canExecute = locationInfo && !locationInfo.isReadOnly;
-      event.command.setHidden(false);
+      event.command.setHidden(
+          CommandUtil.isRootEntry(fileManager.volumeManager, entry));
     } else {
       var directoryModel = fileManager.directoryModel;
       event.canExecute = !fileManager.isOnReadonlyDirectory() &&
diff --git a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
index f2c2dad..3e21c27b 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
@@ -50,6 +50,14 @@
       (container.querySelector('.cancel'));
 
   /**
+   * New folder button in the footer.
+   * @const
+   * @type {!HTMLButtonElement}
+   */
+  this.newFolderButton = /** @type {!HTMLButtonElement} */
+      (container.querySelector('#new-folder-button'));
+
+  /**
    * File type selector in the footer.
    * @const
    * @type {!HTMLSelectElement}
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index d13b5ea9..766e64cc 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -405,8 +405,7 @@
       <div class="left">
         <!-- TODO(fukino): Turn this button into paper-button when the CommandButton supports paper-button. -->
         <button id="new-folder-button" class="primary"
-                visibleif="saveas-file folder" command="#new-folder"
-                tabindex="3" disabled>
+                visibleif="saveas-file folder" tabindex="3" disabled>
           <paper-ripple fit></paper-ripple>
           <span i18n-content="NEW_FOLDER_BUTTON_LABEL"></span>
         </button>