diff --git a/BUILD.gn b/BUILD.gn
index d697f90..54d16ba 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -401,7 +401,6 @@
       "//base:base_junit_tests",
       "//base/android/linker:chromium_android_linker",
       "//build/android/gyp/test:hello_world",
-      "//build/android/rezip",
       "//chrome/android/webapk/shell_apk:webapk",
       "//components/invalidation/impl:components_invalidation_impl_junit_tests",
       "//components/policy/android:components_policy_junit_tests",
diff --git a/DEPS b/DEPS
index 923ce45..9076ffa 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '7a6c9f7be115031a8a86fdae20e8869fd973fdb6',
+  'skia_revision': '2103cf0ff09763aeaa35508734f765aec9b75665',
   # 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': '783b1c5d041c3c612c5193a45937c060a32cc0d0',
+  'v8_revision': '626575112bf0129d6cdf4ea5c843a2231a84fbbb',
   # 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.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '38c2705c697cd9a67b02ead1d601610d7af96524',
+  'pdfium_revision': '6b71f22093fc4abb2da39f5a58b29c45c17ff99a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '201f910a0958c2c25481dc011616aada3df330d9',
+  'catapult_revision': '143ba4ddeb05e6165fb8413c5f3f47d342922d24',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -228,7 +228,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' + '@' + 'cda50c31ad6f31dfaa8568f6e23037dabb6b19e5', # commit position 16087
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'ee5b9eaa30f9734c14c2d35130518b48da7eace6', # commit position 16098
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
@@ -273,7 +273,7 @@
     Var('chromium_git') + '/external/github.com/google/cld_3.git' + '@' + 'ae02d6b8a2af41e87c956c7c7d3f651a8b7b9e79',
 
   'src/third_party/libwebm/source':
-    Var('chromium_git') + '/webm/libwebm.git' + '@' + '9a235e0bc94319c5f7184bd69cbe5468a74a025c',
+    Var('chromium_git') + '/webm/libwebm.git' + '@' + '4956b2dec65352af32dc71bab553acb631c64177',
 
   'src/third_party/pdfium':
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
@@ -397,7 +397,7 @@
 
     # For Linux and Chromium OS.
     'src/third_party/cros_system_api':
-      Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '05cee9da77790110786e6211f75c49d0c7e26ae8',
+      Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'eb397c32a942a2839b2aa3638b6c0da5c3bee146',
 
     # Note that this is different from Android's freetype repo.
     'src/third_party/freetype2/src':
diff --git a/android_webview/tools/apk_merger.py b/android_webview/tools/apk_merger.py
index 74eac37..e3a766b 100755
--- a/android_webview/tools/apk_merger.py
+++ b/android_webview/tools/apk_merger.py
@@ -135,8 +135,7 @@
 
 
 def SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, zipalign_path,
-                    keystore_path, key_name, key_password,
-                    page_align_shared_libraries):
+                    keystore_path, key_name, key_password):
   try:
     finalize_apk.JarSigner(
         keystore_path,
@@ -149,7 +148,6 @@
 
   try:
     finalize_apk.AlignApk(zipalign_path,
-                          page_align_shared_libraries,
                           signed_tmp_apk,
                           new_apk)
   except build_utils.CalledProcessError as e:
@@ -179,8 +177,6 @@
   expected_files = {'snapshot_blob_32.bin': False}
   if args.shared_library:
     expected_files[args.shared_library] = not args.uncompress_shared_libraries
-  if args.debug:
-    expected_files['gdbserver'] = True
 
   # need to unpack APKs to compare their contents
   UnpackApk(args.apk_64bit, tmp_dir_64)
@@ -224,7 +220,8 @@
   parser.add_argument('--key_name', required=True)
   parser.add_argument('--key_password', required=True)
   parser.add_argument('--shared_library')
-  parser.add_argument('--page-align-shared-libraries', action='store_true')
+  parser.add_argument('--page-align-shared-libraries', action='store_true',
+                      help='Obsolete, but remains for backwards compatibility')
   parser.add_argument('--uncompress-shared-libraries', action='store_true')
   parser.add_argument('--debug', action='store_true')
   # This option shall only used in debug build, see http://crbug.com/631494.
@@ -250,8 +247,7 @@
     MergeApk(args, tmp_apk, tmp_dir_32, tmp_dir_64)
 
     SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, args.zipalign_path,
-                    args.keystore_path, args.key_name, args.key_password,
-                    args.page_align_shared_libraries)
+                    args.keystore_path, args.key_name, args.key_password)
 
   except ApkMergeFailure as e:
     print e
diff --git a/ash/common/wm/overview/window_grid.cc b/ash/common/wm/overview/window_grid.cc
index 6f013b3c..99a6e92 100644
--- a/ash/common/wm/overview/window_grid.cc
+++ b/ash/common/wm/overview/window_grid.cc
@@ -313,7 +313,7 @@
         widget_window->GetLayer()->GetAnimator());
     animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
         kOverviewSelectorTransitionMilliseconds));
-    animation_settings.SetTweenType(gfx::Tween::EASE_IN_2);
+    animation_settings.SetTweenType(gfx::Tween::EASE_OUT);
     animation_settings.SetPreemptionStrategy(
         ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
     // CleanupAnimationObserver will delete itself (and the shield widget) when
@@ -661,7 +661,7 @@
       widget_window->GetLayer()->GetAnimator());
   animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
       kOverviewSelectorTransitionMilliseconds));
-  animation_settings.SetTweenType(gfx::Tween::EASE_IN);
+  animation_settings.SetTweenType(gfx::Tween::EASE_OUT);
   animation_settings.SetPreemptionStrategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
   shield_widget_->SetOpacity(kShieldOpacity);
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc
index eecd19a..f32e9a3 100644
--- a/base/metrics/persistent_memory_allocator.cc
+++ b/base/metrics/persistent_memory_allocator.cc
@@ -218,11 +218,9 @@
     // again. Failing will also load the existing value into "last" so there
     // is no need to do another such load when the while-loop restarts. A
     // "strong" compare-exchange is used because failing unnecessarily would
-    // mean repeating some fairly costly validations above. This operation
-    // is "relaxed" because the iterator has no other values to protect and
-    // the referenced object will be accessed via an "acquire" in GetAsObject.
+    // mean repeating some fairly costly validations above.
     if (last_record_.compare_exchange_strong(
-            last, next, std::memory_order_relaxed, std::memory_order_relaxed)) {
+            last, next, std::memory_order_acq_rel, std::memory_order_acquire)) {
       *type_return = block->type_id.load(std::memory_order_relaxed);
       break;
     }
@@ -638,6 +636,10 @@
       return kReferenceNull;
     }
 
+    // Load information into the block header. There is no "release" of the
+    // data here because this memory can, currently, be seen only by the thread
+    // performing the allocation. When it comes time to share this, the thread
+    // will call MakeIterable() which does the release operation.
     block->size = size;
     block->cookie = kBlockCookieAllocated;
     block->type_id.store(type_id, std::memory_order_relaxed);
diff --git a/base/win/BUILD.gn b/base/win/BUILD.gn
index ff2a754..74c1b8a 100644
--- a/base/win/BUILD.gn
+++ b/base/win/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/buildflag_header.gni")
+import("//build/config/sanitizers/sanitizers.gni")
 import("//build/win/message_compiler.gni")
 
 declare_args() {
@@ -42,7 +43,9 @@
     "eventlog_provider.cc",
   ]
 
-  ldflags = [ "/NOENTRY" ]
+  if (!is_asan) {
+    ldflags = [ "/NOENTRY" ]
+  }
 
   deps = [
     "//base/win:eventlog_messages",
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index 82ac496ed..6c20b05 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -31,6 +31,9 @@
                       help='GYP-list of files to add as assets in the form '
                            '"srcPath:zipPath", where ":zipPath" is optional.',
                       default='[]')
+  parser.add_argument('--java-resources',
+                      help='GYP-list of java_resources JARs to include.',
+                      default='[]')
   parser.add_argument('--write-asset-list',
                       action='store_true',
                       help='Whether to create an assets/assets_list file.')
@@ -63,8 +66,6 @@
   parser.add_argument('--native-lib-placeholders',
                       help='GYP-list of native library placeholders to add.',
                       default='[]')
-  parser.add_argument('--emma-device-jar',
-                      help='Path to emma_device.jar to include.')
   parser.add_argument('--uncompress-shared-libraries',
                       action='store_true',
                       help='Uncompress shared libraries')
@@ -74,6 +75,7 @@
       options.uncompressed_assets)
   options.native_lib_placeholders = build_utils.ParseGnList(
       options.native_lib_placeholders)
+  options.java_resources = build_utils.ParseGnList(options.java_resources)
   all_libs = []
   for gyp_list in options.native_libs:
     all_libs.extend(build_utils.ParseGnList(gyp_list))
@@ -161,14 +163,20 @@
 
 def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
   """Add native libraries to APK."""
+  has_crazy_linker = any('android_linker' in os.path.basename(p)
+                         for p in native_libs)
   for path in native_libs:
     basename = os.path.basename(path)
-    apk_path = 'lib/%s/%s' % (android_abi, basename)
 
     compress = None
-    if (uncompress and os.path.splitext(basename)[1] == '.so'):
+    if (uncompress and os.path.splitext(basename)[1] == '.so'
+        and 'android_linker' not in basename):
       compress = False
+      # Add prefix to prevent android install from extracting upon install.
+      if has_crazy_linker:
+        basename = 'crazy.' + basename
 
+    apk_path = 'lib/%s/%s' % (android_abi, basename)
     build_utils.AddToZipHermetic(out_apk,
                                  apk_path,
                                  src_path=path,
@@ -195,9 +203,6 @@
   if options.dex_file:
     input_paths.append(options.dex_file)
 
-  if options.emma_device_jar:
-    input_paths.append(options.emma_device_jar)
-
   input_strings = [options.android_abi,
                    options.native_lib_placeholders,
                    options.uncompress_shared_libraries]
@@ -205,6 +210,9 @@
   if options.secondary_android_abi:
     input_strings.append(options.secondary_android_abi)
 
+  if options.java_resources:
+    input_paths.extend(options.java_resources)
+
   _assets = _ExpandPaths(options.assets)
   _uncompressed_assets = _ExpandPaths(options.uncompressed_assets)
 
@@ -265,8 +273,9 @@
                               options.uncompress_shared_libraries)
 
         for name in sorted(options.native_lib_placeholders):
-          # Empty libs files are ignored by md5check, but rezip requires them
-          # to be empty in order to identify them as placeholders.
+          # Note: Empty libs files are ignored by md5check (can cause issues
+          # with stale builds when the only change is adding/removing
+          # placeholders).
           apk_path = 'lib/%s/%s' % (options.android_abi, name)
           build_utils.AddToZipHermetic(out_apk, apk_path, data='')
 
@@ -274,24 +283,23 @@
         for info in resource_infos[1:]:
           copy_resource(info)
 
-        # 6. Java resources. Used only when coverage is enabled, so order
-        # doesn't matter).
-        if options.emma_device_jar:
-          # Add EMMA Java resources to APK.
-          with zipfile.ZipFile(options.emma_device_jar, 'r') as emma_device_jar:
-            for apk_path in emma_device_jar.namelist():
+        # 6. Java resources that should be accessible via
+        # Class.getResourceAsStream(), in particular parts of Emma jar.
+        # Prebuilt jars may contain class files which we shouldn't include.
+        for java_resource in options.java_resources:
+          with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
+            for apk_path in java_resource_jar.namelist():
               apk_path_lower = apk_path.lower()
+
               if apk_path_lower.startswith('meta-inf/'):
                 continue
-
               if apk_path_lower.endswith('/'):
                 continue
-
               if apk_path_lower.endswith('.class'):
                 continue
 
-              build_utils.AddToZipHermetic(out_apk, apk_path,
-                                           data=emma_device_jar.read(apk_path))
+              build_utils.AddToZipHermetic(
+                  out_apk, apk_path, data=java_resource_jar.read(apk_path))
 
       shutil.move(tmp_apk, options.output_apk)
     finally:
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py
index 532d001f..ecb5ebfe 100755
--- a/build/android/gyp/finalize_apk.py
+++ b/build/android/gyp/finalize_apk.py
@@ -21,32 +21,6 @@
 
 from util import build_utils
 
-def RenameInflateAndAddPageAlignment(
-    rezip_apk_jar_path, in_zip_file, out_zip_file):
-  rezip_apk_cmd = [
-      'java',
-      '-classpath',
-      rezip_apk_jar_path,
-      'RezipApk',
-      'renamealign',
-      in_zip_file,
-      out_zip_file,
-    ]
-  build_utils.CheckOutput(rezip_apk_cmd)
-
-
-def ReorderAndAlignApk(rezip_apk_jar_path, in_zip_file, out_zip_file):
-  rezip_apk_cmd = [
-      'java',
-      '-classpath',
-      rezip_apk_jar_path,
-      'RezipApk',
-      'reorder',
-      in_zip_file,
-      out_zip_file,
-    ]
-  build_utils.CheckOutput(rezip_apk_cmd)
-
 
 def JarSigner(key_path, key_name, key_passwd, unsigned_path, signed_path):
   shutil.copy(unsigned_path, signed_path)
@@ -62,14 +36,15 @@
   build_utils.CheckOutput(sign_cmd)
 
 
-def AlignApk(zipalign_path, package_align, unaligned_path, final_path):
+def AlignApk(zipalign_path, unaligned_path, final_path):
+  # Note -p will page align native libraries (files ending with .so), but
+  # only those that are stored uncompressed.
   align_cmd = [
       zipalign_path,
-      '-f'
+      '-p',
+      '-f',
       ]
 
-  if package_align:
-    align_cmd += ['-p']
 
   align_cmd += [
       '4',  # 4 bytes
@@ -85,23 +60,13 @@
   parser = optparse.OptionParser()
   build_utils.AddDepfileOption(parser)
 
-  parser.add_option('--rezip-apk-jar-path',
-                    help='Path to the RezipApk jar file.')
   parser.add_option('--zipalign-path', help='Path to the zipalign tool.')
-  parser.add_option('--page-align-shared-libraries',
-                    action='store_true',
-                    help='Page align shared libraries.')
   parser.add_option('--unsigned-apk-path', help='Path to input unsigned APK.')
   parser.add_option('--final-apk-path',
       help='Path to output signed and aligned APK.')
   parser.add_option('--key-path', help='Path to keystore for signing.')
   parser.add_option('--key-passwd', help='Keystore password')
   parser.add_option('--key-name', help='Keystore name')
-  parser.add_option('--stamp', help='Path to touch on success.')
-  parser.add_option('--load-library-from-zip', type='int',
-      help='If non-zero, build the APK such that the library can be loaded ' +
-           'directly from the zip file using the crazy linker. The library ' +
-           'will be renamed, uncompressed and page aligned.')
 
   options, _ = parser.parse_args()
 
@@ -110,14 +75,9 @@
     options.key_path,
   ]
 
-  if options.load_library_from_zip:
-    input_paths.append(options.rezip_apk_jar_path)
-
   input_strings = [
-    options.load_library_from_zip,
     options.key_name,
     options.key_passwd,
-    options.page_align_shared_libraries,
   ]
 
   build_utils.CallAndWriteDepfileIfStale(
@@ -129,57 +89,34 @@
       output_paths=[options.final_apk_path])
 
 
+def _NormalizeZip(path):
+  with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk:
+    with zipfile.ZipFile(path, 'r') as zi:
+      with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo:
+        for info in zi.infolist():
+          # Ignore 'extended local file headers'. Python doesn't write them
+          # properly (see https://bugs.python.org/issue1742205) which causes
+          # zipalign to miscalculate alignment. Since we don't use them except
+          # for alignment anyway, we write a stripped file here and let
+          # zipalign add them properly later. eLFHs are controlled by 'general
+          # purpose bit flag 03' (0x08) so we mask that out.
+          info.flag_bits = info.flag_bits & 0xF7
+
+          info.date_time = build_utils.HERMETIC_TIMESTAMP
+          zo.writestr(info, zi.read(info.filename))
+
+    shutil.copy(hermetic_signed_apk.name, path)
+
+
 def FinalizeApk(options):
-  with tempfile.NamedTemporaryFile() as signed_apk_path_tmp, \
-      tempfile.NamedTemporaryFile() as apk_to_sign_tmp:
-
-    if options.load_library_from_zip:
-      # We alter the name of the library so that the Android Package Manager
-      # does not extract it into a separate file. This must be done before
-      # signing, as the filename is part of the signed manifest. At the same
-      # time we uncompress the library, which is necessary so that it can be
-      # loaded directly from the APK.
-      # Move the library to a page boundary by adding a page alignment file.
-      apk_to_sign = apk_to_sign_tmp.name
-      RenameInflateAndAddPageAlignment(
-          options.rezip_apk_jar_path, options.unsigned_apk_path, apk_to_sign)
-    else:
-      apk_to_sign = options.unsigned_apk_path
-
+  with tempfile.NamedTemporaryFile() as signed_apk_path_tmp:
     signed_apk_path = signed_apk_path_tmp.name
     JarSigner(options.key_path, options.key_name, options.key_passwd,
-              apk_to_sign, signed_apk_path)
+              options.unsigned_apk_path, signed_apk_path)
+    # Make the newly added signing files hermetic.
+    _NormalizeZip(signed_apk_path)
 
-    # Make the signing files hermetic.
-    with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk:
-      with zipfile.ZipFile(signed_apk_path, 'r') as zi:
-        with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo:
-          for info in zi.infolist():
-            # Ignore 'extended local file headers'. Python doesn't write them
-            # properly (see https://bugs.python.org/issue1742205) which causes
-            # zipalign to miscalculate alignment. Since we don't use them except
-            # for alignment anyway, we write a stripped file here and let
-            # zipalign add them properly later. eLFHs are controlled by 'general
-            # purpose bit flag 03' (0x08) so we mask that out.
-            info.flag_bits = info.flag_bits & 0xF7
-
-            info.date_time = build_utils.HERMETIC_TIMESTAMP
-            zo.writestr(info, zi.read(info.filename))
-
-      shutil.copy(hermetic_signed_apk.name, signed_apk_path)
-
-    if options.load_library_from_zip:
-      # Reorder the contents of the APK. This re-establishes the canonical
-      # order which means the library will be back at its page aligned location.
-      # This step also aligns uncompressed items to 4 bytes.
-      ReorderAndAlignApk(
-          options.rezip_apk_jar_path, signed_apk_path, options.final_apk_path)
-    else:
-      # Align uncompressed items to 4 bytes
-      AlignApk(options.zipalign_path,
-               options.page_align_shared_libraries,
-               signed_apk_path,
-               options.final_apk_path)
+    AlignApk(options.zipalign_path, signed_apk_path, options.final_apk_path)
 
 
 if __name__ == '__main__':
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 6c29b89..3a529af 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -291,6 +291,10 @@
       help='Whether this library should be treated as a prebuilt library by '
            'generate_gradle.py.')
   parser.add_option('--main-class', help='Java class for java_binary targets.')
+  parser.add_option('--java-resources-jar-path',
+                    help='Path to JAR that contains java resources. Everything '
+                    'from this JAR except meta-inf/ content and .class files '
+                    'will be added to the final APK.')
 
   # android library options
   parser.add_option('--dex-path', help='Path to target\'s dex output.')
@@ -677,6 +681,20 @@
     config['uncompressed_locales_java_list'] = (
         _CreateLocalePaksAssetJavaList(config['uncompressed_assets']))
 
+    # Collect java resources
+    java_resources_jars = [d['java_resources_jar'] for d in all_library_deps
+                          if 'java_resources_jar' in d]
+    if options.tested_apk_config:
+      tested_apk_resource_jars = [d['java_resources_jar']
+                                  for d in tested_apk_library_deps
+                                  if 'java_resources_jar' in d]
+      java_resources_jars = [jar for jar in java_resources_jars
+                             if jar not in tested_apk_resource_jars]
+    config['java_resources_jars'] = java_resources_jars
+
+  if options.type == 'java_library' and options.java_resources_jar_path:
+    deps_info['java_resources_jar'] = options.java_resources_jar_path
+
   build_utils.WriteJson(config, options.build_config, only_if_changed=True)
 
   if options.depfile:
diff --git a/build/android/rezip/BUILD.gn b/build/android/rezip/BUILD.gn
deleted file mode 100644
index 1ace37c..0000000
--- a/build/android/rezip/BUILD.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/android/rules.gni")
-
-java_library("rezip") {
-  jar_path = "$root_build_dir/lib.java/rezip_apk.jar"
-  java_files = [ "RezipApk.java" ]
-}
diff --git a/build/android/rezip/RezipApk.java b/build/android/rezip/RezipApk.java
deleted file mode 100644
index 43d75447..0000000
--- a/build/android/rezip/RezipApk.java
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.regex.Pattern;
-import java.util.zip.CRC32;
-
-/**
- * Command line tool used to build APKs which support loading the native code library
- * directly from the APK file. To construct the APK we rename the native library by
- * adding the prefix "crazy." to the filename. This is done to prevent the Android
- * Package Manager from extracting the library. The native code must be page aligned
- * and uncompressed. The page alignment is implemented by adding a zero filled file
- * in front of the the native code library. This tool is designed so that running
- * SignApk and/or zipalign on the resulting APK does not break the page alignment.
- * This is achieved by outputing the filenames in the same canonical order used
- * by SignApk and adding the same alignment fields added by zipalign.
- */
-class RezipApk {
-    // Alignment to use for non-compressed files (must match zipalign).
-    private static final int ALIGNMENT = 4;
-
-    // Alignment to use for non-compressed *.so files
-    private static final int LIBRARY_ALIGNMENT = 4096;
-
-    // Files matching this pattern are not copied to the output when adding alignment.
-    // When reordering and verifying the APK they are copied to the end of the file.
-    private static Pattern sMetaFilePattern =
-            Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert))|("
-                    + Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
-
-    // Pattern for matching a shared library in the APK
-    private static Pattern sLibraryPattern = Pattern.compile("^lib/[^/]*/lib.*[.]so$");
-    // Pattern for match the crazy linker in the APK
-    private static Pattern sCrazyLinkerPattern =
-            Pattern.compile("^lib/[^/]*/libchromium_android_linker.so$");
-    // Pattern for matching a crazy loaded shared library in the APK
-    private static Pattern sCrazyLibraryPattern = Pattern.compile("^lib/[^/]*/crazy.lib.*[.]so$");
-
-    private static boolean isLibraryFilename(String filename) {
-        return sLibraryPattern.matcher(filename).matches()
-                && !sCrazyLinkerPattern.matcher(filename).matches();
-    }
-
-    private static boolean isCrazyLibraryFilename(String filename) {
-        return sCrazyLibraryPattern.matcher(filename).matches();
-    }
-
-    private static String renameLibraryForCrazyLinker(String filename) {
-        int lastSlash = filename.lastIndexOf('/');
-        // We rename the library, so that the Android Package Manager
-        // no longer extracts the library.
-        return filename.substring(0, lastSlash + 1) + "crazy." + filename.substring(lastSlash + 1);
-    }
-
-    /**
-     * Wraps another output stream, counting the number of bytes written.
-     */
-    private static class CountingOutputStream extends OutputStream {
-        private long mCount = 0;
-        private OutputStream mOut;
-
-        public CountingOutputStream(OutputStream out) {
-            this.mOut = out;
-        }
-
-        /** Returns the number of bytes written. */
-        public long getCount() {
-            return mCount;
-        }
-
-        @Override public void write(byte[] b, int off, int len) throws IOException {
-            mOut.write(b, off, len);
-            mCount += len;
-        }
-
-        @Override public void write(int b) throws IOException {
-            mOut.write(b);
-            mCount++;
-        }
-
-        @Override public void close() throws IOException {
-            mOut.close();
-        }
-
-        @Override public void flush() throws IOException {
-            mOut.flush();
-        }
-    }
-
-    private static String outputName(JarEntry entry, boolean rename) {
-        String inName = entry.getName();
-        if (rename && entry.getSize() > 0 && isLibraryFilename(inName)) {
-            return renameLibraryForCrazyLinker(inName);
-        }
-        return inName;
-    }
-
-    /**
-     * Comparator used to sort jar entries from the input file.
-     * Sorting is done based on the output filename (which maybe renamed).
-     * Filenames are in natural string order, except that filenames matching
-     * the meta-file pattern are always after other files. This is so the manifest
-     * and signature are at the end of the file after any alignment file.
-     */
-    private static class EntryComparator implements Comparator<JarEntry> {
-        private boolean mRename;
-
-        public EntryComparator(boolean rename) {
-            mRename = rename;
-        }
-
-        @Override
-        public int compare(JarEntry j1, JarEntry j2) {
-            String o1 = outputName(j1, mRename);
-            String o2 = outputName(j2, mRename);
-            boolean o1Matches = sMetaFilePattern.matcher(o1).matches();
-            boolean o2Matches = sMetaFilePattern.matcher(o2).matches();
-            if (o1Matches != o2Matches) {
-                return o1Matches ? 1 : -1;
-            } else {
-                return o1.compareTo(o2);
-            }
-        }
-    }
-
-    // Build an ordered list of jar entries. The jar entries from the input are
-    // sorted based on the output filenames (which maybe renamed). If |omitMetaFiles|
-    // is true do not include the jar entries for the META-INF files.
-    // Entries are ordered in the deterministic order used by SignApk.
-    private static List<JarEntry> getOutputFileOrderEntries(
-            JarFile jar, boolean omitMetaFiles, boolean rename) {
-        List<JarEntry> entries = new ArrayList<JarEntry>();
-        for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
-            JarEntry entry = e.nextElement();
-            if (entry.isDirectory()) {
-                continue;
-            }
-            if (omitMetaFiles && sMetaFilePattern.matcher(entry.getName()).matches()) {
-                continue;
-            }
-            entries.add(entry);
-        }
-
-        // We sort the input entries by name. When present META-INF files
-        // are sorted to the end.
-        Collections.sort(entries, new EntryComparator(rename));
-        return entries;
-    }
-
-    /**
-     * Add a zero filled alignment file at this point in the zip file,
-     * The added file will be added before |name| and after |prevName|.
-     * The size of the alignment file is such that the location of the
-     * file |name| will be on a LIBRARY_ALIGNMENT boundary.
-     *
-     * Note this arrangement is devised so that running SignApk and/or zipalign on the resulting
-     * file will not alter the alignment.
-     *
-     * @param offset number of bytes into the output file at this point.
-     * @param timestamp time in millis since the epoch to include in the header.
-     * @param name the name of the library filename.
-     * @param prevName the name of the previous file in the archive (or null).
-     * @param out jar output stream to write the alignment file to.
-     *
-     * @throws IOException if the output file can not be written.
-     */
-    private static void addAlignmentFile(
-            long offset, long timestamp, String name, String prevName,
-            JarOutputStream out) throws IOException {
-
-        // Compute the start and alignment of the library, as if it was next.
-        int headerSize = JarFile.LOCHDR + name.length();
-        long libOffset = offset + headerSize;
-        int libNeeded = LIBRARY_ALIGNMENT - (int) (libOffset % LIBRARY_ALIGNMENT);
-        if (libNeeded == LIBRARY_ALIGNMENT) {
-            // Already aligned, no need to added alignment file.
-            return;
-        }
-
-        // Check that there is not another file between the library and the
-        // alignment file.
-        String alignName = name.substring(0, name.length() - 2) + "align";
-        if (prevName != null && prevName.compareTo(alignName) >= 0) {
-            throw new UnsupportedOperationException(
-                "Unable to insert alignment file, because there is "
-                + "another file in front of the file to be aligned. "
-                + "Other file: " + prevName + " Alignment file: " + alignName
-                + " file: " + name);
-        }
-
-        // Compute the size of the alignment file header.
-        headerSize = JarFile.LOCHDR + alignName.length();
-        // We are going to add an alignment file of type STORED. This file
-        // will itself induce a zipalign alignment adjustment.
-        int extraNeeded =
-                (ALIGNMENT - (int) ((offset + headerSize) % ALIGNMENT)) % ALIGNMENT;
-        headerSize += extraNeeded;
-
-        if (libNeeded < headerSize + 1) {
-            // The header was bigger than the alignment that we need, add another page.
-            libNeeded += LIBRARY_ALIGNMENT;
-        }
-        // Compute the size of the alignment file.
-        libNeeded -= headerSize;
-
-        // Build the header for the alignment file.
-        byte[] zeroBuffer = new byte[libNeeded];
-        JarEntry alignEntry = new JarEntry(alignName);
-        alignEntry.setMethod(JarEntry.STORED);
-        alignEntry.setSize(libNeeded);
-        alignEntry.setTime(timestamp);
-        CRC32 crc = new CRC32();
-        crc.update(zeroBuffer);
-        alignEntry.setCrc(crc.getValue());
-
-        if (extraNeeded != 0) {
-            alignEntry.setExtra(new byte[extraNeeded]);
-        }
-
-        // Output the alignment file.
-        out.putNextEntry(alignEntry);
-        out.write(zeroBuffer);
-        out.closeEntry();
-        out.flush();
-    }
-
-    // Make a JarEntry for the output file which corresponds to the input
-    // file. The output file will be called |name|. The output file will always
-    // be uncompressed (STORED). If the input is not STORED it is necessary to inflate
-    // it to compute the CRC and size of the output entry.
-    private static JarEntry makeStoredEntry(String name, JarEntry inEntry, JarFile in)
-            throws IOException {
-        JarEntry outEntry = new JarEntry(name);
-        outEntry.setMethod(JarEntry.STORED);
-
-        if (inEntry.getMethod() == JarEntry.STORED) {
-            outEntry.setCrc(inEntry.getCrc());
-            outEntry.setSize(inEntry.getSize());
-        } else {
-            // We are inflating the file. We need to compute the CRC and size.
-            byte[] buffer = new byte[4096];
-            CRC32 crc = new CRC32();
-            int size = 0;
-            int num;
-            InputStream data = in.getInputStream(inEntry);
-            while ((num = data.read(buffer)) > 0) {
-                crc.update(buffer, 0, num);
-                size += num;
-            }
-            data.close();
-            outEntry.setCrc(crc.getValue());
-            outEntry.setSize(size);
-        }
-        return outEntry;
-    }
-
-    /**
-     * Copy the contents of the input APK file to the output APK file. If |rename| is
-     * true then non-empty libraries (*.so) in the input will be renamed by prefixing
-     * "crazy.". This is done to prevent the Android Package Manager extracting the
-     * library. Note the crazy linker itself is not renamed, for bootstrapping reasons.
-     * Empty libraries are not renamed (they are in the APK to workaround a bug where
-     * the Android Package Manager fails to delete old versions when upgrading).
-     * There must be exactly one "crazy" library in the output stream. The "crazy"
-     * library will be uncompressed and page aligned in the output stream. Page
-     * alignment is implemented by adding a zero filled file, regular alignment is
-     * implemented by adding a zero filled extra field to the zip file header. If
-     * |addAlignment| is true a page alignment file is added, otherwise the "crazy"
-     * library must already be page aligned. Care is taken so that the output is generated
-     * in the same way as SignApk. This is important so that running SignApk and
-     * zipalign on the output does not break the page alignment. The archive may not
-     * contain a "*.apk" as SignApk has special nested signing logic that we do not
-     * support.
-     *
-     * @param in The input APK File.
-     * @param out The output APK stream.
-     * @param countOut Counting output stream (to measure the current offset).
-     * @param addAlignment Whether to add the alignment file or just check.
-     * @param rename Whether to rename libraries to be "crazy".
-     *
-     * @throws IOException if the output file can not be written.
-     */
-    private static void rezip(
-            JarFile in, JarOutputStream out, CountingOutputStream countOut,
-            boolean addAlignment, boolean rename) throws IOException {
-
-        List<JarEntry> entries = getOutputFileOrderEntries(in, addAlignment, rename);
-        long timestamp = System.currentTimeMillis();
-        byte[] buffer = new byte[4096];
-        boolean firstEntry = true;
-        String prevName = null;
-        int numCrazy = 0;
-        for (JarEntry inEntry : entries) {
-            // Rename files, if specied.
-            String name = outputName(inEntry, rename);
-            if (name.endsWith(".apk")) {
-                throw new UnsupportedOperationException(
-                        "Nested APKs are not supported: " + name);
-            }
-
-            // Build the header.
-            JarEntry outEntry = null;
-            boolean isCrazy = isCrazyLibraryFilename(name);
-            if (isCrazy) {
-                // "crazy" libraries are alway output uncompressed (STORED).
-                outEntry = makeStoredEntry(name, inEntry, in);
-                numCrazy++;
-                if (numCrazy > 1) {
-                    throw new UnsupportedOperationException(
-                            "Found more than one library\n"
-                            + "Multiple libraries are not supported for APKs that use "
-                            + "'load_library_from_zip'.\n"
-                            + "See crbug/388223.\n"
-                            + "Note, check that your build is clean.\n"
-                            + "An unclean build can incorrectly incorporate old "
-                            + "libraries in the APK.");
-                }
-            } else if (inEntry.getMethod() == JarEntry.STORED) {
-                // Preserve the STORED method of the input entry.
-                outEntry = new JarEntry(inEntry);
-                outEntry.setExtra(null);
-            } else {
-                // Create a new entry so that the compressed len is recomputed.
-                outEntry = new JarEntry(name);
-            }
-            outEntry.setTime(timestamp);
-
-            // Compute and add alignment
-            long offset = countOut.getCount();
-            if (firstEntry) {
-                // The first entry in a jar file has an extra field of
-                // four bytes that you can't get rid of; any extra
-                // data you specify in the JarEntry is appended to
-                // these forced four bytes.  This is JAR_MAGIC in
-                // JarOutputStream; the bytes are 0xfeca0000.
-                firstEntry = false;
-                offset += 4;
-            }
-            if (outEntry.getMethod() == JarEntry.STORED) {
-                if (isCrazy) {
-                    if (addAlignment) {
-                        addAlignmentFile(offset, timestamp, name, prevName, out);
-                    }
-                    // We check that we did indeed get to a page boundary.
-                    offset = countOut.getCount() + JarFile.LOCHDR + name.length();
-                    if ((offset % LIBRARY_ALIGNMENT) != 0) {
-                        throw new AssertionError(
-                                "Library was not page aligned when verifying page alignment. "
-                                + "Library name: " + name + " Expected alignment: "
-                                + LIBRARY_ALIGNMENT + "Offset: " + offset + " Error: "
-                                + (offset % LIBRARY_ALIGNMENT));
-                    }
-                } else {
-                    // This is equivalent to zipalign.
-                    offset += JarFile.LOCHDR + name.length();
-                    int needed = (ALIGNMENT - (int) (offset % ALIGNMENT)) % ALIGNMENT;
-                    if (needed != 0) {
-                        outEntry.setExtra(new byte[needed]);
-                    }
-                }
-            }
-            out.putNextEntry(outEntry);
-
-            // Copy the data from the input to the output
-            int num;
-            InputStream data = in.getInputStream(inEntry);
-            while ((num = data.read(buffer)) > 0) {
-                out.write(buffer, 0, num);
-            }
-            data.close();
-            out.closeEntry();
-            out.flush();
-            prevName = name;
-        }
-        if (numCrazy == 0) {
-            throw new AssertionError("There was no crazy library in the archive");
-        }
-    }
-
-    private static void usage() {
-        System.err.println("Usage: prealignapk (addalignment|reorder) input.apk output.apk");
-        System.err.println("\"crazy\" libraries are always inflated in the output");
-        System.err.println(
-                "  renamealign  - rename libraries with \"crazy.\" prefix and add alignment file");
-        System.err.println("  align        - add alignment file");
-        System.err.println("  reorder      - re-creates canonical ordering and checks alignment");
-        System.exit(2);
-    }
-
-    public static void main(String[] args) throws IOException {
-        if (args.length != 3) usage();
-
-        boolean addAlignment = false;
-        boolean rename = false;
-        if (args[0].equals("renamealign")) {
-            // Normal case. Before signing we rename the library and add an alignment file.
-            addAlignment = true;
-            rename = true;
-        } else if (args[0].equals("align")) {
-            // LGPL compliance case. Before signing, we add an alignment file to a
-            // reconstructed APK which already contains the "crazy" library.
-            addAlignment = true;
-            rename = false;
-        } else if (args[0].equals("reorder")) {
-            // Normal case. After jarsigning we write the file in the canonical order and check.
-            addAlignment = false;
-        } else {
-            usage();
-        }
-
-        String inputFilename = args[1];
-        String outputFilename = args[2];
-
-        JarFile inputJar = null;
-        FileOutputStream outputFile = null;
-
-        try {
-            inputJar = new JarFile(new File(inputFilename), true);
-            outputFile = new FileOutputStream(outputFilename);
-
-            CountingOutputStream outCount = new CountingOutputStream(outputFile);
-            JarOutputStream outputJar = new JarOutputStream(outCount);
-
-            // Match the compression level used by SignApk.
-            outputJar.setLevel(9);
-
-            rezip(inputJar, outputJar, outCount, addAlignment, rename);
-            outputJar.close();
-        } finally {
-            if (inputJar != null) inputJar.close();
-            if (outputFile != null) outputFile.close();
-        }
-    }
-}
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index a662457..102e98c 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -32,7 +32,6 @@
 
   # TODO(agrieve): Rename targets below to match above patterns.
   "*android_webview/glue:glue",
-  "//build/android/rezip:rezip",
   "//chrome/test/android/cast_emulator:cast_emulator",
 ]
 
@@ -178,6 +177,12 @@
       ]
     }
 
+    if (is_java && defined(invoker.java_resources_jar)) {
+      args += [
+        "--java-resources-jar-path",
+        rebase_path(invoker.java_resources_jar, root_build_dir),
+      ]
+    }
     if (is_apk || is_deps_dex || (is_java && supports_android)) {
       args += [
         "--dex-path",
@@ -1339,6 +1344,10 @@
           "--assets=@FileArg($_rebased_build_config:assets)",
           "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)",
         ]
+
+        # TODO(mlopatkin) We are relying on the fact that assets_build_config is
+        # an APK build_config.
+        args += [ "--java-resources=@FileArg($_rebased_build_config:java_resources_jars)" ]
       }
       if (defined(invoker.write_asset_list) && invoker.write_asset_list) {
         args += [ "--write-asset-list" ]
@@ -1380,12 +1389,6 @@
         ]
       }
 
-      if (defined(invoker.emma_instrument) && invoker.emma_instrument) {
-        _emma_device_jar = "$android_sdk_root/tools/lib/emma_device.jar"
-        _rebased_emma_device_jar = rebase_path(_emma_device_jar, root_build_dir)
-        args += [ "--emma-device-jar=$_rebased_emma_device_jar" ]
-      }
-
       if (defined(invoker.uncompress_shared_libraries) &&
           invoker.uncompress_shared_libraries) {
         args += [ "--uncompress-shared-libraries" ]
@@ -1401,7 +1404,6 @@
   #   keystore_path: Path to keystore to use for signing.
   #   keystore_name: Key alias to use.
   #   keystore_password: Keystore password.
-  #   rezip_apk: Whether to add crazy-linker alignment.
   template("finalize_apk") {
     action(target_name) {
       deps = []
@@ -1444,20 +1446,6 @@
         "--key-passwd",
         invoker.keystore_password,
       ]
-      if (defined(invoker.rezip_apk) && invoker.rezip_apk) {
-        deps += [ "//build/android/rezip" ]
-        _rezip_jar_path = "$root_build_dir/lib.java/rezip_apk.jar"
-        args += [
-          "--load-library-from-zip=1",
-          "--rezip-apk-jar-path",
-          rebase_path(_rezip_jar_path, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.page_align_shared_libraries) &&
-          invoker.page_align_shared_libraries) {
-        args += [ "--page-align-shared-libraries" ]
-      }
     }
   }
 
@@ -1697,7 +1685,6 @@
       forward_variables_from(invoker,
                              [
                                "assets_build_config",
-                               "emma_instrument",
                                "native_lib_placeholders",
                                "native_libs_filearg",
                                "secondary_abi_native_libs_filearg",
@@ -1705,6 +1692,9 @@
                                "uncompress_shared_libraries",
                                "write_asset_list",
                              ])
+      if (!defined(uncompress_shared_libraries)) {
+        uncompress_shared_libraries = _load_library_from_apk
+      }
       deps = _deps + [ ":${_package_resources_target_name}" ]
       native_libs = _native_libs + _native_libs_even_when_incremental
 
@@ -1721,10 +1711,12 @@
       forward_variables_from(invoker,
                              [
                                "assets_build_config",
-                               "emma_instrument",
                                "secondary_native_libs",
                                "uncompress_shared_libraries",
                              ])
+      if (!defined(uncompress_shared_libraries)) {
+        uncompress_shared_libraries = _load_library_from_apk
+      }
       _dex_target = "//build/android/incremental_install:bootstrap_java__dex"
       deps = _incremental_deps + [
                ":${_incremental_package_resources_target_name}",
@@ -1751,14 +1743,11 @@
 
     _finalize_apk_rule_name = "${target_name}__finalize"
     finalize_apk(_finalize_apk_rule_name) {
-      forward_variables_from(invoker, [ "page_align_shared_libraries" ])
-
       input_apk_path = _packaged_apk_path
       output_apk_path = _final_apk_path
       keystore_path = _keystore_path
       keystore_name = _keystore_name
       keystore_password = _keystore_password
-      rezip_apk = _load_library_from_apk
 
       public_deps = [
         # Generator of the _packaged_apk_path this target takes as input.
@@ -1887,6 +1876,12 @@
       if (_supports_android) {
         dex_path = _dex_path
       }
+      if (defined(invoker.include_java_resources) &&
+          invoker.include_java_resources) {
+        # Use original jar_path because _jar_path points to a library without
+        # resources.
+        java_resources_jar = invoker.jar_path
+      }
     }
 
     process_java_prebuilt(_process_jar_target_name) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 43279e8..1db01006 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -2018,15 +2018,7 @@
     _extra_native_libs_deps = []
     assert(_extra_native_libs_deps == [])  # Mark as used.
     _extra_native_libs_even_when_incremental = []
-    _extra_native_libs_even_when_incremental_deps = []
-    assert(_extra_native_libs_even_when_incremental_deps == [])  # Mark as used.
     if (_native_libs_deps != []) {
-      # zipalign can't align gdb_server, don't pack gdbserver temporarily.
-      if (is_debug && (!defined(invoker.page_align_shared_libraries) ||
-                       !invoker.page_align_shared_libraries)) {
-        _extra_native_libs_even_when_incremental = [ android_gdbserver ]
-      }
-
       if (_use_chromium_linker) {
         _extra_native_libs =
             [ "$root_shlib_dir/libchromium_android_linker$shlib_extension" ]
@@ -2049,7 +2041,6 @@
                                "deps",
                                "extensions_to_not_compress",
                                "language_splits",
-                               "page_align_shared_libraries",
                                "public_deps",
                                "secondary_native_libs",
                                "shared_resources",
@@ -2066,7 +2057,6 @@
       dex_path = final_dex_path
       load_library_from_apk = _load_library_from_apk
       create_density_splits = _create_density_splits
-      emma_instrument = emma_coverage && !_emma_never_instrument
 
       if (!defined(extensions_to_not_compress)) {
         # Allow icu data, v8 snapshots, and pak files to be loaded directly from
@@ -2099,7 +2089,6 @@
            _extra_native_libs_even_when_incremental != []) &&
           !_create_abi_split) {
         deps += _native_libs_deps + _extra_native_libs_deps +
-                _extra_native_libs_even_when_incremental_deps +
                 [ _native_libs_file_arg_dep ]
         native_libs_filearg = _native_libs_file_arg
         native_libs = _extra_native_libs
@@ -2160,9 +2149,7 @@
                                  "public_deps",
                                ])
 
-        incremental_deps =
-            deps + _extra_native_libs_even_when_incremental_deps +
-            [ ":$_manifest_rule" ]
+        incremental_deps = deps + [ ":$_manifest_rule" ]
         deps = []
         deps = incremental_deps + _native_libs_deps + _extra_native_libs_deps +
                [ _native_libs_file_arg_dep ]
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index ce631b6c..a28fad5d 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -39,6 +39,7 @@
 
 android_java_prebuilt("emma_device_java") {
   jar_path = "$android_sdk_root/tools/lib/emma_device.jar"
+  include_java_resources = true
 }
 
 android_aar_prebuilt("android_support_design_java") {
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 434e0b9e..8605c86 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -156,7 +156,7 @@
 }
 
 int RenderSurfaceImpl::ClipTreeIndex() const {
-  return owning_layer_->clip_tree_index();
+  return OwningEffectNode()->clip_id;
 }
 
 int RenderSurfaceImpl::EffectTreeIndex() const {
@@ -349,12 +349,12 @@
 }
 
 int RenderSurfaceImpl::GetRenderPassId() {
-  return owning_layer_->id();
+  return id();
 }
 
 void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) {
   std::unique_ptr<RenderPass> pass = RenderPass::Create(layer_list_.size());
-  pass->SetNew(owning_layer_->id(), content_rect(),
+  pass->SetNew(id(), content_rect(),
                gfx::IntersectRects(content_rect(),
                                    damage_tracker_->current_damage_rect()),
                draw_properties_.screen_space_transform);
diff --git a/cc/trees/clip_node.cc b/cc/trees/clip_node.cc
index c7f85bf..f643013 100644
--- a/cc/trees/clip_node.cc
+++ b/cc/trees/clip_node.cc
@@ -5,6 +5,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/math_util.h"
+#include "cc/layers/layer.h"
 #include "cc/proto/cc_conversions.h"
 #include "cc/proto/gfx_conversions.h"
 #include "cc/trees/clip_node.h"
@@ -13,13 +14,13 @@
 namespace cc {
 
 ClipNode::ClipNode()
-    : id(-1),
-      parent_id(-1),
-      owning_layer_id(-1),
+    : id(ClipTree::kInvalidNodeId),
+      parent_id(ClipTree::kInvalidNodeId),
+      owning_layer_id(Layer::INVALID_ID),
       clip_type(ClipType::NONE),
-      transform_id(-1),
-      target_transform_id(-1),
-      target_effect_id(-1),
+      transform_id(TransformTree::kInvalidNodeId),
+      target_transform_id(TransformTree::kInvalidNodeId),
+      target_effect_id(EffectTree::kInvalidNodeId),
       layer_clipping_uses_only_local_clip(false),
       layers_are_clipped(false),
       layers_are_clipped_when_surfaces_disabled(false),
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 84b3e8f..9251bef 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -1457,8 +1457,7 @@
 
   const ClipNode* clip_node =
       property_trees->clip_tree.Node(render_surface->ClipTreeIndex());
-  SetSurfaceClipRect(property_trees->clip_tree.parent(clip_node),
-                     property_trees, render_surface);
+  SetSurfaceClipRect(clip_node, property_trees, render_surface);
 }
 
 #if DCHECK_IS_ON()
diff --git a/cc/trees/effect_node.cc b/cc/trees/effect_node.cc
index fa5ce228..e284ac6e 100644
--- a/cc/trees/effect_node.cc
+++ b/cc/trees/effect_node.cc
@@ -3,16 +3,18 @@
 // found in the LICENSE file.
 
 #include "base/trace_event/trace_event_argument.h"
+#include "cc/layers/layer.h"
 #include "cc/proto/gfx_conversions.h"
 #include "cc/proto/skia_conversions.h"
 #include "cc/trees/effect_node.h"
+#include "cc/trees/property_tree.h"
 
 namespace cc {
 
 EffectNode::EffectNode()
-    : id(-1),
-      parent_id(-1),
-      owning_layer_id(-1),
+    : id(EffectTree::kInvalidNodeId),
+      parent_id(EffectTree::kInvalidNodeId),
+      owning_layer_id(Layer::INVALID_ID),
       opacity(1.f),
       screen_space_opacity(1.f),
       blend_mode(SkBlendMode::kSrcOver),
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index d589a3a9..97dc00ea 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -10656,7 +10656,6 @@
                                                  parent2, nullptr);
   ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root1.get());
 
-  const int kInvalidPropertyTreeNodeId = -1;
   const int kRootPropertyTreeNodeId = 0;
 
   // Property tree root
@@ -10667,8 +10666,8 @@
   ScrollTree& expected_scroll_tree = property_trees.scroll_tree;
   ScrollNode* property_tree_root = expected_scroll_tree.Node(0);
   property_tree_root->id = kRootPropertyTreeNodeId;
-  property_tree_root->parent_id = kInvalidPropertyTreeNodeId;
-  property_tree_root->owning_layer_id = kInvalidPropertyTreeNodeId;
+  property_tree_root->parent_id = ScrollTree::kInvalidNodeId;
+  property_tree_root->owning_layer_id = Layer::INVALID_ID;
   property_tree_root->scrollable = false;
   property_tree_root->main_thread_scrolling_reasons =
       MainThreadScrollingReason::kNotScrollingOnMain;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 8602c5d..edf102ef 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -585,7 +585,7 @@
       device_viewport_point, type, layer_impl, &scroll_on_main_thread,
       &main_thread_scrolling_reasons);
 
-  if (!test_layer_impl)
+  if (scroll_on_main_thread)
     return false;
 
   if (scrolling_layer_impl == test_layer_impl)
@@ -1664,7 +1664,6 @@
     }
   }
 
-
   CompositorFrame compositor_frame;
   compositor_frame.metadata = std::move(metadata);
   resource_provider_->PrepareSendToParent(resources,
@@ -2534,7 +2533,7 @@
 
   // Walk up the hierarchy and look for a scrollable layer.
   ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree;
-  LayerImpl* potentially_scrolling_layer_impl = NULL;
+  LayerImpl* potentially_scrolling_layer_impl = nullptr;
   if (layer_impl) {
     ScrollNode* scroll_node = scroll_tree.Node(layer_impl->scroll_tree_index());
     for (; scroll_tree.parent(scroll_node);
@@ -2546,7 +2545,7 @@
       if (IsMainThreadScrolling(status, scroll_node)) {
         *scroll_on_main_thread = true;
         *main_thread_scrolling_reasons = status.main_thread_scrolling_reasons;
-        return NULL;
+        return active_tree_->LayerById(scroll_node->owning_layer_id);
       }
 
       if (status.thread == InputHandler::SCROLL_ON_IMPL_THREAD &&
@@ -2575,7 +2574,6 @@
     if (IsMainThreadScrolling(status, scroll_node)) {
       *scroll_on_main_thread = true;
       *main_thread_scrolling_reasons = status.main_thread_scrolling_reasons;
-      return NULL;
     }
   }
 
@@ -2687,15 +2685,15 @@
         device_viewport_point, type, layer_impl, &scroll_on_main_thread,
         &scroll_status.main_thread_scrolling_reasons);
   }
-  if (scrolling_layer_impl)
-    scroll_affects_scroll_handler_ =
-        scrolling_layer_impl->layer_tree_impl()->have_scroll_event_handlers();
 
   if (scroll_on_main_thread) {
     RecordCompositorSlowScrollMetric(type, MAIN_THREAD);
 
     scroll_status.thread = SCROLL_ON_MAIN_THREAD;
     return scroll_status;
+  } else if (scrolling_layer_impl) {
+    scroll_affects_scroll_handler_ =
+        scrolling_layer_impl->layer_tree_impl()->have_scroll_event_handlers();
   }
 
   return ScrollBeginImpl(scroll_state, scrolling_layer_impl, type);
@@ -3251,7 +3249,7 @@
   // Check if mouse is over a scrollbar or not.
   // TODO(sahel): get rid of this extera checking when
   // FindScrollLayerForDeviceViewportPoint finds the proper layer for
-  // scrolling on main thread, as well.
+  // scrolling on main thread when mouse is over scrollbar as well.
   int new_id = Layer::INVALID_ID;
   if (layer_impl && layer_impl->ToScrollbarLayer())
     new_id = layer_impl->ToScrollbarLayer()->ScrollLayerId();
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 3f839f8..79f9496 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -463,6 +463,8 @@
 
   void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
 
+  void SetupMouseMoveAtTestScrollbarStates(bool main_thread_scrolling);
+
   scoped_refptr<AnimationTimeline> timeline() { return timeline_; }
 
  protected:
@@ -11600,7 +11602,8 @@
   EXPECT_FALSE(host_impl_->use_gpu_rasterization());
 }
 
-TEST_F(LayerTreeHostImplTest, LayerTreeHostImplTestScrollbarStates) {
+void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates(
+    bool main_thread_scrolling) {
   LayerTreeSettings settings = DefaultSettings();
   settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500);
   settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300);
@@ -11626,6 +11629,11 @@
   LayerImpl* root_scroll =
       host_impl_->active_tree()->OuterViewportScrollLayer();
 
+  if (main_thread_scrolling) {
+    root_scroll->set_main_thread_scrolling_reasons(
+        MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
+  }
+
   // scrollbar_1 on root scroll.
   std::unique_ptr<SolidColorScrollbarLayerImpl> scrollbar_1 =
       SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(),
@@ -11684,6 +11692,11 @@
   child->SetDrawsContent(true);
   child->SetScrollClipLayer(child_clip_id);
 
+  if (main_thread_scrolling) {
+    child->set_main_thread_scrolling_reasons(
+        MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
+  }
+
   scrollbar_2->SetScrollLayerId(child_scroll_id);
   scrollbar_2->SetDrawsContent(true);
   scrollbar_2->SetBounds(scrollbar_size_2);
@@ -11725,5 +11738,15 @@
   EXPECT_FALSE(scrollbar_2_animation_controller->mouse_is_over_scrollbar());
 }
 
+TEST_F(LayerTreeHostImplTest,
+       LayerTreeHostImplTestScrollbarStatesInMainThreadScorlling) {
+  SetupMouseMoveAtTestScrollbarStates(true);
+}
+
+TEST_F(LayerTreeHostImplTest,
+       LayerTreeHostImplTestScrollbarStatesInNotMainThreadScorlling) {
+  SetupMouseMoveAtTestScrollbarStates(false);
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 0344d8f..e041ce32 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -156,7 +156,7 @@
   DidUpdateScrollState(layer_id);
   TransformTree& transform_tree = property_trees()->transform_tree;
   ScrollTree& scroll_tree = property_trees()->scroll_tree;
-  int transform_id = -1;
+  int transform_id = TransformTree::kInvalidNodeId;
 
   // If pending tree topology changed and we still want to notify the pending
   // tree about scroll offset in the active tree, we may not find the
@@ -171,7 +171,7 @@
     return;
   }
 
-  if (transform_id != -1) {
+  if (transform_id != TransformTree::kInvalidNodeId) {
     TransformNode* node = transform_tree.Node(transform_id);
     if (node->scroll_offset != scroll_tree.current_scroll_offset(layer_id)) {
       node->scroll_offset = scroll_tree.current_scroll_offset(layer_id);
@@ -617,7 +617,8 @@
   ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode();
   int old_id = scroll_node ? scroll_node->owning_layer_id : Layer::INVALID_ID;
   int new_id = layer ? layer->id() : Layer::INVALID_ID;
-  int new_scroll_node_id = layer ? layer->scroll_tree_index() : -1;
+  int new_scroll_node_id =
+      layer ? layer->scroll_tree_index() : ScrollTree::kInvalidNodeId;
   if (layer)
     last_scrolled_layer_id_ = new_id;
 
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index e56c0e42..1bef82ef 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -923,7 +923,7 @@
     // the surface to the space of the surface itself.
     int destination_id = effect_node->transform_id;
     int source_id;
-    if (effect_node->parent_id != -1) {
+    if (effect_node->parent_id != EffectTree::kInvalidNodeId) {
       // For non-root surfaces, transform only by sub-layer scale.
       source_id = destination_id;
     } else {
@@ -968,7 +968,7 @@
   if (node->has_copy_request)
     return node->id;
   else
-    return -1;
+    return EffectTree::kInvalidNodeId;
 }
 
 void EffectTree::AddMaskLayerId(int id) {
@@ -1981,9 +1981,10 @@
     int dest_id) const {
   for (auto& transform_data : cached_data_.draw_transforms[transform_id]) {
     // We initialize draw_transforms with 1 element vectors when
-    // ResetCachedData, so if we hit a -1 target id, it means it's the first
-    // time we compute draw transforms after reset.
-    if (transform_data.target_id == dest_id || transform_data.target_id == -1) {
+    // ResetCachedData, so if we hit an invalid target id, it means it's the
+    // first time we compute draw transforms after reset.
+    if (transform_data.target_id == dest_id ||
+        transform_data.target_id == EffectTree::kInvalidNodeId) {
       return transform_data;
     }
   }
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index e2c12539..d68bb307 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -533,7 +533,7 @@
   // performance.
   DrawTransformData()
       : update_number(-1),
-        target_id(-1),
+        target_id(EffectTree::kInvalidNodeId),
         transforms(gfx::Transform(), gfx::Transform()) {}
 };
 
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 1e6cb286..bcf5615b 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -30,7 +30,6 @@
 
 namespace {
 
-static const int kInvalidPropertyTreeNodeId = -1;
 static const int kRootPropertyTreeNodeId = 0;
 static const int kViewportClipTreeNodeId = 1;
 
@@ -670,7 +669,7 @@
                     ->transform_id);
   DCHECK_NE(
       data_for_children->property_trees->transform_tree.TargetId(node->id),
-      kInvalidPropertyTreeNodeId);
+      TransformTree::kInvalidNodeId);
 
   node->has_potential_animation = has_potentially_animated_transform;
   node->is_currently_animating = TransformIsAnimating(layer);
@@ -1173,7 +1172,7 @@
     if (layer->scroll_clip_layer()) {
       clip_bounds = layer->scroll_clip_layer()->bounds();
       DCHECK(layer->scroll_clip_layer()->transform_tree_index() !=
-             kInvalidPropertyTreeNodeId);
+             TransformTree::kInvalidNodeId);
       node.max_scroll_offset_affected_by_page_scale =
           !data_from_ancestor.property_trees->transform_tree
                .Node(layer->scroll_clip_layer()->transform_tree_index())
@@ -1427,7 +1426,7 @@
   data_for_recursion.transform_fixed_parent = nullptr;
   data_for_recursion.render_target = kRootPropertyTreeNodeId;
   data_for_recursion.clip_tree_parent = kRootPropertyTreeNodeId;
-  data_for_recursion.effect_tree_parent = kInvalidPropertyTreeNodeId;
+  data_for_recursion.effect_tree_parent = EffectTree::kInvalidNodeId;
   data_for_recursion.scroll_tree_parent = kRootPropertyTreeNodeId;
   data_for_recursion.page_scale_layer = page_scale_layer;
   data_for_recursion.inner_viewport_scroll_layer = inner_viewport_scroll_layer;
diff --git a/cc/trees/scroll_node.cc b/cc/trees/scroll_node.cc
index 0e0c7777..7b46d12b 100644
--- a/cc/trees/scroll_node.cc
+++ b/cc/trees/scroll_node.cc
@@ -5,16 +5,18 @@
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/math_util.h"
 #include "cc/input/main_thread_scrolling_reason.h"
+#include "cc/layers/layer.h"
 #include "cc/proto/gfx_conversions.h"
 #include "cc/trees/element_id.h"
+#include "cc/trees/property_tree.h"
 #include "cc/trees/scroll_node.h"
 
 namespace cc {
 
 ScrollNode::ScrollNode()
-    : id(-1),
-      parent_id(-1),
-      owning_layer_id(-1),
+    : id(ScrollTree::kInvalidNodeId),
+      parent_id(ScrollTree::kInvalidNodeId),
+      owning_layer_id(Layer::INVALID_ID),
       scrollable(false),
       main_thread_scrolling_reasons(
           MainThreadScrollingReason::kNotScrollingOnMain),
diff --git a/cc/trees/transform_node.cc b/cc/trees/transform_node.cc
index 97b5cf9f..83d25ec 100644
--- a/cc/trees/transform_node.cc
+++ b/cc/trees/transform_node.cc
@@ -4,18 +4,20 @@
 
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/base/math_util.h"
+#include "cc/layers/layer.h"
 #include "cc/proto/gfx_conversions.h"
+#include "cc/trees/property_tree.h"
 #include "cc/trees/transform_node.h"
 #include "ui/gfx/geometry/point3_f.h"
 
 namespace cc {
 
 TransformNode::TransformNode()
-    : id(-1),
-      parent_id(-1),
-      owning_layer_id(-1),
+    : id(TransformTree::kInvalidNodeId),
+      parent_id(TransformTree::kInvalidNodeId),
+      owning_layer_id(Layer::INVALID_ID),
       sticky_position_constraint_id(-1),
-      source_node_id(-1),
+      source_node_id(TransformTree::kInvalidNodeId),
       sorting_context_id(0),
       needs_local_transform_update(true),
       node_and_ancestors_are_animated_or_invertible(true),
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 7dafeeb2..01d5f66a 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -111,7 +111,6 @@
 
     # Configrations to make android load shared library from APK.
     uncompress_shared_libraries = true
-    page_align_shared_libraries = true
 
     forward_variables_from(invoker, "*")
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
index a04a76d1..d0ec482 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
@@ -678,10 +678,9 @@
         return nativeSetCreditCard(mPersonalDataManagerAndroid, card);
     }
 
-    public void updateServerCardBillingAddress(String cardServerId, String billingAddressId) {
+    public void updateServerCardBillingAddress(CreditCard card) {
         ThreadUtils.assertOnUiThread();
-        nativeUpdateServerCardBillingAddress(
-                mPersonalDataManagerAndroid, cardServerId, billingAddressId);
+        nativeUpdateServerCardBillingAddress(mPersonalDataManagerAndroid, card);
     }
 
     public String getBasicCardPaymentType(String cardNumber, boolean emptyIfInvalid) {
@@ -908,7 +907,7 @@
     private native String nativeSetCreditCard(long nativePersonalDataManagerAndroid,
             CreditCard card);
     private native void nativeUpdateServerCardBillingAddress(long nativePersonalDataManagerAndroid,
-            String guid, String billingAddressId);
+            CreditCard card);
     private native String nativeGetBasicCardPaymentType(
             long nativePersonalDataManagerAndroid, String cardNumber, boolean emptyIfInvalid);
     private native void nativeAddServerCreditCardForTest(long nativePersonalDataManagerAndroid,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardsVariationParameters.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardsVariationParameters.java
index f2da715..0681a57 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardsVariationParameters.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardsVariationParameters.java
@@ -7,12 +7,18 @@
 import android.text.TextUtils;
 
 import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.components.variations.VariationsAssociatedData;
 
+import java.util.Map;
+
 /**
  * Provides easy access to data for field trials to do with the Cards UI.
  */
 public final class CardsVariationParameters {
+    /** Map that stores substitution values for params. */
+    private static Map<String, String> sTestVariationParams;
+
     // Tags are limited to 20 characters.
     private static final String TAG = "CardsVariationParams";
 
@@ -24,6 +30,8 @@
     private static final String PARAM_FIRST_CARD_ANIMATION_MAX_RUNS =
             "first_card_animation_max_runs";
     private static final String PARAM_SCROLL_BELOW_THE_FOLD = "scroll_below_the_fold";
+    private static final String PARAM_IGNORE_UPDATES_FOR_EXISTING_SUGGESTIONS =
+            "ignore_updates_for_existing_suggestions";
 
     private static final String PARAM_DISABLED_VALUE = "off";
 
@@ -31,6 +39,16 @@
 
     private CardsVariationParameters() {}
 
+    // TODO(jkrcal): Do a proper general fix in VariationsAssociatedData in the spirit of
+    // @EnableFeatures and ChromeFeatureList.
+    /**
+     * Sets the parameter values to use in JUnit tests, since native calls are not available there.
+     */
+    @VisibleForTesting
+    public static void setTestVariationParams(Map<String, String> variationParams) {
+        sTestVariationParams = variationParams;
+    }
+
     /**
      * Provides the value of the field trial to offset the peeking card (can be overridden
      * with a command line flag). It will return 0 if there is no such field trial.
@@ -50,19 +68,23 @@
      * @return Whether the NTP should initially be scrolled below the fold.
      */
     public static boolean isScrollBelowTheFoldEnabled() {
-        return Boolean.parseBoolean(VariationsAssociatedData.getVariationParamValue(
-                FIELD_TRIAL_NAME, PARAM_SCROLL_BELOW_THE_FOLD));
+        return Boolean.parseBoolean(getParamValue(PARAM_SCROLL_BELOW_THE_FOLD));
+    }
+
+    /**
+     * @return Whether the NTP should ignore updates for suggestions that have not been seen yet.
+     */
+    public static boolean ignoreUpdatesForExistingSuggestions() {
+        return Boolean.parseBoolean(getParamValue(PARAM_IGNORE_UPDATES_FOR_EXISTING_SUGGESTIONS));
     }
 
     public static boolean isFaviconServiceEnabled() {
-        return !PARAM_DISABLED_VALUE.equals(VariationsAssociatedData.getVariationParamValue(
-                FIELD_TRIAL_NAME, PARAM_FAVICON_SERVICE_NAME));
+        return !PARAM_DISABLED_VALUE.equals(getParamValue(PARAM_FAVICON_SERVICE_NAME));
     }
 
     private static int getIntValue(String paramName, int defaultValue) {
         // TODO(jkrcal): Get parameter by feature name, not field trial name.
-        String value = VariationsAssociatedData.getVariationParamValue(
-                FIELD_TRIAL_NAME, paramName);
+        String value = getParamValue(paramName);
 
         if (!TextUtils.isEmpty(value)) {
             try {
@@ -74,4 +96,14 @@
 
         return defaultValue;
     }
+
+    private static String getParamValue(String paramName) {
+        if (sTestVariationParams != null) {
+            String value = sTestVariationParams.get(paramName);
+            if (value == null) return "";
+            return value;
+        }
+
+        return VariationsAssociatedData.getVariationParamValue(FIELD_TRIAL_NAME, paramName);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
index 5057a76e..3d710bb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
@@ -610,6 +610,7 @@
      * To be triggered when a snippet is bound to a ViewHolder.
      */
     public void onSnippetBound(View cardView) {
+        // Animate the peeking card.
         // We only run if the feature is enabled and once per NTP.
         if (!SnippetsConfig.isIncreasedCardVisibilityEnabled() || mFirstCardAnimationRun) return;
         mFirstCardAnimationRun = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
index a0190f41..c4ecfd88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
@@ -97,8 +97,8 @@
             addChild(section);
         }
 
-        // Add the new suggestions.
-        setSuggestions(category, suggestions, categoryStatus);
+        // Set the new suggestions.
+        setSuggestions(category, suggestions, categoryStatus, /* replaceExisting = */ true);
 
         return suggestions.size();
     }
@@ -110,9 +110,6 @@
 
         if (!canLoadSuggestions(category, status)) return;
 
-        // We never want to refresh the suggestions if we already have some content.
-        if (mSections.get(category).hasSuggestions()) return;
-
         List<SnippetArticle> suggestions =
                 mNewTabPageManager.getSuggestionsSource().getSuggestionsForCategory(category);
 
@@ -121,7 +118,7 @@
         // At first, there might be no suggestions available, we wait until they have been fetched.
         if (suggestions.isEmpty()) return;
 
-        setSuggestions(category, suggestions, status);
+        setSuggestions(category, suggestions, status, /* replaceExisting = */ true);
     }
 
     @Override
@@ -130,7 +127,7 @@
         int status = mNewTabPageManager.getSuggestionsSource().getCategoryStatus(category);
         if (!canLoadSuggestions(category, status)) return;
 
-        setSuggestions(category, suggestions, status);
+        setSuggestions(category, suggestions, status, /* replaceExisting = */ false);
     }
 
     @Override
@@ -173,8 +170,19 @@
         resetSections(/* alwaysAllowEmptySections = */false);
     }
 
+    /**
+     * Puts {@code suggestions} into given {@code category}. It can either replace all existing
+     * suggestions with the new ones or append the new suggestions at the end of the list. This call
+     * may have no or only partial effect if changing the list of suggestions is not allowed (e.g.
+     * because the user has already seen the suggestions).
+     * @param category The category for which the suggestions should be set.
+     * @param suggestions The new list of suggestions for the given category.
+     * @param status The new category status.
+     * @param replaceExisting If true, {@code suggestions} replace the current list of suggestions.
+     * If false, {@code suggestions} are appended to current list of suggestions.
+     */
     private void setSuggestions(@CategoryInt int category, List<SnippetArticle> suggestions,
-            @CategoryStatusEnum int status) {
+            @CategoryStatusEnum int status, boolean replaceExisting) {
         // Count the number of suggestions before this category.
         int globalPositionOffset = 0;
         for (Map.Entry<Integer, SuggestionsSection> entry : mSections.entrySet()) {
@@ -186,7 +194,7 @@
             suggestion.mGlobalPosition = globalPositionOffset + suggestion.mPosition;
         }
 
-        mSections.get(category).addSuggestions(suggestions, status);
+        mSections.get(category).setSuggestions(suggestions, status, replaceExisting);
     }
 
     private boolean canLoadSuggestions(@CategoryInt int category, @CategoryStatusEnum int status) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
index 71b7d4b4..088ee0ac 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -44,6 +44,13 @@
 
     private boolean mIsNtpDestroyed;
 
+    // Keep track of impressions of the suggestions so that we replace only suggestions that
+    // have not been impressed, yet. We keep track of the first suggestion separately as the
+    // first is often impressed in the form of a peeking card and we still want to be able to
+    // replace something in this case.
+    private boolean mFirstSuggestionSeen;
+    private boolean mSubsequentSuggestionsSeen;
+
     /**
      * Delegate interface that allows dismissing this section without introducing
      * a circular dependency.
@@ -120,6 +127,17 @@
             notifyItemRangeRemoved(0, itemCount);
         }
 
+        /**
+         * Clears all suggestions except the first one.
+         */
+        private void clearAllButFirst() {
+            int itemCount = mSuggestions.size();
+            if (itemCount > 1) {
+                mSuggestions.subList(1, itemCount).clear();
+                notifyItemRangeRemoved(1, itemCount - 1);
+            }
+        }
+
         public void addAll(List<SnippetArticle> suggestions) {
             if (suggestions.isEmpty()) return;
 
@@ -228,6 +246,32 @@
         if (child == mSuggestionsList) refreshChildrenVisibility();
     }
 
+    @Override
+    public void onBindViewHolder(NewTabPageViewHolder holder, int position, List<Object> payloads) {
+        super.onBindViewHolder(holder, position, payloads);
+        childSeen(position);
+    }
+
+    /**
+     * Sets the child at position {@code position} as being seen by the user.
+     * @param position Position in the list being shown (the first suggestion being at index 1,
+     * as at index 0, there is a non-suggestion).
+     */
+    @VisibleForTesting
+    public void childSeen(int position) {
+        Log.d(TAG, "childSeen: position %d in category %d", position, mCategoryInfo.getCategory());
+        assert getStartingOffsetForChild(mSuggestionsList) == 1;
+        if (getItemViewType(position) == ItemViewType.SNIPPET) {
+            // We assume all non-snippet cards come after all cards of type SNIPPET.
+            int positionAmongSuggestions = position - 1;
+            if (positionAmongSuggestions == 0) {
+                mFirstSuggestionSeen = true;
+            } else if (positionAmongSuggestions > 0) {
+                mSubsequentSuggestionsSeen = true;
+            }
+        }
+    }
+
     /**
      * Removes a suggestion. Does nothing if the ID is unknown.
      * @param idWithinCategory The ID of the suggestion to remove.
@@ -259,23 +303,51 @@
         return suggestionIds;
     }
 
-    public void addSuggestions(List<SnippetArticle> suggestions, @CategoryStatusEnum int status) {
+    /**
+     * Puts {@code suggestions} into this section. It can either replace all existing suggestions
+     * with the new ones or append the new suggestions at the end of the list. This call may have no
+     * or only partial effect if changing the list of suggestions is not allowed (e.g. because the
+     * user has already seen the suggestions).
+     * @param suggestions The new list of suggestions for the given category.
+     * @param status The new category status.
+     * @param replaceExisting If true, {@code suggestions} replace the current list of suggestions.
+     * If false, {@code suggestions} are appended to current list of suggestions.
+     */
+    public void setSuggestions(List<SnippetArticle> suggestions, @CategoryStatusEnum int status,
+            boolean replaceExisting) {
+        Log.d(TAG, "setSuggestions: previous number of suggestions: %d; replace existing: %b",
+                mSuggestionsList.getItemCount(), replaceExisting);
         if (!SnippetsBridge.isCategoryStatusAvailable(status)) mSuggestionsList.clear();
-        mProgressIndicator.setVisible(SnippetsBridge.isCategoryLoading(status));
 
-        Log.d(TAG, "addSuggestions: current number of suggestions: %d",
-                mSuggestionsList.getItemCount());
+        // Remove suggestions to be replaced.
+        if (replaceExisting && hasSuggestions()) {
+            if (CardsVariationParameters.ignoreUpdatesForExistingSuggestions()
+                    || mSubsequentSuggestionsSeen) {
+                Log.d(TAG, "setSuggestions: replacing existing suggestion not possible");
+                return;
+            }
 
-        int sizeBefore = suggestions.size();
+            if (mFirstSuggestionSeen) {
+                Log.d(TAG, "setSuggestions: keeping the first suggestion");
+                mSuggestionsList.clearAllButFirst();
 
-        // TODO(dgn): remove once the backend stops sending duplicates.
-        if (suggestions.removeAll(mSuggestionsList.mSuggestions)) {
-            Log.d(TAG, "addSuggestions: Removed duplicates from incoming suggestions. "
-                            + "Count changed from %d to %d",
-                    sizeBefore, suggestions.size());
+                // Make sure that {@code mSuggestionsList} will contain as many elements as newly
+                // provided in {@code suggestions}. Remove the kept first element from the new
+                // collection, if it repeats there. Otherwise, remove the last element of the new
+                // collection.
+                if (!suggestions.remove(mSuggestionsList.getSuggestionAt(0))) {
+                    suggestions.remove(suggestions.size() - 1);
+                }
+            } else {
+                Log.d(TAG, "setSuggestions: removing all suggestions");
+                mSuggestionsList.clear();
+            }
         }
 
+        mProgressIndicator.setVisible(SnippetsBridge.isCategoryLoading(status));
+
         mSuggestionsList.addAll(suggestions);
+
         for (SnippetArticle article : suggestions) {
             if (!article.requiresExactOfflinePage()) {
                 updateSnippetOfflineAvailability(article);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/FakeSuggestionsSource.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/FakeSuggestionsSource.java
index 2a60c30..63dcaf2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/FakeSuggestionsSource.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/FakeSuggestionsSource.java
@@ -168,6 +168,7 @@
             return Collections.emptyList();
         }
         List<SnippetArticle> result = mSuggestions.get(category);
-        return result == null ? Collections.<SnippetArticle>emptyList() : result;
+        return result == null ? Collections.<SnippetArticle>emptyList()
+                              : new ArrayList<SnippetArticle>(result);
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
index 8d389d0..dbc2c624 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -179,8 +179,8 @@
             // Include only local profiles, because GUIDs of server profiles change on every browser
             // restart. Server profiles are not supported as billing addresses.
             if (!profile.getIsLocal()) continue;
-            // Do not include profiles with empty billing address info.
-            if (TextUtils.isEmpty(profile.getLabel())) continue;
+            // Do not include profiles without street address.
+            if (TextUtils.isEmpty(profile.getStreetAddress())) continue;
             mProfilesForBillingAddress.add(profile);
             Pair<Integer, Integer> editMessageResIds = AutofillAddress.getEditMessageAndTitleResIds(
                     AutofillAddress.checkAddressCompletionStatus(profile));
@@ -767,7 +767,7 @@
 
         PersonalDataManager pdm = PersonalDataManager.getInstance();
         if (!card.getIsLocal()) {
-            pdm.updateServerCardBillingAddress(card.getServerId(), card.getBillingAddressId());
+            pdm.updateServerCardBillingAddress(card);
             return;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillServerCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillServerCardEditor.java
index 5531401b..5fb89fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillServerCardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillServerCardEditor.java
@@ -14,7 +14,6 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 
 /**
@@ -91,8 +90,7 @@
 
     @Override
     protected boolean saveEntry() {
-        PersonalDataManager.getInstance().updateServerCardBillingAddress(mCard.getServerId(),
-                ((AutofillProfile) mBillingAddress.getSelectedItem()).getGUID());
+        PersonalDataManager.getInstance().updateServerCardBillingAddress(mCard);
         return true;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
index de9d183..64cf4d6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
@@ -69,11 +69,10 @@
                 "Maggie Doe", "Google", "340 Main St", "CA", "", "", "90291", "", "US", "",
                 "jon.doe@gmail.com", "en-US"));
 
-        // Profile with empty billing address info (should not be presented to user).
+        // Profile with empty street address (should not be presented to user).
         String profile8 = helper.setProfile(new AutofillProfile("", "https://example.com", true,
-                "" /* fullName */, "" /* companyName */, "" /* streetAddress */, "" /* region */,
-                "" /* locality */, "" /* dependentLocality */, "" /* postalCode */,
-                "" /* sortingCode */, "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
+                "Jerry Doe", "Google", "" /* streetAddress */, "CA", "Los Angeles", "", "90291", "",
+                "US", "310-310-6000", "jerry.doe@gmail.com", "en-US"));
 
         // This card has no billing address selected.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jane Doe",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 36f0bf7f..2c50fc0 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -70,8 +70,8 @@
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 
@@ -101,6 +101,7 @@
         public final boolean mStatusCard;
         public boolean mActionButton;
         public boolean mProgressItem;
+        public SnippetArticle mFirstItem;
 
         public SectionDescriptor(int numSuggestions) {
             mNumSuggestions = numSuggestions;
@@ -116,6 +117,11 @@
             mProgressItem = true;
             return this;
         }
+
+        public SectionDescriptor withFirstItem(SnippetArticle firstItem) {
+            mFirstItem = firstItem;
+            return this;
+        }
     }
 
     /**
@@ -145,6 +151,15 @@
 
         public void expect(SectionDescriptor descriptor) {
             expect(ItemViewType.HEADER);
+
+            if (descriptor.mFirstItem != null) {
+                if (mTreeNode.getSuggestionAt(mCurrentIndex) != descriptor.mFirstItem) {
+                    fail("Wrong snippet at position " + mCurrentIndex + "\n"
+                            + explainFailedExpectation(
+                                      mTreeNode, mCurrentIndex, ItemViewType.SNIPPET));
+                }
+            }
+
             for (int i = 1; i <= descriptor.mNumSuggestions; i++) {
                 expect(ItemViewType.SNIPPET);
             }
@@ -174,6 +189,9 @@
 
         ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
 
+        // Set empty variation params for the test.
+        CardsVariationParameters.setTestVariationParams(new HashMap<String, String>());
+
         // Initialise the sign in state. We will be signed in by default in the tests.
         assertFalse(ChromePreferenceManager.getInstance(RuntimeEnvironment.application)
                             .getNewTabPageSigninPromoDismissed());
@@ -219,18 +237,10 @@
         mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, suggestions);
 
         assertItemsFor(section(numSuggestions));
-
-        // The adapter should ignore any new incoming data.
-        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES,
-                Arrays.asList(new SnippetArticle[] {
-                        new SnippetArticle(0, "foo", "title1", "pub1", "txt1", "url", 0, 0, 0)}));
-
-        assertItemsFor(section(numSuggestions));
     }
 
     /**
-     * Tests that the adapter keeps listening for suggestion updates if it didn't get anything from
-     * a previous fetch.
+     * Tests that the adapter keeps listening for suggestion updates.
      */
     @Test
     @Feature({"Ntp"})
@@ -247,12 +257,6 @@
         mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, suggestions);
 
         assertItemsFor(section(numSuggestions));
-
-        // The adapter should ignore any new incoming data.
-        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES,
-                Arrays.asList(new SnippetArticle[] {
-                        new SnippetArticle(0, "foo", "title1", "pub1", "txt1", "url", 0, 0, 0)}));
-        assertItemsFor(section(numSuggestions));
     }
 
     /**
@@ -296,12 +300,9 @@
         mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, suggestions);
         assertItemsFor(section(3));
 
-        // If we have snippets, we should not load the new list (i.e. the extra item does *not*
-        // appear).
+        // Add another snippet.
         suggestions.add(new SnippetArticle(0, "https://site.com/url1", "title1", "pub1", "txt1",
                 "https://site.com/url1", 0, 0, 0));
-        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, suggestions);
-        assertItemsFor(section(3));
 
         // When snippets are disabled, we should not be able to load them.
         mSource.setStatusForCategory(KnownCategories.ARTICLES, CategoryStatus.SIGNED_OUT);
@@ -395,6 +396,72 @@
         assertItemsFor();
     }
 
+    /**
+     * Tests that the UI updates on updated suggestions.
+     */
+    @Test
+    @Feature({"Ntp"})
+    public void testUIUpdatesOnNewSuggestionsWhenOtherSectionSeen() {
+        List<SnippetArticle> snippets = createDummySuggestions(4);
+        mSource.setStatusForCategory(KnownCategories.ARTICLES, CategoryStatus.AVAILABLE);
+        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, snippets);
+
+        List<SnippetArticle> bookmarks = createDummySuggestions(2);
+        mSource.setStatusForCategory(KnownCategories.BOOKMARKS, CategoryStatus.AVAILABLE);
+        mSource.setInfoForCategory(KnownCategories.BOOKMARKS,
+                new CategoryInfoBuilder(KnownCategories.BOOKMARKS).showIfEmpty().build());
+        mSource.setSuggestionsForCategory(KnownCategories.BOOKMARKS, bookmarks);
+
+        reloadNtp();
+        assertItemsFor(section(4), section(2));
+
+        mAdapter.getSectionListForTesting()
+                .getSectionForTesting(KnownCategories.BOOKMARKS)
+                .childSeen(2);
+
+        List<SnippetArticle> newSnippets = createDummySuggestions(3);
+        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, newSnippets);
+        assertItemsFor(section(3), section(2));
+
+        reloadNtp();
+        assertItemsFor(section(3), section(2));
+    }
+
+    /**
+    * Tests that the UI updates the first item of the section if the first item of some other
+    * section has been viewed.
+    */
+    @Test
+    @Feature({"Ntp"})
+    public void testUIUpdatesOnNewSuggestionsWhenFirstOfOtherSectionIsSeen() {
+        List<SnippetArticle> snippets = createDummySuggestions(4);
+        SnippetArticle earlier = snippets.get(0);
+        mSource.setStatusForCategory(KnownCategories.ARTICLES, CategoryStatus.AVAILABLE);
+        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, snippets);
+
+        List<SnippetArticle> bookmarks = createDummySuggestions(1);
+        mSource.setStatusForCategory(KnownCategories.BOOKMARKS, CategoryStatus.AVAILABLE);
+        mSource.setInfoForCategory(KnownCategories.BOOKMARKS,
+                new CategoryInfoBuilder(KnownCategories.BOOKMARKS).showIfEmpty().build());
+        mSource.setSuggestionsForCategory(KnownCategories.BOOKMARKS, bookmarks);
+
+        reloadNtp();
+        assertItemsFor(section(4), section(1));
+
+        mAdapter.getSectionListForTesting()
+                .getSectionForTesting(KnownCategories.BOOKMARKS)
+                .childSeen(1);
+
+        List<SnippetArticle> newSnippets = createDummySuggestions(3);
+        SnippetArticle newer = newSnippets.get(0);
+
+        mSource.setSuggestionsForCategory(KnownCategories.ARTICLES, newSnippets);
+        assertItemsFor(section(3).withFirstItem(newer), section(1));
+
+        reloadNtp();
+        assertItemsFor(section(3).withFirstItem(newer), section(1));
+    }
+
     /** Tests whether a section stays visible if empty, if required. */
     @Test
     @Feature({"Ntp"})
@@ -687,7 +754,6 @@
         reset(dataObserver);
         suggestionsSource.setSuggestionsForCategory(
                 KnownCategories.ARTICLES, createDummySuggestions(newSuggestionCount));
-        mAdapter.getSectionListForTesting().onNewSuggestions(KnownCategories.ARTICLES);
         verify(dataObserver).onItemRangeInserted(2, newSuggestionCount);
         verify(dataObserver).onItemRangeChanged(5 + newSuggestionCount, 1, null); // Spacer refresh
         verify(dataObserver, times(2)).onItemRangeRemoved(2 + newSuggestionCount, 1);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
index 7802f8ab..1336e85 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -42,6 +42,7 @@
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -61,6 +62,9 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mBridge = new FakeOfflinePageBridge();
+
+        // Set empty variation params for the test.
+        CardsVariationParameters.setTestVariationParams(new HashMap<String, String>());
     }
 
     @Test
@@ -79,7 +83,7 @@
         assertEquals(1, section.getDismissSiblingPosDelta(1));
 
         // With snippets.
-        section.addSuggestions(snippets, CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
         assertEquals(ItemViewType.SNIPPET, section.getItemViewType(1));
         assertEquals(0, section.getDismissSiblingPosDelta(1));
     }
@@ -99,7 +103,7 @@
         assertEquals(2, section.getItemCount()); // When empty, we have the header and status card.
         assertEquals(ItemViewType.STATUS, section.getItemViewType(1));
 
-        section.addSuggestions(snippets, CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
         verify(mParent).onItemRangeInserted(section, 1, suggestionCount);
         verify(mParent).onItemRangeRemoved(section, 1 + suggestionCount, 1);
     }
@@ -113,7 +117,7 @@
 
         // Simulate initialisation by the adapter. Here we don't care about the notifications, since
         // the RecyclerView will be updated through notifyDataSetChanged.
-        section.addSuggestions(snippets, CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
         reset(mParent);
 
         // We don't clear suggestions when the status is AVAILABLE.
@@ -152,7 +156,7 @@
         section.setStatus(CategoryStatus.AVAILABLE);
         reset(mParent);
 
-        section.addSuggestions(snippets, CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         section.removeSuggestionById(snippets.get(1).mIdWithinCategory);
         verify(mParent).onItemRangeRemoved(section, 2, 1);
@@ -182,7 +186,7 @@
         reset(mParent);
         assertEquals(3, section.getItemCount()); // We have the header and status card and a button.
 
-        section.addSuggestions(snippets, CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
         assertEquals(4, section.getItemCount());
 
         section.removeSuggestionById(snippets.get(0).mIdWithinCategory);
@@ -228,7 +232,7 @@
         mBridge.setItems(Arrays.asList(item0, item1));
 
         SuggestionsSection section = createSectionWithReloadAction(true);
-        section.addSuggestions(snippets, CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         // Check that we pick up the correct information.
         assertEquals(Long.valueOf(0L), snippets.get(0).getOfflinePageOfflineId());
@@ -264,7 +268,8 @@
         assertTrue(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_VIEW_ALL);
 
-        section.addSuggestions(createDummySuggestions(3), CategoryStatus.AVAILABLE);
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         assertTrue(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_VIEW_ALL);
@@ -288,7 +293,8 @@
         assertTrue(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_RELOAD);
 
-        section.addSuggestions(createDummySuggestions(3), CategoryStatus.AVAILABLE);
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         assertTrue(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_FETCH_MORE);
@@ -307,7 +313,8 @@
         assertTrue(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_RELOAD);
 
-        section.addSuggestions(createDummySuggestions(3), CategoryStatus.AVAILABLE);
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         assertFalse(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_NONE);
@@ -326,7 +333,8 @@
         assertFalse(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_NONE);
 
-        section.addSuggestions(createDummySuggestions(3), CategoryStatus.AVAILABLE);
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         assertTrue(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_FETCH_MORE);
@@ -344,7 +352,8 @@
         assertFalse(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_NONE);
 
-        section.addSuggestions(createDummySuggestions(3), CategoryStatus.AVAILABLE);
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
 
         assertFalse(section.getActionItem().isVisible());
         verifyAction(section, ActionItem.ACTION_NONE);
@@ -357,7 +366,8 @@
         SuggestionsCategoryInfo info =
                 spy(new CategoryInfoBuilder(42).withMoreAction().showIfEmpty().build());
         SuggestionsSection section = createSection(info);
-        section.addSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE);
+        section.setSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE,
+                /* replaceExisting = */ true);
         assertFalse(section.getProgressItemForTesting().isVisible());
 
         // Tap the button
@@ -365,10 +375,86 @@
         assertTrue(section.getProgressItemForTesting().isVisible());
 
         // Simulate receiving suggestions.
-        section.addSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE);
+        section.setSuggestions(createDummySuggestions(suggestionCount), CategoryStatus.AVAILABLE,
+                /* replaceExisting = */ false);
         assertFalse(section.getProgressItemForTesting().isVisible());
     }
 
+    /**
+     * Tests that the UI updates on updated suggestions.
+     */
+    @Test
+    @Feature({"Ntp"})
+    public void testSectionUpdatesOnNewSuggestions() {
+        SuggestionsSection section = createSectionWithSuggestions(createDummySuggestions(4));
+        assertEquals(4, section.getSuggestionsCount());
+
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
+        assertEquals(3, section.getSuggestionsCount());
+    }
+
+    /**
+     * Tests that the UI does not update when updating is disabled by a parameter.
+     */
+    @Test
+    @Feature({"Ntp"})
+    public void testSectionDoesNotUpdateOnNewSuggestionsWhenDisabled() {
+        // Override variation params for the test.
+        HashMap<String, String> params = new HashMap<String, String>();
+        params.put("ignore_updates_for_existing_suggestions", "true");
+        CardsVariationParameters.setTestVariationParams(params);
+
+        SuggestionsSection section = createSectionWithSuggestions(createDummySuggestions(4));
+        assertEquals(4, section.getSuggestionsCount());
+
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
+        assertEquals(4, section.getSuggestionsCount());
+    }
+
+    /**
+     * Tests that the UI does not update when the section has been viewed.
+     */
+    @Test
+    @Feature({"Ntp"})
+    public void testSectionDoesNotUpdateOnNewSuggestionsWhenSectionSeen() {
+        SuggestionsSection section = createSectionWithSuggestions(createDummySuggestions(4));
+        assertEquals(4, section.getSuggestionsCount());
+
+        section.childSeen(2);
+
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
+        assertEquals(4, section.getSuggestionsCount());
+    }
+
+    /**
+     * Tests that the UI does not update the first item of the section if it has been viewed.
+     */
+    @Test
+    @Feature({"Ntp"})
+    public void testSectionDoesNotUpdateFirstSuggestionOnNewSuggestionsWhenSeen() {
+        List<SnippetArticle> snippets = createDummySuggestions(4);
+        SnippetArticle firstFromOriginalList = snippets.get(0);
+        SuggestionsSection section = createSectionWithSuggestions(snippets);
+        assertEquals(4, section.getSuggestionsCount());
+
+        section.childSeen(1);
+
+        section.setSuggestions(
+                createDummySuggestions(3), CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
+        assertEquals(3, section.getSuggestionsCount());
+        assertEquals(firstFromOriginalList, section.getSuggestionAt(1));
+    }
+
+    private SuggestionsSection createSectionWithSuggestions(List<SnippetArticle> snippets) {
+        SuggestionsSection section = createSectionWithReloadAction(true);
+        section.setStatus(CategoryStatus.AVAILABLE);
+        section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true);
+        return section;
+    }
+
     private SuggestionsSection createSectionWithReloadAction(boolean hasReloadAction) {
         CategoryInfoBuilder builder = new CategoryInfoBuilder(42).showIfEmpty();
         if (hasReloadAction) builder.withReloadAction();
diff --git a/chrome/app/chrome_crash_reporter_client_win.cc b/chrome/app/chrome_crash_reporter_client_win.cc
index 962c8232..8148716 100644
--- a/chrome/app/chrome_crash_reporter_client_win.cc
+++ b/chrome/app/chrome_crash_reporter_client_win.cc
@@ -253,7 +253,10 @@
 
   std::wstring process_type = install_static::GetSwitchValueFromCommandLine(
       ::GetCommandLine(), install_static::kProcessType);
-  if (process_type != install_static::kCrashpadHandler) {
+  // Don't set up Crashpad crash reporting in the Crashpad handler itself, nor
+  // in the fallback crash handler for the Crashpad handler process.
+  if (process_type != install_static::kCrashpadHandler &&
+      process_type != install_static::kFallbackHandler) {
     crash_reporter::SetCrashReporterClient(instance);
     crash_reporter::InitializeCrashpadWithEmbeddedHandler(
         process_type.empty(), install_static::UTF16ToUTF8(process_type));
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc
index b95c04a..9d135f0 100644
--- a/chrome/app/chrome_exe_main_win.cc
+++ b/chrome/app/chrome_exe_main_win.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/win/registry.h"
 #include "base/win/windows_version.h"
@@ -29,9 +30,11 @@
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/install_static/install_details.h"
+#include "chrome/install_static/install_util.h"
 #include "chrome_elf/chrome_elf_main.h"
 #include "components/crash/content/app/crash_switches.h"
 #include "components/crash/content/app/crashpad.h"
+#include "components/crash/content/app/fallback_crash_handling_win.h"
 #include "components/crash/content/app/run_as_crashpad_handler_win.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/result_codes.h"
@@ -196,6 +199,24 @@
   return false;
 }
 
+int RunFallbackCrashHandler(const base::CommandLine& cmd_line) {
+  // Retrieve the product & version details we need to report the crash
+  // correctly.
+  wchar_t exe_file[MAX_PATH] = {};
+  CHECK(::GetModuleFileName(nullptr, exe_file, arraysize(exe_file)));
+
+  base::string16 product_name;
+  base::string16 version;
+  base::string16 channel_name;
+  base::string16 special_build;
+  install_static::GetExecutableVersionDetails(exe_file, &product_name, &version,
+                                              &special_build, &channel_name);
+
+  return crash_reporter::RunAsFallbackCrashHandler(
+      cmd_line, base::UTF16ToUTF8(product_name), base::UTF16ToUTF8(version),
+      base::UTF16ToUTF8(channel_name));
+}
+
 }  // namespace
 
 #if defined(SYZYASAN)
@@ -228,8 +249,11 @@
          HasValidWindowsPrefetchArgument(*command_line));
 
   if (process_type == crash_reporter::switches::kCrashpadHandler) {
+    crash_reporter::SetupFallbackCrashHandling(*command_line);
     return crash_reporter::RunAsCrashpadHandler(
         *base::CommandLine::ForCurrentProcess());
+  } else if (process_type == crash_reporter::switches::kFallbackCrashHandler) {
+    return RunFallbackCrashHandler(*command_line);
   }
 
   const base::TimeTicks exe_entry_point_ticks = base::TimeTicks::Now();
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 7b064d6..5bc655f5 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -6201,6 +6201,9 @@
   <message name="IDS_ENTERPRISE_ENROLLMENT_ERROR_ACTIVE_DIRECTORY_POLICY_FETCH" desc="Error message shown on the enrollment screen when the system failed to fetch device policy from Active Directory.">
     Oops!  The system failed to fetch policy from Microsoft® Active Directory®.
   </message>
+  <message name="IDS_ENTERPRISE_ENROLLMENT_ERROR_STORE_DM_TOKEN_FAILED" desc="Error message shown on the enrollment screen when the system failed to store DM token into the local state.">
+    Oops!  The system failed to store DM token on the device.
+  </message>
   <message name="IDS_ENTERPRISE_ENROLLMENT_SCREEN_TITLE" desc="The title on the enterprise enrollment dialog.">
     Enterprise enrollment
   </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0ff9de1..9b4acd1 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -261,10 +261,6 @@
     "component_updater/sw_reporter_installer_win.h",
     "component_updater/swiftshader_component_installer.cc",
     "component_updater/swiftshader_component_installer.h",
-    "conflicts/module_database_win.cc",
-    "conflicts/module_database_win.h",
-    "conflicts/module_event_sink_impl_win.cc",
-    "conflicts/module_event_sink_impl_win.h",
     "content_settings/chrome_content_settings_utils.cc",
     "content_settings/chrome_content_settings_utils.h",
     "content_settings/cookie_settings_factory.cc",
diff --git a/chrome/browser/android/webapk/webapk_update_data_fetcher.cc b/chrome/browser/android/webapk/webapk_update_data_fetcher.cc
index 935ffa1..72d1c16 100644
--- a/chrome/browser/android/webapk/webapk_update_data_fetcher.cc
+++ b/chrome/browser/android/webapk/webapk_update_data_fetcher.cc
@@ -112,12 +112,12 @@
   }
 
   InstallableParams params;
-  params.ideal_icon_size_in_px =
+  params.ideal_primary_icon_size_in_px =
       ShortcutHelper::GetIdealHomescreenIconSizeInPx();
-  params.minimum_icon_size_in_px =
+  params.minimum_primary_icon_size_in_px =
       ShortcutHelper::GetMinimumHomescreenIconSizeInPx();
   params.check_installable = true;
-  params.fetch_valid_icon = true;
+  params.fetch_valid_primary_icon = true;
   InstallableManager::CreateForWebContents(web_contents());
   InstallableManager* installable_manager =
       InstallableManager::FromWebContents(web_contents());
@@ -152,15 +152,15 @@
 
   info_.UpdateFromManifest(data.manifest);
   info_.manifest_url = data.manifest_url;
-  info_.best_icon_url = data.icon_url;
-  best_icon_ = *data.icon;
+  info_.best_icon_url = data.primary_icon_url;
+  best_icon_ = *data.primary_icon;
 
   icon_hasher_.reset(new WebApkIconHasher());
   Profile* profile =
       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
   icon_hasher_->DownloadAndComputeMurmur2Hash(
       profile->GetRequestContext(),
-      data.icon_url,
+      data.primary_icon_url,
       base::Bind(&WebApkUpdateDataFetcher::OnGotIconMurmur2Hash,
                  weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
index 155aadaf..a29a5c4 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
@@ -47,10 +47,10 @@
                                                   int minimum_icon_size_in_px,
                                                   bool check_installable) {
   InstallableParams params;
-  params.ideal_icon_size_in_px = ideal_icon_size_in_px;
-  params.minimum_icon_size_in_px = minimum_icon_size_in_px;
+  params.ideal_primary_icon_size_in_px = ideal_icon_size_in_px;
+  params.minimum_primary_icon_size_in_px = minimum_icon_size_in_px;
   params.check_installable = check_installable;
-  params.fetch_valid_icon = true;
+  params.fetch_valid_primary_icon = true;
   return params;
 }
 
@@ -218,10 +218,10 @@
 
   weak_observer_->OnUserTitleAvailable(shortcut_info_.user_title);
 
-  if (data.icon) {
-    shortcut_info_.best_icon_url = data.icon_url;
+  if (data.primary_icon) {
+    shortcut_info_.best_icon_url = data.primary_icon_url;
 
-    CreateLauncherIcon(*(data.icon));
+    CreateLauncherIcon(*(data.primary_icon));
     return;
   }
 
diff --git a/chrome/browser/android/webapps/add_to_homescreen_manager.cc b/chrome/browser/android/webapps/add_to_homescreen_manager.cc
index 3103b17..ddfa514f 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_manager.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_manager.cc
@@ -17,10 +17,10 @@
 #include "chrome/browser/android/webapk/webapk_install_service.h"
 #include "chrome/browser/android/webapk/webapk_metrics.h"
 #include "chrome/browser/banners/app_banner_settings_helper.h"
+#include "chrome/browser/installable/installable_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/origin_util.h"
 #include "jni/AddToHomescreenManager_jni.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
@@ -77,7 +77,7 @@
 void AddToHomescreenManager::Start(content::WebContents* web_contents) {
   bool check_webapk_compatible = false;
   if (ChromeWebApkHost::AreWebApkEnabled() &&
-      content::IsOriginSecure(web_contents->GetLastCommittedURL())) {
+      InstallableManager::IsContentSecure(web_contents)) {
     check_webapk_compatible = true;
   } else {
     ShowDialog();
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 3a5ad19..782f25cf7 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -532,14 +532,11 @@
 void PersonalDataManagerAndroid::UpdateServerCardBillingAddress(
     JNIEnv* env,
     const JavaParamRef<jobject>& unused_obj,
-    const JavaParamRef<jstring>& jcard_server_id,
-    const JavaParamRef<jstring>& jbilling_address_id) {
-  CreditCard card("", kSettingsOrigin);
-  card.set_record_type(CreditCard::MASKED_SERVER_CARD);
-  card.set_server_id(ConvertJavaStringToUTF8(env, jcard_server_id));
-  card.set_billing_address_id(ConvertJavaStringToUTF8(env,
-      jbilling_address_id));
-  personal_data_manager_->UpdateServerCardBillingAddress(card);
+    const JavaParamRef<jobject>& jcard) {
+  CreditCard card;
+  PopulateNativeCreditCardFromJava(jcard, env, &card);
+
+  personal_data_manager_->UpdateServerCardMetadata(card);
 }
 
 ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::GetBasicCardPaymentType(
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.h b/chrome/browser/autofill/android/personal_data_manager_android.h
index 5f48ea0..2b3becc 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.h
+++ b/chrome/browser/autofill/android/personal_data_manager_android.h
@@ -161,13 +161,11 @@
       const base::android::JavaParamRef<jobject>& unused_obj,
       const base::android::JavaParamRef<jobject>& jcard);
 
-  // Updates the billing address of a server credit card with server ID
-  // |jcard_server_id|.
+  // Updates the billing address of a server credit card |jcard|.
   void UpdateServerCardBillingAddress(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& unused_obj,
-      const base::android::JavaParamRef<jstring>& jcard_server_id,
-      const base::android::JavaParamRef<jstring>& jbilling_address_id);
+      const base::android::JavaParamRef<jobject>& jcard);
 
   // Returns the card type according to PaymentRequest spec, or an empty string
   // if the given card number is not valid and |jempty_if_invalid| is true.
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc
index 908b932..dfd57ea 100644
--- a/chrome/browser/banners/app_banner_manager.cc
+++ b/chrome/browser/banners/app_banner_manager.cc
@@ -22,7 +22,6 @@
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/origin_util.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/WebKit/public/platform/modules/installation/installation.mojom.h"
@@ -42,10 +41,10 @@
 InstallableParams ParamsToPerformInstallableCheck(int ideal_icon_size_in_px,
                                                   int minimum_icon_size_in_px) {
   InstallableParams params;
-  params.ideal_icon_size_in_px = ideal_icon_size_in_px;
-  params.minimum_icon_size_in_px = minimum_icon_size_in_px;
+  params.ideal_primary_icon_size_in_px = ideal_icon_size_in_px;
+  params.minimum_primary_icon_size_in_px = minimum_icon_size_in_px;
   params.check_installable = true;
-  params.fetch_valid_icon = true;
+  params.fetch_valid_primary_icon = true;
 
   return params;
 }
@@ -106,7 +105,7 @@
 
   // A secure origin is required to show banners, so exit early if we see the
   // URL is invalid.
-  if (!content::IsOriginSecure(validated_url)) {
+  if (!InstallableManager::IsContentSecure(contents)) {
     ReportStatus(contents, NOT_FROM_SECURE_ORIGIN);
     Stop();
     return;
@@ -267,11 +266,11 @@
     return;
 
   DCHECK(data.is_installable);
-  DCHECK(!data.icon_url.is_empty());
-  DCHECK(data.icon);
+  DCHECK(!data.primary_icon_url.is_empty());
+  DCHECK(data.primary_icon);
 
-  icon_url_ = data.icon_url;
-  icon_.reset(new SkBitmap(*data.icon));
+  icon_url_ = data.primary_icon_url;
+  icon_.reset(new SkBitmap(*data.primary_icon));
 
   SendBannerPromptRequest();
 }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 9659be9..4a6c5b79e 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1078,6 +1078,8 @@
     "policy/device_status_collector.h",
     "policy/display_rotation_default_handler.cc",
     "policy/display_rotation_default_handler.h",
+    "policy/dm_token_storage.cc",
+    "policy/dm_token_storage.h",
     "policy/enrollment_config.h",
     "policy/enrollment_handler_chromeos.cc",
     "policy/enrollment_handler_chromeos.h",
@@ -1595,6 +1597,7 @@
     "policy/device_cloud_policy_manager_chromeos_unittest.cc",
     "policy/device_cloud_policy_store_chromeos_unittest.cc",
     "policy/device_local_account_policy_service_unittest.cc",
+    "policy/dm_token_storage_unittest.cc",
     "policy/extension_cache_unittest.cc",
     "policy/fake_affiliated_invalidation_service_provider.cc",
     "policy/fake_affiliated_invalidation_service_provider.h",
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc b/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc
index 24c24d5..74b8913e 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc
@@ -253,7 +253,13 @@
             ArcSessionManager::Get()->state());
 }
 
-IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ManagedAndroidAccount) {
+#if defined(OS_CHROMEOS)
+// https://crbug.com/681547 - flaky segfault on linux_chromium_chromeos_rel_ng
+#define MAYBE_ManagedAndroidAccount DISABLED_ManagedAndroidAccount
+#else
+#define MAYBE_ManagedAndroidAccount ManagedAndroidAccount
+#endif
+IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, MAYBE_ManagedAndroidAccount) {
   EnableArc();
   token_service()->IssueTokenForAllPendingRequests(kManagedAuthToken,
                                                    base::Time::Max());
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc
index 999c676a..261516ff 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc
@@ -13,7 +13,7 @@
 }  // namespace
 
 const base::Feature kMediaViewFeature{"ArcMediaView",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
 const char kMediaDocumentsProviderAuthority[] =
     "com.android.providers.media.documents";
diff --git a/chrome/browser/chromeos/drive/download_handler.cc b/chrome/browser/chromeos/drive/download_handler.cc
index 9502b8c..42e2303 100644
--- a/chrome/browser/chromeos/drive/download_handler.cc
+++ b/chrome/browser/chromeos/drive/download_handler.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/strings/string_util.h"
 #include "base/supports_user_data.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
@@ -377,9 +378,8 @@
     FileError error) {
   DVLOG(1) << "OnCreateDirectory " << FileErrorToString(error);
   if (error == FILE_ERROR_OK) {
-    base::PostTaskAndReplyWithResult(
-        BrowserThread::GetBlockingPool(),
-        FROM_HERE,
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE, base::TaskTraits().MayBlock(),
         base::Bind(&GetDriveTempDownloadPath, drive_tmp_download_path_),
         callback);
   } else {
diff --git a/chrome/browser/chromeos/drive/fileapi/fileapi_worker.cc b/chrome/browser/chromeos/drive/fileapi/fileapi_worker.cc
index ca54162..fb745cd 100644
--- a/chrome/browser/chromeos/drive/fileapi/fileapi_worker.cc
+++ b/chrome/browser/chromeos/drive/fileapi/fileapi_worker.cc
@@ -9,8 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/task_runner_util.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "components/drive/chromeos/file_system_interface.h"
@@ -185,11 +184,10 @@
   }
 
   // Cache file prepared for modification is available. Open it locally.
-  bool posted = base::PostTaskAndReplyWithResult(
-      BrowserThread::GetBlockingPool(), FROM_HERE,
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, base::TaskTraits().MayBlock(),
       base::Bind(&OpenFile, local_path, file_flags),
       base::Bind(&RunOpenFileCallback, callback, close_callback));
-  DCHECK(posted);
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/file_manager/open_with_browser.cc b/chrome/browser/chromeos/file_manager/open_with_browser.cc
index 8da982e2..eb9352d 100644
--- a/chrome/browser/chromeos/file_manager/open_with_browser.cc
+++ b/chrome/browser/chromeos/file_manager/open_with_browser.cc
@@ -11,7 +11,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/path_service.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
@@ -127,7 +127,7 @@
 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL
 // for |file_path| as fallback.
 // Note that an alternate url is a URL to open a hosted document.
-GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
+GURL ReadUrlFromGDocAsync(const base::FilePath& file_path) {
   GURL url = drive::util::ReadUrlFromGDocFile(file_path);
   if (url.is_empty())
     url = net::FilePathToFileURL(file_path);
@@ -169,10 +169,9 @@
     } else {
       // The file is local (downloaded from an attachment or otherwise copied).
       // Parse the file to extract the Docs url and open this url.
-      base::PostTaskAndReplyWithResult(
-          BrowserThread::GetBlockingPool(),
-          FROM_HERE,
-          base::Bind(&ReadUrlFromGDocOnBlockingPool, file_path),
+      base::PostTaskWithTraitsAndReplyWithResult(
+          FROM_HERE, base::TaskTraits().MayBlock(),
+          base::Bind(&ReadUrlFromGDocAsync, file_path),
           base::Bind(&OpenNewTab, profile));
     }
     return true;
diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
index 11b741f..fde8ecc5 100644
--- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
+++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
@@ -418,6 +418,9 @@
     case policy::EnrollmentStatus::ACTIVE_DIRECTORY_POLICY_FETCH_FAILED:
       UMA(policy::kMetricEnrollmentActiveDirectoryPolicyFetchFailed);
       break;
+    case policy::EnrollmentStatus::DM_TOKEN_STORE_FAILED:
+      UMA(policy::kMetricEnrollmentStoreDMTokenFailed);
+      break;
   }
 }
 
diff --git a/chrome/browser/chromeos/policy/dm_token_storage.cc b/chrome/browser/chromeos/policy/dm_token_storage.cc
new file mode 100644
index 0000000..b3baeeb
--- /dev/null
+++ b/chrome/browser/chromeos/policy/dm_token_storage.cc
@@ -0,0 +1,184 @@
+// 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 "chrome/browser/chromeos/policy/dm_token_storage.h"
+
+#include "base/bind.h"
+#include "chrome/browser/chromeos/settings/token_encryptor.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/cryptohome/system_salt_getter.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+std::string EncryptToken(const std::string& system_salt,
+                         const std::string& dm_token) {
+  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+  chromeos::CryptohomeTokenEncryptor encryptor(system_salt);
+  return encryptor.EncryptWithSystemSalt(dm_token);
+}
+
+std::string DecryptToken(const std::string& system_salt,
+                         const std::string encrypted_dm_token) {
+  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+  chromeos::CryptohomeTokenEncryptor encryptor(system_salt);
+  return encryptor.DecryptWithSystemSalt(encrypted_dm_token);
+}
+
+}  // namespace
+
+namespace policy {
+
+DMTokenStorage::DMTokenStorage(PrefService* local_state)
+    : local_state_(local_state), weak_ptr_factory_(this) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  chromeos::SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
+      &DMTokenStorage::OnSystemSaltRecevied, weak_ptr_factory_.GetWeakPtr()));
+}
+
+DMTokenStorage::~DMTokenStorage() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  FlushStoreTokenCallback(false);
+  FlushRetrieveTokenCallback(std::string());
+}
+
+// static
+void DMTokenStorage::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterStringPref(prefs::kDeviceDMToken, std::string());
+}
+
+void DMTokenStorage::StoreDMToken(const std::string& dm_token,
+                                  StoreCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!store_callback_.is_null()) {
+    DLOG(ERROR)
+        << "Failed to store DM token: Previous store operation is not finished";
+    std::move(callback).Run(false);
+    return;
+  }
+  if (!retrieve_callbacks_.empty()) {
+    DLOG(ERROR)
+        << "Failed to store DM token: Retrieve operation is not finished";
+    std::move(callback).Run(false);
+    return;
+  }
+  store_callback_ = std::move(callback);
+  dm_token_ = dm_token;
+  switch (state_) {
+    case SaltState::LOADING:
+      // Do nothing. Waiting for system salt.
+      break;
+    case SaltState::LOADED:
+      EncryptAndStoreToken();
+      break;
+    case SaltState::ERROR:
+      FlushStoreTokenCallback(false);
+      break;
+  }
+}
+
+void DMTokenStorage::RetrieveDMToken(RetrieveCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!store_callback_.is_null()) {
+    DCHECK(retrieve_callbacks_.empty());
+    DLOG(ERROR)
+        << "Failed to retrieve DM token: Store operation is not finished";
+    std::move(callback).Run(std::string());
+    return;
+  }
+  retrieve_callbacks_.push_back(std::move(callback));
+  switch (state_) {
+    case SaltState::LOADING:
+      // Do nothing. Waiting for system salt.
+      break;
+    case SaltState::LOADED:
+      if (retrieve_callbacks_.size() == 1) {  // First consumer.
+        LoadAndDecryptToken();
+      }
+      break;
+    case SaltState::ERROR:
+      FlushRetrieveTokenCallback(std::string());
+      break;
+  }
+}
+
+void DMTokenStorage::OnSystemSaltRecevied(const std::string& system_salt) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  system_salt_ = system_salt;
+  if (system_salt_.empty()) {
+    state_ = SaltState::ERROR;
+    DLOG(ERROR) << "Failed to get system salt.";
+    FlushStoreTokenCallback(false);
+    FlushRetrieveTokenCallback(std::string());
+    return;
+  }
+  // Should not be concurrent store and get operations.
+  DCHECK(store_callback_.is_null() || retrieve_callbacks_.empty());
+  state_ = SaltState::LOADED;
+  if (!store_callback_.is_null())
+    EncryptAndStoreToken();
+  else if (!retrieve_callbacks_.empty())
+    LoadAndDecryptToken();
+}
+
+void DMTokenStorage::EncryptAndStoreToken() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(!system_salt_.empty());
+  DCHECK(!dm_token_.empty());
+  base::PostTaskAndReplyWithResult(
+      content::BrowserThread::GetBlockingPool(), FROM_HERE,
+      base::Bind(&EncryptToken, system_salt_, dm_token_),
+      base::Bind(&DMTokenStorage::OnTokenEncrypted,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DMTokenStorage::OnTokenEncrypted(const std::string& encrypted_dm_token) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (encrypted_dm_token.empty()) {
+    DLOG(ERROR) << "Failed to encrypt DM token.";
+  } else {
+    local_state_->SetString(prefs::kDeviceDMToken, encrypted_dm_token);
+  }
+  FlushStoreTokenCallback(!encrypted_dm_token.empty());
+}
+
+void DMTokenStorage::LoadAndDecryptToken() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK_EQ(SaltState::LOADED, state_);
+  std::string encrypted_dm_token =
+      local_state_->GetString(prefs::kDeviceDMToken);
+  if (!encrypted_dm_token.empty()) {
+    base::PostTaskAndReplyWithResult(
+        content::BrowserThread::GetBlockingPool(), FROM_HERE,
+        base::Bind(&DecryptToken, system_salt_, encrypted_dm_token),
+        base::Bind(&DMTokenStorage::FlushRetrieveTokenCallback,
+                   weak_ptr_factory_.GetWeakPtr()));
+  } else {
+    DLOG(ERROR) << "No DM token in the local state.";
+    FlushRetrieveTokenCallback(std::string());
+  }
+}
+
+void DMTokenStorage::FlushStoreTokenCallback(bool status) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!store_callback_.is_null()) {
+    std::move(store_callback_).Run(status);
+  }
+}
+
+void DMTokenStorage::FlushRetrieveTokenCallback(const std::string& dm_token) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (retrieve_callbacks_.empty())
+    return;
+  if (dm_token.empty())
+    DLOG(ERROR) << "Failed to retrieve DM token.";
+  std::vector<RetrieveCallback> callbacks;
+  callbacks.swap(retrieve_callbacks_);
+  for (RetrieveCallback& callback : callbacks)
+    std::move(callback).Run(dm_token);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/dm_token_storage.h b/chrome/browser/chromeos/policy/dm_token_storage.h
new file mode 100644
index 0000000..19f3c910
--- /dev/null
+++ b/chrome/browser/chromeos/policy/dm_token_storage.h
@@ -0,0 +1,87 @@
+// 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 CHROME_BROWSER_CHROMEOS_POLICY_DM_TOKEN_STORAGE_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_DM_TOKEN_STORAGE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace policy {
+
+// Helper class to store/retrieve DM token to/from the local state. This is
+// needed for Active Directory management because AD devices lacks DM token in
+// the policies. DM token will be used in the future for ARC++ integration.
+//
+// Note that requests must be made from the UI thread because SystemSaltGetter
+// calls CryptohomeClient which must be called from the UI thread.
+class DMTokenStorage {
+ public:
+  using StoreCallback = base::OnceCallback<void(bool success)>;
+  using RetrieveCallback =
+      base::OnceCallback<void(const std::string& dm_token)>;
+
+  explicit DMTokenStorage(PrefService* local_state);
+  ~DMTokenStorage();
+
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+  // Persists |dm_token| on the device. Overwrites any previous value. Signals
+  // completion via |callback|, passing true if the operation succeeded. Fails
+  // if another operation is running (store or retrieve).
+  void StoreDMToken(const std::string& dm_token, StoreCallback callback);
+
+  // Loads DM token from the local state and decrypts it. Fires callback on
+  // completion. Empty |dm_token| means error. Calls |callback| with empty token
+  // if store operation is running.
+  void RetrieveDMToken(RetrieveCallback callback);
+
+ private:
+  enum class SaltState {
+    // Pending system salt.
+    LOADING,
+    // Failed to load system salt.
+    ERROR,
+    // System salt is loaded.
+    LOADED,
+  };
+
+  // Callback for SystemSaltRetrieveter.
+  void OnSystemSaltRecevied(const std::string& system_salt);
+
+  // Encrypts DM token using system salt and stores it into the local state.
+  void EncryptAndStoreToken();
+
+  // Callback waiting for DM token to be encrypted.
+  void OnTokenEncrypted(const std::string& encrypted_dm_token);
+
+  // Loads encrypted DM token from the local state and decrypts it using system
+  // salt.
+  void LoadAndDecryptToken();
+
+  // Fires StoreCallback (if exists) with the status.
+  void FlushStoreTokenCallback(bool status);
+
+  // Fires RetrieveCallbacks (if exists) with |dm_token|.
+  void FlushRetrieveTokenCallback(const std::string& dm_token);
+
+  PrefService* local_state_;
+  SaltState state_ = SaltState::LOADING;
+  std::string system_salt_;
+  // Stored |dm_token| while waiting for system salt.
+  std::string dm_token_;
+  StoreCallback store_callback_;
+  std::vector<RetrieveCallback> retrieve_callbacks_;
+  base::WeakPtrFactory<DMTokenStorage> weak_ptr_factory_;
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_CHROMEOS_POLICY_DM_TOKEN_STORAGE_H_
diff --git a/chrome/browser/chromeos/policy/dm_token_storage_unittest.cc b/chrome/browser/chromeos/policy/dm_token_storage_unittest.cc
new file mode 100644
index 0000000..bce508e
--- /dev/null
+++ b/chrome/browser/chromeos/policy/dm_token_storage_unittest.cc
@@ -0,0 +1,233 @@
+// 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 "chrome/browser/chromeos/policy/dm_token_storage.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/cryptohome/system_salt_getter.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_cryptohome_client.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+class DMTokenStorageTest : public testing::Test {
+ public:
+  DMTokenStorageTest()
+      : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {}
+  ~DMTokenStorageTest() override {}
+
+  void SetSaltPending() {
+    // Clear the cached salt.
+    chromeos::SystemSaltGetter::Shutdown();
+    fake_cryptohome_client_->set_system_salt(std::vector<uint8_t>());
+    fake_cryptohome_client_->SetServiceIsAvailable(false);
+    chromeos::SystemSaltGetter::Initialize();
+  }
+
+  void SetSaltAvailable() {
+    fake_cryptohome_client_->set_system_salt(
+        chromeos::FakeCryptohomeClient::GetStubSystemSalt());
+    fake_cryptohome_client_->SetServiceIsAvailable(true);
+  }
+
+  void SetSaltError() {
+    fake_cryptohome_client_->set_system_salt(std::vector<uint8_t>());
+    fake_cryptohome_client_->SetServiceIsAvailable(true);
+  }
+
+  void SetUp() override {
+    fake_cryptohome_client_ = new chromeos::FakeCryptohomeClient;
+    SetSaltAvailable();
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient(
+        std::unique_ptr<chromeos::CryptohomeClient>(fake_cryptohome_client_));
+
+    chromeos::SystemSaltGetter::Initialize();
+  }
+
+  void TearDown() override {
+    dm_token_storage_.reset();
+    chromeos::SystemSaltGetter::Shutdown();
+    chromeos::DBusThreadManager::Shutdown();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void CreateDMStorage() {
+    dm_token_storage_ =
+        base::MakeUnique<DMTokenStorage>(scoped_testing_local_state_.Get());
+  }
+
+  void StoreDMToken() {
+    base::RunLoop run_loop;
+    dm_token_storage_->StoreDMToken(
+        "test-token",
+        base::Bind(&DMTokenStorageTest::OnStoreCallback, base::Unretained(this),
+                   run_loop.QuitClosure(), true));
+    run_loop.Run();
+  }
+
+  void OnStoreCallback(const base::Closure& closure,
+                       bool expected,
+                       bool success) {
+    EXPECT_EQ(expected, success);
+    if (!closure.is_null())
+      closure.Run();
+  }
+
+  void OnRetrieveCallback(const base::Closure& closure,
+                          const std::string& expected,
+                          const std::string& actual) {
+    EXPECT_EQ(expected, actual);
+    if (!closure.is_null())
+      closure.Run();
+  }
+
+  content::TestBrowserThreadBundle thread_bundle_;
+  ScopedTestingLocalState scoped_testing_local_state_;
+  chromeos::FakeCryptohomeClient* fake_cryptohome_client_;
+  std::unique_ptr<DMTokenStorage> dm_token_storage_;
+};
+
+TEST_F(DMTokenStorageTest, SaveEncryptedToken) {
+  CreateDMStorage();
+  StoreDMToken();
+
+  {
+    base::RunLoop run_loop;
+    dm_token_storage_->RetrieveDMToken(base::Bind(
+        &DMTokenStorageTest::OnRetrieveCallback, base::Unretained(this),
+        run_loop.QuitClosure(), "test-token"));
+    run_loop.Run();
+  }
+  // Reload shouldn't change the token.
+  CreateDMStorage();
+  {
+    base::RunLoop run_loop;
+    dm_token_storage_->RetrieveDMToken(base::Bind(
+        &DMTokenStorageTest::OnRetrieveCallback, base::Unretained(this),
+        run_loop.QuitClosure(), "test-token"));
+    run_loop.Run();
+  }
+  {
+    // Subsequent retrieving DM token should succeed.
+    base::RunLoop run_loop;
+    dm_token_storage_->RetrieveDMToken(base::Bind(
+        &DMTokenStorageTest::OnRetrieveCallback, base::Unretained(this),
+        run_loop.QuitClosure(), "test-token"));
+    run_loop.Run();
+  }
+}
+
+TEST_F(DMTokenStorageTest, RetrieveEncryptedTokenWithPendingSalt) {
+  CreateDMStorage();
+  StoreDMToken();
+
+  SetSaltPending();
+  CreateDMStorage();
+
+  {
+    base::RunLoop run_loop;
+    dm_token_storage_->RetrieveDMToken(base::Bind(
+        &DMTokenStorageTest::OnRetrieveCallback, base::Unretained(this),
+        run_loop.QuitClosure(), "test-token"));
+    SetSaltAvailable();
+    run_loop.Run();
+  }
+}
+
+TEST_F(DMTokenStorageTest, StoreEncryptedTokenWithPendingSalt) {
+  SetSaltPending();
+  CreateDMStorage();
+  base::RunLoop run_loop;
+  dm_token_storage_->StoreDMToken(
+      "test-token",
+      base::Bind(&DMTokenStorageTest::OnStoreCallback, base::Unretained(this),
+                 run_loop.QuitClosure(), true));
+  SetSaltAvailable();
+  run_loop.Run();
+}
+
+TEST_F(DMTokenStorageTest, MultipleRetrieveTokenCalls) {
+  CreateDMStorage();
+  StoreDMToken();
+  {
+    base::RunLoop run_loop;
+    for (int i = 0; i < 3; ++i) {
+      dm_token_storage_->RetrieveDMToken(base::Bind(
+          &DMTokenStorageTest::OnRetrieveCallback, base::Unretained(this),
+          run_loop.QuitClosure(), "test-token"));
+    }
+    run_loop.Run();
+  }
+}
+
+TEST_F(DMTokenStorageTest, StoreWithSaltError) {
+  SetSaltError();
+  CreateDMStorage();
+  base::RunLoop run_loop;
+  dm_token_storage_->StoreDMToken(
+      "test-token",
+      base::Bind(&DMTokenStorageTest::OnStoreCallback, base::Unretained(this),
+                 run_loop.QuitClosure(), false));
+  run_loop.Run();
+}
+
+TEST_F(DMTokenStorageTest, RetrieveWithSaltError) {
+  CreateDMStorage();
+  StoreDMToken();
+  SetSaltPending();
+  CreateDMStorage();
+  base::RunLoop run_loop;
+  dm_token_storage_->RetrieveDMToken(
+      base::Bind(&DMTokenStorageTest::OnRetrieveCallback,
+                 base::Unretained(this), run_loop.QuitClosure(), ""));
+  SetSaltError();
+  run_loop.Run();
+}
+
+TEST_F(DMTokenStorageTest, RetrieveWithNoToken) {
+  CreateDMStorage();
+  base::RunLoop run_loop;
+  dm_token_storage_->RetrieveDMToken(
+      base::Bind(&DMTokenStorageTest::OnRetrieveCallback,
+                 base::Unretained(this), run_loop.QuitClosure(), ""));
+  run_loop.Run();
+}
+
+TEST_F(DMTokenStorageTest, RetrieveFailIfStoreRunning) {
+  SetSaltPending();
+  CreateDMStorage();
+  base::RunLoop run_loop;
+  dm_token_storage_->StoreDMToken(
+      "test-token",
+      base::Bind(&DMTokenStorageTest::OnStoreCallback, base::Unretained(this),
+                 run_loop.QuitClosure(), true));
+  dm_token_storage_->RetrieveDMToken(
+      base::Bind(&DMTokenStorageTest::OnRetrieveCallback,
+                 base::Unretained(this), base::Closure(), ""));
+  SetSaltAvailable();
+  run_loop.Run();
+}
+
+TEST_F(DMTokenStorageTest, StoreFailIfAnotherStoreRunning) {
+  SetSaltPending();
+  CreateDMStorage();
+  base::RunLoop run_loop;
+  dm_token_storage_->StoreDMToken(
+      "test-token",
+      base::Bind(&DMTokenStorageTest::OnStoreCallback, base::Unretained(this),
+                 run_loop.QuitClosure(), true));
+  dm_token_storage_->StoreDMToken(
+      "test-token", base::Bind(&DMTokenStorageTest::OnStoreCallback,
+                               base::Unretained(this), base::Closure(), false));
+  SetSaltAvailable();
+  run_loop.Run();
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
index 7aceb11..6be059dd 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
 #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h"
+#include "chrome/browser/chromeos/policy/dm_token_storage.h"
 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
 #include "chrome/browser/chromeos/policy/server_backed_state_keys_broker.h"
@@ -244,14 +245,6 @@
 
 void EnrollmentHandlerChromeOS::OnStoreError(CloudPolicyStore* store) {
   DCHECK_EQ(store_, store);
-  if (enrollment_step_ == STEP_STORE_TOKEN_AND_ID) {
-    // Calling OwnerSettingsServiceChromeOS::SetManagementSettings()
-    // on a non- enterprise-managed device will fail as
-    // DeviceCloudPolicyStore listens to all changes on device
-    // settings, and it calls OnStoreError() when the device is not
-    // enterprise-managed.
-    return;
-  }
   LOG(ERROR) << "Error in device policy store.";
   ReportResult(EnrollmentStatus::ForStoreError(store_->status(),
                                                store_->validation_status()));
@@ -423,12 +416,27 @@
                  weak_ptr_factory_.GetWeakPtr()));
 }
 
+void EnrollmentHandlerChromeOS::HandleDMTokenStoreResult(bool success) {
+  CHECK_EQ(STEP_STORE_TOKEN, enrollment_step_);
+  if (!success) {
+    ReportResult(
+        EnrollmentStatus::ForStatus(EnrollmentStatus::DM_TOKEN_STORE_FAILED));
+    return;
+  }
+
+  StartStoreRobotAuth();
+}
+
 void EnrollmentHandlerChromeOS::HandleLockDeviceResult(
     chromeos::InstallAttributes::LockResult lock_result) {
   DCHECK_EQ(STEP_LOCK_DEVICE, enrollment_step_);
   switch (lock_result) {
     case chromeos::InstallAttributes::LOCK_SUCCESS:
-      StartStoreRobotAuth();
+      if (device_mode_ == DEVICE_MODE_ENTERPRISE_AD) {
+        StartStoreDMToken();
+      } else {
+        StartStoreRobotAuth();
+      }
       break;
     case chromeos::InstallAttributes::LOCK_NOT_READY:
       // We wait up to |kLockRetryTimeoutMs| milliseconds and if it hasn't
@@ -459,6 +467,17 @@
   }
 }
 
+void EnrollmentHandlerChromeOS::StartStoreDMToken() {
+  DCHECK(device_mode_ == DEVICE_MODE_ENTERPRISE_AD);
+  SetStep(STEP_STORE_TOKEN);
+  dm_token_storage_ = base::MakeUnique<policy::DMTokenStorage>(
+      g_browser_process->local_state());
+  dm_token_storage_->StoreDMToken(
+      client_->dm_token(),
+      base::Bind(&EnrollmentHandlerChromeOS::HandleDMTokenStoreResult,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
 void EnrollmentHandlerChromeOS::StartStoreRobotAuth() {
   SetStep(STEP_STORE_ROBOT_AUTH);
 
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
index 82232aa..6966101 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
@@ -35,6 +35,7 @@
 namespace policy {
 
 class DeviceCloudPolicyStoreChromeOS;
+class DMTokenStorage;
 class ServerBackedStateKeysBroker;
 
 // Implements the logic that establishes enterprise enrollment for Chromium OS
@@ -111,7 +112,7 @@
     STEP_ROBOT_AUTH_FETCH = 6,    // Fetching device API auth code.
     STEP_ROBOT_AUTH_REFRESH = 7,  // Fetching device API refresh token.
     STEP_LOCK_DEVICE = 8,         // Writing installation-time attributes.
-    STEP_STORE_TOKEN_AND_ID = 9,  // Storing DM token and virtual device ID.
+    STEP_STORE_TOKEN = 9,         // Encrypting and storing DM token.
     STEP_STORE_ROBOT_AUTH = 10,   // Encrypting & writing robot refresh token.
     STEP_STORE_POLICY = 11,       // Storing policy and API refresh token. For
                                   // AD, includes policy fetch via authpolicyd.
@@ -145,6 +146,12 @@
   void HandleLockDeviceResult(
       chromeos::InstallAttributes::LockResult lock_result);
 
+  // Initiates storing DM token. For Active Directory devices only.
+  void StartStoreDMToken();
+
+  // Called after StartStoreDMtoken() is done.
+  void HandleDMTokenStoreResult(bool success);
+
   // Initiates storing of robot auth token.
   void StartStoreRobotAuth();
 
@@ -170,6 +177,7 @@
   std::unique_ptr<CloudPolicyClient> client_;
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
   std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
+  std::unique_ptr<policy::DMTokenStorage> dm_token_storage_;
 
   EnrollmentConfig enrollment_config_;
   std::string auth_token_;
diff --git a/chrome/browser/chromeos/policy/enrollment_status_chromeos.h b/chrome/browser/chromeos/policy/enrollment_status_chromeos.h
index 9319869..bacd989f 100644
--- a/chrome/browser/chromeos/policy/enrollment_status_chromeos.h
+++ b/chrome/browser/chromeos/policy/enrollment_status_chromeos.h
@@ -43,6 +43,8 @@
     ACTIVE_DIRECTORY_POLICY_FETCH_FAILED = 17,  // Failed to fetch Active
                                                 // Directory policy via
                                                 // authpolicyd.
+    DM_TOKEN_STORE_FAILED = 18,  // Failed to store DM token into the
+                                 // local state.
   };
 
   // Helpers for constructing errors for relevant cases.
diff --git a/chrome/browser/conflicts/OWNERS b/chrome/browser/conflicts/OWNERS
deleted file mode 100644
index 2ffdf656..0000000
--- a/chrome/browser/conflicts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-chrisha@chromium.org
-pmonette@chromium.org
diff --git a/chrome/browser/conflicts/module_database_win.cc b/chrome/browser/conflicts/module_database_win.cc
deleted file mode 100644
index e68bd5e..0000000
--- a/chrome/browser/conflicts/module_database_win.cc
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/module_database_win.h"
-
-#include <algorithm>
-#include <tuple>
-
-#include "base/bind.h"
-
-namespace {
-
-// Document the assumptions made on the ProcessType enum in order to convert
-// them to bits.
-static_assert(content::PROCESS_TYPE_UNKNOWN == 1,
-              "assumes unknown process type has value 1");
-static_assert(content::PROCESS_TYPE_BROWSER == 2,
-              "assumes browser process type has value 2");
-constexpr uint32_t kFirstValidProcessType = content::PROCESS_TYPE_BROWSER;
-
-}  // namespace
-
-ModuleDatabase::ModuleDatabase(
-    scoped_refptr<base::SequencedTaskRunner> task_runner)
-    : task_runner_(std::move(task_runner)), weak_ptr_factory_(this) {}
-
-ModuleDatabase::~ModuleDatabase() = default;
-
-void ModuleDatabase::OnProcessStarted(uint32_t process_id,
-                                      uint64_t creation_time,
-                                      content::ProcessType process_type) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
-  CreateProcessInfo(process_id, creation_time, process_type);
-}
-
-void ModuleDatabase::OnModuleLoad(uint32_t process_id,
-                                  uint64_t creation_time,
-                                  const base::FilePath& module_path,
-                                  uint32_t module_size,
-                                  uint32_t module_time_date_stamp,
-                                  uintptr_t module_load_address) {
-  // Messages can arrive from any thread (UI thread for calls over IPC, and
-  // anywhere at all for calls from ModuleWatcher), so bounce if necessary.
-  if (!task_runner_->RunsTasksOnCurrentThread()) {
-    task_runner_->PostTask(
-        FROM_HERE, base::Bind(&ModuleDatabase::OnModuleLoad,
-                              weak_ptr_factory_.GetWeakPtr(), process_id,
-                              creation_time, module_path, module_size,
-                              module_time_date_stamp, module_load_address));
-    return;
-  }
-
-  // In theory this should always succeed. However, it is possible for a client
-  // to misbehave and send out-of-order messages. It is easy to be tolerant of
-  // this by simply not updating the process info in this case. It's not worth
-  // crashing if this data is slightly out of sync as this is purely
-  // informational.
-  auto* process_info = GetProcessInfo(process_id, creation_time);
-  if (!process_info)
-    return;
-
-  auto* module_info =
-      FindOrCreateModuleInfo(module_path, module_size, module_time_date_stamp);
-
-  // Update the list of process types that this module has been seen in.
-  module_info->second.process_types |=
-      ProcessTypeToBit(process_info->first.process_type);
-
-  // Update the load address maps.
-  InsertLoadAddress(module_info->first.module_id, module_load_address,
-                    &process_info->second.loaded_modules);
-  RemoveLoadAddressById(module_info->first.module_id,
-                        &process_info->second.unloaded_modules);
-}
-
-void ModuleDatabase::OnModuleUnload(uint32_t process_id,
-                                    uint64_t creation_time,
-                                    uintptr_t module_load_address) {
-  // Messages can arrive from any thread (UI thread for calls over IPC, and
-  // anywhere at all for calls from ModuleWatcher), so bounce if necessary.
-  if (!task_runner_->RunsTasksOnCurrentThread()) {
-    task_runner_->PostTask(
-        FROM_HERE, base::Bind(&ModuleDatabase::OnModuleUnload,
-                              weak_ptr_factory_.GetWeakPtr(), process_id,
-                              creation_time, module_load_address));
-    return;
-  }
-
-  // See the long-winded comment in OnModuleLoad about reasons why this can
-  // fail (but shouldn't normally).
-  auto* process_info = GetProcessInfo(process_id, creation_time);
-  if (!process_info)
-    return;
-
-  // Find the module corresponding to this load address. This is O(1) in the
-  // common case of removing a recently removed module, but O(n) worst case.
-  // Thankfully, unload events occur far less often and n is quite small.
-  size_t i = FindLoadAddressIndexByAddress(module_load_address,
-                                           process_info->second.loaded_modules);
-
-  // No such module found. This shouldn't happen either, unless messages are
-  // malformed or out of order. Gracefully fail in this case.
-  if (i == kInvalidIndex)
-    return;
-
-  ModuleId module_id = process_info->second.loaded_modules[i].first;
-
-  // Remove from the loaded module list and insert into the unloaded module
-  // list.
-  RemoveLoadAddressByIndex(i, &process_info->second.loaded_modules);
-  InsertLoadAddress(module_id, module_load_address,
-                    &process_info->second.unloaded_modules);
-}
-
-void ModuleDatabase::OnProcessEnded(uint32_t process_id,
-                                    uint64_t creation_time) {
-  // Messages can arrive from any thread (UI thread for calls over IPC, and
-  // anywhere at all for calls from ModuleWatcher), so bounce if necessary.
-  if (!task_runner_->RunsTasksOnCurrentThread()) {
-    task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&ModuleDatabase::OnProcessEnded,
-                   weak_ptr_factory_.GetWeakPtr(), process_id, creation_time));
-    return;
-  }
-
-  DeleteProcessInfo(process_id, creation_time);
-}
-
-// static
-uint32_t ModuleDatabase::ProcessTypeToBit(content::ProcessType process_type) {
-  uint32_t bit_index =
-      static_cast<uint32_t>(process_type) - kFirstValidProcessType;
-  DCHECK_GE(31u, bit_index);
-  uint32_t bit = (1 << bit_index);
-  return bit;
-}
-
-// static
-content::ProcessType ModuleDatabase::BitIndexToProcessType(uint32_t bit_index) {
-  DCHECK_GE(31u, bit_index);
-  return static_cast<content::ProcessType>(bit_index + kFirstValidProcessType);
-}
-
-// static
-size_t ModuleDatabase::FindLoadAddressIndexById(
-    ModuleId module_id,
-    const ModuleLoadAddresses& load_addresses) {
-  // Process elements in reverse order so that RemoveLoadAddressById can handle
-  // the more common case of removing the maximum element in O(1).
-  for (size_t i = load_addresses.size() - 1; i < load_addresses.size(); --i) {
-    if (load_addresses[i].first == module_id)
-      return i;
-  }
-  return kInvalidIndex;
-}
-
-// static
-size_t ModuleDatabase::FindLoadAddressIndexByAddress(
-    uintptr_t load_address,
-    const ModuleLoadAddresses& load_addresses) {
-  for (size_t i = 0; i < load_addresses.size(); ++i) {
-    if (load_addresses[i].second == load_address)
-      return i;
-  }
-  return kInvalidIndex;
-}
-
-// static
-void ModuleDatabase::InsertLoadAddress(ModuleId module_id,
-                                       uintptr_t load_address,
-                                       ModuleLoadAddresses* load_addresses) {
-  // A very small optimization: the largest module_id is always placed at the
-  // end of the array. This is the most common case, and allows O(1)
-  // determination that a |module_id| isn't present when it's bigger than the
-  // maximum already in the array. This keeps insertions to O(1) in the usual
-  // case.
-  if (load_addresses->empty() || module_id > load_addresses->back().first) {
-    load_addresses->emplace_back(module_id, load_address);
-    return;
-  }
-
-  // If the module exists in the collection then update the load address and
-  // return. This should never really occur, unless the client is deliberately
-  // misbehaving or a race causes a reload event (at a different address) to be
-  // processed before the corresponding unload. This is very unlikely.
-  size_t i = FindLoadAddressIndexById(module_id, *load_addresses);
-  if (i != kInvalidIndex) {
-    (*load_addresses)[i].second = load_address;
-    return;
-  }
-
-  // The module does not exist, and by definition is smaller in value than
-  // the largest module ID already present. Add it, ensuring that the largest
-  // module ID stays at the end.
-  load_addresses->emplace(--load_addresses->end(), module_id, load_address);
-}
-
-// static
-void ModuleDatabase::RemoveLoadAddressById(
-    ModuleId module_id,
-    ModuleLoadAddresses* load_addresses) {
-  if (load_addresses->empty())
-    return;
-
-  // This handles the special case of removing the max element in O(1), as
-  // FindLoadAddressIndexById processes the elements in reverse order.
-  size_t i = FindLoadAddressIndexById(module_id, *load_addresses);
-  RemoveLoadAddressByIndex(i, load_addresses);
-}
-
-// static
-void ModuleDatabase::RemoveLoadAddressByIndex(
-    size_t index,
-    ModuleLoadAddresses* load_addresses) {
-  DCHECK_LT(index, load_addresses->size());
-
-  // Special case: removing the last module (with maximum id). Need to find the
-  // new maximum element and ensure it goes to the end.
-  if (load_addresses->size() > 2 && index + 1 == load_addresses->size()) {
-    // Note that |index| == load_addresses->size() - 1, and is the last
-    // indexable element in the vector.
-
-    // Find the index of the new maximum element.
-    ModuleId max_id = -1;  // These start at zero.
-    size_t max_index = kInvalidIndex;
-    for (size_t i = 0; i < load_addresses->size() - 1; ++i) {
-      if ((*load_addresses)[i].first > max_id) {
-        max_id = (*load_addresses)[i].first;
-        max_index = i;
-      }
-    }
-
-    // Remove the last (max) element.
-    load_addresses->resize(index);
-
-    // If the new max element isn't in the last position, then swap it so it is.
-    size_t last_index = load_addresses->size() - 1;
-    if (max_index != last_index)
-      std::swap((*load_addresses)[max_index], (*load_addresses)[last_index]);
-
-    return;
-  }
-
-  // If the element to be removed is second last then a single copy is
-  // sufficient.
-  if (index + 2 == load_addresses->size()) {
-    (*load_addresses)[index] = (*load_addresses)[index + 1];
-  } else {
-    // In the general case two copies are necessary.
-    int max_index = load_addresses->size() - 1;
-    (*load_addresses)[index] = (*load_addresses)[max_index - 1];
-    (*load_addresses)[max_index - 1] = (*load_addresses)[max_index];
-  }
-
-  // Remove the last element, which is now duplicated.
-  load_addresses->resize(load_addresses->size() - 1);
-}
-
-ModuleDatabase::ModuleInfo* ModuleDatabase::FindOrCreateModuleInfo(
-    const base::FilePath& module_path,
-    uint32_t module_size,
-    uint32_t module_time_date_stamp) {
-  auto result = modules_.emplace(
-      std::piecewise_construct,
-      std::forward_as_tuple(ModuleInfoKey(
-          module_path, module_size, module_time_date_stamp, modules_.size())),
-      std::forward_as_tuple(ModuleInfoData()));
-  return &(*result.first);
-}
-
-ModuleDatabase::ProcessInfo* ModuleDatabase::GetProcessInfo(
-    uint32_t process_id,
-    uint64_t creation_time) {
-  ProcessInfoKey key(process_id, creation_time, content::PROCESS_TYPE_UNKNOWN);
-  auto it = processes_.find(key);
-  if (it == processes_.end())
-    return nullptr;
-  return &(*it);
-}
-
-void ModuleDatabase::CreateProcessInfo(uint32_t process_id,
-                                       uint64_t creation_time,
-                                       content::ProcessType process_type) {
-  processes_.emplace(std::piecewise_construct,
-                     std::forward_as_tuple(ProcessInfoKey(
-                         process_id, creation_time, process_type)),
-                     std::forward_as_tuple(ProcessInfoData()));
-}
-
-void ModuleDatabase::DeleteProcessInfo(uint32_t process_id,
-                                       uint64_t creation_time) {
-  ProcessInfoKey key(process_id, creation_time, content::PROCESS_TYPE_UNKNOWN);
-  processes_.erase(key);
-}
-
-// ModuleDatabase::ModuleInfoKey -----------------------------------------------
-
-ModuleDatabase::ModuleInfoKey::ModuleInfoKey(const base::FilePath& module_path,
-                                             uint32_t module_size,
-                                             uint32_t module_time_date_stamp,
-                                             uint32_t module_id)
-    : module_path(module_path),
-      module_size(module_size),
-      module_time_date_stamp(module_time_date_stamp),
-      module_id(module_id) {}
-
-bool ModuleDatabase::ModuleInfoKey::operator<(const ModuleInfoKey& mik) const {
-  // The key consists of the triplet of
-  // (module_path, module_size, module_time_date_stamp).
-  // Use the std::tuple lexicographic comparison operator.
-  return std::make_tuple(module_path, module_size, module_time_date_stamp) <
-         std::make_tuple(mik.module_path, mik.module_size,
-                         mik.module_time_date_stamp);
-}
-
-// ModuleDatabase::ModuleInfoData ----------------------------------------------
-
-ModuleDatabase::ModuleInfoData::ModuleInfoData() : process_types(0) {}
-
-// ModuleDatabase::ProcessInfoKey ----------------------------------------------
-
-ModuleDatabase::ProcessInfoKey::ProcessInfoKey(
-    uint32_t process_id,
-    uint64_t creation_time,
-    content::ProcessType process_type)
-    : process_id(process_id),
-      creation_time(creation_time),
-      process_type(process_type) {}
-
-ModuleDatabase::ProcessInfoKey::~ProcessInfoKey() = default;
-
-bool ModuleDatabase::ProcessInfoKey::operator<(
-    const ProcessInfoKey& pik) const {
-  // The key consists of the pair of (process_id, creation_time).
-  // Use the std::tuple lexicographic comparison operator.
-  return std::make_tuple(process_id, creation_time) <
-         std::make_tuple(pik.process_id, pik.creation_time);
-}
-
-// ModuleDatabase::ProcessInfoData ---------------------------------------------
-
-ModuleDatabase::ProcessInfoData::ProcessInfoData() = default;
-
-ModuleDatabase::ProcessInfoData::ProcessInfoData(const ProcessInfoData& other) =
-    default;
-
-ModuleDatabase::ProcessInfoData::~ProcessInfoData() = default;
diff --git a/chrome/browser/conflicts/module_database_win.h b/chrome/browser/conflicts/module_database_win.h
deleted file mode 100644
index 8172082..0000000
--- a/chrome/browser/conflicts/module_database_win.h
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CONFLICTS_MODULE_DATABASE_WIN_H_
-#define CHROME_BROWSER_CONFLICTS_MODULE_DATABASE_WIN_H_
-
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
-#include "content/public/common/process_type.h"
-
-// A class that keeps track of all modules loaded across Chrome processes.
-// Drives the chrome://conflicts UI.
-class ModuleDatabase {
- public:
-  // A ModuleDatabase is by default bound to a provided sequenced task runner.
-  // All calls must be made in the context of this task runner, unless
-  // otherwise noted. For calls from other contexts this task runner is used to
-  // bounce the call when appropriate.
-  explicit ModuleDatabase(scoped_refptr<base::SequencedTaskRunner> task_runner);
-  ~ModuleDatabase();
-
-  // Indicates that process with the given type has started. This must be called
-  // before any calls to OnModuleEvent or OnModuleUnload. Must be called in the
-  // same sequence as |task_runner_|.
-  void OnProcessStarted(uint32_t process_id,
-                        uint64_t creation_time,
-                        content::ProcessType process_type);
-
-  // Indicates that a module has been loaded. The data passed to this function
-  // is taken as gospel, so if it originates from a remote process it should be
-  // independently validated first. (In practice, see ModuleEventSinkImpl for
-  // details of where this happens.)
-  void OnModuleLoad(uint32_t process_id,
-                    uint64_t creation_time,
-                    const base::FilePath& module_path,
-                    uint32_t module_size,
-                    uint32_t module_time_date_stamp,
-                    uintptr_t module_load_address);
-
-  // Indicates that the module at the given |load_address| in the specified
-  // process is being unloaded. This need not be trusted data, as it will be
-  // validated by the ModuleDatabase directly.
-  void OnModuleUnload(uint32_t process_id,
-                      uint64_t creation_time,
-                      uintptr_t module_load_address);
-
-  // Indicates that the given process has ended. This can be called from any
-  // thread and will be bounced to the |task_runner_|. In practice it will be
-  // invoked from the UI thread as the Mojo channel is torn down.
-  void OnProcessEnded(uint32_t process_id, uint64_t creation_time);
-
-  // TODO(chrisha): Module analysis code, and various accessors for use by
-  // chrome://conflicts.
-
- private:
-  friend class TestModuleDatabase;
-  friend class ModuleDatabaseTest;
-  friend class ModuleEventSinkImplTest;
-
-  // Used by the FindLoadAddress* functions to indicate a load address has not
-  // been found.
-  static constexpr size_t kInvalidIndex = ~0u;
-
-  // Used as a unique identifier for a module in a ModuleSet.
-  using ModuleId = int;
-
-  // Structures for maintaining information about modules.
-  struct ModuleInfoKey;
-  struct ModuleInfoData;
-  using ModuleMap = std::map<ModuleInfoKey, ModuleInfoData>;
-  using ModuleInfo = ModuleMap::value_type;
-
-  // Used for maintaing a list of modules loaded in a process. Maps module IDs
-  // to load addresses.
-  using ModuleLoadAddresses = std::vector<std::pair<ModuleId, uintptr_t>>;
-
-  // Structures for maintaining information about running processes.
-  struct ProcessInfoKey;
-  struct ProcessInfoData;
-  using ProcessMap = std::map<ProcessInfoKey, ProcessInfoData>;
-  using ProcessInfo = ProcessMap::value_type;
-
-  // Converts a valid |process_type| to a bit for use in a bitmask of process
-  // values. Exposed in the header for testing.
-  static uint32_t ProcessTypeToBit(content::ProcessType process_type);
-
-  // Converts a |bit_index| (which maps to the bit 1 << bit_index) to the
-  // corresponding process type. Exposed in the header for testing.
-  static content::ProcessType BitIndexToProcessType(uint32_t bit_index);
-
-  // Performs a linear scan to find the index of a |module_id| or |load_address|
-  // in a collection of modules. Returns kInvalidIndex if the index is not
-  // found.
-  static size_t FindLoadAddressIndexById(
-      ModuleId module_id,
-      const ModuleLoadAddresses& load_addresses);
-  static size_t FindLoadAddressIndexByAddress(
-      uintptr_t load_address,
-      const ModuleLoadAddresses& load_addresses);
-
-  // Inserts a module into a ModuleLoadAddress object.
-  static void InsertLoadAddress(ModuleId module_id,
-                                uintptr_t load_address,
-                                ModuleLoadAddresses* load_addresses);
-
-  // Removes a module from a ModuleLoadAddress object, either by the
-  // |module_id| or the |index| in the collection.
-  static void RemoveLoadAddressById(ModuleId module_id,
-                                    ModuleLoadAddresses* load_addresses);
-  static void RemoveLoadAddressByIndex(size_t index,
-                                       ModuleLoadAddresses* load_addresses);
-
-  // Finds or creates a mutable ModuleInfo entry.
-  ModuleInfo* FindOrCreateModuleInfo(const base::FilePath& module_path,
-                                     uint32_t module_size,
-                                     uint32_t module_time_date_stamp);
-
-  // Finds a process info entry. Returns nullptr if none is found.
-  ProcessInfo* GetProcessInfo(uint32_t process_id, uint64_t creation_time);
-
-  // Creates a process info entry.
-  void CreateProcessInfo(uint32_t process_id,
-                         uint64_t creation_time,
-                         content::ProcessType process_type);
-
-  // Deletes a process info entry.
-  void DeleteProcessInfo(uint32_t process_id, uint64_t creation_time);
-
-  // The task runner to which this object is bound.
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
-  // A map of all known modules.
-  ModuleMap modules_;
-
-  // A map of all known running processes, and modules loaded/unloaded in
-  // them.
-  ProcessMap processes_;
-
-  // Weak pointer factory for this object. This is used when bouncing
-  // incoming events to |task_runner_|.
-  base::WeakPtrFactory<ModuleDatabase> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ModuleDatabase);
-};
-
-// Maintains information about a module. Modules are permanent once added to
-// the ModuleSet, so this structure grows monotonically. In practice this is
-// not an issue as the modules themselves are vastly bigger than the minor
-// amount of metadata tracked here.
-
-// This is the constant portion of the module information, and acts as the key
-// in a std::map.
-struct ModuleDatabase::ModuleInfoKey {
-  ModuleInfoKey(const base::FilePath& module_path,
-                uint32_t module_size,
-                uint32_t module_time_date_stamp,
-                uint32_t module_id);
-
-  // Less-than operator allowing this object to be used in std::map.
-  bool operator<(const ModuleInfoKey& mi) const;
-
-  // Full path to the module on disk. Part of the key for a ModuleInfo.
-  base::FilePath module_path;
-
-  // The module size. Part of the key for a ModuleInfo. This is taken from
-  // SizeOfImage from the module's IMAGE_OPTIONAL_HEADER.
-  uint32_t module_size;
-
-  // The module time date stamp. Part of the key for a ModuleInfo. Taken from
-  // TimeDateStamp from the module's IMAGE_FILE_HEADER.
-  uint32_t module_time_date_stamp;
-
-  // The ID of this module. This is a strictly incrementing value, and is used
-  // to tie a module to the list of running processes in which it is found.
-  // It is not part of the key for the module, but it is immutable. This is
-  // simply the index of the module in the insertion order.
-  ModuleId module_id;
-};
-
-// This is the mutable portion of the module information, and is the storage
-// type in a std::map.
-struct ModuleDatabase::ModuleInfoData {
-  ModuleInfoData();
-
-  // Set of all process types in which this module has been seen (may not be
-  // currently present in a process of that type). This is a conversion of
-  // ProcessType enumeration to a bitfield. See "ProcessTypeToBit" and
-  // "BitIndexToProcessType" for details.
-  uint32_t process_types;
-};
-
-// Information about a running process. This ties modules in a ModuleSet to
-// processes in which they are (or have been) loaded.
-
-// This is the constant portion of the process information, and acts as the key
-// in a std::map.
-struct ModuleDatabase::ProcessInfoKey {
-  ProcessInfoKey(uint32_t process_id,
-                 uint64_t creation_time,
-                 content::ProcessType process_type);
-  ~ProcessInfoKey();
-
-  // Less-than operator allowing this object to be used in std::map.
-  bool operator<(const ProcessInfoKey& pi) const;
-
-  // The process ID.
-  uint32_t process_id;
-
-  // The process creation time. A raw FILETIME value with full precision.
-  // Combined with |process_id| this uniquely identifies a process on a Windows
-  // system.
-  uint64_t creation_time;
-
-  // The type of the process.
-  content::ProcessType process_type;
-};
-
-// This is the mutable portion of the process information, and is the storage
-// type in a std::map.
-struct ModuleDatabase::ProcessInfoData {
-  ProcessInfoData();
-  ProcessInfoData(const ProcessInfoData& other);
-  ~ProcessInfoData();
-
-  // The sets of modules that are loaded/unloaded in this process, by ID. This
-  // is typically a small list so a linear cost is okay to pay for
-  // lookup/deletion (storage is backed by a vector).
-  //
-  // These are modified by the various static *LoadAddress* helper functions in
-  // ModuleDatabase. The vector maintains the invariant the element with maximum
-  // module ID is always last. This ensures that the usual operation of loading
-  // a module is O(1).
-  ModuleLoadAddresses loaded_modules;
-  ModuleLoadAddresses unloaded_modules;
-};
-
-#endif  // CHROME_BROWSER_CONFLICTS_MODULE_DATABASE_WIN_H_
diff --git a/chrome/browser/conflicts/module_database_win_unittest.cc b/chrome/browser/conflicts/module_database_win_unittest.cc
deleted file mode 100644
index a5c3c17..0000000
--- a/chrome/browser/conflicts/module_database_win_unittest.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/module_database_win.h"
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// A simple mechanism for running a single task on a separate thread.
-class SingleTaskRunner : public base::SimpleThread {
- public:
-  explicit SingleTaskRunner(base::Closure task)
-      : base::SimpleThread("SingleTaskRunner"), task_(std::move(task)) {}
-
-  // Runs the provided task and exits.
-  void Run() override { task_.Run(); }
-
- private:
-  base::Closure task_;
-  DISALLOW_COPY_AND_ASSIGN(SingleTaskRunner);
-};
-
-// Launches a thread and runs a single task on it.
-void RunTask(base::Closure task) {
-  SingleTaskRunner task_runner(std::move(task));
-  task_runner.Start();
-  task_runner.Join();
-}
-
-constexpr uint32_t kPid1 = 1234u;
-constexpr uint32_t kPid2 = 2345u;
-
-constexpr uint64_t kCreateTime1 = 1234u;
-constexpr uint64_t kCreateTime2 = 2345u;
-
-constexpr wchar_t kDll1[] = L"dummy.dll";
-constexpr wchar_t kDll2[] = L"foo.dll";
-
-constexpr size_t kSize1 = 100 * 4096;
-constexpr size_t kSize2 = 20 * 4096;
-
-constexpr uint32_t kTime1 = 0xDEADBEEF;
-constexpr uint32_t kTime2 = 0xBAADF00D;
-
-constexpr uintptr_t kGoodAddress1 = 0x04000000u;
-constexpr uintptr_t kGoodAddress2 = 0x05000000u;
-
-}  // namespace
-
-class TestModuleDatabase : ModuleDatabase {
- public:
-  // Types.
-  using ModuleDatabase::ModuleId;
-  using ModuleDatabase::ModuleLoadAddresses;
-
-  // Constants.
-  using ModuleDatabase::kInvalidIndex;
-
-  // Functions.
-  using ModuleDatabase::FindLoadAddressIndexById;
-  using ModuleDatabase::FindLoadAddressIndexByAddress;
-  using ModuleDatabase::InsertLoadAddress;
-  using ModuleDatabase::RemoveLoadAddressById;
-  using ModuleDatabase::RemoveLoadAddressByIndex;
-};
-
-class ModuleDatabaseTest : public testing::Test {
- protected:
-  ModuleDatabaseTest()
-      : dll1_(kDll1),
-        dll2_(kDll2),
-        message_loop_(base::MakeUnique<base::MessageLoop>()),
-        module_database_(
-            base::MakeUnique<ModuleDatabase>(message_loop_->task_runner())) {}
-
-  void RunLoopUntilIdle() { base::RunLoop().RunUntilIdle(); }
-
-  const ModuleDatabase::ModuleMap& modules() {
-    return module_database_->modules_;
-  }
-
-  const ModuleDatabase::ProcessMap& processes() {
-    return module_database_->processes_;
-  }
-
-  static uint32_t ProcessTypeToBit(content::ProcessType process_type) {
-    return ModuleDatabase::ProcessTypeToBit(process_type);
-  }
-
-  // Counts the occurrences of the given |module_id| in the given collection of
-  // |load_addresses|.
-  static size_t ModuleIdCount(
-      ModuleDatabase::ModuleId module_id,
-      const ModuleDatabase::ModuleLoadAddresses& load_addresses) {
-    return std::count_if(
-        load_addresses.begin(), load_addresses.end(),
-        [module_id](const auto& x) { return module_id == x.first; });
-  }
-
- protected:
-  const base::FilePath dll1_;
-  const base::FilePath dll2_;
-
-  std::unique_ptr<base::MessageLoop> message_loop_;
-  std::unique_ptr<ModuleDatabase> module_database_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ModuleDatabaseTest);
-};
-
-TEST_F(ModuleDatabaseTest, LoadAddressVectorOperations) {
-  using TMD = TestModuleDatabase;
-  TestModuleDatabase::ModuleLoadAddresses la;
-
-  // Finds should fail in an empty collection.
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0, la));
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0x04000000, la));
-
-  // A first insert should work. Don't start with ModuleId 0 so that later
-  // inserts can insert that module.
-  TMD::InsertLoadAddress(10, 0x04000000, &la);
-  EXPECT_EQ(1u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-
-  // Finds should work.
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0, la));
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0x03000000, la));
-  EXPECT_EQ(0u, TMD::FindLoadAddressIndexById(10, la));
-  EXPECT_EQ(0u, TMD::FindLoadAddressIndexByAddress(0x04000000, la));
-
-  // A second insert should work. This is the new max so should be at the end
-  // of the collection.
-  TMD::InsertLoadAddress(12, 0x06000000, &la);
-  EXPECT_EQ(2u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-  EXPECT_EQ(12, la[1].first);
-  EXPECT_EQ(0x06000000u, la[1].second);
-
-  // Finds should work.
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0, la));
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0x03000000, la));
-  EXPECT_EQ(0u, TMD::FindLoadAddressIndexById(10, la));
-  EXPECT_EQ(0u, TMD::FindLoadAddressIndexByAddress(0x04000000, la));
-  EXPECT_EQ(1u, TMD::FindLoadAddressIndexById(12, la));
-  EXPECT_EQ(1u, TMD::FindLoadAddressIndexByAddress(0x06000000, la));
-
-  // Another insert should work. This is not the new max, so a swap should
-  // happen to keep the maximum element at the end of the collection.
-  TMD::InsertLoadAddress(11, 0x05000000, &la);
-  EXPECT_EQ(3u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-  EXPECT_EQ(11, la[1].first);
-  EXPECT_EQ(0x05000000u, la[1].second);
-  EXPECT_EQ(12, la[2].first);
-  EXPECT_EQ(0x06000000u, la[2].second);
-
-  // An insert of an existing module should work, but simply overwrite the
-  // load address.
-  TMD::InsertLoadAddress(11, 0x0F000000, &la);
-  EXPECT_EQ(3u, la.size());
-  EXPECT_EQ(11, la[1].first);
-  EXPECT_EQ(0x0F000000u, la[1].second);
-  TMD::InsertLoadAddress(11, 0x05000000, &la);
-  EXPECT_EQ(3u, la.size());
-  EXPECT_EQ(11, la[1].first);
-  EXPECT_EQ(0x05000000u, la[1].second);
-
-  // Finds should work.
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0, la));
-  EXPECT_EQ(TMD::kInvalidIndex, TMD::FindLoadAddressIndexById(0x03000000, la));
-  EXPECT_EQ(0u, TMD::FindLoadAddressIndexById(10, la));
-  EXPECT_EQ(0u, TMD::FindLoadAddressIndexByAddress(0x04000000, la));
-  EXPECT_EQ(1u, TMD::FindLoadAddressIndexById(11, la));
-  EXPECT_EQ(1u, TMD::FindLoadAddressIndexByAddress(0x05000000, la));
-  EXPECT_EQ(2u, TMD::FindLoadAddressIndexById(12, la));
-  EXPECT_EQ(2u, TMD::FindLoadAddressIndexByAddress(0x06000000, la));
-
-  // Do some inserts of lower modules IDs. This ensures that we'll have some
-  // higher module IDs in the vector before some lower modules IDs, for testing
-  // the deletion logic.
-  TMD::InsertLoadAddress(3, 0x07000000, &la);
-  TMD::InsertLoadAddress(4, 0x08000000, &la);
-  TMD::InsertLoadAddress(5, 0x09000000, &la);
-  EXPECT_EQ(6u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-  EXPECT_EQ(11, la[1].first);
-  EXPECT_EQ(0x05000000u, la[1].second);
-  EXPECT_EQ(3, la[2].first);
-  EXPECT_EQ(0x07000000u, la[2].second);
-  EXPECT_EQ(4, la[3].first);
-  EXPECT_EQ(0x08000000u, la[3].second);
-  EXPECT_EQ(5, la[4].first);
-  EXPECT_EQ(0x09000000u, la[4].second);
-  EXPECT_EQ(12, la[5].first);
-  EXPECT_EQ(0x06000000u, la[5].second);
-
-  // Remove an element that isn't in the second last position. The second last
-  // element should be swapped into its position, and the last element moved
-  // to the second last place.
-  TMD::RemoveLoadAddressByIndex(2, &la);
-  EXPECT_EQ(5u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-  EXPECT_EQ(11, la[1].first);
-  EXPECT_EQ(0x05000000u, la[1].second);
-  EXPECT_EQ(5, la[2].first);
-  EXPECT_EQ(0x09000000u, la[2].second);
-  EXPECT_EQ(4, la[3].first);
-  EXPECT_EQ(0x08000000u, la[3].second);
-  EXPECT_EQ(12, la[4].first);
-  EXPECT_EQ(0x06000000u, la[4].second);
-
-  // Remove the second last element. Only the last element should move.
-  TMD::RemoveLoadAddressByIndex(3, &la);
-  EXPECT_EQ(4u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-  EXPECT_EQ(11, la[1].first);
-  EXPECT_EQ(0x05000000u, la[1].second);
-  EXPECT_EQ(5, la[2].first);
-  EXPECT_EQ(0x09000000u, la[2].second);
-  EXPECT_EQ(12, la[3].first);
-  EXPECT_EQ(0x06000000u, la[3].second);
-
-  // Remove the last element. The new maximum should be found moved to the
-  // end.
-  TMD::RemoveLoadAddressByIndex(3, &la);
-  EXPECT_EQ(3u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-  EXPECT_EQ(5, la[1].first);
-  EXPECT_EQ(0x09000000u, la[1].second);
-  EXPECT_EQ(11, la[2].first);
-  EXPECT_EQ(0x05000000u, la[2].second);
-
-  // Remove the last element by ModuleId. The remaining modules should be
-  // swapped.
-  TMD::RemoveLoadAddressById(11, &la);
-  EXPECT_EQ(2u, la.size());
-  EXPECT_EQ(5, la[0].first);
-  EXPECT_EQ(0x09000000u, la[0].second);
-  EXPECT_EQ(10, la[1].first);
-  EXPECT_EQ(0x04000000u, la[1].second);
-
-  // Remove the first element by ModuleId.
-  TMD::RemoveLoadAddressById(5, &la);
-  EXPECT_EQ(1u, la.size());
-  EXPECT_EQ(10, la[0].first);
-  EXPECT_EQ(0x04000000u, la[0].second);
-
-  // Remove the only remaining element.
-  TMD::RemoveLoadAddressByIndex(0, &la);
-  EXPECT_TRUE(la.empty());
-}
-
-TEST_F(ModuleDatabaseTest, LoadAddressVectorStressTest) {
-  using TMD = TestModuleDatabase;
-  TestModuleDatabase::ModuleLoadAddresses la;
-
-  for (size_t n = 1; n < 200; ++n) {
-    // Will keep track of which elements have been inserted.
-    std::vector<bool> inserted(n);
-    size_t inserted_count = 0;
-
-    // Generate a shuffled list of IDs. This will be the insertion order.
-    // More insertions than elements will occur so that rewrites occur.,
-    std::vector<TMD::ModuleId> ids(11 * n / 10);
-    for (size_t i = 0; i < 11 * n / 10; ++i)
-      ids[i] = i % n;
-    std::random_shuffle(ids.begin(), ids.end());
-
-    // Do the insertions.
-    for (auto id : ids) {
-      if (!inserted[id]) {
-        inserted[id] = true;
-        ++inserted_count;
-      }
-
-      // Generate a load address. The load address bakes in the index so that
-      // searching by load address is easy.
-      uintptr_t load_address = static_cast<uintptr_t>(id) << 16;
-
-      // Do the insertion.
-      TMD::InsertLoadAddress(id, load_address, &la);
-      EXPECT_EQ(inserted_count, la.size());
-    }
-
-    // Validate that every element is there, via both search mechanisms.
-    for (size_t id = 0; id < n; ++id) {
-      uintptr_t load_address = static_cast<uintptr_t>(id) << 16;
-      size_t index1 = TMD::FindLoadAddressIndexById(id, la);
-      size_t index2 = TMD::FindLoadAddressIndexByAddress(load_address, la);
-      EXPECT_NE(TMD::kInvalidIndex, index1);
-      EXPECT_EQ(index1, index2);
-    }
-
-    // Generate the deletion order.
-    ids.resize(n);
-    for (size_t i = 0; i < ids.size(); ++i)
-      ids[i] = i;
-    std::random_shuffle(ids.begin(), ids.end());
-
-    // Do the deletions.
-    for (auto id : ids) {
-      --inserted_count;
-      TMD::RemoveLoadAddressById(id, &la);
-      EXPECT_EQ(inserted_count, la.size());
-    }
-  }
-}
-
-TEST_F(ModuleDatabaseTest, TasksAreBounced) {
-  // Run a task on the current thread. This should not be bounced, so no
-  // task should be scheduled on the task runner.
-  module_database_->OnProcessStarted(kPid1, kCreateTime1,
-                                     content::PROCESS_TYPE_BROWSER);
-  EXPECT_TRUE(message_loop_->IsIdleForTesting());
-  module_database_->OnModuleLoad(kPid1, kCreateTime1, dll1_, kSize1, kTime1,
-                                 kGoodAddress1);
-  EXPECT_TRUE(message_loop_->IsIdleForTesting());
-  module_database_->OnProcessEnded(kPid1, kCreateTime1);
-  EXPECT_TRUE(message_loop_->IsIdleForTesting());
-
-  // Indicate another process start on this thread. This call can't be
-  // bounced.
-  module_database_->OnProcessStarted(kPid2, kCreateTime2,
-                                     content::PROCESS_TYPE_BROWSER);
-
-  // Run similar tasks on another thread. These should be bounced.
-  RunTask(base::Bind(&ModuleDatabase::OnModuleLoad,
-                     base::Unretained(module_database_.get()), kPid2,
-                     kCreateTime2, dll1_, kSize1, kTime1, kGoodAddress1));
-  EXPECT_FALSE(message_loop_->IsIdleForTesting());
-  RunLoopUntilIdle();
-
-  RunTask(base::Bind(&ModuleDatabase::OnProcessEnded,
-                     base::Unretained(module_database_.get()), kPid2,
-                     kCreateTime2));
-  EXPECT_FALSE(message_loop_->IsIdleForTesting());
-  RunLoopUntilIdle();
-}
-
-TEST_F(ModuleDatabaseTest, EventsWithoutProcessIgnore) {
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(0u, processes().size());
-
-  module_database_->OnModuleLoad(kPid1, kCreateTime1, dll1_, kSize1, kTime1,
-                                 kGoodAddress1);
-
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(0u, processes().size());
-}
-
-TEST_F(ModuleDatabaseTest, OrphanedUnloadIgnored) {
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(0u, processes().size());
-
-  // Start a process.
-  module_database_->OnProcessStarted(kPid1, kCreateTime1,
-                                     content::PROCESS_TYPE_BROWSER);
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-  auto p1 = processes().begin();
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_BROWSER, p1->first.process_type);
-  EXPECT_EQ(0u, p1->second.loaded_modules.size());
-  EXPECT_EQ(0u, p1->second.unloaded_modules.size());
-
-  // Indicate a module unload. This should do nothing because there's no
-  // corresponding module.
-  module_database_->OnModuleUnload(kPid1, kCreateTime1, kGoodAddress1);
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-  EXPECT_EQ(0u, p1->second.loaded_modules.size());
-  EXPECT_EQ(0u, p1->second.unloaded_modules.size());
-}
-
-TEST_F(ModuleDatabaseTest, DatabaseIsConsistent) {
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(0u, processes().size());
-
-  // Start a process.
-  module_database_->OnProcessStarted(kPid1, kCreateTime1,
-                                     content::PROCESS_TYPE_BROWSER);
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-  auto p1 = processes().begin();
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_BROWSER, p1->first.process_type);
-  EXPECT_EQ(0u, p1->second.loaded_modules.size());
-  EXPECT_EQ(0u, p1->second.unloaded_modules.size());
-
-  // Load a module.
-  module_database_->OnModuleLoad(kPid1, kCreateTime1, dll1_, kSize1, kTime1,
-                                 kGoodAddress1);
-  EXPECT_EQ(1u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-
-  // Ensure that the process and module sets are up to date.
-  auto m1 = modules().begin();
-  EXPECT_EQ(dll1_, m1->first.module_path);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER),
-            m1->second.process_types);
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_BROWSER, p1->first.process_type);
-  EXPECT_EQ(1u, p1->second.loaded_modules.size());
-  EXPECT_EQ(0u, p1->second.unloaded_modules.size());
-  EXPECT_EQ(1u, ModuleIdCount(m1->first.module_id, p1->second.loaded_modules));
-
-  // Provide a redundant load message for that module.
-  module_database_->OnModuleLoad(kPid1, kCreateTime1, dll1_, kSize1, kTime1,
-                                 kGoodAddress1);
-  EXPECT_EQ(1u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-
-  // Ensure that the process and module sets haven't changed.
-  EXPECT_EQ(dll1_, m1->first.module_path);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER),
-            m1->second.process_types);
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_BROWSER, p1->first.process_type);
-  EXPECT_EQ(1u, p1->second.loaded_modules.size());
-  EXPECT_EQ(0u, p1->second.unloaded_modules.size());
-  EXPECT_EQ(1u, ModuleIdCount(m1->first.module_id, p1->second.loaded_modules));
-
-  // Load a second module into the process.
-  module_database_->OnModuleLoad(kPid1, kCreateTime1, dll2_, kSize2, kTime2,
-                                 kGoodAddress2);
-  EXPECT_EQ(2u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-
-  // Ensure that the process and module sets are up to date.
-  auto m2 = modules().rbegin();
-  EXPECT_EQ(dll2_, m2->first.module_path);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER),
-            m2->second.process_types);
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_BROWSER, p1->first.process_type);
-  EXPECT_EQ(2u, p1->second.loaded_modules.size());
-  EXPECT_EQ(0u, p1->second.unloaded_modules.size());
-  EXPECT_EQ(1u, ModuleIdCount(m1->first.module_id, p1->second.loaded_modules));
-  EXPECT_EQ(1u, ModuleIdCount(m2->first.module_id, p1->second.loaded_modules));
-
-  // Unload the second module.
-  module_database_->OnModuleUnload(kPid1, kCreateTime1, kGoodAddress2);
-  EXPECT_EQ(2u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-
-  // Ensure that the process and module sets are up to date.
-  EXPECT_EQ(dll2_, m2->first.module_path);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER),
-            m2->second.process_types);
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_BROWSER, p1->first.process_type);
-  EXPECT_EQ(1u, p1->second.loaded_modules.size());
-  EXPECT_EQ(1u, p1->second.unloaded_modules.size());
-  EXPECT_EQ(1u, ModuleIdCount(m1->first.module_id, p1->second.loaded_modules));
-  EXPECT_EQ(1u,
-            ModuleIdCount(m2->first.module_id, p1->second.unloaded_modules));
-
-  // Start a process.
-  module_database_->OnProcessStarted(kPid2, kCreateTime2,
-                                     content::PROCESS_TYPE_RENDERER);
-  EXPECT_EQ(2u, modules().size());
-  EXPECT_EQ(2u, processes().size());
-  auto p2 = processes().rbegin();
-  EXPECT_EQ(kPid2, p2->first.process_id);
-  EXPECT_EQ(kCreateTime2, p2->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_RENDERER, p2->first.process_type);
-  EXPECT_EQ(0u, p2->second.loaded_modules.size());
-  EXPECT_EQ(0u, p2->second.unloaded_modules.size());
-
-  // Load the dummy.dll in the second process as well.
-  module_database_->OnModuleLoad(kPid2, kCreateTime2, dll1_, kSize1, kTime1,
-                                 kGoodAddress1);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER) |
-                ProcessTypeToBit(content::PROCESS_TYPE_RENDERER),
-            m1->second.process_types);
-  EXPECT_EQ(kPid2, p2->first.process_id);
-  EXPECT_EQ(kCreateTime2, p2->first.creation_time);
-  EXPECT_EQ(content::PROCESS_TYPE_RENDERER, p2->first.process_type);
-  EXPECT_EQ(1u, p2->second.loaded_modules.size());
-  EXPECT_EQ(0u, p2->second.unloaded_modules.size());
-  EXPECT_EQ(1u, ModuleIdCount(m1->first.module_id, p2->second.loaded_modules));
-
-  // End the second process without an explicit unload. This invalidates |p2|.
-  module_database_->OnProcessEnded(kPid2, kCreateTime2);
-  EXPECT_EQ(2u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-  EXPECT_EQ(kPid1, p1->first.process_id);
-  EXPECT_EQ(kCreateTime1, p1->first.creation_time);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER) |
-                ProcessTypeToBit(content::PROCESS_TYPE_RENDERER),
-            m1->second.process_types);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER),
-            m2->second.process_types);
-
-  // End the first process without an explicit unload. This invalidates |p1|.
-  module_database_->OnProcessEnded(kPid1, kCreateTime1);
-  EXPECT_EQ(2u, modules().size());
-  EXPECT_EQ(0u, processes().size());
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER) |
-                ProcessTypeToBit(content::PROCESS_TYPE_RENDERER),
-            m1->second.process_types);
-  EXPECT_EQ(ProcessTypeToBit(content::PROCESS_TYPE_BROWSER),
-            m2->second.process_types);
-}
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win.cc b/chrome/browser/conflicts/module_event_sink_impl_win.cc
deleted file mode 100644
index 428b382..0000000
--- a/chrome/browser/conflicts/module_event_sink_impl_win.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/module_event_sink_impl_win.h"
-
-#include <windows.h>
-#include <psapi.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_piece.h"
-#include "chrome/browser/conflicts/module_database_win.h"
-#include "chrome/common/conflicts/module_watcher_win.h"
-#include "content/public/browser/browser_thread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace {
-
-// Gets the process creation time associated with the given process.
-bool GetProcessCreationTime(base::ProcessHandle process,
-                            uint64_t* creation_time) {
-  FILETIME creation_ft = {};
-  FILETIME exit_ft = {};
-  FILETIME kernel_ft = {};
-  FILETIME user_ft = {};
-  if (!::GetProcessTimes(process, &creation_ft, &exit_ft, &kernel_ft,
-                         &user_ft)) {
-    return false;
-  }
-  *creation_time = (static_cast<uint64_t>(creation_ft.dwHighDateTime) << 32) |
-                   static_cast<uint64_t>(creation_ft.dwLowDateTime);
-  return true;
-}
-
-// Gets the path of the module in the provided remote process. Returns true on
-// success, false otherwise.
-bool GetModulePath(base::ProcessHandle process,
-                   HMODULE module,
-                   base::FilePath* path) {
-  std::vector<wchar_t> temp_path(MAX_PATH);
-  size_t length = 0;
-  while (true) {
-    length = ::GetModuleFileNameEx(process, module, temp_path.data(),
-                                   temp_path.size());
-    if (length == 0)
-      return false;
-    if (length < temp_path.size())
-      break;
-    // The entire buffer was consumed, so grow it to ensure the result wasn't
-    // actually truncated.
-    temp_path.resize(2 * temp_path.size());
-  }
-
-  *path = base::FilePath(base::StringPiece16(temp_path.data(), length));
-  return true;
-}
-
-// Gets the size of a module in a remote process. Returns true on success, false
-// otherwise.
-bool GetModuleSize(base::ProcessHandle process,
-                   HMODULE module,
-                   uint32_t* size) {
-  MODULEINFO info = {};
-  if (!::GetModuleInformation(process, module, &info, sizeof(info)))
-    return false;
-  *size = info.SizeOfImage;
-  return true;
-}
-
-// Reads the typed data from a remote process. Returns true on success, false
-// otherwise.
-template <typename T>
-bool ReadRemoteData(base::ProcessHandle process, uint64_t address, T* data) {
-  const void* typed_address =
-      reinterpret_cast<const void*>(static_cast<uintptr_t>(address));
-  SIZE_T bytes_read = 0;
-  if (!::ReadProcessMemory(process, typed_address, &data, sizeof(data),
-                           &bytes_read)) {
-    return false;
-  }
-  if (bytes_read != sizeof(data))
-    return false;
-  return true;
-}
-
-// Reads the time date stamp from the module loaded in the provided remote
-// |process| at the provided remote |load_address|.
-bool GetModuleTimeDateStamp(base::ProcessHandle process,
-                            uint64_t load_address,
-                            uint32_t* time_date_stamp) {
-  uint64_t address = load_address + offsetof(IMAGE_DOS_HEADER, e_lfanew);
-  LONG e_lfanew = 0;
-  if (!ReadRemoteData(process, address, &e_lfanew))
-    return false;
-
-  address = load_address + e_lfanew + offsetof(IMAGE_NT_HEADERS, FileHeader) +
-            offsetof(IMAGE_FILE_HEADER, TimeDateStamp);
-  DWORD temp = 0;
-  if (!ReadRemoteData(process, address, &temp))
-    return false;
-
-  *time_date_stamp = temp;
-  return true;
-}
-
-}  // namespace
-
-ModuleEventSinkImpl::ModuleEventSinkImpl(base::ProcessHandle process,
-                                         content::ProcessType process_type,
-                                         ModuleDatabase* module_database)
-    : process_(process),
-      module_database_(module_database),
-      process_id_(0),
-      creation_time_(0),
-      in_error_(false) {
-  // Failing to get basic process information means this channel should not
-  // continue to forward data, thus it is marked as being in error.
-  process_id_ = ::GetProcessId(process_);
-  if (!GetProcessCreationTime(process_, &creation_time_)) {
-    in_error_ = true;
-    return;
-  }
-  module_database->OnProcessStarted(process_id_, creation_time_, process_type);
-}
-
-ModuleEventSinkImpl::~ModuleEventSinkImpl() = default;
-
-// static
-void ModuleEventSinkImpl::Create(base::ProcessHandle process,
-                                 content::ProcessType process_type,
-                                 ModuleDatabase* module_database,
-                                 mojom::ModuleEventSinkRequest request) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  auto module_event_sink_impl = base::MakeUnique<ModuleEventSinkImpl>(
-      process, process_type, module_database);
-  base::Closure error_handler = base::Bind(
-      &ModuleDatabase::OnProcessEnded, base::Unretained(module_database),
-      module_event_sink_impl->process_id_,
-      module_event_sink_impl->creation_time_);
-  auto binding = mojo::MakeStrongBinding(std::move(module_event_sink_impl),
-                                         std::move(request));
-  binding->set_connection_error_handler(error_handler);
-}
-
-void ModuleEventSinkImpl::OnModuleEvent(mojom::ModuleEventType event_type,
-                                        uint64_t load_address) {
-  if (in_error_)
-    return;
-
-  // Mojo takes care of validating |event_type|, so only |load_address| needs to
-  // be checked. Load addresses must be aligned with the allocation granularity
-  // which is at least 64KB on any supported Windows OS.
-  if (load_address == 0 || load_address % (64 * 1024) != 0)
-    return;
-
-  switch (event_type) {
-    case mojom::ModuleEventType::MODULE_ALREADY_LOADED:
-    case mojom::ModuleEventType::MODULE_LOADED:
-      return OnModuleLoad(load_address);
-
-    case mojom::ModuleEventType::MODULE_UNLOADED:
-      return OnModuleUnload(load_address);
-  }
-}
-
-void ModuleEventSinkImpl::OnModuleLoad(uint64_t load_address) {
-  if (in_error_)
-    return;
-
-  // The |load_address| is a unique key to a module in a remote process. If
-  // there is a valid module there then the following queries should all pass.
-  // If any of them fail then the load event is silently swallowed. The entire
-  // channel is not marked as being in an error mode, as later events may be
-  // well formed.
-
-  // Convert the |load_address| to a module handle.
-  HMODULE module =
-      reinterpret_cast<HMODULE>(static_cast<uintptr_t>(load_address));
-
-  // Look up the various pieces of module metadata in the remote process.
-
-  base::FilePath module_path;
-  if (!GetModulePath(process_, module, &module_path))
-    return;
-
-  uint32_t module_size = 0;
-  if (!GetModuleSize(process_, module, &module_size))
-    return;
-
-  uint32_t module_time_date_stamp = 0;
-  if (!GetModuleTimeDateStamp(process_, load_address, &module_time_date_stamp))
-    return;
-
-  // Forward this to the module database.
-  module_database_->OnModuleLoad(process_id_, creation_time_, module_path,
-                                 module_size, module_time_date_stamp,
-                                 load_address);
-}
-
-void ModuleEventSinkImpl::OnModuleUnload(uint64_t load_address) {
-  // Forward this directly to the module database.
-  module_database_->OnModuleUnload(process_id_, creation_time_,
-                                   static_cast<uintptr_t>(load_address));
-}
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win.h b/chrome/browser/conflicts/module_event_sink_impl_win.h
deleted file mode 100644
index 5f5b7ce..0000000
--- a/chrome/browser/conflicts/module_event_sink_impl_win.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CONFLICTS_MODULE_EVENT_SINK_IMPL_WIN_H_
-#define CHROME_BROWSER_CONFLICTS_MODULE_EVENT_SINK_IMPL_WIN_H_
-
-#include <stdint.h>
-
-#include "base/process/process_handle.h"
-#include "chrome/common/conflicts/module_event_sink_win.mojom.h"
-#include "content/public/common/process_type.h"
-
-class ModuleDatabase;
-
-// Implementation of the mojom::ModuleEventSink interface. This is the endpoint
-// in the browser process. This redirects calls to the singleton ModuleDatabase
-// object.
-class ModuleEventSinkImpl : public mojom::ModuleEventSink {
- public:
-  // Creates a service endpoint that forwards notifications from the remote
-  // |process| of the provided |process_type| to the provided |module_database|.
-  // The |module_database| must outlive this object.
-  ModuleEventSinkImpl(base::ProcessHandle process,
-                      content::ProcessType process_type,
-                      ModuleDatabase* module_database);
-  ~ModuleEventSinkImpl() override;
-
-  // Factory function for use with service_manager::InterfaceRegistry. This
-  // creates a concrete implementation of mojom::ModuleDatabase interface in the
-  // current process, for the remote process represented by the provided
-  // |request|. This should only be called on the UI thread.
-  static void Create(base::ProcessHandle process,
-                     content::ProcessType process_type,
-                     ModuleDatabase* module_database,
-                     mojom::ModuleEventSinkRequest request);
-
-  // mojom::ModuleEventSink implementation:
-  void OnModuleEvent(mojom::ModuleEventType event_type,
-                     uint64_t load_address) override;
-
-  bool in_error() const { return in_error_; }
-
- private:
-  friend class ModuleEventSinkImplTest;
-
-  // OnModuleEvent disptaches to these two functions depending on the event
-  // type.
-  void OnModuleLoad(uint64_t load_address);
-  void OnModuleUnload(uint64_t load_address);
-
-  // A handle to the process on the other side of the pipe.
-  base::ProcessHandle process_;
-
-  // The module database this forwards events to. The |module_database| must
-  // outlive this object.
-  ModuleDatabase* module_database_;
-
-  // The process ID of the remote process on the other end of the pipe. This is
-  // forwarded along to the ModuleDatabase for each call.
-  uint32_t process_id_;
-
-  // The creation time of the process. Combined with process_id_ this uniquely
-  // identifies a process.
-  uint64_t creation_time_;
-
-  // Indicates whether or not this connection is in an error mode. If true then
-  // all communication from the remote client is silently dropped.
-  bool in_error_;
-
-  DISALLOW_COPY_AND_ASSIGN(ModuleEventSinkImpl);
-};
-
-#endif  // CHROME_BROWSER_CONFLICTS_MODULE_EVENT_SINK_IMPL_WIN_H_
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc b/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc
deleted file mode 100644
index 8b88fce..0000000
--- a/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/module_event_sink_impl_win.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "chrome/browser/conflicts/module_database_win.h"
-#include "chrome/common/conflicts/module_watcher_win.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// The address of this module in memory. The linker will take care of defining
-// this symbol.
-extern "C" IMAGE_DOS_HEADER __ImageBase;
-
-// An invalid load address.
-const uint64_t kInvalidLoadAddress = 0xDEADBEEF;
-
-}  // namespace
-
-class ModuleEventSinkImplTest : public testing::Test {
- protected:
-  ModuleEventSinkImplTest()
-      : message_loop_(base::MakeUnique<base::MessageLoop>()),
-        module_database_(
-            base::MakeUnique<ModuleDatabase>(message_loop_->task_runner())) {}
-
-  void CreateModuleSinkImpl() {
-    module_event_sink_impl_ = base::MakeUnique<ModuleEventSinkImpl>(
-        ::GetCurrentProcess(), content::PROCESS_TYPE_BROWSER,
-        module_database_.get());
-  }
-
-  ModuleDatabase* module_database() {
-    return module_event_sink_impl_->module_database_;
-  }
-
-  const ModuleDatabase::ModuleMap& modules() {
-    return module_database_->modules_;
-  }
-
-  const ModuleDatabase::ProcessMap& processes() {
-    return module_database_->processes_;
-  }
-
-  uint32_t process_id() { return module_event_sink_impl_->process_id_; }
-
-  std::unique_ptr<base::MessageLoop> message_loop_;
-  std::unique_ptr<ModuleDatabase> module_database_;
-  std::unique_ptr<ModuleEventSinkImpl> module_event_sink_impl_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ModuleEventSinkImplTest);
-};
-
-TEST_F(ModuleEventSinkImplTest, CallsForwardedAsExpected) {
-  const uintptr_t kValidLoadAddress = reinterpret_cast<uintptr_t>(&__ImageBase);
-
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(0u, processes().size());
-
-  // Construction should immediately fire off a call to OnProcessStarted and
-  // create a process entry in the module database.
-  CreateModuleSinkImpl();
-  EXPECT_EQ(module_database_.get(), module_database());
-  EXPECT_EQ(::GetCurrentProcessId(), process_id());
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-
-  // An invalid load event should not cause a module entry.
-  module_event_sink_impl_->OnModuleEvent(
-      mojom::ModuleEventType::MODULE_ALREADY_LOADED, kInvalidLoadAddress);
-  EXPECT_EQ(0u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-
-  // A valid load event should cause a module entry.
-  module_event_sink_impl_->OnModuleEvent(mojom::ModuleEventType::MODULE_LOADED,
-                                         kValidLoadAddress);
-  EXPECT_EQ(1u, modules().size());
-  EXPECT_EQ(1u, processes().size());
-}
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index a46af89..9bee026 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -121,8 +121,9 @@
 };
 
 // Tests that message passing between extensions and content scripts works.
-#if defined(MEMORY_SANITIZER)
-// https://crbug.com/582185
+#if defined(MEMORY_SANITIZER) || defined(OS_MACOSX)
+// https://crbug.com/582185 - flakily times out on Linux/CrOS MSAN
+// https://crbug.com/681705 - flakily times out on mac_chromium_rel_ng
 #define MAYBE_Messaging DISABLED_Messaging
 #else
 #define MAYBE_Messaging Messaging
diff --git a/chrome/browser/installable/installable_manager.cc b/chrome/browser/installable/installable_manager.cc
index f7df24d..1e06186 100644
--- a/chrome/browser/installable/installable_manager.cc
+++ b/chrome/browser/installable/installable_manager.cc
@@ -9,11 +9,14 @@
 #include "chrome/browser/manifest/manifest_icon_downloader.h"
 #include "chrome/browser/manifest/manifest_icon_selector.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ssl/security_state_tab_helper.h"
+#include "components/security_state/core/security_state.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/service_worker_context.h"
 #include "content/public/browser/storage_partition.h"
+#include "net/base/url_util.h"
 #include "third_party/WebKit/public/platform/WebDisplayMode.h"
 
 namespace {
@@ -95,6 +98,23 @@
 InstallableManager::~InstallableManager() = default;
 
 // static
+bool InstallableManager::IsContentSecure(content::WebContents* web_contents) {
+  if (!web_contents)
+    return false;
+
+  // Whitelist localhost. Check the VisibleURL to match what the
+  // SecurityStateTabHelper looks at.
+  if (net::IsLocalhost(web_contents->GetVisibleURL().HostNoBrackets()))
+    return true;
+
+  security_state::SecurityInfo security_info;
+  SecurityStateTabHelper::FromWebContents(web_contents)
+      ->GetSecurityInfo(&security_info);
+  return security_info.security_level == security_state::SECURE ||
+         security_info.security_level == security_state::EV_SECURE;
+}
+
+// static
 int InstallableManager::GetMinimumIconSizeInPx() {
   return kIconMinimumSizeInPx;
 }
@@ -115,12 +135,13 @@
 
 InstallableManager::IconProperty& InstallableManager::GetIcon(
     const InstallableParams& params) {
-  return icons_[{params.ideal_icon_size_in_px, params.minimum_icon_size_in_px}];
+  return icons_[{params.ideal_primary_icon_size_in_px,
+                 params.minimum_primary_icon_size_in_px}];
 }
 
 bool InstallableManager::IsIconFetched(const InstallableParams& params) const {
-  const auto it = icons_.find(
-      {params.ideal_icon_size_in_px, params.minimum_icon_size_in_px});
+  const auto it = icons_.find({params.ideal_primary_icon_size_in_px,
+                               params.minimum_primary_icon_size_in_px});
   return it != icons_.end() && it->second.fetched;
 }
 
@@ -136,7 +157,7 @@
   if (params.check_installable && installable_->error != NO_ERROR_DETECTED)
     return installable_->error;
 
-  if (params.fetch_valid_icon) {
+  if (params.fetch_valid_primary_icon) {
     IconProperty& icon = GetIcon(params);
     if (icon.error != NO_ERROR_DETECTED)
       return icon.error;
@@ -186,7 +207,7 @@
   //  b. the resource has been fetched/checked.
   return manifest_->fetched &&
          (!params.check_installable || installable_->fetched) &&
-         (!params.fetch_valid_icon || IsIconFetched(params));
+         (!params.fetch_valid_primary_icon || IsIconFetched(params));
 }
 
 void InstallableManager::Reset() {
@@ -217,8 +238,8 @@
       code,
       manifest_url(),
       manifest(),
-      params.fetch_valid_icon ? icon.url : GURL::EmptyGURL(),
-      params.fetch_valid_icon ? icon.icon.get() : nullptr,
+      params.fetch_valid_primary_icon ? icon.url : GURL::EmptyGURL(),
+      params.fetch_valid_primary_icon ? icon.icon.get() : nullptr,
       params.check_installable ? is_installable() : false};
 
   task.second.Run(data);
@@ -253,7 +274,7 @@
     FetchManifest();
   else if (params.check_installable && !installable_->fetched)
     CheckInstallable();
-  else if (params.fetch_valid_icon && !IsIconFetched(params))
+  else if (params.fetch_valid_primary_icon && !IsIconFetched(params))
     CheckAndFetchBestIcon();
   else
     NOTREACHED();
@@ -381,15 +402,15 @@
   icon.fetched = true;
 
   GURL icon_url = ManifestIconSelector::FindBestMatchingIcon(
-      manifest().icons, params.ideal_icon_size_in_px,
-      params.minimum_icon_size_in_px);
+      manifest().icons, params.ideal_primary_icon_size_in_px,
+      params.minimum_primary_icon_size_in_px);
 
   if (icon_url.is_empty()) {
     icon.error = NO_ACCEPTABLE_ICON;
   } else {
     bool can_download_icon = ManifestIconDownloader::Download(
-        GetWebContents(), icon_url, params.ideal_icon_size_in_px,
-        params.minimum_icon_size_in_px,
+        GetWebContents(), icon_url, params.ideal_primary_icon_size_in_px,
+        params.minimum_primary_icon_size_in_px,
         base::Bind(&InstallableManager::OnAppIconFetched,
                    weak_factory_.GetWeakPtr(), icon_url));
     if (can_download_icon)
diff --git a/chrome/browser/installable/installable_manager.h b/chrome/browser/installable/installable_manager.h
index 5dbd659b..3906abe 100644
--- a/chrome/browser/installable/installable_manager.h
+++ b/chrome/browser/installable/installable_manager.h
@@ -25,20 +25,22 @@
 // Data is cached and fetched in the order specified in this struct. A web app
 // manifest will always be fetched first.
 struct InstallableParams {
-  // The ideal icon size to fetch. Used only if |fetch_valid_icon| is true.
-  int ideal_icon_size_in_px = -1;
+  // The ideal primary icon size to fetch. Used only if
+  // |fetch_valid_primary_icon| is true.
+  int ideal_primary_icon_size_in_px = -1;
 
-  // The minimum icon size to fetch. Used only if |fetch_valid_icon| is true.
-  int minimum_icon_size_in_px = -1;
+  // The minimum primary icon size to fetch. Used only if
+  // |fetch_valid_primary_icon| is true.
+  int minimum_primary_icon_size_in_px = -1;
 
   // Check whether the site is installable. That is, it has a manifest valid for
   // a web app and a service worker controlling the manifest start URL and the
   // current URL.
   bool check_installable = false;
 
-  // Check whether there is an icon in the manifest conforming to the icon size
-  // parameters, and that the icon can be fetched and isn't an empty bitmap.
-  bool fetch_valid_icon = false;
+  // Check whether there is a fetchable, non-empty icon in the manifest
+  // conforming to the primary icon size parameters.
+  bool fetch_valid_primary_icon = false;
 };
 
 // This struct is passed to an InstallableCallback when the InstallableManager
@@ -55,14 +57,15 @@
   // Empty if the site has an unparseable manifest.
   const content::Manifest& manifest;
 
-  // Empty if no icon was requested.
-  const GURL& icon_url;
+  // Empty if no primary_icon was requested.
+  const GURL& primary_icon_url;
 
-  // nullptr if the most appropriate icon couldn't be determined or downloaded.
-  // The underlying icon is owned by the InstallableManager; clients must copy
-  // the bitmap if they want to to use it. If fetch_valid_icon was true and an
-  // icon could not be retrieved, the reason will be in error_code.
-  const SkBitmap* icon;
+  // nullptr if the most appropriate primary icon couldn't be determined or
+  // downloaded. The underlying primary icon is owned by the InstallableManager;
+  // clients must copy the bitmap if they want to to use it. If
+  // fetch_valid_primary_icon was true and a primary icon could not be
+  // retrieved, the reason will be in error_code.
+  const SkBitmap* primary_icon;
 
   // true if the site has a service worker and a viable web app manifest. If
   // check_installable was true and the site isn't installable, the reason will
@@ -81,6 +84,10 @@
   explicit InstallableManager(content::WebContents* web_contents);
   ~InstallableManager() override;
 
+  // Returns true if the overall security state of |web_contents| is sufficient
+  // to be considered installable.
+  static bool IsContentSecure(content::WebContents* web_contents);
+
   // Returns the minimum icon size in pixels for a site to be installable.
   // TODO(dominickn): consolidate this concept with minimum_icon_size_in_px
   // across all platforms.
diff --git a/chrome/browser/installable/installable_manager_browsertest.cc b/chrome/browser/installable/installable_manager_browsertest.cc
index 405b1fe..f75d21e 100644
--- a/chrome/browser/installable/installable_manager_browsertest.cc
+++ b/chrome/browser/installable/installable_manager_browsertest.cc
@@ -19,24 +19,24 @@
 InstallableParams GetManifestParams() {
   InstallableParams params;
   params.check_installable = false;
-  params.fetch_valid_icon = false;
+  params.fetch_valid_primary_icon = false;
   return params;
 }
 
 InstallableParams GetWebAppParams() {
   InstallableParams params = GetManifestParams();
-  params.ideal_icon_size_in_px = 144;
-  params.minimum_icon_size_in_px = 144;
+  params.ideal_primary_icon_size_in_px = 144;
+  params.minimum_primary_icon_size_in_px = 144;
   params.check_installable = true;
-  params.fetch_valid_icon = true;
+  params.fetch_valid_primary_icon = true;
   return params;
 }
 
 InstallableParams GetIconParams() {
   InstallableParams params = GetManifestParams();
-  params.ideal_icon_size_in_px = 144;
-  params.minimum_icon_size_in_px = 144;
-  params.fetch_valid_icon = true;
+  params.ideal_primary_icon_size_in_px = 144;
+  params.minimum_primary_icon_size_in_px = 144;
+  params.fetch_valid_primary_icon = true;
   return params;
 }
 
@@ -51,9 +51,9 @@
     error_code_ = data.error_code;
     manifest_url_ = data.manifest_url;
     manifest_ = data.manifest;
-    icon_url_ = data.icon_url;
-    if (data.icon)
-      icon_.reset(new SkBitmap(*data.icon));
+    icon_url_ = data.primary_icon_url;
+    if (data.primary_icon)
+      icon_.reset(new SkBitmap(*data.primary_icon));
     is_installable_ = data.is_installable;
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
   }
@@ -92,9 +92,9 @@
     error_code_ = data.error_code;
     manifest_url_ = data.manifest_url;
     manifest_ = data.manifest;
-    icon_url_ = data.icon_url;
-    if (data.icon)
-      icon_.reset(new SkBitmap(*data.icon));
+    icon_url_ = data.primary_icon_url;
+    if (data.primary_icon)
+      icon_.reset(new SkBitmap(*data.primary_icon));
     is_installable_ = data.is_installable;
 
     manager_->GetData(params_,
@@ -105,8 +105,8 @@
   void OnDidFinishSecondCheck(const InstallableData& data) {
     EXPECT_EQ(error_code_, data.error_code);
     EXPECT_EQ(manifest_url_, data.manifest_url);
-    EXPECT_EQ(icon_url_, data.icon_url);
-    EXPECT_EQ(icon_.get(), data.icon);
+    EXPECT_EQ(icon_url_, data.primary_icon_url);
+    EXPECT_EQ(icon_.get(), data.primary_icon);
     EXPECT_EQ(is_installable_, data.is_installable);
     EXPECT_EQ(manifest_.IsEmpty(), data.manifest.IsEmpty());
     EXPECT_EQ(manifest_.start_url, data.manifest.start_url);
@@ -348,8 +348,8 @@
         new CallbackTester(run_loop.QuitClosure()));
 
     InstallableParams params = GetWebAppParams();
-    params.ideal_icon_size_in_px = 96;
-    params.minimum_icon_size_in_px = 96;
+    params.ideal_primary_icon_size_in_px = 96;
+    params.minimum_primary_icon_size_in_px = 96;
     RunInstallableManager(tester.get(), params);
     run_loop.Run();
 
@@ -572,8 +572,8 @@
     // Dial up the icon size requirements to something that isn't available.
     // This should now fail with NoIconMatchingRequirements.
     InstallableParams params = GetWebAppParams();
-    params.ideal_icon_size_in_px = 2000;
-    params.minimum_icon_size_in_px = 2000;
+    params.ideal_primary_icon_size_in_px = 2000;
+    params.minimum_primary_icon_size_in_px = 2000;
     RunInstallableManager(tester.get(), params);
     run_loop.Run();
 
@@ -594,8 +594,8 @@
 
     // This should fail with NoIconMatchingRequirements.
     InstallableParams params = GetWebAppParams();
-    params.ideal_icon_size_in_px = 2000;
-    params.minimum_icon_size_in_px = 2000;
+    params.ideal_primary_icon_size_in_px = 2000;
+    params.minimum_primary_icon_size_in_px = 2000;
     NavigateAndRunInstallableManager(tester.get(), params,
                                      "/banners/manifest_test_page.html");
     run_loop.Run();
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 477e507..263632c 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -198,6 +198,7 @@
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/policy/device_status_collector.h"
+#include "chrome/browser/chromeos/policy/dm_token_storage.h"
 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
 #include "chrome/browser/chromeos/power/power_prefs.h"
 #include "chrome/browser/chromeos/preferences.h"
@@ -444,6 +445,7 @@
   policy::BrowserPolicyConnectorChromeOS::RegisterPrefs(registry);
   policy::DeviceCloudPolicyManagerChromeOS::RegisterPrefs(registry);
   policy::DeviceStatusCollector::RegisterPrefs(registry);
+  policy::DMTokenStorage::RegisterPrefs(registry);
   policy::PolicyCertServiceFactory::RegisterPrefs(registry);
   quirks::QuirksManager::RegisterPrefs(registry);
 
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index e675552..1659cdc2 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -331,8 +331,10 @@
     setMDMode_: function() {
       if (loadTimeData.getString('newOobeUI') == 'on') {
         $('oobe').setAttribute('md-mode', 'true');
+        $('oobe-shield').setAttribute('md-mode', 'true');
       } else {
         $('oobe').removeAttribute('md-mode');
+        $('oobe-shield').removeAttribute('md-mode');
       }
     },
   };
diff --git a/chrome/browser/resources/chromeos/login/oobe_a11y_option.css b/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
index 87f86c42..280b5b8 100644
--- a/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
+++ b/chrome/browser/resources/chromeos/login/oobe_a11y_option.css
@@ -9,12 +9,15 @@
 }
 
 #elementBox {
+  padding: 0 10px;
   width: inherit;
 }
 
 paper-toggle-button {
+  /* paper-toggle-button has fixed width of 36px. Make it 32. */
+  -webkit-transform: scale(.8888);
   min-height: 20px;
-  min-width: 36px;
+  min-width: 32px;
 }
 
 #titleContainer {
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.css b/chrome/browser/resources/chromeos/login/oobe_dialog.css
index 4f996e8a..5dabdd2 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog.css
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.css
@@ -10,19 +10,10 @@
   min-height: 84px; /* 64 title + 20 subtitle */
 }
 
-:host([welcome-screen]) .oobe-header {
-  height: 64px;
-  min-height: unset;
-}
-
 #footer-container {
   padding: 44px 64px 0 64px;
 }
 
-:host([welcome-screen]) #footer-container {
-  padding-top: 32px;
-}
-
 #oobe-bottom {
   box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.14);
   height: 80px;
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog_parameters.css b/chrome/browser/resources/chromeos/login/oobe_dialog_parameters.css
index 01b2a77..8583252 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog_parameters.css
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog_parameters.css
@@ -20,15 +20,10 @@
   margin: 36px 0 0 0; /* = 64 - font height*/
 }
 
-oobe-dialog[welcome-screen] h1.title {
-  font-size: 38px;
-  margin: 22px 0 0 0; /* = 64 - font height*/
-}
-
 oobe-dialog .subtitle {
   color: rgba(0, 0, 0, 0.87);
   font-size: 13px;
-  margin: 27px 0 0 0; /* = 40 - line-height */
+  margin: 23px 0 0 0; /* = 40 - 4 (adjustment) - line-height */
 }
 
 oobe-dialog .bottom-buttons {
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.css b/chrome/browser/resources/chromeos/login/oobe_eula.css
index 390d952..44b8810 100644
--- a/chrome/browser/resources/chromeos/login/oobe_eula.css
+++ b/chrome/browser/resources/chromeos/login/oobe_eula.css
@@ -11,7 +11,6 @@
 #installationSettings,
 #logging {
   font: 13px Roboto, sans-serif;
-  margin: 0 20px;
 }
 
 #installationSettings {
@@ -24,17 +23,14 @@
 }
 
 #usageStats {
-  --paper-checkbox-size: 16px;
+  --paper-checkbox-size: 20px;
+  --paper-checkbox-checked-color: rgb(66, 133, 244); /* #4285f4 */
   /* End padding must be greater than --paper-checkbox-label-spacing */
   -webkit-padding-end: 16px;
   max-width: 550px;
   padding-bottom: 20px;
 }
 
-#accept-button-text {
-  text-transform: uppercase;
-}
-
 .bottom-buttons {
   padding: 0 6px; /* = 8px - 2px back button border */
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.css b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.css
index ab3d4cf..196a220 100644
--- a/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.css
+++ b/chrome/browser/resources/chromeos/login/oobe_i18n_dropdown.css
@@ -11,3 +11,7 @@
 #container {
   height: 100%;
 }
+
+#container select  {
+ width: 100%;
+}
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.css b/chrome/browser/resources/chromeos/login/oobe_welcome.css
index 2315acd..45b61aac 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.css
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.css
@@ -6,7 +6,7 @@
 #languageScreen .language-selection-entry {
   border-top: 1px solid lightgrey;
   height: 44px;
-  padding: 0 20px;
+  padding: 0 10px;
 }
 
 #languageScreen .language-selection-entry:last-of-type {
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.css b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.css
index ca71ad5..cc90904 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.css
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome_dialog.css
@@ -14,12 +14,13 @@
   color: rgba(0, 0, 0, 0.87);
   font-family: Roboto, sans-serif;
   font-size: 38px;
-  font-weight: normal;
+  font-weight: 300; /* roboto-light */
   margin: 120px 0 30px 0;
 }
 
 #welcomeIllustration {
   height: 300px;
+  padding-top: 14px;
   width: 390px;
 }
 
diff --git a/chrome/browser/resources/chromeos/login/screen_container.html b/chrome/browser/resources/chromeos/login/screen_container.html
index 87d5781..f258aa4 100644
--- a/chrome/browser/resources/chromeos/login/screen_container.html
+++ b/chrome/browser/resources/chromeos/login/screen_container.html
@@ -3,6 +3,7 @@
 <include src="api_keys_notice.html">
 <div id="scroll-container">
   <div id="outer-container" class="down">
+    <div id="oobe-shield"></div>
     <div id="oobe" class="faded">
       <div id="inner-container" class="down">
         <div id="step-logo" hidden>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index de0ea0a..3b8501e 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -614,7 +614,7 @@
     "//ui/strings",
     "//ui/surface",
     "//ui/web_dialogs",
-    "//v8",
+    "//v8:v8_version",
   ]
   allow_circular_includes_from = []
 
@@ -1511,8 +1511,6 @@
       "views/subtle_notification_view.h",
       "views/sync/bubble_sync_promo_view.cc",
       "views/sync/bubble_sync_promo_view.h",
-      "views/sync/profile_signin_confirmation_dialog_views.cc",
-      "views/sync/profile_signin_confirmation_dialog_views.h",
       "views/task_manager_view.cc",
       "views/task_manager_view.h",
       "views/website_settings/chosen_object_row.cc",
@@ -1564,6 +1562,8 @@
         "views/screen_capture_notification_ui_views.cc",
         "views/sync/one_click_signin_dialog_view.cc",
         "views/sync/one_click_signin_dialog_view.h",
+        "views/sync/profile_signin_confirmation_dialog_views.cc",
+        "views/sync/profile_signin_confirmation_dialog_views.h",
       ]
     }
 
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.h b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.h
index a596b90..d23724f 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.h
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.h
@@ -38,17 +38,16 @@
       content::WebContents* web_contents,
       Profile* profile,
       const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate,
+      ui::ProfileSigninConfirmationDelegate* delegate,
       bool offer_profile_creation);
   virtual ~ProfileSigninConfirmationDialogCocoa();
 
   // Shows the dialog if needed.
-  static void Show(
-      Browser* browser,
-      content::WebContents* web_contents,
-      Profile* profile,
-      const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate);
+  static void Show(Browser* browser,
+                   content::WebContents* web_contents,
+                   Profile* profile,
+                   const std::string& username,
+                   ui::ProfileSigninConfirmationDelegate* delegate);
 
   // Closes the dialog, which deletes itself.
   void Close();
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.mm b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.mm
index eab52ff..dbd031b 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.mm
@@ -16,15 +16,19 @@
 namespace {
 
 // static
-void ShowDialog(Browser* browser,
-                content::WebContents* web_contents,
-                Profile* profile,
-                const std::string& username,
-                std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate,
-                bool offer_profile_creation) {
+void ShowDialog(
+    Browser* browser,
+    content::WebContents* web_contents,
+    Profile* profile,
+    const std::string& username,
+    ui::ProfileSigninConfirmationDelegate* delegate,
+    bool offer_profile_creation) {
   // The dialog owns itself.
-  new ProfileSigninConfirmationDialogCocoa(browser, web_contents, profile,
-                                           username, std::move(delegate),
+  new ProfileSigninConfirmationDialogCocoa(browser,
+                                           web_contents,
+                                           profile,
+                                           username,
+                                           delegate,
                                            offer_profile_creation);
 }
 
@@ -35,18 +39,19 @@
     content::WebContents* web_contents,
     Profile* profile,
     const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate,
+    ui::ProfileSigninConfirmationDelegate* delegate,
     bool offer_profile_creation) {
   // Setup the dialog view controller.
   const base::Closure& closeDialogCallback =
       base::Bind(&ProfileSigninConfirmationDialogCocoa::Close,
                  base::Unretained(this));
-  controller_.reset([[ProfileSigninConfirmationViewController alloc]
-           initWithBrowser:browser
-                  username:username
-                  delegate:std::move(delegate)
-       closeDialogCallback:closeDialogCallback
-      offerProfileCreation:offer_profile_creation]);
+  controller_.reset(
+      [[ProfileSigninConfirmationViewController alloc]
+          initWithBrowser:browser
+                 username:username
+                 delegate:delegate
+      closeDialogCallback:closeDialogCallback
+     offerProfileCreation:offer_profile_creation]);
 
   // Setup the constrained window that will show the view.
   base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc]
@@ -66,10 +71,10 @@
     content::WebContents* web_contents,
     Profile* profile,
     const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) {
+    ui::ProfileSigninConfirmationDelegate* delegate) {
   ui::CheckShouldPromptForNewProfile(
       profile, base::Bind(ShowDialog, browser, web_contents, profile, username,
-                          base::Passed(std::move(delegate))));
+                          delegate));
 }
 
 void ProfileSigninConfirmationDialogCocoa::Close() {
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.h b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.h
index 8e4a35c..2a70b08 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.h
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_UI_COCOA_PROFILES_PROFILE_SIGNIN_CONFIRMATION_VIEW_CONTROLLER_
 
 #import <Cocoa/Cocoa.h>
-#include <memory>
 #include <string>
 
 #include "base/callback.h"
@@ -34,7 +33,7 @@
   bool offerProfileCreation_;
 
   // Dialog button callbacks.
-  std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate_;
+  ui::ProfileSigninConfirmationDelegate* delegate_;
   base::Closure closeDialogCallback_;
 
   // UI elements.
@@ -49,12 +48,10 @@
 }
 
 - (id)initWithBrowser:(Browser*)browser
-                username:(const std::string&)username
-                delegate:
-                    (std::unique_ptr<ui::ProfileSigninConfirmationDelegate>)
-                        delegate
-     closeDialogCallback:(const base::Closure&)closeDialogCallback
-    offerProfileCreation:(bool)offer;
+             username:(const std::string&)username
+             delegate:(ui::ProfileSigninConfirmationDelegate*)delegate
+  closeDialogCallback:(const base::Closure&)closeDialogCallback
+ offerProfileCreation:(bool)offer;
 - (IBAction)cancel:(id)sender;
 - (IBAction)ok:(id)sender;
 - (IBAction)close:(id)sender;
@@ -62,4 +59,12 @@
 
 @end
 
+@interface ProfileSigninConfirmationViewController (TestingAPI)
+
+@property(readonly, nonatomic) ui::ProfileSigninConfirmationDelegate* delegate;
+@property(readonly, nonatomic) NSButton* createProfileButton;
+@property(readonly, nonatomic) NSTextView* explanationField;
+
+@end
+
 #endif  // CHROME_BROWSER_UI_COCOA_PROFILES_PROFILE_SIGNIN_CONFIRMATION_VIEW_CONTROLLER_
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
index 28f0873..5a7480f 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
@@ -142,16 +142,14 @@
 @implementation ProfileSigninConfirmationViewController
 
 - (id)initWithBrowser:(Browser*)browser
-                username:(const std::string&)username
-                delegate:
-                    (std::unique_ptr<ui::ProfileSigninConfirmationDelegate>)
-                        delegate
-     closeDialogCallback:(const base::Closure&)closeDialogCallback
-    offerProfileCreation:(bool)offer {
+             username:(const std::string&)username
+             delegate:(ui::ProfileSigninConfirmationDelegate*)delegate
+  closeDialogCallback:(const base::Closure&)closeDialogCallback
+ offerProfileCreation:(bool)offer {
   if ((self = [super initWithNibName:nil bundle:nil])) {
     browser_ = browser;
     username_ = username;
-    delegate_ = std::move(delegate);
+    delegate_ = delegate;
     closeDialogCallback_ = closeDialogCallback;
     offerProfileCreation_ = offer;
   }
@@ -378,7 +376,7 @@
 - (IBAction)cancel:(id)sender {
   if (delegate_) {
     delegate_->OnCancelSignin();
-    delegate_ = nullptr;
+    delegate_ = NULL;
     closeDialogCallback_.Run();
   }
 }
@@ -386,7 +384,7 @@
 - (IBAction)ok:(id)sender {
   if (delegate_) {
     delegate_->OnContinueSignin();
-    delegate_ = nullptr;
+    delegate_ = NULL;
     closeDialogCallback_.Run();
   }
 }
@@ -394,7 +392,7 @@
 - (IBAction)close:(id)sender {
   if (delegate_) {
     delegate_->OnCancelSignin();
-    delegate_ = nullptr;
+    delegate_ = NULL;
   }
   closeDialogCallback_.Run();
 }
@@ -402,7 +400,7 @@
 - (IBAction)createProfile:(id)sender {
   if (delegate_) {
     delegate_->OnSigninWithNewProfile();
-    delegate_ = nullptr;
+    delegate_ = NULL;
     closeDialogCallback_.Run();
   }
 }
@@ -442,3 +440,19 @@
 }
 
 @end
+
+@implementation ProfileSigninConfirmationViewController (TestingAPI)
+
+- (ui::ProfileSigninConfirmationDelegate*)delegate {
+  return delegate_;
+}
+
+- (NSButton*)createProfileButton {
+  return createProfileButton_.get();
+}
+
+- (NSTextView*)explanationField {
+  return explanationField_.get();
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm
index 4311f676..6380427 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm
@@ -18,32 +18,10 @@
 #import "testing/gtest_mac.h"
 #include "ui/base/l10n/l10n_util.h"
 
-@interface ProfileSigninConfirmationViewController (TestingAPI)
-
-@property(readonly, nonatomic) ui::ProfileSigninConfirmationDelegate* delegate;
-@property(readonly, nonatomic) NSButton* createProfileButton;
-@property(readonly, nonatomic) NSTextView* explanationField;
-
-@end
-
-@implementation ProfileSigninConfirmationViewController (TestingAPI)
-
-- (ui::ProfileSigninConfirmationDelegate*)delegate {
-  return delegate_.get();
-}
-
-- (NSButton*)createProfileButton {
-  return createProfileButton_.get();
-}
-
-- (NSTextView*)explanationField {
-  return explanationField_.get();
-}
-
-@end
-
 class ProfileSigninConfirmationViewControllerTest
-    : public InProcessBrowserTest {
+  : public InProcessBrowserTest,
+    public ui::ProfileSigninConfirmationDelegate {
+
  public:
   ProfileSigninConfirmationViewControllerTest()
     : window_(nil),
@@ -66,11 +44,11 @@
         &ProfileSigninConfirmationViewControllerTest::OnClose,
         base::Unretained(this));
     controller_.reset([[ProfileSigninConfirmationViewController alloc]
-             initWithBrowser:browser()
-                    username:username()
-                    delegate:base::MakeUnique<TestSigninDelegate>(this)
-         closeDialogCallback:close
-        offerProfileCreation:offerProfileCreation]);
+                        initWithBrowser:browser()
+                               username:username()
+                               delegate:this
+                    closeDialogCallback:close
+                   offerProfileCreation:offerProfileCreation]);
     [[window_ contentView] addSubview:[controller_ view]];
     [window_ makeKeyAndOrderFront:NSApp];
     ASSERT_TRUE([window_ isVisible]);
@@ -85,6 +63,10 @@
         IDS_ENTERPRISE_SIGNIN_PROFILE_LINK_LEARN_MORE);
   }
 
+  // ui::ProfileSigninConfirmationDelegate:
+  void OnContinueSignin() override { continued_ = true; }
+  void OnCancelSignin() override { cancelled_ = true; }
+  void OnSigninWithNewProfile() override { created_ = true; }
   void OnClose() { closed_ = true; }
 
   // The window containing the dialog.
@@ -100,23 +82,6 @@
   bool closed_;
 
  private:
-  class TestSigninDelegate : public ui::ProfileSigninConfirmationDelegate {
-   public:
-    explicit TestSigninDelegate(
-        ProfileSigninConfirmationViewControllerTest* client)
-        : client_(client) {}
-
-    // ui::ProfileSigninConfirmationDelegate:
-    void OnContinueSignin() override { client_->continued_ = true; }
-    void OnCancelSignin() override { client_->cancelled_ = true; }
-    void OnSigninWithNewProfile() override { client_->created_ = true; }
-
-   private:
-    ProfileSigninConfirmationViewControllerTest* client_;
-
-    DISALLOW_COPY_AND_ASSIGN(TestSigninDelegate);
-  };
-
   DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationViewControllerTest);
 };
 
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h
index 4d81b16..1eb2bd5 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h
+++ b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.h
@@ -24,7 +24,7 @@
       Browser* browser,
       Profile* profile,
       const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) override;
+      ui::ProfileSigninConfirmationDelegate* delegate) override;
   void ShowManagePasswordsBubble(bool user_action) override;
   void HideManagePasswordsBubble() override;
   base::WeakPtr<ValidationMessageBubble> ShowValidationMessage(
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm
index a66b2ee..bc20ecf6 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm
+++ b/chrome/browser/ui/cocoa/tab_dialogs_cocoa.mm
@@ -11,7 +11,6 @@
 #import "chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_dialog_cocoa.h"
 #include "chrome/browser/ui/cocoa/tab_dialogs_views_mac.h"
 #import "chrome/browser/ui/cocoa/validation_message_bubble_cocoa.h"
-#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/material_design/material_design_controller.h"
 
@@ -65,9 +64,9 @@
     Browser* browser,
     Profile* profile,
     const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) {
-  ProfileSigninConfirmationDialogCocoa::Show(browser, web_contents_, profile,
-                                             username, std::move(delegate));
+    ui::ProfileSigninConfirmationDelegate* delegate) {
+  ProfileSigninConfirmationDialogCocoa::Show(
+      browser, web_contents_, profile, username, delegate);
 }
 
 void TabDialogsCocoa::ShowManagePasswordsBubble(bool user_action) {
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h
index 980201b..622777c 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h
+++ b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h
@@ -15,11 +15,6 @@
 
   // TabDialogs:
   void ShowCollectedCookies() override;
-  void ShowProfileSigninConfirmation(
-      Browser* browser,
-      Profile* profile,
-      const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TabDialogsViewsMac);
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm
index d71c1f2..6187e48 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/cocoa/tab_dialogs_views_mac.h"
 
 #include "chrome/browser/ui/views/collected_cookies_views.h"
-#include "chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h"
 
 TabDialogsViewsMac::TabDialogsViewsMac(content::WebContents* contents)
     : TabDialogsCocoa(contents) {}
@@ -16,12 +15,3 @@
   // Deletes itself on close.
   new CollectedCookiesViews(web_contents());
 }
-
-void TabDialogsViewsMac::ShowProfileSigninConfirmation(
-    Browser* browser,
-    Profile* profile,
-    const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) {
-  ProfileSigninConfirmationDialogViews::ShowDialog(browser, profile, username,
-                                                   std::move(delegate));
-}
diff --git a/chrome/browser/ui/collected_cookies_browsertest.cc b/chrome/browser/ui/collected_cookies_browsertest.cc
index e946733..0316265 100644
--- a/chrome/browser/ui/collected_cookies_browsertest.cc
+++ b/chrome/browser/ui/collected_cookies_browsertest.cc
@@ -22,7 +22,7 @@
  public:
   CollectedCookiesTest() {}
 
-  // DialogBrowserTest:
+  // TestDialogInterface:
   void ShowDialog(const std::string& name) override {
     ASSERT_TRUE(embedded_test_server()->Start());
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index 672c4c3..75b3376 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -242,11 +242,11 @@
 
   content::RecordAction(
       base::UserMetricsAction("Signin_Show_EnterpriseAccountPrompt"));
-  TabDialogs::FromWebContents(web_contents)
-      ->ShowProfileSigninConfirmation(browser_, profile_,
-                                      signin->GetUsernameForAuthInProgress(),
-                                      base::MakeUnique<SigninDialogDelegate>(
-                                          weak_pointer_factory_.GetWeakPtr()));
+  TabDialogs::FromWebContents(web_contents)->ShowProfileSigninConfirmation(
+      browser_,
+      profile_,
+      signin->GetUsernameForAuthInProgress(),
+      new SigninDialogDelegate(weak_pointer_factory_.GetWeakPtr()));
 }
 
 void OneClickSigninSyncStarter::LoadPolicyWithCachedCredentials() {
diff --git a/chrome/browser/ui/tab_dialogs.h b/chrome/browser/ui/tab_dialogs.h
index 41ac3c1..ca3fec18b 100644
--- a/chrome/browser/ui/tab_dialogs.h
+++ b/chrome/browser/ui/tab_dialogs.h
@@ -59,7 +59,7 @@
       Browser* browser,
       Profile* profile,
       const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) = 0;
+      ui::ProfileSigninConfirmationDelegate* delegate) = 0;
 
   // Shows or hides the ManagePasswords bubble.
   // Pass true for |user_action| if this is a user initiated action.
diff --git a/chrome/browser/ui/test/test_browser_dialog.cc b/chrome/browser/ui/test/test_browser_dialog.cc
index 18099e7..5faa2fa 100644
--- a/chrome/browser/ui/test/test_browser_dialog.cc
+++ b/chrome/browser/ui/test/test_browser_dialog.cc
@@ -88,11 +88,11 @@
 
   gfx::NativeView parent = platform_util::GetViewForWindow(DialogParent());
   views::Widget::Widgets widgets_before;
-  views::Widget::GetAllOwnedWidgets(parent, &widgets_before);
+  views::Widget::GetAllChildWidgets(parent, &widgets_before);
 
   ShowDialog(NameFromTestCase());
   views::Widget::Widgets widgets_after;
-  views::Widget::GetAllOwnedWidgets(parent, &widgets_after);
+  views::Widget::GetAllChildWidgets(parent, &widgets_after);
 
   auto added = base::STLSetDifference<std::vector<views::Widget*>>(
       widgets_after, widgets_before);
diff --git a/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc b/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc
index 5ce2fb3a..a4e267e 100644
--- a/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc
+++ b/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/ime_driver/ime_driver_mus.h"
 
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/service_manager_connection.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -38,15 +39,18 @@
   ime_registrar->RegisterDriver(std::move(ime_driver_ptr));
 }
 
-void IMEDriver::StartSession(
-    int32_t session_id,
-    ui::mojom::TextInputClientPtr client,
-    ui::mojom::InputMethodRequest input_method_request) {
+void IMEDriver::StartSession(int32_t session_id,
+                             ui::mojom::StartSessionDetailsPtr details) {
 #if defined(OS_CHROMEOS)
+  std::unique_ptr<RemoteTextInputClient> remote_client =
+      base::MakeUnique<RemoteTextInputClient>(
+          std::move(details->client), details->text_input_type,
+          details->text_input_mode, details->text_direction,
+          details->text_input_flags, details->caret_bounds);
   input_method_bindings_[session_id] =
       base::MakeUnique<mojo::Binding<ui::mojom::InputMethod>>(
-          new InputMethodBridge(std::move(client)),
-          std::move(input_method_request));
+          new InputMethodBridge(std::move(remote_client)),
+          std::move(details->input_method_request));
 #else
   input_method_bindings_[session_id] =
       base::MakeUnique<mojo::Binding<ui::mojom::InputMethod>>(
diff --git a/chrome/browser/ui/views/ime_driver/ime_driver_mus.h b/chrome/browser/ui/views/ime_driver/ime_driver_mus.h
index e81d34d..315c7b9c 100644
--- a/chrome/browser/ui/views/ime_driver/ime_driver_mus.h
+++ b/chrome/browser/ui/views/ime_driver/ime_driver_mus.h
@@ -23,10 +23,8 @@
 
  private:
   // ui::mojom::IMEDriver:
-  void StartSession(
-      int32_t session_id,
-      ui::mojom::TextInputClientPtr client,
-      ui::mojom::InputMethodRequest input_method_request) override;
+  void StartSession(int32_t session_id,
+                    ui::mojom::StartSessionDetailsPtr details) override;
   void CancelSession(int32_t session_id) override;
 
   std::map<int32_t, std::unique_ptr<mojo::Binding<ui::mojom::InputMethod>>>
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
index edf5fb9..a74e7bf 100644
--- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
@@ -7,8 +7,9 @@
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
 
-InputMethodBridge::InputMethodBridge(ui::mojom::TextInputClientPtr client)
-    : client_(base::MakeUnique<RemoteTextInputClient>(std::move(client))),
+InputMethodBridge::InputMethodBridge(
+    std::unique_ptr<RemoteTextInputClient> client)
+    : client_(std::move(client)),
       input_method_chromeos_(
           base::MakeUnique<ui::InputMethodChromeOS>(nullptr)) {
   input_method_chromeos_->SetFocusedTextInputClient(client_.get());
@@ -18,10 +19,12 @@
 
 void InputMethodBridge::OnTextInputTypeChanged(
     ui::TextInputType text_input_type) {
+  client_->SetTextInputType(text_input_type);
   input_method_chromeos_->OnTextInputTypeChanged(client_.get());
 }
 
 void InputMethodBridge::OnCaretBoundsChanged(const gfx::Rect& caret_bounds) {
+  client_->SetCaretBounds(caret_bounds);
   input_method_chromeos_->OnCaretBoundsChanged(client_.get());
 }
 
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
index 4b83a725..8ca254d 100644
--- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_
 #define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_
 
+#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
 #include "services/ui/public/interfaces/ime/ime.mojom.h"
 #include "ui/base/ime/input_method_chromeos.h"
 
@@ -12,7 +13,7 @@
 // forwards the received events to an instance of ui::InputMethodChromeOS.
 class InputMethodBridge : public ui::mojom::InputMethod {
  public:
-  explicit InputMethodBridge(ui::mojom::TextInputClientPtr client);
+  explicit InputMethodBridge(std::unique_ptr<RemoteTextInputClient> client);
   ~InputMethodBridge() override;
 
   // ui::mojom::InputMethod:
@@ -23,7 +24,7 @@
   void CancelComposition() override;
 
  private:
-  std::unique_ptr<ui::TextInputClient> client_;
+  std::unique_ptr<RemoteTextInputClient> client_;
   std::unique_ptr<ui::InputMethodChromeOS> input_method_chromeos_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodBridge);
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc
index 00435e5..6d921d7 100644
--- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc
@@ -106,7 +106,11 @@
 
     ui::mojom::TextInputClientPtr client_ptr;
     client_ = base::MakeUnique<TestTextInputClient>(MakeRequest(&client_ptr));
-    input_method_ = base::MakeUnique<InputMethodBridge>(std::move(client_ptr));
+    input_method_ = base::MakeUnique<InputMethodBridge>(
+        base::MakeUnique<RemoteTextInputClient>(
+            std::move(client_ptr), ui::TEXT_INPUT_TYPE_TEXT,
+            ui::TEXT_INPUT_MODE_DEFAULT, base::i18n::LEFT_TO_RIGHT, 0,
+            gfx::Rect()));
   }
 
   bool ProcessKeyEvent(std::unique_ptr<ui::Event> event) {
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
index b7705ad0..93b7ff2 100644
--- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
@@ -12,11 +12,30 @@
 #include "base/strings/utf_string_conversions.h"
 
 RemoteTextInputClient::RemoteTextInputClient(
-    ui::mojom::TextInputClientPtr remote_client)
-    : remote_client_(std::move(remote_client)) {}
+    ui::mojom::TextInputClientPtr remote_client,
+    ui::TextInputType text_input_type,
+    ui::TextInputMode text_input_mode,
+    base::i18n::TextDirection text_direction,
+    int text_input_flags,
+    gfx::Rect caret_bounds)
+    : remote_client_(std::move(remote_client)),
+      text_input_type_(text_input_type),
+      text_input_mode_(text_input_mode),
+      text_direction_(text_direction),
+      text_input_flags_(text_input_flags),
+      caret_bounds_(caret_bounds) {}
 
 RemoteTextInputClient::~RemoteTextInputClient() {}
 
+void RemoteTextInputClient::SetTextInputType(
+    ui::TextInputType text_input_type) {
+  text_input_type_ = text_input_type;
+}
+
+void RemoteTextInputClient::SetCaretBounds(const gfx::Rect& caret_bounds) {
+  caret_bounds_ = caret_bounds;
+}
+
 void RemoteTextInputClient::SetCompositionText(
     const ui::CompositionText& composition) {
   remote_client_->SetCompositionText(composition);
@@ -39,27 +58,19 @@
 }
 
 ui::TextInputType RemoteTextInputClient::GetTextInputType() const {
-  // TODO(moshayedi): crbug.com/631527.
-  NOTIMPLEMENTED();
-  return ui::TEXT_INPUT_TYPE_TEXT;
+  return text_input_type_;
 }
 
 ui::TextInputMode RemoteTextInputClient::GetTextInputMode() const {
-  // TODO(moshayedi): crbug.com/631527.
-  NOTIMPLEMENTED();
-  return ui::TEXT_INPUT_MODE_DEFAULT;
+  return text_input_mode_;
 }
 
 base::i18n::TextDirection RemoteTextInputClient::GetTextDirection() const {
-  // TODO(moshayedi): crbug.com/631527.
-  NOTIMPLEMENTED();
-  return base::i18n::UNKNOWN_DIRECTION;
+  return text_direction_;
 }
 
 int RemoteTextInputClient::GetTextInputFlags() const {
-  // TODO(moshayedi): crbug.com/631527.
-  NOTIMPLEMENTED();
-  return 0;
+  return text_input_flags_;
 }
 
 bool RemoteTextInputClient::CanComposeInline() const {
@@ -70,9 +81,7 @@
 }
 
 gfx::Rect RemoteTextInputClient::GetCaretBounds() const {
-  // TODO(moshayedi): crbug.com/631527.
-  NOTIMPLEMENTED();
-  return gfx::Rect();
+  return caret_bounds_;
 }
 
 bool RemoteTextInputClient::GetCompositionCharacterBounds(
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
index 056be5f1..18ef7be44 100644
--- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
@@ -13,9 +13,17 @@
 // ui::InputMethod::SetFocusedTextInputClient().
 class RemoteTextInputClient : public ui::TextInputClient {
  public:
-  explicit RemoteTextInputClient(ui::mojom::TextInputClientPtr remote_client);
+  RemoteTextInputClient(ui::mojom::TextInputClientPtr remote_client,
+                        ui::TextInputType text_input_type,
+                        ui::TextInputMode text_input_mode,
+                        base::i18n::TextDirection text_direction,
+                        int text_input_flags,
+                        gfx::Rect caret_bounds);
   ~RemoteTextInputClient() override;
 
+  void SetTextInputType(ui::TextInputType text_input_type);
+  void SetCaretBounds(const gfx::Rect& caret_bounds);
+
  private:
   // ui::TextInputClient:
   void SetCompositionText(const ui::CompositionText& composition) override;
@@ -48,6 +56,11 @@
   void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
 
   ui::mojom::TextInputClientPtr remote_client_;
+  ui::TextInputType text_input_type_;
+  ui::TextInputMode text_input_mode_;
+  base::i18n::TextDirection text_direction_;
+  int text_input_flags_;
+  gfx::Rect caret_bounds_;
 
   DISALLOW_COPY_AND_ASSIGN(RemoteTextInputClient);
 };
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
index 774b60956..1ee37be 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
@@ -21,7 +22,6 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/range/range.h"
@@ -36,17 +36,13 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_client_view.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
-#endif
-
 ProfileSigninConfirmationDialogViews::ProfileSigninConfirmationDialogViews(
     Browser* browser,
     const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate)
+    ui::ProfileSigninConfirmationDelegate* delegate)
     : browser_(browser),
       username_(username),
-      delegate_(std::move(delegate)),
+      delegate_(delegate),
       prompt_for_new_profile_(true) {}
 
 ProfileSigninConfirmationDialogViews::~ProfileSigninConfirmationDialogViews() {}
@@ -56,8 +52,7 @@
     Browser* browser,
     Profile* profile,
     const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) {
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+    ui::ProfileSigninConfirmationDelegate* delegate) {
   // Hides the new avatar bubble if it is currently shown. The new avatar bubble
   // should be automatically closed when it loses focus. However on windows the
   // profile signin confirmation dialog is not modal yet thus it does not take
@@ -66,11 +61,10 @@
   // TODO(guohui): removes the workaround once the profile confirmation dialog
   // is fixed.
   ProfileChooserView::Hide();
-#endif
 
   ProfileSigninConfirmationDialogViews* dialog =
-      new ProfileSigninConfirmationDialogViews(browser, username,
-                                               std::move(delegate));
+      new ProfileSigninConfirmationDialogViews(
+          browser, username, delegate);
   ui::CheckShouldPromptForNewProfile(
       profile,
       // This callback is guaranteed to be invoked, and once it is, the dialog
@@ -123,7 +117,7 @@
       delegate_->OnSigninWithNewProfile();
     else
       delegate_->OnContinueSignin();
-    delegate_ = nullptr;
+    delegate_ = NULL;
   }
   return true;
 }
@@ -131,7 +125,7 @@
 bool ProfileSigninConfirmationDialogViews::Cancel() {
   if (delegate_) {
     delegate_->OnCancelSignin();
-    delegate_ = nullptr;
+    delegate_ = NULL;
   }
   return true;
 }
@@ -252,7 +246,7 @@
   DCHECK(prompt_for_new_profile_);
   if (delegate_) {
     delegate_->OnContinueSignin();
-    delegate_ = nullptr;
+    delegate_ = NULL;
   }
   GetWidget()->Close();
 }
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
index a466abd..ffa5f579 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
@@ -5,8 +5,6 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_SYNC_PROFILE_SIGNIN_CONFIRMATION_DIALOG_VIEWS_H_
 #define CHROME_BROWSER_UI_VIEWS_SYNC_PROFILE_SIGNIN_CONFIRMATION_DIALOG_VIEWS_H_
 
-#include <memory>
-
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
@@ -25,17 +23,16 @@
                                              public views::ButtonListener {
  public:
   // Create and show the dialog, which owns itself.
-  static void ShowDialog(
-      Browser* browser,
-      Profile* profile,
-      const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate);
+  static void ShowDialog(Browser* browser,
+                         Profile* profile,
+                         const std::string& username,
+                         ui::ProfileSigninConfirmationDelegate* delegate);
 
  private:
   ProfileSigninConfirmationDialogViews(
       Browser* browser,
       const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate);
+      ui::ProfileSigninConfirmationDelegate* delegate);
   ~ProfileSigninConfirmationDialogViews() override;
 
   // views::DialogDelegateView:
@@ -72,7 +69,7 @@
   std::string username_;
 
   // Dialog button handler.
-  std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate_;
+  ui::ProfileSigninConfirmationDelegate* delegate_;
 
   // Whether the user should be prompted to create a new profile.
   bool prompt_for_new_profile_;
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views_browsertest.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views_browsertest.cc
deleted file mode 100644
index 0837f0e6..0000000
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views_browsertest.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h"
-
-#include "base/command_line.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
-#include "chrome/browser/ui/tab_dialogs.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/test/test_browser_dialog.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "ui/base/ui_base_switches.h"
-
-namespace {
-
-// Test delegate passed to the confirmation dialog to report back the result.
-class TestSigninDialogDelegate : public ui::ProfileSigninConfirmationDelegate {
- public:
-  TestSigninDialogDelegate() {}
-  virtual ~TestSigninDialogDelegate() {}
-
-  void OnCancelSignin() override {}
-  void OnContinueSignin() override {}
-  void OnSigninWithNewProfile() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestSigninDialogDelegate);
-};
-
-}  // namespace
-
-class ProfileSigninConfirmationDialogTest : public DialogBrowserTest {
- public:
-  ProfileSigninConfirmationDialogTest() {}
-
-  // content::BrowserTestBase:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(switches::kExtendMdToSecondaryUi);
-  }
-
-  // DialogBrowserTest:
-  void ShowDialog(const std::string& name) override {
-    Profile* profile = browser()->profile();
-
-    // Add a bookmark to ensure CheckShouldPromptForNewProfile() returns true.
-    bookmarks::BookmarkModel* bookmarks =
-        BookmarkModelFactory::GetForBrowserContext(profile);
-    bookmarks->AddURL(bookmarks->bookmark_bar_node(), 0,
-                      base::ASCIIToUTF16("title"),
-                      GURL("http://www.example.com"));
-
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-    TabDialogs::FromWebContents(web_contents)
-        ->ShowProfileSigninConfirmation(
-            browser(), profile, "username@example.com",
-            base::MakeUnique<TestSigninDialogDelegate>());
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationDialogTest);
-};
-
-// Test that calls ShowDialog("default"). Interactive when run via
-// browser_tests --gtest_filter=BrowserDialogTest.Invoke --interactive
-// --dialog=ProfileSigninConfirmationDialogTest.InvokeDialog_default
-IN_PROC_BROWSER_TEST_F(ProfileSigninConfirmationDialogTest,
-                       InvokeDialog_default) {
-  RunDialog();
-}
diff --git a/chrome/browser/ui/views/tab_dialogs_views.cc b/chrome/browser/ui/views/tab_dialogs_views.cc
index fa36944f..46177c1 100644
--- a/chrome/browser/ui/views/tab_dialogs_views.cc
+++ b/chrome/browser/ui/views/tab_dialogs_views.cc
@@ -53,10 +53,10 @@
     Browser* browser,
     Profile* profile,
     const std::string& username,
-    std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) {
+    ui::ProfileSigninConfirmationDelegate* delegate) {
 #if !defined(OS_CHROMEOS)
-  ProfileSigninConfirmationDialogViews::ShowDialog(browser, profile, username,
-                                                   std::move(delegate));
+  ProfileSigninConfirmationDialogViews::ShowDialog(
+      browser, profile, username, delegate);
 #else
   NOTREACHED();
 #endif
diff --git a/chrome/browser/ui/views/tab_dialogs_views.h b/chrome/browser/ui/views/tab_dialogs_views.h
index c1bc6fc..83f4e473 100644
--- a/chrome/browser/ui/views/tab_dialogs_views.h
+++ b/chrome/browser/ui/views/tab_dialogs_views.h
@@ -24,7 +24,7 @@
       Browser* browser,
       Profile* profile,
       const std::string& username,
-      std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) override;
+      ui::ProfileSigninConfirmationDelegate* delegate) override;
   void ShowManagePasswordsBubble(bool user_action) override;
   void HideManagePasswordsBubble() override;
   base::WeakPtr<ValidationMessageBubble> ShowValidationMessage(
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
index 2049d78..e747aca9 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -357,6 +357,9 @@
       ShowError(IDS_ENTERPRISE_ENROLLMENT_ERROR_ACTIVE_DIRECTORY_POLICY_FETCH,
                 false);
       return;
+    case policy::EnrollmentStatus::DM_TOKEN_STORE_FAILED:
+      ShowError(IDS_ENTERPRISE_ENROLLMENT_ERROR_STORE_DM_TOKEN_FAILED, false);
+      return;
   }
   NOTREACHED();
 }
diff --git a/chrome/browser/ui/webui/help/help_handler.cc b/chrome/browser/ui/webui/help/help_handler.cc
index d4ffe8ab..9a7197a 100644
--- a/chrome/browser/ui/webui/help/help_handler.cc
+++ b/chrome/browser/ui/webui/help/help_handler.cc
@@ -50,7 +50,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "v8/include/v8.h"
+#include "v8/include/v8-version-string.h"
 
 #if defined(OS_CHROMEOS)
 #include "base/files/file_util_proxy.h"
@@ -376,7 +376,7 @@
   localized_strings->SetString("productTOS", tos);
 
   localized_strings->SetString("jsEngine", "V8");
-  localized_strings->SetString("jsEngineVersion", v8::V8::GetVersion());
+  localized_strings->SetString("jsEngineVersion", V8_VERSION_STRING);
 
   localized_strings->SetString("userAgentInfo", GetUserAgent());
 
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index 7c3ed61..1962582 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -50,7 +50,7 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/common/user_agent.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "v8/include/v8.h"
+#include "v8/include/v8-version-string.h"
 
 #if defined(OS_CHROMEOS)
 #include "base/files/file_util_proxy.h"
@@ -319,7 +319,7 @@
   html_source->AddString("aboutCommandLine", command_line);
 
   html_source->AddString("aboutUserAgent", GetUserAgent());
-  html_source->AddString("aboutJsEngineVersion", v8::V8::GetVersion());
+  html_source->AddString("aboutJsEngineVersion", V8_VERSION_STRING);
   html_source->AddString("aboutBlinkVersion", content::GetWebKitVersion());
 #endif
 
diff --git a/chrome/browser/ui/webui/signin/OWNERS b/chrome/browser/ui/webui/signin/OWNERS
index 568e3fad..4344a30 100644
--- a/chrome/browser/ui/webui/signin/OWNERS
+++ b/chrome/browser/ui/webui/signin/OWNERS
@@ -1,4 +1,5 @@
 achuith@chromium.org
 anthonyvd@chromium.org
+msarda@chromium.org
 rogerta@chromium.org
 xiyuan@chromium.org
diff --git a/chrome/browser/ui/webui/version_ui.cc b/chrome/browser/ui/webui/version_ui.cc
index 2b0f6e8c..c3fbfcc4 100644
--- a/chrome/browser/ui/webui/version_ui.cc
+++ b/chrome/browser/ui/webui/version_ui.cc
@@ -27,7 +27,7 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/common/user_agent.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "v8/include/v8.h"
+#include "v8/include/v8-version-string.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
@@ -61,7 +61,7 @@
   html_source->AddLocalizedString(version_ui::kPlatform, IDS_PLATFORM_LABEL);
   html_source->AddString(version_ui::kOSType, version_info::GetOSType());
   html_source->AddString(version_ui::kJSEngine, "V8");
-  html_source->AddString(version_ui::kJSVersion, v8::V8::GetVersion());
+  html_source->AddString(version_ui::kJSVersion, V8_VERSION_STRING);
 
 #if defined(OS_ANDROID)
   html_source->AddString(version_ui::kOSVersion,
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index e34b618..5e1da61 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -677,7 +677,8 @@
 
 mojom("mojo_bindings") {
   sources = [
-    "conflicts/module_event_sink_win.mojom",
+    "conflicts/module_database_win.mojom",
+    "conflicts/module_event_win.mojom",
     "field_trial_recorder.mojom",
     "net_benchmarking.mojom",
     "network_diagnostics.mojom",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 62a3c14..6df346e7 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -237,7 +237,7 @@
 
 // Enables or disables flash component updates on Chrome OS.
 const base::Feature kCrosCompUpdates{"CrosCompUpdates",
-                                     base::FEATURE_DISABLED_BY_DEFAULT};
+                                     base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // defined(OS_CHROMEOS)
 
 }  // namespace features
diff --git a/chrome/common/conflicts/module_database_win.mojom b/chrome/common/conflicts/module_database_win.mojom
new file mode 100644
index 0000000..2bce402
--- /dev/null
+++ b/chrome/common/conflicts/module_database_win.mojom
@@ -0,0 +1,14 @@
+// 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.
+
+module mojom;
+
+// This brings in a definition for ModuleEvent.
+import "chrome/common/conflicts/module_event_win.mojom";
+
+// Interface for a remote module database.
+interface ModuleDatabase {
+  // Notifies the module database of a module event in a remote process.
+  OnModuleEvent(uint32 process_id, ModuleEvent module_event);
+};
diff --git a/chrome/common/conflicts/module_event_sink_win.mojom b/chrome/common/conflicts/module_event_sink_win.mojom
deleted file mode 100644
index 3d2fa936..0000000
--- a/chrome/common/conflicts/module_event_sink_win.mojom
+++ /dev/null
@@ -1,23 +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.
-
-module mojom;
-
-// The types of module events that can occur.
-enum ModuleEventType {
-  // A module was already loaded, but its presence is being observed.
-  MODULE_ALREADY_LOADED,
-  // A module is in the process of being loaded.
-  MODULE_LOADED,
-  // A module is in the process of being unloaded.
-  MODULE_UNLOADED,
-};
-
-// Interface for a remote consumer of module events.
-interface ModuleEventSink {
-  // Notifies the module database of a module event in a remote process. The
-  // module is identified only by its load address, which is sufficient for
-  // any process to safely look up the module.
-  OnModuleEvent(ModuleEventType event_type, uint64 load_address);
-};
diff --git a/chrome/common/conflicts/module_event_win.mojom b/chrome/common/conflicts/module_event_win.mojom
new file mode 100644
index 0000000..d280156
--- /dev/null
+++ b/chrome/common/conflicts/module_event_win.mojom
@@ -0,0 +1,27 @@
+// 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.
+
+module mojom;
+
+// The types of module events that can occur.
+enum ModuleEventType {
+  // A module was already loaded, but its presence is being observed.
+  MODULE_ALREADY_LOADED,
+  // A module is in the process of being loaded.
+  MODULE_LOADED,
+  // A module is in the process of being unloaded.
+  MODULE_UNLOADED,
+};
+
+// A notification about a module being loaded or unloaded.
+struct ModuleEvent {
+  // The type of event.
+  ModuleEventType event_type;
+  // The full path to the module being loaded or unloaded.
+  string module_path;
+  // The load address of the module.
+  uint64 load_address;
+  // The size of the module in memory, in bytes.
+  uint32 size;
+};
diff --git a/chrome/common/conflicts/module_watcher_win.cc b/chrome/common/conflicts/module_watcher_win.cc
index fca97a3..424fd13 100644
--- a/chrome/common/conflicts/module_watcher_win.cc
+++ b/chrome/common/conflicts/module_watcher_win.cc
@@ -9,11 +9,9 @@
 #include <winternl.h>  // For UNICODE_STRING.
 
 #include <string>
-#include <utility>
 
 #include "base/lazy_instance.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "base/win/scoped_handle.h"
@@ -98,19 +96,22 @@
 constexpr char kLdrRegisterDllNotification[] = "LdrRegisterDllNotification";
 constexpr char kLdrUnregisterDllNotification[] = "LdrUnregisterDllNotification";
 
-// Helper function for converting a UNICODE_STRING to a FilePath.
-base::FilePath ToFilePath(const UNICODE_STRING* str) {
-  return base::FilePath(
-      base::StringPiece16(str->Buffer, str->Length / sizeof(wchar_t)));
+// Helper function for converting a UNICODE_STRING to a UTF8 std::string.
+std::string ToString(const UNICODE_STRING* str) {
+  std::string s;
+  base::WideToUTF8(str->Buffer, str->Length / sizeof(wchar_t), &s);
+  return s;
 }
 
 template <typename NotificationDataType>
 void OnModuleEvent(mojom::ModuleEventType event_type,
                    const NotificationDataType& notification_data,
                    const ModuleWatcher::OnModuleEventCallback& callback) {
-  ModuleWatcher::ModuleEvent event(
-      event_type, ToFilePath(notification_data.FullDllName),
-      notification_data.DllBase, notification_data.SizeOfImage);
+  mojom::ModuleEvent event;
+  event.event_type = event_type;
+  event.module_path = ToString(notification_data.FullDllName);
+  event.load_address = reinterpret_cast<uintptr_t>(notification_data.DllBase);
+  event.size = notification_data.SizeOfImage;
   callback.Run(event);
 }
 
@@ -118,14 +119,14 @@
 
 // static
 std::unique_ptr<ModuleWatcher> ModuleWatcher::Create(
-    OnModuleEventCallback callback) {
+    const OnModuleEventCallback& callback) {
   // If a ModuleWatcher already exists then bail out.
   base::AutoLock lock(g_module_watcher_lock.Get());
   if (g_module_watcher_instance)
     return nullptr;
 
   // This thread acquired the right to create a ModuleWatcher, so do so.
-  g_module_watcher_instance = new ModuleWatcher(std::move(callback));
+  g_module_watcher_instance = new ModuleWatcher(callback);
   return base::WrapUnique(g_module_watcher_instance);
 }
 
@@ -173,11 +174,15 @@
 
   // Walk the module list.
   MODULEENTRY32 module = {sizeof(module)};
+  std::string path;
   for (BOOL result = ::Module32First(snap.Get(), &module); result != FALSE;
        result = ::Module32Next(snap.Get(), &module)) {
-    ModuleEvent event(mojom::ModuleEventType::MODULE_ALREADY_LOADED,
-                      base::FilePath(module.szExePath), module.modBaseAddr,
-                      module.modBaseSize);
+    base::WideToUTF8(module.szExePath, ::wcslen(module.szExePath), &path);
+    mojom::ModuleEvent event;
+    event.event_type = mojom::ModuleEventType::MODULE_ALREADY_LOADED;
+    event.module_path = path;
+    event.load_address = reinterpret_cast<uintptr_t>(module.modBaseAddr);
+    event.size = module.modBaseSize;
     callback_.Run(event);
   }
 
@@ -220,8 +225,8 @@
   }
 }
 
-ModuleWatcher::ModuleWatcher(OnModuleEventCallback callback)
-    : callback_(std::move(callback)) {
+ModuleWatcher::ModuleWatcher(const OnModuleEventCallback& callback)
+    : callback_(callback) {
   RegisterDllNotificationCallback();
   EnumerateAlreadyLoadedModules();
 }
diff --git a/chrome/common/conflicts/module_watcher_win.h b/chrome/common/conflicts/module_watcher_win.h
index a7c00d1..b2255d0 100644
--- a/chrome/common/conflicts/module_watcher_win.h
+++ b/chrome/common/conflicts/module_watcher_win.h
@@ -8,8 +8,7 @@
 #include <memory>
 
 #include "base/callback.h"
-#include "base/files/file_path.h"
-#include "chrome/common/conflicts/module_event_sink_win.mojom.h"
+#include "chrome/common/conflicts/module_event_win.mojom.h"
 
 class ModuleWatcherTest;
 
@@ -23,37 +22,14 @@
 // created.
 class ModuleWatcher {
  public:
-  // Houses information about a module load/unload event, and some module
-  // metadata.
-  struct ModuleEvent {
-    ModuleEvent() = default;
-    ModuleEvent(const ModuleEvent& other) = default;
-    ModuleEvent(mojom::ModuleEventType event_type,
-                const base::FilePath& module_path,
-                void* module_load_address,
-                size_t module_size)
-        : event_type(event_type),
-          module_path(module_path),
-          module_load_address(module_load_address),
-          module_size(module_size) {}
-
-    // The type of module event.
-    mojom::ModuleEventType event_type;
-    // The full path to the module on disk.
-    base::FilePath module_path;
-    // The load address of the module.
-    void* module_load_address;
-    // The size of the module in memory.
-    size_t module_size;
-  };
-
   // The type of callback that will be invoked for each module event. This is
   // invoked by the loader and potentially on any thread. The loader lock is not
   // held but the execution of this callback blocks the module from being bound.
   // Keep the amount of work performed here to an absolute minimum. Note that
   // it is possible for this callback to be invoked after the destruction of the
   // watcher, but very unlikely.
-  using OnModuleEventCallback = base::Callback<void(const ModuleEvent& event)>;
+  using OnModuleEventCallback =
+      base::Callback<void(const mojom::ModuleEvent& event)>;
 
   // Creates and starts a watcher. This enumerates all loaded modules
   // synchronously on the current thread during construction, and provides
@@ -68,7 +44,8 @@
   //
   // Only a single instance of a watcher may exist at any moment. This will
   // return nullptr when trying to create a second watcher.
-  static std::unique_ptr<ModuleWatcher> Create(OnModuleEventCallback callback);
+  static std::unique_ptr<ModuleWatcher> Create(
+      const OnModuleEventCallback& callback);
 
   // This can be called on any thread. After destruction the |callback|
   // provided to the constructor will no longer be invoked with module events.
@@ -106,7 +83,7 @@
 
  private:
   // Private to enforce Singleton semantics. See Create above.
-  explicit ModuleWatcher(OnModuleEventCallback callback);
+  explicit ModuleWatcher(const OnModuleEventCallback& callback);
 
   // The current callback. Can end up being invoked on any thread.
   OnModuleEventCallback callback_;
diff --git a/chrome/common/conflicts/module_watcher_win_unittest.cc b/chrome/common/conflicts/module_watcher_win_unittest.cc
index dd698874..02bea081 100644
--- a/chrome/common/conflicts/module_watcher_win_unittest.cc
+++ b/chrome/common/conflicts/module_watcher_win_unittest.cc
@@ -10,7 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 class ModuleWatcherTest : public testing::Test {
- protected:
+ public:
   ModuleWatcherTest()
       : module_(nullptr),
         module_event_count_(0),
@@ -18,7 +18,7 @@
         module_loaded_event_count_(0),
         module_unloaded_event_count_(0) {}
 
-  void OnModuleEvent(const ModuleWatcher::ModuleEvent& event) {
+  void OnModuleEvent(const mojom::ModuleEvent& event) {
     ++module_event_count_;
     switch (event.event_type) {
       case mojom::ModuleEventType::MODULE_ALREADY_LOADED:
@@ -63,6 +63,7 @@
 
   // Holds a handle to a loaded module.
   HMODULE module_;
+
   // Total number of module events seen.
   int module_event_count_;
   // Total number of MODULE_ALREADY_LOADED events seen.
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index a510af5..51b573d 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1831,6 +1831,10 @@
 // Whether the user may exit enrollment.
 const char kDeviceEnrollmentCanExit[] = "enrollment.can_exit";
 
+// DM token fetched from the DM server during enrollment. Stored for Active
+// Directory devices only.
+const char kDeviceDMToken[] = "device_dm_token";
+
 // How many times HID detection OOBE dialog was shown.
 const char kTimesHIDDialogShown[] = "HIDDialog.shown_how_many_times";
 
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index f0b812c9..08f7784 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -653,6 +653,7 @@
 extern const char kDeviceEnrollmentRequisition[];
 extern const char kDeviceEnrollmentAutoStart[];
 extern const char kDeviceEnrollmentCanExit[];
+extern const char kDeviceDMToken[];
 extern const char kTimesHIDDialogShown[];
 extern const char kUsersLRUInputMethod[];
 extern const char kEchoCheckedOffers[];
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc
index 6098916..633e8e0a 100644
--- a/chrome/install_static/install_util.cc
+++ b/chrome/install_static/install_util.cc
@@ -35,6 +35,8 @@
 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT";
 
 const wchar_t kCrashpadHandler[] = L"crashpad-handler";
+const wchar_t kFallbackHandler[] = L"fallback-handler";
+
 const wchar_t kProcessType[] = L"type";
 const wchar_t kUserDataDirSwitch[] = L"user-data-dir";
 const wchar_t kUtilityProcess[] = L"utility";
diff --git a/chrome/install_static/install_util.h b/chrome/install_static/install_util.h
index 17c11b7f..7283967 100644
--- a/chrome/install_static/install_util.h
+++ b/chrome/install_static/install_util.h
@@ -43,6 +43,7 @@
 // https://crbug.com/604923
 // Unify these constants with those defined in content_switches.h.
 extern const wchar_t kCrashpadHandler[];
+extern const wchar_t kFallbackHandler[];
 extern const wchar_t kProcessType[];
 extern const wchar_t kUserDataDirSwitch[];
 extern const wchar_t kUtilityProcess[];
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn
index 65df57c..84be262 100644
--- a/chrome/installer/mini_installer/BUILD.gn
+++ b/chrome/installer/mini_installer/BUILD.gn
@@ -239,12 +239,15 @@
     ]
 
     ldflags = [
-      "/ENTRY:MainEntryPoint",
       "/FIXED:NO",
       "/ignore:4199",
       "/NXCOMPAT",
     ]
 
+    if (!is_asan) {
+      ldflags += [ "/ENTRY:MainEntryPoint" ]
+    }
+
     libs = [ "setupapi.lib" ]
 
     deps = [
diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc
index 7ca6e9f1..be29092fd 100644
--- a/chrome/installer/mini_installer/mini_installer.cc
+++ b/chrome/installer/mini_installer/mini_installer.cc
@@ -15,7 +15,7 @@
 //   BufferSecurityCheck="false" compiler: /GS-
 //   EntryPointSymbol="MainEntryPoint" linker: /ENTRY
 //   IgnoreAllDefaultLibraries="true" linker: /NODEFAULTLIB
-//   OptimizeForWindows98="1"  liker: /OPT:NOWIN98
+//   OptimizeForWindows98="1" linker: /OPT:NOWIN98
 //   linker: /SAFESEH:NO
 
 // have the linker merge the sections, saving us ~500 bytes.
@@ -895,6 +895,19 @@
   ::ExitProcess(result.exit_code);
 }
 
+#if defined(ADDRESS_SANITIZER)
+// Executables instrumented with ASAN need CRT functions. We do not use
+// the /ENTRY switch for ASAN instrumented executable and a "main" function
+// is required.
+int WINAPI WinMain(HINSTANCE hInstance,
+                   HINSTANCE hPrevInstance,
+                   LPSTR lpCmdLine,
+                   int nCmdShow) {
+  MainEntryPoint();
+  return 0;
+}
+#endif
+
 // VC Express editions don't come with the memset CRT obj file and linking to
 // the obj files between versions becomes a bit problematic. Therefore,
 // simply implement memset.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d5d16ed..cfaf9d82 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2119,7 +2119,6 @@
         "../browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc",
         "../browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc",
         "../browser/ui/views/select_file_dialog_extension_browsertest.cc",
-        "../browser/ui/views/sync/profile_signin_confirmation_dialog_views_browsertest.cc",
       ]
       deps += [ "//ui/views" ]
       if (!is_chromeos && (!is_mac || mac_views_browser)) {
@@ -2350,7 +2349,6 @@
         "../browser/service_process/service_process_control_browsertest.cc",
 
         # inline login UI is disabled on chromeos
-        "../browser/ui/views/sync/profile_signin_confirmation_dialog_views_browsertest.cc",
         "../browser/ui/webui/signin/inline_login_ui_browsertest.cc",
 
         # chromeos does not use the desktop user manager
@@ -3096,8 +3094,6 @@
     "../browser/component_updater/subresource_filter_component_installer_unittest.cc",
     "../browser/component_updater/supervised_user_whitelist_installer_unittest.cc",
     "../browser/component_updater/sw_reporter_installer_win_unittest.cc",
-    "../browser/conflicts/module_database_win_unittest.cc",
-    "../browser/conflicts/module_event_sink_impl_win_unittest.cc",
     "../browser/content_settings/content_settings_default_provider_unittest.cc",
     "../browser/content_settings/content_settings_mock_observer.cc",
     "../browser/content_settings/content_settings_mock_observer.h",
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 61182fe..d2a931c 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -645,7 +645,7 @@
   Refresh();
 }
 
-void PersonalDataManager::UpdateServerCardBillingAddress(
+void PersonalDataManager::UpdateServerCardMetadata(
     const CreditCard& credit_card) {
   DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
 
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index 239c88d6..165862f 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -152,9 +152,9 @@
   // status can be changed. Looks up the card by server ID.
   virtual void UpdateServerCreditCard(const CreditCard& credit_card);
 
-  // Updates the billing address for the server |credit_card|. Looks up the card
-  // by GUID.
-  void UpdateServerCardBillingAddress(const CreditCard& credit_card);
+  // Updates the use stats and billing address id for the server |credit_card|.
+  // Looks up the card by server_id.
+  void UpdateServerCardMetadata(const CreditCard& credit_card);
 
   // Resets the card for |guid| to the masked state.
   void ResetFullServerCard(const std::string& guid);
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn
index 23255030..0cf0c6ca 100644
--- a/components/crash/content/app/BUILD.gn
+++ b/components/crash/content/app/BUILD.gn
@@ -70,12 +70,15 @@
       "fallback_crash_handler_launcher_win.h",
       "fallback_crash_handler_win.cc",
       "fallback_crash_handler_win.h",
+      "fallback_crash_handling_win.cc",
+      "fallback_crash_handling_win.h",
       "run_as_crashpad_handler_win.cc",
       "run_as_crashpad_handler_win.h",
     ]
 
     deps = [
       "//base",
+      "//chrome/install_static:install_static_util",
       "//third_party/crashpad/crashpad/client",
       "//third_party/crashpad/crashpad/handler:handler_lib",
       "//third_party/crashpad/crashpad/minidump",
@@ -221,6 +224,7 @@
     "crash_keys_win_unittest.cc",
     "fallback_crash_handler_launcher_win_unittest.cc",
     "fallback_crash_handler_win_unittest.cc",
+    "fallback_crash_handling_win_unittest.cc",
   ]
   deps = [
     ":lib",
diff --git a/components/crash/content/app/fallback_crash_handler_launcher_win.cc b/components/crash/content/app/fallback_crash_handler_launcher_win.cc
index 1fa0603..45c8c83 100644
--- a/components/crash/content/app/fallback_crash_handler_launcher_win.cc
+++ b/components/crash/content/app/fallback_crash_handler_launcher_win.cc
@@ -28,8 +28,8 @@
     const base::CommandLine& program,
     const base::FilePath& crashpad_database) {
   // Open an inheritable handle to self. This will be inherited to the handler.
-  const DWORD kAccessMask =
-      PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE;
+  const DWORD kAccessMask = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ |
+                            PROCESS_DUP_HANDLE | PROCESS_TERMINATE;
   self_process_handle_.Set(
       OpenProcess(kAccessMask, TRUE, ::GetCurrentProcessId()));
   if (!self_process_handle_.IsValid())
diff --git a/components/crash/content/app/fallback_crash_handler_win.cc b/components/crash/content/app/fallback_crash_handler_win.cc
index 13b89d4..c17849429 100644
--- a/components/crash/content/app/fallback_crash_handler_win.cc
+++ b/components/crash/content/app/fallback_crash_handler_win.cc
@@ -161,23 +161,30 @@
   // Write the key/value pairs and collect their locations.
   std::vector<crashpad::MinidumpSimpleStringDictionaryEntry> entries;
   for (const auto& kv : crash_keys) {
+    // The key of a key/value pair should never be empty.
+    DCHECK(!kv.first.empty());
+
     crashpad::MinidumpSimpleStringDictionaryEntry entry = {0};
 
-    entry.key = next_available_byte;
-    uint32_t key_len = base::saturated_cast<uint32_t>(kv.first.size());
-    if (!WriteAndAdvance(&key_len, sizeof(key_len), &next_available_byte) ||
-        !WriteAndAdvance(&kv.first[0], key_len, &next_available_byte)) {
-      return false;
-    }
+    // Skip this key/value if the value is empty.
+    if (!kv.second.empty()) {
+      entry.key = next_available_byte;
+      uint32_t key_len = base::saturated_cast<uint32_t>(kv.first.size());
+      if (!WriteAndAdvance(&key_len, sizeof(key_len), &next_available_byte) ||
+          !WriteAndAdvance(&kv.first[0], key_len, &next_available_byte)) {
+        return false;
+      }
 
-    entry.value = next_available_byte;
-    uint32_t value_len = base::saturated_cast<uint32_t>(kv.second.size());
-    if (!WriteAndAdvance(&value_len, sizeof(value_len), &next_available_byte) ||
-        !WriteAndAdvance(&kv.second[0], value_len, &next_available_byte)) {
-      return false;
-    }
+      entry.value = next_available_byte;
+      uint32_t value_len = base::saturated_cast<uint32_t>(kv.second.size());
+      if (!WriteAndAdvance(&value_len, sizeof(value_len),
+                           &next_available_byte) ||
+          !WriteAndAdvance(&kv.second[0], value_len, &next_available_byte)) {
+        return false;
+      }
 
-    entries.push_back(entry);
+      entries.push_back(entry);
+    }
   }
 
   // Write the dictionary array itself - note the array is count-prefixed.
@@ -340,10 +347,11 @@
     return false;
 
   // Retrieve the thread id argument.
-  unsigned thread_id = 0;
+  unsigned int thread_id = 0;
   if (!base::StringToUint(cmd_line.GetSwitchValueASCII("thread"), &thread_id)) {
     return false;
   }
+  thread_id_ = thread_id;
 
   // Retrieve the "exception-pointers" argument.
   uint64_t uint_exc_ptrs = 0;
diff --git a/components/crash/content/app/fallback_crash_handler_win.h b/components/crash/content/app/fallback_crash_handler_win.h
index d9e96bb..579bcb5 100644
--- a/components/crash/content/app/fallback_crash_handler_win.h
+++ b/components/crash/content/app/fallback_crash_handler_win.h
@@ -45,6 +45,8 @@
                          const std::string& channel,
                          const std::string& process_type);
 
+  const base::Process& process() const { return process_; }
+
  private:
   base::Process process_;
   base::PlatformThreadId thread_id_;
diff --git a/components/crash/content/app/fallback_crash_handling_win.cc b/components/crash/content/app/fallback_crash_handling_win.cc
new file mode 100644
index 0000000..e83be627
--- /dev/null
+++ b/components/crash/content/app/fallback_crash_handling_win.cc
@@ -0,0 +1,119 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/crash/content/app/fallback_crash_handling_win.h"
+
+#include <memory>
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "components/crash/content/app/crash_switches.h"
+#include "components/crash/content/app/fallback_crash_handler_launcher_win.h"
+#include "components/crash/content/app/fallback_crash_handler_win.h"
+
+namespace crash_reporter {
+
+namespace switches {
+const char kFallbackCrashHandler[] = "fallback-handler";
+const char kPrefetchArgument[] = "/prefetch:7";
+}
+
+const uint32_t kFallbackCrashTerminationCode = 0xFFFF8001;
+
+namespace {
+
+std::unique_ptr<FallbackCrashHandlerLauncher> g_fallback_crash_handler_launcher;
+
+LONG WINAPI FallbackUnhandledExceptionFilter(EXCEPTION_POINTERS* exc_ptrs) {
+  if (!g_fallback_crash_handler_launcher)
+    return EXCEPTION_CONTINUE_SEARCH;
+
+  return g_fallback_crash_handler_launcher->LaunchAndWaitForHandler(exc_ptrs);
+}
+
+}  // namespace
+
+bool SetupFallbackCrashHandling(const base::CommandLine& command_line) {
+  DCHECK(!g_fallback_crash_handler_launcher);
+
+  // Run the same program.
+  base::CommandLine base_command_line(command_line.GetProgram());
+  base_command_line.AppendSwitchASCII("type", switches::kFallbackCrashHandler);
+
+  // This is to support testing under gtest.
+  if (command_line.HasSwitch(::switches::kTestChildProcess)) {
+    base_command_line.AppendSwitchASCII(
+        ::switches::kTestChildProcess,
+        command_line.GetSwitchValueASCII(::switches::kTestChildProcess));
+  }
+
+  // All Chrome processes need a prefetch argument.
+  base_command_line.AppendArg(switches::kPrefetchArgument);
+
+  // Get the database path.
+  base::FilePath database_path = command_line.GetSwitchValuePath("database");
+  if (database_path.empty()) {
+    NOTREACHED();
+    return false;
+  }
+
+  std::unique_ptr<FallbackCrashHandlerLauncher> fallback_launcher(
+      new FallbackCrashHandlerLauncher());
+
+  if (!fallback_launcher->Initialize(base_command_line, database_path)) {
+    NOTREACHED();
+    return false;
+  }
+
+  // This is necessary because chrome_elf stubs out the
+  // SetUnhandledExceptionFilter in the IAT of chrome.exe.
+  typedef PTOP_LEVEL_EXCEPTION_FILTER(WINAPI *
+                                      SetUnhandledExceptionFilterFunction)(
+      PTOP_LEVEL_EXCEPTION_FILTER filter);
+  HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
+  if (!kernel32)
+    return false;
+
+  SetUnhandledExceptionFilterFunction set_unhandled_exception_filter =
+      reinterpret_cast<SetUnhandledExceptionFilterFunction>(
+          GetProcAddress(kernel32, "SetUnhandledExceptionFilter"));
+  if (!set_unhandled_exception_filter)
+    return false;
+
+  // Success, pass ownership to the global.
+  g_fallback_crash_handler_launcher = std::move(fallback_launcher);
+
+  set_unhandled_exception_filter(&FallbackUnhandledExceptionFilter);
+
+  return true;
+}
+
+int RunAsFallbackCrashHandler(const base::CommandLine& command_line,
+                              std::string product_name,
+                              std::string version,
+                              std::string channel_name) {
+  FallbackCrashHandler fallback_handler;
+
+  if (!fallback_handler.ParseCommandLine(command_line)) {
+    // TODO(siggi): Figure out how to UMA from this process, if need be.
+    return 1;
+  }
+
+  if (!fallback_handler.GenerateCrashDump(
+          product_name, version, channel_name,
+          crash_reporter::switches::kCrashpadHandler)) {
+    // TODO(siggi): Figure out how to UMA from this process, if need be.
+    return 2;
+  }
+
+  if (!fallback_handler.process().Terminate(kFallbackCrashTerminationCode,
+                                            false)) {
+    return 3;
+  }
+
+  return 0;
+}
+
+}  // namespace crash_reporter
diff --git a/components/crash/content/app/fallback_crash_handling_win.h b/components/crash/content/app/fallback_crash_handling_win.h
new file mode 100644
index 0000000..ebf5d9f
--- /dev/null
+++ b/components/crash/content/app/fallback_crash_handling_win.h
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRASH_CONTENT_APP_FALLBACK_CRASH_HANDLING_WIN_H_
+#define COMPONENTS_CRASH_CONTENT_APP_FALLBACK_CRASH_HANDLING_WIN_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "base/command_line.h"
+
+namespace crash_reporter {
+
+namespace switches {
+extern const char kFallbackCrashHandler[];
+// The fallback handler uses the same prefetch ID as the Crashpad handler.
+extern const char kPrefetchArgument[];
+}
+
+// A somewhat unique exit code for the crashed process. This is mostly
+// for testing, as there won't likely be anyone around to record the exit
+// code of the Crashpad handler.
+extern const uint32_t kFallbackCrashTerminationCode;
+
+// Sets up fallback crash handling for this process.
+// Note that this installs an unhandled exception filter, and requires
+// that the executable call the "RunAsFallbackCrashHandler" function, when
+// it's passed a --type switch with the value |kFallbackCrashHandlerType|.
+bool SetupFallbackCrashHandling(const base::CommandLine& command_line);
+
+// Runs the fallback crash handler process, to handle a crash in a process
+// that's previously called SetupFallbackCrashHandling.
+// The |product_name|, |version| and |channel_name| parameters will be used
+// as properties of the crash for the purposes of upload.
+int RunAsFallbackCrashHandler(const base::CommandLine& command_line,
+                              std::string product_name,
+                              std::string version,
+                              std::string channel_name);
+
+}  // namespace crash_reporter
+
+#endif  // COMPONENTS_CRASH_CONTENT_APP_FALLBACK_CRASH_HANDLING_WIN_H_
diff --git a/components/crash/content/app/fallback_crash_handling_win_unittest.cc b/components/crash/content/app/fallback_crash_handling_win_unittest.cc
new file mode 100644
index 0000000..7df6b20
--- /dev/null
+++ b/components/crash/content/app/fallback_crash_handling_win_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/crash/content/app/fallback_crash_handling_win.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/test/multiprocess_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
+#include "third_party/crashpad/crashpad/client/crash_report_database.h"
+
+namespace crash_reporter {
+
+namespace {
+
+const DWORD kExceptionCode = 0xCAFEBABE;
+
+// This main function runs in two modes, first as a faux-crashpad handler,
+// and then with --type=fallback-handler to handle the crash in the first
+// instance.
+MULTIPROCESS_TEST_MAIN(FallbackCrashHandlingWinRunHandler) {
+  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+  if (cmd_line->GetSwitchValueASCII("type") ==
+      switches::kFallbackCrashHandler) {
+    return RunAsFallbackCrashHandler(*cmd_line,
+                                     "FallbackCrashHandlingWinRunHandler",
+                                     "1.2.3.4", "FakeChannel");
+  }
+
+  CHECK(SetupFallbackCrashHandling(*cmd_line));
+
+  // Provoke a crash with a well-defined exception code.
+  // The process shouldn't terminate with this exception code.
+  RaiseException(kExceptionCode, 0, 0, nullptr);
+
+  // This process should never return from the exception.
+  CHECK(false) << "Unexpected return from RaiseException";
+
+  // Should never get here.
+  return 0;
+}
+
+class FallbackCrashHandlingTest : public base::MultiProcessTest {
+ public:
+  void SetUp() override { ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); }
+
+ protected:
+  base::ScopedTempDir database_dir_;
+};
+
+}  // namespace
+
+TEST_F(FallbackCrashHandlingTest, SetupAndRunAsFallbackCrashHandler) {
+  // Launch a subprocess to test the fallback handling implementation.
+  base::CommandLine cmd_line = base::GetMultiProcessTestChildBaseCommandLine();
+  cmd_line.AppendSwitchPath("database", database_dir_.GetPath());
+
+  base::LaunchOptions options;
+  options.start_hidden = true;
+  base::Process test_child = base::SpawnMultiProcessTestChild(
+      "FallbackCrashHandlingWinRunHandler", cmd_line, options);
+
+  ASSERT_TRUE(test_child.IsValid());
+  int exit_code = -1;
+  ASSERT_TRUE(test_child.WaitForExit(&exit_code));
+  ASSERT_EQ(kFallbackCrashTerminationCode, static_cast<uint32_t>(exit_code));
+
+  // Validate that the database contains one valid crash dump.
+  std::unique_ptr<crashpad::CrashReportDatabase> database =
+      crashpad::CrashReportDatabase::InitializeWithoutCreating(
+          database_dir_.GetPath());
+
+  std::vector<crashpad::CrashReportDatabase::Report> reports;
+  ASSERT_EQ(crashpad::CrashReportDatabase::kNoError,
+            database->GetPendingReports(&reports));
+
+  EXPECT_EQ(1U, reports.size());
+}
+
+}  // namespace crash_reporter
diff --git a/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc b/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc
index e900dab2..147cfdb 100644
--- a/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc
+++ b/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc
@@ -99,7 +99,7 @@
     const ImageFetchedCallback& callback) {
   ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
   base::StringPiece raw_data = resource_bundle.GetRawDataResourceForScale(
-      IDR_PHYSICAL_WEB_LOGO, resource_bundle.GetMaxScaleFactor());
+      IDR_PHYSICAL_WEB_LOGO_WITH_PADDING, resource_bundle.GetMaxScaleFactor());
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(callback,
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc
index 625994a..dd9b2a9 100644
--- a/components/password_manager/core/browser/password_reuse_detector.cc
+++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -4,6 +4,8 @@
 
 #include "components/password_manager/core/browser/password_reuse_detector.h"
 
+#include <algorithm>
+
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/password_reuse_detector_consumer.h"
 #include "components/password_manager/core/browser/psl_matching_helper.h"
@@ -15,6 +17,22 @@
 // It does not make sense to consider short strings for password reuse, since it
 // is quite likely that they are parts of common words.
 constexpr size_t kMinPasswordLengthToCheck = 8;
+
+// Returns true iff |suffix_candidate| is a suffix of |str|.
+bool IsSuffix(const base::string16& str,
+              const base::string16& suffix_candidate) {
+  if (str.size() < suffix_candidate.size())
+    return false;
+  return std::equal(suffix_candidate.rbegin(), suffix_candidate.rend(),
+                    str.rbegin());
+}
+
+}  // namespace
+
+bool ReverseStringLess::operator()(const base::string16& lhs,
+                                   const base::string16& rhs) const {
+  return std::lexicographical_compare(lhs.rbegin(), lhs.rend(), rhs.rbegin(),
+                                      rhs.rend());
 }
 
 PasswordReuseDetector::PasswordReuseDetector() {}
@@ -40,40 +58,62 @@
     const base::string16& input,
     const std::string& domain,
     PasswordReuseDetectorConsumer* consumer) {
-  // TODO(crbug.com/668155): Optimize password look-up.
   DCHECK(consumer);
+  if (input.size() < kMinPasswordLengthToCheck)
+    return;
+
   const std::string registry_controlled_domain =
       GetRegistryControlledDomain(GURL(domain));
-  for (size_t i = 0; i + kMinPasswordLengthToCheck <= input.size(); ++i) {
-    const base::string16 input_suffix = input.substr(i);
-    auto passwords_it = passwords_.find(input_suffix);
-    if (passwords_it == passwords_.end())
-      continue;
+  auto passwords_iterator = FindSavedPassword(input);
+  if (passwords_iterator == passwords_.end())
+    return;
 
-    // Password found, check whether it's saved on the same domain.
-    const std::set<std::string>& domains = passwords_it->second;
-    DCHECK(!domains.empty());
-    if (domains.find(registry_controlled_domain) == domains.end()) {
-      // Return only one domain.
-      const std::string& saved_domain = *domains.begin();
-      consumer->OnReuseFound(input_suffix, saved_domain, saved_passwords_,
-                             domains.size());
-      return;
-    }
+  const std::set<std::string>& domains = passwords_iterator->second;
+  DCHECK(!domains.empty());
+  if (domains.find(registry_controlled_domain) == domains.end()) {
+    // Return only one domain.
+    const std::string& saved_domain = *domains.begin();
+    consumer->OnReuseFound(passwords_iterator->first, saved_domain,
+                           saved_passwords_, domains.size());
+    return;
   }
 }
 
 void PasswordReuseDetector::AddPassword(const autofill::PasswordForm& form) {
-  const base::string16& password = form.password_value;
-  if (password.size() < kMinPasswordLengthToCheck)
+  if (form.password_value.size() < kMinPasswordLengthToCheck)
     return;
   GURL signon_realm(form.signon_realm);
   const std::string domain = GetRegistryControlledDomain(signon_realm);
-  std::set<std::string>& domains = passwords_[password];
+  std::set<std::string>& domains = passwords_[form.password_value];
   if (domains.find(domain) == domains.end()) {
     ++saved_passwords_;
     domains.insert(domain);
   }
 }
 
+PasswordReuseDetector::passwords_iterator
+PasswordReuseDetector::FindSavedPassword(const base::string16& input) {
+  // Keys in |passwords_| are ordered by lexicographical order of reversed
+  // strings. In order to check a password reuse a key of |passwords_| that is a
+  // suffix of |input| should be found. The longest such key should be the
+  // largest key in the |passwords_| keys order that is equal or smaller to
+  // |input|.
+  if (passwords_.empty())
+    return passwords_.end();
+
+  // lower_bound returns the first key that is bigger or equal to input.
+  auto it = passwords_.lower_bound(input);
+  if (it != passwords_.end() && it->first == input) {
+    // If the key is equal then a saved password is found.
+    return it;
+  }
+
+  // Otherwise the previous key is a candidate for password reuse.
+  if (it == passwords_.begin())
+    return passwords_.end();
+
+  --it;
+  return IsSuffix(input, it->first) ? it : passwords_.end();
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_reuse_detector.h b/components/password_manager/core/browser/password_reuse_detector.h
index 38151de4..967c941a 100644
--- a/components/password_manager/core/browser/password_reuse_detector.h
+++ b/components/password_manager/core/browser/password_reuse_detector.h
@@ -20,6 +20,11 @@
 
 class PasswordReuseDetectorConsumer;
 
+// Comparator that compares reversed strings.
+struct ReverseStringLess {
+  bool operator()(const base::string16& lhs, const base::string16& rhs) const;
+};
+
 // Per-profile class responsible for detection of password reuse, i.e. that the
 // user input on some site contains the password saved on another site.
 // It receives saved passwords through PasswordStoreConsumer interface.
@@ -47,14 +52,23 @@
                   PasswordReuseDetectorConsumer* consumer);
 
  private:
+  using passwords_iterator = std::map<base::string16,
+                                      std::set<std::string>,
+                                      ReverseStringLess>::const_iterator;
+
   // Add password from |form| to |passwords_|.
   void AddPassword(const autofill::PasswordForm& form);
 
+  // Returns the iterator to |passwords_| that corresponds to the longest key in
+  // |passwords_| that is a suffix of |input|. Returns passwords_.end() in case
+  // when no key in |passwords_| is a prefix of |input|.
+  passwords_iterator FindSavedPassword(const base::string16& input);
+
   // Contains all passwords.
   // A key is a password.
   // A value is a set of registry controlled domains on which the password
   // saved.
-  std::map<base::string16, std::set<std::string>> passwords_;
+  std::map<base::string16, std::set<std::string>, ReverseStringLess> passwords_;
 
   // Number of passwords in |passwords_|, each password is calculated the number
   // of times how many different sites it's saved on.
diff --git a/components/password_manager/core/browser/password_reuse_detector_unittest.cc b/components/password_manager/core/browser/password_reuse_detector_unittest.cc
index 7e8331e..dac4dd6 100644
--- a/components/password_manager/core/browser/password_reuse_detector_unittest.cc
+++ b/components/password_manager/core/browser/password_reuse_detector_unittest.cc
@@ -22,21 +22,30 @@
 
 namespace {
 
-std::vector<std::unique_ptr<PasswordForm>> GetSavedForms() {
-  std::vector<std::unique_ptr<PasswordForm>> result;
-  std::vector<std::pair<std::string, std::string>> domains_passwords = {
+std::vector<std::pair<std::string, std::string>> GetTestDomainsPasswords() {
+  return {
       {"https://accounts.google.com", "password"},
       {"https://facebook.com", "123456789"},
       {"https://a.appspot.com", "abcdefghi"},
       {"https://twitter.com", "short"},
+      {"https://example1.com", "secretword"},
+      {"https://example2.com", "secretword"},
   };
+}
 
-  for (const auto& domain_password : domains_passwords) {
-    std::unique_ptr<PasswordForm> form(new PasswordForm);
-    form->signon_realm = domain_password.first;
-    form->password_value = ASCIIToUTF16(domain_password.second);
-    result.push_back(std::move(form));
-  }
+std::unique_ptr<PasswordForm> GetForm(
+    const std::pair<std::string, std::string>& domain_password) {
+  std::unique_ptr<PasswordForm> form(new PasswordForm);
+  form->signon_realm = domain_password.first;
+  form->password_value = ASCIIToUTF16(domain_password.second);
+  return form;
+}
+
+std::vector<std::unique_ptr<PasswordForm>> GetForms(
+    const std::vector<std::pair<std::string, std::string>>& domains_passwords) {
+  std::vector<std::unique_ptr<PasswordForm>> result;
+  for (const auto& domain_password : domains_passwords)
+    result.push_back(GetForm(domain_password));
   return result;
 }
 
@@ -52,7 +61,7 @@
 
 TEST(PasswordReuseDetectorTest, TypingPasswordOnDifferentSite) {
   PasswordReuseDetector reuse_detector;
-  reuse_detector.OnGetPasswordStoreResults(GetSavedForms());
+  reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords()));
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0);
@@ -63,14 +72,27 @@
   testing::Mock::VerifyAndClearExpectations(&mockConsumer);
 
   EXPECT_CALL(mockConsumer,
-              OnReuseFound(ASCIIToUTF16("password"), "google.com", 3, 1));
+              OnReuseFound(ASCIIToUTF16("password"), "google.com", 5, 1));
   reuse_detector.CheckReuse(ASCIIToUTF16("123password"), "https://evil.com",
                             &mockConsumer);
+  testing::Mock::VerifyAndClearExpectations(&mockConsumer);
+
+  EXPECT_CALL(mockConsumer,
+              OnReuseFound(ASCIIToUTF16("password"), "google.com", 5, 1));
+  reuse_detector.CheckReuse(ASCIIToUTF16("password"), "https://evil.com",
+                            &mockConsumer);
+
+  testing::Mock::VerifyAndClearExpectations(&mockConsumer);
+
+  EXPECT_CALL(mockConsumer,
+              OnReuseFound(ASCIIToUTF16("secretword"), "example1.com", 5, 2));
+  reuse_detector.CheckReuse(ASCIIToUTF16("abcdsecretword"), "https://evil.com",
+                            &mockConsumer);
 }
 
 TEST(PasswordReuseDetectorTest, PSLMatchNoReuseEvent) {
   PasswordReuseDetector reuse_detector;
-  reuse_detector.OnGetPasswordStoreResults(GetSavedForms());
+  reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords()));
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0);
@@ -80,20 +102,20 @@
 
 TEST(PasswordReuseDetectorTest, NoPSLMatchReuseEvent) {
   PasswordReuseDetector reuse_detector;
-  reuse_detector.OnGetPasswordStoreResults(GetSavedForms());
+  reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords()));
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   // a.appspot.com and b.appspot.com are not PSL matches. So reuse event should
   // be raised.
   EXPECT_CALL(mockConsumer,
-              OnReuseFound(ASCIIToUTF16("abcdefghi"), "a.appspot.com", 3, 1));
+              OnReuseFound(ASCIIToUTF16("abcdefghi"), "a.appspot.com", 5, 1));
   reuse_detector.CheckReuse(ASCIIToUTF16("abcdefghi"), "https://b.appspot.com",
                             &mockConsumer);
 }
 
 TEST(PasswordReuseDetectorTest, TooShortPasswordNoReuseEvent) {
   PasswordReuseDetector reuse_detector;
-  reuse_detector.OnGetPasswordStoreResults(GetSavedForms());
+  reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords()));
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0);
@@ -102,7 +124,7 @@
 
 TEST(PasswordReuseDetectorTest, PasswordNotInputSuffixNoReuseEvent) {
   PasswordReuseDetector reuse_detector;
-  reuse_detector.OnGetPasswordStoreResults(GetSavedForms());
+  reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords()));
   MockPasswordReuseDetectorConsumer mockConsumer;
 
   EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0);
@@ -117,7 +139,8 @@
        {PasswordStoreChange::ADD, PasswordStoreChange::UPDATE,
         PasswordStoreChange::REMOVE}) {
     PasswordReuseDetector reuse_detector;
-    PasswordStoreChangeList changes = GetChangeList(type, GetSavedForms());
+    PasswordStoreChangeList changes =
+        GetChangeList(type, GetForms(GetTestDomainsPasswords()));
     reuse_detector.OnLoginsChanged(changes);
     MockPasswordReuseDetectorConsumer mockConsumer;
 
@@ -125,13 +148,42 @@
       EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0);
     } else {
       EXPECT_CALL(mockConsumer,
-                  OnReuseFound(ASCIIToUTF16("password"), "google.com", 3, 1));
+                  OnReuseFound(ASCIIToUTF16("password"), "google.com", 5, 1));
     }
     reuse_detector.CheckReuse(ASCIIToUTF16("123password"), "https://evil.com",
                               &mockConsumer);
   }
 }
 
+TEST(PasswordReuseDetectorTest, CheckLongestPasswordMatchReturn) {
+  const std::vector<std::pair<std::string, std::string>> domain_passwords = {
+      {"https://example1.com", "234567890"},
+      {"https://example2.com", "01234567890"},
+      {"https://example3.com", "1234567890"},
+  };
+
+  PasswordReuseDetector reuse_detector;
+  reuse_detector.OnGetPasswordStoreResults(GetForms(domain_passwords));
+
+  MockPasswordReuseDetectorConsumer mockConsumer;
+
+  EXPECT_CALL(mockConsumer,
+              OnReuseFound(ASCIIToUTF16("01234567890"), "example2.com", 3, 1));
+  reuse_detector.CheckReuse(ASCIIToUTF16("abcd01234567890"), "https://evil.com",
+                            &mockConsumer);
+  testing::Mock::VerifyAndClearExpectations(&mockConsumer);
+
+  EXPECT_CALL(mockConsumer,
+              OnReuseFound(ASCIIToUTF16("1234567890"), "example3.com", 3, 1));
+  reuse_detector.CheckReuse(ASCIIToUTF16("1234567890"), "https://evil.com",
+                            &mockConsumer);
+  testing::Mock::VerifyAndClearExpectations(&mockConsumer);
+
+  EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0);
+  reuse_detector.CheckReuse(ASCIIToUTF16("34567890"), "https://evil.com",
+                            &mockConsumer);
+}
+
 }  // namespace
 
 }  // namespace password_manager
diff --git a/components/policy/core/common/cloud/enterprise_metrics.h b/components/policy/core/common/cloud/enterprise_metrics.h
index 5c468a6e..b61fe35 100644
--- a/components/policy/core/common/cloud/enterprise_metrics.h
+++ b/components/policy/core/common/cloud/enterprise_metrics.h
@@ -227,6 +227,8 @@
   kMetricEnrollmentNoDeviceIdentification = 54,
   // Active Directory policy fetch failed.
   kMetricEnrollmentActiveDirectoryPolicyFetchFailed = 55,
+  // Failed to store DM token into the local state.
+  kMetricEnrollmentStoreDMTokenFailed = 56,
 };
 
 // Events related to policy refresh.
diff --git a/components/reading_list/ios/reading_list_entry.h b/components/reading_list/ios/reading_list_entry.h
index e454850..17651cbed 100644
--- a/components/reading_list/ios/reading_list_entry.h
+++ b/components/reading_list/ios/reading_list_entry.h
@@ -15,6 +15,13 @@
 
 namespace reading_list {
 class ReadingListLocal;
+
+// The different ways a reading list entry is added.
+// |ADDED_VIA_CURRENT_APP| is when the entry was added by the user from within
+// the current instance of the app.
+// |ADDED_VIA_EXTENSION| is when the entry was added via the share extension.
+// |ADDED_VIA_SYNC| is when the entry was added with sync.
+enum EntrySource { ADDED_VIA_CURRENT_APP, ADDED_VIA_EXTENSION, ADDED_VIA_SYNC };
 }
 
 namespace sync_pb {
diff --git a/components/reading_list/ios/reading_list_model.h b/components/reading_list/ios/reading_list_model.h
index 73968eea..5a95d7a 100644
--- a/components/reading_list/ios/reading_list_model.h
+++ b/components/reading_list/ios/reading_list_model.h
@@ -93,8 +93,10 @@
   // trimmed copy of |title.
   // 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;
+  virtual const ReadingListEntry& AddEntry(
+      const GURL& url,
+      const std::string& title,
+      reading_list::EntrySource source) = 0;
 
   // Removes an entry. The removal may be asynchronous, and not happen
   // immediately.
diff --git a/components/reading_list/ios/reading_list_model_bridge_observer.h b/components/reading_list/ios/reading_list_model_bridge_observer.h
index 5cb33183..f19e09e 100644
--- a/components/reading_list/ios/reading_list_model_bridge_observer.h
+++ b/components/reading_list/ios/reading_list_model_bridge_observer.h
@@ -30,7 +30,8 @@
             willAddEntry:(const ReadingListEntry&)entry;
 
 - (void)readingListModel:(const ReadingListModel*)model
-             didAddEntry:(const GURL&)url;
+             didAddEntry:(const GURL&)url
+             entrySource:(reading_list::EntrySource)source;
 
 - (void)readingListModelBeganBatchUpdates:(const ReadingListModel*)model;
 - (void)readingListModelCompletedBatchUpdates:(const ReadingListModel*)model;
@@ -65,7 +66,8 @@
   void ReadingListWillAddEntry(const ReadingListModel* model,
                                const ReadingListEntry& entry) override;
   void ReadingListDidAddEntry(const ReadingListModel* model,
-                              const GURL& url) override;
+                              const GURL& url,
+                              reading_list::EntrySource source) override;
   void ReadingListDidApplyChanges(ReadingListModel* model) override;
   void ReadingListWillUpdateEntry(const ReadingListModel* model,
                                   const GURL& url) override;
diff --git a/components/reading_list/ios/reading_list_model_bridge_observer.mm b/components/reading_list/ios/reading_list_model_bridge_observer.mm
index efe4ddd9..3595d38 100644
--- a/components/reading_list/ios/reading_list_model_bridge_observer.mm
+++ b/components/reading_list/ios/reading_list_model_bridge_observer.mm
@@ -54,9 +54,12 @@
 
 void ReadingListModelBridge::ReadingListDidAddEntry(
     const ReadingListModel* model,
-    const GURL& url) {
-  if ([observer_ respondsToSelector:@selector(readingListModel:didAddEntry:)]) {
-    [observer_ readingListModel:model didAddEntry:url];
+    const GURL& url,
+    reading_list::EntrySource source) {
+  if ([observer_ respondsToSelector:@selector(readingListModel:
+                                                   didAddEntry:
+                                                   entrySource:)]) {
+    [observer_ readingListModel:model didAddEntry:url entrySource:source];
   }
 }
 
diff --git a/components/reading_list/ios/reading_list_model_impl.cc b/components/reading_list/ios/reading_list_model_impl.cc
index acb08106..cf7ee6b 100644
--- a/components/reading_list/ios/reading_list_model_impl.cc
+++ b/components/reading_list/ios/reading_list_model_impl.cc
@@ -242,7 +242,7 @@
   GURL url = entry->URL();
   entries_->insert(std::make_pair(url, std::move(*entry)));
   for (auto& observer : observers_) {
-    observer.ReadingListDidAddEntry(this, url);
+    observer.ReadingListDidAddEntry(this, url, reading_list::ADDED_VIA_SYNC);
     observer.ReadingListDidApplyChanges(this);
   }
 }
@@ -306,7 +306,8 @@
 
 const ReadingListEntry& ReadingListModelImpl::AddEntry(
     const GURL& url,
-    const std::string& title) {
+    const std::string& title,
+    reading_list::EntrySource source) {
   DCHECK(CalledOnValidThread());
   DCHECK(loaded());
   DCHECK(url.SchemeIsHTTPOrHTTPS());
@@ -327,7 +328,7 @@
   }
 
   for (auto& observer : observers_) {
-    observer.ReadingListDidAddEntry(this, url);
+    observer.ReadingListDidAddEntry(this, url, source);
     observer.ReadingListDidApplyChanges(this);
   }
 
diff --git a/components/reading_list/ios/reading_list_model_impl.h b/components/reading_list/ios/reading_list_model_impl.h
index 8d31540..1b6f9a2 100644
--- a/components/reading_list/ios/reading_list_model_impl.h
+++ b/components/reading_list/ios/reading_list_model_impl.h
@@ -60,7 +60,8 @@
   void RemoveEntryByURL(const GURL& url) override;
 
   const ReadingListEntry& AddEntry(const GURL& url,
-                                   const std::string& title) override;
+                                   const std::string& title,
+                                   reading_list::EntrySource source) override;
 
   void SetReadStatus(const GURL& url, bool read) override;
 
diff --git a/components/reading_list/ios/reading_list_model_observer.h b/components/reading_list/ios/reading_list_model_observer.h
index fc59569..ffaaed8 100644
--- a/components/reading_list/ios/reading_list_model_observer.h
+++ b/components/reading_list/ios/reading_list_model_observer.h
@@ -8,9 +8,10 @@
 #include <set>
 #include <vector>
 
+#include "components/reading_list/ios/reading_list_entry.h"
+
 class GURL;
 class ReadingListModel;
-class ReadingListEntry;
 
 // Observer for the Reading List model. In the observer methods care should be
 // taken to not modify the model.
@@ -58,8 +59,10 @@
   // Invoked when elements have been added. This method is called after the
   // the entry has been added to the model and the entry can now be retrieved
   // from the model.
+  // |source| says where the entry came from.
   virtual void ReadingListDidAddEntry(const ReadingListModel* model,
-                                      const GURL& url) {}
+                                      const GURL& url,
+                                      reading_list::EntrySource source) {}
 
   // Invoked when an entry is about to change.
   virtual void ReadingListWillUpdateEntry(const ReadingListModel* model,
diff --git a/components/reading_list/ios/reading_list_model_unittest.mm b/components/reading_list/ios/reading_list_model_unittest.mm
index bdcc0084..563c1c3 100644
--- a/components/reading_list/ios/reading_list_model_unittest.mm
+++ b/components/reading_list/ios/reading_list_model_unittest.mm
@@ -231,7 +231,8 @@
     observer_add_ += 1;
   }
   void ReadingListDidAddEntry(const ReadingListModel* model,
-                              const GURL& url) override {
+                              const GURL& url,
+                              reading_list::EntrySource entry_source) override {
     observer_did_add_ += 1;
   }
   void ReadingListWillUpdateEntry(const ReadingListModel* model,
@@ -334,7 +335,8 @@
   ClearCounts();
 
   const ReadingListEntry& entry =
-      model_->AddEntry(GURL("http://example.com"), "\n  \tsample Test ");
+      model_->AddEntry(GURL("http://example.com"), "\n  \tsample Test ",
+                       reading_list::ADDED_VIA_CURRENT_APP);
   EXPECT_EQ(GURL("http://example.com"), entry.URL());
   EXPECT_EQ("sample Test", entry.Title());
 
@@ -371,7 +373,8 @@
 TEST_F(ReadingListModelTest, SyncMergeEntry) {
   auto storage = base::MakeUnique<TestReadingListStorage>(this);
   SetStorage(std::move(storage));
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   model_->SetEntryDistilledPath(GURL("http://example.com"),
                                 base::FilePath("distilled/page.html"));
   const ReadingListEntry* local_entry =
@@ -402,7 +405,8 @@
 TEST_F(ReadingListModelTest, RemoveEntryByUrl) {
   auto storage = base::MakeUnique<TestReadingListStorage>(this);
   SetStorage(std::move(storage));
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   ClearCounts();
   EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
   EXPECT_EQ(1ul, UnreadSize());
@@ -414,7 +418,8 @@
   EXPECT_EQ(0ul, ReadSize());
   EXPECT_EQ(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
 
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   model_->SetReadStatus(GURL("http://example.com"), true);
   ClearCounts();
   EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
@@ -431,7 +436,8 @@
 TEST_F(ReadingListModelTest, RemoveSyncEntryByUrl) {
   auto storage = base::MakeUnique<TestReadingListStorage>(this);
   SetStorage(std::move(storage));
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   ClearCounts();
   EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
   EXPECT_EQ(1ul, UnreadSize());
@@ -443,7 +449,8 @@
   EXPECT_EQ(0ul, ReadSize());
   EXPECT_EQ(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
 
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   model_->SetReadStatus(GURL("http://example.com"), true);
   ClearCounts();
   EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
@@ -458,7 +465,8 @@
 }
 
 TEST_F(ReadingListModelTest, ReadEntry) {
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
 
   ClearCounts();
   model_->SetReadStatus(GURL("http://example.com"), true);
@@ -479,7 +487,7 @@
   GURL url1("http://example.com");
   GURL url2("http://example2.com");
   std::string entry1_title = "foo bar qux";
-  model_->AddEntry(url1, entry1_title);
+  model_->AddEntry(url1, entry1_title, reading_list::ADDED_VIA_CURRENT_APP);
 
   // Check call with nullptr |read| parameter.
   const ReadingListEntry* entry1 = model_->GetEntryByURL(url1);
@@ -502,7 +510,8 @@
 
 TEST_F(ReadingListModelTest, UnreadEntry) {
   // Setup.
-  model_->AddEntry(GURL("http://example.com"), "sample");
+  model_->AddEntry(GURL("http://example.com"), "sample",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   EXPECT_TRUE(model_->GetLocalUnseenFlag());
   model_->SetReadStatus(GURL("http://example.com"), true);
   ClearCounts();
@@ -570,7 +579,8 @@
 
 TEST_F(ReadingListModelTest, UpdateEntryTitle) {
   const GURL gurl("http://example.com");
-  const ReadingListEntry& entry = model_->AddEntry(gurl, "sample");
+  const ReadingListEntry& entry =
+      model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
   ClearCounts();
 
   model_->SetEntryTitle(gurl, "ping");
@@ -580,7 +590,8 @@
 
 TEST_F(ReadingListModelTest, UpdateEntryDistilledState) {
   const GURL gurl("http://example.com");
-  const ReadingListEntry& entry = model_->AddEntry(gurl, "sample");
+  const ReadingListEntry& entry =
+      model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
   ClearCounts();
 
   model_->SetEntryDistilledState(gurl, ReadingListEntry::PROCESSING);
@@ -590,7 +601,8 @@
 
 TEST_F(ReadingListModelTest, UpdateDistilledPath) {
   const GURL gurl("http://example.com");
-  const ReadingListEntry& entry = model_->AddEntry(gurl, "sample");
+  const ReadingListEntry& entry =
+      model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
   ClearCounts();
 
   model_->SetEntryDistilledPath(gurl, base::FilePath("distilled/page.html"));
@@ -601,7 +613,7 @@
 
 TEST_F(ReadingListModelTest, UpdateReadEntryTitle) {
   const GURL gurl("http://example.com");
-  model_->AddEntry(gurl, "sample");
+  model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
   model_->SetReadStatus(gurl, true);
   const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
   ClearCounts();
@@ -613,7 +625,7 @@
 
 TEST_F(ReadingListModelTest, UpdateReadEntryState) {
   const GURL gurl("http://example.com");
-  model_->AddEntry(gurl, "sample");
+  model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
   model_->SetReadStatus(gurl, true);
   const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
   ClearCounts();
@@ -625,7 +637,7 @@
 
 TEST_F(ReadingListModelTest, UpdateReadDistilledPath) {
   const GURL gurl("http://example.com");
-  model_->AddEntry(gurl, "sample");
+  model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
   model_->SetReadStatus(gurl, true);
   const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
   ClearCounts();
diff --git a/components/reading_list/ios/reading_list_store_unittest.mm b/components/reading_list/ios/reading_list_store_unittest.mm
index b13199e4..9ba369d4 100644
--- a/components/reading_list/ios/reading_list_store_unittest.mm
+++ b/components/reading_list/ios/reading_list_store_unittest.mm
@@ -252,7 +252,8 @@
 
 TEST_F(ReadingListStoreTest, ApplySyncChangesOneMerge) {
   syncer::EntityDataMap remote_input;
-  model_->AddEntry(GURL("http://unread.example.com/"), "unread title");
+  model_->AddEntry(GURL("http://unread.example.com/"), "unread title",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   base::test::ios::SpinRunLoopWithMinDelay(
       base::TimeDelta::FromMilliseconds(10));
 
@@ -285,7 +286,8 @@
   base::test::ios::SpinRunLoopWithMinDelay(
       base::TimeDelta::FromMilliseconds(10));
   syncer::EntityDataMap remote_input;
-  model_->AddEntry(GURL("http://unread.example.com/"), "new unread title");
+  model_->AddEntry(GURL("http://unread.example.com/"), "new unread title",
+                   reading_list::ADDED_VIA_CURRENT_APP);
   AssertCounts(0, 0, 0, 0, 0);
 
   std::unique_ptr<sync_pb::ReadingListSpecifics> specifics =
diff --git a/components/resources/OWNERS b/components/resources/OWNERS
index 293f9d2..eb2ef926 100644
--- a/components/resources/OWNERS
+++ b/components/resources/OWNERS
@@ -1,4 +1,5 @@
 per-file autofill_scaled_resources.grdp=estade@chromium.org
+per-file content_suggestions*=file://components/ntp_snippets/OWNERS
 per-file crash_*=cpu@chromium.org
 per-file crash_*=jochen@chromium.org
 per-file crash_*=mark@chromium.org
@@ -17,7 +18,6 @@
 per-file neterror*=juliatuttle@chromium.org
 per-file neterror*=mmenke@chromium.org
 per-file ntp_tiles_resources.grdp=file://components/ntp_tiles/OWNERS
-per-file physical_web*=file://components/physical_web/OWNERS
 per-file proximity_auth*=tengs@chromium.org
 per-file supervised_user_error_page.grpd=aberent@chromium.org
 per-file supervised_user_error_page.grpd=bauerb@chromium.org
diff --git a/components/resources/components_scaled_resources.grd b/components/resources/components_scaled_resources.grd
index 64b479d..511ec196 100644
--- a/components/resources/components_scaled_resources.grd
+++ b/components/resources/components_scaled_resources.grd
@@ -13,10 +13,10 @@
   <release seq="1">
     <structures fallback_to_low_resolution="true">
       <part file="autofill_scaled_resources.grdp" />
+      <part file="content_suggestions_scaled_resources.grdp" />
       <part file="crash_scaled_resources.grdp" />
       <part file="flags_ui_scaled_resources.grdp" />
       <part file="neterror_scaled_resources.grdp" />
-      <part file="physical_web_scaled_resources.grdp" />
       <part file="version_ui_scaled_resources.grdp" />
 
       <!-- Generic resources -->
diff --git a/components/resources/physical_web_scaled_resources.grdp b/components/resources/content_suggestions_scaled_resources.grdp
similarity index 60%
rename from components/resources/physical_web_scaled_resources.grdp
rename to components/resources/content_suggestions_scaled_resources.grdp
index 38d23c4..12b382dc 100644
--- a/components/resources/physical_web_scaled_resources.grdp
+++ b/components/resources/content_suggestions_scaled_resources.grdp
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <grit-part>
-  <structure type="chrome_scaled_image" name="IDR_PHYSICAL_WEB_LOGO" file="physical_web/logo.png" />
+  <structure type="chrome_scaled_image" name="IDR_PHYSICAL_WEB_LOGO_WITH_PADDING" file="content_suggestions/physical_web_logo_with_padding.png" />
 </grit-part>
diff --git a/components/resources/default_100_percent/content_suggestions/physical_web_logo_with_padding.png b/components/resources/default_100_percent/content_suggestions/physical_web_logo_with_padding.png
new file mode 100644
index 0000000..271b580
--- /dev/null
+++ b/components/resources/default_100_percent/content_suggestions/physical_web_logo_with_padding.png
Binary files differ
diff --git a/components/resources/default_100_percent/physical_web/logo.png b/components/resources/default_100_percent/physical_web/logo.png
deleted file mode 100644
index 3007d0b..0000000
--- a/components/resources/default_100_percent/physical_web/logo.png
+++ /dev/null
Binary files differ
diff --git a/components/resources/default_200_percent/content_suggestions/physical_web_logo_with_padding.png b/components/resources/default_200_percent/content_suggestions/physical_web_logo_with_padding.png
new file mode 100644
index 0000000..96aba76
--- /dev/null
+++ b/components/resources/default_200_percent/content_suggestions/physical_web_logo_with_padding.png
Binary files differ
diff --git a/components/resources/default_200_percent/physical_web/logo.png b/components/resources/default_200_percent/physical_web/logo.png
deleted file mode 100644
index 15ec0da..0000000
--- a/components/resources/default_200_percent/physical_web/logo.png
+++ /dev/null
Binary files differ
diff --git a/components/resources/default_300_percent/content_suggestions/physical_web_logo_with_padding.png b/components/resources/default_300_percent/content_suggestions/physical_web_logo_with_padding.png
new file mode 100644
index 0000000..e1ebaed8
--- /dev/null
+++ b/components/resources/default_300_percent/content_suggestions/physical_web_logo_with_padding.png
Binary files differ
diff --git a/components/resources/default_300_percent/physical_web/logo.png b/components/resources/default_300_percent/physical_web/logo.png
deleted file mode 100644
index 821de18e..0000000
--- a/components/resources/default_300_percent/physical_web/logo.png
+++ /dev/null
Binary files differ
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 079bb3f..fcb2e27c 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -151,6 +151,7 @@
     "//ui/shell_dialogs",
     "//ui/snapshot",
     "//ui/touch_selection",
+    "//v8:v8_version",
   ]
 
   public_deps = [
diff --git a/content/browser/devtools/DEPS b/content/browser/devtools/DEPS
index 510478f3..0e86f42b 100644
--- a/content/browser/devtools/DEPS
+++ b/content/browser/devtools/DEPS
@@ -3,5 +3,5 @@
   "+grit/devtools_resources_map.h",
 
   # V8 version info
-  "+v8/include/v8.h",
+  "+v8/include/v8-version-string.h",
 ]
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc
index bd980ec..58c0c46 100644
--- a/content/browser/devtools/devtools_http_handler.cc
+++ b/content/browser/devtools/devtools_http_handler.cc
@@ -37,7 +37,7 @@
 #include "net/server/http_server_request_info.h"
 #include "net/server/http_server_response_info.h"
 #include "net/socket/server_socket.h"
-#include "v8/include/v8.h"
+#include "v8/include/v8-version-string.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
@@ -525,7 +525,7 @@
     version.SetString("WebKit-Version", GetWebKitVersion());
     version.SetString("Browser", product_name_);
     version.SetString("User-Agent", user_agent_);
-    version.SetString("V8-Version", v8::V8::GetVersion());
+    version.SetString("V8-Version", V8_VERSION_STRING);
 #if defined(OS_ANDROID)
     version.SetString("Android-Package",
         base::android::BuildInfo::GetInstance()->package_name());
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index fc8f8812..d900dfd 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1596,6 +1596,9 @@
 }
 
 void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
+  if (!is_active())
+    return;
+
   // Validate the URLs in |params|.  If the renderer can't request the URLs
   // directly, don't show them in the context menu.
   ContextMenuParams validated_params(params);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 7da685df..eb809c41 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -648,6 +648,8 @@
                            RenderViewHostStaysActiveWithLateSwapoutACK);
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
                            LoadEventForwardingWhilePendingDeletion);
+  FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+                           ContextMenuAfterCrossProcessNavigation);
 
   // IPC Message handlers.
   void OnDidAddMessageToConsole(int32_t level,
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h
index 3109d04..7c7e10c6 100644
--- a/content/browser/renderer_host/input/input_router_impl.h
+++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -201,10 +201,6 @@
 
   int routing_id() const { return routing_id_; }
 
-  TouchAction allowed_touch_action() {
-    return touch_action_filter_.allowed_touch_action();
-  }
-
   IPC::Sender* sender_;
   InputRouterClient* client_;
   InputAckHandler* ack_handler_;
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index d0c9b32..9bb4969e 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -156,11 +156,6 @@
                  base::RetainedRef(controller), error_code));
 }
 
-void AudioInputRendererHost::OnData(media::AudioInputController* controller,
-                                    const media::AudioBus* data) {
-  NOTREACHED() << "Only low-latency mode is supported.";
-}
-
 void AudioInputRendererHost::OnLog(media::AudioInputController* controller,
                                    const std::string& message) {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
@@ -180,7 +175,6 @@
   AudioEntry* entry = LookupByController(controller);
   DCHECK(entry);
   DCHECK(PeerHandle());
-  DCHECK(entry->controller->SharedMemoryAndSyncSocketMode());
 
   // Once the audio stream is created then complete the creation process by
   // mapping shared memory and sharing with the renderer process.
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.h b/content/browser/renderer_host/media/audio_input_renderer_host.h
index e4bf199cc..fdd979ab 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -108,8 +108,6 @@
   void OnCreated(media::AudioInputController* controller) override;
   void OnError(media::AudioInputController* controller,
                media::AudioInputController::ErrorCode error_code) override;
-  void OnData(media::AudioInputController* controller,
-              const media::AudioBus* data) override;
   void OnLog(media::AudioInputController* controller,
              const std::string& message) override;
 
@@ -238,7 +236,7 @@
   AudioEntryMap audio_entries_;
 
   // Raw pointer of the UserInputMonitor.
-  media::UserInputMonitor* user_input_monitor_;
+  media::UserInputMonitor* const user_input_monitor_;
 
   std::unique_ptr<media::AudioLog> audio_log_;
 
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
index 3a62616..375da42c 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host_unittest.cc
@@ -162,13 +162,13 @@
       media::AudioManager* audio_manager,
       AudioInputController::EventHandler* event_handler,
       media::UserInputMonitor* user_input_monitor)
-      : AudioInputController(event_handler,
+      : AudioInputController(std::move(task_runner),
+                             event_handler,
                              writer,
                              /*debug_writer*/ nullptr,
                              user_input_monitor,
                              /*agc*/ false) {
-    task_runner_ = std::move(task_runner);
-    task_runner_->PostTask(
+    GetTaskRunnerForTesting()->PostTask(
         FROM_HERE,
         base::Bind(&AudioInputController::EventHandler::OnCreated,
                    base::Unretained(event_handler), base::Unretained(this)));
@@ -178,7 +178,7 @@
         .WillByDefault(SaveArg<0>(&file_name));
   }
 
-  EventHandler* handler() { return handler_; }
+  EventHandler* handler() { return GetHandlerForTesting(); }
 
   // File name that we pretend to do a debug recording to, if any.
   base::FilePath debug_file_name() { return file_name; }
@@ -202,7 +202,8 @@
   void ExecuteClose(const base::Closure& task) {
     // Hop to audio manager thread before calling task, since this is the real
     // behavior.
-    task_runner_->PostTaskAndReply(FROM_HERE, base::Bind([]() {}), task);
+    GetTaskRunnerForTesting()->PostTaskAndReply(FROM_HERE, base::Bind([]() {}),
+                                                task);
   }
 
   base::FilePath file_name;
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 122e9311..6c712a3 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -196,12 +196,8 @@
       NOTREACHED() << "Should only receive one reply per event";
 
     // |fetch_dispatcher| is null if the URLRequest was killed.
-    if (fetch_dispatcher_) {
-      // TODO(falken): Remove this CHECK once https://crbug.com/485900 is
-      // resolved.
-      CHECK(version_->GetMainScriptHttpResponseInfo());
+    if (fetch_dispatcher_)
       fetch_dispatcher_->DidFinish(request_id, fetch_result, response);
-    }
   }
 
  private:
@@ -300,9 +296,6 @@
   DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
       << "Worker stopped too soon after it was started.";
 
-  // TODO(falken): Remove this CHECK once https://crbug.com/485900 is resolved.
-  CHECK(version_->GetMainScriptHttpResponseInfo());
-
   DCHECK(!prepare_callback_.is_null());
   base::Closure prepare_callback = prepare_callback_;
   prepare_callback.Run();
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.cc b/content/browser/service_worker/service_worker_read_from_cache_job.cc
index fea3d199..c0d4966 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ b/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -35,7 +35,12 @@
       resource_id_(resource_id),
       context_(context),
       version_(version),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  DCHECK(version_);
+  DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
+         (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
+          version_->script_url() == request_->url()));
+}
 
 ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() {
 }
@@ -165,11 +170,8 @@
   if (is_range_request())
     SetupRangeResponse(http_info_io_buffer_->response_data_size);
   http_info_io_buffer_ = nullptr;
-  if (is_main_script()) {
-    // TODO(nhiroki): Temporary check for debugging (https://crbug.com/485900).
-    CHECK_EQ(request_->url(), version_->script_url());
+  if (is_main_script())
     version_->SetMainScriptHttpResponseInfo(*http_info_);
-  }
   TRACE_EVENT_ASYNC_END1("ServiceWorker",
                          "ServiceWorkerReadFromCacheJob::ReadInfo",
                          this,
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
index b0fb55e..81c64a9 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -35,6 +35,7 @@
 const int64_t kVersionId = 2;
 const int64_t kMainScriptResourceId = 10;
 const int64_t kImportedScriptResourceId = 11;
+const int64_t kNonExistentResourceId = 12;
 const int64_t kResourceSize = 100;
 
 void DidStoreRegistration(ServiceWorkerStatusCode* status_out,
@@ -227,11 +228,20 @@
 TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
   ASSERT_EQ(SERVICE_WORKER_OK, FindRegistration());
 
-  // Try to read a nonexistent resource from the diskcache.
+  // Populate the script cache map with a nonexistent resource.
+  ServiceWorkerScriptCacheMap* script_cache_map = version_->script_cache_map();
+  script_cache_map->resource_map_.clear();
+  using Record = ServiceWorkerDatabase::ResourceRecord;
+  std::vector<Record> resources = {
+      Record(kNonExistentResourceId, main_script_.url, main_script_.size_bytes),
+      Record(imported_script_.resource_id, imported_script_.url,
+             imported_script_.size_bytes)};
+  script_cache_map->SetResources(resources);
+
+  // Attempt to read it from the disk cache.
   std::unique_ptr<net::URLRequest> request =
-      url_request_context_->CreateRequest(
-          GURL("http://example.com/nonexistent"), net::DEFAULT_PRIORITY,
-          &delegate_);
+      url_request_context_->CreateRequest(main_script_.url,
+                                          net::DEFAULT_PRIORITY, &delegate_);
   const int64_t kNonexistentResourceId = 100;
   test_job_interceptor_->set_main_intercept_job(
       base::MakeUnique<ServiceWorkerReadFromCacheJob>(
diff --git a/content/browser/service_worker/service_worker_script_cache_map.h b/content/browser/service_worker/service_worker_script_cache_map.h
index ac4436d..0051d68 100644
--- a/content/browser/service_worker/service_worker_script_cache_map.h
+++ b/content/browser/service_worker/service_worker_script_cache_map.h
@@ -75,6 +75,7 @@
   friend class ServiceWorkerVersion;
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest,
                            ReadResourceFailure_WaitingWorker);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerReadFromCacheJobTest, ResourceNotFound);
 
   ServiceWorkerScriptCacheMap(
       ServiceWorkerVersion* owner,
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc
index da9a6f9..77a82de8 100644
--- a/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -599,8 +599,7 @@
   }
 
   // We should have a response now.
-  // TODO(falken): Turn to DCHECK once https://crbug.com/485900 is resolved.
-  CHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
+  DCHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
 
   // A response with status code 0 is Blink telling us to respond with network
   // error.
@@ -621,15 +620,8 @@
   DCHECK(version);
   const net::HttpResponseInfo* main_script_http_info =
       version->GetMainScriptHttpResponseInfo();
-  CHECK(main_script_http_info);
-  if (main_script_http_info) {
-    // In normal case |main_script_http_info| must be set while starting the
-    // ServiceWorker. But when the ServiceWorker registration database was not
-    // written correctly, it may be null.
-    // TODO(horo): Change this line to DCHECK when crbug.com/485900 is fixed.
-    http_response_info_.reset(
-        new net::HttpResponseInfo(*main_script_http_info));
-  }
+  DCHECK(main_script_http_info);
+  http_response_info_.reset(new net::HttpResponseInfo(*main_script_http_info));
 
   // Set up a request for reading the stream.
   if (response.stream_url.is_valid()) {
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index dbbcd8a..34437e85 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -661,9 +661,6 @@
     const StatusCallback& error_callback) {
   if (running_status() == EmbeddedWorkerStatus::RUNNING) {
     DCHECK(start_callbacks_.empty());
-    // TODO(falken): Remove this CHECK once https://crbug.com/485900 is
-    // resolved.
-    CHECK(GetMainScriptHttpResponseInfo());
     task.Run();
     return;
   }
@@ -1520,9 +1517,6 @@
 
   switch (running_status()) {
     case EmbeddedWorkerStatus::RUNNING:
-      // TODO(falken): Remove this CHECK once https://crbug.com/485900 is
-      // resolved.
-      CHECK(GetMainScriptHttpResponseInfo());
       RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
       return;
     case EmbeddedWorkerStatus::STARTING:
@@ -1953,11 +1947,6 @@
 
 void ServiceWorkerVersion::FinishStartWorker(ServiceWorkerStatusCode status) {
   start_worker_first_purpose_ = base::nullopt;
-  if (status == SERVICE_WORKER_OK) {
-    // TODO(falken): Remove this CHECK once https://crbug.com/485900 is
-    // resolved.
-    CHECK(GetMainScriptHttpResponseInfo());
-  }
   RunCallbacks(this, &start_callbacks_, status);
 }
 
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.cc b/content/browser/service_worker/service_worker_write_to_cache_job.cc
index 1deab98e..6ed0a5ce 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job.cc
+++ b/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -81,6 +81,10 @@
       did_notify_started_(false),
       did_notify_finished_(false),
       weak_factory_(this) {
+  DCHECK(version_);
+  DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
+         (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
+          version_->script_url() == url_));
   InitNetRequest(extra_load_flags);
 }
 
@@ -299,9 +303,6 @@
   }
 
   if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
-    // TODO(nhiroki): Temporary check for debugging (https://crbug.com/485900).
-    CHECK_EQ(version_->script_url(), url_);
-
     std::string mime_type;
     request->GetMimeType(&mime_type);
     if (mime_type != "application/x-javascript" &&
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 5802527..6d46c96 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -5384,6 +5384,7 @@
   // aren't at present, and if they become the same this test will need to be
   // updated to accommodate.
   EXPECT_NE(TOUCH_ACTION_AUTO, TOUCH_ACTION_NONE);
+
   // Verify the child's input router is initially set for TOUCH_ACTION_AUTO. The
   // TouchStart event will trigger TOUCH_ACTION_NONE being sent back to the
   // browser.
@@ -5391,7 +5392,8 @@
       root->child_at(0)->current_frame_host()->GetRenderWidgetHost();
   InputRouterImpl* child_input_router =
       static_cast<InputRouterImpl*>(child_render_widget_host->input_router());
-  EXPECT_EQ(TOUCH_ACTION_AUTO, child_input_router->allowed_touch_action());
+  EXPECT_EQ(TOUCH_ACTION_AUTO,
+            child_input_router->touch_action_filter_.allowed_touch_action());
 
   // Simulate touch event to sub-frame.
   gfx::Point child_center(150, 150);
@@ -5410,7 +5412,8 @@
 
   // Verify the presence of the touch handler in the child frame correctly
   // propagates touch-action:none information back to the child's input router.
-  EXPECT_EQ(TOUCH_ACTION_NONE, child_input_router->allowed_touch_action());
+  EXPECT_EQ(TOUCH_ACTION_NONE,
+            child_input_router->touch_action_filter_.allowed_touch_action());
 }
 
 namespace {
@@ -9065,4 +9068,34 @@
   EXPECT_EQ("This page has no title.", result);
 }
 
+// Tests that trying to open a context menu in the old RFH after commiting a
+// navigation doesn't crash the browser. https://crbug.com/677266.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+                       ContextMenuAfterCrossProcessNavigation) {
+  // Navigate to a.com.
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+
+  // Disable the swapout ACK and the swapout timer.
+  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
+      shell()->web_contents()->GetMainFrame());
+  scoped_refptr<SwapoutACKMessageFilter> filter = new SwapoutACKMessageFilter();
+  rfh->GetProcess()->AddFilter(filter.get());
+  rfh->DisableSwapOutTimerForTesting();
+
+  // Open a popup on a.com to keep the process alive.
+  OpenPopup(shell(), embedded_test_server()->GetURL("a.com", "/title2.html"),
+            "foo");
+
+  // Cross-process navigation to b.com.
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("b.com", "/title3.html")));
+
+  // Pretend that a.com just requested a context menu. This used to cause a
+  // because the RenderWidgetHostView is destroyed when the frame is swapped and
+  // added to pending delete list.
+  rfh->OnMessageReceived(
+      FrameHostMsg_ContextMenu(rfh->GetRoutingID(), ContextMenuParams()));
+}
+
 }  // namespace content
diff --git a/content/browser/speech/speech_recognition_browsertest.cc b/content/browser/speech/speech_recognition_browsertest.cc
index ac6bcbc..7ddd4ee0 100644
--- a/content/browser/speech/speech_recognition_browsertest.cc
+++ b/content/browser/speech/speech_recognition_browsertest.cc
@@ -156,7 +156,7 @@
     audio_bus->FromInterleaved(&audio_buffer.get()[0],
                                audio_bus->frames(),
                                audio_params.bits_per_sample() / 8);
-    controller->event_handler()->OnData(controller.get(), audio_bus.get());
+    controller->sync_writer()->Write(audio_bus.get(), 0.0, false, 0);
   }
 
   void FeedAudioController(int duration_ms, bool feed_with_noise) {
diff --git a/content/browser/speech/speech_recognizer_impl.cc b/content/browser/speech/speech_recognizer_impl.cc
index 0bc62614..d79c171 100644
--- a/content/browser/speech/speech_recognizer_impl.cc
+++ b/content/browser/speech/speech_recognizer_impl.cc
@@ -276,8 +276,10 @@
                                      this, event_args));
 }
 
-void SpeechRecognizerImpl::OnData(AudioInputController* controller,
-                                  const AudioBus* data) {
+void SpeechRecognizerImpl::Write(const AudioBus* data,
+                                 double volume,
+                                 bool key_pressed,
+                                 uint32_t hardware_delay_bytes) {
   // Convert audio from native format to fixed format used by WebSpeech.
   FSMEventArgs event_args(EVENT_AUDIO_DATA);
   event_args.audio_data = audio_converter_->Convert(data);
@@ -297,6 +299,8 @@
   CHECK(audio_converter_->data_was_converted());
 }
 
+void SpeechRecognizerImpl::Close() {}
+
 void SpeechRecognizerImpl::OnAudioClosed(AudioInputController*) {}
 
 void SpeechRecognizerImpl::OnSpeechRecognitionEngineResults(
@@ -585,7 +589,7 @@
       new OnDataConverter(input_parameters, output_parameters));
 
   audio_controller_ = AudioInputController::Create(
-      audio_manager, this, input_parameters, device_id_, NULL);
+      audio_manager, this, this, input_parameters, device_id_, NULL);
 
   if (!audio_controller_.get()) {
     return Abort(
diff --git a/content/browser/speech/speech_recognizer_impl.h b/content/browser/speech/speech_recognizer_impl.h
index e0a632e9..f284171 100644
--- a/content/browser/speech/speech_recognizer_impl.h
+++ b/content/browser/speech/speech_recognizer_impl.h
@@ -32,6 +32,7 @@
 class CONTENT_EXPORT SpeechRecognizerImpl
     : public SpeechRecognizer,
       public media::AudioInputController::EventHandler,
+      public media::AudioInputController::SyncWriter,
       public NON_EXPORTED_BASE(SpeechRecognitionEngine::Delegate) {
  public:
   static const int kAudioSampleRate;
@@ -134,11 +135,16 @@
   void OnCreated(media::AudioInputController* controller) override {}
   void OnError(media::AudioInputController* controller,
                media::AudioInputController::ErrorCode error_code) override;
-  void OnData(media::AudioInputController* controller,
-              const media::AudioBus* data) override;
   void OnLog(media::AudioInputController* controller,
              const std::string& message) override {}
 
+  // AudioInputController::SyncWriter methods.
+  void Write(const media::AudioBus* data,
+             double volume,
+             bool key_pressed,
+             uint32_t hardware_delay_bytes) override;
+  void Close() override;
+
   // SpeechRecognitionEngineDelegate methods.
   void OnSpeechRecognitionEngineResults(
       const SpeechRecognitionResults& results) override;
diff --git a/content/browser/speech/speech_recognizer_impl_unittest.cc b/content/browser/speech/speech_recognizer_impl_unittest.cc
index 62eae102..80b94bc 100644
--- a/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -183,6 +183,12 @@
     CopyPacketToAudioBus();
   }
 
+  void OnData(media::AudioBus* data) {
+    auto* writer =
+        static_cast<AudioInputController::SyncWriter*>(recognizer_.get());
+    writer->Write(data, 0.0, false, 0);
+  }
+
  protected:
   TestBrowserThreadBundle thread_bundle_;
   scoped_refptr<SpeechRecognizerImpl> recognizer_;
@@ -247,7 +253,7 @@
   // full recording to complete.
   const size_t kNumChunks = 5;
   for (size_t i = 0; i < kNumChunks; ++i) {
-    controller->event_handler()->OnData(controller, audio_bus_.get());
+    OnData(audio_bus_.get());
     base::RunLoop().RunUntilIdle();
     net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
     ASSERT_TRUE(fetcher);
@@ -302,7 +308,7 @@
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
-  controller->event_handler()->OnData(controller, audio_bus_.get());
+  OnData(audio_bus_.get());
   base::RunLoop().RunUntilIdle();
   recognizer_->AbortRecognition();
   base::RunLoop().RunUntilIdle();
@@ -323,7 +329,7 @@
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
-  controller->event_handler()->OnData(controller, audio_bus_.get());
+  OnData(audio_bus_.get());
   base::RunLoop().RunUntilIdle();
   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
@@ -359,7 +365,7 @@
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
-  controller->event_handler()->OnData(controller, audio_bus_.get());
+  OnData(audio_bus_.get());
   base::RunLoop().RunUntilIdle();
   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
   ASSERT_TRUE(fetcher);
@@ -412,7 +418,7 @@
   TestAudioInputController* controller =
       audio_input_controller_factory_.controller();
   ASSERT_TRUE(controller);
-  controller->event_handler()->OnData(controller, audio_bus_.get());
+  OnData(audio_bus_.get());
   controller->event_handler()->OnError(controller,
       AudioInputController::UNKNOWN_ERROR);
   base::RunLoop().RunUntilIdle();
@@ -438,7 +444,7 @@
                      SpeechRecognitionEngine::kAudioPacketIntervalMs + 1;
   // The vector is already filled with zero value samples on create.
   for (int i = 0; i < num_packets; ++i) {
-    controller->event_handler()->OnData(controller, audio_bus_.get());
+    OnData(audio_bus_.get());
   }
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(recognition_started_);
@@ -467,12 +473,12 @@
 
   // The vector is already filled with zero value samples on create.
   for (int i = 0; i < num_packets / 2; ++i) {
-    controller->event_handler()->OnData(controller, audio_bus_.get());
+    OnData(audio_bus_.get());
   }
 
   FillPacketWithTestWaveform();
   for (int i = 0; i < num_packets / 2; ++i) {
-    controller->event_handler()->OnData(controller, audio_bus_.get());
+    OnData(audio_bus_.get());
   }
 
   base::RunLoop().RunUntilIdle();
@@ -504,18 +510,18 @@
                     SpeechRecognitionEngine::kAudioPacketIntervalMs;
   FillPacketWithNoise();
   for (int i = 0; i < num_packets; ++i) {
-    controller->event_handler()->OnData(controller, audio_bus_.get());
+    OnData(audio_bus_.get());
   }
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(-1.0f, volume_);  // No audio volume set yet.
 
   // The vector is already filled with zero value samples on create.
-  controller->event_handler()->OnData(controller, audio_bus_.get());
+  OnData(audio_bus_.get());
   base::RunLoop().RunUntilIdle();
   EXPECT_FLOAT_EQ(0.74939233f, volume_);
 
   FillPacketWithTestWaveform();
-  controller->event_handler()->OnData(controller, audio_bus_.get());
+  OnData(audio_bus_.get());
   base::RunLoop().RunUntilIdle();
   EXPECT_NEAR(0.89926866f, volume_, 0.00001f);
   EXPECT_FLOAT_EQ(0.75071919f, noise_volume_);
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
index 68f011f..3686e85 100644
--- a/content/browser/tracing/tracing_controller_impl.cc
+++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -30,7 +30,7 @@
 #include "content/public/common/content_switches.h"
 #include "gpu/config/gpu_info.h"
 #include "net/base/network_change_notifier.h"
-#include "v8/include/v8.h"
+#include "v8/include/v8-version-string.h"
 
 #if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \
     defined(OS_MACOSX)
@@ -115,7 +115,7 @@
 
   metadata_dict->SetString("network-type", GetNetworkTypeString());
   metadata_dict->SetString("product-version", GetContentClient()->GetProduct());
-  metadata_dict->SetString("v8-version", v8::V8::GetVersion());
+  metadata_dict->SetString("v8-version", V8_VERSION_STRING);
   metadata_dict->SetString("user-agent", GetContentClient()->GetUserAgent());
 
   // OS
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 36bb9a6..b7a055c 100644
--- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -23,6 +23,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
+#include "media/audio/audio_manager.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/perf/perf_test.h"
 
@@ -579,6 +580,31 @@
             ExecuteJavascriptAndReturnResult(call));
 }
 
+#if defined(OS_ANDROID)
+// Disabled until http://crbug.com/679302 is fixed.
+#define MAYBE_GetUserMediaFailToAccessAudioDevice \
+    DISABLED_GetUserMediaFailToAccessAudioDevice
+#else
+#define MAYBE_GetUserMediaFailToAccessAudioDevice \
+    GetUserMediaFailToAccessAudioDevice
+#endif
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+                       MAYBE_GetUserMediaFailToAccessAudioDevice) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+  NavigateToURL(shell(), url);
+
+  // Set the maximum allowed input and output streams to 0
+  // so that the call to create a new audio input stream will fail.
+  media::AudioManager::Get()->SetMaxStreamCountForTesting(0, 0);
+
+  const std::string call = base::StringPrintf(
+      "%s({video: false, audio: true});", kGetUserMediaAndExpectFailure);
+  EXPECT_EQ("TrackStartError",
+            ExecuteJavascriptAndReturnResult(call));
+}
+
 // This test makes two getUserMedia requests, one with impossible constraints
 // that should trigger an error, and one with valid constraints. The test
 // verifies getUserMedia can succeed after being given impossible constraints.
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
index 3be984a..8c94e7a5 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -145,14 +145,15 @@
 // rid of the entire check, and run SubscribeToNotifications on all
 // platforms.
 //
+// TODO(http://crbug.com/633191): Remove OS_MACOSX from this check.
 // TODO(http://crbug.com/636270): Remove OS_WIN from this check.
-#if defined(OS_WIN)
+#if defined(OS_MACOSX) || defined(OS_WIN)
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(&BluetoothRemoteGattCharacteristic::OnStartNotifySessionError,
                  GetWeakPtr(), error_callback,
                  BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
-#else   // defined(OS_WIN))
+#else   // !(defined(OS_MACOSX) || defined(OS_WIN))
   // Find the Client Characteristic Configuration descriptor.
   std::vector<BluetoothRemoteGattDescriptor*> ccc_descriptor =
       GetDescriptorsByUUID(BluetoothRemoteGattDescriptor::
@@ -182,7 +183,7 @@
           GetWeakPtr(), callback),
       base::Bind(&BluetoothRemoteGattCharacteristic::OnStartNotifySessionError,
                  GetWeakPtr(), error_callback));
-#endif  // defined(OS_WIN)
+#endif  // defined(OS_MACOSX) || defined(OS_WIN)
 }
 
 void BluetoothRemoteGattCharacteristic::CancelStartNotifySession(
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
index 4132f8e..c690aea 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
@@ -48,6 +48,10 @@
   std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
   BluetoothRemoteGattDescriptor* GetDescriptor(
       const std::string& identifier) const override;
+  void StartNotifySession(const NotifySessionCallback& callback,
+                          const ErrorCallback& error_callback) override;
+  void StopNotifySession(BluetoothGattNotifySession* session,
+                         const base::Closure& callback) override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -122,8 +126,9 @@
   std::pair<ValueCallback, ErrorCallback> read_characteristic_value_callbacks_;
   // WriteRemoteCharacteristic request callbacks.
   std::pair<base::Closure, ErrorCallback> write_characteristic_value_callbacks_;
-  // Stores SubscribeToNotifications request callbacks.
-  typedef std::pair<base::Closure, const ErrorCallback> PendingStartNotifyCall;
+  // Stores StartNotifySession request callbacks.
+  typedef std::pair<NotifySessionCallback, ErrorCallback>
+      PendingStartNotifyCall;
   std::vector<PendingStartNotifyCall> start_notify_session_callbacks_;
   // Flag indicates if GATT event registration is in progress.
   bool start_notifications_in_progress_;
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
index c5b2b14a..c04df6a 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
@@ -150,6 +150,50 @@
       searched_pair->second.get());
 }
 
+void BluetoothRemoteGattCharacteristicMac::StartNotifySession(
+    const NotifySessionCallback& callback,
+    const ErrorCallback& error_callback) {
+  if (IsNotifying()) {
+    VLOG(2) << "Already notifying. Creating notify session.";
+    std::unique_ptr<BluetoothGattNotifySession> notify_session(
+        new BluetoothGattNotifySession(weak_ptr_factory_.GetWeakPtr()));
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::Bind(callback, base::Passed(std::move(notify_session))));
+    return;
+  }
+
+  if (!SupportsNotificationsOrIndications()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::Bind(error_callback,
+                   BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
+    return;
+  }
+
+  start_notify_session_callbacks_.push_back(
+      std::make_pair(callback, error_callback));
+
+  if (start_notifications_in_progress_) {
+    VLOG(2) << "Start Notifications already in progress. "
+            << "Request has been queued.";
+    return;
+  }
+
+  [GetCBPeripheral() setNotifyValue:YES
+                  forCharacteristic:cb_characteristic_.get()];
+  start_notifications_in_progress_ = true;
+}
+
+void BluetoothRemoteGattCharacteristicMac::StopNotifySession(
+    BluetoothGattNotifySession* session,
+    const base::Closure& callback) {
+  // TODO(http://crbug.com/633191): Remove this method and use the base version.
+  //   Instead, we should implement SubscribeToNotifications and
+  //   UnsubscribeFromNotifications.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+}
+
 void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
@@ -212,34 +256,8 @@
     BluetoothRemoteGattDescriptor* ccc_descriptor,
     const base::Closure& callback,
     const ErrorCallback& error_callback) {
-  if (IsNotifying()) {
-    VLOG(2) << "Already notifying. Creating notify session.";
-    std::unique_ptr<BluetoothGattNotifySession> notify_session(
-        new BluetoothGattNotifySession(weak_ptr_factory_.GetWeakPtr()));
-    callback.Run();
-    return;
-  }
-
-  if (!SupportsNotificationsOrIndications()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::Bind(error_callback,
-                   BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
-    return;
-  }
-
-  start_notify_session_callbacks_.push_back(
-      std::make_pair(callback, error_callback));
-
-  if (start_notifications_in_progress_) {
-    VLOG(2) << "Start Notifications already in progress. "
-            << "Request has been queued.";
-    return;
-  }
-
-  [GetCBPeripheral() setNotifyValue:YES
-                  forCharacteristic:cb_characteristic_.get()];
-  start_notifications_in_progress_ = true;
+  // TODO(http://crbug.com/633191): Implement this method
+  NOTIMPLEMENTED();
 }
 
 void BluetoothRemoteGattCharacteristicMac::UnsubscribeFromNotifications(
@@ -318,7 +336,8 @@
 
 void BluetoothRemoteGattCharacteristicMac::DidUpdateNotificationState(
     NSError* error) {
-  std::vector<PendingStartNotifyCall> reentrant_safe_callbacks;
+  std::vector<std::pair<NotifySessionCallback, ErrorCallback>>
+      reentrant_safe_callbacks;
   reentrant_safe_callbacks.swap(start_notify_session_callbacks_);
   start_notifications_in_progress_ = false;
   if (error) {
@@ -335,7 +354,8 @@
     return;
   }
   for (const auto& callback : reentrant_safe_callbacks) {
-    callback.first.Run();
+    callback.first.Run(base::MakeUnique<BluetoothGattNotifySession>(
+        weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
diff --git a/docs/layout_tests_linux.md b/docs/layout_tests_linux.md
index b1c57e4..1dfd168 100644
--- a/docs/layout_tests_linux.md
+++ b/docs/layout_tests_linux.md
@@ -40,27 +40,6 @@
 
     sudo apt-get remove totem-mozilla
 
-
-## Running layout tests under valgrind on Linux
-
-As above, but use `tools/valgrind/chrome_tests.sh -t webkit` instead.  e.g.
-
-    sh tools/valgrind/chrome_tests.sh -t webkit LayoutTests/fast/
-
-This defaults to using --debug.  Read the script for more details.
-
-If you're trying to reproduce a run from the valgrind buildbot, look for the
-`--run_chunk=XX:YY` line in the bot's log. You can rerun exactly as the bot did
-with the commands.
-
-```shell
-cd ~/chromium/src
-echo XX > valgrind_layout_chunk.txt
-sh tools/valgrind/chrome_tests.sh -t layout -n YY
-```
-
-That will run the XXth chunk of YY layout tests.
-
 ## Configuration tips
 
 *   Use an optimized `content_shell` when rebaselining or running a lot of
diff --git a/docs/linux_debugging.md b/docs/linux_debugging.md
index 3f53fc3..c26a2271 100644
--- a/docs/linux_debugging.md
+++ b/docs/linux_debugging.md
@@ -411,29 +411,6 @@
 up to date. In case this file reference goes out of date, try looking for usage
 of macros like `IPC_MESSAGE_LOG_ENABLED` or `IPC_MESSAGE_MACROS_LOG_ENABLED`.
 
-## Using valgrind
-
-To run valgrind on the browser and renderer processes, with our suppression file
-and flags:
-
-    $ cd $CHROMIUM_ROOT/src
-    $ tools/valgrind/valgrind.sh out/Debug/chrome
-
-You can use valgrind on chrome and/or on the renderers e.g
-`valgrind --smc-check=all ../sconsbuild/Debug/chrome`
-or by passing valgrind as the argument to `--render-cmd-prefix`.
-
-Beware that there are several valgrind "false positives" e.g. pickle, sqlite and
-some instances in webkit that are ignorable. On systems with prelink and address
-space randomization (e.g. Fedora), you may also see valgrind errors in libstdc++
-on startup and in gnome-breakpad.
-
-Valgrind doesn't seem to play nice with tcmalloc. To disable tcmalloc set the GN arg:
-
-    use_allocator="none"
-
-and rebuild.
-
 ## Profiling
 
 See
diff --git a/docs/linux_profiling.md b/docs/linux_profiling.md
index 4d9ce0f..694e4e9 100644
--- a/docs/linux_profiling.md
+++ b/docs/linux_profiling.md
@@ -161,37 +161,6 @@
 For further information, please refer to
 http://google-perftools.googlecode.com/svn/trunk/doc/heapprofile.html.
 
-### Massif
-
-[Massif](http://valgrind.org/docs/manual/mc-manual.html) is a
-[Valgrind](https://www.chromium.org/developers/how-tos/using-valgrind)-based heap
-profiler. It is much slower than the heap profiler from google-perftools, but it
-may have some advantages. (In particular, it handles the multi-process
-executables well).
-
-First, you will need to build massif from valgrind-variant project yourself,
-it's [easy](http://code.google.com/p/valgrind-variant/wiki/HowTo).
-
-Then, make sure your Chromium is built using the
-[valgrind instructions](https://www.chromium.org/developers/how-tos/using-valgrind).
-Now, you can run massif like this:
-
-```
-path-to-valgrind-variant/valgrind/inst/bin/valgrind \
-   --fullpath-after=/chromium/src/ \
-   --trace-children-skip=*npviewer*,/bin/uname,/bin/sh,/usr/bin/which,/bin/ps,/bin/grep,/usr/bin/linux32 \
-   --trace-children=yes \
-   --tool=massif \
-   out/Release/chrome --noerrdialogs --disable-hang-monitor --other-chrome-flags
-```
-
-The result will be stored in massif.out.PID files, which you can post-process
-with [ms_print](http://valgrind.org/docs/manual/mc-manual.html).
-
-TODO(kcc) sometimes when closing a tab the main process kills the tab process
-before massif completes writing it's log file. Need a flag that tells the main
-process to wait longer.
-
 ## Paint profiling
 
 You can use Xephyr to profile how chrome repaints the screen. Xephyr is a
diff --git a/google_apis/gcm/engine/connection_event_tracker.cc b/google_apis/gcm/engine/connection_event_tracker.cc
index 50a5ecdcc..f2be7c8 100644
--- a/google_apis/gcm/engine/connection_event_tracker.cc
+++ b/google_apis/gcm/engine/connection_event_tracker.cc
@@ -25,6 +25,10 @@
                             completed_events_.size(), kMaxClientEvents + 1);
 }
 
+bool ConnectionEventTracker::IsEventInProgress() const {
+  return current_event_.has_time_connection_started_ms();
+}
+
 void ConnectionEventTracker::StartConnectionAttempt() {
   // TODO(harkness): Can we dcheck here that there is not an in progress
   // connection?
@@ -36,14 +40,15 @@
 }
 
 void ConnectionEventTracker::EndConnectionAttempt() {
-  // TODO(harkness): Modify tests so that we can put a DCHECK here.
+  DCHECK(IsEventInProgress());
+
   if (completed_events_.size() == kMaxClientEvents) {
     // Don't let the completed events grow beyond the max.
     completed_events_.pop_front();
     number_discarded_events_++;
   }
 
-  // Current event is now completed, so add it to our list of completed events.
+  // Current event is finished, so add it to our list of completed events.
   current_event_.set_time_connection_ended_ms(base::Time::Now().ToJavaTime());
   completed_events_.push_back(current_event_);
   current_event_.Clear();
diff --git a/google_apis/gcm/engine/connection_event_tracker.h b/google_apis/gcm/engine/connection_event_tracker.h
index 2e18273..6c3a54d 100644
--- a/google_apis/gcm/engine/connection_event_tracker.h
+++ b/google_apis/gcm/engine/connection_event_tracker.h
@@ -22,6 +22,9 @@
   ConnectionEventTracker();
   ~ConnectionEventTracker();
 
+  // Returns a boolean indicating whether an attempt is currently in progress.
+  bool IsEventInProgress() const;
+
   // Start recording a new connection attempt. This should never be called if
   // a connection attempt is already ongoing.
   void StartConnectionAttempt();
diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc
index 2d459f2..1eba5809 100644
--- a/google_apis/gcm/engine/connection_factory_impl.cc
+++ b/google_apis/gcm/engine/connection_factory_impl.cc
@@ -209,9 +209,14 @@
     // connection.
   }
 
-  if (reason == LOGIN_FAILURE)
-    event_tracker_.ConnectionLoginFailed();
-  event_tracker_.EndConnectionAttempt();
+  // SignalConnectionReset can be called at any time without regard to whether
+  // a connection attempt is currently in progress. Only notify the event
+  // tracker if there is an event in progress.
+  if (event_tracker_.IsEventInProgress()) {
+    if (reason == LOGIN_FAILURE)
+      event_tracker_.ConnectionLoginFailed();
+    event_tracker_.EndConnectionAttempt();
+  }
 
   CloseSocket();
   DCHECK(!IsEndpointReachable());
diff --git a/google_apis/gcm/engine/connection_factory_impl_unittest.cc b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
index 3d0f52b3..ed91e4b 100644
--- a/google_apis/gcm/engine/connection_factory_impl_unittest.cc
+++ b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
@@ -602,7 +602,7 @@
   // There should be one failed client event for each failed connection, but
   // there is a maximum cap of kMaxClientEvents, which is 30. There should also
   // be a single event which records the events which were discarded.
-  const auto client_events = GetClientEvents();
+  auto client_events = GetClientEvents();
   ASSERT_EQ(31, client_events.size());
 
   bool found_discarded_events = false;
@@ -626,8 +626,21 @@
   EXPECT_TRUE(connected_server().is_valid());
 
   // Old client events should have been reset after the successful connection.
-  const auto new_client_events = GetClientEvents();
-  ASSERT_EQ(0, new_client_events.size());
+  client_events = GetClientEvents();
+  ASSERT_EQ(0, client_events.size());
+
+  // Test that EndConnectionAttempt doesn't write empty events to the tracker.
+  // There should be 2 events: 1) the successful connection which was previously
+  // established. 2) the unsuccessful connection triggered as a result of the
+  // SOCKET_FAILURE signal. The NETWORK_CHANGE signal should not cause an
+  // additional event since there is no in progress event.
+  factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
+  factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
+  factory()->SignalConnectionReset(ConnectionFactory::NETWORK_CHANGE);
+  WaitForConnections();
+
+  client_events = GetClientEvents();
+  ASSERT_EQ(2, client_events.size());
 }
 
 }  // namespace gcm
diff --git a/ios/chrome/browser/browser_state/BUILD.gn b/ios/chrome/browser/browser_state/BUILD.gn
index fdb46c5..adfa6b7 100644
--- a/ios/chrome/browser/browser_state/BUILD.gn
+++ b/ios/chrome/browser/browser_state/BUILD.gn
@@ -8,11 +8,13 @@
     "browser_state_otr_helper.h",
     "chrome_browser_state.h",
     "chrome_browser_state.mm",
+    "chrome_browser_state_manager.h",
   ]
   deps = [
     "//base",
     "//components/prefs",
     "//components/sync_preferences",
+    "//ios/chrome/browser/tabs",
     "//ios/web",
     "//net",
   ]
@@ -35,7 +37,6 @@
     "chrome_browser_state_impl_io_data.mm",
     "chrome_browser_state_io_data.cc",
     "chrome_browser_state_io_data.h",
-    "chrome_browser_state_manager.h",
     "chrome_browser_state_manager_impl.cc",
     "chrome_browser_state_manager_impl.h",
     "chrome_browser_state_removal_controller.h",
diff --git a/ios/chrome/browser/browser_state_metrics/BUILD.gn b/ios/chrome/browser/browser_state_metrics/BUILD.gn
index 1993bb75..5c6756b 100644
--- a/ios/chrome/browser/browser_state_metrics/BUILD.gn
+++ b/ios/chrome/browser/browser_state_metrics/BUILD.gn
@@ -9,5 +9,6 @@
   ]
   deps = [
     "//components/profile_metrics",
+    "//ios/chrome/browser/browser_state",
   ]
 }
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn
index cfccc2c..cc28d43 100644
--- a/ios/chrome/browser/metrics/BUILD.gn
+++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -48,7 +48,7 @@
     "//ios/chrome/browser/google",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/sync",
-    "//ios/chrome/browser/ui:browser_list",
+    "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/variations",
     "//ios/chrome/browser/variations:ios_chrome_ui_string_overrider_factory",
     "//ios/chrome/common",
@@ -101,7 +101,6 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
-    "//ios/chrome/browser/ui:browser_list",
     "//ios/web",
     "//ui/base",
     "//url",
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
index 3fbd9cc3..bb7b2128 100644
--- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
+++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
@@ -51,7 +51,7 @@
 #include "ios/chrome/browser/signin/ios_chrome_signin_status_metrics_provider_delegate.h"
 #include "ios/chrome/browser/sync/ios_chrome_sync_client.h"
 #include "ios/chrome/browser/tab_parenting_global_observer.h"
-#include "ios/chrome/browser/ui/browser_list_ios.h"
+#include "ios/chrome/browser/tabs/tab_model_list.h"
 #include "ios/chrome/common/channel_info.h"
 #include "ios/web/public/web_thread.h"
 
@@ -193,7 +193,7 @@
   // be worth revisiting this to still log events from non-incognito sessions.
   metrics_service_->RegisterMetricsProvider(
       base::MakeUnique<OmniboxMetricsProvider>(
-          base::Bind(&BrowserListIOS::IsOffTheRecordSessionActive)));
+          base::Bind(&::IsOffTheRecordSessionActive)));
 
   {
     auto stability_metrics_provider =
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
index d528c47..9d4cf92 100644
--- a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
+++ b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
@@ -16,7 +16,7 @@
 #include "ios/chrome/browser/chrome_switches.h"
 #include "ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h"
 #include "ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h"
-#include "ios/chrome/browser/ui/browser_list_ios.h"
+#include "ios/chrome/browser/tabs/tab_model_list.h"
 #include "ios/chrome/browser/variations/ios_chrome_variations_service_client.h"
 #include "ios/chrome/browser/variations/ios_ui_string_overrider_factory.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
@@ -63,7 +63,7 @@
 IOSChromeMetricsServicesManagerClient::CreateRapporServiceImpl() {
   DCHECK(thread_checker_.CalledOnValidThread());
   return base::MakeUnique<rappor::RapporServiceImpl>(
-      local_state_, base::Bind(&BrowserListIOS::IsOffTheRecordSessionActive));
+      local_state_, base::Bind(&::IsOffTheRecordSessionActive));
 }
 
 std::unique_ptr<variations::VariationsService>
diff --git a/ios/chrome/browser/metrics/new_tab_page_uma.mm b/ios/chrome/browser/metrics/new_tab_page_uma.mm
index 48fe6db..47375cc 100644
--- a/ios/chrome/browser/metrics/new_tab_page_uma.mm
+++ b/ios/chrome/browser/metrics/new_tab_page_uma.mm
@@ -10,16 +10,15 @@
 #include "ios/chrome/browser/chrome_url_constants.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/ui/browser_list_ios.h"
+#import "ios/chrome/browser/tabs/tab_model_list.h"
 #include "url/gurl.h"
 
 namespace new_tab_page_uma {
 
 bool IsCurrentlyOnNTP(ios::ChromeBrowserState* browserState) {
-  Tab* currentTab =
-      [[BrowserListIOS::GetLastActiveWithBrowserState(browserState) tabModel]
-          currentTab];
-  return currentTab && currentTab.url == GURL(kChromeUINewTabURL);
+  TabModel* tabModel = GetLastActiveTabModelForChromeBrowserState(browserState);
+  return tabModel.currentTab &&
+         tabModel.currentTab.url == GURL(kChromeUINewTabURL);
 }
 
 void RecordAction(ios::ChromeBrowserState* browserState, ActionType type) {
diff --git a/ios/chrome/browser/omaha/BUILD.gn b/ios/chrome/browser/omaha/BUILD.gn
index b21d3e9..8d5eb217 100644
--- a/ios/chrome/browser/omaha/BUILD.gn
+++ b/ios/chrome/browser/omaha/BUILD.gn
@@ -15,7 +15,7 @@
     "//components/profile_metrics",
     "//components/version_info",
     "//ios/chrome/browser",
-    "//ios/chrome/browser/browser_state:browser_state_impl",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/browser_state_metrics",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/upgrade",
diff --git a/ios/chrome/browser/payments/payment_request_manager.mm b/ios/chrome/browser/payments/payment_request_manager.mm
index b3565d7..0673ad7 100644
--- a/ios/chrome/browser/payments/payment_request_manager.mm
+++ b/ios/chrome/browser/payments/payment_request_manager.mm
@@ -203,10 +203,12 @@
 }
 
 - (void)initializeWebViewForPaymentRequest {
-  DCHECK(_webStateEnabled);
+  if (_enabled) {
+    DCHECK(_webStateEnabled);
 
-  [_paymentRequestJsManager inject];
-  _isScriptInjected = YES;
+    [_paymentRequestJsManager inject];
+    _isScriptInjected = YES;
+  }
 }
 
 - (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand {
@@ -319,10 +321,10 @@
 - (void)webState:(web::WebState*)webState
     didCommitNavigationWithDetails:
         (const web::LoadCommittedDetails&)load_details {
-  _isScriptInjected = NO;
   [self dismissUI];
-  [self initializeWebViewForPaymentRequest];
+  _isScriptInjected = NO;
   [self enableCurrentWebState];
+  [self initializeWebViewForPaymentRequest];
 }
 
 @end
diff --git a/ios/chrome/browser/reading_list/offline_url_utils.cc b/ios/chrome/browser/reading_list/offline_url_utils.cc
index 5ce022c..22d93421 100644
--- a/ios/chrome/browser/reading_list/offline_url_utils.cc
+++ b/ios/chrome/browser/reading_list/offline_url_utils.cc
@@ -66,27 +66,4 @@
 bool IsOfflineURL(const GURL& url) {
   return url.SchemeIs(kChromeUIScheme) && url.host() == kChromeUIOfflineHost;
 }
-
-base::string16 StripSchemeFromOnlineURL(const base::string16& online_url,
-                                        size_t* removed_chars) {
-  base::string16 https_scheme = base::UTF8ToUTF16(base::StringPrintf(
-      "%s%s", url::kHttpsScheme, url::kStandardSchemeSeparator));
-  if (base::StartsWith(online_url, https_scheme,
-                       base::CompareCase::SENSITIVE)) {
-    if (removed_chars) {
-      *removed_chars = https_scheme.length();
-    }
-    return online_url.substr(https_scheme.length());
-  }
-  // http:// scheme should already have been trimmed at this point.
-  // DCHECK to detect formatting changes in omnibox.
-  DCHECK(!base::StartsWith(
-      online_url, base::UTF8ToUTF16(base::StringPrintf(
-                      "%s%s", url::kHttpScheme, url::kStandardSchemeSeparator)),
-      base::CompareCase::SENSITIVE));
-  if (removed_chars) {
-    *removed_chars = 0;
-  }
-  return online_url;
-}
 }
diff --git a/ios/chrome/browser/reading_list/offline_url_utils.h b/ios/chrome/browser/reading_list/offline_url_utils.h
index 1904840..c2c0dcc 100644
--- a/ios/chrome/browser/reading_list/offline_url_utils.h
+++ b/ios/chrome/browser/reading_list/offline_url_utils.h
@@ -31,13 +31,6 @@
 // Returns whether the URL points to a chrome offline URL.
 bool IsOfflineURL(const GURL& url);
 
-// Strips scheme from the original URL of the offline page. This is meant to be
-// used by UI.
-// If |removed_chars| is non-NULL, it is set to the number of chars that have
-// been removed at the begining of |online_url|.
-base::string16 StripSchemeFromOnlineURL(const base::string16& online_url,
-                                        size_t* removed_chars);
-
 }  // namespace reading_list
 
 #endif  // IOS_CHROME_BROWSER_READING_LIST_OFFLINE_URL_UTILS_H_
diff --git a/ios/chrome/browser/reading_list/offline_url_utils_unittest.cc b/ios/chrome/browser/reading_list/offline_url_utils_unittest.cc
index 3f794d3..e8b5ee2 100644
--- a/ios/chrome/browser/reading_list/offline_url_utils_unittest.cc
+++ b/ios/chrome/browser/reading_list/offline_url_utils_unittest.cc
@@ -84,34 +84,3 @@
       reading_list::IsOfflineURL(GURL("chrome://offline/foobar?foo=bar")));
 }
 
-// Checks that https:// scheme is correctly removed by
-// StripSchemeFromOnlineURLTest.
-TEST(OfflineURLUtilsTest, StripSchemeFromOnlineURLTest) {
-  size_t removed_size;
-  base::string16 empty_url;
-  EXPECT_EQ(reading_list::StripSchemeFromOnlineURL(empty_url, &removed_size),
-            empty_url);
-  EXPECT_EQ(removed_size, 0u);
-
-  base::string16 https_url = base::UTF8ToUTF16("https://www.chromium.org/");
-  base::string16 trimmed_https_url = base::UTF8ToUTF16("www.chromium.org/");
-  EXPECT_EQ(reading_list::StripSchemeFromOnlineURL(https_url, &removed_size),
-            trimmed_https_url);
-  EXPECT_EQ(removed_size, 8u);
-  base::string16 http_url = base::UTF8ToUTF16("http://www.chromium.org/");
-  EXPECT_DCHECK_DEATH(
-      reading_list::StripSchemeFromOnlineURL(http_url, &removed_size));
-
-  base::string16 other_scheme_url =
-      base::UTF8ToUTF16("scheme://www.chromium.org/");
-  EXPECT_EQ(
-      reading_list::StripSchemeFromOnlineURL(other_scheme_url, &removed_size),
-      other_scheme_url);
-  EXPECT_EQ(removed_size, 0u);
-
-  base::string16 no_scheme_url = base::UTF8ToUTF16("www.chromium.org/");
-  EXPECT_EQ(
-      reading_list::StripSchemeFromOnlineURL(no_scheme_url, &removed_size),
-      no_scheme_url);
-  EXPECT_EQ(removed_size, 0u);
-}
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.cc b/ios/chrome/browser/reading_list/reading_list_download_service.cc
index 07bddca..f3337a7 100644
--- a/ios/chrome/browser/reading_list/reading_list_download_service.cc
+++ b/ios/chrome/browser/reading_list/reading_list_download_service.cc
@@ -94,7 +94,8 @@
 
 void ReadingListDownloadService::ReadingListDidAddEntry(
     const ReadingListModel* model,
-    const GURL& url) {
+    const GURL& url,
+    reading_list::EntrySource source) {
   DCHECK_EQ(reading_list_model_, model);
   ProcessNewEntry(url);
 }
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.h b/ios/chrome/browser/reading_list/reading_list_download_service.h
index 55adb74..27cfed8c 100644
--- a/ios/chrome/browser/reading_list/reading_list_download_service.h
+++ b/ios/chrome/browser/reading_list/reading_list_download_service.h
@@ -58,7 +58,8 @@
   void ReadingListWillRemoveEntry(const ReadingListModel* model,
                                   const GURL& url) override;
   void ReadingListDidAddEntry(const ReadingListModel* model,
-                              const GURL& url) override;
+                              const GURL& url,
+                              reading_list::EntrySource entry_source) override;
   void ReadingListDidMoveEntry(const ReadingListModel* model,
                                const GURL& url) override;
 
diff --git a/ios/chrome/browser/reading_list/reading_list_web_state_observer_unittest.mm b/ios/chrome/browser/reading_list/reading_list_web_state_observer_unittest.mm
index 45c0e45..4f30e28 100644
--- a/ios/chrome/browser/reading_list/reading_list_web_state_observer_unittest.mm
+++ b/ios/chrome/browser/reading_list/reading_list_web_state_observer_unittest.mm
@@ -56,7 +56,8 @@
     test_web_state_.SetNavigationManager(std::move(test_navigation_manager));
     reading_list_model_ =
         base::MakeUnique<ReadingListModelImpl>(nullptr, nullptr);
-    reading_list_model_->AddEntry(GURL(kTestURL), kTestTitle);
+    reading_list_model_->AddEntry(GURL(kTestURL), kTestTitle,
+                                  reading_list::ADDED_VIA_CURRENT_APP);
     ReadingListWebStateObserver::FromWebState(&test_web_state_,
                                               reading_list_model_.get());
   }
diff --git a/ios/chrome/browser/sessions/BUILD.gn b/ios/chrome/browser/sessions/BUILD.gn
index a3d954c..cf8b95d 100644
--- a/ios/chrome/browser/sessions/BUILD.gn
+++ b/ios/chrome/browser/sessions/BUILD.gn
@@ -19,7 +19,6 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/tabs",
-    "//ios/chrome/browser/ui:browser_list",
     "//ios/public/provider/chrome/browser",
     "//ios/web",
     "//url",
@@ -52,7 +51,6 @@
     "//components/sessions",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/tabs",
-    "//ios/chrome/browser/ui:browser_list",
     "//ios/web",
     "//net",
   ]
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
index 3856953..f8f47ec 100644
--- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
@@ -4,15 +4,18 @@
 
 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h"
 
+#include "base/bind.h"
+#include "base/callback.h"
 #include "components/sessions/ios/ios_live_tab.h"
+#include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h"
 #include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h"
-#include "ios/chrome/browser/tabs/tab.h"
-#include "ios/chrome/browser/tabs/tab_model.h"
-#include "ios/chrome/browser/ui/browser_ios.h"
-#include "ios/chrome/browser/ui/browser_list_ios.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/tabs/tab_model_list.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #include "ios/web/public/web_thread.h"
 #include "url/gurl.h"
@@ -21,6 +24,45 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+sessions::LiveTabContext* FindLiveTabContextWithCondition(
+    const base::Callback<bool(TabModel*)>& condition) {
+  std::vector<ios::ChromeBrowserState*> browser_states =
+      GetApplicationContext()
+          ->GetChromeBrowserStateManager()
+          ->GetLoadedBrowserStates();
+
+  for (ios::ChromeBrowserState* browser_state : browser_states) {
+    DCHECK(!browser_state->IsOffTheRecord());
+    NSArray<TabModel*>* tab_models;
+
+    tab_models = GetTabModelsForChromeBrowserState(browser_state);
+    for (TabModel* tab_model : tab_models) {
+      if (condition.Run(tab_model)) {
+        return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState(
+            browser_state);
+      }
+    }
+
+    if (!browser_state->HasOffTheRecordChromeBrowserState())
+      continue;
+
+    ios::ChromeBrowserState* otr_browser_state =
+        browser_state->GetOffTheRecordChromeBrowserState();
+
+    tab_models = GetTabModelsForChromeBrowserState(otr_browser_state);
+    for (TabModel* tab_model : tab_models) {
+      if (condition.Run(tab_model)) {
+        return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState(
+            browser_state);
+      }
+    }
+  }
+
+  return nullptr;
+}
+}  // namespace
+
 IOSChromeTabRestoreServiceClient::IOSChromeTabRestoreServiceClient(
     ios::ChromeBrowserState* browser_state)
     : browser_state_(browser_state) {}
@@ -39,32 +81,27 @@
     const sessions::LiveTab* tab) {
   const sessions::IOSLiveTab* requested_tab =
       static_cast<const sessions::IOSLiveTab*>(tab);
-  for (BrowserListIOS::const_iterator iter = BrowserListIOS::begin();
-       iter != BrowserListIOS::end(); ++iter) {
-    id<BrowserIOS> browser = *iter;
-    for (Tab* current_tab in [browser tabModel]) {
-      if (current_tab.webState &&
-          current_tab.webState == requested_tab->web_state()) {
-        return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState(
-            [browser browserState]);
-      }
-    }
-  }
-  return nullptr;
+
+  return FindLiveTabContextWithCondition(base::Bind(
+      [](const web::WebState* web_state, TabModel* tab_model) {
+        for (Tab* current_tab in tab_model) {
+          if (current_tab.webState && current_tab.webState == web_state) {
+            return true;
+          }
+        }
+        return false;
+      },
+      requested_tab->web_state()));
 }
 
 sessions::LiveTabContext*
 IOSChromeTabRestoreServiceClient::FindLiveTabContextWithID(
     SessionID::id_type desired_id) {
-  for (BrowserListIOS::const_iterator iter = BrowserListIOS::begin();
-       iter != BrowserListIOS::end(); ++iter) {
-    id<BrowserIOS> browser = *iter;
-    if ([browser tabModel].sessionID.id() == desired_id) {
-      return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState(
-          [browser browserState]);
-    }
-  }
-  return nullptr;
+  return FindLiveTabContextWithCondition(base::Bind(
+      [](SessionID::id_type desired_id, TabModel* tab_model) {
+        return tab_model.sessionID.id() == desired_id;
+      },
+      desired_id));
 }
 
 bool IOSChromeTabRestoreServiceClient::ShouldTrackURLForRestore(
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm
index 160bdd4f..ce78267 100644
--- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm
+++ b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm
@@ -14,8 +14,7 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
-#include "ios/chrome/browser/ui/browser_ios.h"
-#include "ios/chrome/browser/ui/browser_list_ios.h"
+#import "ios/chrome/browser/tabs/tab_model_list.h"
 #import "ios/web/navigation/navigation_manager_impl.h"
 #include "ios/web/public/navigation_item.h"
 #import "ios/web/web_state/web_state_impl.h"
@@ -30,9 +29,7 @@
 TabRestoreServiceDelegateImplIOS::~TabRestoreServiceDelegateImplIOS() {}
 
 TabModel* TabRestoreServiceDelegateImplIOS::tab_model() const {
-  id<BrowserIOS> browser =
-      BrowserListIOS::GetLastActiveWithBrowserState(browser_state_);
-  return [browser tabModel];
+  return GetLastActiveTabModelForChromeBrowserState(browser_state_);
 }
 
 void TabRestoreServiceDelegateImplIOS::ShowBrowserWindow() {
diff --git a/ios/chrome/browser/share_extension/share_extension_item_receiver.mm b/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
index 3b615ec..2a2d88a 100644
--- a/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
+++ b/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
@@ -214,8 +214,9 @@
                                      [entryType integerValue]);
                              if (type == app_group::READING_LIST_ITEM) {
                                LogHistogramReceivedItem(READINGLIST_ENTRY);
-                               _readingListModel->AddEntry(entryURL,
-                                                           entryTitle);
+                               _readingListModel->AddEntry(
+                                   entryURL, entryTitle,
+                                   reading_list::ADDED_VIA_EXTENSION);
                              }
                              if (type == app_group::BOOKMARK_ITEM) {
                                LogHistogramReceivedItem(BOOKMARK_ENTRY);
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index 10bf741..cd740bcd 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -79,8 +79,7 @@
   explicit SyncSessionsClientImpl(ios::ChromeBrowserState* browser_state)
       : browser_state_(browser_state),
         window_delegates_getter_(
-            base::MakeUnique<TabModelSyncedWindowDelegatesGetter>(
-                browser_state)) {}
+            base::MakeUnique<TabModelSyncedWindowDelegatesGetter>()) {}
 
   ~SyncSessionsClientImpl() override {}
 
@@ -138,7 +137,8 @@
 
 IOSChromeSyncClient::IOSChromeSyncClient(ios::ChromeBrowserState* browser_state)
     : browser_state_(browser_state),
-      sync_sessions_client_(new SyncSessionsClientImpl(browser_state)),
+      sync_sessions_client_(
+          base::MakeUnique<SyncSessionsClientImpl>(browser_state)),
       weak_ptr_factory_(this) {}
 
 IOSChromeSyncClient::~IOSChromeSyncClient() {}
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index e667fd4d..8a5b6e5 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -89,7 +89,6 @@
     "//ios/chrome/browser/translate",
     "//ios/chrome/browser/u2f",
     "//ios/chrome/browser/ui",
-    "//ios/chrome/browser/ui:browser_list",
     "//ios/chrome/browser/ui:ui_internal",
     "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/commands",
@@ -123,6 +122,7 @@
   deps = [
     ":tabs",
     "//base",
+    "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
   ]
   libs = [ "Foundation.framework" ]
diff --git a/ios/chrome/browser/tabs/tab_model_list.h b/ios/chrome/browser/tabs/tab_model_list.h
index bbba490..806fbc9 100644
--- a/ios/chrome/browser/tabs/tab_model_list.h
+++ b/ios/chrome/browser/tabs/tab_model_list.h
@@ -34,4 +34,12 @@
 NSArray<TabModel*>* GetTabModelsForChromeBrowserState(
     ios::ChromeBrowserState* browser_state);
 
+// Returns the last active TabModel associated with |browser_state|.
+TabModel* GetLastActiveTabModelForChromeBrowserState(
+    ios::ChromeBrowserState* browser_state);
+
+// Returns true if a incognito session is currently active (i.e. at least
+// one incognito tab is open).
+bool IsOffTheRecordSessionActive();
+
 #endif  // IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_
diff --git a/ios/chrome/browser/tabs/tab_model_list.mm b/ios/chrome/browser/tabs/tab_model_list.mm
index b9562232..eba1a08 100644
--- a/ios/chrome/browser/tabs/tab_model_list.mm
+++ b/ios/chrome/browser/tabs/tab_model_list.mm
@@ -7,7 +7,9 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/supports_user_data.h"
+#include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -85,3 +87,45 @@
       TabModelList::GetForBrowserState(browser_state, false);
   return tab_model_list ? [tab_model_list->tab_models() allObjects] : nil;
 }
+
+TabModel* GetLastActiveTabModelForChromeBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  TabModelList* tab_model_list =
+      TabModelList::GetForBrowserState(browser_state, false);
+  if (!tab_model_list || [tab_model_list->tab_models() count] == 0u)
+    return nil;
+
+  // There is currently no way to mark a TabModel as active. Assert that there
+  // is only one TabModel associated with |browser_state| until it is possible
+  // to mark a TabModel as active.
+  DCHECK_EQ([tab_model_list->tab_models() count], 1u);
+  return [tab_model_list->tab_models() anyObject];
+}
+
+bool IsOffTheRecordSessionActive() {
+  std::vector<ios::ChromeBrowserState*> browser_states =
+      GetApplicationContext()
+          ->GetChromeBrowserStateManager()
+          ->GetLoadedBrowserStates();
+
+  for (ios::ChromeBrowserState* browser_state : browser_states) {
+    DCHECK(!browser_state->IsOffTheRecord());
+    if (!browser_state->HasOffTheRecordChromeBrowserState())
+      continue;
+
+    ios::ChromeBrowserState* otr_browser_state =
+        browser_state->GetOffTheRecordChromeBrowserState();
+
+    TabModelList* tab_model_list =
+        TabModelList::GetForBrowserState(otr_browser_state, false);
+    if (!tab_model_list)
+      continue;
+
+    for (TabModel* tab_model in tab_model_list->tab_models()) {
+      if (![tab_model isEmpty])
+        return true;
+    }
+  }
+
+  return false;
+}
diff --git a/ios/chrome/browser/tabs/tab_model_synced_window_delegate.mm b/ios/chrome/browser/tabs/tab_model_synced_window_delegate.mm
index 9e8701e..1dc244c 100644
--- a/ios/chrome/browser/tabs/tab_model_synced_window_delegate.mm
+++ b/ios/chrome/browser/tabs/tab_model_synced_window_delegate.mm
@@ -11,7 +11,6 @@
 #include "ios/chrome/browser/sync/ios_chrome_synced_tab_delegate.h"
 #include "ios/chrome/browser/tabs/tab.h"
 #include "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/ui/browser_list_ios.h"
 #import "ios/web/public/web_state/web_state.h"
 
 TabModelSyncedWindowDelegate::TabModelSyncedWindowDelegate(TabModel* tab_model)
diff --git a/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h b/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h
index 922dce17..728d144 100644
--- a/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h
+++ b/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h
@@ -15,28 +15,19 @@
 class SyncedWindowDelegate;
 }
 
-namespace ios {
-class ChromeBrowserState;
-}
-
 class TabModelSyncedWindowDelegatesGetter
     : public sync_sessions::SyncedWindowDelegatesGetter {
  public:
-  // TODO(crbug.com/548612): |browser_state| may be unnecessary as iOS does not
-  // supports multi-profile starting with M47. Should it be removed?
-  explicit TabModelSyncedWindowDelegatesGetter(
-      ios::ChromeBrowserState* browser_state);
+  TabModelSyncedWindowDelegatesGetter();
   ~TabModelSyncedWindowDelegatesGetter() override;
 
   // sync_sessions::SyncedWindowDelegatesGetter:
   std::set<const sync_sessions::SyncedWindowDelegate*>
   GetSyncedWindowDelegates() override;
   const sync_sessions::SyncedWindowDelegate* FindById(
-      SessionID::id_type id) override;
+      SessionID::id_type session_id) override;
 
  private:
-  const ios::ChromeBrowserState* const browser_state_;
-
   DISALLOW_COPY_AND_ASSIGN(TabModelSyncedWindowDelegatesGetter);
 };
 
diff --git a/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm b/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm
index 5362854b..df84d972 100644
--- a/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm
+++ b/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm
@@ -4,14 +4,15 @@
 
 #include "ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h"
 
+#include "base/logging.h"
+#include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/tabs/tab_model.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/tabs/tab_model_list.h"
 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
-#import "ios/chrome/browser/ui/browser_list_ios.h"
 
-TabModelSyncedWindowDelegatesGetter::TabModelSyncedWindowDelegatesGetter(
-    ios::ChromeBrowserState* browser_state)
-    : browser_state_(browser_state) {}
+TabModelSyncedWindowDelegatesGetter::TabModelSyncedWindowDelegatesGetter() {}
 
 TabModelSyncedWindowDelegatesGetter::~TabModelSyncedWindowDelegatesGetter() {}
 
@@ -19,18 +20,20 @@
 TabModelSyncedWindowDelegatesGetter::GetSyncedWindowDelegates() {
   std::set<const sync_sessions::SyncedWindowDelegate*> synced_window_delegates;
 
-  for (BrowserListIOS::const_iterator iter = BrowserListIOS::begin();
-       iter != BrowserListIOS::end(); ++iter) {
-    id<BrowserIOS> browser = *iter;
-    TabModel* tabModel = [browser tabModel];
-    // TODO(crbug.com/548612): BrowserState may be unnecessary as iOS does not
-    // support multiple profiles starting with M47. There should still be a way
-    // to filter out Incognito delegates, though.
-    if (tabModel.browserState != browser_state_)
-      continue;
-    // Do not return windows without any tabs, to match desktop.
-    if ([tabModel currentTab])
-      synced_window_delegates.insert([tabModel syncedWindowDelegate]);
+  std::vector<ios::ChromeBrowserState*> browser_states =
+      GetApplicationContext()
+          ->GetChromeBrowserStateManager()
+          ->GetLoadedBrowserStates();
+
+  for (auto* browser_state : browser_states) {
+    DCHECK(!browser_state->IsOffTheRecord());
+    NSArray<TabModel*>* tabModels =
+        GetTabModelsForChromeBrowserState(browser_state);
+    for (TabModel* tabModel in tabModels) {
+      if (tabModel.currentTab) {
+        synced_window_delegates.insert([tabModel syncedWindowDelegate]);
+      }
+    }
   }
 
   return synced_window_delegates;
@@ -38,8 +41,7 @@
 
 const sync_sessions::SyncedWindowDelegate*
 TabModelSyncedWindowDelegatesGetter::FindById(SessionID::id_type session_id) {
-  for (const sync_sessions::SyncedWindowDelegate* delegate :
-       GetSyncedWindowDelegates()) {
+  for (const auto* delegate : GetSyncedWindowDelegates()) {
     if (session_id == delegate->GetSessionId())
       return delegate;
   }
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm
index 4d2e906..dfb7c664 100644
--- a/ios/chrome/browser/tabs/tab_model_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -4,11 +4,13 @@
 
 #import <objc/runtime.h>
 
+#include "base/files/file_path.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #import "ios/chrome/browser/sessions/session_window.h"
@@ -18,6 +20,7 @@
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
 #import "ios/chrome/browser/tabs/tab_private.h"
 #import "ios/chrome/browser/web/chrome_web_client.h"
+#include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
 #import "ios/web/navigation/crw_session_controller.h"
 #import "ios/web/navigation/navigation_manager_impl.h"
 #import "ios/web/public/navigation_manager.h"
@@ -47,17 +50,6 @@
               toDirectory:(NSString*)directory;
 @end
 
-// Trivial objective C class whose unique aim is to be a wrapper of C++
-// classes.
-@interface ClassesWrapper : NSObject {
- @public
-  std::unique_ptr<WebStateImpl> _webStateImpl;
-}
-@end
-
-@implementation ClassesWrapper
-@end
-
 @interface TabTest : Tab
 
 - (instancetype)initWithWindowName:(NSString*)windowName
@@ -81,7 +73,7 @@
     id webControllerMock =
         [OCMockObject niceMockForClass:[CRWWebController class]];
 
-    std::unique_ptr<WebStateImpl> webStateImpl(new WebStateImpl(browserState));
+    auto webStateImpl = base::MakeUnique<WebStateImpl>(browserState);
     webStateImpl->SetWebController(webControllerMock);
     webStateImpl->GetNavigationManagerImpl().InitializeSession(
         windowName, @"opener", NO, -1);
@@ -137,50 +129,48 @@
 
 class TabModelTest : public PlatformTest {
  public:
-  TabModelTest() : web_client_(base::MakeUnique<ChromeWebClient>()) {}
-
- protected:
-  void SetUp() override {
+  TabModelTest()
+      : scoped_browser_state_manager_(
+            base::MakeUnique<TestChromeBrowserStateManager>(base::FilePath())),
+        web_client_(base::MakeUnique<ChromeWebClient>()) {
     DCHECK_CURRENTLY_ON(web::WebThread::UI);
-    PlatformTest::SetUp();
 
     TestChromeBrowserState::Builder test_cbs_builder;
     chrome_browser_state_ = test_cbs_builder.Build();
 
-    sessionWindow_.reset([[SessionWindowIOS alloc] init]);
+    session_window_.reset([[SessionWindowIOS alloc] init]);
     // Create tab model with just a dummy session service so the async state
     // saving doesn't trigger unless actually wanted.
     base::scoped_nsobject<TestSessionService> test_service(
         [[TestSessionService alloc] init]);
-    tabModel_.reset([[TabModel alloc]
-        initWithSessionWindow:sessionWindow_.get()
+    tab_model_.reset([[TabModel alloc]
+        initWithSessionWindow:session_window_.get()
                sessionService:test_service
                  browserState:chrome_browser_state_.get()]);
-    [tabModel_ setWebUsageEnabled:YES];
-    [tabModel_ setPrimary:YES];
-    tabModelObserver_.reset([[TabModelObserverPong alloc] init]);
-    [tabModel_ addObserver:tabModelObserver_];
+    [tab_model_ setWebUsageEnabled:YES];
+    [tab_model_ setPrimary:YES];
+    tab_model_observer_.reset([[TabModelObserverPong alloc] init]);
+    [tab_model_ addObserver:tab_model_observer_];
   }
 
-  void TearDown() override {
-    [tabModel_ removeObserver:tabModelObserver_];
-    [tabModel_ browserStateDestroyed];
-    PlatformTest::TearDown();
+  ~TabModelTest() override {
+    [tab_model_ removeObserver:tab_model_observer_];
+    [tab_model_ browserStateDestroyed];
   }
 
+ protected:
   Tab* CreateTab(NSString* windowName,
                  double lastVisitedTimestamp) NS_RETURNS_RETAINED {
     return [[TabTest alloc] initWithWindowName:windowName
                           lastVisitedTimestamp:lastVisitedTimestamp
                                   browserState:chrome_browser_state_.get()
-                                      tabModel:tabModel_.get()];
+                                      tabModel:tab_model_.get()];
   }
 
   std::unique_ptr<WebStateImpl> CreateWebState(NSString* windowName,
                                                NSString* opener,
                                                NSInteger index) {
-    std::unique_ptr<WebStateImpl> webState(
-        new WebStateImpl(chrome_browser_state_.get()));
+    auto webState = base::MakeUnique<WebStateImpl>(chrome_browser_state_.get());
     webState->GetNavigationManagerImpl().InitializeSession(windowName, opener,
                                                            NO, index);
     return webState;
@@ -195,7 +185,7 @@
   }
 
   void RestoreSession(SessionWindowIOS* window) {
-    [tabModel_ restoreSessionWindow:window];
+    [tab_model_ restoreSessionWindow:window];
   }
 
   // Creates a session window with |entries| entries and a |selectedIndex| of 1.
@@ -211,370 +201,371 @@
   }
 
   web::TestWebThreadBundle thread_bundle_;
+  IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
   web::ScopedTestingWebClient web_client_;
-  base::scoped_nsobject<SessionWindowIOS> sessionWindow_;
+  base::scoped_nsobject<SessionWindowIOS> session_window_;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  base::scoped_nsobject<TabModel> tabModel_;
-  base::scoped_nsobject<TabModelObserverPong> tabModelObserver_;
+  base::scoped_nsobject<TabModel> tab_model_;
+  base::scoped_nsobject<TabModelObserverPong> tab_model_observer_;
   base::mac::ScopedNSAutoreleasePool pool_;
 };
 
 TEST_F(TabModelTest, IsEmpty) {
-  EXPECT_EQ([tabModel_ count], 0U);
-  EXPECT_TRUE([tabModel_ isEmpty]);
-  [tabModel_ insertTabWithURL:kURL
-                     referrer:kReferrer
-                   windowName:@"window 1"
-                       opener:nil
-                      atIndex:0];
-  ASSERT_EQ(1U, [tabModel_ count]);
-  EXPECT_FALSE([tabModel_ isEmpty]);
+  EXPECT_EQ([tab_model_ count], 0U);
+  EXPECT_TRUE([tab_model_ isEmpty]);
+  [tab_model_ insertTabWithURL:kURL
+                      referrer:kReferrer
+                    windowName:@"window 1"
+                        opener:nil
+                       atIndex:0];
+  ASSERT_EQ(1U, [tab_model_ count]);
+  EXPECT_FALSE([tab_model_ isEmpty]);
 }
 
 TEST_F(TabModelTest, InsertUrlSingle) {
-  [tabModel_ insertTabWithURL:kURL
-                     referrer:kReferrer
-                   windowName:@"window 1"
-                       opener:nil
-                      atIndex:0];
-  ASSERT_EQ(1U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+  [tab_model_ insertTabWithURL:kURL
+                      referrer:kReferrer
+                    windowName:@"window 1"
+                        opener:nil
+                       atIndex:0];
+  ASSERT_EQ(1U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
 }
 
 TEST_F(TabModelTest, InsertUrlMultiple) {
-  [tabModel_ insertTabWithURL:kURL
-                     referrer:kReferrer
-                   windowName:@"window 1"
-                       opener:nil
-                      atIndex:0];
-  [tabModel_ insertTabWithURL:kURL
-                     referrer:kReferrer
-                   windowName:@"window 2"
-                       opener:nil
-                      atIndex:0];
-  [tabModel_ insertTabWithURL:kURL
-                     referrer:kReferrer
-                   windowName:@"window 3"
-                       opener:nil
-                      atIndex:1];
+  [tab_model_ insertTabWithURL:kURL
+                      referrer:kReferrer
+                    windowName:@"window 1"
+                        opener:nil
+                       atIndex:0];
+  [tab_model_ insertTabWithURL:kURL
+                      referrer:kReferrer
+                    windowName:@"window 2"
+                        opener:nil
+                       atIndex:0];
+  [tab_model_ insertTabWithURL:kURL
+                      referrer:kReferrer
+                    windowName:@"window 3"
+                        opener:nil
+                       atIndex:1];
 
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:2] windowName]);
 }
 
 TEST_F(TabModelTest, AppendUrlSingle) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  ASSERT_EQ(1U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  ASSERT_EQ(1U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
 }
 
 TEST_F(TabModelTest, AppendUrlMultiple) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:2] windowName]);
 }
 
 TEST_F(TabModelTest, CloseTabAtIndexBeginning) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  [tabModel_ closeTabAtIndex:0];
+  [tab_model_ closeTabAtIndex:0];
 
-  ASSERT_EQ(2U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+  ASSERT_EQ(2U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:1] windowName]);
 }
 
 TEST_F(TabModelTest, CloseTabAtIndexMiddle) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  [tabModel_ closeTabAtIndex:1];
+  [tab_model_ closeTabAtIndex:1];
 
-  ASSERT_EQ(2U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
+  ASSERT_EQ(2U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:1] windowName]);
 }
 
 TEST_F(TabModelTest, CloseTabAtIndexLast) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  [tabModel_ closeTabAtIndex:2];
+  [tab_model_ closeTabAtIndex:2];
 
-  ASSERT_EQ(2U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
+  ASSERT_EQ(2U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:1] windowName]);
 }
 
 TEST_F(TabModelTest, CloseTabAtIndexOnlyOne) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
 
-  [tabModel_ closeTabAtIndex:0];
+  [tab_model_ closeTabAtIndex:0];
 
-  EXPECT_EQ(0U, [tabModel_ count]);
+  EXPECT_EQ(0U, [tab_model_ count]);
 }
 
 TEST_F(TabModelTest, RestoreSessionOnNTPTest) {
-  [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
-                     referrer:kEmptyReferrer
-                   windowName:@"old window"
-                       opener:nil
-                      atIndex:0];
+  [tab_model_ insertTabWithURL:GURL(kChromeUINewTabURL)
+                      referrer:kEmptyReferrer
+                    windowName:@"old window"
+                        opener:nil
+                       atIndex:0];
   base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
 
   RestoreSession(window.get());
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ currentTab] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:2] windowName]);
 }
 
 TEST_F(TabModelTest, RestoreSessionOn2NtpTest) {
-  [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
-                     referrer:kEmptyReferrer
-                   windowName:@"old window 1"
-                       opener:nil
-                      atIndex:0];
-  [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
-                     referrer:kEmptyReferrer
-                   windowName:@"old window 2"
-                       opener:nil
-                      atIndex:1];
+  [tab_model_ insertTabWithURL:GURL(kChromeUINewTabURL)
+                      referrer:kEmptyReferrer
+                    windowName:@"old window 1"
+                        opener:nil
+                       atIndex:0];
+  [tab_model_ insertTabWithURL:GURL(kChromeUINewTabURL)
+                      referrer:kEmptyReferrer
+                    windowName:@"old window 2"
+                        opener:nil
+                       atIndex:1];
   base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
 
   RestoreSession(window.get());
-  ASSERT_EQ(5U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
-  EXPECT_NSEQ(@"old window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"old window 2", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:3] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:4] windowName]);
+  ASSERT_EQ(5U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ currentTab] windowName]);
+  EXPECT_NSEQ(@"old window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"old window 2", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:3] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:4] windowName]);
 }
 
 TEST_F(TabModelTest, RestoreSessionOnAnyTest) {
-  [tabModel_ insertTabWithURL:kURL
-                     referrer:kEmptyReferrer
-                   windowName:@"old window 1"
-                       opener:nil
-                      atIndex:0];
+  [tab_model_ insertTabWithURL:kURL
+                      referrer:kEmptyReferrer
+                    windowName:@"old window 1"
+                        opener:nil
+                       atIndex:0];
   base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
 
   RestoreSession(window.get());
-  ASSERT_EQ(4U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
-  EXPECT_NSEQ(@"old window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:3] windowName]);
+  ASSERT_EQ(4U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ currentTab] windowName]);
+  EXPECT_NSEQ(@"old window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:3] windowName]);
 }
 
 TEST_F(TabModelTest, TabForWindowName) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
-                  referrer:kReferrer2
-                windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:GURL("https://www.some.url2.com")
+                   referrer:kReferrer2
+                 windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  Tab* tab = [tabModel_ tabWithWindowName:@"window 2"];
+  Tab* tab = [tab_model_ tabWithWindowName:@"window 2"];
 
   EXPECT_NSEQ([tab windowName], @"window 2");
   EXPECT_EQ(tab.url, GURL("https://www.some.url2.com/"));
 }
 
 TEST_F(TabModelTest, TabForWindowNameNotFound) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
-                  referrer:kReferrer2
-                windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:GURL("https://www.some.url2.com")
+                   referrer:kReferrer2
+                 windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  Tab* tab = [tabModel_ tabWithWindowName:@"window not found"];
+  Tab* tab = [tab_model_ tabWithWindowName:@"window not found"];
 
   EXPECT_EQ(nil, tab);
 }
 
 TEST_F(TabModelTest, CloseAllTabs) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
-                  referrer:kReferrer2
-                windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:GURL("https://www.some.url2.com")
+                   referrer:kReferrer2
+                 windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
-  [tabModel_ closeAllTabs];
+  [tab_model_ closeAllTabs];
 
-  EXPECT_EQ(0U, [tabModel_ count]);
+  EXPECT_EQ(0U, [tab_model_ count]);
 }
 
 TEST_F(TabModelTest, CloseAllTabsWithNoTabs) {
-  [tabModel_ closeAllTabs];
+  [tab_model_ closeAllTabs];
 
-  EXPECT_EQ(0U, [tabModel_ count]);
+  EXPECT_EQ(0U, [tab_model_ count]);
 }
 
 TEST_F(TabModelTest, InsertWithSessionController) {
-  EXPECT_EQ([tabModel_ count], 0U);
-  EXPECT_TRUE([tabModel_ isEmpty]);
+  EXPECT_EQ([tab_model_ count], 0U);
+  EXPECT_TRUE([tab_model_ isEmpty]);
 
   Tab* new_tab =
-      [tabModel_ insertTabWithWebState:CreateWebState(@"window", @"opener", -1)
-                               atIndex:0];
-  EXPECT_EQ([tabModel_ count], 1U);
-  [tabModel_ setCurrentTab:new_tab];
-  Tab* current_tab = [tabModel_ currentTab];
+      [tab_model_ insertTabWithWebState:CreateWebState(@"window", @"opener", -1)
+                                atIndex:0];
+  EXPECT_EQ([tab_model_ count], 1U);
+  [tab_model_ setCurrentTab:new_tab];
+  Tab* current_tab = [tab_model_ currentTab];
   EXPECT_TRUE(current_tab);
 }
 
 TEST_F(TabModelTest, OpenerOfTab) {
   // Start off with a couple tabs.
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
   // Create parent tab.
-  Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                             atIndex:[tabModel_ count]];
+  Tab* parent_tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                              atIndex:[tab_model_ count]];
   // Create child tab.
   Tab* child_tab =
-      [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
-                               atIndex:[tabModel_ count]];
+      [tab_model_ insertTabWithWebState:CreateChildWebState(parent_tab)
+                                atIndex:[tab_model_ count]];
   // Create another unrelated tab.
-  Tab* another_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                              atIndex:[tabModel_ count]];
+  Tab* another_tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                               atIndex:[tab_model_ count]];
 
   // Create another child of the first tab.
   Tab* child_tab2 =
-      [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
-                               atIndex:[tabModel_ count]];
+      [tab_model_ insertTabWithWebState:CreateChildWebState(parent_tab)
+                                atIndex:[tab_model_ count]];
 
-  EXPECT_FALSE([tabModel_ openerOfTab:parent_tab]);
-  EXPECT_FALSE([tabModel_ openerOfTab:another_tab]);
-  EXPECT_EQ(parent_tab, [tabModel_ openerOfTab:child_tab]);
-  EXPECT_EQ(parent_tab, [tabModel_ openerOfTab:child_tab2]);
+  EXPECT_FALSE([tab_model_ openerOfTab:parent_tab]);
+  EXPECT_FALSE([tab_model_ openerOfTab:another_tab]);
+  EXPECT_EQ(parent_tab, [tab_model_ openerOfTab:child_tab]);
+  EXPECT_EQ(parent_tab, [tab_model_ openerOfTab:child_tab2]);
 }
 
 TEST_F(TabModelTest, OpenerOfTabEmptyModel) {
-  EXPECT_FALSE([tabModel_ openerOfTab:nil]);
+  EXPECT_FALSE([tab_model_ openerOfTab:nil]);
 }
 
 TEST_F(TabModelTest, OpenersEmptyModel) {
   // Empty model.
-  EXPECT_TRUE([tabModel_ isEmpty]);
-  EXPECT_FALSE([tabModel_ nextTabWithOpener:nil afterTab:nil]);
-  EXPECT_FALSE([tabModel_ lastTabWithOpener:nil]);
-  EXPECT_FALSE([tabModel_ firstTabWithOpener:nil]);
+  EXPECT_TRUE([tab_model_ isEmpty]);
+  EXPECT_FALSE([tab_model_ nextTabWithOpener:nil afterTab:nil]);
+  EXPECT_FALSE([tab_model_ lastTabWithOpener:nil]);
+  EXPECT_FALSE([tab_model_ firstTabWithOpener:nil]);
 }
 
 TEST_F(TabModelTest, OpenersNothingOpenedGeneral) {
   // Start with a few tabs.
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
-  Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                      atIndex:[tabModel_ count]];
+  Tab* tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                       atIndex:[tab_model_ count]];
 
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
   // All should fail since this hasn't opened anything else.
-  EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
-  EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
-  EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ nextTabWithOpener:tab afterTab:nil]);
+  EXPECT_FALSE([tab_model_ lastTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ firstTabWithOpener:tab]);
 
   // Add more items to the tab, expect the same results.
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
-  EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
-  EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  EXPECT_FALSE([tab_model_ nextTabWithOpener:tab afterTab:nil]);
+  EXPECT_FALSE([tab_model_ lastTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ firstTabWithOpener:tab]);
 }
 
 TEST_F(TabModelTest, OpenersNothingOpenedFirst) {
   // Our tab is first.
-  Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                      atIndex:[tabModel_ count]];
+  Tab* tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                       atIndex:[tab_model_ count]];
 
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
   // All should fail since this hasn't opened anything else.
-  EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
-  EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
-  EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ nextTabWithOpener:tab afterTab:nil]);
+  EXPECT_FALSE([tab_model_ lastTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ firstTabWithOpener:tab]);
 }
 
 TEST_F(TabModelTest, OpenersNothingOpenedLast) {
   // Our tab is last.
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                      atIndex:[tabModel_ count]];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  Tab* tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                       atIndex:[tab_model_ count]];
 
   // All should fail since this hasn't opened anything else.
-  EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
-  EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
-  EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ nextTabWithOpener:tab afterTab:nil]);
+  EXPECT_FALSE([tab_model_ lastTabWithOpener:tab]);
+  EXPECT_FALSE([tab_model_ firstTabWithOpener:tab]);
 }
 
 TEST_F(TabModelTest, OpenersChildTabBeforeOpener) {
-  Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                             atIndex:[tabModel_ count]];
+  Tab* parent_tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                              atIndex:[tab_model_ count]];
   // Insert child at start
   Tab* child_tab =
-      [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
-                               atIndex:0];
+      [tab_model_ insertTabWithWebState:CreateChildWebState(parent_tab)
+                                atIndex:0];
 
   // Insert a few more between them.
-  [tabModel_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
-  [tabModel_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
+  [tab_model_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
+  [tab_model_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
 
-  EXPECT_FALSE([tabModel_ nextTabWithOpener:parent_tab afterTab:nil]);
-  EXPECT_FALSE([tabModel_ lastTabWithOpener:parent_tab]);
-  EXPECT_EQ([tabModel_ firstTabWithOpener:parent_tab], child_tab);
+  EXPECT_FALSE([tab_model_ nextTabWithOpener:parent_tab afterTab:nil]);
+  EXPECT_FALSE([tab_model_ lastTabWithOpener:parent_tab]);
+  EXPECT_EQ([tab_model_ firstTabWithOpener:parent_tab], child_tab);
 }
 
 TEST_F(TabModelTest, OpenersChildTabAfterOpener) {
-  Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
-                                             atIndex:[tabModel_ count]];
+  Tab* parent_tab = [tab_model_ insertTabWithWebState:CreateWebState(@"window")
+                                              atIndex:[tab_model_ count]];
 
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
   // Insert two children at end.
   Tab* child_tab1 =
-      [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
-                               atIndex:[tabModel_ count]];
+      [tab_model_ insertTabWithWebState:CreateChildWebState(parent_tab)
+                                atIndex:[tab_model_ count]];
   Tab* child_tab2 =
-      [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
-                               atIndex:[tabModel_ count]];
+      [tab_model_ insertTabWithWebState:CreateChildWebState(parent_tab)
+                                atIndex:[tab_model_ count]];
 
-  EXPECT_EQ([tabModel_ nextTabWithOpener:parent_tab afterTab:nil], child_tab1);
-  EXPECT_EQ([tabModel_ nextTabWithOpener:parent_tab afterTab:child_tab1],
+  EXPECT_EQ([tab_model_ nextTabWithOpener:parent_tab afterTab:nil], child_tab1);
+  EXPECT_EQ([tab_model_ nextTabWithOpener:parent_tab afterTab:child_tab1],
             child_tab2);
-  EXPECT_EQ([tabModel_ lastTabWithOpener:parent_tab], child_tab2);
-  EXPECT_FALSE([tabModel_ firstTabWithOpener:parent_tab]);
+  EXPECT_EQ([tab_model_ lastTabWithOpener:parent_tab], child_tab2);
+  EXPECT_FALSE([tab_model_ firstTabWithOpener:parent_tab]);
 }
 
 TEST_F(TabModelTest, AddWithOrderController) {
   // Create a few tabs with the controller at the front.
   Tab* parent =
-      [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+      [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
   // Add a new tab, it should be added behind the parent.
-  Tab* child = [tabModel_
+  Tab* child = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -583,11 +574,11 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
-  EXPECT_EQ([tabModel_ indexOfTab:child], 1U);
+  EXPECT_EQ([tab_model_ indexOfTab:parent], 0U);
+  EXPECT_EQ([tab_model_ indexOfTab:child], 1U);
 
   // Add another new tab without a parent, should go at the end.
-  Tab* tab = [tabModel_
+  Tab* tab = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -596,21 +587,21 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:tab], [tabModel_ count] - 1);
+  EXPECT_EQ([tab_model_ indexOfTab:tab], [tab_model_ count] - 1);
 
   // Same for a tab that's not opened via a LINK transition.
-  Tab* tab2 = [tabModel_ insertOrUpdateTabWithURL:kURL
-                                         referrer:kEmptyReferrer
-                                       transition:ui::PAGE_TRANSITION_TYPED
-                                       windowName:nil
-                                           opener:nil
-                                      openedByDOM:NO
-                                          atIndex:[tabModel_ count]
-                                     inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:tab2], [tabModel_ count] - 1);
+  Tab* tab2 = [tab_model_ insertOrUpdateTabWithURL:kURL
+                                          referrer:kEmptyReferrer
+                                        transition:ui::PAGE_TRANSITION_TYPED
+                                        windowName:nil
+                                            opener:nil
+                                       openedByDOM:NO
+                                           atIndex:[tab_model_ count]
+                                      inBackground:NO];
+  EXPECT_EQ([tab_model_ indexOfTab:tab2], [tab_model_ count] - 1);
 
   // Add a tab in the background. It should appear behind the opening tab.
-  Tab* tab3 = [tabModel_
+  Tab* tab3 = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -619,10 +610,10 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:YES];
-  EXPECT_EQ([tabModel_ indexOfTab:tab3], [tabModel_ indexOfTab:tab] + 1);
+  EXPECT_EQ([tab_model_ indexOfTab:tab3], [tab_model_ indexOfTab:tab] + 1);
 
   // Add another background tab behind the one we just opened.
-  Tab* tab4 = [tabModel_
+  Tab* tab4 = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -631,23 +622,23 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:YES];
-  EXPECT_EQ([tabModel_ indexOfTab:tab4], [tabModel_ indexOfTab:tab3] + 1);
+  EXPECT_EQ([tab_model_ indexOfTab:tab4], [tab_model_ indexOfTab:tab3] + 1);
 }
 
 TEST_F(TabModelTest, AddWithOrderControllerAndGrouping) {
   // Create a few tabs with the controller at the front.
   Tab* parent =
-      [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+      [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
   // Force the history to update, as it is used to determine grouping.
   ASSERT_TRUE([parent navigationManager]);
   [[parent navigationManager]->GetSessionController() commitPendingEntry];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
   ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
 
   // Add a new tab, it should be added behind the parent.
-  Tab* child1 = [tabModel_
+  Tab* child1 = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -656,12 +647,12 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
-  EXPECT_EQ([tabModel_ indexOfTab:child1], 1U);
+  EXPECT_EQ([tab_model_ indexOfTab:parent], 0U);
+  EXPECT_EQ([tab_model_ indexOfTab:child1], 1U);
 
   // Add a second child tab in the background. It should be added behind the
   // first child.
-  Tab* child2 = [tabModel_
+  Tab* child2 = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -670,7 +661,7 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:YES];
-  EXPECT_EQ([tabModel_ indexOfTab:child2], 2U);
+  EXPECT_EQ([tab_model_ indexOfTab:child2], 2U);
 
   // Navigate the parent tab to a new URL.  It should not change any ordering.
   web::NavigationManager::WebLoadParams parent_params(
@@ -679,11 +670,11 @@
   [[parent webController] loadWithParams:parent_params];
   ASSERT_TRUE([parent navigationManager]);
   [[parent navigationManager]->GetSessionController() commitPendingEntry];
-  EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
+  EXPECT_EQ([tab_model_ indexOfTab:parent], 0U);
 
   // Add a new tab. It should be added behind the parent. It should not be added
   // after the previous two children.
-  Tab* child3 = [tabModel_
+  Tab* child3 = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -692,11 +683,11 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:child3], 1U);
+  EXPECT_EQ([tab_model_ indexOfTab:child3], 1U);
 
   // Add a fourt child tab in the background. It should be added behind the
   // third child.
-  Tab* child4 = [tabModel_
+  Tab* child4 = [tab_model_
       insertOrUpdateTabWithURL:kURL
                       referrer:kEmptyReferrer
                     transition:ui::PAGE_TRANSITION_LINK
@@ -705,128 +696,128 @@
                    openedByDOM:NO
                        atIndex:TabModelConstants::kTabPositionAutomatically
                   inBackground:YES];
-  EXPECT_EQ([tabModel_ indexOfTab:child4], 2U);
+  EXPECT_EQ([tab_model_ indexOfTab:child4], 2U);
 
   // The first two children should have been moved to the right.
-  EXPECT_EQ([tabModel_ indexOfTab:child1], 3U);
-  EXPECT_EQ([tabModel_ indexOfTab:child2], 4U);
+  EXPECT_EQ([tab_model_ indexOfTab:child1], 3U);
+  EXPECT_EQ([tab_model_ indexOfTab:child2], 4U);
 
   // Now add a non-owned tab and make sure it is added at the end.
   Tab* nonChild =
-      [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  EXPECT_EQ([tabModel_ indexOfTab:nonChild], [tabModel_ count] - 1);
+      [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  EXPECT_EQ([tab_model_ indexOfTab:nonChild], [tab_model_ count] - 1);
 }
 
 TEST_F(TabModelTest, AddWithLinkTransitionAndIndex) {
   // Create a few tabs with the controller at the front.
   Tab* parent =
-      [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+      [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
   // Force the history to update, as it is used to determine grouping.
   ASSERT_TRUE([parent navigationManager]);
   [[parent navigationManager]->GetSessionController() commitPendingEntry];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
-  [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
+  [tab_model_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
 
   ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
 
   // Add a new tab, it should be added before the parent since the index
   // parameter has been specified with a valid value.
-  Tab* child1 = [tabModel_ insertOrUpdateTabWithURL:kURL
-                                           referrer:kEmptyReferrer
-                                         transition:ui::PAGE_TRANSITION_LINK
-                                         windowName:nil
-                                             opener:parent
-                                        openedByDOM:NO
-                                            atIndex:0
-                                       inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:parent], 1U);
-  EXPECT_EQ([tabModel_ indexOfTab:child1], 0U);
+  Tab* child1 = [tab_model_ insertOrUpdateTabWithURL:kURL
+                                            referrer:kEmptyReferrer
+                                          transition:ui::PAGE_TRANSITION_LINK
+                                          windowName:nil
+                                              opener:parent
+                                         openedByDOM:NO
+                                             atIndex:0
+                                        inBackground:NO];
+  EXPECT_EQ([tab_model_ indexOfTab:parent], 1U);
+  EXPECT_EQ([tab_model_ indexOfTab:child1], 0U);
 
   // Add a new tab, it should be added at the beginning of the stack because
   // the index parameter has been specified with a valid value.
-  Tab* child2 = [tabModel_ insertOrUpdateTabWithURL:kURL
-                                           referrer:kEmptyReferrer
-                                         transition:ui::PAGE_TRANSITION_LINK
-                                         windowName:nil
-                                             opener:parent
-                                        openedByDOM:NO
-                                            atIndex:0
-                                       inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:parent], 2U);
-  EXPECT_EQ([tabModel_ indexOfTab:child1], 1U);
-  EXPECT_EQ([tabModel_ indexOfTab:child2], 0U);
+  Tab* child2 = [tab_model_ insertOrUpdateTabWithURL:kURL
+                                            referrer:kEmptyReferrer
+                                          transition:ui::PAGE_TRANSITION_LINK
+                                          windowName:nil
+                                              opener:parent
+                                         openedByDOM:NO
+                                             atIndex:0
+                                        inBackground:NO];
+  EXPECT_EQ([tab_model_ indexOfTab:parent], 2U);
+  EXPECT_EQ([tab_model_ indexOfTab:child1], 1U);
+  EXPECT_EQ([tab_model_ indexOfTab:child2], 0U);
 
   // Add a new tab, it should be added at position 1 because the index parameter
   // has been specified with a valid value.
-  Tab* child3 = [tabModel_ insertOrUpdateTabWithURL:kURL
-                                           referrer:kEmptyReferrer
-                                         transition:ui::PAGE_TRANSITION_LINK
-                                         windowName:nil
-                                             opener:parent
-                                        openedByDOM:NO
-                                            atIndex:1
-                                       inBackground:NO];
-  EXPECT_EQ([tabModel_ indexOfTab:parent], 3U);
-  EXPECT_EQ([tabModel_ indexOfTab:child1], 2U);
-  EXPECT_EQ([tabModel_ indexOfTab:child3], 1U);
-  EXPECT_EQ([tabModel_ indexOfTab:child2], 0U);
+  Tab* child3 = [tab_model_ insertOrUpdateTabWithURL:kURL
+                                            referrer:kEmptyReferrer
+                                          transition:ui::PAGE_TRANSITION_LINK
+                                          windowName:nil
+                                              opener:parent
+                                         openedByDOM:NO
+                                             atIndex:1
+                                        inBackground:NO];
+  EXPECT_EQ([tab_model_ indexOfTab:parent], 3U);
+  EXPECT_EQ([tab_model_ indexOfTab:child1], 2U);
+  EXPECT_EQ([tab_model_ indexOfTab:child3], 1U);
+  EXPECT_EQ([tab_model_ indexOfTab:child2], 0U);
 }
 
 TEST_F(TabModelTest, MoveTabs) {
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
-  [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
+  [tab_model_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
 
   // Basic sanity checks before moving on.
-  ASSERT_EQ(3U, [tabModel_ count]);
-  ASSERT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
-  ASSERT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
-  ASSERT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
+  ASSERT_EQ(3U, [tab_model_ count]);
+  ASSERT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:0] windowName]);
+  ASSERT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:1] windowName]);
+  ASSERT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:2] windowName]);
 
   // Move a tab from index 1 to index 0 (move tab left by one).
-  [tabModelObserver_ setTabMovedWasCalled:NO];
-  [tabModel_ moveTab:[tabModel_ tabAtIndex:1] toIndex:0];
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+  [tab_model_observer_ setTabMovedWasCalled:NO];
+  [tab_model_ moveTab:[tab_model_ tabAtIndex:1] toIndex:0];
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_TRUE([tab_model_observer_ tabMovedWasCalled]);
 
   // Move a tab from index 1 to index 2 (move tab right by one).
-  [tabModelObserver_ setTabMovedWasCalled:NO];
-  [tabModel_ moveTab:[tabModel_ tabAtIndex:1] toIndex:2];
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+  [tab_model_observer_ setTabMovedWasCalled:NO];
+  [tab_model_ moveTab:[tab_model_ tabAtIndex:1] toIndex:2];
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_TRUE([tab_model_observer_ tabMovedWasCalled]);
 
   // Move a tab from index 0 to index 2 (move tab right by more than one).
-  [tabModelObserver_ setTabMovedWasCalled:NO];
-  [tabModel_ moveTab:[tabModel_ tabAtIndex:0] toIndex:2];
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+  [tab_model_observer_ setTabMovedWasCalled:NO];
+  [tab_model_ moveTab:[tab_model_ tabAtIndex:0] toIndex:2];
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_TRUE([tab_model_observer_ tabMovedWasCalled]);
 
   // Move a tab from index 2 to index 0 (move tab left by more than one).
-  [tabModelObserver_ setTabMovedWasCalled:NO];
-  [tabModel_ moveTab:[tabModel_ tabAtIndex:2] toIndex:0];
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
+  [tab_model_observer_ setTabMovedWasCalled:NO];
+  [tab_model_ moveTab:[tab_model_ tabAtIndex:2] toIndex:0];
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_TRUE([tab_model_observer_ tabMovedWasCalled]);
 
   // Move a tab from index 2 to index 2 (move tab to the same index).
-  [tabModelObserver_ setTabMovedWasCalled:NO];
-  [tabModel_ moveTab:[tabModel_ tabAtIndex:2] toIndex:2];
-  ASSERT_EQ(3U, [tabModel_ count]);
-  EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
-  EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
-  EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
-  EXPECT_FALSE([tabModelObserver_ tabMovedWasCalled]);
+  [tab_model_observer_ setTabMovedWasCalled:NO];
+  [tab_model_ moveTab:[tab_model_ tabAtIndex:2] toIndex:2];
+  ASSERT_EQ(3U, [tab_model_ count]);
+  EXPECT_NSEQ(@"window 2", [[tab_model_ tabAtIndex:0] windowName]);
+  EXPECT_NSEQ(@"window 3", [[tab_model_ tabAtIndex:1] windowName]);
+  EXPECT_NSEQ(@"window 1", [[tab_model_ tabAtIndex:2] windowName]);
+  EXPECT_FALSE([tab_model_observer_ tabMovedWasCalled]);
 }
 
 TEST_F(TabModelTest, SetParentModel) {
@@ -838,20 +829,23 @@
               browserState:chrome_browser_state_.get()
                   tabModel:nil]);
   EXPECT_TRUE([tab parentTabModel] == nil);
-  [tabModel_ insertTab:tab atIndex:0];
-  [tab setParentTabModel:tabModel_.get()];
+  [tab_model_ insertTab:tab atIndex:0];
+  [tab setParentTabModel:tab_model_.get()];
   EXPECT_FALSE([tab parentTabModel] == nil);
-  [tabModel_ closeTabAtIndex:0];
+  [tab_model_ closeTabAtIndex:0];
 }
 
 TEST_F(TabModelTest, PersistSelectionChange) {
+  TestChromeBrowserState::Builder test_cbs_builder;
+  auto chrome_browser_state = test_cbs_builder.Build();
+
   NSString* stashPath =
-      base::SysUTF8ToNSString(chrome_browser_state_->GetStatePath().value());
+      base::SysUTF8ToNSString(chrome_browser_state->GetStatePath().value());
 
   base::scoped_nsobject<TabModel> model([[TabModel alloc]
-      initWithSessionWindow:sessionWindow_.get()
+      initWithSessionWindow:session_window_.get()
              sessionService:[SessionServiceIOS sharedService]
-               browserState:chrome_browser_state_.get()]);
+               browserState:chrome_browser_state.get()]);
 
   [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
   [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
@@ -869,7 +863,7 @@
   base::RunLoop().RunUntilIdle();
 
   SessionWindowIOS* sessionWindow = [[SessionServiceIOS sharedService]
-      loadWindowForBrowserState:chrome_browser_state_.get()];
+      loadWindowForBrowserState:chrome_browser_state.get()];
 
   // Create tab model from saved session.
   base::scoped_nsobject<TestSessionService> test_service(
@@ -878,7 +872,7 @@
   model.reset([[TabModel alloc]
       initWithSessionWindow:sessionWindow
              sessionService:test_service
-               browserState:chrome_browser_state_.get()]);
+               browserState:chrome_browser_state.get()]);
   EXPECT_EQ(model.get().currentTab, [model tabAtIndex:1]);
   [model browserStateDestroyed];
 
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm
index 9ae72de..0b10e80 100644
--- a/ios/chrome/browser/tabs/tab_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/callback.h"
+#include "base/files/file_path.h"
 #include "base/ios/block_types.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/memory/ptr_util.h"
@@ -19,6 +20,7 @@
 #include "components/keyed_service/core/service_access_type.h"
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
 #import "ios/chrome/browser/chrome_url_util.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
 #import "ios/chrome/browser/tabs/tab.h"
@@ -29,6 +31,7 @@
 #import "ios/chrome/browser/web/external_app_launcher.h"
 #include "ios/chrome/test/block_cleanup_test.h"
 #include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_provider.h"
+#include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
 #include "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
 #import "ios/public/provider/chrome/browser/native_app_launcher/fake_native_app_metadata.h"
 #import "ios/public/provider/chrome/browser/native_app_launcher/fake_native_app_whitelist_manager.h"
@@ -160,7 +163,11 @@
 
 class TabTest : public BlockCleanupTest {
  public:
-  TabTest() : thread_bundle_(web::TestWebThreadBundle::REAL_FILE_THREAD) {}
+  TabTest()
+      : thread_bundle_(web::TestWebThreadBundle::REAL_FILE_THREAD),
+        scoped_browser_state_manager_(
+            base::MakeUnique<TestChromeBrowserStateManager>(base::FilePath())) {
+  }
 
   void SetUp() override {
     BlockCleanupTest::SetUp();
@@ -310,7 +317,7 @@
 
  protected:
   web::TestWebThreadBundle thread_bundle_;
-  IOSChromeScopedTestingLocalState local_state_;
+  IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
   base::scoped_nsobject<Tab> tab_;
   history::HistoryService* history_service_;  // weak
@@ -549,10 +556,4 @@
   EXPECT_FALSE([metadata shouldAutoOpenLinks]);
 }
 
-class TestRequestGroupID : public BlockCleanupTest {
- public:
-  void SetUp() override { BlockCleanupTest::SetUp(); }
-  void TearDown() override { BlockCleanupTest::TearDown(); }
-};
-
 }  // namespace
diff --git a/ios/chrome/browser/test/perf_test_with_bvc_ios.h b/ios/chrome/browser/test/perf_test_with_bvc_ios.h
index 6ddb4a1..492f337 100644
--- a/ios/chrome/browser/test/perf_test_with_bvc_ios.h
+++ b/ios/chrome/browser/test/perf_test_with_bvc_ios.h
@@ -13,7 +13,7 @@
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/test/base/perf_test_ios.h"
 #include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_provider.h"
-#include "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
+#include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
 #include "ios/web/public/test/scoped_testing_web_client.h"
 
 @class BrowserViewController;
@@ -47,7 +47,7 @@
 
   web::ScopedTestingWebClient web_client_;
   IOSChromeScopedTestingChromeBrowserProvider provider_;
-  IOSChromeScopedTestingLocalState local_state_;
+  IOSChromeScopedTestingChromeBrowserStateManager browser_state_manager_;
 
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
   std::unique_ptr<TestChromeBrowserState> incognito_chrome_browser_state_;
diff --git a/ios/chrome/browser/test/perf_test_with_bvc_ios.mm b/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
index d0886cf6..546efc3 100644
--- a/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
+++ b/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
@@ -6,11 +6,13 @@
 
 #import <UIKit/UIKit.h>
 
+#include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "ios/chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
 #import "ios/chrome/browser/sessions/session_service.h"
 #import "ios/chrome/browser/sessions/session_window.h"
@@ -66,7 +68,9 @@
     : PerfTest(testGroup),
       slow_teardown_(false),
       web_client_(base::MakeUnique<ChromeWebClient>()),
-      provider_(ios::CreateChromeBrowserProvider()) {}
+      provider_(ios::CreateChromeBrowserProvider()),
+      browser_state_manager_(
+          base::MakeUnique<TestChromeBrowserStateManager>(base::FilePath())) {}
 
 PerfTestWithBVC::PerfTestWithBVC(std::string testGroup,
                                  std::string firstLabel,
@@ -83,7 +87,9 @@
                repeat),
       slow_teardown_(slowTeardown),
       web_client_(base::MakeUnique<ChromeWebClient>()),
-      provider_(ios::CreateChromeBrowserProvider()) {}
+      provider_(ios::CreateChromeBrowserProvider()),
+      browser_state_manager_(
+          base::MakeUnique<TestChromeBrowserStateManager>(base::FilePath())) {}
 
 PerfTestWithBVC::~PerfTestWithBVC() {}
 
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index a786891..686ad438 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -233,7 +233,6 @@
     "prerender_delegate.h",
   ]
   deps = [
-    ":browser_list",
     ":resources",
     ":ui",
     "//base",
@@ -343,18 +342,6 @@
   ]
 }
 
-source_set("browser_list") {
-  sources = [
-    "browser_ios.h",
-    "browser_list_ios.h",
-    "browser_list_ios.mm",
-  ]
-  deps = [
-    "//ios/chrome/browser/browser_state",
-    "//ios/chrome/browser/tabs",
-  ]
-}
-
 source_set("test_support") {
   testonly = true
   sources = [
diff --git a/ios/chrome/browser/ui/browser_ios.h b/ios/chrome/browser/ui/browser_ios.h
deleted file mode 100644
index a65005a..0000000
--- a/ios/chrome/browser/ui/browser_ios.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 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.
-
-#ifndef IOS_CHROME_BROWSER_UI_BROWSER_IOS_H_
-#define IOS_CHROME_BROWSER_UI_BROWSER_IOS_H_
-
-#import <Foundation/Foundation.h>
-
-namespace ios {
-class ChromeBrowserState;
-}
-
-@class TabModel;
-
-// Modeled after chrome/browser/ui/browser, just an abstract interface to
-// a browser to get the browser state and tabs from but can go into a
-// BrowserListIOS.
-@protocol BrowserIOS
-
-- (ios::ChromeBrowserState*)browserState;
-- (TabModel*)tabModel;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_BROWSER_IOS_H_
diff --git a/ios/chrome/browser/ui/browser_list_ios.h b/ios/chrome/browser/ui/browser_list_ios.h
deleted file mode 100644
index a08d490..0000000
--- a/ios/chrome/browser/ui/browser_list_ios.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 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.
-
-#ifndef IOS_CHROME_BROWSER_UI_BROWSER_LIST_IOS_H_
-#define IOS_CHROME_BROWSER_UI_BROWSER_LIST_IOS_H_
-
-#include <vector>
-
-#import "ios/chrome/browser/ui/browser_ios.h"
-
-namespace ios {
-class ChromeBrowserState;
-}
-
-// Modeled after chrome/browser/ui/browser_list.
-
-class BrowserListIOS {
- public:
-  typedef std::vector<id<BrowserIOS>> BrowserVector;
-  typedef BrowserVector::iterator iterator;
-  typedef BrowserVector::const_iterator const_iterator;
-
-  // Note: browsers are not retained, just like desktop browser lists, their
-  // management is outside the list.
-  static void AddBrowser(id<BrowserIOS> browser);
-  static void RemoveBrowser(id<BrowserIOS> browser);
-
-  static id<BrowserIOS> GetLastActiveWithBrowserState(
-      ios::ChromeBrowserState* browser_state);
-
-  static const_iterator begin();
-  static const_iterator end();
-
-  static bool empty() { return !browsers_ || browsers_->empty(); }
-  static size_t size() { return browsers_ ? browsers_->size() : 0; }
-
-  // Returns true if at least one incognito session is active.
-  static bool IsOffTheRecordSessionActive();
-
- private:
-  static BrowserVector* browsers_;
-
-  static void EnsureBrowsersIsValid();
-};
-
-#endif  // IOS_CHROME_BROWSER_UI_BROWSER_LIST_IOS_H_
diff --git a/ios/chrome/browser/ui/browser_list_ios.mm b/ios/chrome/browser/ui/browser_list_ios.mm
deleted file mode 100644
index 3e09bcf..0000000
--- a/ios/chrome/browser/ui/browser_list_ios.mm
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 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.
-
-#import "ios/chrome/browser/ui/browser_list_ios.h"
-
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/tabs/tab_model.h"
-
-BrowserListIOS::BrowserVector* BrowserListIOS::browsers_;
-
-void BrowserListIOS::AddBrowser(id<BrowserIOS> browser) {
-  EnsureBrowsersIsValid();
-  DCHECK(browser);
-  browsers_->push_back(browser);
-}
-
-void BrowserListIOS::RemoveBrowser(id<BrowserIOS> browser) {
-  if (!browsers_)
-    return;
-  DCHECK(browser);
-  const iterator remove_browser =
-      std::find(browsers_->begin(), browsers_->end(), browser);
-  if (remove_browser != browsers_->end())
-    browsers_->erase(remove_browser);
-}
-
-id<BrowserIOS> BrowserListIOS::GetLastActiveWithBrowserState(
-    ios::ChromeBrowserState* browser_state) {
-  DCHECK(browser_state);
-  for (const_iterator i = BrowserListIOS::begin(); i != BrowserListIOS::end();
-       ++i) {
-    if ([*i browserState] == browser_state)
-      return *i;
-  }
-  return NULL;
-}
-
-BrowserListIOS::const_iterator BrowserListIOS::begin() {
-  EnsureBrowsersIsValid();
-  return browsers_->begin();
-}
-
-BrowserListIOS::const_iterator BrowserListIOS::end() {
-  EnsureBrowsersIsValid();
-  return browsers_->end();
-}
-
-// static
-bool BrowserListIOS::IsOffTheRecordSessionActive() {
-  for (const_iterator i = BrowserListIOS::begin(); i != BrowserListIOS::end();
-       ++i) {
-    // Unlike desktop, an Incognito browser can exist but be empty, so filter
-    // that case out.
-    if ([*i browserState] && [*i browserState]->IsOffTheRecord() &&
-        ![[*i tabModel] isEmpty])
-      return true;
-  }
-  return false;
-}
-
-void BrowserListIOS::EnsureBrowsersIsValid() {
-  if (browsers_)
-    return;
-  browsers_ = new BrowserVector;
-}
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h
index 6531d86..c532693 100644
--- a/ios/chrome/browser/ui/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -10,7 +10,6 @@
 #import <UIKit/UIKit.h>
 
 #import "base/ios/block_types.h"
-#import "ios/chrome/browser/ui/browser_ios.h"
 #import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_owner.h"
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
@@ -51,8 +50,7 @@
 
 // The top-level view controller for the browser UI. Manages other controllers
 // which implement the interface.
-@interface BrowserViewController : UIViewController<BrowserIOS,
-                                                    SideSwipeControllerDelegate,
+@interface BrowserViewController : UIViewController<SideSwipeControllerDelegate,
                                                     ToolbarOwner,
                                                     UrlLoader,
                                                     VoiceSearchPresenter,
@@ -93,6 +91,12 @@
 // Returns whether or not text to speech is playing.
 @property(nonatomic, assign, readonly, getter=isPlayingTTS) BOOL playingTTS;
 
+// Returns the TabModel passed to the initializer.
+@property(nonatomic, assign, readonly) TabModel* tabModel;
+
+// Returns the ios::ChromeBrowserState passed to the initializer.
+@property(nonatomic, assign, readonly) ios::ChromeBrowserState* browserState;
+
 // Whether the receiver is currently the primary BVC.
 - (void)setPrimary:(BOOL)primary;
 
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index c3fda741..b768c1e4 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -88,7 +88,6 @@
 #import "ios/chrome/browser/ui/background_generator.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h"
 #import "ios/chrome/browser/ui/browser_container_view.h"
-#import "ios/chrome/browser/ui/browser_list_ios.h"
 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
 #import "ios/chrome/browser/ui/chrome_web_view_factory.h"
 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
@@ -917,7 +916,6 @@
     // TODO(leng): Delay this.
     [[UpgradeCenter sharedInstance] registerClient:self];
     _inNewTabAnimation = NO;
-    BrowserListIOS::AddBrowser(self);
     if (model && browserState)
       [self updateWithTabModel:model browserState:browserState];
     if ([[NSUserDefaults standardUserDefaults]
@@ -943,7 +941,6 @@
   _tabStripController.reset();
   _infoBarContainer.reset();
   _readingListMenuNotifier.reset();
-  BrowserListIOS::RemoveBrowser(self);
   _bookmarkModel->RemoveObserver(_bookmarkModelBridge.get());
   [_model removeObserver:self];
   [[UpgradeCenter sharedInstance] unregisterClient:self];
@@ -1044,6 +1041,14 @@
   return _voiceSearchController && _voiceSearchController->IsPlayingAudio();
 }
 
+- (ios::ChromeBrowserState*)browserState {
+  return _browserState;
+}
+
+- (TabModel*)tabModel {
+  return _model.get();
+}
+
 - (SideSwipeController*)sideSwipeController {
   if (!_sideSwipeController) {
     _sideSwipeController.reset([[SideSwipeController alloc]
@@ -1672,7 +1677,6 @@
   [_contextualSearchMask removeFromSuperview];
   [_paymentRequestManager close];
   _paymentRequestManager.reset();
-  BrowserListIOS::RemoveBrowser(self);
   [_toolbarController browserStateDestroyed];
   [_model browserStateDestroyed];
   [_preloadController browserStateDestroyed];
@@ -3239,16 +3243,6 @@
   }
 }
 
-#pragma mark - BrowserIOS methods
-
-- (ios::ChromeBrowserState*)browserState {
-  return _browserState;
-}
-
-- (TabModel*)tabModel {
-  return _model.get();
-}
-
 #pragma mark - No-tabs UI methods
 
 // Show the No-Tabs UI (hiding normal tab/web ui).
@@ -3503,7 +3497,8 @@
 
   ReadingListModel* readingModel =
       ReadingListModelFactory::GetForBrowserState(_browserState);
-  readingModel->AddEntry(URL, base::SysNSStringToUTF8(title));
+  readingModel->AddEntry(URL, base::SysNSStringToUTF8(title),
+                         reading_list::ADDED_VIA_CURRENT_APP);
 
   NSString* snackBarMessage =
       l10n_util::GetNSString(IDS_IOS_READING_LIST_SNACKBAR_MESSAGE);
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
index d1dee07..53f7535f 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -142,12 +142,16 @@
 // enter edit mode.
 void AddEntriesAndEnterEdit() {
   ReadingListModel* model = GetReadingListModel();
-  model->AddEntry(GURL(kReadURL), std::string(kReadTitle));
+  model->AddEntry(GURL(kReadURL), std::string(kReadTitle),
+                  reading_list::ADDED_VIA_CURRENT_APP);
   model->SetReadStatus(GURL(kReadURL), true);
-  model->AddEntry(GURL(kReadURL2), std::string(kReadTitle2));
+  model->AddEntry(GURL(kReadURL2), std::string(kReadTitle2),
+                  reading_list::ADDED_VIA_CURRENT_APP);
   model->SetReadStatus(GURL(kReadURL2), true);
-  model->AddEntry(GURL(kUnreadURL), std::string(kUnreadTitle));
-  model->AddEntry(GURL(kUnreadURL2), std::string(kUnreadTitle2));
+  model->AddEntry(GURL(kUnreadURL), std::string(kUnreadTitle),
+                  reading_list::ADDED_VIA_CURRENT_APP);
+  model->AddEntry(GURL(kUnreadURL2), std::string(kUnreadTitle2),
+                  reading_list::ADDED_VIA_CURRENT_APP);
   OpenReadingList();
 
   TapButtonWithID(IDS_IOS_READING_LIST_EDIT_BUTTON);
@@ -237,7 +241,8 @@
 
 // Tests that only the "Edit" button is showing when not editing.
 - (void)testVisibleButtonsNonEditingMode {
-  GetReadingListModel()->AddEntry(GURL(kUnreadURL), std::string(kUnreadTitle));
+  GetReadingListModel()->AddEntry(GURL(kUnreadURL), std::string(kUnreadTitle),
+                                  reading_list::ADDED_VIA_CURRENT_APP);
   OpenReadingList();
 
   AssertButtonNotVisibleWithID(IDS_IOS_READING_LIST_DELETE_BUTTON);
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm
index 8ea20799..be6f720a 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller_unittest.mm
@@ -113,9 +113,12 @@
 // Tests that reading list items are displayed.
 TEST_F(ReadingListViewControllerTest, DisplaysItems) {
   // Prefill some items.
-  reading_list_model_->AddEntry(GURL("https://chromium.org"), "news");
-  reading_list_model_->AddEntry(GURL("https://mail.chromium.org"), "mail");
-  reading_list_model_->AddEntry(GURL("https://foo.bar"), "Foo");
+  reading_list_model_->AddEntry(GURL("https://chromium.org"), "news",
+                                reading_list::ADDED_VIA_CURRENT_APP);
+  reading_list_model_->AddEntry(GURL("https://mail.chromium.org"), "mail",
+                                reading_list::ADDED_VIA_CURRENT_APP);
+  reading_list_model_->AddEntry(GURL("https://foo.bar"), "Foo",
+                                reading_list::ADDED_VIA_CURRENT_APP);
   reading_list_model_->SetReadStatus(GURL("https://foo.bar"), true);
 
   // Load view.
@@ -157,7 +160,8 @@
       [OCMockObject partialMockForObject:reading_list_view_controller_.get()];
 
   GURL url("https://chromium.org");
-  reading_list_model_->AddEntry(url, "chromium");
+  reading_list_model_->AddEntry(url, "chromium",
+                                reading_list::ADDED_VIA_CURRENT_APP);
   [reading_list_view_controller_ view];
   [[partialMock expect] dismiss];
 
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn
index c62a0c89..b2a94729 100644
--- a/ios/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -31,9 +31,6 @@
     "resources/toolbar_dark_newtab_incognito_active.png",
     "resources/toolbar_dark_newtab_incognito_active@2x.png",
     "resources/toolbar_dark_newtab_incognito_active@3x.png",
-    "resources/toolbar_tools.png",
-    "resources/toolbar_tools@2x.png",
-    "resources/toolbar_tools@3x.png",
   ]
   outputs = [
     "{{bundle_resources_dir}}/{{source_file_part}}",
@@ -167,12 +164,10 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state:test_support",
-    "//ios/chrome/browser/ssl",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
     "//ios/chrome/test:test_support",
     "//ios/testing:ocmock_support",
-    "//ios/web",
     "//ios/web:test_support",
     "//testing/gtest",
     "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/toolbar/resources/toolbar_tools.png b/ios/chrome/browser/ui/toolbar/resources/toolbar_tools.png
deleted file mode 100644
index ff90580..0000000
--- a/ios/chrome/browser/ui/toolbar/resources/toolbar_tools.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/toolbar_tools@2x.png b/ios/chrome/browser/ui/toolbar/resources/toolbar_tools@2x.png
deleted file mode 100644
index 71ba4df..0000000
--- a/ios/chrome/browser/ui/toolbar/resources/toolbar_tools@2x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/toolbar_tools@3x.png b/ios/chrome/browser/ui/toolbar/resources/toolbar_tools@3x.png
deleted file mode 100644
index 9d00d1e..0000000
--- a/ios/chrome/browser/ui/toolbar/resources/toolbar_tools@3x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.h b/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.h
index 5e63a41..18153d4 100644
--- a/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.h
+++ b/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.h
@@ -18,10 +18,8 @@
   TestToolbarModelIOS();
   ~TestToolbarModelIOS() override;
 
-  // Getter to the TestToolbarModel to set its values in tests.
-  TestToolbarModel* GetToolbarModel();
-
   // ToolbarModelIOS implementation:
+  ToolbarModel* GetToolbarModel() override;
   bool IsLoading() override;
   CGFloat GetLoadProgressFraction() override;
   bool CanGoBack() override;
@@ -31,15 +29,6 @@
   bool IsCurrentTabBookmarkedByUser() override;
   bool ShouldDisplayHintText() override;
 
-  base::string16 GetFormattedURL(size_t* prefix_end) const override;
-  GURL GetURL() const override;
-  security_state::SecurityLevel GetSecurityLevel(
-      bool ignore_editing) const override;
-  gfx::VectorIconId GetVectorIcon() const override;
-  base::string16 GetSecureVerboseText() const override;
-  base::string16 GetEVCertName() const override;
-  bool ShouldDisplayURL() const override;
-
   void set_is_loading(bool is_loading) { is_loading_ = is_loading; }
   void set_load_progress_fraction(CGFloat load_progress_fraction) {
     load_progress_fraction_ = load_progress_fraction;
diff --git a/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.mm b/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.mm
index 6511803..11736d3 100644
--- a/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.mm
+++ b/ios/chrome/browser/ui/toolbar/test_toolbar_model_ios.mm
@@ -20,7 +20,7 @@
 
 TestToolbarModelIOS::~TestToolbarModelIOS() {}
 
-TestToolbarModel* TestToolbarModelIOS::GetToolbarModel() {
+ToolbarModel* TestToolbarModelIOS::GetToolbarModel() {
   return test_toolbar_model_.get();
 }
 
@@ -56,31 +56,3 @@
   return false;
 }
 
-base::string16 TestToolbarModelIOS::GetFormattedURL(size_t* prefix_end) const {
-  return test_toolbar_model_->GetFormattedURL(prefix_end);
-}
-
-GURL TestToolbarModelIOS::GetURL() const {
-  return test_toolbar_model_->GetURL();
-}
-
-security_state::SecurityLevel TestToolbarModelIOS::GetSecurityLevel(
-    bool ignore_editing) const {
-  return test_toolbar_model_->GetSecurityLevel(ignore_editing);
-}
-
-gfx::VectorIconId TestToolbarModelIOS::GetVectorIcon() const {
-  return test_toolbar_model_->GetVectorIcon();
-}
-
-base::string16 TestToolbarModelIOS::GetSecureVerboseText() const {
-  return test_toolbar_model_->GetSecureVerboseText();
-}
-
-base::string16 TestToolbarModelIOS::GetEVCertName() const {
-  return test_toolbar_model_->GetEVCertName();
-}
-
-bool TestToolbarModelIOS::ShouldDisplayURL() const {
-  return test_toolbar_model_->ShouldDisplayURL();
-}
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h b/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h
index c146fc09..6b53dac 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h
@@ -18,6 +18,7 @@
   ~ToolbarModelImplIOS() override;
 
   // ToolbarModelIOS implementation:
+  ToolbarModel* GetToolbarModel() override;
   bool IsLoading() override;
   CGFloat GetLoadProgressFraction() override;
   bool CanGoBack() override;
@@ -28,17 +29,6 @@
   bool ShouldDisplayHintText() override;
 
  private:
-  // ToolbarModel:
-  base::string16 GetFormattedURL(size_t* prefix_end) const override;
-  GURL GetURL() const override;
-  security_state::SecurityLevel GetSecurityLevel(
-      bool ignore_editing) const override;
-  gfx::VectorIconId GetVectorIcon() const override;
-  base::string16 GetSecureVerboseText() const override;
-  base::string16 GetEVCertName() const override;
-  bool ShouldDisplayURL() const override;
-
- private:
   ToolbarModelDelegateIOS* delegate_;
   std::unique_ptr<ToolbarModel> toolbar_model_;
 
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.mm b/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.mm
index e8db613..ee723d97 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.mm
@@ -9,10 +9,8 @@
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#include "ios/chrome/browser/reading_list/offline_url_utils.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_model_delegate_ios.h"
-#import "ios/web/public/navigation_item.h"
 #import "ios/web/public/web_state/web_state.h"
 
 namespace {
@@ -37,6 +35,10 @@
 
 ToolbarModelImplIOS::~ToolbarModelImplIOS() {}
 
+ToolbarModel* ToolbarModelImplIOS::GetToolbarModel() {
+  return toolbar_model_.get();
+}
+
 bool ToolbarModelImplIOS::IsLoading() {
   // Please note, ToolbarModel's notion of isLoading is slightly different from
   // WebState's IsLoading().
@@ -81,50 +83,3 @@
   return [current_tab.webController wantsLocationBarHintText];
 }
 
-base::string16 ToolbarModelImplIOS::GetFormattedURL(size_t* prefix_end) const {
-  base::string16 formatted_url = toolbar_model_->GetFormattedURL(prefix_end);
-  Tab* current_tab = delegate_->GetCurrentTab();
-  if (!current_tab || !current_tab.webState ||
-      !current_tab.webState->GetNavigationManager() ||
-      !current_tab.webState->GetNavigationManager()->GetVisibleItem()) {
-    return formatted_url;
-  }
-  GURL url =
-      current_tab.webState->GetNavigationManager()->GetVisibleItem()->GetURL();
-  if (reading_list::IsOfflineURL(url) &&
-      GetSecurityLevel(true /*ignore_editing*/) ==
-          security_state::SecurityLevel::NONE) {
-    size_t removed = 0;
-    formatted_url =
-        reading_list::StripSchemeFromOnlineURL(formatted_url, &removed);
-    if (prefix_end) {
-      *prefix_end -= removed;
-    }
-  }
-  return formatted_url;
-}
-
-GURL ToolbarModelImplIOS::GetURL() const {
-  return toolbar_model_->GetURL();
-}
-
-security_state::SecurityLevel ToolbarModelImplIOS::GetSecurityLevel(
-    bool ignore_editing) const {
-  return toolbar_model_->GetSecurityLevel(ignore_editing);
-}
-
-gfx::VectorIconId ToolbarModelImplIOS::GetVectorIcon() const {
-  return toolbar_model_->GetVectorIcon();
-}
-
-base::string16 ToolbarModelImplIOS::GetSecureVerboseText() const {
-  return toolbar_model_->GetSecureVerboseText();
-}
-
-base::string16 ToolbarModelImplIOS::GetEVCertName() const {
-  return toolbar_model_->GetEVCertName();
-}
-
-bool ToolbarModelImplIOS::ShouldDisplayURL() const {
-  return toolbar_model_->ShouldDisplayURL();
-}
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios_unittest.mm b/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios_unittest.mm
index 958bf3f..308a1b0 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios_unittest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios_unittest.mm
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/mac/scoped_nsobject.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/bookmarks/browser/bookmark_model.h"
@@ -15,15 +14,12 @@
 #include "components/toolbar/test_toolbar_model.h"
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_model_delegate_ios.h"
 #include "ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h"
 #import "ios/chrome/browser/xcallback_parameters.h"
 #import "ios/testing/ocmock_complex_type_helper.h"
-#import "ios/web/public/navigation_item.h"
-#import "ios/web/public/test/fakes/test_navigation_manager.h"
 #import "ios/web/public/test/fakes/test_web_state.h"
 #include "ios/web/public/test/test_web_thread.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
@@ -221,58 +217,4 @@
   EXPECT_FALSE(toolbarModel_->IsCurrentTabBookmarked());
 }
 
-TEST_F(ToolbarModelImplIOSTest, TestGetFormattedURL) {
-  ToolbarModelImplIOSTestWebState web_state(chrome_browser_state_.get());
-  IOSSecurityStateTabHelper::CreateForWebState(&web_state);
-  auto test_navigation_manager = base::MakeUnique<web::TestNavigationManager>();
-  auto visible_item = web::NavigationItem::Create();
-  test_navigation_manager->SetVisibleItem(visible_item.get());
-  web_state.SetNavigationManager(std::move(test_navigation_manager));
-  id tabMock = [[TMITestTabMock alloc]
-      initWithRepresentedObject:[OCMockObject mockForClass:[Tab class]]];
-  OCMockObject* tabModelMock = static_cast<OCMockObject*>(tabModel_.get());
-  [[[tabModelMock stub] andReturn:tabMock] currentTab];
-  [static_cast<TMITestTabMock*>(tabMock) setWebState:&web_state];
-
-  size_t length = 0;
-  const char no_scheme_url[] = "www.chromium.org";
-  const char http_url[] = "http://www.chromium.org";
-  const char https_url[] = "https://www.chromium.org";
-  const char chrome_url[] = "chrome://www.chromium.org";
-  const char offline_url[] = "chrome://offline/testid/page.html";
-  // Test that only http:// scheme is stripped out for online URL.
-  visible_item->SetURL(GURL(http_url));
-  EXPECT_EQ(toolbarModel_->GetFormattedURL(&length),
-            base::UTF8ToUTF16(no_scheme_url));
-  EXPECT_EQ(length, 0u);
-
-  visible_item->SetURL(GURL(https_url));
-  EXPECT_EQ(toolbarModel_->GetFormattedURL(&length),
-            base::UTF8ToUTF16(https_url));
-  EXPECT_EQ(length, 8u);
-
-  visible_item->SetURL(GURL(chrome_url));
-  EXPECT_EQ(toolbarModel_->GetFormattedURL(&length),
-            base::UTF8ToUTF16(chrome_url));
-  EXPECT_EQ(length, 9u);
-
-  // Test that only http:// and https:// scheme are stripped out for offline
-  // URL.
-  visible_item->SetURL(GURL(offline_url));
-  visible_item->SetVirtualURL(GURL(http_url));
-  EXPECT_EQ(toolbarModel_->GetFormattedURL(&length),
-            base::UTF8ToUTF16(no_scheme_url));
-  EXPECT_EQ(length, 0u);
-
-  visible_item->SetVirtualURL(GURL(https_url));
-  EXPECT_EQ(toolbarModel_->GetFormattedURL(&length),
-            base::UTF8ToUTF16(no_scheme_url));
-  EXPECT_EQ(length, 0u);
-
-  visible_item->SetVirtualURL(GURL(chrome_url));
-  EXPECT_EQ(toolbarModel_->GetFormattedURL(&length),
-            base::UTF8ToUTF16(chrome_url));
-  EXPECT_EQ(length, 9u);
-}
-
 }  // namespace
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_model_ios.h b/ios/chrome/browser/ui/toolbar/toolbar_model_ios.h
index b471271..9c98fbe 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_model_ios.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_model_ios.h
@@ -9,8 +9,15 @@
 
 #include "components/toolbar/toolbar_model.h"
 
-class ToolbarModelIOS : public ToolbarModel {
+// This class adds some IOS specific methods to the ToolbarModel.
+// It does not inherit from ToolbarModel on purpose.
+class ToolbarModelIOS {
  public:
+  virtual ~ToolbarModelIOS() {}
+
+  // Returns the |ToolbarModel| contained by this instance.
+  virtual ToolbarModel* GetToolbarModel() = 0;
+
   // Returns true if the current tab is currently loading.
   virtual bool IsLoading() = 0;
 
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h b/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h
index 433719d..6a88fdb 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h
+++ b/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h
@@ -13,6 +13,7 @@
 // TintedButton specialization that updates the tint color when the tools menu
 // is visible or when the reading list associated with |readingListModel|
 // contains unread items.
+// Draws and animates the icon of the button using UIBezierPaths.
 @interface ToolbarToolsMenuButton : TintedButton
 
 // Initializes and returns a newly allocated TintedButton with the specified
@@ -32,6 +33,10 @@
 // items.
 - (void)setReadingListContainsUnseenItems:(BOOL)readingListContainsUnseenItems;
 
+// Triggers an animation on the button to draw the user's attention to the
+// button.
+- (void)triggerAnimation;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_TOOLS_MENU_BUTTON_H_
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.mm b/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.mm
index 29de8ed..dff031a 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.mm
@@ -4,23 +4,70 @@
 
 #import "ios/chrome/browser/ui/toolbar/toolbar_tools_menu_button.h"
 
+#import <QuartzCore/CAAnimation.h>
+#import <QuartzCore/CAMediaTimingFunction.h>
+
 #include "ios/chrome/browser/ui/toolbar/toolbar_button_tints.h"
-#import "ios/chrome/browser/ui/uikit_ui_util.h"
 
-@interface ToolbarToolsMenuButton ()
-// Updates the tint configuration based on the button's situation, e.g. whether
-// the tools menu is visible or not.
-- (void)updateTintOfButton;
-@end
+namespace {
+// The number of dots drawn.
+const int kNumberOfDots = 3;
+// Position of the topmost dot.
+const CGFloat kDotOffsetX = 22;
+const CGFloat kDotOffsetY = 18;
+// Vertical space between dots.
+const CGFloat kVerticalSpaceBetweenDots = 6;
+// The duration of the animation, in seconds.
+const CFTimeInterval kAnimationDuration = 1;
+// The frame offset at which the animation to the intermediary value finishes.
+const int kIntermediaryValueBeginFrame = 15;
+// The frame offset at which the animation to the final value starts.
+const int kIntermediaryValueEndFrame = 29;
+// The frame offset at which the animation to the final value finishes.
+const int kFinalValueBeginFrame = 37;
+// The number of frames between the start of each dot's animation.
+const double kFramesBetweenAnimationOfEachDot = 3;
+// The maximum width of the segment/dots.
+const CGFloat kMaxWidthOfSegment = 7.4;
+// Constants for the properties of the stroke during the animations.
+// The strokeEnd is slightly more than 0.5, because if the strokeEnd is
+// exactly equal to strokeStart, the line is not drawn.
+const CGFloat kStrokeStartAtRest = 0.5;
+const CGFloat kStrokeEndAtRest = kStrokeStartAtRest + 0.001;
+const CGFloat kLineWidthAtRest = 4;
+const CGFloat kStrokeStartAtApogee = 0;
+const CGFloat kStrokeEndAtApogee = 1;
+const CGFloat kLineWidthAtApogee = 3;
+}  // namespace
 
-@interface ToolbarToolsMenuButton () {
+@interface ToolbarToolsMenuButton ()<CAAnimationDelegate> {
   // The style of the toolbar the button is in.
   ToolbarControllerStyle style_;
   // Whether the tools menu is visible.
   BOOL toolsMenuVisible_;
   // Whether the reading list contains unseen items.
   BOOL readingListContainsUnseenItems_;
+  // The CALayers containing the drawn dots.
+  base::scoped_nsobject<CAShapeLayer> pathLayers_[kNumberOfDots];
+  // Whether the CALayers are being animated.
+  BOOL animationOnGoing_;
 }
+// Updates the tint configuration based on the button's situation, e.g. whether
+// the tools menu is visible or not.
+- (void)updateTintOfButton;
+// Initializes the pathLayers.
+- (void)initializeShapeLayers;
+// Returns a keyframe-based animation of the property identified by |keyPath|.
+// The animation immidiately sets the property's value to |initialValue|.
+// After |frameStart| frames, the property's value animates to
+// |intermediaryValue|, and then to |finalValue|.
+- (CAAnimation*)animationWithInitialValue:(id)initialValue
+                        intermediaryValue:(id)intermediaryValue
+                               finalValue:(id)finalValue
+                               frameStart:(int)frameStart
+                               forKeyPath:(NSString*)keyPath;
+// Starts animating the button towards the color |targetColor|.
+- (void)animateToColor:(UIColor*)targetColor;
 @end
 
 @implementation ToolbarToolsMenuButton
@@ -34,11 +81,6 @@
               forState:UIControlStateNormal];
     [self setTintColor:toolbar::HighlighButtonTint(style_)
               forState:UIControlStateHighlighted];
-
-    [self setImageEdgeInsets:UIEdgeInsetsMakeDirected(0, -3, 0, 0)];
-    UIImage* image = [UIImage imageNamed:@"toolbar_tools"];
-    image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
-    [self setImage:image forState:UIControlStateNormal];
   }
   return self;
 }
@@ -53,6 +95,10 @@
   [self updateTintOfButton];
 }
 
+- (void)triggerAnimation {
+  [self animateToColor:toolbar::HighlighButtonTint(style_)];
+}
+
 #pragma mark - Private
 
 - (void)updateTintOfButton {
@@ -65,4 +111,179 @@
   }
 }
 
+- (void)initializeShapeLayers {
+  for (int i = 0; i < kNumberOfDots; i++) {
+    base::scoped_nsobject<CAShapeLayer>& pathLayer = pathLayers_[i];
+    if (pathLayer) {
+      [pathLayer removeFromSuperlayer];
+    }
+
+    const CGFloat x = kDotOffsetX;
+    const CGFloat y = kDotOffsetY + kVerticalSpaceBetweenDots * i;
+
+    UIBezierPath* path = [UIBezierPath bezierPath];
+    [path moveToPoint:CGPointMake(x - kMaxWidthOfSegment * 0.5, y)];
+    [path addLineToPoint:CGPointMake(x + kMaxWidthOfSegment * 0.5, y)];
+
+    pathLayer.reset([[CAShapeLayer layer] retain]);
+    [pathLayer setFrame:self.bounds];
+    [pathLayer setPath:path.CGPath];
+    [pathLayer setStrokeColor:[self.tintColor CGColor]];
+    [pathLayer setFillColor:nil];
+    [pathLayer setLineWidth:kLineWidthAtRest];
+    [pathLayer setLineCap:kCALineCapRound];
+    [pathLayer setStrokeStart:kStrokeStartAtRest];
+    [pathLayer setStrokeEnd:kStrokeEndAtRest];
+    [self.layer addSublayer:pathLayer.get()];
+  }
+}
+
+- (CAAnimation*)animationWithInitialValue:(id)initialValue
+                        intermediaryValue:(id)intermediaryValue
+                               finalValue:(id)finalValue
+                               frameStart:(int)frameStart
+                               forKeyPath:(NSString*)keyPath {
+  // The property is animated the following way:
+  //
+  //  value
+  //    ^
+  //    |                                             .final...final
+  //    |                                            .
+  //    |               .intermediary...intermediary.
+  //    |              .
+  // initial...initial.
+  //    |
+  //    +---------+-----------+--------------+-----------+-------+---> frames
+  //    0       start         |              |           |       60
+  //                        start+           |         start+
+  //            kIntermediaryValueBeginFrame | kFinalValueBeginFrame
+  //                                         |
+  //                                       start+
+  //                            kIntermediaryValueEndFrame
+
+  CAKeyframeAnimation* animation =
+      [CAKeyframeAnimation animationWithKeyPath:keyPath];
+  animation.duration = kAnimationDuration;
+  animation.removedOnCompletion = NO;
+
+  // Set up the values.
+  animation.values = @[
+    initialValue, initialValue, intermediaryValue, intermediaryValue,
+    finalValue, finalValue
+  ];
+
+  // Set up the timing functions.
+  NSMutableArray* timings = [NSMutableArray array];
+  for (size_t i = 0; i < [animation.values count] - 1; i++)
+    [timings addObject:[CAMediaTimingFunction
+                           functionWithName:kCAMediaTimingFunctionEaseIn]];
+  animation.timingFunctions = timings;
+
+  // Set up the key times.
+  const double totalNumberOfFrames = 60 * kAnimationDuration;
+  animation.keyTimes = @[
+    @0, @(frameStart / totalNumberOfFrames),
+    @((frameStart + kIntermediaryValueBeginFrame) / totalNumberOfFrames),
+    @((frameStart + kIntermediaryValueEndFrame) / totalNumberOfFrames),
+    @((frameStart + kFinalValueBeginFrame) / totalNumberOfFrames), @1
+  ];
+
+  DCHECK_EQ([animation.keyTimes count], [animation.values count]);
+  DCHECK_EQ([animation.keyTimes count] - 1, [animation.timingFunctions count]);
+
+#if DCHECK_IS_ON()
+  for (NSNumber* number in animation.keyTimes) {
+    DCHECK_GE([number floatValue], 0);
+    DCHECK_LE([number floatValue], 1);
+  }
+#endif
+
+  return animation;
+}
+
+- (void)animateToColor:(UIColor*)targetColor {
+  animationOnGoing_ = YES;
+
+  // Add four animations for each stroke.
+  for (int i = 0; i < kNumberOfDots; i++) {
+    base::scoped_nsobject<CAShapeLayer>& pathLayer = pathLayers_[i];
+    DCHECK(pathLayer.get());
+    const int frameStart =
+        (kNumberOfDots - i) * kFramesBetweenAnimationOfEachDot;
+
+    // Start of the stroke animation.
+    CAAnimation* strokeStartAnimation =
+        [self animationWithInitialValue:@(kStrokeStartAtRest)
+                      intermediaryValue:@(kStrokeStartAtApogee)
+                             finalValue:@(kStrokeStartAtRest)
+                             frameStart:frameStart
+                             forKeyPath:@"strokeStart"];
+
+    // End of the stroke animation.
+    CAAnimation* strokeEndAnimation =
+        [self animationWithInitialValue:@(kStrokeEndAtRest)
+                      intermediaryValue:@(kStrokeEndAtApogee)
+                             finalValue:@(kStrokeEndAtRest)
+                             frameStart:frameStart
+                             forKeyPath:@"strokeEnd"];
+
+    // Width of the stroke animation.
+    CAAnimation* lineWidthAnimation =
+        [self animationWithInitialValue:@(kLineWidthAtRest)
+                      intermediaryValue:@(kLineWidthAtApogee)
+                             finalValue:@(kLineWidthAtRest)
+                             frameStart:frameStart
+                             forKeyPath:@"lineWidth"];
+
+    // Color of the stroke animation.
+    CGColorRef initialColor = self.tintColor.CGColor;
+    CGColorRef finalColor = targetColor.CGColor;
+    CAAnimation* colorAnimation =
+        [self animationWithInitialValue:(__bridge id)initialColor
+                      intermediaryValue:(__bridge id)finalColor
+                             finalValue:(__bridge id)finalColor
+                             frameStart:frameStart
+                             forKeyPath:@"strokeColor"];
+    colorAnimation.fillMode = kCAFillModeForwards;
+
+    // |self| needs to know when the animations are finished. This is achieved
+    // by having |self| be registered as a CAAnimationDelegate.
+    // Because all animations have the same duration, any animation can be used.
+    // Arbitrarly use the |strokeStartAnimation| of the first dot.
+    if (i == 0) {
+      strokeStartAnimation.delegate = self;
+    }
+
+    [pathLayer addAnimation:strokeStartAnimation forKey:nil];
+    [pathLayer addAnimation:strokeEndAnimation forKey:nil];
+    [pathLayer addAnimation:lineWidthAnimation forKey:nil];
+    [pathLayer addAnimation:colorAnimation forKey:nil];
+  }
+
+  self.tintColor = targetColor;
+}
+
+#pragma mark - UIView
+
+- (void)tintColorDidChange {
+  // The CAShapeLayer needs to be recreated when the tint color changes, to
+  // reflect the tint color.
+  // However, recreating the CAShapeLayer while it is animating cancels the
+  // animation. To avoid canceling the animation, skip recreating the
+  // CAShapeLayer when an animation is on going.
+  // To reflect any potential tint color change, the CAShapeLayer will be
+  // recreated at the end of the animation.
+  if (!animationOnGoing_)
+    [self initializeShapeLayers];
+}
+
+#pragma mark - CAAnimationDelegate
+
+- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)flag {
+  animationOnGoing_ = NO;
+  // Recreate the CAShapeLayers in case the tint code changed while the
+  // animation was going on.
+  [self initializeShapeLayers];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/toolbar/tools_menu_button_observer_bridge.mm b/ios/chrome/browser/ui/toolbar/tools_menu_button_observer_bridge.mm
index aed29ae..965fbd75 100644
--- a/ios/chrome/browser/ui/toolbar/tools_menu_button_observer_bridge.mm
+++ b/ios/chrome/browser/ui/toolbar/tools_menu_button_observer_bridge.mm
@@ -34,6 +34,21 @@
   return self;
 }
 
+- (void)updateButtonWithModel:(const ReadingListModel*)model {
+  DCHECK(model == _model);
+  BOOL readingListContainsUnseenItems = model->GetLocalUnseenFlag();
+  [_button setReadingListContainsUnseenItems:readingListContainsUnseenItems];
+}
+
+- (void)buttonPressed:(UIButton*)sender {
+  if (_model) {
+    _model->ResetLocalUnseenFlag();
+  }
+  [_button setReadingListContainsUnseenItems:NO];
+}
+
+#pragma mark - ReadingListModelBridgeObserver
+
 - (void)readingListModelLoaded:(const ReadingListModel*)model {
   [self updateButtonWithModel:model];
 }
@@ -47,17 +62,11 @@
   _model = nullptr;
 }
 
-- (void)updateButtonWithModel:(const ReadingListModel*)model {
-  DCHECK(model == _model);
-  BOOL readingListContainsUnseenItems = model->GetLocalUnseenFlag();
-  [_button setReadingListContainsUnseenItems:readingListContainsUnseenItems];
-}
-
-- (void)buttonPressed:(UIButton*)sender {
-  if (_model) {
-    _model->ResetLocalUnseenFlag();
-  }
-  [_button setReadingListContainsUnseenItems:NO];
+- (void)readingListModel:(const ReadingListModel*)model
+             didAddEntry:(const GURL&)url
+             entrySource:(reading_list::EntrySource)source {
+  if (source == reading_list::ADDED_VIA_CURRENT_APP)
+    [_button triggerAnimation];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index d31f77e..73cacaa 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -1318,7 +1318,8 @@
 }
 
 - (ToolbarModel*)toolbarModel {
-  return [self.delegate toolbarModelIOS];
+  ToolbarModelIOS* toolbarModelIOS = [self.delegate toolbarModelIOS];
+  return toolbarModelIOS ? toolbarModelIOS->GetToolbarModel() : nullptr;
 }
 
 #pragma mark -
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn
index ba78745..c3a011be 100644
--- a/ios/chrome/test/app/BUILD.gn
+++ b/ios/chrome/test/app/BUILD.gn
@@ -53,6 +53,7 @@
     "//ios/chrome/browser/autofill",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/browser_state:browser_state_impl",
     "//ios/chrome/browser/browsing_data",
     "//ios/chrome/browser/content_settings",
     "//ios/chrome/browser/history",
@@ -61,7 +62,6 @@
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/tabs",
-    "//ios/chrome/browser/ui:browser_list",
     "//ios/chrome/browser/ui:ui_internal",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/main",
diff --git a/ios/chrome/test/app/chrome_test_util.mm b/ios/chrome/test/app/chrome_test_util.mm
index 0f9fbca..9f43f5a 100644
--- a/ios/chrome/test/app/chrome_test_util.mm
+++ b/ios/chrome/test/app/chrome_test_util.mm
@@ -16,10 +16,10 @@
 #import "ios/chrome/app/main_controller_private.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h"
 #import "ios/chrome/browser/metrics/previous_session_info.h"
 #import "ios/chrome/browser/metrics/previous_session_info_private.h"
 #import "ios/chrome/browser/tabs/tab.h"
-#import "ios/chrome/browser/ui/browser_list_ios.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
@@ -65,14 +65,17 @@
 // Returns the original ChromeBrowserState if |incognito| is false. If
 // |ingonito| is true, returns an off-the-record ChromeBrowserState.
 ios::ChromeBrowserState* GetBrowserState(bool incognito) {
-  DCHECK(!BrowserListIOS::empty());
-  id<BrowserIOS> browser = *BrowserListIOS::begin();
-  DCHECK(browser);
-  ios::ChromeBrowserState* browser_state = [browser browserState];
-  DCHECK(browser_state);
-  browser_state = incognito ? browser_state->GetOffTheRecordChromeBrowserState()
-                            : browser_state->GetOriginalChromeBrowserState();
-  return browser_state;
+  std::vector<ios::ChromeBrowserState*> browser_states =
+      GetApplicationContext()
+          ->GetChromeBrowserStateManager()
+          ->GetLoadedBrowserStates();
+  DCHECK(!browser_states.empty());
+
+  ios::ChromeBrowserState* browser_state = browser_states.front();
+  DCHECK(!browser_state->IsOffTheRecord());
+
+  return incognito ? browser_state->GetOffTheRecordChromeBrowserState()
+                   : browser_state;
 }
 
 // Gets the root UIViewController.
diff --git a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
index b03ca13..95850733 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
@@ -17,7 +17,7 @@
     "//ios/clean/chrome/browser",
     "//ios/clean/chrome/browser/ui/commands",
     "//ios/clean/chrome/browser/ui/settings",
-    "//ios/clean/chrome/browser/ui/tab",
+    "//ios/clean/chrome/browser/ui/tab_strip",
     "//ios/web",
     "//net",
     "//ui/base",
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index f8406b2..2b477e3 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -17,7 +17,7 @@
 #import "ios/clean/chrome/browser/ui/commands/tab_commands.h"
 #import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h"
 #import "ios/clean/chrome/browser/ui/settings/settings_coordinator.h"
-#import "ios/clean/chrome/browser/ui/tab/tab_coordinator.h"
+#import "ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.h"
 #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h"
 #import "ios/web/public/navigation_manager.h"
 #include "ios/web/public/web_state/web_state.h"
@@ -87,7 +87,8 @@
 - (void)showTabAtIndexPath:(NSIndexPath*)indexPath {
   DCHECK(_placeholderWebState);
 
-  TabCoordinator* tabCoordinator = [[TabCoordinator alloc] init];
+  TabStripContainerCoordinator* tabCoordinator =
+      [[TabStripContainerCoordinator alloc] init];
   tabCoordinator.webState = _placeholderWebState.get();
   tabCoordinator.presentationKey = indexPath;
   [self addChildCoordinator:tabCoordinator];
diff --git a/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn b/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn
index 1038444a..69254568 100644
--- a/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn
+++ b/ios/clean/chrome/browser/ui/tab_strip/BUILD.gn
@@ -2,6 +2,23 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+source_set("tab_strip") {
+  sources = [
+    "tab_strip_container_coordinator.h",
+    "tab_strip_container_coordinator.mm",
+  ]
+  deps = [
+    ":tab_strip_ui",
+    "//base",
+    "//ios/clean/chrome/browser",
+    "//ios/clean/chrome/browser/ui/actions",
+    "//ios/clean/chrome/browser/ui/animators",
+    "//ios/clean/chrome/browser/ui/tab",
+  ]
+  libs = [ "UIKit.framework" ]
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
 source_set("tab_strip_ui") {
   sources = [
     "tab_strip_container_view_controller.h",
diff --git a/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.h b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.h
new file mode 100644
index 0000000..b0e05642
--- /dev/null
+++ b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.h
@@ -0,0 +1,35 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ======                        New Architecture                         =====
+// =         This code is only used in the new iOS Chrome architecture.       =
+// ============================================================================
+
+#ifndef IOS_CLEAN_CHROME_BROWSER_UI_TAB_STRIP_TAB_STRIP_CONTAINER_COORDINATOR_H_
+#define IOS_CLEAN_CHROME_BROWSER_UI_TAB_STRIP_TAB_STRIP_CONTAINER_COORDINATOR_H_
+
+#import <UIKit/UIKit.h>
+#import "ios/clean/chrome/browser/browser_coordinator.h"
+
+namespace web {
+class WebState;
+}
+
+// Coordinator that runs a tab strip container: A composed UI consisting of a
+// tab strip and a tab.
+@interface TabStripContainerCoordinator : BrowserCoordinator
+
+// The webState representing the web page that will be displayed in this tab.
+// Calling code should assign this before starting this coordinator.
+// This coordinator doesn't assume ownersip of |webState|.
+@property(nonatomic, assign) web::WebState* webState;
+
+// An opaque key provided by this coordinator's parent which can be passed in
+// to a transition animation to synchronize the presentation with the presenting
+// view controller, if any.
+@property(nonatomic, copy) NSObject* presentationKey;
+
+@end
+
+#endif  // IOS_CLEAN_CHROME_BROWSER_UI_TAB_STRIP_TAB_STRIP_CONTAINER_COORDINATOR_H_
diff --git a/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.mm b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.mm
new file mode 100644
index 0000000..889bdb8
--- /dev/null
+++ b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.mm
@@ -0,0 +1,100 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ======                        New Architecture                         =====
+// =         This code is only used in the new iOS Chrome architecture.       =
+// ============================================================================
+
+#import "ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_coordinator.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#import "ios/clean/chrome/browser/browser_coordinator+internal.h"
+#import "ios/clean/chrome/browser/ui/actions/tab_grid_actions.h"
+#import "ios/clean/chrome/browser/ui/animators/zoom_transition_animator.h"
+#import "ios/clean/chrome/browser/ui/tab/tab_coordinator.h"
+#import "ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_view_controller.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface TabStripContainerCoordinator ()<
+    UIViewControllerTransitioningDelegate>
+@property(nonatomic, strong) TabStripContainerViewController* viewController;
+@end
+
+@implementation TabStripContainerCoordinator
+
+@synthesize webState = _webState;
+@synthesize presentationKey = _presentationKey;
+@synthesize viewController = _viewController;
+
+- (void)start {
+  self.viewController = [[TabStripContainerViewController alloc] init];
+  self.viewController.transitioningDelegate = self;
+  self.viewController.modalPresentationStyle = UIModalPresentationCustom;
+
+  TabCoordinator* tabCoordinator = [[TabCoordinator alloc] init];
+  tabCoordinator.webState = self.webState;
+  [self addChildCoordinator:tabCoordinator];
+  // Unset the root view controller, so |tabCoordinator| doesn't present
+  // its view controller.
+  tabCoordinator.rootViewController = nil;
+  [tabCoordinator start];
+
+  // PLACEHOLDER: Replace this placeholder with an actual tab strip view
+  // controller.
+  UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
+  [button addTarget:nil
+                action:@selector(showTabGrid:)
+      forControlEvents:UIControlEventTouchUpInside];
+  [button setTitle:@"Tab grid" forState:UIControlStateNormal];
+  button.frame = CGRectMake(10, 10, 100, 100);
+
+  UIViewController* tabStripViewController = [[UIViewController alloc] init];
+  tabStripViewController.view.backgroundColor = [UIColor blackColor];
+  [tabStripViewController.view addSubview:button];
+  self.viewController.tabStripViewController = tabStripViewController;
+  self.viewController.contentViewController = tabCoordinator.viewController;
+
+  [self.rootViewController presentViewController:self.viewController
+                                        animated:YES
+                                      completion:nil];
+}
+
+- (void)stop {
+  [self.viewController dismissViewControllerAnimated:YES completion:nil];
+  self.viewController = nil;
+}
+
+- (BOOL)canAddOverlayCoordinator:(BrowserCoordinator*)overlayCoordinator {
+  // This coordinator will always accept overlay coordinators.
+  return YES;
+}
+
+#pragma mark - UIViewControllerTransitioningDelegate
+
+- (id<UIViewControllerAnimatedTransitioning>)
+animationControllerForPresentedController:(UIViewController*)presented
+                     presentingController:(UIViewController*)presenting
+                         sourceController:(UIViewController*)source {
+  ZoomTransitionAnimator* animator = [[ZoomTransitionAnimator alloc] init];
+  animator.presenting = YES;
+  animator.presentationKey = self.presentationKey;
+  [animator selectDelegate:@[ source, presenting ]];
+  return animator;
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)
+animationControllerForDismissedController:(UIViewController*)dismissed {
+  ZoomTransitionAnimator* animator = [[ZoomTransitionAnimator alloc] init];
+  animator.presenting = NO;
+  animator.presentationKey = self.presentationKey;
+  [animator selectDelegate:@[ dismissed.presentingViewController ]];
+  return animator;
+}
+
+@end
diff --git a/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_view_controller.mm b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_view_controller.mm
index ff47f80..4afbb09 100644
--- a/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/tab_strip/tab_strip_container_view_controller.mm
@@ -44,7 +44,7 @@
 
 // Called after a new strip view controller is set, but before
 // |-didMoveToParentViewController:| is called on that view controller.
-- (void)didAddStripViewController;
+- (void)didAddTabStripViewController;
 
 // Methods to populate the constraint properties.
 - (void)updateContentConstraintsWithStrip;
@@ -87,7 +87,7 @@
   [self.contentViewController didMoveToParentViewController:self];
 }
 
-- (void)setStripViewController:(UIViewController*)tabStripViewController {
+- (void)setTabStripViewController:(UIViewController*)tabStripViewController {
   if (self.tabStripViewController == tabStripViewController)
     return;
 
@@ -101,7 +101,7 @@
   tabStripViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:tabStripViewController.view];
   _tabStripViewController = tabStripViewController;
-  [self didAddStripViewController];
+  [self didAddTabStripViewController];
   [self.view setNeedsUpdateConstraints];
   [self.tabStripViewController didMoveToParentViewController:self];
 }
@@ -181,7 +181,7 @@
   }
 }
 
-- (void)didAddStripViewController {
+- (void)didAddTabStripViewController {
   [self updateStripConstraints];
   // If there's already a content view controller, update the constraints for
   // that, too.
diff --git a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
index cb9ea56..5a0f3ff 100644
--- a/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.mm
@@ -8,7 +8,7 @@
 
 #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h"
 
-#import "ios/clean/chrome/browser/ui/actions/tab_grid_actions.h"
+#import "ios/clean/chrome/browser/ui/actions/tab_strip_actions.h"
 #import "ios/clean/chrome/browser/ui/actions/tools_menu_actions.h"
 #import "ios/clean/chrome/browser/ui/commands/toolbar_commands.h"
 
@@ -35,7 +35,7 @@
   [tabSwitcher setTitle:@"⊞" forState:UIControlStateNormal];
   tabSwitcher.titleLabel.font = [UIFont systemFontOfSize:24.0];
   [tabSwitcher addTarget:nil
-                  action:@selector(showTabGrid:)
+                  action:@selector(toggleTabStrip:)
         forControlEvents:UIControlEventTouchUpInside];
 
   // Placeholder omnibox.
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h
index 8f5c7f19..7547b6b7 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.h
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -31,6 +31,8 @@
 @protocol LogoVendor;
 @protocol TextFieldStyling;
 @protocol NativeAppWhitelistManager;
+@class Tab;
+@class TabModel;
 @class UITextField;
 @class UIView;
 @protocol UrlLoader;
@@ -97,6 +99,7 @@
   // TODO(rohitrao): Change from |id| to |TabModel*| once TabModel is moved into
   // the Chromium tree.
   virtual void InitializeCastService(id main_tab_model) const;
+  virtual void InitializeCastService(TabModel* main_tab_model) const;
 
   // Attaches any embedder-specific tab helpers to the given |web_state|.  The
   // owning |tab| is included for helpers that need access to information that
@@ -104,6 +107,7 @@
   // TODO(rohitrao): Change from |id| to |Tab*| once Tab is moved into the
   // Chromium tree.
   virtual void AttachTabHelpers(web::WebState* web_state, id tab) const;
+  virtual void AttachTabHelpers(web::WebState* web_state, Tab* tab) const;
 
   // Returns whether safe browsing is enabled. See the comment on
   // metrics_services_manager_client.h for details on |on_update_callback|.
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
index d771c77..9e1d496 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -76,9 +76,23 @@
 
 void ChromeBrowserProvider::InitializeCastService(id main_tab_model) const {}
 
+void ChromeBrowserProvider::InitializeCastService(
+    TabModel* main_tab_model) const {
+  // Invokes the version taking an "id" as this is the only version currently
+  // overridden by the downstream provider.
+  InitializeCastService(static_cast<id>(main_tab_model));
+}
+
 void ChromeBrowserProvider::AttachTabHelpers(web::WebState* web_state,
                                              id tab) const {}
 
+void ChromeBrowserProvider::AttachTabHelpers(web::WebState* web_state,
+                                             Tab* tab) const {
+  // Invokes the version taking an "id" as this is the only version currently
+  // overridden by the downstream provider.
+  AttachTabHelpers(web_state, static_cast<id>(tab));
+}
+
 bool ChromeBrowserProvider::IsSafeBrowsingEnabled(
     const base::Closure& on_update_callback) {
   return false;
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc
index 878daf2..04636f3 100644
--- a/media/audio/audio_input_controller.cc
+++ b/media/audio/audio_input_controller.cc
@@ -4,6 +4,8 @@
 
 #include "media/audio/audio_input_controller.h"
 
+#include <inttypes.h>
+
 #include <algorithm>
 #include <limits>
 #include <utility>
@@ -20,6 +22,7 @@
 #include "media/audio/audio_file_writer.h"
 #include "media/base/user_input_monitor.h"
 
+namespace media {
 namespace {
 
 const int kMaxInputChannels = 3;
@@ -49,7 +52,7 @@
 
 // Helper method which calculates the average power of an audio bus. Unit is in
 // dBFS, where 0 dBFS corresponds to all channels and samples equal to 1.0.
-float AveragePower(const media::AudioBus& buffer) {
+float AveragePower(const AudioBus& buffer) {
   const int frames = buffer.frames();
   const int channels = buffer.channels();
   if (frames <= 0 || channels <= 0)
@@ -81,22 +84,125 @@
 
 }  // namespace
 
-namespace media {
+// Private subclass of AIC that covers the state while capturing audio.
+// This class implements the callback interface from the lower level audio
+// layer and gets called back on the audio hw thread.
+// We implement this in a sub class instead of directly in the AIC so that
+// - The AIC itself is not an AudioInputCallback.
+// - The lifetime of the AudioCallback is shorter than the AIC
+// - How tasks are posted to the AIC from the hw callback thread, is different
+//   than how tasks are posted from the AIC to itself from the main thread.
+//   So, this difference is isolated to the subclass (see below).
+// - The callback class can gather information on what happened during capture
+//   and store it in a state that can be fetched after stopping capture
+//   (received_callback, error_during_callback).
+// The AIC itself must not be AddRef-ed on the hw callback thread so that we
+// can be guaranteed to not receive callbacks generated by the hw callback
+// thread after Close() has been called on the audio manager thread and
+// the callback object deleted. To avoid AddRef-ing the AIC and to cancel
+// potentially pending tasks, we use a weak pointer to the AIC instance
+// when posting.
+class AudioInputController::AudioCallback
+    : public AudioInputStream::AudioInputCallback {
+ public:
+  explicit AudioCallback(AudioInputController* controller)
+      : controller_(controller),
+        weak_controller_(controller->weak_ptr_factory_.GetWeakPtr()) {}
+  ~AudioCallback() override {}
+
+  bool received_callback() const { return received_callback_; }
+  bool error_during_callback() const { return error_during_callback_; }
+
+ private:
+  void OnData(AudioInputStream* stream,
+              const AudioBus* source,
+              uint32_t hardware_delay_bytes,
+              double volume) override {
+    TRACE_EVENT0("audio", "AC::OnData");
+
+    received_callback_ = true;
+
+    DeliverDataToSyncWriter(source, hardware_delay_bytes, volume);
+    PerformOptionalDebugRecording(source);
+  }
+
+  void OnError(AudioInputStream* stream) override {
+    error_during_callback_ = true;
+    controller_->task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&AudioInputController::DoReportError, weak_controller_));
+  }
+
+  void PerformOptionalDebugRecording(const AudioBus* source) {
+    // Called on the hw callback thread while recording is enabled.
+    if (!controller_->debug_writer_ || !controller_->debug_writer_->WillWrite())
+      return;
+
+    // TODO(tommi): This is costly. AudioBus heap allocs and we create a new
+    // one for every callback. We could instead have a pool of bus objects
+    // that get returned to us somehow.
+    // We should also avoid calling PostTask here since the implementation
+    // of the debug writer will basically do a PostTask straight away anyway.
+    // Might require some modifications to AudioInputDebugWriter though since
+    // there are some threading concerns there and AudioInputDebugWriter's
+    // lifetime guarantees need to be longer than that of associated active
+    // audio streams.
+    std::unique_ptr<AudioBus> source_copy =
+        AudioBus::Create(source->channels(), source->frames());
+    source->CopyTo(source_copy.get());
+    controller_->task_runner_->PostTask(
+        FROM_HERE, base::Bind(&AudioInputController::WriteInputDataForDebugging,
+                              weak_controller_, base::Passed(&source_copy)));
+  }
+
+  void DeliverDataToSyncWriter(const AudioBus* source,
+                               uint32_t hardware_delay_bytes,
+                               double volume) {
+    bool key_pressed = controller_->CheckForKeyboardInput();
+    controller_->sync_writer_->Write(source, volume, key_pressed,
+                                     hardware_delay_bytes);
+
+    // The way the two classes interact here, could be done in a nicer way.
+    // As is, we call the AIC here to check the audio power, return  and then
+    // post a task to the AIC based on what the AIC said.
+    // The reason for this is to keep all PostTask calls from the hw callback
+    // thread to the AIC, that use a weak pointer, in the same class.
+    float average_power_dbfs;
+    int mic_volume_percent;
+    if (controller_->CheckAudioPower(source, volume, &average_power_dbfs,
+                                     &mic_volume_percent)) {
+      // Use event handler on the audio thread to relay a message to the ARIH
+      // in content which does the actual logging on the IO thread.
+      controller_->task_runner_->PostTask(
+          FROM_HERE,
+          base::Bind(&AudioInputController::DoLogAudioLevels, weak_controller_,
+                     average_power_dbfs, mic_volume_percent));
+    }
+  }
+
+  AudioInputController* const controller_;
+  // We do not want any pending posted tasks generated from the callback class
+  // to keep the controller object alive longer than it should. So we use
+  // a weak ptr whenever we post, we use this weak pointer.
+  base::WeakPtr<AudioInputController> weak_controller_;
+  bool received_callback_ = false;
+  bool error_during_callback_ = false;
+};
 
 // static
 AudioInputController::Factory* AudioInputController::factory_ = nullptr;
 
 AudioInputController::AudioInputController(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     EventHandler* handler,
     SyncWriter* sync_writer,
     std::unique_ptr<AudioFileWriter> debug_writer,
     UserInputMonitor* user_input_monitor,
     const bool agc_is_enabled)
     : creator_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      task_runner_(std::move(task_runner)),
       handler_(handler),
       stream_(nullptr),
-      should_report_stats(0),
-      state_(CLOSED),
       sync_writer_(sync_writer),
       max_volume_(0.0),
       user_input_monitor_(user_input_monitor),
@@ -107,36 +213,42 @@
       silence_state_(SILENCE_STATE_NO_MEASUREMENT),
 #endif
       prev_key_down_count_(0),
-      debug_writer_(std::move(debug_writer)) {
+      debug_writer_(std::move(debug_writer)),
+      weak_ptr_factory_(this) {
   DCHECK(creator_task_runner_.get());
+  DCHECK(handler_);
+  DCHECK(sync_writer_);
 }
 
 AudioInputController::~AudioInputController() {
-  DCHECK_EQ(state_, CLOSED);
+  DCHECK(!audio_callback_);
+  DCHECK(!stream_);
 }
 
 // static
 scoped_refptr<AudioInputController> AudioInputController::Create(
     AudioManager* audio_manager,
     EventHandler* event_handler,
+    SyncWriter* sync_writer,
     const AudioParameters& params,
     const std::string& device_id,
     UserInputMonitor* user_input_monitor) {
   DCHECK(audio_manager);
+  DCHECK(event_handler);
+  DCHECK(sync_writer);
 
   if (!params.IsValid() || (params.channels() > kMaxInputChannels))
     return nullptr;
 
   if (factory_) {
-    return factory_->Create(audio_manager->GetTaskRunner(),
-                            /*sync_writer*/ nullptr, audio_manager,
-                            event_handler, params, user_input_monitor);
+    return factory_->Create(audio_manager->GetTaskRunner(), sync_writer,
+                            audio_manager, event_handler, params,
+                            user_input_monitor);
   }
 
   scoped_refptr<AudioInputController> controller(new AudioInputController(
-      event_handler, nullptr, nullptr, user_input_monitor, false));
-
-  controller->task_runner_ = audio_manager->GetTaskRunner();
+      audio_manager->GetTaskRunner(), event_handler, sync_writer, nullptr,
+      user_input_monitor, false));
 
   // Create and open a new audio input stream from the existing
   // audio-device thread.
@@ -165,6 +277,7 @@
     const bool agc_is_enabled) {
   DCHECK(audio_manager);
   DCHECK(sync_writer);
+  DCHECK(event_handler);
 
   if (!params.IsValid() || (params.channels() > kMaxInputChannels))
     return nullptr;
@@ -178,9 +291,8 @@
   // Create the AudioInputController object and ensure that it runs on
   // the audio-manager thread.
   scoped_refptr<AudioInputController> controller(new AudioInputController(
-      event_handler, sync_writer, std::move(debug_writer), user_input_monitor,
-      agc_is_enabled));
-  controller->task_runner_ = audio_manager->GetTaskRunner();
+      audio_manager->GetTaskRunner(), event_handler, sync_writer,
+      std::move(debug_writer), user_input_monitor, agc_is_enabled));
 
   // Create and open a new audio input stream from the existing
   // audio-device thread. Use the provided audio-input device.
@@ -207,19 +319,19 @@
     UserInputMonitor* user_input_monitor) {
   DCHECK(sync_writer);
   DCHECK(stream);
+  DCHECK(event_handler);
 
   if (factory_) {
     return factory_->Create(
         task_runner, sync_writer, AudioManager::Get(), event_handler,
-        media::AudioParameters::UnavailableDeviceParams(), user_input_monitor);
+        AudioParameters::UnavailableDeviceParams(), user_input_monitor);
   }
 
   // Create the AudioInputController object and ensure that it runs on
   // the audio-manager thread.
   scoped_refptr<AudioInputController> controller(new AudioInputController(
-      event_handler, sync_writer, std::move(debug_writer), user_input_monitor,
-      false));
-  controller->task_runner_ = task_runner;
+      task_runner, event_handler, sync_writer, std::move(debug_writer),
+      user_input_monitor, false));
 
   if (!controller->task_runner_->PostTask(
           FROM_HERE,
@@ -233,6 +345,7 @@
 }
 
 void AudioInputController::Record() {
+  DCHECK(creator_task_runner_->BelongsToCurrentThread());
   task_runner_->PostTask(FROM_HERE, base::Bind(
       &AudioInputController::DoRecord, this));
 }
@@ -246,6 +359,7 @@
 }
 
 void AudioInputController::SetVolume(double volume) {
+  DCHECK(creator_task_runner_->BelongsToCurrentThread());
   task_runner_->PostTask(FROM_HERE, base::Bind(
       &AudioInputController::DoSetVolume, this, volume));
 }
@@ -254,9 +368,9 @@
                                     const AudioParameters& params,
                                     const std::string& device_id) {
   DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK(!stream_);
   SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime");
-  if (handler_)
-    handler_->OnLog(this, "AIC::DoCreate");
+  handler_->OnLog(this, "AIC::DoCreate");
 
 #if defined(AUDIO_POWER_MONITORING)
   // Disable power monitoring for streams that run without AGC enabled to
@@ -266,6 +380,8 @@
   silence_state_ = SILENCE_STATE_NO_MEASUREMENT;
 #endif
 
+  // MakeAudioInputStream might fail and return nullptr. If so,
+  // DoCreateForStream will handle and report it.
   DoCreateForStream(audio_manager->MakeAudioInputStream(
       params, device_id, base::Bind(&AudioInputController::LogMessage, this)));
 }
@@ -289,99 +405,94 @@
 void AudioInputController::DoCreateForStream(
     AudioInputStream* stream_to_control) {
   DCHECK(task_runner_->BelongsToCurrentThread());
-
   DCHECK(!stream_);
-  stream_ = stream_to_control;
-  should_report_stats = 1;
 
-  if (!stream_) {
-    if (handler_)
-      handler_->OnError(this, STREAM_CREATE_ERROR);
+  if (!stream_to_control) {
     LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED);
+    handler_->OnError(this, STREAM_CREATE_ERROR);
     return;
   }
 
-  if (stream_ && !stream_->Open()) {
-    stream_->Close();
-    stream_ = nullptr;
-    if (handler_)
-      handler_->OnError(this, STREAM_OPEN_ERROR);
+  if (!stream_to_control->Open()) {
+    stream_to_control->Close();
     LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED);
+    handler_->OnError(this, STREAM_OPEN_ERROR);
     return;
   }
 
   // Set AGC state using mode in |agc_is_enabled_| which can only be enabled in
   // CreateLowLatency().
 #if defined(AUDIO_POWER_MONITORING)
-  bool agc_is_supported = false;
-  agc_is_supported = stream_->SetAutomaticGainControl(agc_is_enabled_);
+  bool agc_is_supported =
+      stream_to_control->SetAutomaticGainControl(agc_is_enabled_);
   // Disable power measurements on platforms that does not support AGC at a
   // lower level. AGC can fail on platforms where we don't support the
   // functionality to modify the input volume slider. One such example is
   // Windows XP.
   power_measurement_is_enabled_ &= agc_is_supported;
 #else
-  stream_->SetAutomaticGainControl(agc_is_enabled_);
+  stream_to_control->SetAutomaticGainControl(agc_is_enabled_);
 #endif
 
-
-  state_ = CREATED;
-  if (handler_)
-    handler_->OnCreated(this);
-
-  if (user_input_monitor_) {
-    user_input_monitor_->EnableKeyPressMonitoring();
-    prev_key_down_count_ = user_input_monitor_->GetKeyPressCount();
-  }
+  // Finally, keep the stream pointer around, update the state and notify.
+  stream_ = stream_to_control;
+  handler_->OnCreated(this);
 }
 
 void AudioInputController::DoRecord() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
 
-  if (state_ != CREATED)
+  if (!stream_ || audio_callback_)
     return;
 
-  {
-    base::AutoLock auto_lock(lock_);
-    state_ = RECORDING;
+  handler_->OnLog(this, "AIC::DoRecord");
+
+  if (user_input_monitor_) {
+    user_input_monitor_->EnableKeyPressMonitoring();
+    prev_key_down_count_ = user_input_monitor_->GetKeyPressCount();
   }
 
-  if (handler_)
-    handler_->OnLog(this, "AIC::DoRecord");
-
-  stream_->Start(this);
+  audio_callback_.reset(new AudioCallback(this));
+  stream_->Start(audio_callback_.get());
 }
 
 void AudioInputController::DoClose() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
-  // If we have already logged something, this does nothing.
-  // Otherwise, we haven't recieved data.
-  LogCaptureStartupResult(CAPTURE_STARTUP_NEVER_GOT_DATA);
 
-  if (state_ == CLOSED)
+  if (!stream_)
     return;
 
-  // If this is a low-latency stream, log the total duration (since DoCreate)
-  // and add it to a UMA histogram.
-  if (!low_latency_create_time_.is_null()) {
-    base::TimeDelta duration =
-        base::TimeTicks::Now() - low_latency_create_time_;
-    UMA_HISTOGRAM_LONG_TIMES("Media.InputStreamDuration", duration);
-    if (handler_) {
-      std::string log_string =
-          base::StringPrintf("AIC::DoClose: stream duration=");
-      log_string += base::Int64ToString(duration.InSeconds());
-      log_string += " seconds";
-      handler_->OnLog(this, log_string);
+  // Allow calling unconditionally and bail if we don't have a stream to close.
+  if (audio_callback_) {
+    stream_->Stop();
+
+    if (!low_latency_create_time_.is_null()) {
+      LogCaptureStartupResult(audio_callback_->received_callback()
+                                  ? CAPTURE_STARTUP_OK
+                                  : CAPTURE_STARTUP_NEVER_GOT_DATA);
+      UMA_HISTOGRAM_BOOLEAN("Media.Audio.Capture.CallbackError",
+                            audio_callback_->error_during_callback());
+      if (audio_callback_->received_callback()) {
+        // Log the total duration (since DoCreate) and update the histogram.
+        const base::TimeDelta duration =
+            base::TimeTicks::Now() - low_latency_create_time_;
+        UMA_HISTOGRAM_LONG_TIMES("Media.InputStreamDuration", duration);
+        const std::string log_string = base::StringPrintf(
+            "AIC::DoClose: stream duration=%" PRId64 " seconds",
+            duration.InSeconds());
+        handler_->OnLog(this, log_string);
+      }
     }
+
+    audio_callback_.reset();
   }
 
-  DoStopCloseAndClearStream();
+  stream_->Close();
+  stream_ = nullptr;
 
-  if (SharedMemoryAndSyncSocketMode())
-    sync_writer_->Close();
+  sync_writer_->Close();
 
   if (user_input_monitor_)
     user_input_monitor_->DisableKeyPressMonitoring();
@@ -396,13 +507,14 @@
   if (debug_writer_)
     debug_writer_->Stop();
 
-  state_ = CLOSED;
+  max_volume_ = 0.0;
+  low_latency_create_time_ = base::TimeTicks();  // Reset to null.
+  weak_ptr_factory_.InvalidateWeakPtrs();
 }
 
 void AudioInputController::DoReportError() {
   DCHECK(task_runner_->BelongsToCurrentThread());
-  if (handler_)
-    handler_->OnError(this, STREAM_ERROR);
+  handler_->OnError(this, STREAM_ERROR);
 }
 
 void AudioInputController::DoSetVolume(double volume) {
@@ -410,7 +522,7 @@
   DCHECK_GE(volume, 0);
   DCHECK_LE(volume, 1.0);
 
-  if (state_ != CREATED && state_ != RECORDING)
+  if (!stream_)
     return;
 
   // Only ask for the maximum volume at first call and use cached value
@@ -428,100 +540,11 @@
   stream_->SetVolume(max_volume_ * volume);
 }
 
-void AudioInputController::OnData(AudioInputStream* stream,
-                                  const AudioBus* source,
-                                  uint32_t hardware_delay_bytes,
-                                  double volume) {
-  TRACE_EVENT0("audio", "AudioInputController::OnData");
-  if (debug_writer_ && debug_writer_->WillWrite()) {
-    std::unique_ptr<AudioBus> source_copy =
-        AudioBus::Create(source->channels(), source->frames());
-    source->CopyTo(source_copy.get());
-    task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(
-            &AudioInputController::WriteInputDataForDebugging,
-            this,
-            base::Passed(&source_copy)));
-  }
-  // Now we have data, so we know for sure that startup was ok.
-  LogCaptureStartupResult(CAPTURE_STARTUP_OK);
-
-  {
-    base::AutoLock auto_lock(lock_);
-    if (state_ != RECORDING)
-      return;
-  }
-
-  bool key_pressed = false;
-  if (user_input_monitor_) {
-    size_t current_count = user_input_monitor_->GetKeyPressCount();
-    key_pressed = current_count != prev_key_down_count_;
-    prev_key_down_count_ = current_count;
-    DVLOG_IF(6, key_pressed) << "Detected keypress.";
-  }
-
-  // Use SharedMemory and SyncSocket if the client has created a SyncWriter.
-  // Used by all low-latency clients except WebSpeech.
-  if (SharedMemoryAndSyncSocketMode()) {
-    sync_writer_->Write(source, volume, key_pressed, hardware_delay_bytes);
-
-#if defined(AUDIO_POWER_MONITORING)
-    // Only do power-level measurements if DoCreate() has been called. It will
-    // ensure that logging will mainly be done for WebRTC and WebSpeech
-    // clients.
-    if (!power_measurement_is_enabled_)
-      return;
-
-    // Perform periodic audio (power) level measurements.
-    if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() >
-        kPowerMonitorLogIntervalSeconds) {
-      // Calculate the average power of the signal, or the energy per sample.
-      const float average_power_dbfs = AveragePower(*source);
-
-      // Add current microphone volume to log and UMA histogram.
-      const int mic_volume_percent = static_cast<int>(100.0 * volume);
-
-      // Use event handler on the audio thread to relay a message to the ARIH
-      // in content which does the actual logging on the IO thread.
-      task_runner_->PostTask(FROM_HERE,
-                             base::Bind(&AudioInputController::DoLogAudioLevels,
-                                        this,
-                                        average_power_dbfs,
-                                        mic_volume_percent));
-
-      last_audio_level_log_time_ = base::TimeTicks::Now();
-    }
-#endif
-    return;
-  }
-
-  // TODO(henrika): Investigate if we can avoid the extra copy here.
-  // (see http://crbug.com/249316 for details). AFAIK, this scope is only
-  // active for WebSpeech clients.
-  std::unique_ptr<AudioBus> audio_data =
-      AudioBus::Create(source->channels(), source->frames());
-  source->CopyTo(audio_data.get());
-
-  // Ownership of the audio buffer will be with the callback until it is run,
-  // when ownership is passed to the callback function.
-  task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(
-          &AudioInputController::DoOnData, this, base::Passed(&audio_data)));
-}
-
-void AudioInputController::DoOnData(std::unique_ptr<AudioBus> data) {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  if (handler_)
-    handler_->OnData(this, data.get());
-}
-
 void AudioInputController::DoLogAudioLevels(float level_dbfs,
                                             int microphone_volume_percent) {
 #if defined(AUDIO_POWER_MONITORING)
   DCHECK(task_runner_->BelongsToCurrentThread());
-  if (!handler_)
+  if (!stream_)
     return;
 
   // Detect if the user has enabled hardware mute by pressing the mute
@@ -555,14 +578,9 @@
 #endif
 }
 
-void AudioInputController::OnError(AudioInputStream* stream) {
-  // Handle error on the audio-manager thread.
-  task_runner_->PostTask(FROM_HERE, base::Bind(
-      &AudioInputController::DoReportError, this));
-}
-
 void AudioInputController::EnableDebugRecording(
     const base::FilePath& file_name) {
+  DCHECK(creator_task_runner_->BelongsToCurrentThread());
   task_runner_->PostTask(
       FROM_HERE, base::Bind(&AudioInputController::DoEnableDebugRecording, this,
                             file_name));
@@ -575,20 +593,6 @@
       base::Bind(&AudioInputController::DoDisableDebugRecording, this));
 }
 
-void AudioInputController::DoStopCloseAndClearStream() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-
-  // Allow calling unconditionally and bail if we don't have a stream to close.
-  if (stream_ != nullptr) {
-    stream_->Stop();
-    stream_->Close();
-    stream_ = nullptr;
-  }
-
-  // The event handler should not be touched after the stream has been closed.
-  handler_ = nullptr;
-}
-
 #if defined(AUDIO_POWER_MONITORING)
 void AudioInputController::UpdateSilenceState(bool silence) {
   if (silence) {
@@ -621,15 +625,8 @@
 
 void AudioInputController::LogCaptureStartupResult(
     CaptureStartupResult result) {
-  // Decrement shall_report_stats and check if it was 1 before decrement,
-  // which would imply that this is the first time this method is called
-  // after initialization. To avoid underflow, we
-  // also check if should_report_stats is one before decrementing.
-  if (base::AtomicRefCountIsOne(&should_report_stats) &&
-      !base::AtomicRefCountDec(&should_report_stats)) {
-    UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess",
-                              result, CAPTURE_STARTUP_RESULT_MAX + 1);
-  }
+  UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess",
+                            result, CAPTURE_STARTUP_RESULT_MAX + 1);
 }
 
 void AudioInputController::DoEnableDebugRecording(
@@ -657,4 +654,45 @@
   handler_->OnLog(this, message);
 }
 
+bool AudioInputController::CheckForKeyboardInput() {
+  if (!user_input_monitor_)
+    return false;
+
+  const size_t current_count = user_input_monitor_->GetKeyPressCount();
+  const bool key_pressed = current_count != prev_key_down_count_;
+  prev_key_down_count_ = current_count;
+  DVLOG_IF(6, key_pressed) << "Detected keypress.";
+
+  return key_pressed;
+}
+
+bool AudioInputController::CheckAudioPower(const AudioBus* source,
+                                           double volume,
+                                           float* average_power_dbfs,
+                                           int* mic_volume_percent) {
+#if defined(AUDIO_POWER_MONITORING)
+  // Only do power-level measurements if DoCreate() has been called. It will
+  // ensure that logging will mainly be done for WebRTC and WebSpeech
+  // clients.
+  if (!power_measurement_is_enabled_)
+    return false;
+
+  // Perform periodic audio (power) level measurements.
+  const auto now = base::TimeTicks::Now();
+  if ((now - last_audio_level_log_time_).InSeconds() <=
+      kPowerMonitorLogIntervalSeconds) {
+    return false;
+  }
+
+  *average_power_dbfs = AveragePower(*source);
+  *mic_volume_percent = static_cast<int>(100.0 * volume);
+
+  last_audio_level_log_time_ = now;
+
+  return true;
+#else
+  return false;
+#endif
+}
+
 }  // namespace media
diff --git a/media/audio/audio_input_controller.h b/media/audio/audio_input_controller.h
index ef691f1..cfd6592 100644
--- a/media/audio/audio_input_controller.h
+++ b/media/audio/audio_input_controller.h
@@ -11,15 +11,8 @@
 #include <memory>
 #include <string>
 
-#include "base/atomicops.h"
-#include "base/callback.h"
 #include "base/files/file.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "build/build_config.h"
+#include "base/memory/weak_ptr.h"
 #include "media/audio/audio_io.h"
 #include "media/audio/audio_manager_base.h"
 #include "media/base/audio_bus.h"
@@ -55,14 +48,11 @@
 //                        AudioInputStream::Open()
 //                                  .- - - - - - - - - - - - ->   OnError()
 //                                  .------------------------->  OnCreated()
-//                               kCreated
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 // Record() ==>                 DoRecord()
 //                      AudioInputStream::Start()
-//                              kRecording
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 // Close() ==>                  DoClose()
-//                           state_ = kClosed
 //                        AudioInputStream::Stop()
 //                        AudioInputStream::Close()
 //                          SyncWriter::Close()
@@ -85,8 +75,7 @@
 class UserInputMonitor;
 
 class MEDIA_EXPORT AudioInputController
-    : public base::RefCountedThreadSafe<AudioInputController>,
-      public AudioInputStream::AudioInputCallback {
+    : public base::RefCountedThreadSafe<AudioInputController> {
  public:
   // Error codes to make native logging more clear. These error codes are added
   // to generic error strings to provide a higher degree of details.
@@ -114,8 +103,6 @@
     virtual void OnCreated(AudioInputController* controller) = 0;
     virtual void OnError(AudioInputController* controller,
                          ErrorCode error_code) = 0;
-    virtual void OnData(AudioInputController* controller,
-                        const AudioBus* data) = 0;
     virtual void OnLog(AudioInputController* controller,
                        const std::string& message) = 0;
 
@@ -164,6 +151,7 @@
   static scoped_refptr<AudioInputController> Create(
       AudioManager* audio_manager,
       EventHandler* event_handler,
+      SyncWriter* sync_writer,
       const AudioParameters& params,
       const std::string& device_id,
       UserInputMonitor* user_input_monitor);
@@ -221,16 +209,6 @@
   // to muted and 1.0 to maximum volume.
   virtual void SetVolume(double volume);
 
-  // AudioInputCallback implementation. Threading details depends on the
-  // device-specific implementation.
-  void OnData(AudioInputStream* stream,
-              const AudioBus* source,
-              uint32_t hardware_delay_bytes,
-              double volume) override;
-  void OnError(AudioInputStream* stream) override;
-
-  bool SharedMemoryAndSyncSocketMode() const { return sync_writer_ != NULL; }
-
   // Enable debug recording of audio input.
   virtual void EnableDebugRecording(const base::FilePath& file_name);
 
@@ -260,13 +238,6 @@
     CAPTURE_STARTUP_RESULT_MAX = CAPTURE_STARTUP_NEVER_GOT_DATA
   };
 
-  // Internal state of the source.
-  enum State {
-    CREATED,
-    RECORDING,
-    CLOSED
-  };
-
 #if defined(AUDIO_POWER_MONITORING)
   // Used to log a silence report (see OnData).
   // Elements in this enum should not be deleted or rearranged; the only
@@ -287,13 +258,22 @@
   };
 #endif
 
-  AudioInputController(EventHandler* handler,
+  AudioInputController(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                       EventHandler* handler,
                        SyncWriter* sync_writer,
                        std::unique_ptr<AudioFileWriter> debug_writer,
                        UserInputMonitor* user_input_monitor,
                        const bool agc_is_enabled);
-  ~AudioInputController() override;
+  virtual ~AudioInputController();
 
+  const scoped_refptr<base::SingleThreadTaskRunner>& GetTaskRunnerForTesting()
+      const {
+    return task_runner_;
+  }
+
+  EventHandler* GetHandlerForTesting() const { return handler_; }
+
+ private:
   // Methods called on the audio thread (owned by the AudioManager).
   void DoCreate(AudioManager* audio_manager,
                 const AudioParameters& params,
@@ -306,12 +286,8 @@
   void DoClose();
   void DoReportError();
   void DoSetVolume(double volume);
-  void DoOnData(std::unique_ptr<AudioBus> data);
   void DoLogAudioLevels(float level_dbfs, int microphone_volume_percent);
 
-  // Helper method that stops, closes, and NULL:s |*stream_|.
-  void DoStopCloseAndClearStream();
-
 #if defined(AUDIO_POWER_MONITORING)
   // Updates the silence state, see enum SilenceState above for state
   // transitions.
@@ -336,44 +312,49 @@
   // Called by the stream with log messages.
   void LogMessage(const std::string& message);
 
+  // Called on the hw callback thread. Checks for keyboard input if
+  // user_input_monitor_ is set otherwise returns false.
+  bool CheckForKeyboardInput();
+
+  // Does power monitoring on supported platforms.
+  // Called on the hw callback thread.
+  // Returns true iff average power and mic volume was returned and should
+  // be posted to DoLogAudioLevels on the audio thread.
+  // Returns false if either power measurements are disabled or aren't needed
+  // right now (they're done periodically).
+  bool CheckAudioPower(const AudioBus* source,
+                       double volume,
+                       float* average_power_dbfs,
+                       int* mic_volume_percent);
+
   // Gives access to the task runner of the creating thread.
-  scoped_refptr<base::SingleThreadTaskRunner> creator_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> const creator_task_runner_;
 
   // The task runner of audio-manager thread that this object runs on.
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> const task_runner_;
 
   // Contains the AudioInputController::EventHandler which receives state
   // notifications from this class.
-  EventHandler* handler_;
+  EventHandler* const handler_;
 
   // Pointer to the audio input stream object.
+  // Only used on the audio thread.
   AudioInputStream* stream_;
 
-  // Flag for whether CaptureStartupResults shall be reported.
-  // A value of 1 means that stats shall be reported,
-  // any other value means that stats have already been reported.
-  base::AtomicRefCount should_report_stats;
-
-  // |state_| is written on the audio thread and is read on the hardware audio
-  // thread. These operations need to be locked. But lock is not required for
-  // reading on the audio input controller thread.
-  State state_;
-
-  base::Lock lock_;
-
   // SyncWriter is used only in low-latency mode for synchronous writing.
-  SyncWriter* sync_writer_;
+  SyncWriter* const sync_writer_;
 
   static Factory* factory_;
 
   double max_volume_;
 
-  UserInputMonitor* user_input_monitor_;
+  UserInputMonitor* const user_input_monitor_;
 
   const bool agc_is_enabled_;
 
 #if defined(AUDIO_POWER_MONITORING)
-  // Enabled in DoCrete() but not in DoCreateForStream().
+  // Will be set to true if an AGC is supported and enabled (see DoCreate and
+  // DoCreateForStream). By default set to false.
   bool power_measurement_is_enabled_;
 
   // Updated each time a power measurement is performed.
@@ -394,7 +375,29 @@
   // Used for audio debug recordings. Accessed on audio thread.
   const std::unique_ptr<AudioFileWriter> debug_writer_;
 
- private:
+  class AudioCallback;
+  // Holds a pointer to the callback object that receives audio data from
+  // the lower audio layer. Valid only while 'recording' (between calls to
+  // stream_->Start() and stream_->Stop()).
+  // The value of this pointer is only set and read on the audio thread while
+  // the callbacks themselves occur on the hw callback thread. More details
+  // in the AudioCallback class in the cc file.
+  std::unique_ptr<AudioCallback> audio_callback_;
+
+  // A weak pointer factory that we use when posting tasks to the audio thread
+  // that we want to be automatically discarded after Close() has been called
+  // and that we do not want to keep the AudioInputController instance alive
+  // beyond what is desired by the user of the instance (e.g.
+  // AudioInputRendererHost). An example of where this is important is when
+  // we fire error notifications from the hw callback thread, post them to
+  // the audio thread. In that case, we do not want the error notification to
+  // keep the AudioInputController alive for as long as the error notification
+  // is pending and then make a callback from an AudioInputController that has
+  // already been closed.
+  // The weak_ptr_factory_ and all outstanding weak pointers, are invalidated
+  // at the end of DoClose.
+  base::WeakPtrFactory<AudioInputController> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(AudioInputController);
 };
 
diff --git a/media/audio/audio_input_controller_unittest.cc b/media/audio/audio_input_controller_unittest.cc
index 6d44002..fdf6120 100644
--- a/media/audio/audio_input_controller_unittest.cc
+++ b/media/audio/audio_input_controller_unittest.cc
@@ -8,16 +8,19 @@
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
+#include "base/threading/thread.h"
 #include "media/audio/audio_device_description.h"
 #include "media/audio/audio_input_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::_;
+using ::testing::AnyNumber;
 using ::testing::AtLeast;
 using ::testing::Exactly;
 using ::testing::InvokeWithoutArgs;
 using ::testing::NotNull;
+using base::WaitableEvent;
 
 namespace media {
 
@@ -53,8 +56,6 @@
   MOCK_METHOD1(OnCreated, void(AudioInputController* controller));
   MOCK_METHOD2(OnError, void(AudioInputController* controller,
                              AudioInputController::ErrorCode error_code));
-  MOCK_METHOD2(OnData,
-               void(AudioInputController* controller, const AudioBus* data));
   MOCK_METHOD2(OnLog,
                void(AudioInputController* controller,
                     const std::string& message));
@@ -63,23 +64,57 @@
   DISALLOW_COPY_AND_ASSIGN(MockAudioInputControllerEventHandler);
 };
 
+class MockSyncWriter : public AudioInputController::SyncWriter {
+ public:
+  MockSyncWriter() {}
+
+  MOCK_METHOD4(Write,
+               void(const AudioBus* data,
+                    double volume,
+                    bool key_pressed,
+                    uint32_t hardware_delay_bytes));
+  MOCK_METHOD0(Close, void());
+};
+
 // Test fixture.
 class AudioInputControllerTest : public testing::Test {
  public:
   AudioInputControllerTest()
-      : audio_manager_(
-            AudioManager::CreateForTesting(message_loop_.task_runner())) {
-    // Flush the message loop to ensure that AudioManager is fully initialized.
-    base::RunLoop().RunUntilIdle();
+      : audio_thread_("AudioThread"),
+        suspend_event_(WaitableEvent::ResetPolicy::AUTOMATIC,
+                       WaitableEvent::InitialState::NOT_SIGNALED) {
+    audio_thread_.StartAndWaitForTesting();
+    audio_manager_ =
+        AudioManager::CreateForTesting(audio_thread_.task_runner());
   }
   ~AudioInputControllerTest() override {
-    audio_manager_.reset();
-    base::RunLoop().RunUntilIdle();
+    audio_task_runner()->PostTask(
+        FROM_HERE, base::Bind(&AudioInputControllerTest::DeleteAudioManager,
+                              base::Unretained(this)));
+    audio_thread_.Stop();
   }
 
+  scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner() const {
+    return audio_thread_.task_runner();
+  }
+
+  void SuspendAudioThread() {
+    audio_task_runner()->PostTask(
+        FROM_HERE, base::Bind(&AudioInputControllerTest::WaitForResume,
+                              base::Unretained(this)));
+  }
+
+  void ResumeAudioThread() { suspend_event_.Signal(); }
+
+ private:
+  void DeleteAudioManager() { audio_manager_.reset(); }
+  void WaitForResume() { suspend_event_.Wait(); }
+
  protected:
+  base::Thread audio_thread_;
   base::MessageLoop message_loop_;
   ScopedAudioManagerPtr audio_manager_;
+  WaitableEvent suspend_event_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AudioInputControllerTest);
@@ -90,56 +125,59 @@
   base::RunLoop run_loop;
 
   MockAudioInputControllerEventHandler event_handler;
-
-  // OnCreated() will be posted once.
-  EXPECT_CALL(event_handler, OnCreated(NotNull()))
-      .WillOnce(QuitRunLoop(&run_loop));
+  MockSyncWriter sync_writer;
+  scoped_refptr<AudioInputController> controller;
 
   AudioParameters params(AudioParameters::AUDIO_FAKE, kChannelLayout,
                          kSampleRate, kBitsPerSample, kSamplesPerPacket);
 
-  scoped_refptr<AudioInputController> controller = AudioInputController::Create(
-      audio_manager_.get(), &event_handler, params,
+  SuspendAudioThread();
+  controller = AudioInputController::Create(
+      audio_manager_.get(), &event_handler, &sync_writer, params,
       AudioDeviceDescription::kDefaultDeviceId, NULL);
   ASSERT_TRUE(controller.get());
+  EXPECT_CALL(event_handler, OnCreated(controller.get())).Times(Exactly(1));
+  EXPECT_CALL(event_handler, OnLog(controller.get(), _));
+  EXPECT_CALL(sync_writer, Close()).Times(Exactly(1));
+  ResumeAudioThread();
 
-  // Wait for OnCreated() to fire.
-  run_loop.Run();
-
-  // Close the AudioInputController synchronously.
   CloseAudioController(controller.get());
+
+  audio_thread_.FlushForTesting();
 }
 
 // Test a normal call sequence of create, record and close.
 TEST_F(AudioInputControllerTest, RecordAndClose) {
   MockAudioInputControllerEventHandler event_handler;
+  MockSyncWriter sync_writer;
   int count = 0;
 
   // OnCreated() will be called once.
   EXPECT_CALL(event_handler, OnCreated(NotNull()))
       .Times(Exactly(1));
 
-  // OnData() shall be called ten times.
-  EXPECT_CALL(event_handler, OnData(NotNull(), NotNull()))
+  // Write() should be called ten times.
+  EXPECT_CALL(sync_writer, Write(NotNull(), _, _, _))
       .Times(AtLeast(10))
-      .WillRepeatedly(CheckCountAndPostQuitTask(
-          &count, 10, message_loop_.task_runner()));
+      .WillRepeatedly(
+          CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner()));
+
+  EXPECT_CALL(event_handler, OnLog(_, _)).Times(AnyNumber());
+  EXPECT_CALL(sync_writer, Close()).Times(Exactly(1));
 
   AudioParameters params(AudioParameters::AUDIO_FAKE, kChannelLayout,
                          kSampleRate, kBitsPerSample, kSamplesPerPacket);
 
   // Creating the AudioInputController should render an OnCreated() call.
   scoped_refptr<AudioInputController> controller = AudioInputController::Create(
-      audio_manager_.get(), &event_handler, params,
+      audio_manager_.get(), &event_handler, &sync_writer, params,
       AudioDeviceDescription::kDefaultDeviceId, NULL);
   ASSERT_TRUE(controller.get());
 
   controller->Record();
 
-  // Record and wait until ten OnData() callbacks are received.
+  // Record and wait until ten Write() callbacks are received.
   base::RunLoop().Run();
-
-  // Close the AudioInputController synchronously.
   CloseAudioController(controller.get());
 }
 
@@ -147,10 +185,10 @@
 TEST_F(AudioInputControllerTest, SamplesPerPacketTooLarge) {
   // Create an audio device with a very large packet size.
   MockAudioInputControllerEventHandler event_handler;
+  MockSyncWriter sync_writer;
 
   // OnCreated() shall not be called in this test.
-  EXPECT_CALL(event_handler, OnCreated(NotNull()))
-    .Times(Exactly(0));
+  EXPECT_CALL(event_handler, OnCreated(NotNull())).Times(Exactly(0));
 
   AudioParameters params(AudioParameters::AUDIO_FAKE,
                          kChannelLayout,
@@ -158,7 +196,7 @@
                          kBitsPerSample,
                          kSamplesPerPacket * 1000);
   scoped_refptr<AudioInputController> controller = AudioInputController::Create(
-      audio_manager_.get(), &event_handler, params,
+      audio_manager_.get(), &event_handler, &sync_writer, params,
       AudioDeviceDescription::kDefaultDeviceId, NULL);
   ASSERT_FALSE(controller.get());
 }
@@ -166,9 +204,13 @@
 // Test calling AudioInputController::Close multiple times.
 TEST_F(AudioInputControllerTest, CloseTwice) {
   MockAudioInputControllerEventHandler event_handler;
+  MockSyncWriter sync_writer;
 
   // OnCreated() will be called only once.
-  EXPECT_CALL(event_handler, OnCreated(NotNull()));
+  EXPECT_CALL(event_handler, OnCreated(NotNull())).Times(Exactly(1));
+  EXPECT_CALL(event_handler, OnLog(_, _)).Times(AnyNumber());
+  // This callback should still only be called once.
+  EXPECT_CALL(sync_writer, Close()).Times(Exactly(1));
 
   AudioParameters params(AudioParameters::AUDIO_FAKE,
                          kChannelLayout,
@@ -176,7 +218,7 @@
                          kBitsPerSample,
                          kSamplesPerPacket);
   scoped_refptr<AudioInputController> controller = AudioInputController::Create(
-      audio_manager_.get(), &event_handler, params,
+      audio_manager_.get(), &event_handler, &sync_writer, params,
       AudioDeviceDescription::kDefaultDeviceId, NULL);
   ASSERT_TRUE(controller.get());
 
diff --git a/media/audio/audio_io.h b/media/audio/audio_io.h
index e09b36e..6ab50aa 100644
--- a/media/audio/audio_io.h
+++ b/media/audio/audio_io.h
@@ -94,8 +94,10 @@
   // The output stream does not take ownership of this callback.
   virtual void Start(AudioSourceCallback* callback) = 0;
 
-  // Stops playing audio. Effect might not be instantaneous as the hardware
-  // might have locked audio data that is processing.
+  // Stops playing audio.  The operation completes synchronously meaning that
+  // once Stop() has completed executing, no further callbacks will be made to
+  // the callback object that was supplied to Start() and it can be safely
+  // deleted.
   virtual void Stop() = 0;
 
   // Sets the relative volume, with range [0.0, 1.0] inclusive.
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
index 097e4c9a..30430bf 100644
--- a/media/audio/audio_manager.cc
+++ b/media/audio/audio_manager.cc
@@ -303,6 +303,10 @@
     scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
     AudioLogFactory* audio_log_factory);
 
+void AudioManager::SetMaxStreamCountForTesting(int max_input, int max_output) {
+  NOTREACHED();
+}
+
 AudioManager::AudioManager(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner)
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 6563251..c5a7cdd 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -251,6 +251,9 @@
   // Gets the name of the audio manager (e.g., Windows, Mac, PulseAudio).
   virtual const char* GetName() = 0;
 
+  // Limits the number of streams that can be created for testing purposes.
+  virtual void SetMaxStreamCountForTesting(int max_input, int max_output);
+
  protected:
   AudioManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner);
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index dd6e9a2a..670820d 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -433,4 +433,10 @@
   return audio_log_factory_->CreateAudioLog(component);
 }
 
+void AudioManagerBase::SetMaxStreamCountForTesting(int max_input,
+                                                   int max_output) {
+  max_num_output_streams_ = max_output;
+  max_num_input_streams_ = max_input;
+}
+
 }  // namespace media
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index 4dc3fd3f..b3100cf6 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -68,6 +68,8 @@
   std::unique_ptr<AudioLog> CreateAudioLog(
       AudioLogFactory::AudioComponent component) override;
 
+  void SetMaxStreamCountForTesting(int max_input, int max_output) final;
+
   // AudioManagerBase:
 
   // Called internally by the audio stream when it has been closed.
diff --git a/media/audio/test_audio_input_controller_factory.cc b/media/audio/test_audio_input_controller_factory.cc
index fb70e32a..1766b925 100644
--- a/media/audio/test_audio_input_controller_factory.cc
+++ b/media/audio/test_audio_input_controller_factory.cc
@@ -15,16 +15,16 @@
     EventHandler* event_handler,
     SyncWriter* sync_writer,
     UserInputMonitor* user_input_monitor)
-    : AudioInputController(event_handler,
+    : AudioInputController(audio_manager->GetTaskRunner(),
+                           event_handler,
                            sync_writer,
                            nullptr,
                            user_input_monitor,
                            false),
       audio_parameters_(audio_parameters),
       factory_(factory),
-      event_handler_(event_handler) {
-  task_runner_ = audio_manager->GetTaskRunner();
-}
+      event_handler_(event_handler),
+      sync_writer_(sync_writer) {}
 
 TestAudioInputController::~TestAudioInputController() {
   // Inform the factory so that it allows creating new instances in future.
@@ -37,7 +37,7 @@
 }
 
 void TestAudioInputController::Close(const base::Closure& closed_task) {
-  task_runner_->PostTask(FROM_HERE, closed_task);
+  GetTaskRunnerForTesting()->PostTask(FROM_HERE, closed_task);
   if (factory_->delegate_)
     factory_->delegate_->TestAudioControllerClosed(this);
 }
@@ -59,8 +59,9 @@
     AudioParameters params,
     UserInputMonitor* user_input_monitor) {
   DCHECK(!controller_);  // Only one test instance managed at a time.
-  controller_ = new TestAudioInputController(
-      this, audio_manager, params, event_handler, NULL, user_input_monitor);
+  controller_ =
+      new TestAudioInputController(this, audio_manager, params, event_handler,
+                                   sync_writer, user_input_monitor);
   return controller_;
 }
 
diff --git a/media/audio/test_audio_input_controller_factory.h b/media/audio/test_audio_input_controller_factory.h
index 4a04d36e..90f81b7f 100644
--- a/media/audio/test_audio_input_controller_factory.h
+++ b/media/audio/test_audio_input_controller_factory.h
@@ -65,6 +65,9 @@
   // Returns the event handler installed on the AudioInputController.
   EventHandler* event_handler() const { return event_handler_; }
 
+  // Returns a pointer to the audio callback for the AudioInputController.
+  SyncWriter* sync_writer() const { return sync_writer_; }
+
   // Notifies the TestAudioControllerOpened() event to the delegate (if any).
   void Record() override;
 
@@ -84,7 +87,8 @@
   // These are not owned by us and expected to be valid for this object's
   // lifetime.
   TestAudioInputControllerFactory* factory_;
-  EventHandler* event_handler_;
+  EventHandler* const event_handler_;
+  SyncWriter* const sync_writer_;
 
   DISALLOW_COPY_AND_ASSIGN(TestAudioInputController);
 };
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn
index f6ddd335..80e3a38 100644
--- a/remoting/host/win/BUILD.gn
+++ b/remoting/host/win/BUILD.gn
@@ -276,10 +276,12 @@
     "entry_point.cc",
   ]
 
-  ldflags = [
-    "/ENTRY:HostEntryPoint",
-    # "/NODEFAULTLIB",
-  ]
+  if (!is_asan) {
+    ldflags = [
+      "/ENTRY:HostEntryPoint",
+      # "/NODEFAULTLIB",
+    ]
+  }
 }
 
 executable("remoting_me2me_host") {
@@ -304,7 +306,12 @@
 
   output_name = "remoting_host"
 
-  ldflags = [ "/ENTRY:HostEntryPoint" ]
+  if (!is_asan) {
+    ldflags = [
+      "/ENTRY:HostEntryPoint",
+      # "/NODEFAULTLIB",
+    ]
+  }
 }
 
 shared_library("remoting_core") {
@@ -440,10 +447,12 @@
     "entry_point.cc",
   ]
 
-  ldflags = [
-    "/ENTRY:HostEntryPoint",
-    # "/NODEFAULTLIB",
-  ]
+  if (!is_asan) {
+    ldflags = [
+      "/ENTRY:HostEntryPoint",
+      # "/NODEFAULTLIB",
+    ]
+  }
 }
 
 executable("remoting_native_messaging_host") {
diff --git a/remoting/host/win/entry_point.cc b/remoting/host/win/entry_point.cc
index 0d711f2..a4e1f10 100644
--- a/remoting/host/win/entry_point.cc
+++ b/remoting/host/win/entry_point.cc
@@ -14,3 +14,21 @@
   int exit_code = remoting::HostMain(0, nullptr);
   ExitProcess(exit_code);
 }
+
+#if defined(ADDRESS_SANITIZER)
+// Executables instrumented with ASAN need CRT functions. We do not use
+// the /ENTRY switch for ASAN instrumented executable and a "main" function
+// is required.
+int WINAPI wWinMain (HINSTANCE hInstance,
+                     HINSTANCE hPrevInstance,
+                     LPSTR lpCmdLine,
+                     int nCmdShow) {
+  HostEntryPoint();
+  return 0;
+}
+
+int wmain() {
+  HostEntryPoint();
+  return 0;
+}
+#endif
diff --git a/services/ui/ime/ime_server_impl.cc b/services/ui/ime/ime_server_impl.cc
index 0731d02..a5a10d37 100644
--- a/services/ui/ime/ime_server_impl.cc
+++ b/services/ui/ime/ime_server_impl.cc
@@ -4,6 +4,7 @@
 
 #include "services/ui/ime/ime_server_impl.h"
 
+#include "base/memory/ptr_util.h"
 #include "services/catalog/public/interfaces/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ui/ime/ime_registrar_impl.h"
@@ -46,26 +47,20 @@
   driver_ = std::move(driver);
 
   while (!pending_requests_.empty()) {
-    driver_->StartSession(current_id_++,
-                          std::move(pending_requests_.front().first),
-                          std::move(pending_requests_.front().second));
+    driver_->StartSession(current_id_++, std::move(pending_requests_.front()));
     pending_requests_.pop();
   }
 }
 
-void IMEServerImpl::StartSession(
-    mojom::TextInputClientPtr client,
-    mojom::InputMethodRequest input_method_request) {
+void IMEServerImpl::StartSession(mojom::StartSessionDetailsPtr details) {
   if (driver_.get()) {
     // TODO(moshayedi): crbug.com/634431. This will forward all calls from
     // clients to the driver as they are. We may need to check |caret_bounds|
     // parameter of InputMethod::OnCaretBoundsChanged() here and limit them to
     // client's focused window.
-    driver_->StartSession(current_id_++, std::move(client),
-                          std::move(input_method_request));
+    driver_->StartSession(current_id_++, std::move(details));
   } else {
-    pending_requests_.push(
-        std::make_pair(std::move(client), std::move(input_method_request)));
+    pending_requests_.push(std::move(details));
   }
 }
 
diff --git a/services/ui/ime/ime_server_impl.h b/services/ui/ime/ime_server_impl.h
index 22156cb..76cc5a8 100644
--- a/services/ui/ime/ime_server_impl.h
+++ b/services/ui/ime/ime_server_impl.h
@@ -28,8 +28,7 @@
 
  private:
   // mojom::IMEServer:
-  void StartSession(mojom::TextInputClientPtr client,
-                    mojom::InputMethodRequest input_method) override;
+  void StartSession(mojom::StartSessionDetailsPtr details) override;
 
   void OnGotCatalogEntries(std::vector<catalog::mojom::EntryPtr> entries);
 
@@ -39,9 +38,7 @@
   mojom::IMEDriverPtr driver_;
   int current_id_;
 
-  using PendingRequest =
-      std::pair<mojom::TextInputClientPtr, mojom::InputMethodRequest>;
-  std::queue<PendingRequest> pending_requests_;
+  std::queue<mojom::StartSessionDetailsPtr> pending_requests_;
 
   DISALLOW_COPY_AND_ASSIGN(IMEServerImpl);
 };
diff --git a/services/ui/ime/ime_unittest.cc b/services/ui/ime/ime_unittest.cc
index 121cdc1..582521f 100644
--- a/services/ui/ime/ime_unittest.cc
+++ b/services/ui/ime/ime_unittest.cc
@@ -93,7 +93,11 @@
   TestTextInputClient client(MakeRequest(&client_ptr));
 
   ui::mojom::InputMethodPtr input_method;
-  ime_server_->StartSession(std::move(client_ptr), MakeRequest(&input_method));
+  ui::mojom::StartSessionDetailsPtr details =
+      ui::mojom::StartSessionDetails::New();
+  details->client = std::move(client_ptr);
+  details->input_method_request = MakeRequest(&input_method);
+  ime_server_->StartSession(std::move(details));
 
   // Send character key event.
   ui::KeyEvent char_event('A', ui::VKEY_A, 0);
diff --git a/services/ui/ime/test_ime_driver/test_ime_driver.cc b/services/ui/ime/test_ime_driver/test_ime_driver.cc
index 5003640..613d103e 100644
--- a/services/ui/ime/test_ime_driver/test_ime_driver.cc
+++ b/services/ui/ime/test_ime_driver/test_ime_driver.cc
@@ -41,14 +41,12 @@
 
 TestIMEDriver::~TestIMEDriver() {}
 
-void TestIMEDriver::StartSession(
-    int32_t session_id,
-    mojom::TextInputClientPtr client,
-    mojom::InputMethodRequest input_method_request) {
+void TestIMEDriver::StartSession(int32_t session_id,
+                                 mojom::StartSessionDetailsPtr details) {
   input_method_bindings_[session_id].reset(
       new mojo::Binding<mojom::InputMethod>(
-          new TestInputMethod(std::move(client)),
-          std::move(input_method_request)));
+          new TestInputMethod(std::move(details->client)),
+          std::move(details->input_method_request)));
 }
 
 void TestIMEDriver::CancelSession(int32_t session_id) {
diff --git a/services/ui/ime/test_ime_driver/test_ime_driver.h b/services/ui/ime/test_ime_driver/test_ime_driver.h
index 30fcd5360..3e26953a 100644
--- a/services/ui/ime/test_ime_driver/test_ime_driver.h
+++ b/services/ui/ime/test_ime_driver/test_ime_driver.h
@@ -23,10 +23,8 @@
 
  private:
   // ui::mojom::IMEDriver:
-  void StartSession(
-      int32_t session_id,
-      ui::mojom::TextInputClientPtr client,
-      ui::mojom::InputMethodRequest input_method_request) override;
+  void StartSession(int32_t session_id,
+                    ui::mojom::StartSessionDetailsPtr details) override;
   void CancelSession(int32_t session_id) override;
 
   std::map<int32_t, std::unique_ptr<mojo::Binding<mojom::InputMethod>>>
diff --git a/services/ui/public/interfaces/ime/BUILD.gn b/services/ui/public/interfaces/ime/BUILD.gn
index 3a60f3f..85909fb 100644
--- a/services/ui/public/interfaces/ime/BUILD.gn
+++ b/services/ui/public/interfaces/ime/BUILD.gn
@@ -10,6 +10,7 @@
   ]
 
   public_deps = [
+    "//mojo/common:common_custom_types",
     "//ui/events/mojo:interfaces",
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/range/mojo",
diff --git a/services/ui/public/interfaces/ime/ime.mojom b/services/ui/public/interfaces/ime/ime.mojom
index d491da3..c122750 100644
--- a/services/ui/public/interfaces/ime/ime.mojom
+++ b/services/ui/public/interfaces/ime/ime.mojom
@@ -4,6 +4,7 @@
 
 module ui.mojom;
 
+import "mojo/common/text_direction.mojom";
 import "ui/events/mojo/event.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "ui/gfx/range/mojo/range.mojom";
@@ -64,14 +65,26 @@
   URL,
 };
 
+// Parameters needed to start an IME session.
+struct StartSessionDetails {
+  TextInputClient client;
+  InputMethod& input_method_request;
+
+  // Initial details about |client| required by IMEDriver.
+  TextInputType text_input_type;
+  TextInputMode text_input_mode;
+  mojo.common.mojom.TextDirection text_direction;
+  int32 text_input_flags;
+  gfx.mojom.Rect caret_bounds;
+};
+
 // A service which provides the IMEDriver interface is responsible for doing
 // the composition logic. After starting a session, it receives events from
 // the client via the InputMethod interface, and sends composition events to
 // the client via the TextInputClient.
 interface IMEDriver {
   // session_id is unique and generated by Mus.
-  StartSession(int32 session_id, TextInputClient client,
-               InputMethod& input_method);
+  StartSession(int32 session_id, StartSessionDetails details);
   CancelSession(int32 session_id);
 };
 
@@ -79,8 +92,7 @@
 // does minimal processing and mostly just acts as lightweight proxy between
 // the client app and the registered IME driver.
 interface IMEServer {
-  StartSession(TextInputClient client,
-               InputMethod& input_method);
+  StartSession(StartSessionDetails details);
 };
 
 // An IME driver register should register itself to Mus using the IMERegistrar
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d26c1d3e..5d3b758 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -829,6 +829,25 @@
             ]
         }
     ],
+    "HttpFormWarning": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "HttpFormWarning"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSurfaceClearYosemite": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index 875d507..10607bf0 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -588,6 +588,7 @@
 Bug(none) fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ]
 Bug(none) fast/events/touch/compositor-touch-hit-rects-squashing.html [ Failure ]
 Bug(none) fast/events/touch/compositor-touch-hit-rects-trigger-commit.html [ Failure ]
+Bug(none) fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html [ Failure ]
 Bug(none) fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 Bug(none) fast/events/touch/gesture/gesture-scroll-by-page.html [ Failure ]
 Bug(none) fast/events/touch/gesture/gesture-scroll-by-pixel.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index bf5e4ec..ac42e3d2 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -340,7 +340,7 @@
 # imported/wpt/user-timing [ Pass ]
 imported/wpt/vibration [ Skip ]
 ## Owners: bsheedy@chromium.org
-# imported/wpt/vr [ Pass ]
+# imported/wpt/webvr [ Pass ]
 imported/wpt/wai-aria [ Skip ]
 ## Owners: suzyh@chromium.org
 # imported/wpt/web-animations [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/animations/pause-paused-animation-for-testing.html b/third_party/WebKit/LayoutTests/animations/pause-paused-animation-for-testing.html
new file mode 100644
index 0000000..ba6364b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/pause-paused-animation-for-testing.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<style>
+@keyframes test {}
+#target {
+  animation: test 1s paused;
+}
+</style>
+<div id="target"></div>
+<script>
+test(() => {
+  internals.pauseAnimations(0);
+}, 'Do not crash when pausing a paused animation for testing');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html
new file mode 100644
index 0000000..3ec49e4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="resources/canvas-Float32ImageData.js"></script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html
new file mode 100644
index 0000000..b3c97567
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker("resources/canvas-Float32ImageData-workers.js"));
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
index f1b473d..77d93449 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
@@ -18,16 +18,16 @@
 PASS new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present..
 PASS new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4..
-PASS new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not equal to (4 * width * height)..
-PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of 4..
+PASS new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number..
+PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
 PASS new ImageData(self, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS new ImageData(null, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
-PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
+PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS (new ImageData(new Uint8ClampedArray(28), 7)).height is 1
 PASS imageDataFromData.width is 100
 PASS imageDataFromData.height is 50
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
index 51185d7..8f444dd 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
@@ -19,16 +19,16 @@
 PASS [Worker] new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS [Worker] new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present..
 PASS [Worker] new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS [Worker] new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4..
-PASS [Worker] new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not equal to (4 * width * height)..
-PASS [Worker] new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of 4..
+PASS [Worker] new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number..
+PASS [Worker] new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
 PASS [Worker] new ImageData(self, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS [Worker] new ImageData(null, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS [Worker] new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS [Worker] new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
-PASS [Worker] new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS [Worker] new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS [Worker] new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS [Worker] (new ImageData(new Uint8ClampedArray(28), 7)).height is 1
 PASS [Worker] imageDataFromData.width is 100
 PASS [Worker] imageDataFromData.height is 50
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html b/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html
new file mode 100644
index 0000000..5731c30
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+
+// RGBA(255,0,0,255) -> LinearRGB(0x3c00, 0x0, 0x0, 0x3c00)
+var data = new Float32Array([0x00003c00, 0x0, 0x0, 0x00003c00]);
+
+test(function() {
+
+  assert_equals((new Float32ImageData(1, 1)).colorSpace, "linear-rgb", "The default color space for Float32ImageData is linear-rgb.");
+  assert_equals((new Float32ImageData(1, 1, "linear-rgb")).colorSpace, "linear-rgb", "The color space read from Float32ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(1, 1, "legacy-srgb");}, "Legacy SRGB is not supported in Float32ImageData.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(1, 1, "srgb");}, "SRGB is not supported in Float32ImageData.");
+  assert_throws(null, function() {fImageData = new Float32ImageData(1, 1, "undefined");}, "Only members of ImageDataColorSpace enum are processed in Float32ImageData constructor.");
+
+  assert_equals((new Float32ImageData(data, 1, 1)).colorSpace, "linear-rgb", "The default color space for Float32ImageData is linear-rgb.");
+  assert_equals((new Float32ImageData(data, 1, 1, "linear-rgb")).colorSpace, "linear-rgb", "The color space read from Float32ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(data, 1, 1, "legacy-srgb");}, "Legacy SRGB is not supported in Float32ImageData.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(data, 1, 1, "srgb");}, "SRGB is not supported in Float32ImageData.");
+  assert_throws(null, function() {fImageData = new Float32ImageData(data, 1, 1, "undefined");}, "Only members of ImageDataColorSpace enum are processed in Float32ImageData constructor.");
+
+}, 'This test examines the correct behavior of Float32ImageData API in setting and getting ImageDataColorSpace.');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html b/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html
new file mode 100644
index 0000000..a170bc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+
+var data = new Uint8ClampedArray([255, 0, 0, 255]);
+
+function createImageDataAndGetColorSpace(colorSpace) {
+  experimental = new ImageData(1,1); 
+  imageData = experimental.createImageData(1, 1, colorSpace)
+  return imageData.colorSpace;
+}
+
+function createWithDataAndGetColorSpaceW(colorSpace) {
+  experimental = new ImageData(1,1); 
+  imageData = experimental.createImageData(data, 1, colorSpace)
+  return imageData.colorSpace;
+}
+
+function createWithDataAndGetColorSpaceWH(colorSpace) {
+  experimental = new ImageData(1,1); 
+  imageData = experimental.createImageData(data, 1, 1, colorSpace)
+  return imageData.colorSpace;
+}
+
+test(function() {
+  assert_equals((new ImageData(1,1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb.");
+  assert_equals(createImageDataAndGetColorSpace("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set.");
+  assert_equals(createImageDataAndGetColorSpace("srgb"), "srgb", "The color space read from ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {createImageDataAndGetColorSpace("linear-rgb");}, "Linear RGB is not supported in ImageData.");
+  assert_throws(null, function() {createImageDataAndGetColorSpace("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor.");
+
+  assert_equals((new ImageData(data,1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb.");
+  assert_equals(createWithDataAndGetColorSpaceW("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set.");
+  assert_equals(createWithDataAndGetColorSpaceW("srgb"), "srgb", "The color space read from ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {createWithDataAndGetColorSpaceW("linear-rgb");}, "Linear RGB is not supported in ImageData.");
+  assert_throws(null, function() {createWithDataAndGetColorSpaceW("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor.");
+
+  assert_equals((new ImageData(data,1, 1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb.");
+  assert_equals(createWithDataAndGetColorSpaceWH("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set.");
+  assert_equals(createWithDataAndGetColorSpaceWH("srgb"), "srgb", "The color space read from ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {createWithDataAndGetColorSpaceWH("linear-rgb");}, "Linear RGB is not supported in ImageData.");
+  assert_throws(null, function() {createWithDataAndGetColorSpaceWH("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor.");
+
+}, 'This test examines the correct behavior of createImageData API in setting and getting ImageData.colorSpace.');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js
new file mode 100644
index 0000000..7c872b55
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js
@@ -0,0 +1,2 @@
+importScripts('../../../resources/testharness.js', 'canvas-Float32ImageData.js');
+done();
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js
new file mode 100644
index 0000000..838297b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js
@@ -0,0 +1,121 @@
+function setF16Color(float32ImageData, i, f16Color) {
+  var s = i * 4;
+  float32ImageData[s] = f16Color[0];
+  float32ImageData[s + 1] = f16Color[1];
+  float32ImageData[s + 2] = f16Color[2];
+  float32ImageData[s + 3] = f16Color[3];
+}
+
+function getF16Color(float32ImageData, i) {
+  var result = [];
+  var s = i * 4;
+  for (var j = 0; j < 4; j++) {
+    result[j] = float32ImageData[s + j];
+  }
+  return result;
+}
+
+function compareF16Colors(f16Color1, f16Color2) {
+  for (var j = 0; j < 4; j++)
+    if (f16Color1[j] != f16Color2[j])
+      return false;
+  return true;
+}
+
+test(function() {
+
+  float32ImageData = new Float32ImageData(100, 50);
+  assert_equals(float32ImageData.width, 100,
+      "The width of the float32ImageData should be the width we passed to the constructor.");
+  assert_equals(float32ImageData.height, 50,
+      "The height of the float32ImageData should be the height we passed to the constructor.");
+
+  var f16ColorData = getF16Color(float32ImageData.data, 4);
+  assert_equals(f16ColorData[0], 0,
+      "The default ImageData color is transparent black.");
+  assert_equals(f16ColorData[1], 0,
+      "The default ImageData color is transparent black.");
+  assert_equals(f16ColorData[2], 0,
+      "The default ImageData color is transparent black.");
+  assert_equals(f16ColorData[3], 0,
+      "The default ImageData color is transparent black.");
+
+  var testColor = new Float32Array([0x00003c00, 0x00003c01, 0x00003c02, 0x00003c03]);
+  setF16Color(float32ImageData.data, 4, testColor);
+  f16ColorData = getF16Color(float32ImageData.data, 4);
+  assert_equals(f16ColorData[0], 0x00003c00,
+      "The red component of f16 color is the value we set.");
+  assert_equals(f16ColorData[1], 0x00003c01,
+      "The green component of f16 color is the value we set.");
+  assert_equals(f16ColorData[2], 0x00003c02,
+      "The blue component of f16 color is the value we set.");
+  assert_equals(f16ColorData[3], 0x00003c03,
+      "The alpha component of f16 color is the value we set.");
+
+  assert_throws(null, function() {new Float32ImageData(10);},
+      "Float32ImageData constructor requires both width and height.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(0,10);},
+      "Float32ImageData width must be greater than zero.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(10,0);},
+      "Float32ImageData height must be greater than zero.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData('width', 'height');},
+      "Float32ImageData width and height must be numbers.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(1 << 31, 1 << 31);},
+      "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow.");
+
+  assert_throws(null, function() {new Float32ImageData(new Float32Array(0));},
+      "The Float32Array passed to the constructor cannot have a length of zero.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(new Float32Array(27), 2);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(new Float32Array(28), 7, 0);},
+      "The size of Float32Array passed to the constructor must be equal to 4 * width * height.");
+  assert_throws(null, function() {new Float32ImageData(self, 4, 4);},
+      "The object passed to the constructor as data array should be of type Float32Array.");
+  assert_throws(null, function() {new Float32ImageData(null, 4, 4);},
+      "The object passed to the constructor as data array should be of type Float32Array.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 0);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 13);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 31);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 'biggish');},
+      "The width parameter must be a number.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 24, 1 << 31);},
+      "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 31, 1 << 24);},
+      "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow.");
+  assert_equals((new Float32ImageData(new Float32Array(28), 7)).height, 1,
+      "The height must be equal to size of the data array divided by 4 * width.");
+
+  float32ImageDataFromData = new Float32ImageData(float32ImageData.data, 100);
+  assert_equals(float32ImageDataFromData.width, 100,
+      "The width of the float32ImageDataFromData should be the same as that of float32ImageData.");
+  assert_equals(float32ImageDataFromData.height, 50,
+      "The height of the float32ImageDataFromData should be the same as that of float32ImageData.");
+  assert_true(float32ImageDataFromData.data == float32ImageData.data,
+      "The pixel data buffer of float32ImageDataFromData should be the same as that of float32ImageData.");
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 10),
+                               getF16Color(float32ImageData.data, 10)),
+      "The color of a pixel from float32ImageDataFromData should be the same as that of float32ImageData.");
+  setF16Color(float32ImageData.data, 10, testColor);
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 10),
+                               getF16Color(float32ImageData.data, 10)),
+      "Setting the color of a pixel from float32ImageData must cascade to the same pixel of float32ImageDataFromData.");
+
+  var data = new Float32Array(400);
+  data[22] = 129;
+  float32ImageDataFromData = new Float32ImageData(data, 20, 5);
+  assert_equals(float32ImageDataFromData.width, 20,
+      "The width of the float32ImageData should be the width we passed to the constructor.");
+  assert_equals(float32ImageDataFromData.height, 5,
+      "The height of the Float32ImageData must be equal to size of the Float32Array divided by 4 * width.");
+  assert_true(float32ImageDataFromData.data == data,
+      "The pixel data buffer of float32ImageDataFromData should be the same buffer passed to the constructor.");
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 2), getF16Color(data, 2)),
+      "The pixel data of float32ImageDataFromData should be the same as that of the buffer passed to the constructor.");
+  setF16Color(float32ImageDataFromData.data, 2, testColor);
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 2), getF16Color(data, 2)),
+      "Setting the color of a pixel from float32ImageDataFromData must cascade to the same pixel of the buffer passed to the constructor.");
+
+}, 'This test examines the correct behavior of Float32ImageData API.');
diff --git a/third_party/WebKit/LayoutTests/fast/css/fontfacesetloadevent-constructor.html b/third_party/WebKit/LayoutTests/fast/css/fontfacesetloadevent-constructor.html
new file mode 100644
index 0000000..940d601
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/fontfacesetloadevent-constructor.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>FontFaceSetLoadEvent Constructor</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+  test(function() {
+    var ff = [];
+    var e = new FontFaceSetLoadEvent('type');
+    assert_array_equals(e.fontfaces, ff);
+    assert_not_equals(e.fontfaces, ff);
+  }, 'Test FontFaceSetLoadEvent constructor without FontFaceSetLoadEventInit dictionary');
+
+  test(function() {
+    var ff = [ new FontFace('family', 'src') ];
+    var e = new FontFaceSetLoadEvent('type', { fontfaces: ff });
+    assert_array_equals(e.fontfaces, ff);
+    assert_not_equals(e.fontfaces, ff);
+  }, 'Test FontFaceSetLoadEvent constructor with FontFaceSetLoadEventInit dictionary');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout-expected.txt
new file mode 100644
index 0000000..29f4ce2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout-expected.txt
@@ -0,0 +1,7 @@
+This test verifies the touch event target rects are updated correctly when an element transfroms without causing layout.
+
+[object HTMLDivElement]: #document (100, 100, 50, 50)
+
+[object HTMLDivElement]: #document (150, 100, 50, 50)
+
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html
new file mode 100644
index 0000000..80f0b5b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<style>
+#box {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  width: 50px;
+  height: 50px;
+  background-color: blue;
+}
+</style>
+
+<p id="description">
+This test verifies the touch event target rects are updated correctly when
+an element transfroms without causing layout.
+</p>
+
+<div id="tests">
+  <div id="box"></div>
+</div>
+<div id="console" style="display:none;"></div>
+
+<script src="resources/compositor-touch-hit-rects.js"></script>
+<script>
+
+const box = document.getElementById("box");
+box.addEventListener("touchstart", () => {}, false);
+internals.forceCompositingUpdate(document);
+logRects(box, true);
+
+// The box should be able to translate to a new location
+box.style.transform = "translate(50px,0px)";
+internals.forceCompositingUpdate(document);
+logRects(box, true);
+
+document.getElementById("console").style.display = "block";
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/performance/longtasktiming.html b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-attributes.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/fast/performance/longtasktiming.html
rename to third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-attributes.html
diff --git a/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-externalscript.html b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-externalscript.html
new file mode 100644
index 0000000..95334f21
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-externalscript.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="resources/slow.js"></script>
+<script>
+
+async_test(function (t) {
+    var observer = new PerformanceObserver(
+        t.step_func(function (entryList) {
+            var entries = entryList.getEntries();
+            assert_equals(entries.length, 1,
+                "Exactly one entry is expected.");
+            var longtask = entries[0];
+            assert_equals(longtask.entryType, "longtask",
+                "entryType expected to be: longtask");
+            assert_equals(longtask.name, "same-origin-self",
+                "name expected to be: same-origin-self");
+            assert_greater_than(longtask.duration, 50,
+                "duration expected to be greater than 50ms threshold");
+            assert_equals(longtask.startTime, Math.floor(longtask.startTime),
+                "startTime expected to have 1 miillisecond granularity");
+
+            // Assert the TaskAttributionTiming entry in attribution.
+            assert_equals(longtask.attribution.length, 1,
+                "Exactly one attribution entry is expected");
+            var attribution = longtask.attribution[0];
+            assert_equals(attribution.entryType, "taskattribution");
+            assert_equals(attribution.name, "frame");
+            assert_equals(attribution.duration, 0);
+            assert_equals(attribution.startTime, 0);
+
+            observer.disconnect();
+            t.done();
+        })
+    );
+    observer.observe({entryTypes: ["longtask"]});
+
+}, "Performance longtask entries are observable");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-raf.html b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-raf.html
new file mode 100644
index 0000000..7edb8451
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/longtask-raf.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="resources/slowraf.js"></script>
+<script>
+
+async_test(function (t) {
+    var observer = new PerformanceObserver(
+        t.step_func(function (entryList) {
+            var entries = entryList.getEntries();
+            assert_equals(entries.length, 1,
+                "Exactly one entry is expected.");
+            var longtask = entries[0];
+            assert_equals(longtask.entryType, "longtask",
+                "entryType expected to be: longtask");
+            assert_equals(longtask.name, "same-origin-self",
+                "name expected to be: same-origin-self");
+            assert_greater_than(longtask.duration, 50,
+                "duration expected to be greater than 50ms threshold");
+            assert_equals(longtask.startTime, Math.floor(longtask.startTime),
+                "startTime expected to have 1 miillisecond granularity");
+
+            // Assert the TaskAttributionTiming entry in attribution.
+            assert_equals(longtask.attribution.length, 1,
+                "Exactly one attribution entry is expected");
+            var attribution = longtask.attribution[0];
+            assert_equals(attribution.entryType, "taskattribution");
+            assert_equals(attribution.name, "frame");
+            assert_equals(attribution.duration, 0);
+            assert_equals(attribution.startTime, 0);
+
+            observer.disconnect();
+            t.done();
+        })
+    );
+    observer.observe({entryTypes: ["longtask"]});
+
+}, "Performance longtask entries are observable");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/resources/slow.js b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/resources/slow.js
new file mode 100644
index 0000000..302b216
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/resources/slow.js
@@ -0,0 +1,4 @@
+
+/* Generate a slow task */
+var begin = window.performance.now();
+while (window.performance.now() < begin + 51);
diff --git a/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/resources/slowraf.js b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/resources/slowraf.js
new file mode 100644
index 0000000..8103bc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/performance-timing/longtask/resources/slowraf.js
@@ -0,0 +1,6 @@
+
+window.requestAnimationFrame(function() {
+    /* Generate a slow task */
+    var begin = window.performance.now();
+    while (window.performance.now() < begin + 51);
+});
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index e33469d..4bc15ac 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -344,6 +344,12 @@
     method readAsBinaryString
     method readAsDataURL
     method readAsText
+interface Float32ImageData
+    getter colorSpace
+    getter data
+    getter height
+    getter width
+    method constructor
 interface ForeignFetchEvent : ExtendableEvent
     getter origin
     getter request
@@ -510,9 +516,12 @@
     method close
     method constructor
 interface ImageData
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
+    method createImageData
 interface InstallEvent : ExtendableEvent
     method constructor
     method registerForeignFetch
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
index 170fd3c..60010f18 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1314,6 +1314,10 @@
     setter unicodeRange
     setter variant
     setter weight
+interface FontFaceSetLoadEvent : Event
+    attribute @@toStringTag
+    getter fontfaces
+    method constructor
 interface FormData
     attribute @@toStringTag
     method @@iterator
@@ -3017,6 +3021,8 @@
     method transferFromImageBitmap
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index 170fd3c..60010f18 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1314,6 +1314,10 @@
     setter unicodeRange
     setter variant
     setter weight
+interface FontFaceSetLoadEvent : Event
+    attribute @@toStringTag
+    getter fontfaces
+    method constructor
 interface FormData
     attribute @@toStringTag
     method @@iterator
@@ -3017,6 +3021,8 @@
     method transferFromImageBitmap
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 4ba23236..9c93825 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -345,6 +345,12 @@
     method readAsBinaryString
     method readAsDataURL
     method readAsText
+interface Float32ImageData
+    getter colorSpace
+    getter data
+    getter height
+    getter width
+    method constructor
 interface ForeignFetchEvent : ExtendableEvent
     getter origin
     getter request
@@ -511,9 +517,12 @@
     method close
     method constructor
 interface ImageData
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
+    method createImageData
 interface InstallEvent : ExtendableEvent
     method constructor
     method registerForeignFetch
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 2452562e..179caa5 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -368,6 +368,8 @@
     method close
     method constructor
 interface ImageData
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 02dde09..d859f5d 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -387,6 +387,8 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index dd40740..89fed15 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1385,6 +1385,10 @@
     setter unicodeRange
     setter variant
     setter weight
+interface FontFaceSetLoadEvent : Event
+    attribute @@toStringTag
+    getter fontfaces
+    method constructor
 interface FormData
     attribute @@toStringTag
     method @@iterator
@@ -3088,6 +3092,8 @@
     method transferFromImageBitmap
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index ebb785d..c644e8f 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -382,6 +382,8 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 69ddde5..0e953d1 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -354,6 +354,13 @@
 [Worker]     method readAsBinaryString
 [Worker]     method readAsDataURL
 [Worker]     method readAsText
+[Worker] interface Float32ImageData
+[Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
+[Worker]     getter height
+[Worker]     getter width
+[Worker]     method constructor
 [Worker] interface FormData
 [Worker]     attribute @@toStringTag
 [Worker]     method @@iterator
@@ -534,9 +541,12 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
+[Worker]     method createImageData
 [Worker] interface MessageChannel
 [Worker]     attribute @@toStringTag
 [Worker]     getter port1
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 6260f407..8243e85 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -1856,6 +1856,13 @@
     setter onloadend
     setter onloadstart
     setter onprogress
+interface Float32ImageData
+    attribute @@toStringTag
+    getter colorSpace
+    getter data
+    getter height
+    getter width
+    method constructor
 interface FocusEvent : UIEvent
     attribute @@toStringTag
     getter relatedTarget
@@ -1880,6 +1887,10 @@
     setter unicodeRange
     setter variant
     setter weight
+interface FontFaceSetLoadEvent : Event
+    attribute @@toStringTag
+    getter fontfaces
+    method constructor
 interface FormData
     attribute @@toStringTag
     method @@iterator
@@ -3676,9 +3687,12 @@
     method takePhoto
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
+    method createImageData
 interface InputDeviceCapabilities
     attribute @@toStringTag
     getter firesTouchEvents
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
index fc7acef4..087a14e 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -349,6 +349,13 @@
 [Worker]     method readAsBinaryString
 [Worker]     method readAsDataURL
 [Worker]     method readAsText
+[Worker] interface Float32ImageData
+[Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
+[Worker]     getter height
+[Worker]     getter width
+[Worker]     method constructor
 [Worker] interface FormData
 [Worker]     attribute @@toStringTag
 [Worker]     method @@iterator
@@ -529,9 +536,12 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
+[Worker]     method createImageData
 [Worker] interface MessageChannel
 [Worker]     attribute @@toStringTag
 [Worker]     getter port1
diff --git a/third_party/WebKit/Source/bindings/core/v8/ConditionalFeatures.cpp b/third_party/WebKit/Source/bindings/core/v8/ConditionalFeatures.cpp
index 95e4dc3b..6b28b52d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ConditionalFeatures.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ConditionalFeatures.cpp
@@ -45,6 +45,13 @@
       V8Window::installLongTaskObserver(isolate, world, instanceObject,
                                         prototypeObject, interfaceObject);
     }
+  } else if (wrapperTypeInfo == &V8Document::wrapperTypeInfo) {
+    if (RuntimeEnabledFeatures::setRootScrollerEnabled() ||
+        (originTrialContext &&
+         originTrialContext->isTrialEnabled("RootScroller"))) {
+      V8Document::installRootScroller(isolate, world, v8::Local<v8::Object>(),
+                                      prototypeObject, interfaceObject);
+    }
   }
 }
 
diff --git a/third_party/WebKit/Source/build/scripts/json5_generator.py b/third_party/WebKit/Source/build/scripts/json5_generator.py
new file mode 100644
index 0000000..a4b7416
--- /dev/null
+++ b/third_party/WebKit/Source/build/scripts/json5_generator.py
@@ -0,0 +1,233 @@
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generic generator for configuration files in JSON5 format.
+
+The configuration file is expected to contain either a data array or a data map,
+an optional parameters validation map, and an optional metdata map. Examples:
+{
+  data: [
+    "simple_item",
+    "simple_item2",
+    {name:"complex_item", param:"Hello World"},
+  ],
+}
+
+{
+  metadata: {
+    namespace: "css",
+  },
+  parameters: {
+    param1: {default: 1, valid_values:[1,2,3]},
+    param2: {valid_type: "str"},
+  },
+  data: {
+    "simple_item": {},
+    "item": {param1:1, param2: "Hello World"},
+    "bad_item_fails_validation": {
+      name: "bad_item_fails_validation",
+      param1: "bad_value_fails_valid_values_check",
+      param2: 1.9,
+      unknown_param_fails_validation: true,
+    },
+  },
+}
+
+The entries in data array/map are stored in the array self.name_dictionaries.
+Each entry in name_dictionaries is always stored as a dictionary.
+A simple non-map item is converted to a dictionary containing one entry with
+key of "name" and its value the simple item.
+
+The order of entries in name_dictionaries is the same as that specified in the
+data array. While for the data map case, by default the entries are sorted
+alphabetically by name.
+
+The optional map "parameters" specifies the default values and the valid values
+or valid types contained in the data entries. If parameters is specified, then
+data entries may not contain keys not present in parameters.
+
+The optional map "metadata" overrides the values specified in default_metadata
+if present, and stored as self.metadata. Keys in "metadata" must be present in
+default_metadata or an exception raised.
+"""
+
+import argparse
+import ast
+import copy
+import os
+import os.path
+import re
+
+
+def _json5_load(lines):
+    # Use json5.loads when json5 is available. Currently we use simple
+    # regexs to convert well-formed JSON5 to PYL format.
+    # Strip away comments and quote unquoted keys.
+    re_comment = re.compile(r"^\s*//.*$|//+ .*$", re.MULTILINE)
+    re_map_keys = re.compile(r"^\s+([$A-Za-z_][\w]*)\s*:", re.MULTILINE)
+    pyl = re.sub(re_map_keys, r"'\1':", re.sub(re_comment, "", lines))
+    # Convert map values of true/false to Python version True/False.
+    re_true = re.compile(r":\s*true\b")
+    re_false = re.compile(r":\s*false\b")
+    pyl = re.sub(re_true, ":True", re.sub(re_false, ":False", pyl))
+    return ast.literal_eval(pyl)
+
+
+def _merge_doc(doc, doc2):
+    def _merge_dict(key):
+        if key in doc or key in doc2:
+            merged = doc.get(key, {})
+            merged.update(doc2.get(key, {}))
+            doc[key] = merged
+
+    _merge_dict("metadata")
+    _merge_dict("parameters")
+    if type(doc["data"]) is list:
+        doc["data"].extend(doc2["data"])
+    else:
+        _merge_dict("data")
+
+
+class Json5File(object):
+    def __init__(self, doc, default_metadata=None):
+        self.name_dictionaries = []
+        self.metadata = copy.deepcopy(default_metadata if default_metadata else {})
+        self._defaults = {}
+        self._process(doc)
+
+    @classmethod
+    def load_from_files(cls, file_paths, default_metadata):
+        merged_doc = dict()
+        for path in file_paths:
+            assert path.endswith(".json5")
+            with open(os.path.abspath(path)) as json5_file:
+                doc = _json5_load(json5_file.read())
+                if not merged_doc:
+                    merged_doc = doc
+                else:
+                    _merge_doc(merged_doc, doc)
+        return Json5File(merged_doc, default_metadata)
+
+    def _process(self, doc):
+        # Process optional metadata map entries.
+        for key, value in doc.get("metadata", {}).items():
+            self._process_metadata(key, value)
+        # Get optional parameters map, and get the default value map from it.
+        parameters = doc.get("parameters", {})
+        if parameters:
+            self._get_defaults(parameters)
+        # Process normal entries.
+        items = doc["data"]
+        if type(items) is list:
+            for item in items:
+                entry = self._get_entry(item, parameters)
+                self.name_dictionaries.append(entry)
+        else:
+            for key, value in items.items():
+                value["name"] = key
+                entry = self._get_entry(value, parameters)
+                self.name_dictionaries.append(entry)
+            self.name_dictionaries.sort(key=lambda entry: entry["name"])
+
+    def _process_metadata(self, key, value):
+        if key not in self.metadata:
+            raise Exception("Unknown metadata: '%s'\nKnown metadata: %s" %
+                            (key, self.metadata.keys()))
+        self.metadata[key] = value
+
+    def _get_defaults(self, parameters):
+        for key, value in parameters.items():
+            if value and "default" in value:
+                self._defaults[key] = value["default"]
+            else:
+                self._defaults[key] = None
+
+    def _get_entry(self, item, parameters):
+        entry = copy.deepcopy(self._defaults)
+        if type(item) is not dict:
+            entry["name"] = item
+            return entry
+        if "name" not in item:
+            raise Exception("Missing name in item: %s" % item)
+        entry["name"] = item.pop("name")
+        for key, value in item.items():
+            if key not in parameters:
+                raise Exception(
+                    "Unknown parameter: '%s'\nKnown params: %s" %
+                    (key, parameters.keys()))
+            if parameters[key]:
+                self._validate_parameter(parameters[key], value)
+            entry[key] = value
+        return entry
+
+    def _validate_parameter(self, parameter, value):
+        valid_values = parameter.get("valid_values")
+        if valid_values and value not in valid_values:
+            raise Exception("Unknown value: '%s'\nKnown values: %s" %
+                            (value, valid_values))
+        valid_type = parameter.get("valid_type")
+        if valid_type and type(value).__name__ != valid_type:
+            raise Exception("Incorrect type: '%s'\nExpected type: %s" %
+                            (type(value).__name__, valid_type))
+
+
+class Writer(object):
+    # Subclasses should override.
+    class_name = None
+    default_metadata = None
+
+    def __init__(self, json5_files):
+        self._outputs = {}  # file_name -> generator
+        self.gperf_path = None
+        if isinstance(json5_files, basestring):
+            json5_files = [json5_files]
+        if json5_files:
+            self.json5_file = Json5File.load_from_files(json5_files,
+                                                        self.default_metadata)
+
+    def _write_file_if_changed(self, output_dir, contents, file_name):
+        path = os.path.join(output_dir, file_name)
+
+        # The build system should ensure our output directory exists, but just
+        # in case.
+        directory = os.path.dirname(path)
+        if not os.path.exists(directory):
+            os.makedirs(directory)
+
+        # Only write the file if the contents have changed. This allows ninja to
+        # skip rebuilding targets which depend on the output.
+        with open(path, "a+") as output_file:
+            output_file.seek(0)
+            if output_file.read() != contents:
+                output_file.truncate(0)
+                output_file.write(contents)
+
+    def write_files(self, output_dir):
+        for file_name, generator in self._outputs.items():
+            self._write_file_if_changed(output_dir, generator(), file_name)
+
+    def set_gperf_path(self, gperf_path):
+        self.gperf_path = gperf_path
+
+
+class Maker(object):
+    def __init__(self, writer_class):
+        self._writer_class = writer_class
+
+    def main(self):
+        parser = argparse.ArgumentParser()
+        # Require at least one input file.
+        parser.add_argument("files", nargs="+")
+
+        parser.add_argument("--gperf", default="gperf")
+        parser.add_argument("--developer_dir", help="Path to Xcode.")
+        parser.add_argument("--output_dir", default=os.getcwd())
+        args = parser.parse_args()
+
+        if args.developer_dir:
+            os.environ["DEVELOPER_DIR"] = args.developer_dir
+
+        writer = self._writer_class(args.files)
+        writer.set_gperf_path(args.gperf)
+        writer.write_files(args.output_dir)
diff --git a/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py b/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py
index 99041b2..f86922f7 100755
--- a/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py
+++ b/third_party/WebKit/Source/build/scripts/make_css_value_keywords.py
@@ -5,10 +5,9 @@
 import subprocess
 import sys
 
-from in_file import InFile
 from name_utilities import enum_for_css_keyword
 from name_utilities import upper_first_letter
-import in_generator
+import json5_generator
 import license
 
 
@@ -106,19 +105,16 @@
 """
 
 
-class CSSValueKeywordsWriter(in_generator.Writer):
+class CSSValueKeywordsWriter(json5_generator.Writer):
     class_name = "CSSValueKeywords"
-    defaults = {
-        'mode': None,
-    }
 
     def __init__(self, file_paths):
-        in_generator.Writer.__init__(self, file_paths)
+        json5_generator.Writer.__init__(self, file_paths)
         self._outputs = {(self.class_name + ".h"): self.generate_header,
                          (self.class_name + ".cpp"): self.generate_implementation,
                         }
 
-        self._value_keywords = self.in_file.name_dictionaries
+        self._value_keywords = self.json5_file.name_dictionaries
         first_keyword_id = 1
         for offset, keyword in enumerate(self._value_keywords):
             keyword['lower_name'] = keyword['name'].lower()
@@ -174,4 +170,4 @@
 
 
 if __name__ == "__main__":
-    in_generator.Maker(CSSValueKeywordsWriter).main(sys.argv)
+    json5_generator.Maker(CSSValueKeywordsWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_internal_settings.py b/third_party/WebKit/Source/build/scripts/make_internal_settings.py
index abaef7b8..0838614 100755
--- a/third_party/WebKit/Source/build/scripts/make_internal_settings.py
+++ b/third_party/WebKit/Source/build/scripts/make_internal_settings.py
@@ -29,29 +29,23 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import sys
-import in_generator
+import json5_generator
 import template_expander
 import name_utilities
 from make_settings import to_passing_type, to_idl_type
 
 
-class MakeInternalSettingsWriter(in_generator.Writer):
-    defaults = {
-        'type': 'bool',
-        'initial': None,
-        'invalidate': None,
-    }
-    default_parameters = {}
+class MakeInternalSettingsWriter(json5_generator.Writer):
     filters = {
         'upper_first': name_utilities.upper_first,
         'to_passing_type': to_passing_type,
         'to_idl_type': to_idl_type,
     }
 
-    def __init__(self, in_file_path):
-        super(MakeInternalSettingsWriter, self).__init__(in_file_path)
+    def __init__(self, json5_file_path):
+        super(MakeInternalSettingsWriter, self).__init__(json5_file_path)
 
-        self.in_file.name_dictionaries.sort(key=lambda entry: entry['name'])
+        self.json5_file.name_dictionaries.sort(key=lambda entry: entry['name'])
 
         self._outputs = {
             ('InternalSettingsGenerated.h'): self.generate_header,
@@ -59,7 +53,7 @@
             ('InternalSettingsGenerated.idl'): self.generate_idl,
         }
         self._template_context = {
-            'settings': self.in_file.name_dictionaries,
+            'settings': self.json5_file.name_dictionaries,
         }
 
     @template_expander.use_jinja('InternalSettingsGenerated.h.tmpl', filters=filters)
@@ -76,4 +70,4 @@
 
 
 if __name__ == '__main__':
-    in_generator.Maker(MakeInternalSettingsWriter).main(sys.argv)
+    json5_generator.Maker(MakeInternalSettingsWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/make_settings.py b/third_party/WebKit/Source/build/scripts/make_settings.py
index f1436ca..431863a 100755
--- a/third_party/WebKit/Source/build/scripts/make_settings.py
+++ b/third_party/WebKit/Source/build/scripts/make_settings.py
@@ -29,9 +29,10 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import sys
-import in_generator
-import template_expander
+
+import json5_generator
 import name_utilities
+import template_expander
 
 
 def to_passing_type(typename):
@@ -54,29 +55,24 @@
     return None
 
 
-class MakeSettingsWriter(in_generator.Writer):
-    defaults = {
-        'type': 'bool',
-        'initial': None,
-        'invalidate': None,
-    }
-    default_parameters = {}
+class MakeSettingsWriter(json5_generator.Writer):
     filters = {
+        'cpp_bool': name_utilities.cpp_bool,
         'upper_first': name_utilities.upper_first,
         'to_passing_type': to_passing_type,
         'to_idl_type': to_idl_type,
     }
 
-    def __init__(self, in_file_path):
-        super(MakeSettingsWriter, self).__init__(in_file_path)
+    def __init__(self, json5_file_path):
+        super(MakeSettingsWriter, self).__init__(json5_file_path)
 
-        self.in_file.name_dictionaries.sort(key=lambda entry: entry['name'])
+        self.json5_file.name_dictionaries.sort(key=lambda entry: entry['name'])
 
         self._outputs = {
             ('SettingsMacros.h'): self.generate_macros,
         }
         self._template_context = {
-            'settings': self.in_file.name_dictionaries,
+            'settings': self.json5_file.name_dictionaries,
         }
 
     @template_expander.use_jinja('SettingsMacros.h.tmpl', filters=filters)
@@ -85,4 +81,4 @@
 
 
 if __name__ == '__main__':
-    in_generator.Maker(MakeSettingsWriter).main(sys.argv)
+    json5_generator.Maker(MakeSettingsWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/name_utilities.py b/third_party/WebKit/Source/build/scripts/name_utilities.py
index 90b80ba..c5fdcaa 100644
--- a/third_party/WebKit/Source/build/scripts/name_utilities.py
+++ b/third_party/WebKit/Source/build/scripts/name_utilities.py
@@ -93,6 +93,16 @@
     return os.path.basename(entry['name'])
 
 
+def cpp_bool(value):
+    if value is True:
+        return 'true'
+    if value is False:
+        return 'false'
+    # Return value as is, which for example may be a platform-dependent constant
+    # such as "defaultSelectTrailingWhitespaceEnabled".
+    return value
+
+
 def cpp_name(entry):
     return entry['ImplementedAs'] or script_name(entry)
 
diff --git a/third_party/WebKit/Source/build/scripts/templates/SettingsMacros.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/SettingsMacros.h.tmpl
index 60677760..c21f1b6 100644
--- a/third_party/WebKit/Source/build/scripts/templates/SettingsMacros.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/SettingsMacros.h.tmpl
@@ -22,11 +22,11 @@
 // End of SETTINGS_MEMBER_VARIABLES.
 
 #define SETTINGS_INITIALIZER_LIST \
-    {% for setting in settings if setting.initial and setting.type != 'bool' %}
+    {% for setting in settings if setting.initial is not none and setting.type != 'bool' %}
     , m_{{setting.name}}({{setting.initial}}) \
     {% endfor %}
-    {% for setting in settings if setting.initial and setting.type == 'bool' %}
-    , m_{{setting.name}}({{setting.initial}}) \
+    {% for setting in settings if setting.initial is not none and setting.type == 'bool' %}
+    , m_{{setting.name}}({{setting.initial|cpp_bool}}) \
     {% endfor %}
 // End of SETTINGS_INITIALIZER_LIST.
 
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index b6e498519..c6f4436 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -342,14 +342,14 @@
   inputs = scripts_for_in_files + [
              "../build/scripts/make_settings.py",
              "../build/scripts/templates/SettingsMacros.h.tmpl",
-             "frame/Settings.in",
+             "frame/Settings.json5",
            ]
   outputs = [
     "$blink_core_output_dir/SettingsMacros.h",
   ]
 
   args = [
-    rebase_path("frame/Settings.in", root_build_dir),
+    rebase_path("frame/Settings.json5", root_build_dir),
     "--output_dir",
     rel_blink_core_gen_dir,
   ]
@@ -363,7 +363,7 @@
              "../build/scripts/templates/InternalSettingsGenerated.idl.tmpl",
              "../build/scripts/templates/InternalSettingsGenerated.cpp.tmpl",
              "../build/scripts/templates/InternalSettingsGenerated.h.tmpl",
-             "frame/Settings.in",
+             "frame/Settings.json5",
            ]
   outputs = [
     "$blink_core_output_dir/testing/InternalSettingsGenerated.idl",
@@ -372,7 +372,7 @@
   ]
 
   args = [
-    rebase_path("frame/Settings.in", root_build_dir),
+    rebase_path("frame/Settings.json5", root_build_dir),
     "--output_dir",
     "$rel_blink_core_gen_dir/testing",
   ]
@@ -494,8 +494,8 @@
   script = "../build/scripts/make_css_value_keywords.py"
 
   in_files = [
-    "css/CSSValueKeywords.in",
-    "css/SVGCSSValueKeywords.in",
+    "css/CSSValueKeywords.json5",
+    "css/SVGCSSValueKeywords.json5",
   ]
   outputs = [
     "$blink_core_output_dir/CSSValueKeywords.cpp",
diff --git a/third_party/WebKit/Source/core/animation/Animation.cpp b/third_party/WebKit/Source/core/animation/Animation.cpp
index e6bfdee..b015454e6 100644
--- a/third_party/WebKit/Source/core/animation/Animation.cpp
+++ b/third_party/WebKit/Source/core/animation/Animation.cpp
@@ -1080,7 +1080,6 @@
 }
 
 void Animation::pauseForTesting(double pauseTime) {
-  RELEASE_ASSERT(!paused());
   setCurrentTimeInternal(pauseTime, TimingUpdateOnDemand);
   if (hasActiveAnimationsOnCompositor())
     toKeyframeEffectReadOnly(m_content.get())
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index e2ee147..eb7930c 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -192,6 +192,7 @@
                                  "frame/ImageBitmap.idl",
                                  "frame/Location.idl",
                                  "frame/VisualViewport.idl",
+                                 "html/Float32ImageData.idl",
                                  "html/FormData.idl",
                                  "html/HTMLAllCollection.idl",
                                  "html/HTMLAnchorElement.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index 023484e0..7000b35e 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -356,12 +356,19 @@
     "properties/CSSPropertyAPIPaintOrder.cpp",
     "properties/CSSPropertyAPIRotate.cpp",
     "properties/CSSPropertyAPIScrollSnapCoordinate.cpp",
+    "properties/CSSPropertyAPIShapeMargin.cpp",
     "properties/CSSPropertyAPISize.cpp",
+    "properties/CSSPropertyAPIStrokeDasharray.cpp",
+    "properties/CSSPropertyAPITabSize.cpp",
     "properties/CSSPropertyAPITextDecorationColor.cpp",
     "properties/CSSPropertyAPITextDecorationSkip.cpp",
+    "properties/CSSPropertyAPITextIndent.cpp",
     "properties/CSSPropertyAPITextUnderlinePosition.cpp",
     "properties/CSSPropertyAPITransformOrigin.cpp",
     "properties/CSSPropertyAPITranslate.cpp",
+    "properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp",
+    "properties/CSSPropertyAPIWebkitHighlight.cpp",
+    "properties/CSSPropertyAPIWebkitLineClamp.cpp",
     "properties/CSSPropertyAPIWebkitPadding.cpp",
     "properties/CSSPropertyAPIWebkitTransformOriginZ.cpp",
     "properties/CSSPropertyAPIWillChange.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in
index 68f3635..27001cd 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.in
+++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -355,7 +355,7 @@
 scroll-snap-destination runtime_flag=CSSScrollSnapPoints, converter=convertPosition
 scroll-snap-coordinate runtime_flag=CSSScrollSnapPoints, converter=convertSnapCoordinates, api_class
 shape-image-threshold interpolable, type_name=float
-shape-margin interpolable, converter=convertLength
+shape-margin interpolable, converter=convertLength, api_class
 shape-outside interpolable, converter=convertShapeValue, typedom_types=[Image]
 shape-rendering inherited, svg
 size custom_all, api_class
@@ -364,7 +364,7 @@
 stop-color interpolable, svg, converter=convertColor
 stop-opacity interpolable, svg, converter=convertNumberOrPercentage
 stroke interpolable, inherited, svg, setter=setStrokePaint, custom_all
-stroke-dasharray interpolable, inherited, svg, name_for_methods=StrokeDashArray, converter=convertStrokeDasharray
+stroke-dasharray interpolable, inherited, svg, name_for_methods=StrokeDashArray, converter=convertStrokeDasharray, api_class
 stroke-dashoffset interpolable, inherited, svg, name_for_methods=StrokeDashOffset, converter=convertLength
 stroke-linecap svg, inherited, type_name=LineCap, name_for_methods=CapStyle
 stroke-linejoin svg, inherited, type_name=LineJoin, name_for_methods=JoinStyle
@@ -372,8 +372,8 @@
 stroke-opacity interpolable, inherited, svg, converter=convertNumberOrPercentage
 stroke-width interpolable, inherited, svg, converter=convertUnzoomedLength
 table-layout
-tab-size inherited, converter=convertLengthOrTabSpaces, type_name=TabSize
-text-align inherited, custom_value, keyword_only, keywords=[left|right|center|justify|-webkit-left|-webkit-right|-webkit-center|start|end], initial_keyword=start
+tab-size inherited, converter=convertLengthOrTabSpaces, type_name=TabSize, api_class
+text-align inherited, custom_value, keyword_only, keywords=[left|right|center|justify|webkitLeft|webkitRight|webkitCenter|start|end], initial_keyword=start
 text-align-last inherited, type_name=TextAlignLast
 text-anchor inherited, svg
 text-combine-upright inherited, type_name=TextCombine, name_for_methods=TextCombine
@@ -383,7 +383,7 @@
 text-decoration-line runtime_flag=CSS3TextDecorations, name_for_methods=TextDecoration, type_name=TextDecoration, converter=convertFlags<TextDecoration>
 text-decoration-skip runtime_flag=CSS3TextDecorations, inherited, type_name=TextDecorationSkip, converter=convertFlags<TextDecorationSkip>, api_class
 text-decoration-style runtime_flag=CSS3TextDecorations, type_name=TextDecorationStyle
-text-indent interpolable, inherited, custom_all
+text-indent interpolable, inherited, custom_all, api_class
 text-justify runtime_flag=CSS3Text, inherited, type_name=TextJustify
 text-overflow type_name=TextOverflow
 text-shadow interpolable, inherited, converter=convertShadowList
@@ -415,7 +415,7 @@
 -webkit-box-decoration-break
 -webkit-box-direction inherited, independent, keyword_only, keywords=[normal|reverse], initial_keyword=normal
 -webkit-box-flex type_name=float
--webkit-box-flex-group type_name=unsigned int
+-webkit-box-flex-group type_name=unsigned int, api_class
 -webkit-box-lines
 -webkit-box-ordinal-group type_name=unsigned int
 -webkit-box-orient
@@ -428,10 +428,10 @@
 column-rule-width interpolable, converter=convertLineWidth<unsigned short>
 column-span type_name=ColumnSpan
 column-width interpolable, converter=convertComputedLength<float>, custom_all
--webkit-highlight inherited, converter=convertString<CSSValueNone>
+-webkit-highlight inherited, converter=convertString<CSSValueNone>, api_class
 -webkit-hyphenate-character inherited, name_for_methods=HyphenationString, converter=convertString<CSSValueAuto>
 -webkit-line-break inherited, type_name=LineBreak
--webkit-line-clamp type_name=LineClampValue
+-webkit-line-clamp type_name=LineClampValue, api_class
 -webkit-margin-after-collapse type_name=EMarginCollapse
 -webkit-margin-before-collapse type_name=EMarginCollapse
 -webkit-margin-bottom-collapse type_name=EMarginCollapse, name_for_methods=MarginAfterCollapse
diff --git a/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.cpp b/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.cpp
index 4dc999a..71eedf7 100644
--- a/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.cpp
+++ b/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.cpp
@@ -8,7 +8,6 @@
 #include "core/css/CSSURIValue.h"
 #include "core/css/CSSValueList.h"
 #include "core/css/CSSVariableReferenceValue.h"
-#include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSParserIdioms.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/CSSVariableParser.h"
@@ -130,7 +129,8 @@
 }
 
 const CSSValue* consumeSingleType(const CSSSyntaxComponent& syntax,
-                                  CSSParserTokenRange& range) {
+                                  CSSParserTokenRange& range,
+                                  const CSSParserContext* context) {
   using namespace CSSPropertyParserHelpers;
 
   switch (syntax.m_type) {
@@ -153,9 +153,7 @@
     case CSSSyntaxType::Color:
       return consumeColor(range, HTMLStandardMode);
     case CSSSyntaxType::Image:
-      // TODO(timloh): This probably needs a proper parser context for relative
-      // URL resolution.
-      return consumeImage(range, strictCSSParserContext());
+      return consumeImage(range, context);
     case CSSSyntaxType::Url:
       return consumeUrl(range);
     case CSSSyntaxType::Integer:
@@ -177,25 +175,27 @@
 }
 
 const CSSValue* consumeSyntaxComponent(const CSSSyntaxComponent& syntax,
-                                       CSSParserTokenRange range) {
+                                       CSSParserTokenRange range,
+                                       const CSSParserContext* context) {
   // CSS-wide keywords are already handled by the CSSPropertyParser
   if (syntax.m_repeatable) {
     CSSValueList* list = CSSValueList::createSpaceSeparated();
     while (!range.atEnd()) {
-      const CSSValue* value = consumeSingleType(syntax, range);
+      const CSSValue* value = consumeSingleType(syntax, range, context);
       if (!value)
         return nullptr;
       list->append(*value);
     }
     return list;
   }
-  const CSSValue* result = consumeSingleType(syntax, range);
+  const CSSValue* result = consumeSingleType(syntax, range, context);
   if (!range.atEnd())
     return nullptr;
   return result;
 }
 
 const CSSValue* CSSSyntaxDescriptor::parse(CSSParserTokenRange range,
+                                           const CSSParserContext* context,
                                            bool isAnimationTainted) const {
   if (isTokenStream()) {
     return CSSVariableParser::parseRegisteredPropertyValue(range, false,
@@ -203,7 +203,8 @@
   }
   range.consumeWhitespace();
   for (const CSSSyntaxComponent& component : m_syntaxComponents) {
-    if (const CSSValue* result = consumeSyntaxComponent(component, range))
+    if (const CSSValue* result =
+            consumeSyntaxComponent(component, range, context))
       return result;
   }
   return CSSVariableParser::parseRegisteredPropertyValue(range, true,
diff --git a/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.h b/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.h
index 63e9e14d..0ff8908 100644
--- a/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.h
+++ b/third_party/WebKit/Source/core/css/CSSSyntaxDescriptor.h
@@ -9,6 +9,7 @@
 
 namespace blink {
 
+class CSSParserContext;
 class CSSValue;
 
 enum class CSSSyntaxType {
@@ -42,7 +43,9 @@
  public:
   CSSSyntaxDescriptor(String syntax);
 
-  const CSSValue* parse(CSSParserTokenRange, bool isAnimationTainted) const;
+  const CSSValue* parse(CSSParserTokenRange,
+                        const CSSParserContext*,
+                        bool isAnimationTainted) const;
   bool isValid() const { return !m_syntaxComponents.isEmpty(); }
   bool isTokenStream() const {
     return m_syntaxComponents.size() == 1 &&
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.in b/third_party/WebKit/Source/core/css/CSSValueKeywords.in
deleted file mode 100644
index 1cebf6a..0000000
--- a/third_party/WebKit/Source/core/css/CSSValueKeywords.in
+++ /dev/null
@@ -1,1113 +0,0 @@
-//
-// CSS value names
-//
-
-// The mode argument is used to limit the keyword to be used only for certain
-// CSSParserModes. Values that have the prefix -internal- are only allowed by
-// CSSParserModes listed in allowInternalPropertyAndValue()
-
-inherit
-initial
-//
-// outline-style
-// border-top-style
-// border-bottom-style
-// border-left-style
-// border-right-style
-// The order here must match the order of the EBorderStyle enum in ComputedStyleConstants.h.
-none
-hidden
-inset
-groove
-outset
-ridge
-dotted
-dashed
-solid
-double
-
-//
-// font
-//
-caption
-icon
-menu
-message-box
-small-caption
--webkit-mini-control
--webkit-small-control
--webkit-control
-status-bar
-
-//
-// font-style
-//
-//normal
-italic
-oblique
-// The following is only allowed in @font-face:
-all
-
-// font-variant-ligatures:
-//
-// normal
-common-ligatures
-no-common-ligatures
-discretionary-ligatures
-no-discretionary-ligatures
-historical-ligatures
-no-historical-ligatures
-contextual
-no-contextual
-
-// font-variant-caps:
-//
-// normal
-small-caps
-all-small-caps
-petite-caps
-all-petite-caps
-unicase
-titling-caps
-
-// font-variant-numeric
-// normal
-lining-nums
-oldstyle-nums
-proportional-nums
-tabular-nums
-diagonal-fractions
-stacked-fractions
-ordinal
-slashed-zero
-
-//
-// font-weigth
-//
-normal
-bold
-bolder
-lighter
-100
-200
-300
-400
-500
-600
-700
-800
-900
-
-//
-// font-stretch
-//
-ultra-condensed
-extra-condensed
-condensed
-semi-condensed
-semi-expanded
-expanded
-extra-expanded
-ultra-expanded
-
-//
-// font-size
-//
-xx-small
-x-small
-small
-medium
-large
-x-large
-xx-large
--webkit-xxx-large
-smaller
-larger
-
-//
-// font-family (<generic-family> in CSS 2.1)
-//
-serif
-sans-serif
-cursive
-fantasy
-monospace
--webkit-body
--webkit-pictograph
-
-//
-// font-display
-//
-//auto
-//block
-swap
-fallback
-optional
-
-//
-//
-// *-color
-//
-aqua
-black
-blue
-fuchsia
-gray
-green
-lime
-maroon
-navy
-olive
-orange
-purple
-red
-silver
-teal
-white
-yellow
-transparent
--webkit-link
--webkit-activelink
-activeborder
-activecaption
-appworkspace
-background
-buttonface
-buttonhighlight
-buttonshadow
-buttontext
-captiontext
-graytext
-highlight
-highlighttext
-inactiveborder
-inactivecaption
-inactivecaptiontext
-infobackground
-infotext
-menutext
-scrollbar
-threeddarkshadow
-threedface
-threedhighlight
-threedlightshadow
-threedshadow
-window
-windowframe
-windowtext
--internal-active-list-box-selection
--internal-active-list-box-selection-text
--internal-inactive-list-box-selection
--internal-inactive-list-box-selection-text
--webkit-focus-ring-color mode=QuirksOrUASheet
-currentcolor
-grey
-//
-// Value used to implement the behavior in:
-// https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk
--internal-quirk-inherit
-//
-// background-repeat
-//
-repeat
-repeat-x
-repeat-y
-no-repeat
-// round
-// space
-//
-// -webkit-mask-composite
-//
-clear
-copy
-source-over
-source-in
-source-out
-source-atop
-destination-over
-destination-in
-destination-out
-destination-atop
-xor
-// highlight
-plus-lighter
-//
-// vertical-align
-//
-baseline
-middle
-sub
-super
-text-top
-text-bottom
-top
-bottom
-// HTML alignment MIDDLE has no corresponding CSS alignment
--webkit-baseline-middle
-//
-// text-align
-// The order of this enum must match the order found in CSSParserFastPaths::isValidKeywordPropertyAndValue().
-//
--webkit-auto
-left
-right
-center
-justify
--webkit-left
--webkit-right
--webkit-center
--webkit-match-parent
--internal-center
-//
-// text-justify
-//
-//auto
-//none
-inter-word
-distribute
-//
-// list-style-position
-//
-outside
-inside
-//
-// list-style-type
-// The order of this enum must match the order found in CSSParserFastPaths::isValidKeywordPropertyAndValue().
-//
-disc
-circle
-square
-decimal
-decimal-leading-zero
-arabic-indic
-bengali
-cambodian
-khmer
-devanagari
-gujarati
-gurmukhi
-kannada
-lao
-malayalam
-mongolian
-myanmar
-oriya
-persian
-urdu
-telugu
-tibetan
-thai
-lower-roman
-upper-roman
-lower-greek
-lower-alpha
-lower-latin
-upper-alpha
-upper-latin
-cjk-earthly-branch
-cjk-heavenly-stem
-ethiopic-halehame
-ethiopic-halehame-am
-ethiopic-halehame-ti-er
-ethiopic-halehame-ti-et
-hangul
-hangul-consonant
-korean-hangul-formal
-korean-hanja-formal
-korean-hanja-informal
-hebrew
-armenian
-lower-armenian
-upper-armenian
-georgian
-cjk-ideographic
-simp-chinese-formal
-simp-chinese-informal
-trad-chinese-formal
-trad-chinese-informal
-hiragana
-katakana
-hiragana-iroha
-katakana-iroha
-//none
-//
-// display
-// The order of this enum must match the order found in CSSParserFastPaths::isValidKeywordPropertyAndValue().
-//
-inline
-block
-list-item
-inline-block
-table
-inline-table
-table-row-group
-table-header-group
-table-footer-group
-table-row
-table-column-group
-table-column
-table-cell
-table-caption
--webkit-box
--webkit-inline-box
-flex
-inline-flex
-grid
-inline-grid
-contents
-//none
--webkit-flex
--webkit-inline-flex
-//
-// cursor
-// The order of this enum must match the order found in CSSPropertyParser::consumeCursor().
-//
-auto
-crosshair
-default
-pointer
-move
-vertical-text
-cell
-context-menu
-alias
-// copy
-progress
-no-drop
-not-allowed
-zoom-in
-zoom-out
-e-resize
-ne-resize
-nw-resize
-n-resize
-se-resize
-sw-resize
-s-resize
-w-resize
-ew-resize
-ns-resize
-nesw-resize
-nwse-resize
-col-resize
-row-resize
-text
-wait
-help
-all-scroll
--webkit-grab
--webkit-grabbing
--webkit-zoom-in
--webkit-zoom-out
-// none
-//
-// direction
-//
-ltr
-rtl
-//
-// text-transform
-//
-capitalize
-uppercase
-lowercase
-//none
-//
-// visibility
-//
-visible
-//hidden
-collapse
-//
-// Unordered rest
-//
-a3
-a4
-a5
-above
-absolute
-always
-avoid
-b4
-b5
-below
-bidi-override
-blink
-both
-close-quote
-embed
-fixed
-hand
-hide
-isolate
-isolate-override
-plaintext
--webkit-isolate
--webkit-isolate-override
--webkit-plaintext
-landscape
-ledger
-legal
-letter
-line-through
-local
-no-close-quote
-no-open-quote
-nowrap
-open-quote
-overlay
-overline
-portrait
-pre
-pre-line
-pre-wrap
-relative
-scroll
-separate
-show
-static
-thick
-thin
-underline
-wavy
--webkit-nowrap
-
-// CSS3 Values
-// box-align
-stretch
-start
-end
-//center
-//baseline
-
-// box-decoration-break
-clone
-slice
-
-// box-direction
-// normal
-reverse
-
-// box-orient
-horizontal
-vertical
-inline-axis
-block-axis
-
-// box-pack
-// start
-// end
-// center
-// justify
-
-// box-lines
-single
-multiple
-
-// align-content
-// start
-// end
-flex-start
-flex-end
-// center
-space-between
-space-around
-space-evenly
-// stretch
-unsafe
-safe
-
-// align-items / align-self
-// flex-start
-// flex-end
-// center
-// baseline
-// stretch
-
-// justify-content
-// start
-// end
-// flex-start
-// flex-end
-// center
-// space-between
-// space-around
-// space-evenly
-// stretch
-// unsafe
-// safe
-
-
-// flex-flow
-row
-row-reverse
-column
-column-reverse
-// nowrap
-wrap
-wrap-reverse
-
-// grid-auto-flow
-auto-flow
-dense
-
-//
-// -webkit-user-modify
-//
-read-only
-read-write
-read-write-plaintext-only
-
-//
-// -webkit-user-drag
-//
-element
-
-//
-// CSS3 intrinsic dimension keywords
-//
--webkit-min-content
--webkit-max-content
--webkit-fill-available
--webkit-fit-content
-min-content
-max-content
-fit-content
-
-//
-// text-overflow
-//
-clip
-ellipsis
-
-//
-// text-decoration-skip
-//
-objects
-ink
-
-//
-// -webkit-margin-collapse
-//
-// collapse
-// separate
-discard
-
-//
-// word-break
-//
-break-all
-keep-all
-
-//
-// word-wrap
-//
-break-word
-
-//
-// nbsp-mode
-//
-space
-
-//
-// -webkit-line-break
-//
-// auto
-loose
-// normal
-strict
-after-white-space
-
-// hyphens
-manual
-
-// -webkit-appearance
-// The order here must match the order in the ControlPart enum in ThemeTypes.h.
-// All appearance values that should be accepted by the parser should be listed between 'checkbox' and 'textarea':
-checkbox
-radio
-push-button
-square-button
-button
-button-bevel
-inner-spin-button
-listbox
-listitem
-media-enter-fullscreen-button
-media-exit-fullscreen-button
-media-fullscreen-volume-slider
-media-fullscreen-volume-slider-thumb
-media-mute-button
-media-play-button
-media-overlay-play-button
-media-toggle-closed-captions-button
-media-slider
-media-sliderthumb
-media-volume-slider-container
-media-volume-slider
-media-volume-sliderthumb
-media-controls-background
-media-controls-fullscreen-background
-media-current-time-display
-media-time-remaining-display
--internal-media-cast-off-button
--internal-media-overlay-cast-off-button
--internal-media-track-selection-checkmark
--internal-media-closed-captions-icon
--internal-media-subtitles-icon
--internal-media-overflow-button
--internal-media-download-button
-menulist
-menulist-button
-menulist-text
-menulist-textfield
-meter
-progress-bar
-progress-bar-value
-slider-horizontal
-slider-vertical
-sliderthumb-horizontal
-sliderthumb-vertical
-caret
-searchfield
-searchfield-cancel-button
-textfield
-textarea
-// An appearance value that should not be accepted by the parser:
-caps-lock-indicator
-
-//
-// border-image
-//
-// stretch
-// repeat
-round
-
-//
-// background-clip/background-origin
-//
-// border/content/padding are deprecated and ultimately will only apply to the -webkit- form of these properties.
-// border-box/content-box/padding-box should be used instead.
-//
-border
-border-box
-content
-content-box
-padding
-padding-box
-
-// CSS 3 SHAPES
-margin-box
-
-//
-// background-size
-//
-contain
-cover
-
-//
-// -webkit-rtl-ordering
-//
-logical
-visual
-
-//
-// animation-direction
-//
-alternate
-alternate-reverse
-
-//
-// animation-fill-mode
-//
-forwards
-backwards
-// both
-
-//
-// animation-iteration-count
-infinite
-
-//
-// animation-play-state
-//
-running
-paused
-
-//
-// transform-style
-//
-flat
-preserve-3d
-
-//
-// transition-timing-function
-// animation-timing-function
-//
-ease
-linear
-ease-in
-ease-out
-ease-in-out
-step-start
-step-middle
-step-end
-steps
-cubic-bezier
-
-//
-// zoom
-//
-document
-reset
-
-//
-// user-zoom
-//
-// fixed
-zoom
-
-//
-// pointer-events
-//
-visiblePainted
-visibleFill
-visibleStroke
-//visible
-painted
-fill
-stroke
-bounding-box
-//all
-//none
-
-//
-// speech
-//
-spell-out
-digits
-literal-punctuation
-no-punctuation
-
-//
-// -webkit-font-smoothing
-//
-// auto
-// none
-antialiased
-subpixel-antialiased
-
-// text-rendering
-//auto
-optimizeSpeed
-optimizeLegibility
-geometricPrecision
-
-// -webkit-color-adjust
-economy
-exact
-
-// -webkit-writing-mode
-// SVG compatibility
-lr
-rl
-tb
-lr-tb
-rl-tb
-tb-rl
-// Standard values from CSS3
-horizontal-tb
-vertical-rl
-vertical-lr
-
-// -webkit-ruby-position
-after
-before
-
-// -webkit-text-emphasis-position
-over
-under
-
-// -webkit-text-emphasis-style
-filled
-open
-dot
-// circle
-double-circle
-triangle
-sesame
-
-// -webkit-radial-gradient
-// circle
-ellipse
-closest-side
-closest-corner
-farthest-side
-farthest-corner
-// contain
-// cover
-
-// text-orientation/-webkit-text-orientation
-mixed
-sideways
-sideways-right
-upright
-vertical-right
-
-// -webkit-font-feature-settings
-on
-off
-
-// image-rendering
-//auto
-//optimizeSpeed
-optimizeQuality
-pixelated
--webkit-optimize-contrast
-
-// shape-outside
-nonzero
-evenodd
-at
-// closest-side
-// farthest-side
-
-alphabetic
-
-// (display-mode:) media feature
-fullscreen
-standalone
-minimal-ui
-browser
-
-// position
-sticky
-
-// (pointer:) media feature
-// none
-coarse
-fine
-
-// (hover:) media feature
-//  none
-on-demand
-hover
-
-// blend modes
-// normal
-multiply
-screen
-// overlay
-darken
-lighten
-color-dodge
-color-burn
-hard-light
-soft-light
-difference
-exclusion
-hue
-saturation
-color
-luminosity
-
-// object-fit
-scale-down
-
-// column-fill
-balance
-
-// overflow
--webkit-paged-x
--webkit-paged-y
-
-// -webkit-app-region
-drag
-no-drag
-
-// grid-{column|row}-{start|end}
-span
-
-// grid-template-{columns|rows}
-minmax
-
-// text-indent
-each-line
-//hanging   // hanging exists in SVGCSSValueKeywords.in
-
-// (scan:) media feature
-progressive
-interlace
-
-//
-// paint-order
-//
-// normal
-// fill
-// stroke
-markers
-
-//
-// CSS3 viewport-length keywords
-//
--internal-extend-to-zoom
-
-// isolation
-// auto
-isolate
-
-// touch-action
-pan-x
-pan-y
-pan-left
-pan-right
-pan-up
-pan-down
-manipulation
-pinch-zoom
-
-// justify-items / justify-self
-// auto
-// stretch
-// baseline
-last-baseline
-// center
-// start
-// end
-self-start
-self-end
-// flex-start
-// flex-end
-// left
-// right
-// unsafe
-// safe
-legacy
-
-// scroll-behavior
-// auto
-smooth
-
-// will-change
-// auto
-contents
-scroll-position
-
-// all
-// initial
-// inherit
-revert
-unset
-
-// background-image, etc.
-linear-gradient
-radial-gradient
-repeating-linear-gradient
-repeating-radial-gradient
-paint
--webkit-cross-fade
--webkit-gradient
--webkit-linear-gradient
--webkit-radial-gradient
--webkit-repeating-linear-gradient
--webkit-repeating-radial-gradient
--webkit-image-set
-
-// deprecated gradients
-from
-to
-color-stop
-radial
-
-// content
-attr
-counter
-counters
-
-// clip
-rect
-
-// shapes
-polygon
-
-// @font-face src
-format
-
-// (-webkit-)filter
-invert
-grayscale
-sepia
-saturate
-hue-rotate
-opacity
-brightness
-contrast
-blur
-drop-shadow
-url
-
-// colors
-rgb
-rgba
-hsl
-hsla
-
-// transform
-matrix
-matrix3d
-perspective
-rotate
-rotateX
-rotateY
-rotateZ
-rotate3d
-scale
-scaleX
-scaleY
-scaleZ
-scale3d
-skew
-skewX
-skewY
-translate
-translateX
-translateY
-translateZ
-translate3d
-
-// motion path
-path
-
-calc
--webkit-calc
-
-// scroll-snap-type
-// none
-mandatory
-proximity
-from-image
-
-// containment
-paint
-style
-layout
-size
-
-// grid auto-repeat
-auto-fill
-auto-fit
-
-var
--internal-variable-value
-
-// break-before, break-after, break-inside
-avoid-page
-page
-recto
-verso
-avoid-column
-
-// shape
-// rect
-// round
-
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.json5 b/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
new file mode 100644
index 0000000..6dc8b5a
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
@@ -0,0 +1,1125 @@
+{
+// The mode argument is used to limit the keyword to be used only for certain
+// CSSParserModes. Values that have the prefix -internal- are only allowed by
+// CSSParserModes listed in allowInternalPropertyAndValue()
+
+parameters: {
+    mode: {},
+},
+
+//
+// CSS value names
+//
+
+data: [
+
+  "inherit",
+  "initial",
+  //
+  // outline-style
+  // border-top-style
+  // border-bottom-style
+  // border-left-style
+  // border-right-style
+  // The order here must match the order of the EBorderStyle enum in ComputedStyleConstants.h.
+  "none",
+  "hidden",
+  "inset",
+  "groove",
+  "outset",
+  "ridge",
+  "dotted",
+  "dashed",
+  "solid",
+  "double",
+
+  //
+  // font
+  //
+  "caption",
+  "icon",
+  "menu",
+  "message-box",
+  "small-caption",
+  "-webkit-mini-control",
+  "-webkit-small-control",
+  "-webkit-control",
+  "status-bar",
+
+  //
+  // font-style
+  //
+  //normal
+  "italic",
+  "oblique",
+  // The following is only allowed in @font-face:
+  "all",
+
+  // font-variant-ligatures:
+  //
+  // normal
+  "common-ligatures",
+  "no-common-ligatures",
+  "discretionary-ligatures",
+  "no-discretionary-ligatures",
+  "historical-ligatures",
+  "no-historical-ligatures",
+  "contextual",
+  "no-contextual",
+
+  // font-variant-caps:
+  //
+  // normal
+  "small-caps",
+  "all-small-caps",
+  "petite-caps",
+  "all-petite-caps",
+  "unicase",
+  "titling-caps",
+
+  // font-variant-numeric
+  // normal
+  "lining-nums",
+  "oldstyle-nums",
+  "proportional-nums",
+  "tabular-nums",
+  "diagonal-fractions",
+  "stacked-fractions",
+  "ordinal",
+  "slashed-zero",
+
+  //
+  // font-weigth
+  //
+  "normal",
+  "bold",
+  "bolder",
+  "lighter",
+  "100",
+  "200",
+  "300",
+  "400",
+  "500",
+  "600",
+  "700",
+  "800",
+  "900",
+
+  //
+  // font-stretch
+  //
+  "ultra-condensed",
+  "extra-condensed",
+  "condensed",
+  "semi-condensed",
+  "semi-expanded",
+  "expanded",
+  "extra-expanded",
+  "ultra-expanded",
+
+  //
+  // font-size
+  //
+  "xx-small",
+  "x-small",
+  "small",
+  "medium",
+  "large",
+  "x-large",
+  "xx-large",
+  "-webkit-xxx-large",
+  "smaller",
+  "larger",
+
+  //
+  // font-family (<generic-family> in CSS 2.1)
+  //
+  "serif",
+  "sans-serif",
+  "cursive",
+  "fantasy",
+  "monospace",
+  "-webkit-body",
+  "-webkit-pictograph",
+
+  //
+  // font-display
+  //
+  //auto
+  //block
+  "swap",
+  "fallback",
+  "optional",
+
+  //
+  //
+  // *-color
+  //
+  "aqua",
+  "black",
+  "blue",
+  "fuchsia",
+  "gray",
+  "green",
+  "lime",
+  "maroon",
+  "navy",
+  "olive",
+  "orange",
+  "purple",
+  "red",
+  "silver",
+  "teal",
+  "white",
+  "yellow",
+  "transparent",
+  "-webkit-link",
+  "-webkit-activelink",
+  "activeborder",
+  "activecaption",
+  "appworkspace",
+  "background",
+  "buttonface",
+  "buttonhighlight",
+  "buttonshadow",
+  "buttontext",
+  "captiontext",
+  "graytext",
+  "highlight",
+  "highlighttext",
+  "inactiveborder",
+  "inactivecaption",
+  "inactivecaptiontext",
+  "infobackground",
+  "infotext",
+  "menutext",
+  "scrollbar",
+  "threeddarkshadow",
+  "threedface",
+  "threedhighlight",
+  "threedlightshadow",
+  "threedshadow",
+  "window",
+  "windowframe",
+  "windowtext",
+  "-internal-active-list-box-selection",
+  "-internal-active-list-box-selection-text",
+  "-internal-inactive-list-box-selection",
+  "-internal-inactive-list-box-selection-text",
+  {
+    name: "-webkit-focus-ring-color",
+    mode: "QuirksOrUASheet",
+  },
+  "currentcolor",
+  "grey",
+  //
+  // Value used to implement the behavior in:
+  // https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk
+  "-internal-quirk-inherit",
+  //
+  // background-repeat
+  //
+  "repeat",
+  "repeat-x",
+  "repeat-y",
+  "no-repeat",
+  // round
+  // space
+  //
+  // -webkit-mask-composite
+  //
+  "clear",
+  "copy",
+  "source-over",
+  "source-in",
+  "source-out",
+  "source-atop",
+  "destination-over",
+  "destination-in",
+  "destination-out",
+  "destination-atop",
+  "xor",
+  // highlight
+  "plus-lighter",
+  //
+  // vertical-align
+  //
+  "baseline",
+  "middle",
+  "sub",
+  "super",
+  "text-top",
+  "text-bottom",
+  "top",
+  "bottom",
+  // HTML alignment MIDDLE has no corresponding CSS alignment
+  "-webkit-baseline-middle",
+  //
+  // text-align
+  // The order of this enum must match the order found in CSSParserFastPaths::isValidKeywordPropertyAndValue().
+  //
+  "-webkit-auto",
+  "left",
+  "right",
+  "center",
+  "justify",
+  "-webkit-left",
+  "-webkit-right",
+  "-webkit-center",
+  "-webkit-match-parent",
+  "-internal-center",
+  //
+  // text-justify
+  //
+  //auto
+  //none
+  "inter-word",
+  "distribute",
+  //
+  // list-style-position
+  //
+  "outside",
+  "inside",
+  //
+  // list-style-type
+  // The order of this enum must match the order found in CSSParserFastPaths::isValidKeywordPropertyAndValue().
+  //
+  "disc",
+  "circle",
+  "square",
+  "decimal",
+  "decimal-leading-zero",
+  "arabic-indic",
+  "bengali",
+  "cambodian",
+  "khmer",
+  "devanagari",
+  "gujarati",
+  "gurmukhi",
+  "kannada",
+  "lao",
+  "malayalam",
+  "mongolian",
+  "myanmar",
+  "oriya",
+  "persian",
+  "urdu",
+  "telugu",
+  "tibetan",
+  "thai",
+  "lower-roman",
+  "upper-roman",
+  "lower-greek",
+  "lower-alpha",
+  "lower-latin",
+  "upper-alpha",
+  "upper-latin",
+  "cjk-earthly-branch",
+  "cjk-heavenly-stem",
+  "ethiopic-halehame",
+  "ethiopic-halehame-am",
+  "ethiopic-halehame-ti-er",
+  "ethiopic-halehame-ti-et",
+  "hangul",
+  "hangul-consonant",
+  "korean-hangul-formal",
+  "korean-hanja-formal",
+  "korean-hanja-informal",
+  "hebrew",
+  "armenian",
+  "lower-armenian",
+  "upper-armenian",
+  "georgian",
+  "cjk-ideographic",
+  "simp-chinese-formal",
+  "simp-chinese-informal",
+  "trad-chinese-formal",
+  "trad-chinese-informal",
+  "hiragana",
+  "katakana",
+  "hiragana-iroha",
+  "katakana-iroha",
+  //none
+  //
+  // display
+  // The order of this enum must match the order found in CSSParserFastPaths::isValidKeywordPropertyAndValue().
+  //
+  "inline",
+  "block",
+  "list-item",
+  "inline-block",
+  "table",
+  "inline-table",
+  "table-row-group",
+  "table-header-group",
+  "table-footer-group",
+  "table-row",
+  "table-column-group",
+  "table-column",
+  "table-cell",
+  "table-caption",
+  "-webkit-box",
+  "-webkit-inline-box",
+  "flex",
+  "inline-flex",
+  "grid",
+  "inline-grid",
+  "contents",
+  //none
+  "-webkit-flex",
+  "-webkit-inline-flex",
+  //
+  // cursor
+  // The order of this enum must match the order found in CSSPropertyParser::consumeCursor().
+  //
+  "auto",
+  "crosshair",
+  "default",
+  "pointer",
+  "move",
+  "vertical-text",
+  "cell",
+  "context-menu",
+  "alias",
+  // copy
+  "progress",
+  "no-drop",
+  "not-allowed",
+  "zoom-in",
+  "zoom-out",
+  "e-resize",
+  "ne-resize",
+  "nw-resize",
+  "n-resize",
+  "se-resize",
+  "sw-resize",
+  "s-resize",
+  "w-resize",
+  "ew-resize",
+  "ns-resize",
+  "nesw-resize",
+  "nwse-resize",
+  "col-resize",
+  "row-resize",
+  "text",
+  "wait",
+  "help",
+  "all-scroll",
+  "-webkit-grab",
+  "-webkit-grabbing",
+  "-webkit-zoom-in",
+  "-webkit-zoom-out",
+  // none
+  //
+  // direction
+  //
+  "ltr",
+  "rtl",
+  //
+  // text-transform
+  //
+  "capitalize",
+  "uppercase",
+  "lowercase",
+  //none
+  //
+  // visibility
+  //
+  "visible",
+  //hidden
+  "collapse",
+  //
+  // Unordered rest
+  //
+  "a3",
+  "a4",
+  "a5",
+  "above",
+  "absolute",
+  "always",
+  "avoid",
+  "b4",
+  "b5",
+  "below",
+  "bidi-override",
+  "blink",
+  "both",
+  "close-quote",
+  "embed",
+  "fixed",
+  "hand",
+  "hide",
+  "isolate",
+  "isolate-override",
+  "plaintext",
+  "-webkit-isolate",
+  "-webkit-isolate-override",
+  "-webkit-plaintext",
+  "landscape",
+  "ledger",
+  "legal",
+  "letter",
+  "line-through",
+  "local",
+  "no-close-quote",
+  "no-open-quote",
+  "nowrap",
+  "open-quote",
+  "overlay",
+  "overline",
+  "portrait",
+  "pre",
+  "pre-line",
+  "pre-wrap",
+  "relative",
+  "scroll",
+  "separate",
+  "show",
+  "static",
+  "thick",
+  "thin",
+  "underline",
+  "wavy",
+  "-webkit-nowrap",
+
+  // CSS3 Values
+  // box-align
+  "stretch",
+  "start",
+  "end",
+  //center
+  //baseline
+
+  // box-decoration-break
+  "clone",
+  "slice",
+
+  // box-direction
+  // normal
+  "reverse",
+
+  // box-orient
+  "horizontal",
+  "vertical",
+  "inline-axis",
+  "block-axis",
+
+  // box-pack
+  // start
+  // end
+  // center
+  // justify
+
+  // box-lines
+  "single",
+  "multiple",
+
+  // align-content
+  // start
+  // end
+  "flex-start",
+  "flex-end",
+  // center
+  "space-between",
+  "space-around",
+  "space-evenly",
+  // stretch
+  "unsafe",
+  "safe",
+
+  // align-items / align-self
+  // flex-start
+  // flex-end
+  // center
+  // baseline
+  // stretch
+
+  // justify-content
+  // start
+  // end
+  // flex-start
+  // flex-end
+  // center
+  // space-between
+  // space-around
+  // space-evenly
+  // stretch
+  // unsafe
+  // safe
+
+
+  // flex-flow
+  "row",
+  "row-reverse",
+  "column",
+  "column-reverse",
+  // nowrap
+  "wrap",
+  "wrap-reverse",
+
+  // grid-auto-flow
+  "auto-flow",
+  "dense",
+
+  //
+  // -webkit-user-modify
+  //
+  "read-only",
+  "read-write",
+  "read-write-plaintext-only",
+
+  //
+  // -webkit-user-drag
+  //
+  "element",
+
+  //
+  // CSS3 intrinsic dimension keywords
+  //
+  "-webkit-min-content",
+  "-webkit-max-content",
+  "-webkit-fill-available",
+  "-webkit-fit-content",
+  "min-content",
+  "max-content",
+  "fit-content",
+
+  //
+  // text-overflow
+  //
+  "clip",
+  "ellipsis",
+
+  //
+  // text-decoration-skip
+  //
+  "objects",
+  "ink",
+
+  //
+  // -webkit-margin-collapse
+  //
+  // collapse
+  // separate
+  "discard",
+
+  //
+  // word-break
+  //
+  "break-all",
+  "keep-all",
+
+  //
+  // word-wrap
+  //
+  "break-word",
+
+  //
+  // nbsp-mode
+  //
+  "space",
+
+  //
+  // -webkit-line-break
+  //
+  // auto
+  "loose",
+  // normal
+  "strict",
+  "after-white-space",
+
+  // hyphens
+  "manual",
+
+  // -webkit-appearance
+  // The order here must match the order in the ControlPart enum in ThemeTypes.h.
+  // All appearance values that should be accepted by the parser should be listed between 'checkbox' and 'textarea':
+  "checkbox",
+  "radio",
+  "push-button",
+  "square-button",
+  "button",
+  "button-bevel",
+  "inner-spin-button",
+  "listbox",
+  "listitem",
+  "media-enter-fullscreen-button",
+  "media-exit-fullscreen-button",
+  "media-fullscreen-volume-slider",
+  "media-fullscreen-volume-slider-thumb",
+  "media-mute-button",
+  "media-play-button",
+  "media-overlay-play-button",
+  "media-toggle-closed-captions-button",
+  "media-slider",
+  "media-sliderthumb",
+  "media-volume-slider-container",
+  "media-volume-slider",
+  "media-volume-sliderthumb",
+  "media-controls-background",
+  "media-controls-fullscreen-background",
+  "media-current-time-display",
+  "media-time-remaining-display",
+  "-internal-media-cast-off-button",
+  "-internal-media-overlay-cast-off-button",
+  "-internal-media-track-selection-checkmark",
+  "-internal-media-closed-captions-icon",
+  "-internal-media-subtitles-icon",
+  "-internal-media-overflow-button",
+  "-internal-media-download-button",
+  "menulist",
+  "menulist-button",
+  "menulist-text",
+  "menulist-textfield",
+  "meter",
+  "progress-bar",
+  "progress-bar-value",
+  "slider-horizontal",
+  "slider-vertical",
+  "sliderthumb-horizontal",
+  "sliderthumb-vertical",
+  "caret",
+  "searchfield",
+  "searchfield-cancel-button",
+  "textfield",
+  "textarea",
+  // An appearance value that should not be accepted by the parser:
+  "caps-lock-indicator",
+
+  //
+  // border-image
+  //
+  // stretch
+  // repeat
+  "round",
+
+  //
+  // background-clip/background-origin
+  //
+  // border/content/padding are deprecated and ultimately will only apply to the -webkit- form of these properties.
+  // border-box/content-box/padding-box should be used instead.
+  //
+  "border",
+  "border-box",
+  "content",
+  "content-box",
+  "padding",
+  "padding-box",
+
+  // CSS 3 SHAPES
+  "margin-box",
+
+  //
+  // background-size
+  //
+  "contain",
+  "cover",
+
+  //
+  // -webkit-rtl-ordering
+  //
+  "logical",
+  "visual",
+
+  //
+  // animation-direction
+  //
+  "alternate",
+  "alternate-reverse",
+
+  //
+  // animation-fill-mode
+  //
+  "forwards",
+  "backwards",
+  // both
+
+  //
+  // animation-iteration-count
+  "infinite",
+
+  //
+  // animation-play-state
+  //
+  "running",
+  "paused",
+
+  //
+  // transform-style
+  //
+  "flat",
+  "preserve-3d",
+
+  //
+  // transition-timing-function
+  // animation-timing-function
+  //
+  "ease",
+  "linear",
+  "ease-in",
+  "ease-out",
+  "ease-in-out",
+  "step-start",
+  "step-middle",
+  "step-end",
+  "steps",
+  "cubic-bezier",
+
+  //
+  // zoom
+  //
+  "document",
+  "reset",
+
+  //
+  // user-zoom
+  //
+  // fixed
+  "zoom",
+
+  //
+  // pointer-events
+  //
+  "visiblePainted",
+  "visibleFill",
+  "visibleStroke",
+  //visible
+  "painted",
+  "fill",
+  "stroke",
+  "bounding-box",
+  //all
+  //none
+
+  //
+  // speech
+  //
+  "spell-out",
+  "digits",
+  "literal-punctuation",
+  "no-punctuation",
+
+  //
+  // -webkit-font-smoothing
+  //
+  // auto
+  // none
+  "antialiased",
+  "subpixel-antialiased",
+
+  // text-rendering
+  //auto
+  "optimizeSpeed",
+  "optimizeLegibility",
+  "geometricPrecision",
+
+  // -webkit-color-adjust
+  "economy",
+  "exact",
+
+  // -webkit-writing-mode
+  // SVG compatibility
+  "lr",
+  "rl",
+  "tb",
+  "lr-tb",
+  "rl-tb",
+  "tb-rl",
+  // Standard values from CSS3
+  "horizontal-tb",
+  "vertical-rl",
+  "vertical-lr",
+
+  // -webkit-ruby-position
+  "after",
+  "before",
+
+  // -webkit-text-emphasis-position
+  "over",
+  "under",
+
+  // -webkit-text-emphasis-style
+  "filled",
+  "open",
+  "dot",
+  // circle
+  "double-circle",
+  "triangle",
+  "sesame",
+
+  // -webkit-radial-gradient
+  // circle
+  "ellipse",
+  "closest-side",
+  "closest-corner",
+  "farthest-side",
+  "farthest-corner",
+  // contain
+  // cover
+
+  // text-orientation/-webkit-text-orientation
+  "mixed",
+  "sideways",
+  "sideways-right",
+  "upright",
+  "vertical-right",
+
+  // -webkit-font-feature-settings
+  "on",
+  "off",
+
+  // image-rendering
+  //auto
+  //optimizeSpeed
+  "optimizeQuality",
+  "pixelated",
+  "-webkit-optimize-contrast",
+
+  // shape-outside
+  "nonzero",
+  "evenodd",
+  "at",
+  // closest-side
+  // farthest-side
+
+  "alphabetic",
+
+  // (display-mode:) media feature
+  "fullscreen",
+  "standalone",
+  "minimal-ui",
+  "browser",
+
+  // position
+  "sticky",
+
+  // (pointer:) media feature
+  // none
+  "coarse",
+  "fine",
+
+  // (hover:) media feature
+  //  none
+  "on-demand",
+  "hover",
+
+  // blend modes
+  // normal
+  "multiply",
+  "screen",
+  // overlay
+  "darken",
+  "lighten",
+  "color-dodge",
+  "color-burn",
+  "hard-light",
+  "soft-light",
+  "difference",
+  "exclusion",
+  "hue",
+  "saturation",
+  "color",
+  "luminosity",
+
+  // object-fit
+  "scale-down",
+
+  // column-fill
+  "balance",
+
+  // overflow
+  "-webkit-paged-x",
+  "-webkit-paged-y",
+
+  // -webkit-app-region
+  "drag",
+  "no-drag",
+
+  // grid-{column|row}-{start|end}
+  "span",
+
+  // grid-template-{columns|rows}
+  "minmax",
+
+  // text-indent
+  "each-line",
+  //hanging   // hanging exists in SVGCSSValueKeywords.in
+
+  // (scan:) media feature
+  "progressive",
+  "interlace",
+
+  //
+  // paint-order
+  //
+  // normal
+  // fill
+  // stroke
+  "markers",
+
+  //
+  // CSS3 viewport-length keywords
+  //
+  "-internal-extend-to-zoom",
+
+  // isolation
+  // auto
+  // isolate
+
+  // touch-action
+  "pan-x",
+  "pan-y",
+  "pan-left",
+  "pan-right",
+  "pan-up",
+  "pan-down",
+  "manipulation",
+  "pinch-zoom",
+
+  // justify-items / justify-self
+  // auto
+  // stretch
+  // baseline
+  "last-baseline",
+  // center
+  // start
+  // end
+  "self-start",
+  "self-end",
+  // flex-start
+  // flex-end
+  // left
+  // right
+  // unsafe
+  // safe
+  "legacy",
+
+  // scroll-behavior
+  // auto
+  "smooth",
+
+  // will-change
+  // auto
+  // contents
+  "scroll-position",
+
+  // all
+  // initial
+  // inherit
+  "revert",
+  "unset",
+
+  // background-image, etc.
+  "linear-gradient",
+  "radial-gradient",
+  "repeating-linear-gradient",
+  "repeating-radial-gradient",
+  "paint",
+  "-webkit-cross-fade",
+  "-webkit-gradient",
+  "-webkit-linear-gradient",
+  "-webkit-radial-gradient",
+  "-webkit-repeating-linear-gradient",
+  "-webkit-repeating-radial-gradient",
+  "-webkit-image-set",
+
+  // deprecated gradients
+  "from",
+  "to",
+  "color-stop",
+  "radial",
+
+  // content
+  "attr",
+  "counter",
+  "counters",
+
+  // clip
+  "rect",
+
+  // shapes
+  "polygon",
+
+  // @font-face src
+  "format",
+
+  // (-webkit-)filter
+  "invert",
+  "grayscale",
+  "sepia",
+  "saturate",
+  "hue-rotate",
+  "opacity",
+  "brightness",
+  "contrast",
+  "blur",
+  "drop-shadow",
+  "url",
+
+  // colors
+  "rgb",
+  "rgba",
+  "hsl",
+  "hsla",
+
+  // transform
+  "matrix",
+  "matrix3d",
+  "perspective",
+  "rotate",
+  "rotateX",
+  "rotateY",
+  "rotateZ",
+  "rotate3d",
+  "scale",
+  "scaleX",
+  "scaleY",
+  "scaleZ",
+  "scale3d",
+  "skew",
+  "skewX",
+  "skewY",
+  "translate",
+  "translateX",
+  "translateY",
+  "translateZ",
+  "translate3d",
+
+  // motion path
+  "path",
+
+  "calc",
+  "-webkit-calc",
+
+  // scroll-snap-type
+  // none
+  "mandatory",
+  "proximity",
+  "from-image",
+
+  // containment
+  // paint
+  "style",
+  "layout",
+  "size",
+
+  // grid auto-repeat
+  "auto-fill",
+  "auto-fit",
+
+  "var",
+  "-internal-variable-value",
+
+  // break-before, break-after, break-inside
+  "avoid-page",
+  "page",
+  "recto",
+  "verso",
+  "avoid-column",
+
+  // shape
+  // rect
+  // round
+
+]
+}
diff --git a/third_party/WebKit/Source/core/css/CSSVariableData.cpp b/third_party/WebKit/Source/core/css/CSSVariableData.cpp
index 07b022425..58f2fa5 100644
--- a/third_party/WebKit/Source/core/css/CSSVariableData.cpp
+++ b/third_party/WebKit/Source/core/css/CSSVariableData.cpp
@@ -73,7 +73,10 @@
 const CSSValue* CSSVariableData::parseForSyntax(
     const CSSSyntaxDescriptor& syntax) const {
   DCHECK(!needsVariableResolution());
-  return syntax.parse(tokenRange(), m_isAnimationTainted);
+  // TODO(timloh): This probably needs a proper parser context for
+  // relative URL resolution.
+  return syntax.parse(tokenRange(), strictCSSParserContext(),
+                      m_isAnimationTainted);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl b/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl
index 201f53c2..047b12d 100644
--- a/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl
+++ b/third_party/WebKit/Source/core/css/FontFaceSetLoadEvent.idl
@@ -30,10 +30,10 @@
 
 // https://dev.w3.org/csswg/css-font-loading/#fontfacesetloadevent
 
-// TODO(foolip): This interface should have a constructor and
-// [Exposed=Window,Worker], and thus not [NoInterfaceObject].
 [
-    NoInterfaceObject,
+  Constructor(DOMString type, optional FontFaceSetLoadEventInit eventInitDict),
+  // TODO(lunalu): Exposed=(Window,Worker)
+  Exposed=Window
 ] interface FontFaceSetLoadEvent : Event {
-    readonly attribute sequence<FontFace> fontfaces;
+    [SameObject] readonly attribute FrozenArray<FontFace> fontfaces;
 };
diff --git a/third_party/WebKit/Source/core/css/PropertyRegistration.cpp b/third_party/WebKit/Source/core/css/PropertyRegistration.cpp
index 09683e1..71bbc5d70 100644
--- a/third_party/WebKit/Source/core/css/PropertyRegistration.cpp
+++ b/third_party/WebKit/Source/core/css/PropertyRegistration.cpp
@@ -5,11 +5,14 @@
 #include "core/css/PropertyRegistration.h"
 
 #include "core/animation/CSSValueInterpolationType.h"
+#include "core/css/CSSStyleSheet.h"
 #include "core/css/CSSSyntaxDescriptor.h"
 #include "core/css/CSSValueList.h"
 #include "core/css/CSSVariableReferenceValue.h"
 #include "core/css/PropertyDescriptor.h"
 #include "core/css/PropertyRegistry.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSTokenizer.h"
 #include "core/css/parser/CSSVariableParser.h"
 #include "core/css/resolver/StyleBuilderConverter.h"
@@ -108,8 +111,10 @@
   if (descriptor.hasInitialValue()) {
     CSSTokenizer tokenizer(descriptor.initialValue());
     bool isAnimationTainted = false;
-    const CSSValue* initial =
-        syntaxDescriptor.parse(tokenizer.tokenRange(), isAnimationTainted);
+    const CSSValue* initial = syntaxDescriptor.parse(
+        tokenizer.tokenRange(),
+        document->elementSheet().contents()->parserContext(),
+        isAnimationTainted);
     if (!initial) {
       exceptionState.throwDOMException(
           SyntaxError,
diff --git a/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in b/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in
deleted file mode 100644
index 139c7ced..0000000
--- a/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in
+++ /dev/null
@@ -1,282 +0,0 @@
-//
-// SVG CSS value names
-//
-
-// CSS_PROP_*_COLOR
-//
-aliceblue
-antiquewhite
-// aqua
-aquamarine
-azure
-beige
-bisque
-// black
-blanchedalmond
-// blue
-blueviolet
-brown
-burlywood
-cadetblue
-chartreuse
-chocolate
-coral
-cornflowerblue
-cornsilk
-crimson
-cyan
-darkblue
-darkcyan
-darkgoldenrod
-darkgray
-darkgreen
-darkgrey
-darkkhaki
-darkmagenta
-darkolivegreen
-darkorange
-darkorchid
-darkred
-darksalmon
-darkseagreen
-darkslateblue
-darkslategray
-darkslategrey
-darkturquoise
-darkviolet
-deeppink
-deepskyblue
-dimgray
-dimgrey
-dodgerblue
-firebrick
-floralwhite
-forestgreen
-// fuchsia
-gainsboro
-ghostwhite
-gold
-goldenrod
-// gray
-// grey
-// green
-greenyellow
-honeydew
-hotpink
-indianred
-indigo
-ivory
-khaki
-lavender
-lavenderblush
-lawngreen
-lemonchiffon
-lightblue
-lightcoral
-lightcyan
-lightgoldenrodyellow
-lightgray
-lightgreen
-lightgrey
-lightpink
-lightsalmon
-lightseagreen
-lightskyblue
-lightslategray
-lightslategrey
-lightsteelblue
-lightyellow
-// lime
-limegreen
-linen
-magenta
-// maroon
-mediumaquamarine
-mediumblue
-mediumorchid
-mediumpurple
-mediumseagreen
-mediumslateblue
-mediumspringgreen
-mediumturquoise
-mediumvioletred
-midnightblue
-mintcream
-mistyrose
-moccasin
-navajowhite
-// navy
-oldlace
-// olive
-olivedrab
-// orange
-orangered
-orchid
-palegoldenrod
-palegreen
-paleturquoise
-palevioletred
-papayawhip
-peachpuff
-peru
-pink
-plum
-powderblue
-// purple
-rebeccapurple
-// red
-rosybrown
-royalblue
-saddlebrown
-salmon
-sandybrown
-seagreen
-seashell
-sienna
-// silver
-skyblue
-slateblue
-slategray
-slategrey
-snow
-springgreen
-steelblue
-tan
-// teal
-thistle
-tomato
-turquoise
-violet
-wheat
-// white
-whitesmoke
-// yellow
-yellowgreen
-
-// mask-type / mask-mode
-alpha
-luminance
-
-// CSS_PROP_CLIP_PATH
-// CSS_PROP_CLIP_RULE
-// nonzero and evenodd part of core CSS values now.
-
-// CSS_PROP_MASK
-// CSS_PROP_OPACITY
-accumulate
-new
-
-// CSS_PROP_FILTER
-// CSS_PROP_FLOOD_COLOR
-//currentColor
-
-// CSS_PROP_FLOOD_OPACITY
-// CSS_PROP_LIGHTING_COLOR
-//currentColor
-
-// CSS_PROP_STOP_COLOR
-// CSS_PROP_STOP_OPACITY
-// CSS_PROP_COLOR_INTERPOLATION
-//auto
-sRGB
-linearRGB
-
-// CSS_PROP_COLOR_INTERPOLATION_FILTERS
-//auto
-//sRGB
-//linearRGB
-
-// CSS_PROP_COLOR_PROFILE
-//sRGB
-
-// CSS_PROP_COLOR_RENDERING
-//auto
-//optimizeSpeed
-//optimizeQuality
-
-//// CSS_PROP_FILL
-//currentColor
-
-// CSS_PROP_FILL_OPACITY
-// CSS_PROP_FILL_RULE
-//nonzero
-//evenodd
-
-// CSS_PROP_IMAGE_RENDERING
-//auto
-//optimizeSpeed
-//optimizeQuality
-
-// CSS_PROP_MARKER
-// CSS_PROP_MARKER_END
-// CSS_PROP_MARKER_MID
-// CSS_PROP_MARKER_START
-// CSS_PROP_SHAPE_RENDERING
-//auto
-//optimizeSpeed
-crispEdges
-//geometricPrecision
-
-// CSS_PROP_STROKE
-// CSS_PROP_STROKE_DASHARRAY
-// CSS_PROP_STROKE_DASHOFFSET
-// CSS_PROP_STROKE_LINECAP
-butt
-// round
-// square
-
-// CSS_PROP_STROKE_LINEJOIN
-miter
-// round
-bevel
-
-// CSS_PROP_STROKE_MITERLIMIT
-// CSS_PROP_STROKE_OPACITY
-// CSS_PROP_STROKE_WIDTH
-
-// CSS_PROP_ALIGNMENT_BASELINE
-//auto
-// baseline
-before-edge
-after-edge
-//middle
-central
-text-before-edge
-text-after-edge
-ideographic
-hanging
-mathematical
-
-// CSS_PROP_BASELINE_SHIFT
-//baseline
-// sub
-// super
-
-// CSS_PROP_DOMINANT_BASELINE
-//auto
-use-script
-no-change
-reset-size
-
-// CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL
-
-// CSS_PROP_GLYPH_ORIENTATION_VERTICAL
-// CSS_PROP_TEXT_ANCHOR
-// start
-// middle
-// end
-
-// CSS_PROP_BUFFERED_RENDERING
-// auto
-// static
-dynamic
-
-// CSS_PROP_VECTOR_EFFECT
-// none
-non-scaling-stroke
-
-// CSS_PROP_PAINT_ORDER
-// normal
-// fill
-// stroke
-// markers
diff --git a/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.json5 b/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.json5
new file mode 100644
index 0000000..23811899
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.json5
@@ -0,0 +1,286 @@
+{
+//
+// SVG CSS value names
+//
+
+data: [
+  // CSS_PROP_*_COLOR
+  //
+  "aliceblue",
+  "antiquewhite",
+  // aqua
+  "aquamarine",
+  "azure",
+  "beige",
+  "bisque",
+  // black
+  "blanchedalmond",
+  // blue
+  "blueviolet",
+  "brown",
+  "burlywood",
+  "cadetblue",
+  "chartreuse",
+  "chocolate",
+  "coral",
+  "cornflowerblue",
+  "cornsilk",
+  "crimson",
+  "cyan",
+  "darkblue",
+  "darkcyan",
+  "darkgoldenrod",
+  "darkgray",
+  "darkgreen",
+  "darkgrey",
+  "darkkhaki",
+  "darkmagenta",
+  "darkolivegreen",
+  "darkorange",
+  "darkorchid",
+  "darkred",
+  "darksalmon",
+  "darkseagreen",
+  "darkslateblue",
+  "darkslategray",
+  "darkslategrey",
+  "darkturquoise",
+  "darkviolet",
+  "deeppink",
+  "deepskyblue",
+  "dimgray",
+  "dimgrey",
+  "dodgerblue",
+  "firebrick",
+  "floralwhite",
+  "forestgreen",
+  // fuchsia
+  "gainsboro",
+  "ghostwhite",
+  "gold",
+  "goldenrod",
+  // gray
+  // grey
+  // green
+  "greenyellow",
+  "honeydew",
+  "hotpink",
+  "indianred",
+  "indigo",
+  "ivory",
+  "khaki",
+  "lavender",
+  "lavenderblush",
+  "lawngreen",
+  "lemonchiffon",
+  "lightblue",
+  "lightcoral",
+  "lightcyan",
+  "lightgoldenrodyellow",
+  "lightgray",
+  "lightgreen",
+  "lightgrey",
+  "lightpink",
+  "lightsalmon",
+  "lightseagreen",
+  "lightskyblue",
+  "lightslategray",
+  "lightslategrey",
+  "lightsteelblue",
+  "lightyellow",
+  // lime
+  "limegreen",
+  "linen",
+  "magenta",
+  // maroon
+  "mediumaquamarine",
+  "mediumblue",
+  "mediumorchid",
+  "mediumpurple",
+  "mediumseagreen",
+  "mediumslateblue",
+  "mediumspringgreen",
+  "mediumturquoise",
+  "mediumvioletred",
+  "midnightblue",
+  "mintcream",
+  "mistyrose",
+  "moccasin",
+  "navajowhite",
+  // navy
+  "oldlace",
+  // olive
+  "olivedrab",
+  // orange
+  "orangered",
+  "orchid",
+  "palegoldenrod",
+  "palegreen",
+  "paleturquoise",
+  "palevioletred",
+  "papayawhip",
+  "peachpuff",
+  "peru",
+  "pink",
+  "plum",
+  "powderblue",
+  // purple
+  "rebeccapurple",
+  // red
+  "rosybrown",
+  "royalblue",
+  "saddlebrown",
+  "salmon",
+  "sandybrown",
+  "seagreen",
+  "seashell",
+  "sienna",
+  // silver
+  "skyblue",
+  "slateblue",
+  "slategray",
+  "slategrey",
+  "snow",
+  "springgreen",
+  "steelblue",
+  "tan",
+  // teal
+  "thistle",
+  "tomato",
+  "turquoise",
+  "violet",
+  "wheat",
+  // white
+  "whitesmoke",
+  // yellow
+  "yellowgreen",
+
+  // mask-type / mask-mode
+  "alpha",
+  "luminance",
+
+  // CSS_PROP_CLIP_PATH
+  // CSS_PROP_CLIP_RULE
+  // nonzero and evenodd part of core CSS values now.
+
+  // CSS_PROP_MASK
+  // CSS_PROP_OPACITY
+  "accumulate",
+  "new",
+
+  // CSS_PROP_FILTER
+  // CSS_PROP_FLOOD_COLOR
+  //currentColor
+
+  // CSS_PROP_FLOOD_OPACITY
+  // CSS_PROP_LIGHTING_COLOR
+  //currentColor
+
+  // CSS_PROP_STOP_COLOR
+  // CSS_PROP_STOP_OPACITY
+  // CSS_PROP_COLOR_INTERPOLATION
+  //auto
+  "sRGB",
+  "linearRGB",
+
+  // CSS_PROP_COLOR_INTERPOLATION_FILTERS
+  //auto
+  //sRGB
+  //linearRGB
+
+  // CSS_PROP_COLOR_PROFILE
+  //sRGB
+
+  // CSS_PROP_COLOR_RENDERING
+  //auto
+  //optimizeSpeed
+  //optimizeQuality
+
+  //// CSS_PROP_FILL
+  //currentColor
+
+  // CSS_PROP_FILL_OPACITY
+  // CSS_PROP_FILL_RULE
+  //nonzero
+  //evenodd
+
+  // CSS_PROP_IMAGE_RENDERING
+  //auto
+  //optimizeSpeed
+  //optimizeQuality
+
+  // CSS_PROP_MARKER
+  // CSS_PROP_MARKER_END
+  // CSS_PROP_MARKER_MID
+  // CSS_PROP_MARKER_START
+  // CSS_PROP_SHAPE_RENDERING
+  //auto
+  //optimizeSpeed
+  "crispEdges",
+  //geometricPrecision
+
+  // CSS_PROP_STROKE
+  // CSS_PROP_STROKE_DASHARRAY
+  // CSS_PROP_STROKE_DASHOFFSET
+  // CSS_PROP_STROKE_LINECAP
+  "butt",
+  // round
+  // square
+
+  // CSS_PROP_STROKE_LINEJOIN
+  "miter",
+  // round
+  "bevel",
+
+  // CSS_PROP_STROKE_MITERLIMIT
+  // CSS_PROP_STROKE_OPACITY
+  // CSS_PROP_STROKE_WIDTH
+
+  // CSS_PROP_ALIGNMENT_BASELINE
+  //auto
+  // baseline
+  "before-edge",
+  "after-edge",
+  //middle
+  "central",
+  "text-before-edge",
+  "text-after-edge",
+  "ideographic",
+  "hanging",
+  "mathematical",
+
+  // CSS_PROP_BASELINE_SHIFT
+  //baseline
+  // sub
+  // super
+
+  // CSS_PROP_DOMINANT_BASELINE
+  //auto
+  "use-script",
+  "no-change",
+  "reset-size",
+
+  // CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL
+
+  // CSS_PROP_GLYPH_ORIENTATION_VERTICAL
+  // CSS_PROP_TEXT_ANCHOR
+  // start
+  // middle
+  // end
+
+  // CSS_PROP_BUFFERED_RENDERING
+  // auto
+  // static
+  "dynamic",
+
+  // CSS_PROP_VECTOR_EFFECT
+  // none
+  "non-scaling-stroke",
+
+  // CSS_PROP_PAINT_ORDER
+  // normal
+  // fill
+  // stroke
+  // markers
+]
+}
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
index a7d9ba7..bf5c2567 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -89,7 +89,7 @@
       // TODO(timloh): This is a bit wasteful, we parse the registered property
       // to validate but throw away the result.
       if (registration &&
-          !registration->syntax().parse(tokenizer.tokenRange(),
+          !registration->syntax().parse(tokenizer.tokenRange(), context,
                                         isAnimationTainted)) {
         return MutableStylePropertySet::SetResult{didParse, didChange};
       }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index b7f9ff35..86ad465 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -344,12 +344,6 @@
   return nullptr;
 }
 
-static CSSValue* consumeWebkitHighlight(CSSParserTokenRange& range) {
-  if (range.peek().id() == CSSValueNone)
-    return consumeIdent(range);
-  return consumeString(range);
-}
-
 class FontVariantLigaturesParser {
   STACK_ALLOCATED();
 
@@ -613,14 +607,6 @@
                        UnitlessQuirk::Allow);
 }
 
-static CSSValue* consumeTabSize(CSSParserTokenRange& range,
-                                CSSParserMode cssParserMode) {
-  CSSPrimitiveValue* parsedValue = consumeInteger(range, 0);
-  if (parsedValue)
-    return parsedValue;
-  return consumeLength(range, cssParserMode, ValueRangeNonNegative);
-}
-
 static CSSValue* consumeTextSizeAdjust(CSSParserTokenRange& range,
                                        CSSParserMode cssParserMode) {
   if (range.peek().id() == CSSValueAuto)
@@ -713,48 +699,6 @@
   return list;
 }
 
-static CSSValue* consumeTextIndent(CSSParserTokenRange& range,
-                                   CSSParserMode cssParserMode) {
-  // [ <length> | <percentage> ] && hanging? && each-line?
-  // Keywords only allowed when css3Text is enabled.
-  CSSValueList* list = CSSValueList::createSpaceSeparated();
-
-  bool hasLengthOrPercentage = false;
-  bool hasEachLine = false;
-  bool hasHanging = false;
-
-  do {
-    if (!hasLengthOrPercentage) {
-      if (CSSValue* textIndent = consumeLengthOrPercent(
-              range, cssParserMode, ValueRangeAll, UnitlessQuirk::Allow)) {
-        list->append(*textIndent);
-        hasLengthOrPercentage = true;
-        continue;
-      }
-    }
-
-    if (RuntimeEnabledFeatures::css3TextEnabled()) {
-      CSSValueID id = range.peek().id();
-      if (!hasEachLine && id == CSSValueEachLine) {
-        list->append(*consumeIdent(range));
-        hasEachLine = true;
-        continue;
-      }
-      if (!hasHanging && id == CSSValueHanging) {
-        list->append(*consumeIdent(range));
-        hasHanging = true;
-        continue;
-      }
-    }
-    return nullptr;
-  } while (!range.atEnd());
-
-  if (!hasLengthOrPercentage)
-    return nullptr;
-
-  return list;
-}
-
 static bool validWidthOrHeightKeyword(CSSValueID id,
                                       const CSSParserContext* context) {
   if (id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent ||
@@ -815,41 +759,6 @@
   return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, unitless);
 }
 
-static CSSValue* consumeClipComponent(CSSParserTokenRange& range,
-                                      CSSParserMode cssParserMode) {
-  if (range.peek().id() == CSSValueAuto)
-    return consumeIdent(range);
-  return consumeLength(range, cssParserMode, ValueRangeAll,
-                       UnitlessQuirk::Allow);
-}
-
-static CSSValue* consumeClip(CSSParserTokenRange& range,
-                             CSSParserMode cssParserMode) {
-  if (range.peek().id() == CSSValueAuto)
-    return consumeIdent(range);
-
-  if (range.peek().functionId() != CSSValueRect)
-    return nullptr;
-
-  CSSParserTokenRange args = consumeFunction(range);
-  // rect(t, r, b, l) || rect(t r b l)
-  CSSValue* top = consumeClipComponent(args, cssParserMode);
-  if (!top)
-    return nullptr;
-  bool needsComma = consumeCommaIncludingWhitespace(args);
-  CSSValue* right = consumeClipComponent(args, cssParserMode);
-  if (!right || (needsComma && !consumeCommaIncludingWhitespace(args)))
-    return nullptr;
-  CSSValue* bottom = consumeClipComponent(args, cssParserMode);
-  if (!bottom || (needsComma && !consumeCommaIncludingWhitespace(args)))
-    return nullptr;
-  CSSValue* left = consumeClipComponent(args, cssParserMode);
-  if (!left || !args.atEnd())
-    return nullptr;
-  return CSSQuadValue::create(top, right, bottom, left,
-                              CSSQuadValue::SerializeAsRect);
-}
-
 static bool consumePan(CSSParserTokenRange& range,
                        CSSValue*& panX,
                        CSSValue*& panY,
@@ -904,17 +813,6 @@
   return list;
 }
 
-static CSSPrimitiveValue* consumeLineClamp(CSSParserTokenRange& range) {
-  if (range.peek().type() != PercentageToken &&
-      range.peek().type() != NumberToken)
-    return nullptr;
-  CSSPrimitiveValue* clampValue = consumePercent(range, ValueRangeNonNegative);
-  if (clampValue)
-    return clampValue;
-  // When specifying number of lines, don't allow 0 as a valid value.
-  return consumePositiveInteger(range);
-}
-
 static CSSValue* consumeLocale(CSSParserTokenRange& range) {
   if (range.peek().id() == CSSValueAuto)
     return consumeIdent(range);
@@ -1746,22 +1644,6 @@
   return consumeUrl(range);
 }
 
-static CSSValue* consumeStrokeDasharray(CSSParserTokenRange& range) {
-  CSSValueID id = range.peek().id();
-  if (id == CSSValueNone)
-    return consumeIdent(range);
-
-  CSSValueList* dashes = CSSValueList::createCommaSeparated();
-  do {
-    CSSPrimitiveValue* dash =
-        consumeLengthOrPercent(range, SVGAttributeMode, ValueRangeNonNegative);
-    if (!dash || (consumeCommaIncludingWhitespace(range) && range.atEnd()))
-      return nullptr;
-    dashes->append(*dash);
-  } while (!range.atEnd());
-  return dashes;
-}
-
 static CSSValue* consumeBaselineShift(CSSParserTokenRange& range) {
   CSSValueID id = range.peek().id();
   if (id == CSSValueBaseline || id == CSSValueSub || id == CSSValueSuper)
@@ -3140,8 +3022,6 @@
   switch (property) {
     case CSSPropertyQuotes:
       return consumeQuotes(m_range);
-    case CSSPropertyWebkitHighlight:
-      return consumeWebkitHighlight(m_range);
     case CSSPropertyFontVariantCaps:
       return consumeFontVariantCaps(m_range);
     case CSSPropertyFontVariantLigatures:
@@ -3157,8 +3037,6 @@
     case CSSPropertyLetterSpacing:
     case CSSPropertyWordSpacing:
       return consumeSpacing(m_range, m_context->mode());
-    case CSSPropertyTabSize:
-      return consumeTabSize(m_range, m_context->mode());
     case CSSPropertyTextSizeAdjust:
       return consumeTextSizeAdjust(m_range, m_context->mode());
     case CSSPropertyFontSize:
@@ -3176,8 +3054,6 @@
                             property == CSSPropertyCounterIncrement ? 1 : 0);
     case CSSPropertySnapHeight:
       return consumeSnapHeight(m_range, m_context->mode());
-    case CSSPropertyTextIndent:
-      return consumeTextIndent(m_range, m_context->mode());
     case CSSPropertyMaxWidth:
     case CSSPropertyMaxHeight:
       return consumeMaxWidthOrHeight(m_range, m_context, UnitlessQuirk::Allow);
@@ -3223,16 +3099,12 @@
       return consumeLengthOrPercent(m_range, m_context->mode(),
                                     ValueRangeNonNegative,
                                     UnitlessQuirk::Allow);
-    case CSSPropertyClip:
-      return consumeClip(m_range, m_context->mode());
     case CSSPropertyTouchAction:
       return consumeTouchAction(m_range);
     case CSSPropertyScrollSnapDestination:
     case CSSPropertyObjectPosition:
     case CSSPropertyPerspectiveOrigin:
       return consumePosition(m_range, m_context->mode(), UnitlessQuirk::Forbid);
-    case CSSPropertyWebkitLineClamp:
-      return consumeLineClamp(m_range);
     case CSSPropertyWebkitFontSizeDelta:
       return consumeLength(m_range, m_context->mode(), ValueRangeAll,
                            UnitlessQuirk::Allow);
@@ -3264,9 +3136,6 @@
     case CSSPropertyGridRowGap:
       return consumeLengthOrPercent(m_range, m_context->mode(),
                                     ValueRangeNonNegative);
-    case CSSPropertyShapeMargin:
-      return consumeLengthOrPercent(m_range, m_context->mode(),
-                                    ValueRangeNonNegative);
     case CSSPropertyShapeImageThreshold:
       return consumeNumber(m_range, ValueRangeAll);
     case CSSPropertyWebkitBoxOrdinalGroup:
@@ -3372,8 +3241,6 @@
     case CSSPropertyFlexGrow:
     case CSSPropertyFlexShrink:
       return consumeNumber(m_range, ValueRangeNonNegative);
-    case CSSPropertyStrokeDasharray:
-      return consumeStrokeDasharray(m_range);
     case CSSPropertyColumnRuleWidth:
       return consumeColumnRuleWidth(m_range, m_context->mode());
     case CSSPropertyStrokeOpacity:
@@ -3419,8 +3286,6 @@
     case CSSPropertyBorderBottomLeftRadius:
     case CSSPropertyBorderBottomRightRadius:
       return consumeBorderRadiusCorner(m_range, m_context->mode());
-    case CSSPropertyWebkitBoxFlexGroup:
-      return consumeInteger(m_range, 0);
     case CSSPropertyOrder:
       return consumeInteger(m_range);
     case CSSPropertyVerticalAlign:
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp
new file mode 100644
index 0000000..38448d1
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp
@@ -0,0 +1,19 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIShapeMargin.h"
+
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIShapeMargin::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  return CSSPropertyParserHelpers::consumeLengthOrPercent(
+      range, context->mode(), ValueRangeNonNegative);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp
new file mode 100644
index 0000000..ca27b4b1
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIStrokeDasharray.h"
+
+#include "core/css/CSSValueList.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIStrokeDasharray::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  CSSValueID id = range.peek().id();
+  if (id == CSSValueNone)
+    return CSSPropertyParserHelpers::consumeIdent(range);
+
+  CSSValueList* dashes = CSSValueList::createCommaSeparated();
+  do {
+    CSSPrimitiveValue* dash = CSSPropertyParserHelpers::consumeLengthOrPercent(
+        range, SVGAttributeMode, ValueRangeNonNegative);
+    if (!dash ||
+        (CSSPropertyParserHelpers::consumeCommaIncludingWhitespace(range) &&
+         range.atEnd()))
+      return nullptr;
+    dashes->append(*dash);
+  } while (!range.atEnd());
+  return dashes;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp
new file mode 100644
index 0000000..884ede0
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPITabSize.h"
+
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPITabSize::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  CSSPrimitiveValue* parsedValue =
+      CSSPropertyParserHelpers::consumeInteger(range, 0);
+  if (parsedValue)
+    return parsedValue;
+  return CSSPropertyParserHelpers::consumeLength(range, context->mode(),
+                                                 ValueRangeNonNegative);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp
new file mode 100644
index 0000000..2935c41
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp
@@ -0,0 +1,59 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPITextIndent.h"
+
+#include "core/css/CSSValueList.h"
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "platform/RuntimeEnabledFeatures.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPITextIndent::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  // [ <length> | <percentage> ] && hanging? && each-line?
+  // Keywords only allowed when css3Text is enabled.
+  CSSValueList* list = CSSValueList::createSpaceSeparated();
+
+  bool hasLengthOrPercentage = false;
+  bool hasEachLine = false;
+  bool hasHanging = false;
+
+  do {
+    if (!hasLengthOrPercentage) {
+      if (CSSValue* textIndent =
+              CSSPropertyParserHelpers::consumeLengthOrPercent(
+                  range, context->mode(), ValueRangeAll,
+                  CSSPropertyParserHelpers::UnitlessQuirk::Allow)) {
+        list->append(*textIndent);
+        hasLengthOrPercentage = true;
+        continue;
+      }
+    }
+
+    if (RuntimeEnabledFeatures::css3TextEnabled()) {
+      CSSValueID id = range.peek().id();
+      if (!hasEachLine && id == CSSValueEachLine) {
+        list->append(*CSSPropertyParserHelpers::consumeIdent(range));
+        hasEachLine = true;
+        continue;
+      }
+      if (!hasHanging && id == CSSValueHanging) {
+        list->append(*CSSPropertyParserHelpers::consumeIdent(range));
+        hasHanging = true;
+        continue;
+      }
+    }
+    return nullptr;
+  } while (!range.atEnd());
+
+  if (!hasLengthOrPercentage)
+    return nullptr;
+
+  return list;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp
new file mode 100644
index 0000000..458b25f
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIWebkitBoxFlexGroup::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  return CSSPropertyParserHelpers::consumeInteger(range, 0);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp
new file mode 100644
index 0000000..798e4ca1
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIWebkitHighlight.h"
+
+#include "core/css/CSSStringValue.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIWebkitHighlight::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  if (range.peek().id() == CSSValueNone)
+    return CSSPropertyParserHelpers::consumeIdent(range);
+  return CSSPropertyParserHelpers::consumeString(range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp
new file mode 100644
index 0000000..982854e4
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyAPIWebkitLineClamp.h"
+
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+const CSSValue* CSSPropertyAPIWebkitLineClamp::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext* context) {
+  if (range.peek().type() != PercentageToken &&
+      range.peek().type() != NumberToken)
+    return nullptr;
+  CSSPrimitiveValue* clampValue =
+      CSSPropertyParserHelpers::consumePercent(range, ValueRangeNonNegative);
+  if (clampValue)
+    return clampValue;
+  // When specifying number of lines, don't allow 0 as a valid value.
+  return CSSPropertyParserHelpers::consumePositiveInteger(range);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp b/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp
index f894395..aad1e53 100644
--- a/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp
@@ -36,7 +36,7 @@
       m_rootElementStyle(document.documentElement()
                              ? document.documentElement()->computedStyle()
                              : document.computedStyle()),
-      m_elementLinkState(NotInsideLink),
+      m_elementLinkState(EInsideLink::kNotInsideLink),
       m_distributedToInsertionPoint(false) {}
 
 ElementResolveContext::ElementResolveContext(Element& element)
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index d837619..cddb5ad 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -693,11 +693,11 @@
   if (element->isLink()) {
     state.style()->setIsLink(true);
     EInsideLink linkState = state.elementLinkState();
-    if (linkState != NotInsideLink) {
+    if (linkState != EInsideLink::kNotInsideLink) {
       bool forceVisited = InspectorInstrumentation::forcePseudoState(
           element, CSSSelector::PseudoVisited);
       if (forceVisited)
-        linkState = InsideVisitedLink;
+        linkState = EInsideLink::kInsideVisitedLink;
     }
     state.style()->setInsideLink(linkState);
   }
@@ -1114,7 +1114,7 @@
   if (state.animationUpdate().isEmpty())
     return false;
 
-  if (state.style()->insideLink() != NotInsideLink) {
+  if (state.style()->insideLink() != EInsideLink::kNotInsideLink) {
     DCHECK(state.applyPropertyToRegularStyle());
     state.setApplyPropertyToVisitedLinkStyle(true);
   }
@@ -1541,7 +1541,7 @@
   if (!shouldUpdateNeedsApplyPass && !needsApplyPass.get(priority, isImportant))
     return;
 
-  if (state.style()->insideLink() != NotInsideLink) {
+  if (state.style()->insideLink() != EInsideLink::kNotInsideLink) {
     for (const auto& matchedProperties : range) {
       unsigned linkMatchType = matchedProperties.m_types.linkMatchType;
       // FIXME: It would be nicer to pass these as arguments but that requires
diff --git a/third_party/WebKit/Source/core/dom/DOMTypedArray.h b/third_party/WebKit/Source/core/dom/DOMTypedArray.h
index 292003a..9dff983 100644
--- a/third_party/WebKit/Source/core/dom/DOMTypedArray.h
+++ b/third_party/WebKit/Source/core/dom/DOMTypedArray.h
@@ -54,7 +54,8 @@
   }
 
   static ThisType* createOrNull(unsigned length) {
-    RefPtr<WTF::ArrayBuffer> buffer = WTF::ArrayBuffer::createOrNull(length, 1);
+    RefPtr<WTF::ArrayBuffer> buffer =
+        WTF::ArrayBuffer::createOrNull(length, sizeof(ValueType));
     return buffer ? create(buffer.release(), 0, length) : nullptr;
   }
 
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index c6fc0601..8dd0107 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -1369,13 +1369,13 @@
 // We use HashMap::set over HashMap::add here as we want to
 // replace the ComputedStyle but not the Node if the Node is
 // already present.
-void Document::addStyleReattachData(Node& node,
+void Document::addStyleReattachData(const Node& node,
                                     StyleReattachData& styleReattachData) {
   DCHECK(node.isElementNode() || node.isTextNode());
   m_styleReattachDataMap.set(&node, styleReattachData);
 }
 
-StyleReattachData Document::getStyleReattachData(Node& node) {
+StyleReattachData Document::getStyleReattachData(const Node& node) const {
   return m_styleReattachDataMap.get(&node);
 }
 
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 19e980fe..9700908d 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -347,8 +347,8 @@
   // just for the web IDL implementation.
   Element* scrollingElementNoLayout();
 
-  void addStyleReattachData(Node&, StyleReattachData&);
-  StyleReattachData getStyleReattachData(Node&);
+  void addStyleReattachData(const Node&, StyleReattachData&);
+  StyleReattachData getStyleReattachData(const Node&) const;
 
   String readyState() const;
 
@@ -1450,7 +1450,7 @@
   // This HashMap is used to stash information (ComputedStyle, nextTextSibling)
   // generated in the Style Resolution phase that is required in the
   // Layout Tree construction phase.
-  HeapHashMap<Member<Node>, StyleReattachData> m_styleReattachDataMap;
+  HeapHashMap<Member<const Node>, StyleReattachData> m_styleReattachDataMap;
 
   bool m_wellFormed;
 
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl
index 9c10395..826a96d 100644
--- a/third_party/WebKit/Source/core/dom/Document.idl
+++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -78,7 +78,7 @@
     [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
 
     // NonDocumentRootScroller (https://github.com/bokand/NonDocumentRootScroller)
-    [RaisesException=Setter, RuntimeEnabled=SetRootScroller, Measure] attribute Element? rootScroller;
+    [RaisesException=Setter, OriginTrialEnabled=RootScroller, Measure] attribute Element? rootScroller;
 
     // FIXME: xmlEncoding/xmlVersion/xmlStandalone have been removed from the spec.
     [MeasureAs=DocumentXMLEncoding] readonly attribute DOMString? xmlEncoding;
diff --git a/third_party/WebKit/Source/core/dom/DocumentTest.cpp b/third_party/WebKit/Source/core/dom/DocumentTest.cpp
index 13a714a..a13fa7f 100644
--- a/third_party/WebKit/Source/core/dom/DocumentTest.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentTest.cpp
@@ -450,8 +450,8 @@
 TEST_F(DocumentTest, SynchronousMutationNotifier) {
   auto& observer = *new TestSynchronousMutationObserver(document());
 
-  EXPECT_EQ(observer.lifecycleContext(), document());
-  EXPECT_EQ(observer.countContextDestroyedCalled(), 0);
+  EXPECT_EQ(document(), observer.lifecycleContext());
+  EXPECT_EQ(0, observer.countContextDestroyedCalled());
 
   Element* divNode = document().createElement("div");
   document().body()->appendChild(divNode);
@@ -467,18 +467,18 @@
   EXPECT_TRUE(observer.removedNodes().isEmpty());
 
   textNode->remove();
-  ASSERT_EQ(observer.removedNodes().size(), 1u);
+  ASSERT_EQ(1u, observer.removedNodes().size());
   EXPECT_EQ(textNode, observer.removedNodes()[0]);
 
   divNode->removeChildren();
-  EXPECT_EQ(observer.removedNodes().size(), 1u)
+  EXPECT_EQ(1u, observer.removedNodes().size())
       << "ContainerNode::removeChildren() doesn't call nodeWillBeRemoved()";
-  ASSERT_EQ(observer.removedChildrenNodes().size(), 1u);
+  ASSERT_EQ(1u, observer.removedChildrenNodes().size());
   EXPECT_EQ(divNode, observer.removedChildrenNodes()[0]);
 
   document().shutdown();
-  EXPECT_EQ(observer.lifecycleContext(), nullptr);
-  EXPECT_EQ(observer.countContextDestroyedCalled(), 1);
+  EXPECT_EQ(nullptr, observer.lifecycleContext());
+  EXPECT_EQ(1, observer.countContextDestroyedCalled());
 }
 
 TEST_F(DocumentTest, SynchronousMutationNotifieAppendChild) {
@@ -505,12 +505,12 @@
   Text* mergeSampleB = document().createTextNode("b123456789");
   document().body()->appendChild(mergeSampleB);
 
-  EXPECT_EQ(observer.mergeTextNodesRecords().size(), 0u);
+  EXPECT_EQ(0u, observer.mergeTextNodesRecords().size());
   document().body()->normalize();
 
-  ASSERT_EQ(observer.mergeTextNodesRecords().size(), 1u);
-  EXPECT_EQ(observer.mergeTextNodesRecords()[0]->m_node, mergeSampleB);
-  EXPECT_EQ(observer.mergeTextNodesRecords()[0]->m_offset, 10u);
+  ASSERT_EQ(1u, observer.mergeTextNodesRecords().size());
+  EXPECT_EQ(mergeSampleB, observer.mergeTextNodesRecords()[0]->m_node);
+  EXPECT_EQ(10u, observer.mergeTextNodesRecords()[0]->m_offset);
 }
 
 TEST_F(DocumentTest, SynchronousMutationNotifieRemoveChild) {
@@ -540,8 +540,8 @@
   document().body()->appendChild(splitSample);
 
   splitSample->splitText(4, ASSERT_NO_EXCEPTION);
-  ASSERT_EQ(observer.splitTextNodes().size(), 1u);
-  EXPECT_EQ(observer.splitTextNodes()[0], splitSample);
+  ASSERT_EQ(1u, observer.splitTextNodes().size());
+  EXPECT_EQ(splitSample, observer.splitTextNodes()[0]);
 }
 
 TEST_F(DocumentTest, SynchronousMutationNotifierUpdateCharacterData) {
@@ -559,35 +559,35 @@
   Text* replaceSample = document().createTextNode("c123456789");
   document().body()->appendChild(replaceSample);
 
-  EXPECT_EQ(observer.updatedCharacterDataRecords().size(), 0u);
+  EXPECT_EQ(0u, observer.updatedCharacterDataRecords().size());
 
   appendSample->appendData("abc");
-  ASSERT_EQ(observer.updatedCharacterDataRecords().size(), 1u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[0]->m_node, appendSample);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[0]->m_offset, 10u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[0]->m_oldLength, 0u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[0]->m_newLength, 3u);
+  ASSERT_EQ(1u, observer.updatedCharacterDataRecords().size());
+  EXPECT_EQ(appendSample, observer.updatedCharacterDataRecords()[0]->m_node);
+  EXPECT_EQ(10u, observer.updatedCharacterDataRecords()[0]->m_offset);
+  EXPECT_EQ(0u, observer.updatedCharacterDataRecords()[0]->m_oldLength);
+  EXPECT_EQ(3u, observer.updatedCharacterDataRecords()[0]->m_newLength);
 
   deleteSample->deleteData(3, 4, ASSERT_NO_EXCEPTION);
-  ASSERT_EQ(observer.updatedCharacterDataRecords().size(), 2u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[1]->m_node, deleteSample);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[1]->m_offset, 3u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[1]->m_oldLength, 4u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[1]->m_newLength, 0u);
+  ASSERT_EQ(2u, observer.updatedCharacterDataRecords().size());
+  EXPECT_EQ(deleteSample, observer.updatedCharacterDataRecords()[1]->m_node);
+  EXPECT_EQ(3u, observer.updatedCharacterDataRecords()[1]->m_offset);
+  EXPECT_EQ(4u, observer.updatedCharacterDataRecords()[1]->m_oldLength);
+  EXPECT_EQ(0u, observer.updatedCharacterDataRecords()[1]->m_newLength);
 
   insertSample->insertData(3, "def", ASSERT_NO_EXCEPTION);
-  ASSERT_EQ(observer.updatedCharacterDataRecords().size(), 3u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[2]->m_node, insertSample);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[2]->m_offset, 3u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[2]->m_oldLength, 0u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[2]->m_newLength, 3u);
+  ASSERT_EQ(3u, observer.updatedCharacterDataRecords().size());
+  EXPECT_EQ(insertSample, observer.updatedCharacterDataRecords()[2]->m_node);
+  EXPECT_EQ(3u, observer.updatedCharacterDataRecords()[2]->m_offset);
+  EXPECT_EQ(0u, observer.updatedCharacterDataRecords()[2]->m_oldLength);
+  EXPECT_EQ(3u, observer.updatedCharacterDataRecords()[2]->m_newLength);
 
   replaceSample->replaceData(6, 4, "ghi", ASSERT_NO_EXCEPTION);
-  ASSERT_EQ(observer.updatedCharacterDataRecords().size(), 4u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[3]->m_node, replaceSample);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[3]->m_offset, 6u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[3]->m_oldLength, 4u);
-  EXPECT_EQ(observer.updatedCharacterDataRecords()[3]->m_newLength, 3u);
+  ASSERT_EQ(4u, observer.updatedCharacterDataRecords().size());
+  EXPECT_EQ(replaceSample, observer.updatedCharacterDataRecords()[3]->m_node);
+  EXPECT_EQ(6u, observer.updatedCharacterDataRecords()[3]->m_offset);
+  EXPECT_EQ(4u, observer.updatedCharacterDataRecords()[3]->m_oldLength);
+  EXPECT_EQ(3u, observer.updatedCharacterDataRecords()[3]->m_newLength);
 }
 
 // This tests that meta-theme-color can be found correctly
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 600af2f1..3eb14f3b 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -1826,6 +1826,14 @@
   return document().contextDocument();
 }
 
+void Node::willMoveToNewDocument(Document& oldDocument, Document& newDocument) {
+  if (!oldDocument.frameHost() ||
+      oldDocument.frameHost() == newDocument.frameHost())
+    return;
+
+  oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(*this);
+}
+
 void Node::didMoveToNewDocument(Document& oldDocument) {
   TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(oldDocument);
 
@@ -1838,14 +1846,10 @@
   }
 
   oldDocument.markers().removeMarkers(this);
-  if (oldDocument.frameHost() && !document().frameHost())
-    oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(
-        *this);
-  else if (document().frameHost() && !oldDocument.frameHost())
+  if (document().frameHost() &&
+      document().frameHost() != oldDocument.frameHost()) {
     document().frameHost()->eventHandlerRegistry().didMoveIntoFrameHost(*this);
-  else if (oldDocument.frameHost() != document().frameHost())
-    EventHandlerRegistry::didMoveBetweenFrameHosts(
-        *this, oldDocument.frameHost(), document().frameHost());
+  }
 
   if (const HeapVector<TraceWrapperMember<MutationObserverRegistration>>*
           registry = mutationObserverRegistry()) {
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index b3f64137..c02e8527 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -867,6 +867,8 @@
 
   Node(TreeScope*, ConstructionType);
 
+  virtual void willMoveToNewDocument(Document& oldDocument,
+                                     Document& newDocument);
   virtual void didMoveToNewDocument(Document& oldDocument);
 
   void addedEventListener(const AtomicString& eventType,
diff --git a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
index 8600f77..bea9098 100644
--- a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
@@ -128,6 +128,8 @@
     Document& oldDocument,
     Document& newDocument) const {
   DCHECK_NE(oldDocument, newDocument);
+  // Note: at the start of this function, node.document() may already have
+  // changed to match |newDocument|, which is why |oldDocument| is passed in.
 
   if (node.hasRareData()) {
     NodeRareData* rareData = node.rareData();
@@ -135,6 +137,7 @@
       rareData->nodeLists()->adoptDocument(oldDocument, newDocument);
   }
 
+  node.willMoveToNewDocument(oldDocument, newDocument);
   oldDocument.moveNodeIteratorsToNewDocument(node, newDocument);
 
   if (node.getCustomElementState() == CustomElementState::Custom) {
diff --git a/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp b/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
index 17d0f56..dd0fec9 100644
--- a/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
+++ b/third_party/WebKit/Source/core/dom/VisitedLinkState.cpp
@@ -119,22 +119,22 @@
   const AtomicString& attribute = linkAttribute(element);
 
   if (attribute.isNull())
-    return NotInsideLink;  // This can happen for <img usemap>
+    return EInsideLink::kNotInsideLink;  // This can happen for <img usemap>
 
   // An empty attribute refers to the document itself which is always
   // visited. It is useful to check this explicitly so that visited
   // links can be tested in platform independent manner, without
   // explicit support in the test harness.
   if (attribute.isEmpty())
-    return InsideVisitedLink;
+    return EInsideLink::kInsideVisitedLink;
 
   if (LinkHash hash = linkHashForElement(element, attribute)) {
     m_linksCheckedForVisitedState.add(hash);
     if (Platform::current()->isLinkVisited(hash))
-      return InsideVisitedLink;
+      return EInsideLink::kInsideVisitedLink;
   }
 
-  return InsideUnvisitedLink;
+  return EInsideLink::kInsideUnvisitedLink;
 }
 
 DEFINE_TRACE(VisitedLinkState) {
diff --git a/third_party/WebKit/Source/core/dom/VisitedLinkState.h b/third_party/WebKit/Source/core/dom/VisitedLinkState.h
index ebe3a6a..284b979 100644
--- a/third_party/WebKit/Source/core/dom/VisitedLinkState.h
+++ b/third_party/WebKit/Source/core/dom/VisitedLinkState.h
@@ -52,7 +52,7 @@
   EInsideLink determineLinkState(const Element& element) {
     if (element.isLink())
       return determineLinkStateSlowCase(element);
-    return NotInsideLink;
+    return EInsideLink::kNotInsideLink;
   }
 
   DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/core/editing/CaretBase.cpp b/third_party/WebKit/Source/core/editing/CaretBase.cpp
index 8b150d8..16e0f02e 100644
--- a/third_party/WebKit/Source/core/editing/CaretBase.cpp
+++ b/third_party/WebKit/Source/core/editing/CaretBase.cpp
@@ -113,10 +113,6 @@
                                     caretLocalRect);
 }
 
-LayoutRect CaretBase::computeCaretRect(const VisiblePosition& caretPosition) {
-  return computeCaretRect(caretPosition.toPositionWithAffinity());
-}
-
 IntRect CaretBase::absoluteBoundsForLocalRect(Node* node,
                                               const LayoutRect& rect) {
   LayoutBlock* caretPainter = caretLayoutObject(node);
@@ -168,11 +164,10 @@
 
 void CaretBase::paintCaret(Node* node,
                            GraphicsContext& context,
-                           const DisplayItemClient& client,
                            const LayoutRect& caretLocalRect,
                            const LayoutPoint& paintOffset,
                            DisplayItem::Type displayItemType) {
-  if (DrawingRecorder::useCachedDrawingIfPossible(context, client,
+  if (DrawingRecorder::useCachedDrawingIfPossible(context, *this,
                                                   displayItemType))
     return;
 
@@ -184,7 +179,7 @@
   const Color caretColor =
       node->layoutObject()->resolveColor(CSSPropertyCaretColor);
   IntRect paintRect = pixelSnappedIntRect(drawingRect);
-  DrawingRecorder drawingRecorder(context, client, DisplayItem::kCaret,
+  DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret,
                                   paintRect);
   context.fillRect(paintRect, caretColor);
 }
diff --git a/third_party/WebKit/Source/core/editing/CaretBase.h b/third_party/WebKit/Source/core/editing/CaretBase.h
index c29b3f5..993371d 100644
--- a/third_party/WebKit/Source/core/editing/CaretBase.h
+++ b/third_party/WebKit/Source/core/editing/CaretBase.h
@@ -27,7 +27,7 @@
 #ifndef CaretBase_h
 #define CaretBase_h
 
-#include "core/editing/VisiblePosition.h"
+#include "core/editing/PositionWithAffinity.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/geometry/LayoutRect.h"
 #include "platform/graphics/paint/DisplayItem.h"
@@ -50,26 +50,17 @@
   // PositionWithAffinity version if possible.
   // A position in HTMLTextFromControlElement is a typical example.
   static LayoutRect computeCaretRect(const PositionWithAffinity& caretPosition);
-
-  // TODO(yosin): We should move |computeCaretRect()| with |VisiblePosition| to
-  // "FrameCaret.cpp" as static file local function.
-  static LayoutRect computeCaretRect(const VisiblePosition& caretPosition);
-
-  // TODO(yosin): We should move |absoluteBoundsForLocalRect()| with
-  // |VisiblePosition| to "FrameCaret.cpp" as static file local function.
   static IntRect absoluteBoundsForLocalRect(Node*, const LayoutRect&);
 
   // TODO(yosin): We should move |shouldRepaintCaret()| to "FrameCaret.cpp" as
   // static file local function.
   static bool shouldRepaintCaret(Node&);
-  // TODO(yosin): We should make |paintCaret()| to non-static member and get rid
-  // |DisplayItemClient| parameter.
-  static void paintCaret(Node*,
-                         GraphicsContext&,
-                         const DisplayItemClient&,
-                         const LayoutRect& caretLocalRect,
-                         const LayoutPoint&,
-                         DisplayItem::Type);
+
+  void paintCaret(Node*,
+                  GraphicsContext&,
+                  const LayoutRect& caretLocalRect,
+                  const LayoutPoint&,
+                  DisplayItem::Type);
 
   static LayoutBlock* caretLayoutObject(Node*);
   void invalidateLocalCaretRect(Node*, const LayoutRect&);
diff --git a/third_party/WebKit/Source/core/editing/DragCaretController.cpp b/third_party/WebKit/Source/core/editing/DragCaretController.cpp
index 6aff51fb..0ea817c 100644
--- a/third_party/WebKit/Source/core/editing/DragCaretController.cpp
+++ b/third_party/WebKit/Source/core/editing/DragCaretController.cpp
@@ -111,9 +111,8 @@
                                          GraphicsContext& context,
                                          const LayoutPoint& paintOffset) const {
   if (m_position.anchorNode()->document().frame() == frame) {
-    CaretBase::paintCaret(m_position.anchorNode(), context, *m_caretBase,
-                          m_caretLocalRect, paintOffset,
-                          DisplayItem::kDragCaret);
+    m_caretBase->paintCaret(m_position.anchorNode(), context, m_caretLocalRect,
+                            paintOffset, DisplayItem::kDragCaret);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index ca05390e..0945f8a 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -352,7 +352,7 @@
     if (isTypingAction) {
       DCHECK(frame().document());
       TypingCommand::deleteKeyPressed(
-          *frame().document(), source,
+          *frame().document(),
           canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
       revealSelectionAfterEditingOperation();
     } else {
@@ -374,13 +374,13 @@
       case DeleteDirection::Forward:
         DCHECK(frame().document());
         TypingCommand::forwardDeleteKeyPressed(
-            *frame().document(), source, &editingState, options, granularity);
+            *frame().document(), &editingState, options, granularity);
         if (editingState.isAborted())
           return false;
         break;
       case DeleteDirection::Backward:
         DCHECK(frame().document());
-        TypingCommand::deleteKeyPressed(*frame().document(), source, options,
+        TypingCommand::deleteKeyPressed(*frame().document(), options,
                                         granularity);
         break;
     }
@@ -396,8 +396,9 @@
   return true;
 }
 
+// TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|.
 void Editor::deleteSelectionWithSmartDelete(
-    EditCommandSource source,
+    EditCommandSource,
     DeleteMode deleteMode,
     InputEvent::InputType inputType,
     const Position& referenceMovePosition) {
@@ -412,7 +413,7 @@
       *frame().document(), deleteMode == DeleteMode::Smart,
       kMergeBlocksAfterDelete, kExpandForSpecialElements, kSanitizeMarkup,
       inputType, referenceMovePosition)
-      ->apply(source);
+      ->apply();
 }
 
 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) {
@@ -590,7 +591,8 @@
   return smartInsertDeleteEnabled() && pasteboard->canSmartReplace();
 }
 
-void Editor::replaceSelectionWithFragment(EditCommandSource source,
+// TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|.
+void Editor::replaceSelectionWithFragment(EditCommandSource,
                                           DocumentFragment* fragment,
                                           bool selectReplacement,
                                           bool smartReplace,
@@ -613,7 +615,7 @@
   DCHECK(frame().document());
   ReplaceSelectionCommand::create(*frame().document(), fragment, options,
                                   inputType)
-      ->apply(source);
+      ->apply();
   revealSelectionAfterEditingOperation();
 }
 
@@ -641,7 +643,7 @@
   DCHECK(frame().document());
   ReplaceSelectionCommand::create(*frame().document(), fragment, options,
                                   InputEvent::InputType::InsertFromDrop)
-      ->apply(EditCommandSource::kMenuOrKeyBinding);
+      ->apply();
 }
 
 bool Editor::deleteSelectionAfterDraggingWithEvents(
@@ -728,9 +730,10 @@
   client().respondToChangedContents();
 }
 
-void Editor::removeFormattingAndStyle(EditCommandSource source) {
+// TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|.
+void Editor::removeFormattingAndStyle(EditCommandSource) {
   DCHECK(frame().document());
-  RemoveFormatCommand::create(*frame().document())->apply(source);
+  RemoveFormatCommand::create(*frame().document())->apply();
 }
 
 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) {
@@ -769,13 +772,14 @@
         DCHECK(frame().document());
         ApplyStyleCommand::create(*frame().document(),
                                   EditingStyle::create(style), inputType)
-            ->apply(source);
+            ->apply();
       }
       break;
   }
 }
 
-void Editor::applyParagraphStyle(EditCommandSource source,
+// TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|.
+void Editor::applyParagraphStyle(EditCommandSource,
                                  StylePropertySet* style,
                                  InputEvent::InputType inputType) {
   if (frame().selection().isNone() || !style)
@@ -783,7 +787,7 @@
   DCHECK(frame().document());
   ApplyStyleCommand::create(*frame().document(), EditingStyle::create(style),
                             inputType, ApplyStyleCommand::ForceBlockProperties)
-      ->apply(source);
+      ->apply();
 }
 
 void Editor::applyStyleToSelection(EditCommandSource source,
@@ -1011,7 +1015,7 @@
 
   // Insert the text
   TypingCommand::insertText(
-      *selection.start().document(), source, text, selection,
+      *selection.start().document(), text, selection,
       selectInsertedText ? TypingCommand::SelectInsertedText : 0,
       triggeringEvent && triggeringEvent->isComposition()
           ? TypingCommand::TextCompositionConfirm
@@ -1037,11 +1041,7 @@
   VisiblePosition caret = frame().selection().selection().visibleStart();
   bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
   DCHECK(frame().document());
-  // we can pass |EditCommandSource::kMenuOrKeyBinding| because
-  // |insertLineBreak()| is only used by |Editor::handleTextEvent()| and
-  // |Editor::insertParagraphSeparator()|.
-  if (!TypingCommand::insertLineBreak(*frame().document(),
-                                      EditCommandSource::kMenuOrKeyBinding))
+  if (!TypingCommand::insertLineBreak(*frame().document()))
     return false;
   revealSelectionAfterEditingOperation(
       alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded
@@ -1061,11 +1061,7 @@
   bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
   DCHECK(frame().document());
   EditingState editingState;
-  // We can |EditCommandSource::kMenuOrKeyBinding| because
-  // |Editor::insertParagraphSeparator()| is only used by
-  // |Editor::handleTextEvent()|.
-  if (!TypingCommand::insertParagraphSeparator(
-          *frame().document(), EditCommandSource::kMenuOrKeyBinding))
+  if (!TypingCommand::insertParagraphSeparator(*frame().document()))
     return false;
   revealSelectionAfterEditingOperation(
       alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded
@@ -1450,7 +1446,8 @@
                  startCaretRect.height());
 }
 
-void Editor::computeAndSetTypingStyle(EditCommandSource source,
+// TODO(chongz): Pass |EditCommandSource| to |CompositeEditCommand|.
+void Editor::computeAndSetTypingStyle(EditCommandSource,
                                       StylePropertySet* style,
                                       InputEvent::InputType inputType) {
   if (!style || style->isEmpty()) {
@@ -1476,7 +1473,7 @@
   if (!blockStyle->isEmpty()) {
     DCHECK(frame().document());
     ApplyStyleCommand::create(*frame().document(), blockStyle, inputType)
-        ->apply(source);
+        ->apply();
   }
 
   // Set the remaining style as the typing style.
diff --git a/third_party/WebKit/Source/core/editing/FrameCaret.cpp b/third_party/WebKit/Source/core/editing/FrameCaret.cpp
index a6329c5..5e5eee8 100644
--- a/third_party/WebKit/Source/core/editing/FrameCaret.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameCaret.cpp
@@ -234,7 +234,8 @@
   }
   return CaretBase::absoluteBoundsForLocalRect(
       caretNode,
-      CaretBase::computeCaretRect(createVisiblePosition(caretPosition())));
+      CaretBase::computeCaretRect(
+          createVisiblePosition(caretPosition()).toPositionWithAffinity()));
 }
 
 void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) {
@@ -255,8 +256,8 @@
 
   const LayoutRect caretLocalRect =
       CaretBase::computeCaretRect(caretPosition());
-  CaretBase::paintCaret(caretPosition().anchorNode(), context, *m_caretBase,
-                        caretLocalRect, paintOffset, DisplayItem::kCaret);
+  m_caretBase->paintCaret(caretPosition().anchorNode(), context, caretLocalRect,
+                          paintOffset, DisplayItem::kCaret);
 }
 
 void FrameCaret::dataWillChange(const CharacterData& node) {
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index 3a1071d..1b11d96a 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -144,9 +144,8 @@
   switch (compositionType) {
     case TypingCommand::TextCompositionType::TextCompositionUpdate:
     case TypingCommand::TextCompositionType::TextCompositionConfirm:
-      TypingCommand::insertText(
-          *frame.document(), EditCommandSource::kMenuOrKeyBinding, text,
-          options, compositionType, isIncrementalInsertion);
+      TypingCommand::insertText(*frame.document(), text, options,
+                                compositionType, isIncrementalInsertion);
       break;
     case TypingCommand::TextCompositionType::TextCompositionCancel:
       // TODO(chongz): Use TypingCommand::insertText after TextEvent was
@@ -306,10 +305,8 @@
   // If text is empty, then delete the old composition here. If text is
   // non-empty, InsertTextCommand::input will delete the old composition with
   // an optimized replace operation.
-  if (text.isEmpty()) {
-    TypingCommand::deleteSelection(document(),
-                                   EditCommandSource::kMenuOrKeyBinding, 0);
-  }
+  if (text.isEmpty())
+    TypingCommand::deleteSelection(document(), 0);
 
   clear();
 
@@ -538,7 +535,6 @@
       // composition, however some IME (e.g. Japanese IBus-Anthy) did this, so
       // we simply delete selection without sending extra events.
       TypingCommand::deleteSelection(document(),
-                                     EditCommandSource::kMenuOrKeyBinding,
                                      TypingCommand::PreventSpellChecking);
     }
 
@@ -797,8 +793,7 @@
   dispatchBeforeInputEditorCommand(
       document().focusedElement(), InputEvent::InputType::DeleteContentBackward,
       new RangeVector(1, m_frame->selection().firstRange()));
-  TypingCommand::deleteSelection(document(),
-                                 EditCommandSource::kMenuOrKeyBinding);
+  TypingCommand::deleteSelection(document());
 }
 
 // TODO(yabinh): We should reduce the number of selectionchange events.
@@ -833,8 +828,7 @@
     const int adjustedStart = start - static_cast<int>(diff);
     if (!setSelectionOffsets(PlainTextRange(adjustedStart, selectionStart)))
       return;
-    TypingCommand::deleteSelection(document(),
-                                   EditCommandSource::kMenuOrKeyBinding);
+    TypingCommand::deleteSelection(document());
 
     selectionEnd = selectionEnd - (selectionStart - adjustedStart);
     selectionStart = adjustedStart;
@@ -859,8 +853,7 @@
     const int adjustedEnd = end + static_cast<int>(diff);
     if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
       return;
-    TypingCommand::deleteSelection(document(),
-                                   EditCommandSource::kMenuOrKeyBinding);
+    TypingCommand::deleteSelection(document());
   }
 
   setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommandTest.cpp
index 40129f6..cd06bf1 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommandTest.cpp
@@ -46,7 +46,7 @@
 
   FormatBlockCommand* command =
       FormatBlockCommand::create(document(), HTMLNames::footerTag);
-  command->apply(EditCommandSource::kMenuOrKeyBinding);
+  command->apply();
 
   EXPECT_EQ(
       "<body contenteditable=\"false\">\n"
@@ -70,7 +70,7 @@
 
   IndentOutdentCommand* command =
       IndentOutdentCommand::create(document(), IndentOutdentCommand::Indent);
-  command->apply(EditCommandSource::kMenuOrKeyBinding);
+  command->apply();
 
   EXPECT_EQ(
       "<head><style>li:first-child { visibility:visible; }</style></head>"
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp
index 5357b8e3..24af3cb0 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp
@@ -44,7 +44,7 @@
   ApplyStyleCommand::create(document(), EditingStyle::create(style),
                             InputEvent::InputType::FormatJustifyCenter,
                             ApplyStyleCommand::ForceBlockProperties)
-      ->apply(EditCommandSource::kDOM);
+      ->apply();
   // Shouldn't crash.
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 57d9249..1774c34 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -187,7 +187,7 @@
   DCHECK(isTopLevelCommand() || !m_composition);
 }
 
-bool CompositeEditCommand::apply(EditCommandSource source) {
+bool CompositeEditCommand::apply() {
   DCHECK(!isCommandGroupWrapper());
   if (!endingSelection().isContentRichlyEditable()) {
     switch (inputType()) {
@@ -223,9 +223,6 @@
   // the creation of VisiblePositions).
   document().updateStyleAndLayoutIgnorePendingStylesheets();
 
-  if (!willApplyEditing(source))
-    return false;
-
   LocalFrame* frame = document().frame();
   DCHECK(frame);
   EditingState editingState;
@@ -252,11 +249,6 @@
   return command->m_composition.get();
 }
 
-bool CompositeEditCommand::willApplyEditing(EditCommandSource) {
-  // TODO(chongz): Move all the 'beforeinput' dispatching logic here.
-  return true;
-}
-
 bool CompositeEditCommand::preservesTypingStyle() const {
   return false;
 }
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
index 54ca077..24d67a7 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
@@ -96,7 +96,7 @@
   ~CompositeEditCommand() override;
 
   // Returns |false| if the command failed.  e.g. It's aborted.
-  bool apply(EditCommandSource);
+  bool apply();
   bool isFirstCommand(EditCommand* command) {
     return !m_commands.isEmpty() && m_commands.front() == command;
   }
@@ -118,15 +118,6 @@
  protected:
   explicit CompositeEditCommand(Document&);
 
-  // TODO(chongz): Implement "beforeinput" as described below:
-  // Fires "beforeinput" and will return |false| to cancel applying editing if
-  //   * "beforeinput" was canceled, or
-  //   * |frame| was destroyed by event handlers.
-  // |willApplyEditing()| should be called from
-  //   * |CompositeEditCommand::apply()|, and
-  //   * |TypingCommand::willAddTypingToOpenCommand()|.
-  bool willApplyEditing(EditCommandSource);
-
   //
   // sugary-sweet convenience functions to help create and apply edit commands
   // in composite commands
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp
index b317923..d9851af 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommandTest.cpp
@@ -51,8 +51,7 @@
       kNoExpandForSpecialElements, kSanitizeMarkup,
       InputEvent::InputType::DeleteByCut);
 
-  EXPECT_TRUE(command->apply(EditCommandSource::kMenuOrKeyBinding))
-      << "the delete command should have succeeded";
+  EXPECT_TRUE(command->apply()) << "the delete command should have succeeded";
   EXPECT_EQ("<div contenteditable=\"true\"><br></div>",
             document().body()->innerHTML());
   EXPECT_TRUE(frame->selection().isCaret());
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index 22ef3baf..d6da2ae 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -363,14 +363,14 @@
 }
 
 static bool executeInsertFragment(LocalFrame& frame,
-                                  EditCommandSource source,
+                                  EditCommandSource,
                                   DocumentFragment* fragment) {
   DCHECK(frame.document());
   return ReplaceSelectionCommand::create(
              *frame.document(), fragment,
              ReplaceSelectionCommand::PreventNesting,
              InputEvent::InputType::None)
-      ->apply(source);
+      ->apply();
 }
 
 static bool executeInsertElement(LocalFrame& frame,
@@ -541,12 +541,12 @@
 
 static bool executeCreateLink(LocalFrame& frame,
                               Event*,
-                              EditCommandSource source,
+                              EditCommandSource,
                               const String& value) {
   if (value.isEmpty())
     return false;
   DCHECK(frame.document());
-  return CreateLinkCommand::create(*frame.document(), value)->apply(source);
+  return CreateLinkCommand::create(*frame.document(), value)->apply();
 }
 
 static bool executeCut(LocalFrame& frame,
@@ -593,10 +593,9 @@
       // time, siding with IE, not Firefox).
       DCHECK(frame.document());
       TypingCommand::deleteKeyPressed(
-          *frame.document(), source,
-          frame.selection().granularity() == WordGranularity
-              ? TypingCommand::SmartDelete
-              : 0);
+          *frame.document(), frame.selection().granularity() == WordGranularity
+                                 ? TypingCommand::SmartDelete
+                                 : 0);
       return true;
   }
   NOTREACHED();
@@ -756,7 +755,7 @@
 
 static bool executeFormatBlock(LocalFrame& frame,
                                Event*,
-                               EditCommandSource source,
+                               EditCommandSource,
                                const String& value) {
   String tagName = value.lower();
   if (tagName[0] == '<' && tagName[tagName.length() - 1] == '>')
@@ -771,7 +770,7 @@
   DCHECK(frame.document());
   FormatBlockCommand* command =
       FormatBlockCommand::create(*frame.document(), qualifiedTagName);
-  command->apply(source);
+  command->apply();
   return command->didApply();
 }
 
@@ -791,8 +790,7 @@
       // only needed for backward compatibility with ourselves, and for
       // consistency with Delete.
       DCHECK(frame.document());
-      TypingCommand::forwardDeleteKeyPressed(*frame.document(), source,
-                                             &editingState);
+      TypingCommand::forwardDeleteKeyPressed(*frame.document(), &editingState);
       if (editingState.isAborted())
         return false;
       return true;
@@ -811,12 +809,12 @@
 
 static bool executeIndent(LocalFrame& frame,
                           Event*,
-                          EditCommandSource source,
+                          EditCommandSource,
                           const String&) {
   DCHECK(frame.document());
   return IndentOutdentCommand::create(*frame.document(),
                                       IndentOutdentCommand::Indent)
-      ->apply(source);
+      ->apply();
 }
 
 static bool executeInsertBacktab(LocalFrame& frame,
@@ -876,7 +874,7 @@
       // is only needed for backward compatibility with ourselves, and for
       // consistency with other commands.
       DCHECK(frame.document());
-      return TypingCommand::insertLineBreak(*frame.document(), source);
+      return TypingCommand::insertLineBreak(*frame.document());
   }
   NOTREACHED();
   return false;
@@ -897,29 +895,29 @@
 
 static bool executeInsertNewlineInQuotedContent(LocalFrame& frame,
                                                 Event*,
-                                                EditCommandSource source,
+                                                EditCommandSource,
                                                 const String&) {
   DCHECK(frame.document());
   return TypingCommand::insertParagraphSeparatorInQuotedContent(
-      *frame.document(), source);
+      *frame.document());
 }
 
 static bool executeInsertOrderedList(LocalFrame& frame,
                                      Event*,
-                                     EditCommandSource source,
+                                     EditCommandSource,
                                      const String&) {
   DCHECK(frame.document());
   return InsertListCommand::create(*frame.document(),
                                    InsertListCommand::OrderedList)
-      ->apply(source);
+      ->apply();
 }
 
 static bool executeInsertParagraph(LocalFrame& frame,
                                    Event*,
-                                   EditCommandSource source,
+                                   EditCommandSource,
                                    const String&) {
   DCHECK(frame.document());
-  return TypingCommand::insertParagraphSeparator(*frame.document(), source);
+  return TypingCommand::insertParagraphSeparator(*frame.document());
 }
 
 static bool executeInsertTab(LocalFrame& frame,
@@ -935,21 +933,21 @@
 
 static bool executeInsertText(LocalFrame& frame,
                               Event*,
-                              EditCommandSource source,
+                              EditCommandSource,
                               const String& value) {
   DCHECK(frame.document());
-  TypingCommand::insertText(*frame.document(), source, value, 0);
+  TypingCommand::insertText(*frame.document(), value, 0);
   return true;
 }
 
 static bool executeInsertUnorderedList(LocalFrame& frame,
                                        Event*,
-                                       EditCommandSource source,
+                                       EditCommandSource,
                                        const String&) {
   DCHECK(frame.document());
   return InsertListCommand::create(*frame.document(),
                                    InsertListCommand::UnorderedList)
-      ->apply(source);
+      ->apply();
 }
 
 static bool executeJustifyCenter(LocalFrame& frame,
@@ -1470,12 +1468,12 @@
 
 static bool executeOutdent(LocalFrame& frame,
                            Event*,
-                           EditCommandSource source,
+                           EditCommandSource,
                            const String&) {
   DCHECK(frame.document());
   return IndentOutdentCommand::create(*frame.document(),
                                       IndentOutdentCommand::Outdent)
-      ->apply(source);
+      ->apply();
 }
 
 static bool executeToggleOverwrite(LocalFrame& frame,
@@ -1775,10 +1773,10 @@
 
 static bool executeUnlink(LocalFrame& frame,
                           Event*,
-                          EditCommandSource source,
+                          EditCommandSource,
                           const String&) {
   DCHECK(frame.document());
-  return UnlinkCommand::create(*frame.document())->apply(source);
+  return UnlinkCommand::create(*frame.document())->apply();
 }
 
 static bool executeUnscript(LocalFrame& frame,
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommandTest.cpp
index bea2af380..c77927164 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommandTest.cpp
@@ -42,7 +42,7 @@
   InsertListCommand* command =
       InsertListCommand::create(document(), InsertListCommand::OrderedList);
   // This should not DCHECK.
-  EXPECT_TRUE(command->apply(EditCommandSource::kMenuOrKeyBinding))
+  EXPECT_TRUE(command->apply())
       << "The insert ordered list command should have succeeded";
   EXPECT_EQ("<ol><li>d</li></ol>", document().body()->innerHTML());
 }
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp
index 7eb43fe..3624499 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp
@@ -47,8 +47,7 @@
   ReplaceSelectionCommand* command =
       ReplaceSelectionCommand::create(document(), fragment, options);
 
-  EXPECT_TRUE(command->apply(EditCommandSource::kMenuOrKeyBinding))
-      << "the replace command should have succeeded";
+  EXPECT_TRUE(command->apply()) << "the replace command should have succeeded";
   EXPECT_EQ("foo", document().body()->innerHTML()) << "no DOM tree mutation";
 }
 
@@ -71,8 +70,7 @@
   ReplaceSelectionCommand* command =
       ReplaceSelectionCommand::create(document(), fragment, options);
 
-  EXPECT_TRUE(command->apply(EditCommandSource::kMenuOrKeyBinding))
-      << "the replace command should have succeeded";
+  EXPECT_TRUE(command->apply()) << "the replace command should have succeeded";
   EXPECT_EQ("<b>t</b>bar<b>ext</b>", document().body()->innerHTML())
       << "'bar' should have been inserted";
 }
@@ -95,8 +93,7 @@
   ReplaceSelectionCommand::CommandOptions options = 0;
   ReplaceSelectionCommand* command =
       ReplaceSelectionCommand::create(document(), fragment, options);
-  EXPECT_TRUE(command->apply(EditCommandSource::kMenuOrKeyBinding))
-      << "the replace command should have succeeded";
+  EXPECT_TRUE(command->apply()) << "the replace command should have succeeded";
 
   EXPECT_EQ(
       "<head><style>foo { bar: baz; }</style></head>"
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index 85fbcce8..89d68d2 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -122,39 +122,6 @@
   return event->text().length();
 }
 
-InputEvent::InputType inputTypeForTypingCommand(
-    TypingCommand::ETypingCommand commandType,
-    TextGranularity granularity,
-    TypingCommand::TextCompositionType compositionType) {
-  using InputType = InputEvent::InputType;
-
-  switch (commandType) {
-    // TODO(chongz): |DeleteSelection| is used by IME but we don't have
-    // direction info.
-    case TypingCommand::DeleteSelection:
-      return InputType::DeleteContentBackward;
-    case TypingCommand::DeleteKey:
-      if (compositionType != TypingCommand::TextCompositionNone)
-        return InputType::DeleteComposedCharacterBackward;
-      return deletionInputTypeFromTextGranularity(DeleteDirection::Backward,
-                                                  granularity);
-    case TypingCommand::ForwardDeleteKey:
-      if (compositionType != TypingCommand::TextCompositionNone)
-        return InputType::DeleteComposedCharacterForward;
-      return deletionInputTypeFromTextGranularity(DeleteDirection::Forward,
-                                                  granularity);
-    case TypingCommand::InsertText:
-      return InputType::InsertText;
-    case TypingCommand::InsertLineBreak:
-      return InputType::InsertLineBreak;
-    case TypingCommand::InsertParagraphSeparator:
-    case TypingCommand::InsertParagraphSeparatorInQuotedContent:
-      return InputType::InsertParagraph;
-    default:
-      return InputType::None;
-  }
-}
-
 }  // anonymous namespace
 
 using namespace HTMLNames;
@@ -178,14 +145,10 @@
       m_shouldRetainAutocorrectionIndicator(options &
                                             RetainAutocorrectionIndicator),
       m_shouldPreventSpellChecking(options & PreventSpellChecking) {
-  m_inputType = inputTypeForTypingCommand(m_commandType, m_granularity,
-                                          m_compositionType);
   updatePreservesTypingStyle(m_commandType);
 }
 
-void TypingCommand::deleteSelection(Document& document,
-                                    EditCommandSource source,
-                                    Options options) {
+void TypingCommand::deleteSelection(Document& document, Options options) {
   LocalFrame* frame = document.frame();
   DCHECK(frame);
 
@@ -198,14 +161,6 @@
 
     lastTypingCommand->setShouldPreventSpellChecking(options &
                                                      PreventSpellChecking);
-    if (!lastTypingCommand->willAddTypingToOpenCommand(
-            source, InputEvent::InputType::DeleteContentBackward))
-      return;
-
-    // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
-    // needs to be audited.  See http://crbug.com/590369 for more details.
-    document.updateStyleAndLayoutIgnorePendingStylesheets();
-
     // InputMethodController uses this function to delete composition
     // selection.  It won't be aborted.
     lastTypingCommand->deleteSelection(options & SmartDelete,
@@ -213,11 +168,10 @@
     return;
   }
 
-  TypingCommand::create(document, DeleteSelection, "", options)->apply(source);
+  TypingCommand::create(document, DeleteSelection, "", options)->apply();
 }
 
 void TypingCommand::deleteKeyPressed(Document& document,
-                                     EditCommandSource source,
                                      Options options,
                                      TextGranularity granularity) {
   if (granularity == CharacterGranularity) {
@@ -232,15 +186,6 @@
                                                        frame);
         lastTypingCommand->setShouldPreventSpellChecking(options &
                                                          PreventSpellChecking);
-        if (!lastTypingCommand->willAddTypingToOpenCommand(
-                source, InputEvent::InputType::DeleteContentBackward))
-          return;
-
-        // TODO(editing-dev): The use of
-        // updateStyleAndLayoutIgnorePendingStylesheets needs to be audited.
-        // See http://crbug.com/590369 for more details.
-        document.updateStyleAndLayoutIgnorePendingStylesheets();
-
         EditingState editingState;
         lastTypingCommand->deleteKeyPressed(granularity, options & KillRing,
                                             &editingState);
@@ -249,12 +194,10 @@
     }
   }
 
-  TypingCommand::create(document, DeleteKey, "", options, granularity)
-      ->apply(source);
+  TypingCommand::create(document, DeleteKey, "", options, granularity)->apply();
 }
 
 void TypingCommand::forwardDeleteKeyPressed(Document& document,
-                                            EditCommandSource source,
                                             EditingState* editingState,
                                             Options options,
                                             TextGranularity granularity) {
@@ -267,14 +210,6 @@
       updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand, frame);
       lastTypingCommand->setShouldPreventSpellChecking(options &
                                                        PreventSpellChecking);
-      if (!lastTypingCommand->willAddTypingToOpenCommand(
-              source, InputEvent::InputType::DeleteContentForward))
-        return;
-
-      // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
-      // needs to be audited.  See http://crbug.com/590369 for more details.
-      document.updateStyleAndLayoutIgnorePendingStylesheets();
-
       lastTypingCommand->forwardDeleteKeyPressed(
           granularity, options & KillRing, editingState);
       return;
@@ -282,13 +217,13 @@
   }
 
   TypingCommand::create(document, ForwardDeleteKey, "", options, granularity)
-      ->apply(source);
+      ->apply();
 }
 
 String TypingCommand::textDataForInputEvent() const {
-  if (m_inputType == InputEvent::InputType::InsertText)
+  if (m_commands.isEmpty() || isIncrementalInsertion())
     return m_textToInsert;
-  return CompositeEditCommand::textDataForInputEvent();
+  return m_commands.back()->textDataForInputEvent();
 }
 
 void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(
@@ -304,7 +239,6 @@
 }
 
 void TypingCommand::insertText(Document& document,
-                               EditCommandSource source,
                                const String& text,
                                Options options,
                                TextCompositionType composition,
@@ -316,7 +250,7 @@
     document.frame()->spellChecker().updateMarkersForWordsAffectedByEditing(
         isSpaceOrNewline(text[0]));
 
-  insertText(document, source, text, frame->selection().selection(), options,
+  insertText(document, text, frame->selection().selection(), options,
              composition, isIncrementalInsertion);
 }
 
@@ -344,7 +278,6 @@
 // FIXME: We shouldn't need to take selectionForInsertion. It should be
 // identical to FrameSelection's current selection.
 void TypingCommand::insertText(Document& document,
-                               EditCommandSource source,
                                const String& text,
                                const VisibleSelection& selectionForInsertion,
                                Options options,
@@ -391,16 +324,8 @@
         options & RetainAutocorrectionIndicator);
     lastTypingCommand->setShouldPreventSpellChecking(options &
                                                      PreventSpellChecking);
-    lastTypingCommand->m_isIncrementalInsertion = isIncrementalInsertion;
-    if (!lastTypingCommand->willAddTypingToOpenCommand(
-            source, InputEvent::InputType::InsertText, newText))
-      return;
-
-    // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
-    // needs to be audited.  See http://crbug.com/590369 for more details.
-    document.updateStyleAndLayoutIgnorePendingStylesheets();
-
     EditingState editingState;
+    lastTypingCommand->m_isIncrementalInsertion = isIncrementalInsertion;
     lastTypingCommand->insertText(newText, options & SelectInsertedText,
                                   &editingState);
 
@@ -426,7 +351,7 @@
     command->setEndingVisibleSelection(selectionForInsertion);
   }
   command->m_isIncrementalInsertion = isIncrementalInsertion;
-  const bool aborted = !(command->apply(source));
+  const bool aborted = !(command->apply());
 
   if (changeSelection) {
     command->setEndingVisibleSelection(currentSelection);
@@ -446,40 +371,22 @@
   }
 }
 
-bool TypingCommand::insertLineBreak(Document& document,
-                                    EditCommandSource source) {
+bool TypingCommand::insertLineBreak(Document& document) {
   if (TypingCommand* lastTypingCommand =
           lastTypingCommandIfStillOpenForTyping(document.frame())) {
     lastTypingCommand->setShouldRetainAutocorrectionIndicator(false);
-    if (!lastTypingCommand->willAddTypingToOpenCommand(
-            source, InputEvent::InputType::InsertLineBreak))
-      return false;
-
-    // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
-    // needs to be audited.  See http://crbug.com/590369 for more details.
-    document.updateStyleAndLayoutIgnorePendingStylesheets();
-
     EditingState editingState;
     lastTypingCommand->insertLineBreak(&editingState);
     return !editingState.isAborted();
   }
 
-  return TypingCommand::create(document, InsertLineBreak, "", 0)->apply(source);
+  return TypingCommand::create(document, InsertLineBreak, "", 0)->apply();
 }
 
 bool TypingCommand::insertParagraphSeparatorInQuotedContent(
-    Document& document,
-    EditCommandSource source) {
+    Document& document) {
   if (TypingCommand* lastTypingCommand =
           lastTypingCommandIfStillOpenForTyping(document.frame())) {
-    if (!lastTypingCommand->willAddTypingToOpenCommand(
-            source, InputEvent::InputType::InsertParagraph))
-      return false;
-
-    // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
-    // needs to be audited.  See http://crbug.com/590369 for more details.
-    document.updateStyleAndLayoutIgnorePendingStylesheets();
-
     EditingState editingState;
     lastTypingCommand->insertParagraphSeparatorInQuotedContent(&editingState);
     return !editingState.isAborted();
@@ -487,29 +394,20 @@
 
   return TypingCommand::create(document,
                                InsertParagraphSeparatorInQuotedContent)
-      ->apply(source);
+      ->apply();
 }
 
-bool TypingCommand::insertParagraphSeparator(Document& document,
-                                             EditCommandSource source) {
+bool TypingCommand::insertParagraphSeparator(Document& document) {
   if (TypingCommand* lastTypingCommand =
           lastTypingCommandIfStillOpenForTyping(document.frame())) {
     lastTypingCommand->setShouldRetainAutocorrectionIndicator(false);
-    if (!lastTypingCommand->willAddTypingToOpenCommand(
-            source, InputEvent::InputType::InsertParagraph))
-      return false;
-
-    // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets
-    // needs to be audited.  See http://crbug.com/590369 for more details.
-    document.updateStyleAndLayoutIgnorePendingStylesheets();
-
     EditingState editingState;
     lastTypingCommand->insertParagraphSeparator(&editingState);
     return !editingState.isAborted();
   }
 
   return TypingCommand::create(document, InsertParagraphSeparator, "", 0)
-      ->apply(source);
+      ->apply();
 }
 
 TypingCommand* TypingCommand::lastTypingCommandIfStillOpenForTyping(
@@ -567,15 +465,33 @@
 }
 
 InputEvent::InputType TypingCommand::inputType() const {
-  return m_inputType;
-}
+  using InputType = InputEvent::InputType;
 
-bool TypingCommand::willAddTypingToOpenCommand(EditCommandSource source,
-                                               InputEvent::InputType inputType,
-                                               const String& text) {
-  m_inputType = inputType;
-  m_textToInsert = text;
-  return willApplyEditing(source);
+  switch (m_commandType) {
+    // TODO(chongz): |DeleteSelection| is used by IME but we don't have
+    // direction info.
+    case DeleteSelection:
+      return InputType::DeleteContentBackward;
+    case DeleteKey:
+      if (m_compositionType != TextCompositionNone)
+        return InputType::DeleteComposedCharacterBackward;
+      return deletionInputTypeFromTextGranularity(DeleteDirection::Backward,
+                                                  m_granularity);
+    case ForwardDeleteKey:
+      if (m_compositionType != TextCompositionNone)
+        return InputType::DeleteComposedCharacterForward;
+      return deletionInputTypeFromTextGranularity(DeleteDirection::Forward,
+                                                  m_granularity);
+    case InsertText:
+      return InputType::InsertText;
+    case InsertLineBreak:
+      return InputType::InsertLineBreak;
+    case InsertParagraphSeparator:
+    case InsertParagraphSeparatorInQuotedContent:
+      return InputType::InsertParagraph;
+    default:
+      return InputType::None;
+  }
 }
 
 void TypingCommand::typingAddedToOpenCommand(
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
index ecc6a3d..437980a 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
@@ -58,33 +58,28 @@
   };
   typedef unsigned Options;
 
-  static void deleteSelection(Document&, EditCommandSource, Options = 0);
+  static void deleteSelection(Document&, Options = 0);
   static void deleteKeyPressed(Document&,
-                               EditCommandSource,
                                Options,
                                TextGranularity = CharacterGranularity);
   static void forwardDeleteKeyPressed(Document&,
-                                      EditCommandSource,
                                       EditingState*,
                                       Options = 0,
                                       TextGranularity = CharacterGranularity);
   static void insertText(Document&,
-                         EditCommandSource,
                          const String&,
                          Options,
                          TextCompositionType = TextCompositionNone,
                          const bool isIncrementalInsertion = false);
   static void insertText(Document&,
-                         EditCommandSource,
                          const String&,
                          const VisibleSelection&,
                          Options,
                          TextCompositionType = TextCompositionNone,
                          const bool isIncrementalInsertion = false);
-  static bool insertLineBreak(Document&, EditCommandSource);
-  static bool insertParagraphSeparator(Document&, EditCommandSource);
-  static bool insertParagraphSeparatorInQuotedContent(Document&,
-                                                      EditCommandSource);
+  static bool insertLineBreak(Document&);
+  static bool insertParagraphSeparator(Document&);
+  static bool insertParagraphSeparatorInQuotedContent(Document&);
   static void closeTyping(LocalFrame*);
 
   void insertText(const String& text, bool selectInsertedText, EditingState*);
@@ -107,7 +102,8 @@
 
   ETypingCommand commandTypeOfOpenCommand() const { return m_commandType; }
   TextCompositionType compositionType() const { return m_compositionType; }
-  // Returns text data of the last added typing.
+  // |TypingCommand| may contain multiple |InsertTextCommand|, should return
+  // |textDataForInputEvent()| of the last one.
   String textDataForInputEvent() const final;
 
  private:
@@ -159,10 +155,6 @@
                                                              LocalFrame*);
 
   void updatePreservesTypingStyle(ETypingCommand);
-  // Returns |false| to cancel adding typing.
-  bool willAddTypingToOpenCommand(EditCommandSource,
-                                  InputEvent::InputType,
-                                  const String& text = nullAtom);
   void typingAddedToOpenCommand(ETypingCommand);
   bool makeEditableRootEmpty(EditingState*);
 
@@ -174,7 +166,6 @@
 
   ETypingCommand m_commandType;
   String m_textToInsert;
-  InputEvent::InputType m_inputType;
   bool m_openForMoreTyping;
   bool m_selectInsertedText;
   bool m_smartDelete;
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommandTest.cpp
index 11674a6..f34fa352 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommandTest.cpp
@@ -50,8 +50,7 @@
                                       .build());
 
   // Inserting line break should not crash or hit assertion.
-  TypingCommand::insertLineBreak(document(),
-                                 EditCommandSource::kMenuOrKeyBinding);
+  TypingCommand::insertLineBreak(document());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
index 407f538..c02a63b 100644
--- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
+++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp
@@ -187,14 +187,6 @@
   didRemoveAllEventHandlers(target);
 }
 
-void EventHandlerRegistry::didMoveBetweenFrameHosts(EventTarget& target,
-                                                    FrameHost* oldFrameHost,
-                                                    FrameHost* newFrameHost) {
-  ASSERT(newFrameHost != oldFrameHost);
-  oldFrameHost->eventHandlerRegistry().didMoveOutOfFrameHost(target);
-  newFrameHost->eventHandlerRegistry().didMoveIntoFrameHost(target);
-}
-
 void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) {
   for (size_t i = 0; i < EventHandlerClassCount; ++i) {
     EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h
index 56d7750..94cd9ab 100644
--- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h
+++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h
@@ -63,9 +63,6 @@
 
   void didMoveIntoFrameHost(EventTarget&);
   void didMoveOutOfFrameHost(EventTarget&);
-  static void didMoveBetweenFrameHosts(EventTarget&,
-                                       FrameHost* oldFrameHost,
-                                       FrameHost* newFrameHost);
 
   // Either |documentDetached| or |didMove{Into,OutOf,Between}FrameHosts| must
   // be called whenever the FrameHost that is associated with a registered event
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index 3b9f60c..d5f6e8a 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -4,6 +4,7 @@
 
 #include "core/frame/ImageBitmap.h"
 
+#include "core/html/Float32ImageData.h"
 #include "core/html/HTMLCanvasElement.h"
 #include "core/html/HTMLVideoElement.h"
 #include "core/html/ImageData.h"
@@ -757,6 +758,8 @@
                                  resizedPixels.release().leakRef());
 }
 
+// TODO(zakerinasab): Fix this and the constructor from Float32ImageData
+// when the CL for Float32ImageData landed.
 ImageBitmap::ImageBitmap(ImageData* data,
                          Optional<IntRect> cropRect,
                          const ImageBitmapOptions& options) {
@@ -905,6 +908,10 @@
   m_image = StaticBitmapImage::create(std::move(skImage));
 }
 
+ImageBitmap::ImageBitmap(Float32ImageData* data,
+                         Optional<IntRect> cropRect,
+                         const ImageBitmapOptions& options) {}
+
 ImageBitmap::ImageBitmap(ImageBitmap* bitmap,
                          Optional<IntRect> cropRect,
                          const ImageBitmapOptions& options) {
@@ -989,6 +996,12 @@
   return new ImageBitmap(data, cropRect, options);
 }
 
+ImageBitmap* ImageBitmap::create(Float32ImageData* data,
+                                 Optional<IntRect> cropRect,
+                                 const ImageBitmapOptions& options) {
+  return new ImageBitmap(data, cropRect, options);
+}
+
 ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap,
                                  Optional<IntRect> cropRect,
                                  const ImageBitmapOptions& options) {
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h
index 99fd4d5..eab4930 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.h
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -21,6 +21,7 @@
 #include <memory>
 
 namespace blink {
+class Float32ImageData;
 class HTMLCanvasElement;
 class HTMLVideoElement;
 class ImageData;
@@ -65,6 +66,9 @@
   static ImageBitmap* create(ImageData*,
                              Optional<IntRect>,
                              const ImageBitmapOptions& = ImageBitmapOptions());
+  static ImageBitmap* create(Float32ImageData*,
+                             Optional<IntRect>,
+                             const ImageBitmapOptions& = ImageBitmapOptions());
   static ImageBitmap* create(ImageBitmap*,
                              Optional<IntRect>,
                              const ImageBitmapOptions& = ImageBitmapOptions());
@@ -150,6 +154,7 @@
   ImageBitmap(HTMLCanvasElement*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(OffscreenCanvas*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(ImageData*, Optional<IntRect>, const ImageBitmapOptions&);
+  ImageBitmap(Float32ImageData*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(PassRefPtr<StaticBitmapImage>);
   ImageBitmap(PassRefPtr<StaticBitmapImage>,
diff --git a/third_party/WebKit/Source/core/frame/Settings.in b/third_party/WebKit/Source/core/frame/Settings.in
deleted file mode 100644
index b35509b..0000000
--- a/third_party/WebKit/Source/core/frame/Settings.in
+++ /dev/null
@@ -1,435 +0,0 @@
-# Defines properties which are available on the Settings object.
-#
-# Please think carefully before adding a new Setting.  Some questions to
-# consider are:
-# - Should this be a RuntimeEnabledFeature instead? Settings are for things
-#   which we support either values of at runtime.  Features are set at renderer
-#   process startup and are never changed. Features also tend to be set to a
-#   value based on the platform or the stability of the code in question, where
-#   as settings both codepaths need to be stable.
-# - How will you ensure test coverage of all relevant values of your setting?
-# - Is the default value appropriate for other platforms or ports which may
-#   not be aware of your setting?
-# - Can your setting result in behavior differences observable to web
-#   developers?
-# - Should this setting ideally be removed in the future?  If so please file
-#   a bug and reference it in the comments for your setting.
-#
-# One reason to add a Setting is to manage the risk associated with adding a
-# new feature.  For example, we may choose to ship a new UI behavior or
-# performance optimization to ChromeOS users first (in order to gather feedback
-# and metrics on its use from the wild) before attempting to ship it to
-# Windows.
-#
-# FIXME: Add support for global settings.
-# FIXME: Add support for custom getters/setters.
-
-defaultTextEncodingName type=String
-
-# Do not hide chars typed in password fields immediately, but let the last char stay
-# visible for N seconds, configured by the passwordEchoDurationInSeconds setting
-# FIXME: Enable automatically if passwordEchoDurationInSeconds is set to a positive value.
-passwordEchoEnabled initial=false
-
-# Configure how long the last char should say visible in seconds.
-passwordEchoDurationInSeconds type=double, initial=1
-
-# Sets the magnification value for validation message timer.  If the
-# magnification value is N, a validation message disappears automatically after
-# <message length> * N / 1000 seconds.  If N is equal to or less than 0, a
-# validation message doesn't disappears automaticaly.
-validationMessageTimerMagnification type=int, initial=50
-
-# Number of pixels below which 2D canvas is rendered in software
-# even if hardware acceleration is enabled.
-# Hardware acceleration is useful for large canvases where it can avoid the
-# pixel bandwidth between the CPU and GPU. But GPU acceleration comes at
-# a price - extra back-buffer and texture copy. Small canvases are also
-# widely used for stylized fonts. Anti-aliasing text in hardware at that
-# scale is generally slower. So below a certain size it is better to
-# draw canvas in software.
-minimumAccelerated2dCanvasSize type=int, initial=257*256
-
-minimumFontSize type=int, initial=0, invalidate=Style
-minimumLogicalFontSize type=int, initial=0, invalidate=Style
-defaultFontSize type=int, initial=0, invalidate=Style
-defaultFixedFontSize type=int, initial=0, invalidate=Style
-
-editingBehaviorType type=EditingBehaviorType, initial=editingBehaviorTypeForPlatform()
-
-localStorageEnabled initial=false
-allowUniversalAccessFromFileURLs initial=true
-allowFileAccessFromFileURLs initial=true
-javaScriptCanOpenWindowsAutomatically initial=false
-supportsMultipleWindows initial=true
-javaScriptCanAccessClipboard initial=false
-shouldPrintBackgrounds initial=false
-shouldClearDocumentBackground initial=true
-
-textAreasAreResizable initial=false, invalidate=Style
-acceleratedCompositingEnabled initial=true, invalidate=AcceleratedCompositing
-
-offlineWebApplicationCacheEnabled initial=true
-allowScriptsToCloseWindows initial=false
-
-# FIXME: This should really be disabled by default as it makes platforms that
-# don't support the feature download files they can't use by.
-# Leaving enabled for now to not change existing behavior.
-downloadableBinaryFontsEnabled initial=true
-
-xssAuditorEnabled initial=false
-
-preferCompositingToLCDTextEnabled initial=false, invalidate=AcceleratedCompositing
-
-# 3D canvas (WebGL) support.
-webGLEnabled initial=false
-
-webGLErrorsToConsoleEnabled initial=true
-antialiased2dCanvasEnabled initial=true
-antialiasedClips2dCanvasEnabled initial=true
-accelerated2dCanvasMSAASampleCount type=int, initial=0
-
-hyperlinkAuditingEnabled initial=false
-allowRunningOfInsecureContent initial=true
-
-mediaControlsOverlayPlayButtonEnabled initial=false
-mediaPlaybackRequiresUserGesture initial=false
-
-# This flags overrides mediaPlaybackRequiresUserGesture
-crossOriginMediaPlaybackRequiresUserGesture initial=false
-
-presentationRequiresUserGesture initial=true
-
-scrollAnimatorEnabled initial=true
-
-# Used to disable threaded, compositor scrolling for testing purposes.
-# crbug.com/410974 tracks removal once alternative solutions for selective
-# main thread scrolling are supported.
-threadedScrollingEnabled initial=true, invalidate=Style
-
-# Used in layout tests for gesture tap highlights. Makes the highlights square
-# (rather than rounded) to make it possible to reftest the results.
-mockGestureTapHighlightsEnabled initial=false
-
-shouldRespectImageOrientation initial=false
-
-# Limited use by features which behave differently depending on the input
-# devices available.  For example, the pointer and hover media queries.
-# Note that we need to be careful when basing behavior or UI on this -
-# just because a device is present doesn't mean the user cares about it
-# or uses it (i.e. Chromebook Pixel users generally don't want to give up
-# screen real estate just because they happen to have a touchscreen).
-deviceSupportsTouch initial=false
-
-# This value indicates the number of simultaneous multi-touch points supported
-# by the currently connected screen/digitizer that supports the most points.
-# From Pointer Events spec:
-#   http://www.w3.org/TR/pointerevents/#widl-Navigator-maxTouchPoints
-maxTouchPoints type=int, initial=0
-
-# Whether touch gestures should be "fuzzed" to nearest touch targets.
-# It's expected that this is enabled everywhere by default, but it may be
-# disabled for testing purposes as the algorithm is not yet perfect.
-# crbug.com/304895 tracks removal once we're satisfied with the algorithm.
-touchAdjustmentEnabled initial=true
-
-# Determines whether WebViewClient::didTapMultipleTargets will be used for
-# touch disambiguation.
-multiTargetTapNotificationEnabled initial=true
-
-syncXHRInDocumentsEnabled initial=true
-cookieEnabled initial=true
-navigateOnDragDrop initial=true
-DOMPasteAllowed initial=false
-
-allowCustomScrollbarInMainFrame initial=true
-webSecurityEnabled initial=true
-
-# Special keyboard navigation mode intented for platforms with no
-# proper mouse or touch support, such as a TV controller with a remote.
-spatialNavigationEnabled initial=false
-
-# This setting adds a means to enable/disable touch initiated drag & drop. If
-# enabled, the user can initiate drag using long press.
-# crbug.com/304894 tracks removal once it's been enabled on all platforms.
-touchDragDropEnabled initial=false
-
-# Some apps could have a default video poster if it is not set.
-defaultVideoPosterURL type=String
-
-smartInsertDeleteEnabled initial=false
-selectTrailingWhitespaceEnabled initial=defaultSelectTrailingWhitespaceEnabled
-
-selectionIncludesAltImageText initial=false
-
-selectionStrategy type=SelectionStrategy, initial=SelectionStrategy::Character
-
-######## Settings used by Android WebView below ########
-
-useLegacyBackgroundSizeShorthandBehavior initial=false
-
-# This quirk is to maintain compatibility with Android apps built on
-# the Android SDK prior to and including version 18.
-# Presumably, this can be removed any time after 2015.
-# See http://crbug.com/282130.
-viewportMetaZeroValuesQuirk initial=false
-
-# Another Android SDK <= 18 quirk, removable 2015.
-# See http://crbug.com/295287
-ignoreMainFrameOverflowHiddenQuirk initial=false
-
-# Yet another Android SDK <= 18 quirk, removable 2015.
-# See http://crbug.com/305236
-reportScreenSizeInPhysicalPixelsQuirk initial=false
-
-# One more Android SDK <= 18 quirk, removable 2015.
-# See http://crbug.com/306548
-viewportMetaMergeContentQuirk initial=false
-
-# This quirk is to maintain compatibility with Android apps.
-# It will be possible to remove it once WebSettings.{get|set}UseWideViewPort
-# API function will be removed.
-# See http://crbug.com/288037.
-wideViewportQuirkEnabled initial=false
-
-# Used by the android_webview to support a horizontal height auto-sizing
-# mode.
-forceZeroLayoutHeight initial=false, invalidate=ViewportDescription
-
-mainFrameClipsContent initial=true
-
-# For android.webkit.WebSettings.setUseWideViewport()
-# http://developer.android.com/reference/android/webkit/WebSettings.html#setUseWideViewPort(boolean)
-useWideViewport initial=true, invalidate=ViewportDescription
-
-# For android.webkit.WebSettings.setLoadWithOverviewMode()
-# http://developer.android.com/reference/android/webkit/WebSettings.html#setLoadWithOverviewMode(boolean)
-loadWithOverviewMode initial=true, invalidate=ViewportDescription
-
-# Used by android_webview to support legacy apps that inject script into a top-level initial empty
-# document and expect it to persist on navigation, even though the origin is unique. Note that this
-# behavior violates the requirements described by [Initialising a new Document object] in
-# https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents.
-shouldReuseGlobalForUnownedMainFrame initial=false
-
-######## End of settings used by Android WebView ########
-
-
-# Touch based text selection and editing on desktop.
-# crbug.com/304873 tracks removal once it's been enabled on all platforms.
-touchEditingEnabled initial=false
-
-# If true, scrollers will use overlay scrollbars.  These do not take up any
-# layout width, are drawn using solid color quads by the compositor, and fade away
-# after a timeout.
-useSolidColorScrollbars initial=false
-
-# Experiment to have all APIs reflect the layout viewport.
-# crbug.com/489206 tracks the experiment.
-inertVisualViewport initial=false
-
-# The rubber-band overscroll effect is implemented in Blink and is being moved
-# to the compositor thread. This will be set to true and eventually removed.
-# crbug.com/133097
-rubberBandingOnCompositorThread initial=false
-
-# Font scale factor for accessibility, applied as part of text autosizing.
-accessibilityFontScaleFactor type=double, initial=1.0, invalidate=TextAutosizing
-
-# Only used by Layout Tests and inspector emulation.
-mediaTypeOverride type=String, initial="", invalidate=MediaQuery
-displayModeOverride type=WebDisplayMode, initial=WebDisplayModeUndefined, invalidate=MediaQuery
-
-# loadsImagesAutomatically only suppresses the network load of
-# the image URL. A cached image will still be rendered if requested.
-loadsImagesAutomatically initial=false, invalidate=ImageLoading
-imagesEnabled initial=true, invalidate=ImageLoading
-imageAnimationPolicy type=ImageAnimationPolicy, initial=ImageAnimationPolicyAllowed
-
-# Number of outstanding and pending tokens allowed in the background HTML
-# parser. A value of 0 indicates the parser should use its default value.
-backgroundHtmlParserOutstandingTokenLimit type=unsigned, initial=0
-backgroundHtmlParserPendingTokenLimit type=unsigned, initial=0
-
-# Html preload scanning is a fast, early scan of HTML documents to find loadable
-# resources before the parser advances to them. If it is disabled, resources will
-# be loaded later.
-doHtmlPreloadScanning initial=true
-
-pluginsEnabled initial=false
-
-viewportEnabled initial=false, invalidate=ViewportDescription
-viewportMetaEnabled initial=false, invalidate=ViewportDescription
-
-dnsPrefetchingEnabled initial=false, invalidate=DNSPrefetching
-
-dataSaverEnabled initial=false
-
-# FIXME: This is a temporary flag and should be removed
-# when squashing is ready. (crbug.com/261605)
-layerSquashingEnabled initial=false
-
-# Clients that execute script should call ScriptController::canExecuteScripts()
-# instead of this function. ScriptController::canExecuteScripts() checks the
-# HTML sandbox, plugin sandboxing, and other important details.
-scriptEnabled initial=false
-
-# Forces initialization of main world, even if no scripts will be executed.
-# Used by inspector to report all contexts.
-forceMainWorldInitialization initial=false, invalidate=DOMWorlds
-
-# Compensates for poor text legibility on mobile devices. This value is
-# multiplied by the font scale factor when performing text autosizing of
-# websites that do not set an explicit viewport description.
-deviceScaleAdjustment type=double, initial=1.0, invalidate=TextAutosizing
-
-# This value indicates the maximum number of bytes a document is allowed to
-# transmit in Beacons (via navigator.sendBeacon()) -- Beacons are intended to be
-# smaller payloads transmitted as a page is unloading, not a general (one-way)
-# network transmission API. The spec <https://w3c.github.io/beacon/> does not
-# proscribe an upper limit, but allows for it -- the underlying API will return
-# 'false' in that case.
-maxBeaconTransmission type=int, initial=65536
-
-# This value is set to false if the platform does not support fullscreen.
-# When set to false all the requests to enter fullscreen will return an error
-# (fullscreenerror or webkitfullscreenerror) as specified in the standard:
-# http://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen
-fullscreenSupported initial=true
-
-# V8 supports different types of caching. Used by V8 bindings.
-v8CacheOptions type=V8CacheOptions, initial=V8CacheOptionsDefault
-
-# V8 code cache for CacheStorage supports three types of strategies (none, normal and aggressive).
-v8CacheStrategiesForCacheStorage type=V8CacheStrategiesForCacheStorage, initial=V8CacheStrategiesForCacheStorage::Default
-
-# These values are bit fields for the properties of available pointing devices
-# and may take on multiple values (e.g. laptop with touchpad and touchscreen
-# has pointerType coarse *and* fine).
-availablePointerTypes type=int, initial=PointerTypeNone, invalidate=MediaQuery
-availableHoverTypes type=int, initial=HoverTypeNone, invalidate=MediaQuery
-
-# These values specify properties of the user's primary pointing device only.
-primaryPointerType type=PointerType, initial=PointerTypeNone, invalidate=MediaQuery
-primaryHoverType type=HoverType, initial=HoverTypeNone, invalidate=MediaQuery
-
-# Whether accessibility support is enabled at all.
-accessibilityEnabled initial=false, invalidate=AccessibilityState
-
-# If true, the value in password fields is exposed to assistive technologies.
-accessibilityPasswordValuesEnabled initial=false
-
-# If true, static text nodes expose inline text box children.
-inlineTextBoxAccessibilityEnabled initial=false
-
-# If true, context menu will be shown on mouse up instead of mouse down.
-# Typically enabled on Windows to match platform convention.
-showContextMenuOnMouseUp initial=false
-
-# If true, context menu will be shown on any long press event.
-# Used on Android to prevent a context menu from being shown in certain situations
-# (i.e. long pressing an empty div)
-alwaysShowContextMenuOnTouch initial=true
-
-disableReadingFromCanvas initial=false
-strictMixedContentChecking initial=false
-strictMixedContentCheckingForPlugin initial=false
-strictPowerfulFeatureRestrictions initial=false
-strictlyBlockBlockableMixedContent initial=false
-allowGeolocationOnInsecureOrigins initial=false
-logDnsPrefetchAndPreconnect initial=false
-logPreload initial=false
-
-# These values specify the UA intial viewport style.
-# It is dynamically set by the inspector for mobile emulation and can be
-# used by content embedders to specify custom style on certain platforms.
-viewportStyle type=WebViewportStyle, initial=WebViewportStyle::Default, invalidate=ViewportRule
-
-# Automatic track selection is performed based on user preference for track kind specified
-# by this setting.
-textTrackKindUserPreference type=TextTrackKindUserPreference, initial=TextTrackKindUserPreference::Default, invalidate=TextTrackKindUserPreference
-
-# User style overrides for captions and subtitles
-textTrackBackgroundColor type=String
-textTrackFontFamily type=String
-textTrackFontStyle type=String
-textTrackFontVariant type=String
-textTrackTextColor type=String
-textTrackTextShadow type=String
-textTrackTextSize type=String
-
-# Margin for title-safe placement of cues with overscan, gives top and bottom margin size as
-# percentage of video element height (for horizontal text) into which cues will not be placed.
-textTrackMarginPercentage type=double, initial=0
-
-lowPriorityIframes initial=false
-
-progressBarCompletion type=ProgressBarCompletion, initial=ProgressBarCompletion::LoadEvent
-
-historyEntryRequiresUserGesture initial=false
-
-# Do we want to try to save screen real estate in the media player by hiding
-# the volume slider / mute button?
-preferHiddenVolumeControls initial=false
-
-# Whether to disallow network fetches for parser blocking scripts in the main
-# frame inserted via document.write, for users on 2G or connections that are
-# effectively 2G.
-disallowFetchForDocWrittenScriptsInMainFrameIfEffectively2G initial=false
-
-# Whether to disallow network fetches for parser blocking scripts in the main
-# frame inserted via document.write, for users on slow connections.
-disallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections initial=false
-
-# Whether to disallow network fetches for parser blocking scripts in the main
-# frame inserted via document.write, regardless of connection type.
-disallowFetchForDocWrittenScriptsInMainFrame initial=false
-
-# Whether to invalidate device-dependent media queries and restore scroll positions
-# on frame resize assuming device rotation.
-mainFrameResizesAreOrientationChanges initial=false
-
-# Ability to override the default 'passive' value in AddEventListenerOptions. This
-# is useful to demonstrate the power of passive event listeners. This can be removed
-# when there is greater adoption, interventions to force it on and associated devtools
-# to enable it have been shipped.
-passiveListenerDefault type=PassiveListenerDefault, initial=PassiveListenerDefault::False
-
-# Use default interpolation quality to scale bitmap images if quality is not determined
-# in other ways. This can help us writing reftests containing scaled images.
-useDefaultImageInterpolationQuality initial=false
-
-# Variant of the ParseHTMLOnMainThread experiment. One experiment immediately
-# tokenizes input bytes. The default is to tokenize with a post task.
-parseHTMLOnMainThreadSyncTokenize initial=false
-
-# Variant of the ParseHTMLOnMainThread experiment. This is designed to coalesce
-# TokenizedChunks when the experiment is running in threaded mode.
-parseHTMLOnMainThreadCoalesceChunks initial=false
-
-# Whether the CSSPreloadScanner is used for externally CSS preloads. NoPreload
-# indicates that the scanner will be used, but no preloads issued.
-cssExternalScannerNoPreload initial=false
-cssExternalScannerPreload initial=false
-
-browserSideNavigationEnabled initial=false
-
-# Some platforms have media subsystems which are too buggy to allow preloading
-# of content by default. See http://crbug.com/612909 for details.
-forcePreloadNoneForMediaElements initial=false
-
-hideScrollbars initial=false
-
-# Spellchecking is enabled by default for elements that do not specify it explicitly
-# using the "spellcheck" attribute.
-spellCheckEnabledByDefault initial=true
-
-# Whether download UI should be hidden for the current page content.
-hideDownloadUI initial=false
-
-# Whether or not to issue range requests for images and show placeholders.
-fetchImagePlaceholders initial=false
-
-# Whether the frame is a presentation receiver and should expose
-# `navigator.presentation.receiver`.
-presentationReceiver initial=false
diff --git a/third_party/WebKit/Source/core/frame/Settings.json5 b/third_party/WebKit/Source/core/frame/Settings.json5
new file mode 100644
index 0000000..7be353a
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/Settings.json5
@@ -0,0 +1,932 @@
+{
+// Defines properties which are available on the Settings object.
+//
+// Please think carefully before adding a new Setting.  Some questions to
+// consider are:
+// - Should this be a RuntimeEnabledFeature instead? Settings are for things
+//   which we support either values of at runtime.  Features are set at renderer
+//   process startup and are never changed. Features also tend to be set to a
+//   value based on the platform or the stability of the code in question, where
+//   as settings both codepaths need to be stable.
+// - How will you ensure test coverage of all relevant values of your setting?
+// - Is the default value appropriate for other platforms or ports which may
+//   not be aware of your setting?
+// - Can your setting result in behavior differences observable to web
+//   developers?
+// - Should this setting ideally be removed in the future?  If so please file
+//   a bug and reference it in the comments for your setting.
+//
+// One reason to add a Setting is to manage the risk associated with adding a
+// new feature.  For example, we may choose to ship a new UI behavior or
+// performance optimization to ChromeOS users first (in order to gather feedback
+// and metrics on its use from the wild) before attempting to ship it to
+// Windows.
+//
+// FIXME: Add support for global settings.
+// FIXME: Add support for custom getters/setters.
+
+// Valid parameters for data entries below.
+parameters: {
+    type: {
+        default: "bool"
+    },
+    initial: {},
+    invalidate: {},
+},
+
+data: [
+  {
+    name: "defaultTextEncodingName",
+    type: "String",
+  },
+
+  // Do not hide chars typed in password fields immediately, but let the last char stay
+  // visible for N seconds, configured by the passwordEchoDurationInSeconds setting
+  // FIXME: Enable automatically if passwordEchoDurationInSeconds is set to a positive value.
+  {
+    name: "passwordEchoEnabled",
+    initial: false,
+  },
+
+  // Configure how long the last char should say visible in seconds.
+  {
+    name: "passwordEchoDurationInSeconds",
+    initial: 1,
+    type: "double",
+  },
+
+  // Sets the magnification value for validation message timer.  If the
+  // magnification value is N, a validation message disappears automatically after
+  // <message length> * N / 1000 seconds.  If N is equal to or less than 0, a
+  // validation message doesn't disappears automaticaly.
+  {
+    name: "validationMessageTimerMagnification",
+    initial: 50,
+    type: "int",
+  },
+
+  // Number of pixels below which 2D canvas is rendered in software
+  // even if hardware acceleration is enabled.
+  // Hardware acceleration is useful for large canvases where it can avoid the
+  // pixel bandwidth between the CPU and GPU. But GPU acceleration comes at
+  // a price - extra back-buffer and texture copy. Small canvases are also
+  // widely used for stylized fonts. Anti-aliasing text in hardware at that
+  // scale is generally slower. So below a certain size it is better to
+  // draw canvas in software.
+  {
+    name: "minimumAccelerated2dCanvasSize",
+    initial: "257*256",
+    type: "int",
+  },
+
+  {
+    name: "minimumFontSize",
+    initial: 0,
+    invalidate: "Style",
+    type: "int",
+  },
+  {
+    name: "minimumLogicalFontSize",
+    initial: 0,
+    invalidate: "Style",
+    type: "int",
+  },
+  {
+    name: "defaultFontSize",
+    initial: 0,
+    invalidate: "Style",
+    type: "int",
+  },
+  {
+    name: "defaultFixedFontSize",
+    initial: 0,
+    invalidate: "Style",
+    type: "int",
+  },
+
+  {
+    name: "editingBehaviorType",
+    initial: "editingBehaviorTypeForPlatform()",
+    type: "EditingBehaviorType",
+  },
+
+  {
+    name: "localStorageEnabled",
+    initial: false,
+  },
+  {
+    name: "allowUniversalAccessFromFileURLs",
+    initial: true,
+  },
+  {
+    name: "allowFileAccessFromFileURLs",
+    initial: true,
+  },
+  {
+    name: "javaScriptCanOpenWindowsAutomatically",
+    initial: false,
+  },
+  {
+    name: "supportsMultipleWindows",
+    initial: true,
+  },
+  {
+    name: "javaScriptCanAccessClipboard",
+    initial: false,
+  },
+  {
+    name: "shouldPrintBackgrounds",
+    initial: false,
+  },
+  {
+    name: "shouldClearDocumentBackground",
+    initial: true,
+  },
+
+  {
+    name: "textAreasAreResizable",
+    initial: false,
+    invalidate: "Style",
+  },
+  {
+    name: "acceleratedCompositingEnabled",
+    initial: true,
+    invalidate: "AcceleratedCompositing",
+  },
+
+  {
+    name: "offlineWebApplicationCacheEnabled",
+    initial: true,
+  },
+  {
+    name: "allowScriptsToCloseWindows",
+    initial: false,
+  },
+
+  // FIXME: This should really be disabled by default as it makes platforms that
+  // don't support the feature download files they can't use by.
+  // Leaving enabled for now to not change existing behavior.
+  {
+    name: "downloadableBinaryFontsEnabled",
+    initial: true,
+  },
+
+  {
+    name: "xssAuditorEnabled",
+    initial: false,
+  },
+
+  {
+    name: "preferCompositingToLCDTextEnabled",
+    initial: false,
+    invalidate: "AcceleratedCompositing",
+  },
+
+  // 3D canvas (WebGL) support.
+  {
+    name: "webGLEnabled",
+    initial: false,
+  },
+
+  {
+    name: "webGLErrorsToConsoleEnabled",
+    initial: true,
+  },
+  {
+    name: "antialiased2dCanvasEnabled",
+    initial: true,
+  },
+  {
+    name: "antialiasedClips2dCanvasEnabled",
+    initial: true,
+  },
+  {
+    name: "accelerated2dCanvasMSAASampleCount",
+    initial: 0,
+    type: "int",
+  },
+
+  {
+    name: "hyperlinkAuditingEnabled",
+    initial: false,
+  },
+  {
+    name: "allowRunningOfInsecureContent",
+    initial: true,
+  },
+
+  {
+    name: "mediaControlsOverlayPlayButtonEnabled",
+    initial: false,
+  },
+  {
+    name: "mediaPlaybackRequiresUserGesture",
+    initial: false,
+  },
+
+  // This flags overrides mediaPlaybackRequiresUserGesture
+  {
+    name: "crossOriginMediaPlaybackRequiresUserGesture",
+    initial: false,
+  },
+
+  {
+    name: "presentationRequiresUserGesture",
+    initial: true,
+  },
+
+  {
+    name: "scrollAnimatorEnabled",
+    initial: true,
+  },
+
+  // Used to disable threaded, compositor scrolling for testing purposes.
+  // crbug.com/410974 tracks removal once alternative solutions for selective
+  // main thread scrolling are supported.
+  {
+    name: "threadedScrollingEnabled",
+    initial: true,
+    invalidate: "Style",
+  },
+
+  // Used in layout tests for gesture tap highlights. Makes the highlights square
+  // (rather than rounded) to make it possible to reftest the results.
+  {
+    name: "mockGestureTapHighlightsEnabled",
+    initial: false,
+  },
+
+  {
+    name: "shouldRespectImageOrientation",
+    initial: false,
+  },
+
+  // Limited use by features which behave differently depending on the input
+  // devices available.  For example, the pointer and hover media queries.
+  // Note that we need to be careful when basing behavior or UI on this -
+  // just because a device is present doesn't mean the user cares about it
+  // or uses it (i.e. Chromebook Pixel users generally don't want to give up
+  // screen real estate just because they happen to have a touchscreen).
+  {
+    name: "deviceSupportsTouch",
+    initial: false,
+  },
+
+  // This value indicates the number of simultaneous multi-touch points supported
+  // by the currently connected screen/digitizer that supports the most points.
+  // From Pointer Events spec:
+  //   http://www.w3.org/TR/pointerevents///widl-Navigator-maxTouchPoints
+  {
+    name: "maxTouchPoints",
+    initial: 0,
+    type: "int",
+  },
+
+  // Whether touch gestures should be "fuzzed" to nearest touch targets.
+  // It's expected that this is enabled everywhere by default, but it may be
+  // disabled for testing purposes as the algorithm is not yet perfect.
+  // crbug.com/304895 tracks removal once we're satisfied with the algorithm.
+  {
+    name: "touchAdjustmentEnabled",
+    initial: true,
+  },
+
+  // Determines whether WebViewClient::didTapMultipleTargets will be used for
+  // touch disambiguation.
+  {
+    name: "multiTargetTapNotificationEnabled",
+    initial: true,
+  },
+
+  {
+    name: "syncXHRInDocumentsEnabled",
+    initial: true,
+  },
+  {
+    name: "cookieEnabled",
+    initial: true,
+  },
+  {
+    name: "navigateOnDragDrop",
+    initial: true,
+  },
+  {
+    name: "DOMPasteAllowed",
+    initial: false,
+  },
+
+  {
+    name: "allowCustomScrollbarInMainFrame",
+    initial: true,
+  },
+  {
+    name: "webSecurityEnabled",
+    initial: true,
+  },
+
+  // Special keyboard navigation mode intented for platforms with no
+  // proper mouse or touch support, such as a TV controller with a remote.
+  {
+    name: "spatialNavigationEnabled",
+    initial: false,
+  },
+
+  // This setting adds a means to enable/disable touch initiated drag & drop. If
+  // enabled, the user can initiate drag using long press.
+  // crbug.com/304894 tracks removal once it's been enabled on all platforms.
+  {
+    name: "touchDragDropEnabled",
+    initial: false,
+  },
+
+  // Some apps could have a default video poster if it is not set.
+  {
+    name: "defaultVideoPosterURL",
+    type: "String",
+  },
+
+  {
+    name: "smartInsertDeleteEnabled",
+    initial: false,
+  },
+  {
+    name: "selectTrailingWhitespaceEnabled",
+    initial: "defaultSelectTrailingWhitespaceEnabled",
+  },
+
+  {
+    name: "selectionIncludesAltImageText",
+    initial: false,
+  },
+
+  {
+    name: "selectionStrategy",
+    initial: "SelectionStrategy::Character",
+    type: "SelectionStrategy",
+  },
+
+  //////////////// Settings used by Android WebView below ////////////////
+
+  {
+    name: "useLegacyBackgroundSizeShorthandBehavior",
+    initial: false,
+  },
+
+  // This quirk is to maintain compatibility with Android apps built on
+  // the Android SDK prior to and including version 18.
+  // Presumably, this can be removed any time after 2015.
+  // See http://crbug.com/282130.
+  {
+    name: "viewportMetaZeroValuesQuirk",
+    initial: false,
+  },
+
+  // Another Android SDK <= 18 quirk, removable 2015.
+  // See http://crbug.com/295287
+  {
+    name: "ignoreMainFrameOverflowHiddenQuirk",
+    initial: false,
+  },
+
+  // Yet another Android SDK <= 18 quirk, removable 2015.
+  // See http://crbug.com/305236
+  {
+    name: "reportScreenSizeInPhysicalPixelsQuirk",
+    initial: false,
+  },
+
+  // One more Android SDK <= 18 quirk, removable 2015.
+  // See http://crbug.com/306548
+  {
+    name: "viewportMetaMergeContentQuirk",
+    initial: false,
+  },
+
+  // This quirk is to maintain compatibility with Android apps.
+  // It will be possible to remove it once WebSettings.{get|set}UseWideViewPort
+  // API function will be removed.
+  // See http://crbug.com/288037.
+  {
+    name: "wideViewportQuirkEnabled",
+    initial: false,
+  },
+
+  // Used by the android_webview to support a horizontal height auto-sizing
+  // mode.
+  {
+    name: "forceZeroLayoutHeight",
+    initial: false,
+    invalidate: "ViewportDescription",
+  },
+
+  {
+    name: "mainFrameClipsContent",
+    initial: true,
+  },
+
+  // For android.webkit.WebSettings.setUseWideViewport()
+  // http://developer.android.com/reference/android/webkit/WebSettings.html//setUseWideViewPort(boolean)
+  {
+    name: "useWideViewport",
+    initial: true,
+    invalidate: "ViewportDescription",
+  },
+
+  // For android.webkit.WebSettings.setLoadWithOverviewMode()
+  // http://developer.android.com/reference/android/webkit/WebSettings.html//setLoadWithOverviewMode(boolean)
+  {
+    name: "loadWithOverviewMode",
+    initial: true,
+    invalidate: "ViewportDescription",
+  },
+
+  // Used by android_webview to support legacy apps that inject script into a top-level initial empty
+  // document and expect it to persist on navigation, even though the origin is unique. Note that this
+  // behavior violates the requirements described by [Initialising a new Document object] in
+  // https://html.spec.whatwg.org/multipage/browsers.html//navigating-across-documents.
+  {
+    name: "shouldReuseGlobalForUnownedMainFrame",
+    initial: false,
+  },
+
+  //////////////// End of settings used by Android WebView ////////////////
+
+
+  // Touch based text selection and editing on desktop.
+  // crbug.com/304873 tracks removal once it's been enabled on all platforms.
+  {
+    name: "touchEditingEnabled",
+    initial: false,
+  },
+
+  // If true, scrollers will use overlay scrollbars.  These do not take up any
+  // layout width, are drawn using solid color quads by the compositor, and fade away
+  // after a timeout.
+  {
+    name: "useSolidColorScrollbars",
+    initial: false,
+  },
+
+  // Experiment to have all APIs reflect the layout viewport.
+  // crbug.com/489206 tracks the experiment.
+  {
+    name: "inertVisualViewport",
+    initial: false,
+  },
+
+  // The rubber-band overscroll effect is implemented in Blink and is being moved
+  // to the compositor thread. This will be set to true and eventually removed.
+  // crbug.com/133097
+  {
+    name: "rubberBandingOnCompositorThread",
+    initial: false,
+  },
+
+  // Font scale factor for accessibility, applied as part of text autosizing.
+  {
+    name: "accessibilityFontScaleFactor",
+    initial: "1.0",
+    invalidate: "TextAutosizing",
+    type: "double",
+  },
+
+  // Only used by Layout Tests and inspector emulation.
+  {
+    name: "mediaTypeOverride",
+    initial: "\"\"",
+    invalidate: "MediaQuery",
+    type: "String",
+  },
+  {
+    name: "displayModeOverride",
+    initial: "WebDisplayModeUndefined",
+    invalidate: "MediaQuery",
+    type: "WebDisplayMode",
+  },
+
+  // loadsImagesAutomatically only suppresses the network load of
+  // the image URL. A cached image will still be rendered if requested.
+  {
+    name: "loadsImagesAutomatically",
+    initial: false,
+    invalidate: "ImageLoading",
+  },
+  {
+    name: "imagesEnabled",
+    initial: true,
+    invalidate: "ImageLoading",
+  },
+  {
+    name: "imageAnimationPolicy",
+    initial: "ImageAnimationPolicyAllowed",
+    type: "ImageAnimationPolicy",
+  },
+
+  // Number of outstanding and pending tokens allowed in the background HTML
+  // parser. A value of 0 indicates the parser should use its default value.
+  {
+    name: "backgroundHtmlParserOutstandingTokenLimit",
+    initial: 0,
+    type: "unsigned",
+  },
+  {
+    name: "backgroundHtmlParserPendingTokenLimit",
+    initial: 0,
+    type: "unsigned",
+  },
+
+  // Html preload scanning is a fast, early scan of HTML documents to find loadable
+  // resources before the parser advances to them. If it is disabled, resources will
+  // be loaded later.
+  {
+    name: "doHtmlPreloadScanning",
+    initial: true,
+  },
+
+  {
+    name: "pluginsEnabled",
+    initial: false,
+  },
+
+  {
+    name: "viewportEnabled",
+    initial: false,
+    invalidate: "ViewportDescription",
+  },
+  {
+    name: "viewportMetaEnabled",
+    initial: false,
+    invalidate: "ViewportDescription",
+  },
+
+  {
+    name: "dnsPrefetchingEnabled",
+    initial: false,
+    invalidate: "DNSPrefetching",
+  },
+
+  {
+    name: "dataSaverEnabled",
+    initial: false,
+  },
+
+  // FIXME: This is a temporary flag and should be removed
+  // when squashing is ready. (crbug.com/261605)
+  {
+    name: "layerSquashingEnabled",
+    initial: false,
+  },
+
+  // Clients that execute script should call ScriptController::canExecuteScripts()
+  // instead of this function. ScriptController::canExecuteScripts() checks the
+  // HTML sandbox, plugin sandboxing, and other important details.
+  {
+    name: "scriptEnabled",
+    initial: false,
+  },
+
+  // Forces initialization of main world, even if no scripts will be executed.
+  // Used by inspector to report all contexts.
+  {
+    name: "forceMainWorldInitialization",
+    initial: false,
+    invalidate: "DOMWorlds",
+  },
+
+  // Compensates for poor text legibility on mobile devices. This value is
+  // multiplied by the font scale factor when performing text autosizing of
+  // websites that do not set an explicit viewport description.
+  {
+    name: "deviceScaleAdjustment",
+    initial: "1.0",
+    invalidate: "TextAutosizing",
+    type: "double",
+  },
+
+  // This value indicates the maximum number of bytes a document is allowed to
+  // transmit in Beacons (via navigator.sendBeacon()) -- Beacons are intended to be
+  // smaller payloads transmitted as a page is unloading, not a general (one-way)
+  // network transmission API. The spec <https://w3c.github.io/beacon/> does not
+  // proscribe an upper limit, but allows for it -- the underlying API will return
+  // 'false' in that case.
+  {
+    name: "maxBeaconTransmission",
+    initial: 65536,
+    type: "int",
+  },
+
+  // This value is set to false if the platform does not support fullscreen.
+  // When set to false all the requests to enter fullscreen will return an error
+  // (fullscreenerror or webkitfullscreenerror) as specified in the standard:
+  // http://fullscreen.spec.whatwg.org///dom-element-requestfullscreen
+  {
+    name: "fullscreenSupported",
+    initial: true,
+  },
+
+  // V8 supports different types of caching. Used by V8 bindings.
+  {
+    name: "v8CacheOptions",
+    initial: "V8CacheOptionsDefault",
+    type: "V8CacheOptions",
+  },
+
+  // V8 code cache for CacheStorage supports three types of strategies (none, normal and aggressive).
+  {
+    name: "v8CacheStrategiesForCacheStorage",
+    initial: "V8CacheStrategiesForCacheStorage::Default",
+    type: "V8CacheStrategiesForCacheStorage",
+  },
+
+  // These values are bit fields for the properties of available pointing devices
+  // and may take on multiple values (e.g. laptop with touchpad and touchscreen
+  // has pointerType coarse *and* fine).
+  {
+    name: "availablePointerTypes",
+    initial: "PointerTypeNone",
+    invalidate: "MediaQuery",
+    type: "int",
+  },
+  {
+    name: "availableHoverTypes",
+    initial: "HoverTypeNone",
+    invalidate: "MediaQuery",
+    type: "int",
+  },
+
+  // These values specify properties of the user's primary pointing device only.
+  {
+    name: "primaryPointerType",
+    initial: "PointerTypeNone",
+    invalidate: "MediaQuery",
+    type: "PointerType",
+  },
+  {
+    name: "primaryHoverType",
+    initial: "HoverTypeNone",
+    invalidate: "MediaQuery",
+    type: "HoverType",
+  },
+
+  // Whether accessibility support is enabled at all.
+  {
+    name: "accessibilityEnabled",
+    initial: false,
+    invalidate: "AccessibilityState",
+  },
+
+  // If true, the value in password fields is exposed to assistive technologies.
+  {
+    name: "accessibilityPasswordValuesEnabled",
+    initial: false,
+  },
+
+  // If true, static text nodes expose inline text box children.
+  {
+    name: "inlineTextBoxAccessibilityEnabled",
+    initial: false,
+  },
+
+  // If true, context menu will be shown on mouse up instead of mouse down.
+  // Typically enabled on Windows to match platform convention.
+  {
+    name: "showContextMenuOnMouseUp",
+    initial: false,
+  },
+
+  // If true, context menu will be shown on any long press event.
+  // Used on Android to prevent a context menu from being shown in certain situations
+  // (i.e. long pressing an empty div)
+  {
+    name: "alwaysShowContextMenuOnTouch",
+    initial: true,
+  },
+
+  {
+    name: "disableReadingFromCanvas",
+    initial: false,
+  },
+  {
+    name: "strictMixedContentChecking",
+    initial: false,
+  },
+  {
+    name: "strictMixedContentCheckingForPlugin",
+    initial: false,
+  },
+  {
+    name: "strictPowerfulFeatureRestrictions",
+    initial: false,
+  },
+  {
+    name: "strictlyBlockBlockableMixedContent",
+    initial: false,
+  },
+  {
+    name: "allowGeolocationOnInsecureOrigins",
+    initial: false,
+  },
+  {
+    name: "logDnsPrefetchAndPreconnect",
+    initial: false,
+  },
+  {
+    name: "logPreload",
+    initial: false,
+  },
+
+  // These values specify the UA intial viewport style.
+  // It is dynamically set by the inspector for mobile emulation and can be
+  // used by content embedders to specify custom style on certain platforms.
+  {
+    name: "viewportStyle",
+    initial: "WebViewportStyle::Default",
+    invalidate: "ViewportRule",
+    type: "WebViewportStyle",
+  },
+
+  // Automatic track selection is performed based on user preference for track kind specified
+  // by this setting.
+  {
+    name: "textTrackKindUserPreference",
+    initial: "TextTrackKindUserPreference::Default",
+    invalidate: "TextTrackKindUserPreference",
+    type: "TextTrackKindUserPreference",
+  },
+
+  // User style overrides for captions and subtitles
+  {
+    name: "textTrackBackgroundColor",
+    type: "String",
+  },
+  {
+    name: "textTrackFontFamily",
+    type: "String",
+  },
+  {
+    name: "textTrackFontStyle",
+    type: "String",
+  },
+  {
+    name: "textTrackFontVariant",
+    type: "String",
+  },
+  {
+    name: "textTrackTextColor",
+    type: "String",
+  },
+  {
+    name: "textTrackTextShadow",
+    type: "String",
+  },
+  {
+    name: "textTrackTextSize",
+    type: "String",
+  },
+
+  // Margin for title-safe placement of cues with overscan, gives top and bottom margin size as
+  // percentage of video element height (for horizontal text) into which cues will not be placed.
+  {
+    name: "textTrackMarginPercentage",
+    initial: 0,
+    type: "double",
+  },
+
+  {
+    name: "lowPriorityIframes",
+    initial: false,
+  },
+
+  {
+    name: "progressBarCompletion",
+    initial: "ProgressBarCompletion::LoadEvent",
+    type: "ProgressBarCompletion",
+  },
+
+  {
+    name: "historyEntryRequiresUserGesture",
+    initial: false,
+  },
+
+  // Do we want to try to save screen real estate in the media player by hiding
+  // the volume slider / mute button?
+  {
+    name: "preferHiddenVolumeControls",
+    initial: false,
+  },
+
+  // Whether to disallow network fetches for parser blocking scripts in the main
+  // frame inserted via document.write, for users on 2G or connections that are
+  // effectively 2G.
+  {
+    name: "disallowFetchForDocWrittenScriptsInMainFrameIfEffectively2G",
+    initial: false,
+  },
+
+  // Whether to disallow network fetches for parser blocking scripts in the main
+  // frame inserted via document.write, for users on slow connections.
+  {
+    name: "disallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections",
+    initial: false,
+  },
+
+  // Whether to disallow network fetches for parser blocking scripts in the main
+  // frame inserted via document.write, regardless of connection type.
+  {
+    name: "disallowFetchForDocWrittenScriptsInMainFrame",
+    initial: false,
+  },
+
+  // Whether to invalidate device-dependent media queries and restore scroll positions
+  // on frame resize assuming device rotation.
+  {
+    name: "mainFrameResizesAreOrientationChanges",
+    initial: false,
+  },
+
+  // Ability to override the default 'passive' value in AddEventListenerOptions. This
+  // is useful to demonstrate the power of passive event listeners. This can be removed
+  // when there is greater adoption, interventions to force it on and associated devtools
+  // to enable it have been shipped.
+  {
+    name: "passiveListenerDefault",
+    initial: "PassiveListenerDefault::False",
+    type: "PassiveListenerDefault",
+  },
+
+  // Use default interpolation quality to scale bitmap images if quality is not determined
+  // in other ways. This can help us writing reftests containing scaled images.
+  {
+    name: "useDefaultImageInterpolationQuality",
+    initial: false,
+  },
+
+  // Variant of the ParseHTMLOnMainThread experiment. One experiment immediately
+  // tokenizes input bytes. The default is to tokenize with a post task.
+  {
+    name: "parseHTMLOnMainThreadSyncTokenize",
+    initial: false,
+  },
+
+  // Variant of the ParseHTMLOnMainThread experiment. This is designed to coalesce
+  // TokenizedChunks when the experiment is running in threaded mode.
+  {
+    name: "parseHTMLOnMainThreadCoalesceChunks",
+    initial: false,
+  },
+
+  // Whether the CSSPreloadScanner is used for externally CSS preloads. NoPreload
+  // indicates that the scanner will be used, but no preloads issued.
+  {
+    name: "cssExternalScannerNoPreload",
+    initial: false,
+  },
+  {
+    name: "cssExternalScannerPreload",
+    initial: false,
+  },
+
+  {
+    name: "browserSideNavigationEnabled",
+    initial: false,
+  },
+
+  // Some platforms have media subsystems which are too buggy to allow preloading
+  // of content by default. See http://crbug.com/612909 for details.
+  {
+    name: "forcePreloadNoneForMediaElements",
+    initial: false,
+  },
+
+  {
+    name: "hideScrollbars",
+    initial: false,
+  },
+
+  // Spellchecking is enabled by default for elements that do not specify it explicitly
+  // using the "spellcheck" attribute.
+  {
+    name: "spellCheckEnabledByDefault",
+    initial: true,
+  },
+
+  // Whether download UI should be hidden for the current page content.
+  {
+    name: "hideDownloadUI",
+    initial: false,
+  },
+
+  // Whether or not to issue range requests for images and show placeholders.
+  {
+    name: "fetchImagePlaceholders",
+    initial: false,
+  },
+
+  // Whether the frame is a presentation receiver and should expose
+  // `navigator.presentation.receiver`.
+  {
+    name: "presentationReceiver",
+    initial: false,
+  },
+]
+}
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn
index 63cfdfcb..0fab038 100644
--- a/third_party/WebKit/Source/core/html/BUILD.gn
+++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -17,6 +17,8 @@
     "CrossOriginAttribute.h",
     "DocumentNameCollection.cpp",
     "DocumentNameCollection.h",
+    "Float32ImageData.cpp",
+    "Float32ImageData.h",
     "FormAssociated.h",
     "FormData.cpp",
     "FormData.h",
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.cpp b/third_party/WebKit/Source/core/html/Float32ImageData.cpp
new file mode 100644
index 0000000..544e19e4
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/Float32ImageData.cpp
@@ -0,0 +1,173 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/html/Float32ImageData.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/V8Float32Array.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/frame/ImageBitmap.h"
+#include "core/imagebitmap/ImageBitmapOptions.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "wtf/CheckedNumeric.h"
+
+namespace blink {
+
+bool Float32ImageData::validateConstructorArguments(
+    const unsigned& paramFlags,
+    const IntSize* size,
+    const unsigned& width,
+    const unsigned& height,
+    const DOMFloat32Array* data,
+    const String* colorSpace,
+    ExceptionState* exceptionState) {
+  return ImageData::validateConstructorArguments(
+      paramFlags, size, width, height, data, colorSpace, exceptionState,
+      kFloat32ImageData);
+}
+
+DOMFloat32Array* Float32ImageData::allocateAndValidateFloat32Array(
+    const unsigned& length,
+    ExceptionState* exceptionState) {
+  if (!length)
+    return nullptr;
+  DOMFloat32Array* dataArray = DOMFloat32Array::createOrNull(length);
+  if (!dataArray || length != dataArray->length()) {
+    if (exceptionState) {
+      exceptionState->throwDOMException(
+          V8RangeError, "Out of memory at Float32ImageData creation");
+    }
+    return nullptr;
+  }
+  return dataArray;
+}
+
+Float32ImageData* Float32ImageData::create(const IntSize& size) {
+  if (!Float32ImageData::validateConstructorArguments(kParamSize, &size))
+    return nullptr;
+  DOMFloat32Array* dataArray =
+      Float32ImageData::allocateAndValidateFloat32Array(4 * size.width() *
+                                                        size.height());
+  return dataArray ? new Float32ImageData(size, dataArray) : nullptr;
+}
+
+Float32ImageData* Float32ImageData::create(const IntSize& size,
+                                           DOMFloat32Array* dataArray) {
+  if (!Float32ImageData::validateConstructorArguments(kParamSize | kParamData,
+                                                      &size, 0, 0, dataArray))
+    return nullptr;
+  return new Float32ImageData(size, dataArray);
+}
+
+Float32ImageData* Float32ImageData::create(unsigned width,
+                                           unsigned height,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamWidth | kParamHeight, nullptr, width, height, nullptr, nullptr,
+          &exceptionState))
+    return nullptr;
+  DOMFloat32Array* dataArray =
+      Float32ImageData::allocateAndValidateFloat32Array(4 * width * height,
+                                                        &exceptionState);
+  return dataArray ? new Float32ImageData(IntSize(width, height), dataArray)
+                   : nullptr;
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(kParamData | kParamWidth,
+                                                      nullptr, width, 0, data,
+                                                      nullptr, &exceptionState))
+    return nullptr;
+  unsigned height = data->length() / (width * 4);
+  return new Float32ImageData(IntSize(width, height), data);
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           unsigned height,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
+          nullptr, &exceptionState))
+    return nullptr;
+  return new Float32ImageData(IntSize(width, height), data);
+}
+
+Float32ImageData* Float32ImageData::create(unsigned width,
+                                           unsigned height,
+                                           String colorSpace,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height,
+          nullptr, &colorSpace, &exceptionState))
+    return nullptr;
+
+  DOMFloat32Array* dataArray =
+      Float32ImageData::allocateAndValidateFloat32Array(4 * width * height,
+                                                        &exceptionState);
+  return dataArray ? new Float32ImageData(IntSize(width, height), dataArray,
+                                          colorSpace)
+                   : nullptr;
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           String colorSpace,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data,
+          &colorSpace, &exceptionState))
+    return nullptr;
+  unsigned height = data->length() / (width * 4);
+  return new Float32ImageData(IntSize(width, height), data, colorSpace);
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           unsigned height,
+                                           String colorSpace,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr,
+          width, height, data, &colorSpace, &exceptionState))
+    return nullptr;
+  return new Float32ImageData(IntSize(width, height), data, colorSpace);
+}
+
+v8::Local<v8::Object> Float32ImageData::associateWithWrapper(
+    v8::Isolate* isolate,
+    const WrapperTypeInfo* wrapperType,
+    v8::Local<v8::Object> wrapper) {
+  wrapper =
+      ScriptWrappable::associateWithWrapper(isolate, wrapperType, wrapper);
+
+  if (!wrapper.IsEmpty() && m_data.get()) {
+    // Create a V8 Float32Array object and set the "data" property
+    // of the Float32ImageData object to the created v8 object, eliminating the
+    // C++ callback when accessing the "data" property.
+    v8::Local<v8::Value> pixelArray = ToV8(m_data.get(), wrapper, isolate);
+    if (pixelArray.IsEmpty() ||
+        !v8CallBoolean(wrapper->DefineOwnProperty(
+            isolate->GetCurrentContext(), v8AtomicString(isolate, "data"),
+            pixelArray, v8::ReadOnly)))
+      return v8::Local<v8::Object>();
+  }
+  return wrapper;
+}
+
+Float32ImageData::Float32ImageData(const IntSize& size,
+                                   DOMFloat32Array* dataArray,
+                                   String colorSpaceName)
+    : m_size(size),
+      m_colorSpace(ImageData::getImageDataColorSpace(colorSpaceName)),
+      m_data(dataArray) {
+  DCHECK_GE(size.width(), 0);
+  DCHECK_GE(size.height(), 0);
+  SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <=
+                 m_data->length());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.h b/third_party/WebKit/Source/core/html/Float32ImageData.h
new file mode 100644
index 0000000..73a6b904
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/Float32ImageData.h
@@ -0,0 +1,96 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Float32ImageData_h
+#define Float32ImageData_h
+
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "core/CoreExport.h"
+#include "core/dom/DOMTypedArray.h"
+#include "core/html/ImageData.h"
+#include "core/imagebitmap/ImageBitmapSource.h"
+#include "platform/geometry/IntRect.h"
+#include "platform/geometry/IntSize.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Compiler.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+
+class ExceptionState;
+
+class CORE_EXPORT Float32ImageData final
+    : public GarbageCollectedFinalized<Float32ImageData>,
+      public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static Float32ImageData* create(const IntSize&);
+  static Float32ImageData* create(const IntSize&, DOMFloat32Array*);
+  static Float32ImageData* create(unsigned width,
+                                  unsigned height,
+                                  ExceptionState&);
+  static Float32ImageData* create(unsigned width,
+                                  unsigned height,
+                                  String colorSpace,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  String colorSpace,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  unsigned height,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  unsigned height,
+                                  String colorSpace,
+                                  ExceptionState&);
+
+  IntSize size() const { return m_size; }
+  int width() const { return m_size.width(); }
+  int height() const { return m_size.height(); }
+  String colorSpace() const {
+    return ImageData::getImageDataColorSpaceName(m_colorSpace);
+  }
+  ImageDataColorSpace imageDataColorSpace() { return m_colorSpace; }
+  const DOMFloat32Array* data() const { return m_data.get(); }
+  DOMFloat32Array* data() { return m_data.get(); }
+
+  DEFINE_INLINE_TRACE() { visitor->trace(m_data); }
+
+  WARN_UNUSED_RESULT v8::Local<v8::Object> associateWithWrapper(
+      v8::Isolate*,
+      const WrapperTypeInfo*,
+      v8::Local<v8::Object> wrapper) override;
+
+ private:
+  Float32ImageData(const IntSize&,
+                   DOMFloat32Array*,
+                   String = kLinearRGBImageDataColorSpaceName);
+
+  IntSize m_size;
+  ImageDataColorSpace m_colorSpace;
+  Member<DOMFloat32Array> m_data;
+
+  static bool validateConstructorArguments(const unsigned&,
+                                           const IntSize* = nullptr,
+                                           const unsigned& = 0,
+                                           const unsigned& = 0,
+                                           const DOMFloat32Array* = nullptr,
+                                           const String* = nullptr,
+                                           ExceptionState* = nullptr);
+
+  static DOMFloat32Array* allocateAndValidateFloat32Array(
+      const unsigned&,
+      ExceptionState* = nullptr);
+};
+
+}  // namespace blink
+
+#endif  // Float32ImageData_h
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.idl b/third_party/WebKit/Source/core/html/Float32ImageData.idl
new file mode 100644
index 0000000..9446a3c
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/Float32ImageData.idl
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imagedata
+
+[
+    Constructor(unsigned long sw, unsigned long sh),
+    Constructor(unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace),
+    Constructor(Float32Array data, unsigned long sw),
+    Constructor(Float32Array data, unsigned long sw, unsigned long sh),
+    Constructor(Float32Array data, unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace),
+
+    Exposed=(Window,Worker),
+    RaisesException=Constructor,
+    RuntimeEnabled=ExperimentalCanvasFeatures,
+] interface Float32ImageData {
+    readonly attribute unsigned long width;
+    readonly attribute unsigned long height;
+    readonly attribute Float32Array data;
+    readonly attribute ImageDataColorSpace colorSpace;
+};
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index a07ec21..68d1351 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -793,7 +793,7 @@
   return m_originClean;
 }
 
-bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const {
+bool HTMLCanvasElement::shouldAccelerate(AccelerationCriteria criteria) const {
   if (m_context && !m_context->is2d())
     return false;
 
@@ -809,8 +809,8 @@
   if (layoutBox() && !layoutBox()->hasAcceleratedCompositing())
     return false;
 
-  CheckedNumeric<int> checkedCanvasPixelCount = size.width();
-  checkedCanvasPixelCount *= size.height();
+  CheckedNumeric<int> checkedCanvasPixelCount = size().width();
+  checkedCanvasPixelCount *= size().height();
   if (!checkedCanvasPixelCount.IsValid())
     return false;
   int canvasPixelCount = checkedCanvasPixelCount.ValueOrDie();
@@ -832,10 +832,12 @@
   }
 
   // Do not use acceleration for small canvas.
-  Settings* settings = document().settings();
-  if (!settings ||
-      canvasPixelCount < settings->getMinimumAccelerated2dCanvasSize())
-    return false;
+  if (criteria != IgnoreCanvasSizeAccelerationCriteria) {
+    Settings* settings = document().settings();
+    if (!settings ||
+        canvasPixelCount < settings->getMinimumAccelerated2dCanvasSize())
+      return false;
+  }
 
   // When GPU allocated memory runs low (due to having created too many
   // accelerated canvases), the compositor starves and browser becomes laggy.
@@ -873,7 +875,7 @@
 
 }  // namespace
 
-bool HTMLCanvasElement::shouldUseDisplayList(const IntSize& deviceSize) {
+bool HTMLCanvasElement::shouldUseDisplayList() {
   if (m_context->colorSpace() != kLegacyCanvasColorSpace)
     return false;
 
@@ -887,15 +889,13 @@
 }
 
 std::unique_ptr<ImageBufferSurface>
-HTMLCanvasElement::createWebGLImageBufferSurface(const IntSize& deviceSize,
-                                                 OpacityMode opacityMode) {
+HTMLCanvasElement::createWebGLImageBufferSurface(OpacityMode opacityMode) {
   DCHECK(is3D());
   // If 3d, but the use of the canvas will be for non-accelerated content
   // then make a non-accelerated ImageBuffer. This means copying the internal
   // Image will require a pixel readback, but that is unavoidable in this case.
   auto surface = WTF::wrapUnique(new AcceleratedImageBufferSurface(
-      deviceSize, opacityMode, m_context->skColorSpace(),
-      m_context->colorType()));
+      size(), opacityMode, m_context->skColorSpace(), m_context->colorType()));
   if (surface->isValid())
     return std::move(surface);
   return nullptr;
@@ -903,12 +903,8 @@
 
 std::unique_ptr<ImageBufferSurface>
 HTMLCanvasElement::createAcceleratedImageBufferSurface(
-    const IntSize& deviceSize,
     OpacityMode opacityMode,
     int* msaaSampleCount) {
-  if (!shouldAccelerate(deviceSize))
-    return nullptr;
-
   if (document().settings()) {
     *msaaSampleCount =
         document().settings()->getAccelerated2dCanvasMSAASampleCount();
@@ -929,7 +925,7 @@
 
   std::unique_ptr<ImageBufferSurface> surface =
       WTF::wrapUnique(new Canvas2DImageBufferSurface(
-          std::move(contextProvider), deviceSize, *msaaSampleCount, opacityMode,
+          std::move(contextProvider), size(), *msaaSampleCount, opacityMode,
           Canvas2DLayerBridge::EnableAcceleration, m_context->skColorSpace(),
           m_context->colorType()));
   if (!surface->isValid()) {
@@ -945,12 +941,11 @@
 
 std::unique_ptr<ImageBufferSurface>
 HTMLCanvasElement::createUnacceleratedImageBufferSurface(
-    const IntSize& deviceSize,
     OpacityMode opacityMode) {
-  if (shouldUseDisplayList(deviceSize)) {
+  if (shouldUseDisplayList()) {
     auto surface = WTF::wrapUnique(new RecordingImageBufferSurface(
-        deviceSize, WTF::wrapUnique(new UnacceleratedSurfaceFactory),
-        opacityMode, m_context->skColorSpace(), m_context->colorType()));
+        size(), WTF::wrapUnique(new UnacceleratedSurfaceFactory), opacityMode,
+        m_context->skColorSpace(), m_context->colorType()));
     if (surface->isValid()) {
       CanvasMetrics::countCanvasContextUsage(
           CanvasMetrics::DisplayList2DCanvasImageBufferCreated);
@@ -961,9 +956,8 @@
   }
 
   auto surfaceFactory = WTF::makeUnique<UnacceleratedSurfaceFactory>();
-  auto surface = surfaceFactory->createSurface(deviceSize, opacityMode,
-                                               m_context->skColorSpace(),
-                                               m_context->colorType());
+  auto surface = surfaceFactory->createSurface(
+      size(), opacityMode, m_context->skColorSpace(), m_context->colorType());
   if (surface->isValid()) {
     CanvasMetrics::countCanvasContextUsage(
         CanvasMetrics::Unaccelerated2DCanvasImageBufferCreated);
@@ -1000,12 +994,14 @@
     if (externalSurface->isValid())
       surface = std::move(externalSurface);
   } else if (is3D()) {
-    surface = createWebGLImageBufferSurface(size(), opacityMode);
+    surface = createWebGLImageBufferSurface(opacityMode);
   } else {
-    surface = createAcceleratedImageBufferSurface(size(), opacityMode,
-                                                  &msaaSampleCount);
+    if (shouldAccelerate(NormalAccelerationCriteria)) {
+      surface =
+          createAcceleratedImageBufferSurface(opacityMode, &msaaSampleCount);
+    }
     if (!surface) {
-      surface = createUnacceleratedImageBufferSurface(size(), opacityMode);
+      surface = createUnacceleratedImageBufferSurface(opacityMode);
     }
   }
   if (!surface)
@@ -1024,7 +1020,6 @@
     return;
   }
 
-  m_imageBuffer->setClient(this);
   // Enabling MSAA overrides a request to disable antialiasing. This is true
   // regardless of whether the rendering mode is accelerated or not. For
   // consistency, we don't want to apply AA in accelerated canvases but not in
@@ -1072,9 +1067,10 @@
 
   // Four bytes per pixel per buffer.
   CheckedNumeric<intptr_t> checkedExternallyAllocatedMemory = 4 * bufferCount;
-  if (is3D())
+  if (is3D()) {
     checkedExternallyAllocatedMemory +=
         m_context->externallyAllocatedBytesPerPixel();
+  }
 
   checkedExternallyAllocatedMemory *= width();
   checkedExternallyAllocatedMemory *= height();
@@ -1214,6 +1210,21 @@
   HTMLElement::didMoveToNewDocument(oldDocument);
 }
 
+void HTMLCanvasElement::willDrawImageTo2DContext(CanvasImageSource* source) {
+  if (ExpensiveCanvasHeuristicParameters::EnableAccelerationToAvoidReadbacks &&
+      source->isAccelerated() && !buffer()->isAccelerated() &&
+      shouldAccelerate(IgnoreCanvasSizeAccelerationCriteria)) {
+    OpacityMode opacityMode =
+        m_context->creationAttributes().alpha() ? NonOpaque : Opaque;
+    int msaaSampleCount = 0;
+    std::unique_ptr<ImageBufferSurface> surface =
+        createAcceleratedImageBufferSurface(opacityMode, &msaaSampleCount);
+    if (surface) {
+      buffer()->setSurface(std::move(surface));
+    }
+  }
+}
+
 PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(
     SourceImageStatus* status,
     AccelerationHint hint,
@@ -1261,8 +1272,9 @@
             DisableAccelerationToAvoidReadbacks &&
         !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() &&
         hint == PreferNoAcceleration && m_context->isAccelerated() &&
-        hasImageBuffer())
+        hasImageBuffer()) {
       buffer()->disableAcceleration();
+    }
     RefPtr<Image> image = renderingContext()->getImage(hint, reason);
     if (image) {
       skImage =
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
index f1443be0..4025122 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -238,6 +238,8 @@
 
   void detachContext() { m_context = nullptr; }
 
+  void willDrawImageTo2DContext(CanvasImageSource*);
+
  protected:
   void didMoveToNewDocument(Document& oldDocument) override;
 
@@ -250,7 +252,11 @@
   static ContextFactoryVector& renderingContextFactories();
   static CanvasRenderingContextFactory* getRenderingContextFactory(int);
 
-  bool shouldAccelerate(const IntSize&) const;
+  enum AccelerationCriteria {
+    NormalAccelerationCriteria,
+    IgnoreCanvasSizeAccelerationCriteria,
+  };
+  bool shouldAccelerate(AccelerationCriteria) const;
 
   void parseAttribute(const AttributeModificationParams&) override;
   LayoutObject* createLayoutObject(const ComputedStyle&) override;
@@ -259,19 +265,16 @@
   void reset();
 
   std::unique_ptr<ImageBufferSurface> createWebGLImageBufferSurface(
-      const IntSize& deviceSize,
       OpacityMode);
   std::unique_ptr<ImageBufferSurface> createAcceleratedImageBufferSurface(
-      const IntSize& deviceSize,
       OpacityMode,
       int* msaaSampleCount);
   std::unique_ptr<ImageBufferSurface> createUnacceleratedImageBufferSurface(
-      const IntSize& deviceSize,
       OpacityMode);
   void createImageBuffer();
   void createImageBufferInternal(
       std::unique_ptr<ImageBufferSurface> externalSurface);
-  bool shouldUseDisplayList(const IntSize& deviceSize);
+  bool shouldUseDisplayList();
 
   void setSurfaceSize(const IntSize&);
 
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp
index 355814b..3cca1f6 100644
--- a/third_party/WebKit/Source/core/html/ImageData.cpp
+++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -34,11 +34,163 @@
 #include "core/frame/ImageBitmap.h"
 #include "core/imagebitmap/ImageBitmapOptions.h"
 #include "platform/RuntimeEnabledFeatures.h"
-#include "wtf/CheckedNumeric.h"
 
 namespace blink {
 
+bool ImageData::validateConstructorArguments(const unsigned& paramFlags,
+                                             const IntSize* size,
+                                             const unsigned& width,
+                                             const unsigned& height,
+                                             const DOMArrayBufferView* data,
+                                             const String* colorSpace,
+                                             ExceptionState* exceptionState,
+                                             ImageDataType imageDataType) {
+  if (paramFlags & kParamData) {
+    if (data->type() != DOMArrayBufferView::ViewType::TypeUint8Clamped &&
+        data->type() != DOMArrayBufferView::ViewType::TypeFloat32)
+      return false;
+    if (data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped &&
+        imageDataType != kUint8ClampedImageData)
+      imageDataType = kFloat32ImageData;
+  }
+
+  // ImageData::create parameters without ExceptionState
+  if (paramFlags & kParamSize) {
+    if (!size->width() || !size->height())
+      return false;
+    CheckedNumeric<unsigned> dataSize = 4;
+    dataSize *= size->width();
+    dataSize *= size->height();
+    if (!dataSize.IsValid())
+      return false;
+    if (paramFlags & kParamData) {
+      DCHECK(data);
+      unsigned length =
+          data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped
+              ? (const_cast<DOMUint8ClampedArray*>(
+                     static_cast<const DOMUint8ClampedArray*>(data)))
+                    ->length()
+              : (const_cast<DOMFloat32Array*>(
+                     static_cast<const DOMFloat32Array*>(data)))
+                    ->length();
+      if (dataSize.ValueOrDie() > length)
+        return false;
+    }
+    return true;
+  }
+
+  // ImageData::create parameters with ExceptionState
+  if ((paramFlags & kParamWidth) && !width) {
+    exceptionState->throwDOMException(
+        IndexSizeError, "The source width is zero or not a number.");
+    return false;
+  }
+  if ((paramFlags & kParamHeight) && !height) {
+    exceptionState->throwDOMException(
+        IndexSizeError, "The source height is zero or not a number.");
+    return false;
+  }
+  if (paramFlags & (kParamWidth | kParamHeight)) {
+    CheckedNumeric<unsigned> dataSize = 4;
+    dataSize *= width;
+    dataSize *= height;
+    if (!dataSize.IsValid()) {
+      exceptionState->throwDOMException(
+          IndexSizeError,
+          "The requested image size exceeds the supported range.");
+      return false;
+    }
+  }
+  if (paramFlags & kParamData) {
+    DCHECK(data);
+    unsigned length =
+        data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped
+            ? (const_cast<DOMUint8ClampedArray*>(
+                   static_cast<const DOMUint8ClampedArray*>(data)))
+                  ->length()
+            : (const_cast<DOMFloat32Array*>(
+                   static_cast<const DOMFloat32Array*>(data)))
+                  ->length();
+    if (!length) {
+      exceptionState->throwDOMException(IndexSizeError,
+                                        "The input data has zero elements.");
+      return false;
+    }
+    if (length % 4) {
+      exceptionState->throwDOMException(
+          IndexSizeError, "The input data length is not a multiple of 4.");
+      return false;
+    }
+    length /= 4;
+    if (length % width) {
+      exceptionState->throwDOMException(
+          IndexSizeError,
+          "The input data length is not a multiple of (4 * width).");
+      return false;
+    }
+    if ((paramFlags & kParamHeight) && height != length / width) {
+      exceptionState->throwDOMException(
+          IndexSizeError,
+          "The input data length is not equal to (4 * width * height).");
+      return false;
+    }
+  }
+  if (paramFlags & kParamColorSpace) {
+    if (!colorSpace || colorSpace->length() == 0) {
+      exceptionState->throwDOMException(
+          NotSupportedError, "The source color space is not defined.");
+      return false;
+    }
+    if (imageDataType == kUint8ClampedImageData &&
+        *colorSpace != kLegacyImageDataColorSpaceName &&
+        *colorSpace != kSRGBImageDataColorSpaceName) {
+      exceptionState->throwDOMException(NotSupportedError,
+                                        "The input color space is not "
+                                        "supported in "
+                                        "Uint8ClampedArray-backed ImageData.");
+      return false;
+    }
+    if (imageDataType == kFloat32ImageData &&
+        *colorSpace != kLinearRGBImageDataColorSpaceName) {
+      exceptionState->throwDOMException(NotSupportedError,
+                                        "The input color space is not "
+                                        "supported in "
+                                        "Float32Array-backed ImageData.");
+      return false;
+    }
+  }
+  return true;
+}
+
+DOMUint8ClampedArray* ImageData::allocateAndValidateUint8ClampedArray(
+    const unsigned& length,
+    ExceptionState* exceptionState) {
+  if (!length)
+    return nullptr;
+  DOMUint8ClampedArray* dataArray = DOMUint8ClampedArray::createOrNull(length);
+  if (!dataArray || length != dataArray->length()) {
+    if (exceptionState) {
+      exceptionState->throwDOMException(V8RangeError,
+                                        "Out of memory at ImageData creation");
+    }
+    return nullptr;
+  }
+  return dataArray;
+}
+
 ImageData* ImageData::create(const IntSize& size) {
+  if (!ImageData::validateConstructorArguments(kParamSize, &size))
+    return nullptr;
+  DOMUint8ClampedArray* byteArray =
+      ImageData::allocateAndValidateUint8ClampedArray(4 * size.width() *
+                                                      size.height());
+  if (!byteArray)
+    return nullptr;
+  return new ImageData(size, byteArray);
+}
+
+// This function accepts size (0, 0).
+ImageData* ImageData::createForTest(const IntSize& size) {
   CheckedNumeric<unsigned> dataSize = 4;
   dataSize *= size.width();
   dataSize *= size.height();
@@ -55,94 +207,33 @@
 
 ImageData* ImageData::create(const IntSize& size,
                              DOMUint8ClampedArray* byteArray) {
-  CheckedNumeric<unsigned> dataSize = 4;
-  dataSize *= size.width();
-  dataSize *= size.height();
-  if (!dataSize.IsValid())
+  if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size,
+                                               0, 0, byteArray))
     return nullptr;
-
-  if (!dataSize.IsValid() || dataSize.ValueOrDie() > byteArray->length())
-    return nullptr;
-
   return new ImageData(size, byteArray);
 }
 
 ImageData* ImageData::create(unsigned width,
                              unsigned height,
                              ExceptionState& exceptionState) {
-  if (!width || !height) {
-    exceptionState.throwDOMException(
-        IndexSizeError, String::format("The source %s is zero or not a number.",
-                                       width ? "height" : "width"));
+  if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight,
+                                               nullptr, width, height, nullptr,
+                                               nullptr, &exceptionState))
     return nullptr;
-  }
-
-  CheckedNumeric<unsigned> dataSize = 4;
-  dataSize *= width;
-  dataSize *= height;
-  if (!dataSize.IsValid() || static_cast<int>(width) < 0 ||
-      static_cast<int>(height) < 0) {
-    exceptionState.throwDOMException(
-        IndexSizeError,
-        "The requested image size exceeds the supported range.");
-    return nullptr;
-  }
-
   DOMUint8ClampedArray* byteArray =
-      DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie());
-  if (!byteArray) {
-    exceptionState.throwDOMException(V8Error,
-                                     "Out of memory at ImageData creation");
-    return nullptr;
-  }
-
-  return new ImageData(IntSize(width, height), byteArray);
-}
-
-bool ImageData::validateConstructorArguments(DOMUint8ClampedArray* data,
-                                             unsigned width,
-                                             unsigned& lengthInPixels,
-                                             ExceptionState& exceptionState) {
-  if (!width) {
-    exceptionState.throwDOMException(
-        IndexSizeError, "The source width is zero or not a number.");
-    return false;
-  }
-  DCHECK(data);
-  unsigned length = data->length();
-  if (!length) {
-    exceptionState.throwDOMException(IndexSizeError,
-                                     "The input data has a zero byte length.");
-    return false;
-  }
-  if (length % 4) {
-    exceptionState.throwDOMException(
-        IndexSizeError, "The input data byte length is not a multiple of 4.");
-    return false;
-  }
-  length /= 4;
-  if (length % width) {
-    exceptionState.throwDOMException(
-        IndexSizeError,
-        "The input data byte length is not a multiple of (4 * width).");
-    return false;
-  }
-  lengthInPixels = length;
-  return true;
+      ImageData::allocateAndValidateUint8ClampedArray(4 * width * height,
+                                                      &exceptionState);
+  return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr;
 }
 
 ImageData* ImageData::create(DOMUint8ClampedArray* data,
                              unsigned width,
                              ExceptionState& exceptionState) {
-  unsigned lengthInPixels = 0;
-  if (!validateConstructorArguments(data, width, lengthInPixels,
-                                    exceptionState)) {
-    DCHECK(exceptionState.hadException());
+  if (!ImageData::validateConstructorArguments(kParamData | kParamWidth,
+                                               nullptr, width, 0, data, nullptr,
+                                               &exceptionState))
     return nullptr;
-  }
-  DCHECK_GT(lengthInPixels, 0u);
-  DCHECK_GT(width, 0u);
-  unsigned height = lengthInPixels / width;
+  unsigned height = data->length() / (width * 4);
   return new ImageData(IntSize(width, height), data);
 }
 
@@ -150,23 +241,81 @@
                              unsigned width,
                              unsigned height,
                              ExceptionState& exceptionState) {
-  unsigned lengthInPixels = 0;
-  if (!validateConstructorArguments(data, width, lengthInPixels,
-                                    exceptionState)) {
-    DCHECK(exceptionState.hadException());
+  if (!ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
+          nullptr, &exceptionState))
     return nullptr;
-  }
-  DCHECK_GT(lengthInPixels, 0u);
-  DCHECK_GT(width, 0u);
-  if (height != lengthInPixels / width) {
-    exceptionState.throwDOMException(
-        IndexSizeError,
-        "The input data byte length is not equal to (4 * width * height).");
-    return nullptr;
-  }
   return new ImageData(IntSize(width, height), data);
 }
 
+ImageDataColorSpace ImageData::getImageDataColorSpace(String colorSpaceName) {
+  if (colorSpaceName == kLegacyImageDataColorSpaceName)
+    return kLegacyImageDataColorSpace;
+  if (colorSpaceName == kSRGBImageDataColorSpaceName)
+    return kSRGBImageDataColorSpace;
+  if (colorSpaceName == kLinearRGBImageDataColorSpaceName)
+    return kLinearRGBImageDataColorSpace;
+  NOTREACHED();
+  return kLegacyImageDataColorSpace;
+}
+
+String ImageData::getImageDataColorSpaceName(ImageDataColorSpace colorSpace) {
+  switch (colorSpace) {
+    case kLegacyImageDataColorSpace:
+      return kLegacyImageDataColorSpaceName;
+    case kSRGBImageDataColorSpace:
+      return kSRGBImageDataColorSpaceName;
+    case kLinearRGBImageDataColorSpace:
+      return kLinearRGBImageDataColorSpaceName;
+  }
+  NOTREACHED();
+  return String();
+}
+
+ImageData* ImageData::createImageData(unsigned width,
+                                      unsigned height,
+                                      String colorSpace,
+                                      ExceptionState& exceptionState) {
+  if (!ImageData::validateConstructorArguments(
+          kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height,
+          nullptr, &colorSpace, &exceptionState))
+    return nullptr;
+
+  DOMUint8ClampedArray* byteArray =
+      ImageData::allocateAndValidateUint8ClampedArray(4 * width * height,
+                                                      &exceptionState);
+  return byteArray
+             ? new ImageData(IntSize(width, height), byteArray, colorSpace)
+             : nullptr;
+}
+
+ImageData* ImageData::createImageData(DOMUint8ClampedArray* data,
+                                      unsigned width,
+                                      String colorSpace,
+                                      ExceptionState& exceptionState) {
+  if (!ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data,
+          &colorSpace, &exceptionState))
+    return nullptr;
+  unsigned height = data->length() / (width * 4);
+  return new ImageData(IntSize(width, height), data, colorSpace);
+}
+
+ImageData* ImageData::createImageData(DOMUint8ClampedArray* data,
+                                      unsigned width,
+                                      unsigned height,
+                                      String colorSpace,
+                                      ExceptionState& exceptionState) {
+  if (!ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr,
+          width, height, data, &colorSpace, &exceptionState))
+    return nullptr;
+  return new ImageData(IntSize(width, height), data, colorSpace);
+}
+
+// TODO(zakerinasab): Fix this when ImageBitmap color correction code is landed.
+// Tip: If the source Image Data has a color space, createImageBitmap must
+// respect this color space even when no color space tag is passed to it.
 ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState,
                                            EventTarget& eventTarget,
                                            Optional<IntRect> cropRect,
@@ -211,8 +360,12 @@
   return wrapper;
 }
 
-ImageData::ImageData(const IntSize& size, DOMUint8ClampedArray* byteArray)
-    : m_size(size), m_data(byteArray) {
+ImageData::ImageData(const IntSize& size,
+                     DOMUint8ClampedArray* byteArray,
+                     String colorSpaceName)
+    : m_size(size),
+      m_colorSpace(getImageDataColorSpace(colorSpaceName)),
+      m_data(byteArray) {
   DCHECK_GE(size.width(), 0);
   DCHECK_GE(size.height(), 0);
   SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <=
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h
index 206671a..286092d 100644
--- a/third_party/WebKit/Source/core/html/ImageData.h
+++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -31,18 +31,44 @@
 
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "core/CoreExport.h"
+#include "core/dom/DOMArrayBufferView.h"
 #include "core/dom/DOMTypedArray.h"
 #include "core/imagebitmap/ImageBitmapSource.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/geometry/IntSize.h"
 #include "platform/heap/Handle.h"
+#include "wtf/CheckedNumeric.h"
 #include "wtf/Compiler.h"
+#include "wtf/text/WTFString.h"
 
 namespace blink {
 
 class ExceptionState;
 class ImageBitmapOptions;
 
+enum ConstructorParams {
+  kParamSize = 1,
+  kParamWidth = 1 << 1,
+  kParamHeight = 1 << 2,
+  kParamData = 1 << 3,
+  kParamColorSpace = 1 << 4,
+};
+
+enum ImageDataType {
+  kUint8ClampedImageData,
+  kFloat32ImageData,
+};
+
+enum ImageDataColorSpace {
+  kLegacyImageDataColorSpace,
+  kSRGBImageDataColorSpace,
+  kLinearRGBImageDataColorSpace,
+};
+
+const char* const kLinearRGBImageDataColorSpaceName = "linear-rgb";
+const char* const kSRGBImageDataColorSpaceName = "srgb";
+const char* const kLegacyImageDataColorSpaceName = "legacy-srgb";
+
 class CORE_EXPORT ImageData final : public GarbageCollectedFinalized<ImageData>,
                                     public ScriptWrappable,
                                     public ImageBitmapSource {
@@ -60,9 +86,30 @@
                            unsigned height,
                            ExceptionState&);
 
+  static ImageData* createForTest(const IntSize&);
+
+  ImageData* createImageData(unsigned width,
+                             unsigned height,
+                             String colorSpace,
+                             ExceptionState&);
+  ImageData* createImageData(DOMUint8ClampedArray*,
+                             unsigned width,
+                             String colorSpace,
+                             ExceptionState&);
+  ImageData* createImageData(DOMUint8ClampedArray*,
+                             unsigned width,
+                             unsigned height,
+                             String colorSpace,
+                             ExceptionState&);
+
+  static ImageDataColorSpace getImageDataColorSpace(String);
+  static String getImageDataColorSpaceName(ImageDataColorSpace);
+
   IntSize size() const { return m_size; }
   int width() const { return m_size.width(); }
   int height() const { return m_size.height(); }
+  String colorSpace() const { return getImageDataColorSpaceName(m_colorSpace); }
+  ImageDataColorSpace imageDataColorSpace() { return m_colorSpace; }
   const DOMUint8ClampedArray* data() const { return m_data.get(); }
   DOMUint8ClampedArray* data() { return m_data.get(); }
 
@@ -81,16 +128,28 @@
       const WrapperTypeInfo*,
       v8::Local<v8::Object> wrapper) override;
 
- private:
-  ImageData(const IntSize&, DOMUint8ClampedArray*);
+  static bool validateConstructorArguments(
+      const unsigned&,
+      const IntSize* = nullptr,
+      const unsigned& = 0,
+      const unsigned& = 0,
+      const DOMArrayBufferView* = nullptr,
+      const String* = nullptr,
+      ExceptionState* = nullptr,
+      ImageDataType = kUint8ClampedImageData);
 
-  static bool validateConstructorArguments(DOMUint8ClampedArray*,
-                                           unsigned width,
-                                           unsigned&,
-                                           ExceptionState&);
+ private:
+  ImageData(const IntSize&,
+            DOMUint8ClampedArray*,
+            String = kLegacyImageDataColorSpaceName);
 
   IntSize m_size;
+  ImageDataColorSpace m_colorSpace;
   Member<DOMUint8ClampedArray> m_data;
+
+  static DOMUint8ClampedArray* allocateAndValidateUint8ClampedArray(
+      const unsigned&,
+      ExceptionState* = nullptr);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/ImageData.idl b/third_party/WebKit/Source/core/html/ImageData.idl
index d52d253..38051b0 100644
--- a/third_party/WebKit/Source/core/html/ImageData.idl
+++ b/third_party/WebKit/Source/core/html/ImageData.idl
@@ -27,6 +27,9 @@
  */
 
 // https://html.spec.whatwg.org/#dom-imagedata
+// https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imagedata
+
+enum ImageDataColorSpace { "legacy-srgb", "srgb", "linear-rgb" };
 
 [
     Constructor(unsigned long sw, unsigned long sh),
@@ -34,8 +37,13 @@
     Exposed=(Window,Worker),
     RaisesException=Constructor,
 ] interface ImageData {
+
+    [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace);
+    [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(Uint8ClampedArray data, unsigned long sw, ImageDataColorSpace colorSpace);
+    [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(Uint8ClampedArray data, unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace);
+
     readonly attribute unsigned long width;
     readonly attribute unsigned long height;
-    // TODO(foolip): Expose data.
-    // readonly attribute Uint8ClampedArray data;
+    readonly attribute Uint8ClampedArray data;
+    readonly attribute ImageDataColorSpace colorSpace;
 };
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
index 6d1eff20..4050fa6 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
@@ -86,14 +86,11 @@
 }
 
 void recordIdleTaskStatusHistogram(
-    CanvasAsyncBlobCreator::ToBlobFunctionType functionType,
     CanvasAsyncBlobCreator::IdleTaskStatus status) {
-  // TODO(crbug.com/653599): Add histograms for OffscreenCanvas.convertToBlob.
-  if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise)
-    return;
-  DEFINE_STATIC_LOCAL(EnumerationHistogram, toBlobIdleTaskStatus,
-                      ("Blink.Canvas.ToBlob.IdleTaskStatus",
-                       CanvasAsyncBlobCreator::IdleTaskCount));
+  DEFINE_THREAD_SAFE_STATIC_LOCAL(
+      EnumerationHistogram, toBlobIdleTaskStatus,
+      new EnumerationHistogram("Blink.Canvas.ToBlob.IdleTaskStatus",
+                               CanvasAsyncBlobCreator::IdleTaskCount));
   toBlobIdleTaskStatus.count(status);
 }
 
@@ -107,52 +104,57 @@
 };
 
 void recordElapsedTimeHistogram(
-    CanvasAsyncBlobCreator::ToBlobFunctionType functionType,
     ElapsedTimeHistogramType type,
     CanvasAsyncBlobCreator::MimeType mimeType,
     double elapsedTime) {
-  // TODO(crbug.com/653599): Add histograms for OffscreenCanvas.convertToBlob.
-  if (functionType == CanvasAsyncBlobCreator::OffscreenCanvasToBlobPromise)
-    return;
-
   if (type == InitiateEncodingDelay) {
     if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) {
-      DEFINE_STATIC_LOCAL(
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
           CustomCountHistogram, toBlobPNGInitiateEncodingCounter,
-          ("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50));
+          new CustomCountHistogram(
+              "Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000,
+              50));
       toBlobPNGInitiateEncodingCounter.count(elapsedTime * 1000000.0);
     } else if (mimeType == CanvasAsyncBlobCreator::MimeTypeJpeg) {
-      DEFINE_STATIC_LOCAL(
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
           CustomCountHistogram, toBlobJPEGInitiateEncodingCounter,
-          ("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50));
+          new CustomCountHistogram(
+              "Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000,
+              50));
       toBlobJPEGInitiateEncodingCounter.count(elapsedTime * 1000000.0);
     }
   } else if (type == IdleEncodeDuration) {
     if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) {
-      DEFINE_STATIC_LOCAL(
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
           CustomCountHistogram, toBlobPNGIdleEncodeCounter,
-          ("Blink.Canvas.ToBlob.IdleEncodeDuration.PNG", 0, 10000000, 50));
+          new CustomCountHistogram("Blink.Canvas.ToBlob.IdleEncodeDuration.PNG",
+                                   0, 10000000, 50));
       toBlobPNGIdleEncodeCounter.count(elapsedTime * 1000000.0);
     } else if (mimeType == CanvasAsyncBlobCreator::MimeTypeJpeg) {
-      DEFINE_STATIC_LOCAL(
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
           CustomCountHistogram, toBlobJPEGIdleEncodeCounter,
-          ("Blink.Canvas.ToBlob.IdleEncodeDuration.JPEG", 0, 10000000, 50));
+          new CustomCountHistogram(
+              "Blink.Canvas.ToBlob.IdleEncodeDuration.JPEG", 0, 10000000, 50));
       toBlobJPEGIdleEncodeCounter.count(elapsedTime * 1000000.0);
     }
   } else if (type == ToBlobDuration) {
     if (mimeType == CanvasAsyncBlobCreator::MimeTypePng) {
-      DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobPNGCounter,
-                          ("Blink.Canvas.ToBlobDuration.PNG", 0, 10000000, 50));
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
+          CustomCountHistogram, toBlobPNGCounter,
+          new CustomCountHistogram("Blink.Canvas.ToBlobDuration.PNG", 0,
+                                   10000000, 50));
       toBlobPNGCounter.count(elapsedTime * 1000000.0);
     } else if (mimeType == CanvasAsyncBlobCreator::MimeTypeJpeg) {
-      DEFINE_STATIC_LOCAL(
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
           CustomCountHistogram, toBlobJPEGCounter,
-          ("Blink.Canvas.ToBlobDuration.JPEG", 0, 10000000, 50));
+          new CustomCountHistogram("Blink.Canvas.ToBlobDuration.JPEG", 0,
+                                   10000000, 50));
       toBlobJPEGCounter.count(elapsedTime * 1000000.0);
     } else if (mimeType == CanvasAsyncBlobCreator::MimeTypeWebp) {
-      DEFINE_STATIC_LOCAL(
+      DEFINE_THREAD_SAFE_STATIC_LOCAL(
           CustomCountHistogram, toBlobWEBPCounter,
-          ("Blink.Canvas.ToBlobDuration.WEBP", 0, 10000000, 50));
+          new CustomCountHistogram("Blink.Canvas.ToBlobDuration.WEBP", 0,
+                                   10000000, 50));
       toBlobWEBPCounter.count(elapsedTime * 1000000.0);
     }
   }
@@ -296,7 +298,7 @@
 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality,
                                                   double deadlineSeconds) {
   recordElapsedTimeHistogram(
-      m_functionType, InitiateEncodingDelay, MimeTypeJpeg,
+      InitiateEncodingDelay, MimeTypeJpeg,
       WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime);
   if (m_idleTaskStatus == IdleTaskSwitchedToImmediateTask) {
     return;
@@ -321,7 +323,7 @@
 
 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) {
   recordElapsedTimeHistogram(
-      m_functionType, InitiateEncodingDelay, MimeTypePng,
+      InitiateEncodingDelay, MimeTypePng,
       WTF::monotonicallyIncreasingTime() - m_scheduleInitiateStartTime);
   if (m_idleTaskStatus == IdleTaskSwitchedToImmediateTask) {
     return;
@@ -362,8 +364,7 @@
 
   m_idleTaskStatus = IdleTaskCompleted;
   m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
-  recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypePng,
-                             m_elapsedTime);
+  recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypePng, m_elapsedTime);
   if (isDeadlineNearOrPassed(deadlineSeconds)) {
     TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
         ->postTask(BLINK_FROM_HERE,
@@ -386,8 +387,7 @@
   m_elapsedTime += (WTF::monotonicallyIncreasingTime() - startTime);
   if (m_numRowsCompleted == m_size.height()) {
     m_idleTaskStatus = IdleTaskCompleted;
-    recordElapsedTimeHistogram(m_functionType, IdleEncodeDuration, MimeTypeJpeg,
-                               m_elapsedTime);
+    recordElapsedTimeHistogram(IdleEncodeDuration, MimeTypeJpeg, m_elapsedTime);
 
     if (isDeadlineNearOrPassed(deadlineSeconds)) {
       TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
@@ -458,8 +458,8 @@
 }
 
 void CanvasAsyncBlobCreator::createBlobAndReturnResult() {
-  recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
-  recordElapsedTimeHistogram(m_functionType, ToBlobDuration, m_mimeType,
+  recordIdleTaskStatusHistogram(m_idleTaskStatus);
+  recordElapsedTimeHistogram(ToBlobDuration, m_mimeType,
                              WTF::monotonicallyIncreasingTime() - m_startTime);
 
   Blob* resultBlob =
@@ -478,10 +478,10 @@
 }
 
 void CanvasAsyncBlobCreator::createNullAndReturnResult() {
-  recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
+  recordIdleTaskStatusHistogram(m_idleTaskStatus);
   if (m_functionType == HTMLCanvasToBlobCallback) {
     DCHECK(isMainThread());
-    recordIdleTaskStatusHistogram(m_functionType, m_idleTaskStatus);
+    recordIdleTaskStatusHistogram(m_idleTaskStatus);
     TaskRunnerHelper::get(TaskType::CanvasBlobSerialization, m_document)
         ->postTask(BLINK_FROM_HERE,
                    WTF::bind(&BlobCallback::handleEvent,
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
index 6a771c1..c5a39da 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
@@ -200,7 +200,7 @@
 
 void CanvasAsyncBlobCreatorTest::prepareMockCanvasAsyncBlobCreatorFailPng() {
   IntSize testSize(0, 0);
-  ImageData* imageData = ImageData::create(testSize);
+  ImageData* imageData = ImageData::createForTest(testSize);
 
   // We reuse the class MockCanvasAsyncBlobCreatorWithoutCompletePng because
   // this test case is expected to fail at initialization step before
@@ -229,7 +229,7 @@
 
 void CanvasAsyncBlobCreatorTest::prepareMockCanvasAsyncBlobCreatorFailJpeg() {
   IntSize testSize(0, 0);
-  ImageData* imageData = ImageData::create(testSize);
+  ImageData* imageData = ImageData::createForTest(testSize);
 
   // We reuse the class MockCanvasAsyncBlobCreatorWithoutCompleteJpeg because
   // this test case is expected to fail at initialization step before
diff --git a/third_party/WebKit/Source/core/layout/BidiRun.h b/third_party/WebKit/Source/core/layout/BidiRun.h
index b119dd7..e56869f1 100644
--- a/third_party/WebKit/Source/core/layout/BidiRun.h
+++ b/third_party/WebKit/Source/core/layout/BidiRun.h
@@ -46,6 +46,17 @@
     m_hasHyphen = false;
   }
 
+  BidiRun(int start,
+          int stop,
+          unsigned char level,
+          LineLayoutItem lineLayoutItem)
+      : BidiCharacterRun(start, stop, level),
+        m_lineLayoutItem(lineLayoutItem),
+        m_box(nullptr) {
+    // Stored in base class to save space.
+    m_hasHyphen = false;
+  }
+
   BidiRun* next() { return static_cast<BidiRun*>(m_next); }
 
  public:
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
index d90fd3f1..d45ad3a0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
@@ -162,6 +162,7 @@
                                          LayoutUnit position) const override;
 
   RootInlineBox* createAndAppendRootInlineBox();
+  RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
 
   // Return the number of lines in *this* block flow. Does not recurse into
   // block flow children.
@@ -872,7 +873,6 @@
   InlineFlowBox* createLineBoxes(LineLayoutItem,
                                  const LineInfo&,
                                  InlineBox* childBox);
-  RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
   void setMarginsForRubyRun(BidiRun*,
                             LayoutRubyRun*,
                             LayoutObject*,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index ceda19d..3ad08c2 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -55,6 +55,7 @@
 #include "core/layout/shapes/ShapeOutsideInfo.h"
 #include "core/page/AutoscrollController.h"
 #include "core/page/Page.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
 #include "core/page/scrolling/SnapCoordinator.h"
 #include "core/paint/BackgroundImageGeometry.h"
 #include "core/paint/BoxPaintInvalidator.h"
@@ -335,6 +336,11 @@
     }
   }
 
+  if (diff.transformChanged()) {
+    if (ScrollingCoordinator* scrollingCoordinator =
+            document().frame()->page()->scrollingCoordinator())
+      scrollingCoordinator->notifyTransformChanged(*this);
+  }
   // Non-atomic inlines should be LayoutInline or LayoutText, not LayoutBox.
   DCHECK(!isInline() || isAtomicInlineLevel());
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc
index 417b8d46..aa1fecfe 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_layout_algorithm.cc
@@ -7,6 +7,7 @@
 #include "core/layout/ng/ng_break_token.h"
 #include "core/layout/ng/ng_constraint_space.h"
 #include "core/layout/ng/ng_constraint_space_builder.h"
+#include "core/layout/ng/ng_fragment.h"
 #include "core/layout/ng/ng_fragment_builder.h"
 #include "core/layout/ng/ng_inline_node.h"
 #include "core/layout/ng/ng_length_utils.h"
@@ -69,6 +70,7 @@
     case kStateFinalize:
       line_builder_->CreateFragments(builder_);
       *fragment_out = builder_->ToBoxFragment();
+      line_builder_->CopyFragmentDataToLayoutBlockFlow();
       state_ = kStateInit;
       return kNewFragment;
   };
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
index d825058..5186ccd 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc
@@ -4,12 +4,14 @@
 
 #include "core/layout/ng/ng_inline_node.h"
 
+#include "core/layout/LayoutBlockFlow.h"
 #include "core/layout/LayoutObject.h"
 #include "core/layout/LayoutText.h"
 #include "core/layout/ng/ng_bidi_paragraph.h"
 #include "core/layout/ng/ng_box_fragment.h"
 #include "core/layout/ng/ng_constraint_space_builder.h"
 #include "core/layout/ng/ng_fragment_builder.h"
+#include "core/layout/ng/ng_line_builder.h"
 #include "core/layout/ng/ng_layout_inline_items_builder.h"
 #include "core/layout/ng/ng_physical_box_fragment.h"
 #include "core/layout/ng/ng_physical_text_fragment.h"
@@ -80,7 +82,7 @@
   while (node) {
     if (node->isText()) {
       builder->SetIsSVGText(node->isSVGInlineText());
-      builder->Append(toLayoutText(node)->text(), node->style());
+      builder->Append(toLayoutText(node)->text(), node->style(), node);
     } else if (node->isFloating() || node->isOutOfFlowPositioned()) {
       // Skip positioned objects.
     } else if (!node->isInline()) {
@@ -91,7 +93,7 @@
       // For atomic inlines add a unicode "object replacement character" to
       // signal the presence of a non-text object to the unicode bidi algorithm.
       if (node->isAtomicInlineLevel()) {
-        builder->Append(objectReplacementCharacter);
+        builder->Append(objectReplacementCharacter, nullptr, node);
       }
 
       // Otherwise traverse to children if they exist.
@@ -239,8 +241,6 @@
     return false;
   }
 
-  // TODO(layout-dev): Implement copying of fragment data to LayoutObject tree.
-
   // Reset algorithm for future use
   layout_algorithm_ = nullptr;
   return true;
@@ -257,6 +257,50 @@
   return next_sibling_;
 }
 
+// Find the first LayoutBlockFlow in the ancestor chain of |start_inilne_|.
+LayoutBlockFlow* NGInlineNode::GetLayoutBlockFlow() const {
+  for (LayoutObject* layout_object = start_inline_->parent(); layout_object;
+       layout_object = layout_object->parent()) {
+    if (layout_object->isLayoutBlockFlow())
+      return toLayoutBlockFlow(layout_object);
+  }
+  ASSERT_NOT_REACHED();
+  return nullptr;
+}
+
+// Compute the delta of text offsets between NGInlineNode and LayoutText.
+// This map is needed to produce InlineTextBox since its offsets are to
+// LayoutText.
+// TODO(kojii): Since NGInlineNode has text after whitespace collapsed, the
+// length may not match with LayoutText. This function updates LayoutText to
+// match, but this needs more careful coding, if we keep copying to layoutobject
+// tree.
+void NGInlineNode::GetLayoutTextOffsets(
+    Vector<unsigned, 32>* text_offsets_out) {
+  LayoutText* current_text = nullptr;
+  unsigned current_offset = 0;
+  for (unsigned i = 0; i < items_.size(); i++) {
+    const NGLayoutInlineItem& item = items_[i];
+    LayoutObject* next_object = item.GetLayoutObject();
+    LayoutText* next_text = next_object && next_object->isText()
+                                ? toLayoutText(next_object)
+                                : nullptr;
+    if (next_text != current_text) {
+      if (current_text &&
+          current_text->textLength() != item.StartOffset() - current_offset) {
+        current_text->setText(Text(current_offset, item.StartOffset()).impl());
+      }
+      current_text = next_text;
+      current_offset = item.StartOffset();
+    }
+    (*text_offsets_out)[i] = current_offset;
+  }
+  if (current_text &&
+      current_text->textLength() != text_content_.length() - current_offset) {
+    current_text->setText(Text(current_offset, text_content_.length()).impl());
+  }
+}
+
 DEFINE_TRACE(NGInlineNode) {
   visitor->trace(next_sibling_);
   visitor->trace(layout_algorithm_);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h
index d0b6c0d..15f3040 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.h
@@ -18,6 +18,7 @@
 namespace blink {
 
 class ComputedStyle;
+class LayoutBlockFlow;
 class LayoutObject;
 class LayoutUnit;
 class NGConstraintSpace;
@@ -49,6 +50,9 @@
   Vector<NGLayoutInlineItem>& Items() { return items_; }
   NGLayoutInlineItemRange Items(unsigned start_index, unsigned end_index);
 
+  LayoutBlockFlow* GetLayoutBlockFlow() const;
+  void GetLayoutTextOffsets(Vector<unsigned, 32>*);
+
   bool IsBidiEnabled() const { return is_bidi_enabled_; }
 
   DECLARE_VIRTUAL_TRACE();
@@ -86,14 +90,18 @@
 // element where possible.
 class NGLayoutInlineItem {
  public:
-  NGLayoutInlineItem(unsigned start, unsigned end, const ComputedStyle* style)
+  NGLayoutInlineItem(unsigned start,
+                     unsigned end,
+                     const ComputedStyle* style,
+                     LayoutObject* layout_object = nullptr)
       : start_offset_(start),
         end_offset_(end),
         bidi_level_(UBIDI_LTR),
         script_(USCRIPT_INVALID_CODE),
         fallback_priority_(FontFallbackPriority::Invalid),
         rotate_sideways_(false),
-        style_(style) {
+        style_(style),
+        layout_object_(layout_object) {
     DCHECK(end >= start);
   }
 
@@ -105,6 +113,7 @@
   UBiDiLevel BidiLevel() const { return bidi_level_; }
   UScriptCode Script() const { return script_; }
   const ComputedStyle* Style() const { return style_; }
+  LayoutObject* GetLayoutObject() const { return layout_object_; }
 
   void SetEndOffset(unsigned);
 
@@ -127,6 +136,7 @@
   bool rotate_sideways_;
   const ComputedStyle* style_;
   Vector<RefPtr<const ShapeResult>> shape_results_;
+  LayoutObject* layout_object_;
 
   friend class NGInlineNode;
 };
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc
index 1335f71d3..7f51d7b 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_inline_node_test.cc
@@ -30,7 +30,10 @@
   void Append(const String& text, const ComputedStyle* style = nullptr) {
     unsigned start = text_content_.length();
     text_content_.append(text);
-    items_.push_back(NGLayoutInlineItem(start, start + text.length(), style));
+    // Pass non-null LayoutObject to indicate this is a text from LayoutText.
+    LayoutObject* layout_object = reinterpret_cast<LayoutObject*>(1);
+    items_.push_back(
+        NGLayoutInlineItem(start, start + text.length(), style, layout_object));
   }
 
   void Append(UChar character) {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
index 950a1775..57adefd0 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
@@ -96,10 +96,11 @@
 }
 
 void NGLayoutInlineItemsBuilder::Append(const String& string,
-                                        const ComputedStyle* style) {
+                                        const ComputedStyle* style,
+                                        LayoutObject* layout_object) {
   if (string.isEmpty()) {
     unsigned offset = text_.length();
-    items_->push_back(NGLayoutInlineItem(offset, offset, style));
+    items_->push_back(NGLayoutInlineItem(offset, offset, style, layout_object));
     return;
   }
 
@@ -149,13 +150,22 @@
     }
   }
 
-  items_->push_back(NGLayoutInlineItem(start_offset, text_.length(), style));
+  items_->push_back(
+      NGLayoutInlineItem(start_offset, text_.length(), style, layout_object));
 }
 
-void NGLayoutInlineItemsBuilder::Append(UChar character) {
+void NGLayoutInlineItemsBuilder::Append(UChar character,
+                                        const ComputedStyle* style,
+                                        LayoutObject* layout_object) {
   DCHECK(character != spaceCharacter && character != tabulationCharacter &&
          character != newlineCharacter && character != zeroWidthSpaceCharacter);
-  AppendAsOpaqueToSpaceCollapsing(character);
+  if (has_pending_newline_)
+    ProcessPendingNewline(emptyString(), nullptr);
+
+  text_.append(character);
+  unsigned end_offset = text_.length();
+  items_->push_back(
+      NGLayoutInlineItem(end_offset - 1, end_offset, style, layout_object));
   is_last_collapsible_space_ = false;
 }
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.h
index 9d69786f..adeb6f9 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.h
@@ -46,13 +46,20 @@
   // When appending, spaces are collapsed according to CSS Text, The white space
   // processing rules
   // https://drafts.csswg.org/css-text-3/#white-space-rules
-  void Append(const String&, const ComputedStyle*);
+  // @param style The style for the string.
+  // If a nullptr, it should skip shaping. Atomic inlines and bidi controls use
+  // this.
+  // @param LayoutObject The LayoutObject for the string.
+  // If a nullptr, it does not generate BidiRun. Bidi controls use this.
+  void Append(const String&, const ComputedStyle*, LayoutObject* = nullptr);
 
   // Append a character.
   // Currently this function is for adding control characters such as
   // objectReplacementCharacter, and does not support all space collapsing logic
   // as its String version does.
-  void Append(UChar);
+  // See the String version for using nullptr for ComputedStyle and
+  // LayoutObject.
+  void Append(UChar, const ComputedStyle* = nullptr, LayoutObject* = nullptr);
 
   // Append a character.
   // The character is opaque to space collapsing that spaces before this
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
index e1999af..7b85379 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
@@ -4,6 +4,10 @@
 
 #include "core/layout/ng/ng_line_builder.h"
 
+#include "core/layout/BidiRun.h"
+#include "core/layout/LayoutBlockFlow.h"
+#include "core/layout/line/LineInfo.h"
+#include "core/layout/line/RootInlineBox.h"
 #include "core/layout/ng/ng_bidi_paragraph.h"
 #include "core/layout/ng/ng_constraint_space.h"
 #include "core/layout/ng/ng_fragment_builder.h"
@@ -11,6 +15,7 @@
 #include "core/layout/ng/ng_text_fragment.h"
 #include "core/layout/ng/ng_units.h"
 #include "core/style/ComputedStyle.h"
+#include "platform/text/BidiRunList.h"
 
 namespace blink {
 
@@ -43,10 +48,13 @@
   const Vector<NGLayoutInlineItem>& items = inline_box_->Items();
   for (const auto& line_item_chunk : line_item_chunks_) {
     const NGLayoutInlineItem& start_item = items[line_item_chunk.start_index];
-    const ComputedStyle* style = start_item.Style();
     // Skip bidi controls.
-    if (!style)
+    if (!start_item.GetLayoutObject())
       continue;
+    const ComputedStyle* style = start_item.Style();
+    // TODO(kojii): Handling atomic inline needs more thoughts.
+    if (!style)
+      style = start_item.GetLayoutObject()->style();
 
     // TODO(kojii): The block size for a text fragment isn't clear, revisit when
     // we implement line box layout.
@@ -68,6 +76,11 @@
   }
   DCHECK_EQ(fragments_.size(), offsets_.size());
 
+  line_box_data_list_.grow(line_box_data_list_.size() + 1);
+  LineBoxData& line_box_data = line_box_data_list_.back();
+  line_box_data.fragment_end = fragments_.size();
+  line_box_data.inline_size = inline_offset;
+
   max_inline_size_ = std::max(max_inline_size_, inline_offset);
   // TODO(kojii): Implement block size when we support baseline alignment.
   content_size_ += LayoutUnit(100);
@@ -127,6 +140,81 @@
       .SetBlockOverflow(content_size_);
 }
 
+void NGLineBuilder::CopyFragmentDataToLayoutBlockFlow() {
+  LayoutBlockFlow* block = inline_box_->GetLayoutBlockFlow();
+  block->deleteLineBoxTree();
+
+  Vector<NGLayoutInlineItem>& items = inline_box_->Items();
+  Vector<unsigned, 32> text_offsets(items.size());
+  inline_box_->GetLayoutTextOffsets(&text_offsets);
+
+  HeapVector<Member<const NGFragment>, 32> fragments_for_bidi_runs;
+  fragments_for_bidi_runs.reserveInitialCapacity(items.size());
+  BidiRunList<BidiRun> bidi_runs;
+  LineInfo line_info;
+  unsigned fragment_index = 0;
+  for (const auto& line_box_data : line_box_data_list_) {
+    // Create a BidiRunList for this line.
+    for (; fragment_index < line_box_data.fragment_end; fragment_index++) {
+      const NGFragment* fragment = fragments_[fragment_index];
+      const NGPhysicalTextFragment* text_fragment =
+          toNGPhysicalTextFragment(fragment->PhysicalFragment());
+      // TODO(kojii): needs to reverse for RTL?
+      for (unsigned item_index = text_fragment->StartIndex();
+           item_index < text_fragment->EndIndex(); item_index++) {
+        const NGLayoutInlineItem& item = items[item_index];
+        LayoutObject* layout_object = item.GetLayoutObject();
+        if (!layout_object)  // Skip bidi controls.
+          continue;
+        BidiRun* run;
+        if (layout_object->isText()) {
+          unsigned text_offset = text_offsets[item_index];
+          run = new BidiRun(item.StartOffset() - text_offset,
+                            item.EndOffset() - text_offset, item.BidiLevel(),
+                            LineLayoutItem(layout_object));
+        } else {
+          DCHECK(layout_object->isAtomicInlineLevel());
+          run = new BidiRun(0, 1, item.BidiLevel(),
+                            LineLayoutItem(layout_object));
+        }
+        bidi_runs.addRun(run);
+        fragments_for_bidi_runs.append(fragment);
+      }
+    }
+    // TODO(kojii): bidi needs to find the logical last run.
+    bidi_runs.setLogicallyLastRun(bidi_runs.lastRun());
+
+    // Create a RootInlineBox from BidiRunList. InlineBoxes created for the
+    // RootInlineBox are set to Bidirun::m_box.
+    line_info.setEmpty(false);
+    // TODO(kojii): Implement setFirstLine, LastLine, etc.
+    RootInlineBox* line_box = block->constructLine(bidi_runs, line_info);
+
+    // Copy fragments data to InlineBoxes.
+    DCHECK_EQ(fragments_for_bidi_runs.size(), bidi_runs.runCount());
+    BidiRun* run = bidi_runs.firstRun();
+    for (const auto& fragment : fragments_for_bidi_runs) {
+      DCHECK(run);
+      InlineBox* inline_box = run->m_box;
+      inline_box->setLogicalWidth(fragment->InlineSize());
+      inline_box->setLogicalLeft(fragment->InlineOffset());
+      inline_box->setLogicalTop(fragment->BlockOffset());
+      run = run->next();
+    }
+    DCHECK(!run);
+
+    // Copy LineBoxData to RootInlineBox.
+    line_box->setLogicalWidth(line_box_data.inline_size);
+    // TODO(kojii): Compute top/bottom/leading in |CreateLine()| and store in
+    // line_box_data.
+    line_box->setLineTopBottomPositions(LayoutUnit(), LayoutUnit(100),
+                                        LayoutUnit(), LayoutUnit(100));
+
+    bidi_runs.deleteRuns();
+    fragments_for_bidi_runs.clear();
+  }
+}
+
 DEFINE_TRACE(NGLineBuilder) {
   visitor->trace(inline_box_);
   visitor->trace(constraint_space_);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.h
index 2bb728b..702f220 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.h
@@ -32,6 +32,12 @@
   // Create fragments for lines created by |CreateLine()|.
   void CreateFragments(NGFragmentBuilder*);
 
+  // Copy fragment data of all lines created by this NGLineBuilder to
+  // LayoutBlockFlow.
+  // This must run after |CreateFragments()|, and after the fragments it created
+  // are placed.
+  void CopyFragmentDataToLayoutBlockFlow();
+
   DECLARE_VIRTUAL_TRACE();
 
  private:
@@ -43,11 +49,22 @@
     LayoutUnit inline_size;
   };
 
+  // LineBoxData is a set of data for a line box that are computed in early
+  // phases, such as in |CreateLine()|, and will be used in later phases.
+  // TODO(kojii): Not sure if all these data are needed in fragment tree. If
+  // they are, we can create a linebox fragment, store them there, and this
+  // isn't needed. For now, we're trying to minimize data in fragments.
+  struct LineBoxData {
+    unsigned fragment_end;
+    LayoutUnit inline_size;
+  };
+
   Member<NGInlineNode> inline_box_;
   Member<const NGConstraintSpace> constraint_space_;
   HeapVector<Member<NGFragment>, 32> fragments_;
   Vector<NGLogicalOffset, 32> offsets_;
   Vector<LineItemChunk, 32> line_item_chunks_;
+  Vector<LineBoxData, 32> line_box_data_list_;
   LayoutUnit content_size_;
   LayoutUnit max_inline_size_;
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_text_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_text_layout_algorithm.cc
index 198a1998..55509b48 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_text_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_text_layout_algorithm.cc
@@ -57,7 +57,10 @@
     for (; i < items.size(); i++) {
       const NGLayoutInlineItem& item = items[i];
       // Split chunks before bidi controls, or at bidi level boundaries.
-      if (!item.Style() || item.BidiLevel() != start_item.BidiLevel()) {
+      // Also split at LayoutObject boundaries to generate InlineBox in
+      // |CopyFragmentDataToLayoutBlockFlow()|.
+      if (item.GetLayoutObject() != start_item.GetLayoutObject() ||
+          !item.Style() || item.BidiLevel() != start_item.BidiLevel()) {
         break;
       }
       inline_size += item.InlineSize();
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePaintServer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePaintServer.cpp
index ae34b3d..eae1e9ff 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePaintServer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePaintServer.cpp
@@ -96,7 +96,7 @@
       break;
   }
 
-  if (style.insideLink() == InsideVisitedLink) {
+  if (style.insideLink() == EInsideLink::kInsideVisitedLink) {
     // FIXME: This code doesn't support the uri component of the visited link
     // paint, https://bugs.webkit.org/show_bug.cgi?id=70006
     SVGPaintType visitedPaintType = applyToFill
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 27681120..15fd00d0 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -128,6 +128,18 @@
   m_shouldScrollOnMainThreadDirty = true;
 }
 
+void ScrollingCoordinator::notifyTransformChanged(const LayoutBox& box) {
+  if (m_page->deprecatedLocalMainFrame()->view()->needsLayout())
+    return;
+
+  for (PaintLayer* layer = box.enclosingLayer(); layer;
+       layer = layer->parent()) {
+    if (m_layersWithTouchRects.contains(layer)) {
+      m_touchEventTargetRectsAreDirty = true;
+      return;
+    }
+  }
+}
 void ScrollingCoordinator::notifyOverflowUpdated() {
   m_scrollGestureRegionIsDirty = true;
 }
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
index 7d97eb4..9f681cd 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.h
@@ -41,6 +41,7 @@
 
 class CompositorAnimationHost;
 class CompositorAnimationTimeline;
+class LayoutBox;
 class LocalFrame;
 class FrameView;
 class GraphicsLayer;
@@ -74,6 +75,8 @@
   void notifyGeometryChanged();
   // Called when any frame recalculates its overflows after style change.
   void notifyOverflowUpdated();
+  // Called when any layoutBox has transform changed
+  void notifyTransformChanged(const LayoutBox&);
 
   void updateAfterCompositingChangeIfNeeded();
 
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index e4402ca..1b5ca74b 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -2162,7 +2162,7 @@
 
 Color ComputedStyle::visitedDependentColor(int colorProperty) const {
   Color unvisitedColor = colorIncludingFallback(colorProperty, false);
-  if (insideLink() != InsideVisitedLink)
+  if (insideLink() != EInsideLink::kInsideVisitedLink)
     return unvisitedColor;
 
   Color visitedColor = colorIncludingFallback(colorProperty, true);
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 825e0e5..261bc9b 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -301,7 +301,8 @@
     ComputedStyleBase::setBitDefaults();
     m_inheritedData.m_hasSimpleUnderline = false;
     m_inheritedData.m_cursorStyle = static_cast<unsigned>(initialCursor());
-    m_inheritedData.m_insideLink = NotInsideLink;
+    m_inheritedData.m_insideLink =
+        static_cast<unsigned>(EInsideLink::kNotInsideLink);
 
     m_nonInheritedData.m_effectiveDisplay =
         m_nonInheritedData.m_originalDisplay =
@@ -2592,7 +2593,7 @@
     return static_cast<EInsideLink>(m_inheritedData.m_insideLink);
   }
   void setInsideLink(EInsideLink insideLink) {
-    m_inheritedData.m_insideLink = insideLink;
+    m_inheritedData.m_insideLink = static_cast<unsigned>(insideLink);
   }
 
   bool hasExplicitlyInheritedProperties() const {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 3df5a14..c9f8b42 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -405,7 +405,11 @@
   None
 };
 
-enum EInsideLink { NotInsideLink, InsideUnvisitedLink, InsideVisitedLink };
+enum class EInsideLink : unsigned {
+  kNotInsideLink,
+  kInsideUnvisitedLink,
+  kInsideVisitedLink
+};
 
 enum ETransformStyle3D { TransformStyle3DFlat, TransformStyle3DPreserve3D };
 
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index de42787..13a11e8 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -424,7 +424,8 @@
   // FIXME: Is it a privacy violation to expose visited information to
   // accessibility APIs?
   return m_layoutObject->style()->isLink() &&
-         m_layoutObject->style()->insideLink() == InsideVisitedLink;
+         m_layoutObject->style()->insideLink() ==
+             EInsideLink::kInsideVisitedLink;
 }
 
 //
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
index 38d19c5..ff45c6d 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.cpp
@@ -124,7 +124,7 @@
 
   // If the resolver is not in the set of ActiveAlgorithms then the frame
   // disconnected so we reject.
-  if (!gatt()->RemoveFromActiveAlgorithms(resolver)) {
+  if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->reject(
         DOMException::create(NetworkError, kGATTServerDisconnected));
     return;
@@ -143,13 +143,14 @@
 ScriptPromise BluetoothRemoteGATTCharacteristic::readValue(
     ScriptState* scriptState) {
   // We always check that the device is connected.
-  if (!gatt()->connected()) {
+  if (!getGatt()->connected()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(NetworkError, kGATTServerNotConnected));
   }
 
-  if (!gatt()->device()->isValidCharacteristic(m_characteristic->instance_id)) {
+  if (!getGatt()->device()->isValidCharacteristic(
+          m_characteristic->instance_id)) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(InvalidStateError, kInvalidCharacteristic));
@@ -157,7 +158,7 @@
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
-  gatt()->AddToActiveAlgorithms(resolver);
+  getGatt()->AddToActiveAlgorithms(resolver);
 
   mojom::blink::WebBluetoothService* service = m_device->bluetooth()->service();
   service->RemoteCharacteristicReadValue(
@@ -179,7 +180,7 @@
 
   // If the resolver is not in the set of ActiveAlgorithms then the frame
   // disconnected so we reject.
-  if (!gatt()->RemoveFromActiveAlgorithms(resolver)) {
+  if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->reject(
         DOMException::create(NetworkError, kGATTServerDisconnected));
     return;
@@ -197,13 +198,14 @@
     ScriptState* scriptState,
     const DOMArrayPiece& value) {
   // We always check that the device is connected.
-  if (!gatt()->connected()) {
+  if (!getGatt()->connected()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(NetworkError, kGATTServerNotConnected));
   }
 
-  if (!gatt()->device()->isValidCharacteristic(m_characteristic->instance_id)) {
+  if (!getGatt()->device()->isValidCharacteristic(
+          m_characteristic->instance_id)) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(InvalidStateError, kInvalidCharacteristic));
@@ -226,7 +228,7 @@
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
-  gatt()->AddToActiveAlgorithms(resolver);
+  getGatt()->AddToActiveAlgorithms(resolver);
 
   mojom::blink::WebBluetoothService* service = m_device->bluetooth()->service();
   service->RemoteCharacteristicWriteValue(
@@ -247,7 +249,7 @@
 
   // If the resolver is not in the set of ActiveAlgorithms then the frame
   // disconnected so we reject.
-  if (!gatt()->RemoveFromActiveAlgorithms(resolver)) {
+  if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) {
     resolver->reject(
         DOMException::create(NetworkError, kGATTServerDisconnected));
     return;
@@ -263,13 +265,14 @@
 ScriptPromise BluetoothRemoteGATTCharacteristic::startNotifications(
     ScriptState* scriptState) {
   // We always check that the device is connected.
-  if (!gatt()->connected()) {
+  if (!getGatt()->connected()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(NetworkError, kGATTServerNotConnected));
   }
 
-  if (!gatt()->device()->isValidCharacteristic(m_characteristic->instance_id)) {
+  if (!getGatt()->device()->isValidCharacteristic(
+          m_characteristic->instance_id)) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(InvalidStateError, kInvalidCharacteristic));
@@ -277,7 +280,7 @@
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
-  gatt()->AddToActiveAlgorithms(resolver);
+  getGatt()->AddToActiveAlgorithms(resolver);
 
   mojom::blink::WebBluetoothService* service = m_device->bluetooth()->service();
   service->RemoteCharacteristicStartNotifications(
@@ -292,13 +295,14 @@
 ScriptPromise BluetoothRemoteGATTCharacteristic::stopNotifications(
     ScriptState* scriptState) {
   // We always check that the device is connected.
-  if (!gatt()->connected()) {
+  if (!getGatt()->connected()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(NetworkError, kGATTServerNotConnected));
   }
 
-  if (!gatt()->device()->isValidCharacteristic(m_characteristic->instance_id)) {
+  if (!getGatt()->device()->isValidCharacteristic(
+          m_characteristic->instance_id)) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(InvalidStateError, kInvalidCharacteristic));
@@ -306,7 +310,7 @@
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
-  gatt()->AddToActiveAlgorithms(resolver);
+  getGatt()->AddToActiveAlgorithms(resolver);
 
   mojom::blink::WebBluetoothService* service = m_device->bluetooth()->service();
   service->RemoteCharacteristicStopNotifications(
@@ -357,13 +361,14 @@
     ScriptState* scriptState,
     mojom::blink::WebBluetoothGATTQueryQuantity quantity,
     const String& descriptor) {
-  if (!gatt()->connected()) {
+  if (!getGatt()->connected()) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(NetworkError, kGATTServerNotConnected));
   }
 
-  if (!gatt()->device()->isValidCharacteristic(m_characteristic->instance_id)) {
+  if (!getGatt()->device()->isValidCharacteristic(
+          m_characteristic->instance_id)) {
     return ScriptPromise::rejectWithDOMException(
         scriptState,
         DOMException::create(InvalidStateError, kInvalidCharacteristic));
@@ -371,7 +376,7 @@
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
-  gatt()->AddToActiveAlgorithms(resolver);
+  getGatt()->AddToActiveAlgorithms(resolver);
 
   mojom::blink::WebBluetoothService* service = m_device->bluetooth()->service();
   WTF::Optional<String> uuid = WTF::nullopt;
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.h
index 5731f0f9..c4aaabd 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.h
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTCharacteristic.h
@@ -102,7 +102,7 @@
  private:
   friend class BluetoothRemoteGATTDescriptor;
 
-  BluetoothRemoteGATTServer* gatt() { return m_service->device()->gatt(); }
+  BluetoothRemoteGATTServer* getGatt() { return m_service->device()->gatt(); }
 
   void ReadValueCallback(ScriptPromiseResolver*,
                          mojom::blink::WebBluetoothResult,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h
index 59cab16..6a2fc29 100644
--- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h
+++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h
@@ -53,7 +53,7 @@
  private:
   friend class DescriptorReadValueCallback;
 
-  BluetoothRemoteGATTServer* getGatt() { return m_characteristic->gatt(); }
+  BluetoothRemoteGATTServer* getGatt() { return m_characteristic->getGatt(); }
 
   mojom::blink::WebBluetoothRemoteGATTDescriptorPtr m_descriptor;
   Member<BluetoothRemoteGATTCharacteristic> m_characteristic;
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
index b4be242..cda9d72b 100644
--- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
@@ -1174,6 +1174,10 @@
 
   validateStateStack();
 
+  willDrawImage(imageSource);
+
+  validateStateStack();
+
   // Heuristic for disabling acceleration based on anticipated texture upload
   // overhead.
   // See comments in ExpensiveCanvasHeuristicParameters.h for explanation.
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
index 281f1d5..9ac6534d 100644
--- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.h
@@ -242,6 +242,8 @@
 
   virtual ColorBehavior drawImageColorBehavior() const = 0;
 
+  virtual void willDrawImage(CanvasImageSource*) const {}
+
   void restoreMatrixClipStack(SkCanvas*) const;
 
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
index 37fc6a6..080321b 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -90,7 +90,7 @@
   explicit CanvasRenderingContext2DAutoRestoreSkCanvas(
       CanvasRenderingContext2D* context)
       : m_context(context), m_saveCount(0) {
-    ASSERT(m_context);
+    DCHECK(m_context);
     SkCanvas* c = m_context->drawingCanvas();
     if (c) {
       m_saveCount = c->getSaveCount();
@@ -195,7 +195,7 @@
     return;
   // This code path is for restoring from an eviction
   // Restoring from surface failure is handled internally
-  ASSERT(m_contextLostMode != NotLostContext && !canvas()->hasImageBuffer());
+  DCHECK(m_contextLostMode != NotLostContext && !canvas()->hasImageBuffer());
 
   if (canvas()->buffer()) {
     if (contextLostRestoredEventsEnabled()) {
@@ -268,6 +268,10 @@
   }
 }
 
+void CanvasRenderingContext2D::willDrawImage(CanvasImageSource* source) const {
+  canvas()->willDrawImageTo2DContext(source);
+}
+
 ColorBehavior CanvasRenderingContext2D::drawImageColorBehavior() const {
   return CanvasRenderingContext::colorBehaviorForMediaDrawnToCanvas();
 }
@@ -452,7 +456,7 @@
     HashMap<String, Font>::iterator i =
         m_fontsResolvedUsingCurrentStyle.find(newFont);
     if (i != m_fontsResolvedUsingCurrentStyle.end()) {
-      ASSERT(m_fontLRUList.contains(newFont));
+      DCHECK(m_fontLRUList.contains(newFont));
       m_fontLRUList.remove(newFont);
       m_fontLRUList.add(newFont);
       modifiableState().setFont(
@@ -474,7 +478,7 @@
       canvas()->document().ensureStyleResolver().computeFont(fontStyle.get(),
                                                              *parsedStyle);
       m_fontsResolvedUsingCurrentStyle.add(newFont, fontStyle->font());
-      ASSERT(!m_fontLRUList.contains(newFont));
+      DCHECK(!m_fontLRUList.contains(newFont));
       m_fontLRUList.add(newFont);
       pruneLocalFontCache(canvasFontCache->hardMaxFonts());  // hard limit
       schedulePruneLocalFontCacheIfNeeded();                 // soft limit
@@ -682,7 +686,7 @@
     case CanvasRenderingContext2DState::DirectionLTR:
       return TextDirection::kLtr;
   }
-  ASSERT_NOT_REACHED();
+  NOTREACHED();
   return TextDirection::kLtr;
 }
 
@@ -829,9 +833,10 @@
   // anti-aliasing, which is expected when !creationAttributes().alpha(), so we
   // need to fall out of display list mode when drawing text to an opaque
   // canvas. crbug.com/583809
-  if (!creationAttributes().alpha() && !isAccelerated())
+  if (!creationAttributes().alpha() && !isAccelerated()) {
     canvas()->disableDeferral(
         DisableDeferralReasonSubPixelTextAntiAliasingSupport);
+  }
 
   const Font& font = accessFont();
   font.getFontDescription().setSubpixelAscentDescent(true);
@@ -1003,7 +1008,7 @@
 
 bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path,
                                                     Element* element) {
-  ASSERT(element);
+  DCHECK(element);
   if (!state().isTransformInvertible())
     return false;
   if (path.isEmpty())
@@ -1090,9 +1095,10 @@
 
   if (state().hasClip()) {
     hitRegionPath.intersectPath(state().getCurrentClipPath());
-    if (hitRegionPath.isEmpty())
+    if (hitRegionPath.isEmpty()) {
       exceptionState.throwDOMException(NotSupportedError,
                                        "The specified path has no pixels.");
+    }
   }
 
   if (!m_hitRegionManager)
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h
index 2740912..ae240f1a 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.h
@@ -199,6 +199,8 @@
 
   ColorBehavior drawImageColorBehavior() const final;
 
+  void willDrawImage(CanvasImageSource*) const final;
+
  private:
   friend class CanvasRenderingContext2DAutoRestoreSkCanvas;
 
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index 43a45fe..59ebdfbb 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -1007,44 +1007,6 @@
       savedFixedRenderingMode);
 }
 
-TEST_F(CanvasRenderingContext2DTest,
-       PreferNoAccelerationHintDisablesAcceleration) {
-  bool savedFixedRenderingMode =
-      RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled();
-  RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(false);
-
-  createContext(NonOpaque);
-  FakeGLES2Interface gl;
-  std::unique_ptr<FakeWebGraphicsContext3DProvider> contextProvider(
-      new FakeWebGraphicsContext3DProvider(&gl));
-  IntSize size(300, 300);
-  RefPtr<Canvas2DLayerBridge> bridge =
-      makeBridge(std::move(contextProvider), size,
-                 Canvas2DLayerBridge::EnableAcceleration);
-  std::unique_ptr<Canvas2DImageBufferSurface> surface(
-      new Canvas2DImageBufferSurface(bridge, size));
-  canvasElement().createImageBufferUsingSurfaceForTesting(std::move(surface));
-
-  EXPECT_TRUE(canvasElement().buffer()->isAccelerated());
-  SourceImageStatus status = InvalidSourceImageStatus;
-  canvasElement().getSourceImageForCanvas(
-      &status, PreferNoAcceleration, SnapshotReasonUnitTests, FloatSize(size));
-  EXPECT_EQ(NormalSourceImageStatus, status);
-  if (ExpensiveCanvasHeuristicParameters::DisableAccelerationToAvoidReadbacks) {
-    EXPECT_FALSE(canvasElement().buffer()->isAccelerated());
-    EXPECT_EQ(0u, getGlobalAcceleratedImageBufferCount());
-    EXPECT_EQ(0, getGlobalGPUMemoryUsage());
-  } else {
-    EXPECT_TRUE(canvasElement().buffer()->isAccelerated());
-    EXPECT_EQ(1u, getGlobalAcceleratedImageBufferCount());
-    EXPECT_EQ(720000, getGlobalGPUMemoryUsage());
-  }
-
-  // Restore global state to prevent side-effects on other tests
-  RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(
-      savedFixedRenderingMode);
-}
-
 TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) {
   bool savedFixedRenderingMode =
       RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled();
diff --git a/third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp b/third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp
index 25c7a74..f58d57c 100644
--- a/third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp
+++ b/third_party/WebKit/Source/modules/fetch/GlobalFetch.cpp
@@ -40,7 +40,8 @@
                       const RequestInfo& input,
                       const Dictionary& init,
                       ExceptionState& exceptionState) override {
-    if (!scriptState->contextIsValid()) {
+    ExecutionContext* executionContext = m_fetchManager->getExecutionContext();
+    if (!scriptState->contextIsValid() || !executionContext) {
       // TODO(yhirano): Should this be moved to bindings?
       exceptionState.throwTypeError("The global scope is shutting down.");
       return ScriptPromise();
@@ -53,10 +54,8 @@
     if (exceptionState.hadException())
       return ScriptPromise();
 
-    if (ExecutionContext* executionContext =
-            m_fetchManager->getExecutionContext())
-      InspectorInstrumentation::willSendXMLHttpOrFetchNetworkRequest(
-          executionContext, r->url());
+    InspectorInstrumentation::willSendXMLHttpOrFetchNetworkRequest(
+        executionContext, r->url());
     return m_fetchManager->fetch(scriptState, r->passRequestData(scriptState));
   }
 
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 3f892ec..85aa7103 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -219,7 +219,7 @@
 ScrollTopLeftInterop status=experimental
 Sensor status=experimental
 ServiceWorkerNavigationPreload origin_trial_feature_name=ServiceWorkerNavigationPreload
-SetRootScroller status=experimental
+SetRootScroller status=experimental, origin_trial_feature_name=RootScroller
 ShadowPiercingDescendantCombinator status=experimental
 ShapeDetection status=experimental
 SharedArrayBuffer
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index 5ad87f8..0efabea5 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -785,19 +785,24 @@
 }
 
 void Canvas2DLayerBridge::flush() {
-  if (!getOrCreateSurface())
+  if (!m_didDrawSinceLastFlush)
     return;
   TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
+  if (!getOrCreateSurface())
+    return;
   flushRecordingOnly();
   getOrCreateSurface()->getCanvas()->flush();
+  m_didDrawSinceLastFlush = false;
 }
 
 void Canvas2DLayerBridge::flushGpu() {
-  TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushGpu");
   flush();
   gpu::gles2::GLES2Interface* gl = contextGL();
-  if (isAccelerated() && gl)
+  if (isAccelerated() && gl && m_didDrawSinceLastGpuFlush) {
+    TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushGpu");
     gl->Flush();
+    m_didDrawSinceLastGpuFlush = false;
+  }
 }
 
 gpu::gles2::GLES2Interface* Canvas2DLayerBridge::contextGL() {
@@ -1053,6 +1058,8 @@
     Platform::current()->currentThread()->addTaskObserver(this);
     m_isRegisteredTaskObserver = true;
   }
+  m_didDrawSinceLastFlush = true;
+  m_didDrawSinceLastGpuFlush = true;
 }
 
 void Canvas2DLayerBridge::prepareSurfaceForPaintingIfNeeded() {
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
index faf0123..0ba1285a 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
@@ -144,6 +144,8 @@
   sk_sp<SkColorSpace> colorSpace() const { return m_colorSpace; }
   SkColorType colorType() const { return m_colorType; }
 
+  bool hasRecordedDrawCommands() { return m_haveRecordedDrawCommands; }
+
   sk_sp<SkImage> newImageSnapshot(AccelerationHint, SnapshotReason);
 
   // The values of the enum entries must not change because they are used for
@@ -266,6 +268,8 @@
   bool m_surfaceCreationFailedAtLeastOnce = false;
   bool m_hibernationScheduled = false;
   bool m_dontUseIdleSchedulingForTesting = false;
+  bool m_didDrawSinceLastFlush = false;
+  bool m_didDrawSinceLastGpuFlush = false;
 
   friend class Canvas2DLayerBridgeTest;
   friend class CanvasRenderingContext2DTest;
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
index aeb1bfd..40a2e40a 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -1311,4 +1311,65 @@
   EXPECT_EQ(1u, gl.destroyImageCount());
 }
 
+class FlushMockGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
+ public:
+  MOCK_METHOD0(Flush, void());
+};
+
+TEST_F(Canvas2DLayerBridgeTest, NoUnnecessaryFlushes) {
+  FlushMockGLES2Interface gl;
+  std::unique_ptr<FakeWebGraphicsContext3DProvider> contextProvider =
+      WTF::wrapUnique(new FakeWebGraphicsContext3DProvider(&gl));
+
+  EXPECT_CALL(gl, Flush()).Times(0);
+  Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(
+      std::move(contextProvider), IntSize(300, 150), 0, NonOpaque,
+      Canvas2DLayerBridge::ForceAccelerationForTesting, nullptr,
+      kN32_SkColorType)));
+  EXPECT_FALSE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  EXPECT_CALL(gl, Flush()).Times(0);
+  bridge->didDraw(FloatRect(0, 0, 1, 1));
+  EXPECT_TRUE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  EXPECT_CALL(gl, Flush()).Times(1);
+  bridge->flushGpu();
+  EXPECT_FALSE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  EXPECT_CALL(gl, Flush()).Times(0);
+  bridge->didDraw(FloatRect(0, 0, 1, 1));
+  EXPECT_TRUE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  EXPECT_CALL(gl, Flush()).Times(1);
+  bridge->flushGpu();
+  EXPECT_FALSE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  // No flush because already flushed since last draw
+  EXPECT_CALL(gl, Flush()).Times(0);
+  bridge->flushGpu();
+  EXPECT_FALSE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  EXPECT_CALL(gl, Flush()).Times(0);
+  bridge->didDraw(FloatRect(0, 0, 1, 1));
+  EXPECT_TRUE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  // Flushes recording, but not the gpu
+  EXPECT_CALL(gl, Flush()).Times(0);
+  bridge->flush();
+  EXPECT_FALSE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+
+  EXPECT_CALL(gl, Flush()).Times(1);
+  bridge->flushGpu();
+  EXPECT_FALSE(bridge->hasRecordedDrawCommands());
+  ::testing::Mock::VerifyAndClearExpectations(&gl);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h b/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
index b9c71588..3fbcba25 100644
--- a/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
+++ b/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
@@ -60,20 +60,11 @@
   // lists. Rationale: The allocation of large textures for canvas
   // tends to starve the compositor, and increase the probability of
   // failure of subsequent allocations required for double buffering.
-  PreferDisplayListOverGpuSizeThreshold = 4096 * 4096,
+  PreferDisplayListOverGpuSizeThreshold = 8096 * 4096,
 
   // Disable Acceleration heuristic parameters
   //===========================================
 
-  GetImageDataForcesNoAcceleration = 1,
-
-  // When a canvas is used as a source image, if its destination is
-  // non-accelerated and the source canvas is accelerated, a readback
-  // from the gpu is necessary. This option causes the source canvas to
-  // switch to non-accelerated when this situation is encountered to
-  // prevent future canvas-to-canvas draws from requiring a readback.
-  DisableAccelerationToAvoidReadbacks = 1,
-
   // When drawing very large images to canvases, there is a point where
   // GPU acceleration becomes inefficient due to texture upload overhead,
   // especially when the image is large enough that it is likely to
@@ -84,6 +75,27 @@
   DrawImageTextureUploadSoftSizeLimitScaleThreshold = 4,
   DrawImageTextureUploadHardSizeLimit = 8192 * 8192,
 
+  // GPU readback prevention heuristics
+  //====================================
+
+  GetImageDataForcesNoAcceleration = 1,
+
+  // When a canvas is used as a source image, if its destination is
+  // non-accelerated and the source canvas is accelerated, a readback
+  // from the gpu is necessary. This option causes the source canvas to
+  // switch to non-accelerated when this situation is encountered to
+  // prevent future canvas-to-canvas draws from requiring a readback.
+  DisableAccelerationToAvoidReadbacks = 0,
+
+  // See description of DisableAccelerationToAvoidReadbacks. This is the
+  // opposite strategy : accelerate the destination canvas. If both
+  // EnableAccelerationToAvoidReadbacks and
+  // DisableAccelerationToAvoidReadbacks are specified, we try to enable
+  // acceleration on the destination first. If that does not succeed,
+  // we disable acceleration on the source canvas. Either way, future
+  // readbacks are prevented.
+  EnableAccelerationToAvoidReadbacks = 1,
+
 };  // enum
 
 // Constants and Coefficients for 2D Canvas Dynamic Rendering Mode Switching
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
index 4982dd7..493a379 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -146,16 +146,6 @@
   return m_client ? m_client->isDirty() : false;
 }
 
-void ImageBuffer::didDisableAcceleration() const {
-  DCHECK(m_gpuMemoryUsage);
-  DCHECK_GT(s_globalAcceleratedImageBufferCount, 0u);
-  if (m_client)
-    m_client->didDisableAcceleration();
-  s_globalAcceleratedImageBufferCount--;
-  s_globalGPUMemoryUsage -= m_gpuMemoryUsage;
-  m_gpuMemoryUsage = 0;
-}
-
 void ImageBuffer::didFinalizeFrame() {
   if (m_client)
     m_client->didFinalizeFrame();
@@ -367,8 +357,9 @@
   DCHECK(canvas());
 
   if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration &&
-      !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled())
+      !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) {
     const_cast<ImageBuffer*>(this)->disableAcceleration();
+  }
 
   sk_sp<SkImage> snapshot = m_surface->newImageSnapshot(
       PreferNoAcceleration, SnapshotReasonGetImageData);
@@ -442,22 +433,22 @@
   if (!isSurfaceValid())
     return;
 
-  ASSERT(sourceRect.width() > 0);
-  ASSERT(sourceRect.height() > 0);
+  DCHECK_GT(sourceRect.width(), 0);
+  DCHECK_GT(sourceRect.height(), 0);
 
   int originX = sourceRect.x();
   int destX = destPoint.x() + sourceRect.x();
-  ASSERT(destX >= 0);
-  ASSERT(destX < m_surface->size().width());
-  ASSERT(originX >= 0);
-  ASSERT(originX < sourceRect.maxX());
+  DCHECK_GE(destX, 0);
+  DCHECK_LT(destX, m_surface->size().width());
+  DCHECK_GE(originX, 0);
+  DCHECK_LT(originX, sourceRect.maxX());
 
   int originY = sourceRect.y();
   int destY = destPoint.y() + sourceRect.y();
-  ASSERT(destY >= 0);
-  ASSERT(destY < m_surface->size().height());
-  ASSERT(originY >= 0);
-  ASSERT(originY < sourceRect.maxY());
+  DCHECK_GE(destY, 0);
+  DCHECK_LT(destY, m_surface->size().height());
+  DCHECK_GE(originY, 0);
+  DCHECK_LT(originY, sourceRect.maxY());
 
   const size_t srcBytesPerRow = 4 * sourceSize.width();
   const void* srcAddr = source + originY * srcBytesPerRow + originX * 4;
@@ -492,6 +483,9 @@
     s_globalAcceleratedImageBufferCount--;
     s_globalGPUMemoryUsage -= m_gpuMemoryUsage;
     m_gpuMemoryUsage = 0;
+
+    if (m_client)
+      m_client->didDisableAcceleration();
   }
 }
 
@@ -519,12 +513,6 @@
   if (!isAccelerated())
     return;
 
-  sk_sp<SkImage> image =
-      m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonPaint);
-  // Using a GPU-backed image with RecordingImageBufferSurface
-  // will fail at playback time.
-  image = image->makeNonTextureImage();
-
   // Create and configure a recording (unaccelerated) surface.
   std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory =
       WTF::makeUnique<UnacceleratedSurfaceFactory>();
@@ -532,13 +520,26 @@
       WTF::wrapUnique(new RecordingImageBufferSurface(
           m_surface->size(), std::move(surfaceFactory),
           m_surface->getOpacityMode(), m_surface->colorSpace()));
+  setSurface(std::move(surface));
+}
+
+void ImageBuffer::setSurface(std::unique_ptr<ImageBufferSurface> surface) {
+  sk_sp<SkImage> image =
+      m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonPaint);
+
+  if (surface->isRecording()) {
+    // Using a GPU-backed image with RecordingImageBufferSurface
+    // will fail at playback time.
+    image = image->makeNonTextureImage();
+  }
+
   surface->canvas()->drawImage(image.get(), 0, 0);
   surface->setImageBuffer(this);
   if (m_client)
     m_client->restoreCanvasMatrixClipStack(surface->canvas());
   m_surface = std::move(surface);
 
-  didDisableAcceleration();
+  updateGPUMemoryUsage();
 }
 
 bool ImageDataBuffer::encodeImage(const String& mimeType,
@@ -556,7 +557,7 @@
   } else {
     if (!PNGImageEncoder::encode(*this, encodedImage))
       return false;
-    ASSERT(mimeType == "image/png");
+    DCHECK_EQ(mimeType, "image/png");
   }
 
   return true;
@@ -564,7 +565,7 @@
 
 String ImageDataBuffer::toDataURL(const String& mimeType,
                                   const double& quality) const {
-  ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+  DCHECK(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
   Vector<unsigned char> result;
   if (!encodeImage(mimeType, quality, &result))
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
index 435e534..4fed4e1 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
@@ -101,7 +101,6 @@
   bool wasDrawnToAfterSnapshot() const {
     return m_snapshotState == DrawnToAfterSnapshot;
   }
-  void didDisableAcceleration() const;
 
   void setFilterQuality(SkFilterQuality filterQuality) {
     m_surface->setFilterQuality(filterQuality);
@@ -182,6 +181,7 @@
   intptr_t getGPUMemoryUsage() { return m_gpuMemoryUsage; }
 
   void disableAcceleration();
+  void setSurface(std::unique_ptr<ImageBufferSurface>);
 
   WeakPtrFactory<ImageBuffer> m_weakPtrFactory;
 
diff --git a/third_party/WebKit/Source/platform/text/BidiCharacterRun.h b/third_party/WebKit/Source/platform/text/BidiCharacterRun.h
index 95306b4..f8f839c 100644
--- a/third_party/WebKit/Source/platform/text/BidiCharacterRun.h
+++ b/third_party/WebKit/Source/platform/text/BidiCharacterRun.h
@@ -60,6 +60,13 @@
     }
   }
 
+  BidiCharacterRun(int start, int stop, unsigned char level)
+      : m_override(false),
+        m_level(level),
+        m_next(0),
+        m_start(start),
+        m_stop(stop) {}
+
   // BidiCharacterRun are allocated out of the rendering partition.
   PLATFORM_EXPORT void* operator new(size_t);
   PLATFORM_EXPORT void operator delete(void*);
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.cpp b/third_party/WebKit/Source/wtf/text/WTFString.cpp
index 3b04de8..0cfe473 100644
--- a/third_party/WebKit/Source/wtf/text/WTFString.cpp
+++ b/third_party/WebKit/Source/wtf/text/WTFString.cpp
@@ -42,6 +42,31 @@
 
 using namespace Unicode;
 
+namespace {
+
+Vector<char> asciiDebug(StringImpl* impl) {
+  if (!impl)
+    return asciiDebug(String("[null]").impl());
+
+  Vector<char> buffer;
+  for (unsigned i = 0; i < impl->length(); ++i) {
+    UChar ch = (*impl)[i];
+    if (isASCIIPrintable(ch)) {
+      if (ch == '\\')
+        buffer.push_back('\\');
+      buffer.push_back(static_cast<char>(ch));
+    } else {
+      buffer.push_back('\\');
+      buffer.push_back('u');
+      appendUnsignedAsHexFixedSize(ch, buffer, 4);
+    }
+  }
+  buffer.push_back('\0');
+  return buffer;
+}
+
+}  // namespace
+
 // Construct a string with UTF-16 data.
 String::String(const UChar* characters, unsigned length)
     : m_impl(characters ? StringImpl::create(characters, length) : nullptr) {}
@@ -811,46 +836,10 @@
   return out << '"';
 }
 
-}  // namespace WTF
-
 #ifndef NDEBUG
-// For use in the debugger
-String* string(const char*);
-Vector<char> asciiDebug(StringImpl*);
-Vector<char> asciiDebug(String&);
-
 void String::show() const {
   dataLogF("%s\n", asciiDebug(impl()).data());
 }
-
-String* string(const char* s) {
-  // leaks memory!
-  return new String(s);
-}
-
-Vector<char> asciiDebug(StringImpl* impl) {
-  if (!impl)
-    return asciiDebug(String("[null]").impl());
-
-  Vector<char> buffer;
-  for (unsigned i = 0; i < impl->length(); ++i) {
-    UChar ch = (*impl)[i];
-    if (isASCIIPrintable(ch)) {
-      if (ch == '\\')
-        buffer.push_back('\\');
-      buffer.push_back(static_cast<char>(ch));
-    } else {
-      buffer.push_back('\\');
-      buffer.push_back('u');
-      appendUnsignedAsHexFixedSize(ch, buffer, 4);
-    }
-  }
-  buffer.push_back('\0');
-  return buffer;
-}
-
-Vector<char> asciiDebug(String& string) {
-  return asciiDebug(string.impl());
-}
-
 #endif
+
+}  // namespace WTF
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.h b/third_party/WebKit/Source/wtf/text/WTFString.h
index db63892..6fe8763 100644
--- a/third_party/WebKit/Source/wtf/text/WTFString.h
+++ b/third_party/WebKit/Source/wtf/text/WTFString.h
@@ -426,6 +426,7 @@
   }
 
 #ifndef NDEBUG
+  // For use in the debugger.
   void show() const;
 #endif
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index 09d8d60..a041526 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -264,11 +264,12 @@
             optparse.make_option(
                 "--child-processes",
                 help="Number of drivers to run in parallel."),
+            # TODO(tkent): Remove --enable-wptserve.
             optparse.make_option(
                 "--enable-wptserve",
                 dest="enable_wptserve",
                 action="store_true",
-                default=False,
+                default=True,
                 help="Enable running web-platform-tests using WPTserve instead of Apache."),
             optparse.make_option(
                 "--disable-breakpad",
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 5ff826f91..7d4422f1 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4210,6 +4210,11 @@
     in canvas.toBlob. When the encoding idle task is delayed for longer than
     IdleTaskCompleteTimeoutDelay, the browser will switch to a non-idle task to
     force encoding to happen on the main thread.
+
+    In addition, metric values from OffscreenCanvas.convertToBlob API call are
+    also gathered into this histogram, because the logic flow is exactly the
+    same as canvas.toBlob. It's worth to note that the values can come from idle
+    tasks on either main or worker thread.
   </summary>
 </histogram>
 
@@ -4218,6 +4223,11 @@
   <owner>xlai@chromium.org</owner>
   <summary>
     Records the status of the idle task when finishing a toBlob call.
+
+    In addition, metric values from OffscreenCanvas.convertToBlob API call are
+    also gathered into this histogram, because the logic flow is exactly the
+    same as canvas.toBlob. It's worth to note that the values can come from idle
+    tasks on either main or worker thread.
   </summary>
 </histogram>
 
@@ -4234,13 +4244,25 @@
     canvas.toBlob. When the initialization idle task is delayed for longer than
     IdleTaskStartTimeoutDelay, the browser will switch to a non-idle task to
     force initialization and encoding to occur on the main thread.
+
+    In addition, metric values from OffscreenCanvas.convertToBlob API call are
+    also gathered into this histogram, because the logic flow is exactly the
+    same as canvas.toBlob. It's worth to note that the values can come from idle
+    tasks on either main or worker thread.
   </summary>
 </histogram>
 
 <histogram name="Blink.Canvas.ToBlobDuration" units="microseconds">
   <owner>junov@chromium.org</owner>
   <owner>xlai@chromium.org</owner>
-  <summary>Time spent on 2D canvas toBlob API call.</summary>
+  <summary>
+    Time spent on 2D canvas toBlob API call.
+
+    In addition, metric values from OffscreenCanvas.convertToBlob API call are
+    also gathered into this histogram, because the logic flow is exactly the
+    same as canvas.toBlob. It's worth to note that the values can come from idle
+    tasks on either main or worker thread.
+  </summary>
 </histogram>
 
 <histogram name="Blink.Canvas.ToDataURL" units="microseconds">
@@ -24151,6 +24173,14 @@
   <summary>Records the autoplay source of audios.</summary>
 </histogram>
 
+<histogram name="Media.Audio.Capture.CallbackError" enum="BooleanError">
+  <owner>tommi@chromium.org</owner>
+  <summary>
+    A boolean that reflects whether or not an error was reported during audio
+    capture.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.Capture.FramesProvided" units="frames">
   <owner>grunell@chromium.org</owner>
   <summary>
@@ -48749,6 +48779,22 @@
   </summary>
 </histogram>
 
+<histogram name="Power.ConnectedChargingPorts"
+    enum="PowerConnectedChargingPorts">
+  <owner>bleung@chromium.org</owner>
+  <owner>derat@chromium.org</owner>
+  <summary>
+    Connected charging ports on Chrome OS. A sample is reported every time that
+    the power manager polls sysfs (typically every 30 seconds). Ordinals are
+    assigned based on the lexicographical ordering of power supply names from
+    sysfs and have no implied correspondence with ports' physical locations. For
+    example, with ports 'CROS_USB_PD_CHARGER0' and 'CROS_USB_PD_CHARGER1',
+    'first' refers to the former and 'second' to the latter. To determine a
+    port's physical location, see the powerd charging_ports pref in the device's
+    overlay.
+  </summary>
+</histogram>
+
 <histogram name="Power.DarkResumeWakeDurationMs" units="ms">
   <owner>chirantan@chromium.org</owner>
   <summary>
@@ -84166,6 +84212,9 @@
   <int value="55" label="AD policy fetch fail">
     Active Directory policy fetch failed.
   </int>
+  <int value="56" label="Store DM token failed">
+    Failed to store DM token into the local state.
+  </int>
 </enum>
 
 <enum name="EnterprisePolicies" type="int">
@@ -100453,6 +100502,17 @@
   <int value="4" label="Safe Spring Charger"/>
 </enum>
 
+<enum name="PowerConnectedChargingPorts" type="int">
+  <summary>
+    Connected charging ports on Chrome OS, as reported by the kernel.
+  </summary>
+  <int value="0" label="No ports connected"/>
+  <int value="1" label="First port connected"/>
+  <int value="2" label="Second port connected"/>
+  <int value="3" label="First and second ports connected"/>
+  <int value="4" label="More than two ports exist"/>
+</enum>
+
 <enum name="PowerSupplyType" type="int">
   <summary>
     The type of power supply connected to a Chrome OS system, as reported by the
@@ -109834,6 +109894,8 @@
   <suffix name="toDataURL" label="Image formats passed to canvas.toDataURL"/>
   <suffix name="toBlobCallback"
       label="Image formats passed to canvas.toBlob (callback)"/>
+  <suffix name="convertToBlobPromise"
+      label="Image formats passed to OffscreenCanvas.convertToBlob (promise)"/>
   <affected-histogram name="Canvas.RequestedImageMimeTypes"/>
 </histogram_suffixes>
 
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index 2331252..b9d1a27 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -198,8 +198,7 @@
   SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
 
 
-@decorators.Disabled('win',  # crbug.com/662971
-                     'mac')  # crbug.com/663025
+@decorators.Disabled('win')  # crbug.com/662971
 class TwitterDesktopStory(_NewsBrowsingStory):
   NAME = 'browse:social:twitter'
   URL = 'https://www.twitter.com/nasa'
diff --git a/ui/aura/mus/input_method_mus.cc b/ui/aura/mus/input_method_mus.cc
index fdce898..230dfff 100644
--- a/ui/aura/mus/input_method_mus.cc
+++ b/ui/aura/mus/input_method_mus.cc
@@ -92,9 +92,8 @@
     UpdateTextInputType();
   InputMethodBase::OnTextInputTypeChanged(client);
 
-  if (input_method_) {
+  if (input_method_)
     input_method_->OnTextInputTypeChanged(client->GetTextInputType());
-  }
 }
 
 void InputMethodMus::OnCaretBoundsChanged(const ui::TextInputClient* client) {
@@ -124,10 +123,22 @@
   InputMethodBase::OnDidChangeFocusedClient(focused_before, focused);
   UpdateTextInputType();
 
+  // TODO(moshayedi): crbug.com/681563. Handle when there is no focused clients.
+  if (!focused)
+    return;
+
   text_input_client_ = base::MakeUnique<TextInputClientImpl>(focused);
   if (ime_server_) {
-    ime_server_->StartSession(text_input_client_->CreateInterfacePtrAndBind(),
-                              MakeRequest(&input_method_));
+    ui::mojom::StartSessionDetailsPtr details =
+        ui::mojom::StartSessionDetails::New();
+    details->client = text_input_client_->CreateInterfacePtrAndBind();
+    details->input_method_request = MakeRequest(&input_method_);
+    details->text_input_type = focused->GetTextInputType();
+    details->text_input_mode = focused->GetTextInputMode();
+    details->text_direction = focused->GetTextDirection();
+    details->text_input_flags = focused->GetTextInputFlags();
+    details->caret_bounds = focused->GetCaretBounds();
+    ime_server_->StartSession(std::move(details));
   }
 }
 
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index db48036..83a532b 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -1096,7 +1096,7 @@
 }
 
 std::unique_ptr<ui::EventTargetIterator> Window::GetChildIterator() const {
-  return base::MakeUnique<ui::EventTargetIteratorImpl<Window>>(children());
+  return base::MakeUnique<ui::EventTargetIteratorPtrImpl<Window>>(children());
 }
 
 ui::EventTargeter* Window::GetEventTargeter() {
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index 02495f46..4ccccb4 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -158,10 +158,10 @@
 void WindowEventDispatcher::ProcessedTouchEvent(uint32_t unique_event_id,
                                                 Window* window,
                                                 ui::EventResult result) {
-  std::unique_ptr<ui::GestureRecognizer::Gestures> gestures(
+  ui::GestureRecognizer::Gestures gestures =
       ui::GestureRecognizer::Get()->AckTouchEvent(unique_event_id, result,
-                                                  window));
-  DispatchDetails details = ProcessGestures(window, gestures.get());
+                                                  window);
+  DispatchDetails details = ProcessGestures(window, std::move(gestures));
   if (details.dispatcher_destroyed)
     return;
 }
@@ -275,9 +275,9 @@
 
 ui::EventDispatchDetails WindowEventDispatcher::ProcessGestures(
     Window* target,
-    ui::GestureRecognizer::Gestures* gestures) {
+    ui::GestureRecognizer::Gestures gestures) {
   DispatchDetails details;
-  if (!gestures || gestures->empty())
+  if (gestures.empty())
     return details;
 
   // If a window has been hidden between the touch event and now, the associated
@@ -285,10 +285,9 @@
   if (!target)
     return details;
 
-  for (size_t i = 0; i < gestures->size(); ++i) {
-    ui::GestureEvent* event = gestures->get().at(i);
+  for (const auto& event : gestures) {
     event->ConvertLocationToTarget(window(), target);
-    details = DispatchEvent(target, event);
+    details = DispatchEvent(target, event.get());
     if (details.dispatcher_destroyed || details.target_destroyed)
       break;
   }
@@ -486,13 +485,12 @@
       const ui::TouchEvent& touchevent = *event.AsTouchEvent();
 
       if (!touchevent.synchronous_handling_disabled()) {
-        std::unique_ptr<ui::GestureRecognizer::Gestures> gestures;
-
         Window* window = static_cast<Window*>(target);
-        gestures.reset(ui::GestureRecognizer::Get()->AckTouchEvent(
-            touchevent.unique_event_id(), event.result(), window));
+        ui::GestureRecognizer::Gestures gestures =
+            ui::GestureRecognizer::Get()->AckTouchEvent(
+                touchevent.unique_event_id(), event.result(), window);
 
-        return ProcessGestures(window, gestures.get());
+        return ProcessGestures(window, std::move(gestures));
       }
     }
   }
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index b4cfb13..219037c 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -154,7 +154,7 @@
       WARN_UNUSED_RESULT;
   ui::EventDispatchDetails ProcessGestures(
       Window* target,
-      ui::GestureRecognizer::Gestures* gestures) WARN_UNUSED_RESULT;
+      ui::GestureRecognizer::Gestures gestures) WARN_UNUSED_RESULT;
 
   // Called when a window becomes invisible, either by being removed
   // from root window hierarchy, via SetVisible(false) or being destroyed.
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
index 584c1a10..1adb0004 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -846,24 +846,20 @@
                                                 ui::GestureEvent* gesture) {}
 
 void TouchExplorationController::ProcessGestureEvents() {
-  std::unique_ptr<ScopedVector<ui::GestureEvent>> gestures(
-      gesture_provider_->GetAndResetPendingGestures());
-  if (gestures) {
-    for (ScopedVector<GestureEvent>::iterator i = gestures->begin();
-         i != gestures->end();
-         ++i) {
-      if ((*i)->type() == ui::ET_GESTURE_SWIPE &&
-          state_ == GESTURE_IN_PROGRESS) {
-        OnSwipeEvent(*i);
-        // The tap timer to leave gesture state is ended, and we now wait for
-        // all fingers to be released.
-        tap_timer_.Stop();
-        SET_STATE(WAIT_FOR_NO_FINGERS);
-        return;
-      }
-      if (state_ == SLIDE_GESTURE && (*i)->IsScrollGestureEvent()) {
-        SideSlideControl(*i);
-      }
+  std::vector<std::unique_ptr<GestureEvent>> gestures =
+      gesture_provider_->GetAndResetPendingGestures();
+  for (const auto& gesture : gestures) {
+    if (gesture->type() == ui::ET_GESTURE_SWIPE &&
+        state_ == GESTURE_IN_PROGRESS) {
+      OnSwipeEvent(gesture.get());
+      // The tap timer to leave gesture state is ended, and we now wait for
+      // all fingers to be released.
+      tap_timer_.Stop();
+      SET_STATE(WAIT_FOR_NO_FINGERS);
+      return;
+    }
+    if (state_ == SLIDE_GESTURE && gesture->IsScrollGestureEvent()) {
+      SideSlideControl(gesture.get());
     }
   }
 }
diff --git a/ui/events/event_target_iterator.h b/ui/events/event_target_iterator.h
index fe3eca6c..ae83b828 100644
--- a/ui/events/event_target_iterator.h
+++ b/ui/events/event_target_iterator.h
@@ -5,6 +5,7 @@
 #ifndef UI_EVENTS_EVENT_TARGET_ITERATOR_H_
 #define UI_EVENTS_EVENT_TARGET_ITERATOR_H_
 
+#include <memory>
 #include <vector>
 
 namespace ui {
@@ -18,21 +19,19 @@
   virtual EventTarget* GetNextTarget() = 0;
 };
 
-// Provides an EventTargetIterator implementation for iterating over a list of
+// Provides EventTargetIterator implementations for iterating over a list of
 // EventTargets. The list is iterated in the reverse order, since typically the
 // EventTargets are maintained in increasing z-order in the lists.
-template<typename T>
-class EventTargetIteratorImpl : public EventTargetIterator {
+template <typename T>
+class EventTargetIteratorPtrImpl : public EventTargetIterator {
  public:
-  explicit EventTargetIteratorImpl(const std::vector<T*>& children)
-      : begin_(children.rbegin()),
-        end_(children.rend()) {
-  }
-  ~EventTargetIteratorImpl() override {}
+  explicit EventTargetIteratorPtrImpl(const std::vector<T*>& children)
+      : begin_(children.rbegin()), end_(children.rend()) {}
+  ~EventTargetIteratorPtrImpl() override {}
 
   EventTarget* GetNextTarget() override {
     if (begin_ == end_)
-      return NULL;
+      return nullptr;
     EventTarget* target = *(begin_);
     ++begin_;
     return target;
@@ -43,6 +42,27 @@
   typename std::vector<T*>::const_reverse_iterator end_;
 };
 
+template <typename T>
+class EventTargetIteratorUniquePtrImpl : public EventTargetIterator {
+ public:
+  explicit EventTargetIteratorUniquePtrImpl(
+      const std::vector<std::unique_ptr<T>>& children)
+      : begin_(children.rbegin()), end_(children.rend()) {}
+  ~EventTargetIteratorUniquePtrImpl() override {}
+
+  EventTarget* GetNextTarget() override {
+    if (begin_ == end_)
+      return nullptr;
+    EventTarget* target = begin_->get();
+    ++begin_;
+    return target;
+  }
+
+ private:
+  typename std::vector<std::unique_ptr<T>>::const_reverse_iterator begin_;
+  typename std::vector<std::unique_ptr<T>>::const_reverse_iterator end_;
+};
+
 }  // namespace ui
 
 #endif  // UI_EVENTS_EVENT_TARGET_ITERATOR_H_
diff --git a/ui/events/gesture_detection/motion_event_buffer.cc b/ui/events/gesture_detection/motion_event_buffer.cc
index d75c621..b2ce72f9 100644
--- a/ui/events/gesture_detection/motion_event_buffer.cc
+++ b/ui/events/gesture_detection/motion_event_buffer.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <algorithm>
+#include <iterator>
 #include <utility>
 
 #include "base/trace_event/trace_event.h"
@@ -27,7 +29,7 @@
 // the last time delta.
 const int kResampleMaxPredictionMs = 8;
 
-typedef ScopedVector<MotionEventGeneric> MotionEventVector;
+using MotionEventVector = std::vector<std::unique_ptr<MotionEventGeneric>>;
 
 float Lerp(float a, float b, float alpha) {
   return a + alpha * (b - a);
@@ -59,34 +61,20 @@
          tool == MotionEvent::TOOL_TYPE_FINGER;
 }
 
-size_t CountSamplesNoLaterThan(const MotionEventVector& batch,
-                               base::TimeTicks time) {
-  size_t count = 0;
-  while (count < batch.size() && batch[count]->GetEventTime() <= time)
-    ++count;
-  return count;
-}
-
+// Splits a chunk of events from the front of the provided |batch| and returns
+// it. Requires that |batch| is sorted.
 MotionEventVector ConsumeSamplesNoLaterThan(MotionEventVector* batch,
                                             base::TimeTicks time) {
   DCHECK(batch);
-  size_t count = CountSamplesNoLaterThan(*batch, time);
-  DCHECK_GE(batch->size(), count);
-  if (count == 0)
-    return MotionEventVector();
-
-  if (count == batch->size())
-    return std::move(*batch);
-
-  // TODO(jdduke): Use a ScopedDeque to work around this mess.
-  MotionEventVector unconsumed_batch;
-  unconsumed_batch.insert(
-      unconsumed_batch.begin(), batch->begin() + count, batch->end());
-  batch->weak_erase(batch->begin() + count, batch->end());
-
-  unconsumed_batch.swap(*batch);
-  DCHECK_GE(unconsumed_batch.size(), 1U);
-  return unconsumed_batch;
+  auto first_kept_event = std::partition_point(
+      batch->begin(), batch->end(),
+      [time](const std::unique_ptr<MotionEventGeneric>& event) {
+        return event->GetEventTime() <= time;
+      });
+  MotionEventVector result(std::make_move_iterator(batch->begin()),
+                           std::make_move_iterator(first_kept_event));
+  batch->erase(batch->begin(), first_kept_event);
+  return result;
 }
 
 // Linearly interpolate the pointer position between two MotionEvent samples.
@@ -158,10 +146,10 @@
 // Events must be in non-decreasing (time) order.
 std::unique_ptr<MotionEventGeneric> ConsumeSamples(MotionEventVector events) {
   DCHECK(!events.empty());
-  std::unique_ptr<MotionEventGeneric> event(events.back());
-  for (size_t i = 0; i + 1 < events.size(); ++i)
-    event->PushHistoricalEvent(std::unique_ptr<MotionEvent>(events[i]));
-  events.weak_clear();
+  std::unique_ptr<MotionEventGeneric> event = std::move(events.back());
+  events.pop_back();
+  for (auto& historic_event : events)
+    event->PushHistoricalEvent(std::move(historic_event));
   return event;
 }
 
@@ -183,12 +171,12 @@
   if (next) {
     DCHECK(resample_time < next->GetEventTime());
     // Interpolate between current sample and future sample.
-    event0 = events.back();
+    event0 = events.back().get();
     event1 = next;
   } else if (events.size() >= 2) {
     // Extrapolate future sample using current sample and past sample.
-    event0 = events[events.size() - 2];
-    event1 = events[events.size() - 1];
+    event0 = events[events.size() - 2].get();
+    event1 = events[events.size() - 1].get();
 
     const base::TimeTicks time1 = event1->GetEventTime();
     base::TimeTicks max_predict =
@@ -228,10 +216,8 @@
 
   std::unique_ptr<MotionEventGeneric> resampled_event =
       ResampleMotionEvent(*event0, *event1, resample_time);
-  for (size_t i = 0; i < events.size(); ++i)
-    resampled_event->PushHistoricalEvent(
-        std::unique_ptr<MotionEvent>(events[i]));
-  events.weak_clear();
+  for (auto& historic_event : events)
+    resampled_event->PushHistoricalEvent(std::move(historic_event));
   return resampled_event;
 }
 
@@ -273,6 +259,7 @@
   }
 
   if (CanAddSample(*buffered_events_.front(), *clone)) {
+    // Ensure that buffered_events_ is ordered.
     DCHECK(buffered_events_.back()->GetEventTime() <= clone->GetEventTime());
   } else {
     FlushWithoutResampling(std::move(buffered_events_));
@@ -293,8 +280,8 @@
 
   // TODO(jdduke): Use a persistent MotionEventVector vector for temporary
   // storage.
-  MotionEventVector events(
-      ConsumeSamplesNoLaterThan(&buffered_events_, frame_time));
+  MotionEventVector events =
+      ConsumeSamplesNoLaterThan(&buffered_events_, frame_time);
   if (events.empty()) {
     DCHECK(!buffered_events_.empty());
     client_->SetNeedsFlush();
@@ -316,7 +303,7 @@
   DCHECK(!events.empty());
   base::TimeTicks original_event_time = events.back()->GetEventTime();
   const MotionEvent* next_event =
-      !buffered_events_.empty() ? buffered_events_.front() : nullptr;
+      !buffered_events_.empty() ? buffered_events_.front().get() : nullptr;
 
   std::unique_ptr<MotionEventGeneric> resampled_event =
       ConsumeSamplesAndTryResampling(resample_time, std::move(events),
diff --git a/ui/events/gesture_detection/motion_event_buffer.h b/ui/events/gesture_detection/motion_event_buffer.h
index 9eb1c4c..68a8449 100644
--- a/ui/events/gesture_detection/motion_event_buffer.h
+++ b/ui/events/gesture_detection/motion_event_buffer.h
@@ -6,9 +6,9 @@
 #define UI_EVENTS_GESTURE_DETECTION_MOTION_EVENT_BUFFER_H_
 
 #include <memory>
+#include <vector>
 
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
 #include "base/time/time.h"
 #include "ui/events/gesture_detection/gesture_detection_export.h"
 
@@ -55,13 +55,15 @@
   void Flush(base::TimeTicks frame_time);
 
  private:
-  typedef ScopedVector<MotionEventGeneric> MotionEventVector;
+  using MotionEventVector = std::vector<std::unique_ptr<MotionEventGeneric>>;
 
   void FlushWithResampling(MotionEventVector events,
                            base::TimeTicks resample_time);
   void FlushWithoutResampling(MotionEventVector events);
 
   MotionEventBufferClient* const client_;
+
+  // An ordered vector of buffered events.
   MotionEventVector buffered_events_;
 
   // Time of the most recently extrapolated event. This will be 0 if the
diff --git a/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
index bae3499..a128574b 100644
--- a/ui/events/gesture_detection/motion_event_buffer_unittest.cc
+++ b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
@@ -46,7 +46,7 @@
 
   // MotionEventBufferClient implementation.
   void ForwardMotionEvent(const MotionEvent& event) override {
-    forwarded_events_.push_back(event.Clone().release());
+    forwarded_events_.push_back(event.Clone());
   }
 
   void SetNeedsFlush() override { needs_flush_ = true; }
@@ -57,14 +57,14 @@
     return needs_flush;
   }
 
-  ScopedVector<MotionEvent> GetAndResetForwardedEvents() {
-    ScopedVector<MotionEvent> forwarded_events;
+  std::vector<std::unique_ptr<MotionEvent>> GetAndResetForwardedEvents() {
+    std::vector<std::unique_ptr<MotionEvent>> forwarded_events;
     forwarded_events.swap(forwarded_events_);
     return forwarded_events;
   }
 
   const MotionEvent* GetLastEvent() const {
-    return forwarded_events_.empty() ? NULL : forwarded_events_.back();
+    return forwarded_events_.empty() ? nullptr : forwarded_events_.back().get();
   }
 
   static base::TimeDelta LargeDelta() {
@@ -241,7 +241,7 @@
   }
 
  private:
-  ScopedVector<MotionEvent> forwarded_events_;
+  std::vector<std::unique_ptr<MotionEvent>> forwarded_events_;
   bool needs_flush_;
 };
 
@@ -299,7 +299,8 @@
 
   // The flushed events should include the up and the moves, with the latter
   // combined into a single event with history.
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(2U, events.size());
   EXPECT_EVENT_EQ(up, *events.back());
   EXPECT_EQ(2U, events.front()->GetHistorySize());
@@ -340,7 +341,8 @@
 
   // The flushed event should only include the latest move event.
   buffer.Flush(event_time);
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(3U, events.size());
   EXPECT_EVENT_EQ(move2, *events.back());
   EXPECT_FALSE(GetAndResetNeedsFlush());
@@ -438,7 +440,8 @@
   buffer.Flush(flush_time);
   EXPECT_FALSE(GetAndResetNeedsFlush());
   ASSERT_TRUE(GetLastEvent());
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EVENT_IGNORING_HISTORY_EQ(move1, *events.front());
   EXPECT_EVENT_HISTORY_EQ(*events.front(), 0, move0);
@@ -526,7 +529,8 @@
 
   // There should only be one flushed event, with the second remaining buffered
   // and no resampling having occurred.
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EVENT_EQ(move0, *events.front());
 
@@ -594,7 +598,8 @@
   // the two events.
   base::TimeTicks expected_time =
       move1.GetEventTime() + (move1.GetEventTime() - move0.GetEventTime()) / 2;
-  ScopedVector<MotionEvent> events0 = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events0 =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events0.size());
   EXPECT_EQ(2U, events0.front()->GetHistorySize());
   EXPECT_EQ(expected_time, events0.front()->GetEventTime());
@@ -619,7 +624,8 @@
   flush_time = event_time + ResampleDelta();
   buffer.Flush(flush_time);
   ASSERT_TRUE(GetLastEvent());
-  ScopedVector<MotionEvent> events1 = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events1 =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events1.size());
   EXPECT_EVENT_EQ(move3, *events1.front());
   EXPECT_FALSE(GetAndResetNeedsFlush());
@@ -648,7 +654,8 @@
 
   // There should only be one flushed event, and no resampling should have
   // occured between the first and the second as they were temporally too close.
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EQ(1U, events.front()->GetHistorySize());
   EXPECT_EVENT_IGNORING_HISTORY_EQ(*events.front(), move1);
@@ -678,7 +685,8 @@
 
   // There should only be one flushed event, and no resampling should have
   // occured between the first and the second as they were temporally too close.
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EQ(1U, events.front()->GetHistorySize());
   EXPECT_EVENT_IGNORING_HISTORY_EQ(*events.front(), move1);
@@ -718,7 +726,8 @@
       interpolated_time,
       move0.GetX(0) + (move1.GetX(0) - move0.GetX(0)) * alpha,
       move0.GetY(0) + (move1.GetY(0) - move0.GetY(0)) * alpha);
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EQ(1U, events.front()->GetHistorySize());
   EXPECT_EVENT_IGNORING_HISTORY_EQ(*events.front(), interpolated_event);
@@ -770,7 +779,8 @@
       expected_time,
       move0.GetX(0) + (move1.GetX(0) - move0.GetX(0)) * expected_alpha,
       move0.GetY(0) + (move1.GetY(0) - move0.GetY(0)) * expected_alpha);
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EQ(2U, events.front()->GetHistorySize());
   EXPECT_EVENT_IGNORING_HISTORY_EQ(*events.front(), extrapolated_event);
@@ -815,7 +825,8 @@
       expected_time,
       move0.GetX(0) + (move1.GetX(0) - move0.GetX(0)) * expected_alpha,
       move0.GetY(0) + (move1.GetY(0) - move0.GetY(0)) * expected_alpha);
-  ScopedVector<MotionEvent> events = GetAndResetForwardedEvents();
+  std::vector<std::unique_ptr<MotionEvent>> events =
+      GetAndResetForwardedEvents();
   ASSERT_EQ(1U, events.size());
   EXPECT_EQ(2U, events.front()->GetHistorySize());
   EXPECT_EVENT_IGNORING_HISTORY_EQ(*events.front(), extrapolated_event);
diff --git a/ui/events/gesture_detection/motion_event_generic.h b/ui/events/gesture_detection/motion_event_generic.h
index 3b754e6..3a90b80 100644
--- a/ui/events/gesture_detection/motion_event_generic.h
+++ b/ui/events/gesture_detection/motion_event_generic.h
@@ -9,7 +9,6 @@
 #include <stdint.h>
 
 #include "base/containers/stack_container.h"
-#include "base/memory/scoped_vector.h"
 #include "ui/events/gesture_detection/gesture_detection_export.h"
 #include "ui/events/gesture_detection/motion_event.h"
 
@@ -127,7 +126,7 @@
   int button_state_;
   int flags_;
   base::StackVector<PointerProperties, kTypicalMaxPointerCount> pointers_;
-  ScopedVector<MotionEvent> historical_events_;
+  std::vector<std::unique_ptr<MotionEvent>> historical_events_;
 };
 
 }  // namespace ui
diff --git a/ui/events/gestures/gesture_provider_aura.cc b/ui/events/gestures/gesture_provider_aura.cc
index 1e14dcbb..e154e4b 100644
--- a/ui/events/gestures/gesture_provider_aura.cc
+++ b/ui/events/gestures/gesture_provider_aura.cc
@@ -61,19 +61,15 @@
     // Dispatching event caused by timer.
     client_->OnGestureEvent(gesture_consumer_, event.get());
   } else {
-    // Memory managed by ScopedVector pending_gestures_.
     pending_gestures_.push_back(std::move(event));
   }
 }
 
-ScopedVector<GestureEvent>* GestureProviderAura::GetAndResetPendingGestures() {
-  if (pending_gestures_.empty())
-    return NULL;
-  // Caller is responsible for deleting old_pending_gestures.
-  ScopedVector<GestureEvent>* old_pending_gestures =
-      new ScopedVector<GestureEvent>();
-  old_pending_gestures->swap(pending_gestures_);
-  return old_pending_gestures;
+std::vector<std::unique_ptr<GestureEvent>>
+GestureProviderAura::GetAndResetPendingGestures() {
+  std::vector<std::unique_ptr<GestureEvent>> result;
+  result.swap(pending_gestures_);
+  return result;
 }
 
 void GestureProviderAura::OnTouchEnter(int pointer_id, float x, float y) {
diff --git a/ui/events/gestures/gesture_provider_aura.h b/ui/events/gestures/gesture_provider_aura.h
index c0e397b..4fa90ac 100644
--- a/ui/events/gestures/gesture_provider_aura.h
+++ b/ui/events/gestures/gesture_provider_aura.h
@@ -7,8 +7,10 @@
 
 #include <stdint.h>
 
+#include <memory>
+#include <vector>
+
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
 #include "ui/events/event.h"
 #include "ui/events/events_export.h"
 #include "ui/events/gesture_detection/filtered_gesture_provider.h"
@@ -42,7 +44,7 @@
   bool OnTouchEvent(TouchEvent* event);
   void OnTouchEventAck(uint32_t unique_touch_event_id, bool event_consumed);
   const MotionEventAura& pointer_state() { return pointer_state_; }
-  ScopedVector<GestureEvent>* GetAndResetPendingGestures();
+  std::vector<std::unique_ptr<GestureEvent>> GetAndResetPendingGestures();
   void OnTouchEnter(int pointer_id, float x, float y);
 
   // GestureProviderClient implementation
@@ -54,7 +56,7 @@
   FilteredGestureProvider filtered_gesture_provider_;
 
   bool handling_event_;
-  ScopedVector<GestureEvent> pending_gestures_;
+  std::vector<std::unique_ptr<GestureEvent>> pending_gestures_;
 
   // |gesture_consumer_| must outlive this object.
   GestureConsumer* gesture_consumer_;
diff --git a/ui/events/gestures/gesture_recognizer.h b/ui/events/gestures/gesture_recognizer.h
index bc20699..4f3daf4 100644
--- a/ui/events/gestures/gesture_recognizer.h
+++ b/ui/events/gestures/gesture_recognizer.h
@@ -7,9 +7,9 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <vector>
 
-#include "base/memory/scoped_vector.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/events_export.h"
 #include "ui/events/gestures/gesture_types.h"
@@ -24,8 +24,7 @@
   static GestureRecognizer* Get();
   static void Reset();
 
-  // List of GestureEvent*.
-  typedef ScopedVector<GestureEvent> Gestures;
+  using Gestures = std::vector<std::unique_ptr<GestureEvent>>;
 
   virtual ~GestureRecognizer() {}
 
@@ -34,12 +33,11 @@
   virtual bool ProcessTouchEventPreDispatch(TouchEvent* event,
                                             GestureConsumer* consumer) = 0;
 
-  // Returns a list of zero or more GestureEvents. The caller is responsible for
-  // freeing the returned events. Acks the gesture packet in the queue which
-  // matches with unique_event_id.
-  virtual Gestures* AckTouchEvent(uint32_t unique_event_id,
-                                  ui::EventResult result,
-                                  GestureConsumer* consumer) = 0;
+  // Returns a list of zero or more GestureEvents. Acks the gesture packet in
+  // the queue which matches with unique_event_id.
+  virtual Gestures AckTouchEvent(uint32_t unique_event_id,
+                                 ui::EventResult result,
+                                 GestureConsumer* consumer) = 0;
 
   // This is called when the consumer is destroyed. So this should cleanup any
   // internal state maintained for |consumer|. Returns true iff there was
diff --git a/ui/events/gestures/gesture_recognizer_impl.cc b/ui/events/gestures/gesture_recognizer_impl.cc
index 9bd655d2e..bc0776b 100644
--- a/ui/events/gestures/gesture_recognizer_impl.cc
+++ b/ui/events/gestures/gesture_recognizer_impl.cc
@@ -273,7 +273,7 @@
   return gesture_provider->OnTouchEvent(event);
 }
 
-GestureRecognizer::Gestures* GestureRecognizerImpl::AckTouchEvent(
+GestureRecognizer::Gestures GestureRecognizerImpl::AckTouchEvent(
     uint32_t unique_event_id,
     ui::EventResult result,
     GestureConsumer* consumer) {
diff --git a/ui/events/gestures/gesture_recognizer_impl.h b/ui/events/gestures/gesture_recognizer_impl.h
index aabda346..a3e0f573 100644
--- a/ui/events/gestures/gesture_recognizer_impl.h
+++ b/ui/events/gestures/gesture_recognizer_impl.h
@@ -70,9 +70,9 @@
   bool ProcessTouchEventPreDispatch(TouchEvent* event,
                                     GestureConsumer* consumer) override;
 
-  Gestures* AckTouchEvent(uint32_t unique_event_id,
-                          ui::EventResult result,
-                          GestureConsumer* consumer) override;
+  Gestures AckTouchEvent(uint32_t unique_event_id,
+                         ui::EventResult result,
+                         GestureConsumer* consumer) override;
 
   bool CleanupStateForConsumer(GestureConsumer* consumer) override;
   void AddGestureEventHelper(GestureEventHelper* helper) override;
diff --git a/ui/events/gestures/gesture_recognizer_impl_mac.cc b/ui/events/gestures/gesture_recognizer_impl_mac.cc
index 73e3cdc9..d3036c7 100644
--- a/ui/events/gestures/gesture_recognizer_impl_mac.cc
+++ b/ui/events/gestures/gesture_recognizer_impl_mac.cc
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include "base/macros.h"
+#include "ui/events/event.h"
 #include "ui/events/gestures/gesture_recognizer.h"
 
 namespace ui {
@@ -24,10 +25,10 @@
     return false;
   }
 
-  Gestures* AckTouchEvent(uint32_t unique_event_id,
-                          ui::EventResult result,
-                          GestureConsumer* consumer) override {
-    return NULL;
+  Gestures AckTouchEvent(uint32_t unique_event_id,
+                         ui::EventResult result,
+                         GestureConsumer* consumer) override {
+    return {};
   }
   bool CleanupStateForConsumer(GestureConsumer* consumer) override {
     return false;
diff --git a/ui/events/platform/platform_event_source_unittest.cc b/ui/events/platform/platform_event_source_unittest.cc
index e2d87c067..9ef8bc5e 100644
--- a/ui/events/platform/platform_event_source_unittest.cc
+++ b/ui/events/platform/platform_event_source_unittest.cc
@@ -9,10 +9,11 @@
 
 #include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
+#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -26,14 +27,11 @@
 namespace {
 
 std::unique_ptr<PlatformEvent> CreatePlatformEvent() {
-  std::unique_ptr<PlatformEvent> event(new PlatformEvent());
+  std::unique_ptr<PlatformEvent> event = base::MakeUnique<PlatformEvent>();
   memset(event.get(), 0, sizeof(PlatformEvent));
   return event;
 }
 
-template <typename T>
-void DestroyScopedPtr(std::unique_ptr<T> object) {}
-
 void RemoveDispatcher(PlatformEventDispatcher* dispatcher) {
   PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(dispatcher);
 }
@@ -61,7 +59,8 @@
 
   // Dispatches the stream of events, and returns the number of events that are
   // dispatched before it is requested to stop.
-  size_t DispatchEventStream(const ScopedVector<PlatformEvent>& events) {
+  size_t DispatchEventStream(
+      const std::vector<std::unique_ptr<PlatformEvent>>& events) {
     stop_stream_ = false;
     for (size_t count = 0; count < events.size(); ++count) {
       DispatchEvent(*events[count]);
@@ -157,13 +156,13 @@
 // Tests that a dispatcher receives an event.
 TEST_F(PlatformEventTest, DispatcherBasic) {
   std::vector<int> list_dispatcher;
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   EXPECT_EQ(0u, list_dispatcher.size());
   {
     TestPlatformEventDispatcher dispatcher(1, &list_dispatcher);
 
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+    std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
     source()->Dispatch(*event);
     ASSERT_EQ(1u, list_dispatcher.size());
     EXPECT_EQ(1, list_dispatcher[0]);
@@ -179,12 +178,12 @@
 TEST_F(PlatformEventTest, DispatcherOrder) {
   std::vector<int> list_dispatcher;
   int sequence[] = {21, 3, 6, 45};
-  ScopedVector<TestPlatformEventDispatcher> dispatchers;
-  for (size_t i = 0; i < arraysize(sequence); ++i) {
+  std::vector<std::unique_ptr<TestPlatformEventDispatcher>> dispatchers;
+  for (auto id : sequence) {
     dispatchers.push_back(
-        new TestPlatformEventDispatcher(sequence[i], &list_dispatcher));
+        base::MakeUnique<TestPlatformEventDispatcher>(id, &list_dispatcher));
   }
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   ASSERT_EQ(arraysize(sequence), list_dispatcher.size());
   EXPECT_EQ(std::vector<int>(sequence, sequence + arraysize(sequence)),
@@ -198,7 +197,7 @@
   TestPlatformEventDispatcher first(12, &list_dispatcher);
   TestPlatformEventDispatcher second(23, &list_dispatcher);
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   ASSERT_EQ(2u, list_dispatcher.size());
   EXPECT_EQ(12, list_dispatcher[0]);
@@ -215,13 +214,13 @@
 // Tests that observers receive events.
 TEST_F(PlatformEventTest, ObserverBasic) {
   std::vector<int> list_observer;
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   EXPECT_EQ(0u, list_observer.size());
   {
     TestPlatformEventObserver observer(31, &list_observer);
 
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+    std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
     source()->Dispatch(*event);
     ASSERT_EQ(1u, list_observer.size());
     EXPECT_EQ(31, list_observer[0]);
@@ -237,12 +236,12 @@
 TEST_F(PlatformEventTest, ObserverOrder) {
   std::vector<int> list_observer;
   const int sequence[] = {21, 3, 6, 45};
-  ScopedVector<TestPlatformEventObserver> observers;
-  for (size_t i = 0; i < arraysize(sequence); ++i) {
+  std::vector<std::unique_ptr<TestPlatformEventObserver>> observers;
+  for (auto id : sequence) {
     observers.push_back(
-        new TestPlatformEventObserver(sequence[i], &list_observer));
+        base::MakeUnique<TestPlatformEventObserver>(id, &list_observer));
   }
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   ASSERT_EQ(arraysize(sequence), list_observer.size());
   EXPECT_EQ(std::vector<int>(sequence, sequence + arraysize(sequence)),
@@ -256,7 +255,7 @@
   TestPlatformEventObserver first_o(10, &list);
   TestPlatformEventDispatcher second_d(23, &list);
   TestPlatformEventObserver second_o(20, &list);
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   const int expected[] = {10, 20, 12, 23};
   EXPECT_EQ(std::vector<int>(expected, expected + arraysize(expected)), list);
@@ -268,7 +267,7 @@
   std::vector<int> list;
   TestPlatformEventDispatcher dispatcher(10, &list);
   TestPlatformEventObserver observer(15, &list);
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   ASSERT_EQ(2u, list.size());
   EXPECT_EQ(15, list[0]);
@@ -297,7 +296,7 @@
       source()->OverrideDispatcher(&overriding_dispatcher);
   overriding_dispatcher.set_post_dispatch_action(POST_DISPATCH_PERFORM_DEFAULT);
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   // First the observer, then the overriding dispatcher, then the default
   // dispatcher.
@@ -365,7 +364,7 @@
 
   second.set_callback(base::Bind(&RemoveDispatcher, base::Unretained(&third)));
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   // |second| removes |third| from the dispatcher list during dispatch. So the
   // event should only reach |first|, |second|, and |fourth|.
@@ -385,7 +384,7 @@
 
   second.set_callback(base::Bind(&RemoveDispatcher, base::Unretained(&second)));
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   // |second| removes itself from the dispatcher list during dispatch. So the
   // event should reach all three dispatchers in the list.
@@ -405,7 +404,7 @@
 
   second.set_callback(base::Bind(&RemoveDispatcher, base::Unretained(&second)));
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   // |second| removes itself during dispatch. So both dispatchers will have
   // received the event.
@@ -424,7 +423,7 @@
 
   second.set_callback(base::Bind(&RemoveDispatcher, base::Unretained(&first)));
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   // |second| removes |first| from the dispatcher list during dispatch. The
   // event should reach all three dispatchers.
@@ -447,7 +446,7 @@
                                 base::Unretained(&first),
                                 base::Unretained(&second)));
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   // |third| removes |first| and |second| from the dispatcher list during
   // dispatch. The event should reach all three dispatchers.
@@ -468,7 +467,7 @@
   TestPlatformEventDispatcher fourth(30, &list);
   RemoveDispatchers(&third, &fourth);
 
-  std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+  std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
   source()->Dispatch(*event);
   ASSERT_EQ(2u, list.size());
   EXPECT_EQ(10, list[0]);
@@ -539,7 +538,7 @@
     std::unique_ptr<ScopedEventDispatcher> second_override_handle =
         source()->OverrideDispatcher(&second_overriding);
 
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+    std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
     source()->Dispatch(*event);
     ASSERT_EQ(2u, list.size());
     EXPECT_EQ(15, list[0]);
@@ -600,11 +599,9 @@
  public:
   void NestedTask(std::vector<int>* list,
                   TestPlatformEventDispatcher* dispatcher) {
-    ScopedVector<PlatformEvent> events;
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
-    events.push_back(std::move(event));
-    event = CreatePlatformEvent();
-    events.push_back(std::move(event));
+    std::vector<std::unique_ptr<PlatformEvent>> events;
+    events.push_back(CreatePlatformEvent());
+    events.push_back(CreatePlatformEvent());
 
     // Attempt to dispatch a couple of events. Dispatching the first event will
     // have terminated the ScopedEventDispatcher object, which will terminate
@@ -641,7 +638,7 @@
     std::unique_ptr<ScopedEventDispatcher> override_handle =
         source()->OverrideDispatcher(&overriding);
 
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+    std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
     source()->Dispatch(*event);
     ASSERT_EQ(2u, list.size());
     EXPECT_EQ(15, list[0]);
@@ -682,7 +679,7 @@
  public:
   void NestedTask(std::unique_ptr<ScopedEventDispatcher> dispatch_handle,
                   std::vector<int>* list) {
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+    std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
     source()->Dispatch(*event);
     ASSERT_EQ(2u, list->size());
     EXPECT_EQ(15, (*list)[0]);
@@ -741,7 +738,7 @@
     std::unique_ptr<ScopedEventDispatcher> override_handle =
         source()->OverrideDispatcher(&overriding);
 
-    std::unique_ptr<PlatformEvent> event(CreatePlatformEvent());
+    std::unique_ptr<PlatformEvent> event = CreatePlatformEvent();
     source()->Dispatch(*event);
     ASSERT_EQ(2u, list.size());
     EXPECT_EQ(15, list[0]);
diff --git a/ui/events/test/test_event_target.cc b/ui/events/test/test_event_target.cc
index eefebed2..0445d0d 100644
--- a/ui/events/test/test_event_target.cc
+++ b/ui/events/test/test_event_target.cc
@@ -25,24 +25,20 @@
 TestEventTarget::~TestEventTarget() {}
 
 void TestEventTarget::AddChild(std::unique_ptr<TestEventTarget> child) {
-  TestEventTarget* child_r = child.get();
-  if (child->parent()) {
-    AddChild(child->parent()->RemoveChild(child.release()));
-  } else {
-    children_.push_back(std::move(child));
-  }
-  child_r->set_parent(this);
+  DCHECK(!child->parent());
+  children_.push_back(std::move(child));
+  children_.back()->set_parent(this);
 }
 
 std::unique_ptr<TestEventTarget> TestEventTarget::RemoveChild(
     TestEventTarget* c) {
-  ScopedVector<TestEventTarget>::iterator iter = std::find(children_.begin(),
-                                                           children_.end(),
-                                                           c);
-  if (iter != children_.end()) {
-    children_.weak_erase(iter);
-    c->set_parent(NULL);
-    return base::WrapUnique(c);
+  for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
+    if (iter->get() == c) {
+      std::unique_ptr<TestEventTarget> child = std::move(*iter);
+      children_.erase(iter);
+      child->set_parent(nullptr);
+      return child;
+    }
   }
   return nullptr;
 }
@@ -72,8 +68,8 @@
 }
 
 std::unique_ptr<EventTargetIterator> TestEventTarget::GetChildIterator() const {
-  return base::MakeUnique<EventTargetIteratorImpl<TestEventTarget>>(
-      children_.get());
+  return base::MakeUnique<EventTargetIteratorUniquePtrImpl<TestEventTarget>>(
+      children_);
 }
 
 EventTargeter* TestEventTarget::GetEventTargeter() {
diff --git a/ui/events/test/test_event_target.h b/ui/events/test/test_event_target.h
index 3b5311d..9e9af656 100644
--- a/ui/events/test/test_event_target.h
+++ b/ui/events/test/test_event_target.h
@@ -7,12 +7,12 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
 #include "ui/events/event_target.h"
 
 typedef std::vector<std::string> HandlerSequenceRecorder;
@@ -35,7 +35,7 @@
     mark_events_as_handled_ = handle;
   }
 
-  TestEventTarget* child_at(int index) { return children_[index]; }
+  TestEventTarget* child_at(int index) { return children_[index].get(); }
   size_t child_count() const { return children_.size(); }
 
   void SetEventTargeter(std::unique_ptr<EventTargeter> targeter);
@@ -68,7 +68,7 @@
   void set_parent(TestEventTarget* parent) { parent_ = parent; }
 
   TestEventTarget* parent_;
-  ScopedVector<TestEventTarget> children_;
+  std::vector<std::unique_ptr<TestEventTarget>> children_;
   std::unique_ptr<EventTargeter> targeter_;
   bool mark_events_as_handled_;
 
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 674685b..638bd29f 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -283,14 +283,7 @@
   if (keyboard_mode_ == FLOATING) {
     NotifyKeyboardBoundsChanging(gfx::Rect());
   } else if (keyboard_mode_ == FULL_WIDTH) {
-    // TODO(bshe): revisit this logic after we decide to support resize virtual
-    // keyboard.
-    int keyboard_height = GetContainerWindow()->bounds().height();
-    const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds();
-    gfx::Rect new_bounds = root_bounds;
-    new_bounds.set_y(root_bounds.height() - keyboard_height);
-    new_bounds.set_height(keyboard_height);
-    GetContainerWindow()->SetBounds(new_bounds);
+    AdjustKeyboardBounds();
     // No animation added, so call ShowAnimationFinished immediately.
     ShowAnimationFinished();
   }
@@ -319,6 +312,7 @@
 void KeyboardController::OnWindowAddedToRootWindow(aura::Window* window) {
   if (!window->GetRootWindow()->HasObserver(this))
     window->GetRootWindow()->AddObserver(this);
+  AdjustKeyboardBounds();
 }
 
 void KeyboardController::OnWindowRemovingFromRootWindow(aura::Window* window,
@@ -511,4 +505,21 @@
     observer.OnKeyboardHidden();
 }
 
+void KeyboardController::AdjustKeyboardBounds() {
+  // When keyboard is floating, no resize is necessary.
+  if (keyboard_mode_ == FLOATING)
+    return;
+
+  if (keyboard_mode_ == FULL_WIDTH) {
+    // TODO(bshe): revisit this logic after we decide to support resize virtual
+    // keyboard.
+    int keyboard_height = GetContainerWindow()->bounds().height();
+    const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds();
+    gfx::Rect new_bounds = root_bounds;
+    new_bounds.set_y(root_bounds.height() - keyboard_height);
+    new_bounds.set_height(keyboard_height);
+    GetContainerWindow()->SetBounds(new_bounds);
+  }
+}
+
 }  // namespace keyboard
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h
index 817fa0d..2bfe473f 100644
--- a/ui/keyboard/keyboard_controller.h
+++ b/ui/keyboard/keyboard_controller.h
@@ -159,6 +159,10 @@
   void ShowAnimationFinished();
   void HideAnimationFinished();
 
+  // Called when the keyboard mode is set or the keyboard is moved to another
+  // display.
+  void AdjustKeyboardBounds();
+
   std::unique_ptr<KeyboardUI> ui_;
   KeyboardLayoutDelegate* layout_delegate_;
   std::unique_ptr<aura::Window> container_;
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index c2b47f3c..147c6df0 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -299,7 +299,8 @@
   const gfx::Rect& initial_bounds = container->bounds();
   // The container should be positioned at the bottom of screen and has 0
   // height.
-  ASSERT_EQ(gfx::Rect(), initial_bounds);
+  ASSERT_EQ(0, initial_bounds.height());
+  ASSERT_EQ(screen_bounds.height(), initial_bounds.y());
   VerifyKeyboardWindowSize(container, keyboard);
 
   // In FULL_WIDTH mode, attempt to change window width or move window up from
@@ -328,6 +329,38 @@
   VerifyKeyboardWindowSize(container, keyboard);
 }
 
+TEST_F(KeyboardControllerTest, KeyboardSizeMultiRootWindow) {
+  aura::Window* container(controller()->GetContainerWindow());
+  aura::Window* keyboard(ui()->GetKeyboardWindow());
+  gfx::Rect screen_bounds = root_window()->bounds();
+  root_window()->AddChild(container);
+  container->AddChild(keyboard);
+  const gfx::Rect& initial_bounds = container->bounds();
+  // The container should be positioned at the bottom of screen and has 0
+  // height.
+  ASSERT_EQ(0, initial_bounds.height());
+  ASSERT_EQ(screen_bounds.height(), initial_bounds.y());
+  VerifyKeyboardWindowSize(container, keyboard);
+
+  // Adding new root window.
+  std::unique_ptr<aura::WindowTreeHost> secondary_tree_host =
+      base::WrapUnique<aura::WindowTreeHost>(
+          aura::WindowTreeHost::Create(gfx::Rect(0, 0, 1000, 500)));
+  secondary_tree_host->InitHost();
+  EXPECT_EQ(1000, secondary_tree_host->window()->bounds().width());
+  EXPECT_EQ(500, secondary_tree_host->window()->bounds().height());
+
+  // Move the keyboard into the secondary root window.
+  controller()->HideKeyboard(
+      KeyboardController::HideReason::HIDE_REASON_AUTOMATIC);
+  root_window()->RemoveChild(container);
+  secondary_tree_host->window()->AddChild(container);
+
+  const gfx::Rect& new_bounds = container->bounds();
+  EXPECT_EQ(500, new_bounds.y());
+  VerifyKeyboardWindowSize(container, keyboard);
+}
+
 TEST_F(KeyboardControllerTest, FloatingKeyboardSize) {
   aura::Window* container(controller()->GetContainerWindow());
   aura::Window* keyboard(ui()->GetKeyboardWindow());
@@ -567,6 +600,7 @@
   root_window()->RemoveChild(keyboard_container);
   ResetController();
   EXPECT_TRUE(IsKeyboardClosed());
+  keyboard::SetAccessibilityKeyboardEnabled(false);
 }
 
 class KeyboardControllerAnimationTest : public KeyboardControllerTest {
@@ -675,6 +709,8 @@
   aura::Window* container(controller()->GetContainerWindow());
   aura::Window* keyboard(ui()->GetKeyboardWindow());
   root_window()->AddChild(container);
+
+  keyboard::SetTouchKeyboardEnabled(true);
   controller()->SetKeyboardMode(FLOATING);
   container->AddChild(keyboard);
   // Mock focus on an input field.
diff --git a/ui/login/screen_container.css b/ui/login/screen_container.css
index 6e0fcfe..2dd778817 100644
--- a/ui/login/screen_container.css
+++ b/ui/login/screen_container.css
@@ -19,6 +19,7 @@
 
 .oobe-display #outer-container {
   -webkit-perspective: 600px;
+  bottom: 47px; /* header-bar is 47 pixels high during OOBE */
 }
 
 .pin-container.pin-enabled {
@@ -66,6 +67,19 @@
   pointer-events: none;
 }
 
+#oobe-shield {
+  display: none;
+}
+
+#oobe-shield[md-mode] {
+  background-color: rgba(20, 29, 40, .8); /* #141D28 80% */
+  display: block;
+  height: 100%;
+  left: 0;
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
 
 #oobe[md-mode] #progress-dots {
   display: none;
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 48f3fbbe..d65f4bc 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -1158,7 +1158,7 @@
 }
 
 std::unique_ptr<ui::EventTargetIterator> View::GetChildIterator() const {
-  return base::MakeUnique<ui::EventTargetIteratorImpl<View>>(children_);
+  return base::MakeUnique<ui::EventTargetIteratorPtrImpl<View>>(children_);
 }
 
 ui::EventTargeter* View::GetEventTargeter() {